@semantic-ui/component
Advanced tools
Comparing version 0.1.7 to 0.2.0
@@ -15,8 +15,8 @@ { | ||
"dependencies": { | ||
"@semantic-ui/query": "^0.1.7", | ||
"@semantic-ui/reactivity": "^0.1.7", | ||
"@semantic-ui/templating": "^0.1.7", | ||
"@semantic-ui/utils": "^0.1.7" | ||
"@semantic-ui/query": "^0.2.0", | ||
"@semantic-ui/reactivity": "^0.2.0", | ||
"@semantic-ui/templating": "^0.2.0", | ||
"@semantic-ui/utils": "^0.2.0" | ||
}, | ||
"version": "0.1.7" | ||
"version": "0.2.0" | ||
} |
import { unsafeCSS } from 'lit'; | ||
import { each, noop, isServer, isClient, kebabToCamel } from '@semantic-ui/utils'; | ||
import { each, noop, isServer, isClient, camelToKebab, kebabToCamel } from '@semantic-ui/utils'; | ||
import { TemplateCompiler, Template } from '@semantic-ui/templating'; | ||
@@ -135,3 +135,8 @@ | ||
const newValue = this[property]; | ||
adjustPropertyFromAttribute(this, property, newValue, componentSpec); | ||
adjustPropertyFromAttribute({ | ||
el: this, | ||
attribute: camelToKebab(property), | ||
attributeValue: newValue, | ||
componentSpec | ||
}); | ||
}); | ||
@@ -166,3 +171,8 @@ } | ||
super.attributeChangedCallback(attribute, oldValue, newValue); | ||
adjustPropertyFromAttribute(this, attribute, newValue, componentSpec); | ||
adjustPropertyFromAttribute({ | ||
el: this, | ||
attribute, | ||
attributeValue: newValue, | ||
componentSpec | ||
}); | ||
this.call(onAttributeChanged, { args: [attribute, oldValue, newValue], }); | ||
@@ -169,0 +179,0 @@ } |
@@ -39,3 +39,3 @@ import { nothing, noChange } from 'lit'; | ||
// this is an empty template | ||
if(this.template?.ast.length == 0) { | ||
if(!this.template || this.template?.ast.length == 0) { | ||
return; | ||
@@ -51,3 +51,3 @@ } | ||
// this is an empty template | ||
if(this.template?.ast.length == 0) { | ||
if(!this.template || this.template?.ast.length == 0) { | ||
return nothing; | ||
@@ -78,5 +78,2 @@ } | ||
template = this.subTemplates[templateName]; | ||
if (!template) { | ||
return false; | ||
} | ||
} | ||
@@ -89,8 +86,9 @@ else if(templateOrName instanceof Template) { | ||
// avoid recreating if identical template | ||
if(isEqual(template.ast, this.ast)) { | ||
return; | ||
// make sure we have something to create | ||
if (!template) { | ||
return false; | ||
} | ||
// use ast for unique id | ||
this.ast = template.ast; | ||
// store template id | ||
this.templateID = template.id; | ||
this.template = template.clone({ | ||
@@ -97,0 +95,0 @@ templateName, |
@@ -21,3 +21,3 @@ import { html, svg } from 'lit'; | ||
static getID({ ast, data, isSVG } = {}) { | ||
return hashCode({ ast, data, isSVG }); | ||
return hashCode({ ast }); | ||
} | ||
@@ -24,0 +24,0 @@ |
@@ -17,2 +17,4 @@ import { get, each, unique, firstMatch, inArray, isString, kebabToCamel, camelToKebab } from '@semantic-ui/utils'; | ||
const SPECIAL_ATTRIBUTES = ['disabled', 'value']; | ||
// allow 'arrow-down' or 'down-arrow' | ||
@@ -42,4 +44,3 @@ const reverseDashes = (string) => { | ||
*/ | ||
export const adjustPropertyFromAttribute = (el, attribute, attributeValue, componentSpec) => { | ||
export const adjustPropertyFromAttribute = ({el, attribute, attributeValue, componentSpec}) => { | ||
// This is used to search for potential values that should match to the canonical value. | ||
@@ -52,2 +53,3 @@ // This is because we support swapping ordering and spaces for dashes | ||
const checkSpecForAllowedValue = ({attribute, optionValue, optionAttributeValue }) => { | ||
// "arrow down" -> arrow-down | ||
@@ -90,21 +92,42 @@ optionValue = tokenizeSpaces(optionValue); | ||
// this assigns the value to the DOM element | ||
const setProperty = (property, value) => { | ||
const setProperty = (attribute, value) => { | ||
// convert <div icon-after> to => el.iconAfter | ||
property = kebabToCamel(property); | ||
const property = kebabToCamel(attribute); | ||
if(value !== undefined) { | ||
el[property] = value; | ||
} | ||
// this appears to be necessary for special attributes like "disabled" | ||
if(inArray(attribute, SPECIAL_ATTRIBUTES)) { | ||
el.requestUpdate(); | ||
} | ||
}; | ||
// this removes the related propery from the element | ||
const removeProperty = (property) => { | ||
const removeProperty = (attribute) => { | ||
// convert <div icon-after> to => el.iconAfter | ||
property = kebabToCamel(property); | ||
const property = kebabToCamel(attribute); | ||
el[property] = null; | ||
el[property] = undefined; | ||
// this appears to be necessary for special attributes like "disabled" | ||
if(inArray(attribute, SPECIAL_ATTRIBUTES)) { | ||
el.requestUpdate(); | ||
} | ||
}; | ||
// this checks for boolean values like <ui-button disabled> | ||
const isBooleanValue = (attribute, attributeValue) => { | ||
// handles basic booleans of type Boolean in spec | ||
const isBooleanType = componentSpec.propertyTypes[attribute] == Boolean; | ||
// handles complex booleans where one value of allowed values is a identity, i.e. disabled, clickable-disabled | ||
const isIdentityBoolean = componentSpec.optionAttributes[attribute] == attribute; | ||
// this is a scenario where a grouping has a default styling like `animated` | ||
const isAttributeClass = inArray(attribute, componentSpec.attributeClasses); | ||
return (isBooleanType || isAttributeClass || isIdentityBoolean) && inArray(attributeValue, ['', true, attribute]); | ||
}; | ||
if (componentSpec) { | ||
@@ -116,3 +139,8 @@ | ||
each(attributeValue.split(' '), (className) => { | ||
adjustPropertyFromAttribute(el, className, true, componentSpec); | ||
adjustPropertyFromAttribute({ | ||
el, | ||
attribute: className, | ||
attributeValue: true, | ||
componentSpec | ||
}); | ||
}); | ||
@@ -124,5 +152,4 @@ } | ||
else if (inArray(attribute, componentSpec.attributes)) { | ||
// boolean attribute | ||
if(componentSpec.propertyTypes[attribute] == Boolean && inArray(attributeValue, ['', true])) { | ||
// check if this is a boolean value | ||
if(isBooleanValue(attribute, attributeValue)) { | ||
attributeValue = true; | ||
@@ -133,3 +160,3 @@ setProperty(attribute, attributeValue); | ||
// this means the attribute was removed | ||
// check if the attribute was removed (null) | ||
if(attributeValue === null) { | ||
@@ -140,6 +167,2 @@ removeProperty(attribute); | ||
if(attributeValue === undefined) { | ||
return; | ||
} | ||
// we still need to transform values from "arrow down" to "arrow-down" or "down-arrow" | ||
@@ -167,2 +190,11 @@ const { matchingValue } = checkSpecForAllowedValue({ | ||
// remove the matching attribute if the value is removed | ||
// but ONLY if the current value is the option value | ||
// this is because attribute changed handlers can fire in any order | ||
if(matchingAttribute && attributeValue === null) { | ||
if(el[matchingAttribute] == attribute) { | ||
removeProperty(matchingAttribute); | ||
} | ||
return; | ||
} | ||
if (matchingAttribute && matchingValue) { | ||
@@ -169,0 +201,0 @@ setProperty(matchingAttribute, matchingValue); |
import { LitElement } from 'lit'; | ||
import { each, isFunction, isClassInstance, kebabToCamel, keys, unique, isServer, inArray, get } from '@semantic-ui/utils'; | ||
import { each, isFunction, isClassInstance, kebabToCamel, camelToKebab, keys, unique, isServer, isEqual, inArray, get } from '@semantic-ui/utils'; | ||
import { ReactiveVar } from '@semantic-ui/reactivity'; | ||
@@ -73,5 +73,6 @@ import { $ } from '@semantic-ui/query'; | ||
// emphasis="primary" but also setting props | ||
each(componentSpec.attributes, (name) => { | ||
const propertyType = componentSpec.propertyTypes[name]; | ||
properties[name] = WebComponentBase.getPropertySettings(name, propertyType); | ||
each(componentSpec.attributes, (attributeName) => { | ||
const propertyType = componentSpec.propertyTypes[attributeName]; | ||
const propertyName = kebabToCamel(attributeName); | ||
properties[propertyName] = WebComponentBase.getPropertySettings(attributeName, propertyType); | ||
}); | ||
@@ -81,14 +82,16 @@ | ||
// but do not have attributes -- for instance functions | ||
each(componentSpec.properties, (name) => { | ||
const propertyType = componentSpec.propertyTypes[name]; | ||
properties[name] = WebComponentBase.getPropertySettings(name, propertyType); | ||
each(componentSpec.properties, (attributeName) => { | ||
const propertyType = componentSpec.propertyTypes[attributeName]; | ||
const propertyName = kebabToCamel(attributeName); | ||
properties[propertyName] = WebComponentBase.getPropertySettings(attributeName, propertyType); | ||
}); | ||
// primary -> emphasis="primary" | ||
each(componentSpec.optionAttributes, (attributeValues, attribute) => { | ||
properties[attribute] = { type: String, noAccessor: true }; | ||
each(componentSpec.optionAttributes, (attributeValues, attributeName) => { | ||
const propertyName = kebabToCamel(attributeName); | ||
properties[propertyName] = { type: String, noAccessor: true, attribute: attributeName }; | ||
}); | ||
} | ||
if (settings) { | ||
each(settings, (defaultValue, name) => { | ||
each(settings, (defaultValue, propertyName) => { | ||
// this can either be a settings object or a default value | ||
@@ -102,6 +105,6 @@ // i.e. { foo: 'baz' } // basic | ||
}; | ||
properties[name] = (defaultValue?.type) | ||
const attributeName = camelToKebab(propertyName); | ||
properties[propertyName] = (defaultValue?.type) | ||
? settings | ||
: WebComponentBase.getPropertySettings(name, defaultValue?.constructor, propertySettings) | ||
: WebComponentBase.getPropertySettings(attributeName, defaultValue?.constructor, propertySettings) | ||
; | ||
@@ -113,7 +116,14 @@ }); | ||
static getPropertySettings(name, type = String, { propertyOnly = false } = {}) { | ||
static getPropertySettings(propName, type = String, { propertyOnly = false } = {}) { | ||
let property = { | ||
type, | ||
attribute: true, | ||
//hasChanged: isEqual, | ||
/* | ||
Lit converts properties to lowercase name instead of kebab case | ||
i.e. firstName -> <my-component firstname="John"> | ||
we want `first-name="John"`, this means we need to manually specify attribute | ||
*/ | ||
attribute: camelToKebab(propName), | ||
hasChanged: (a, b) => { | ||
return !isEqual(a, b); | ||
}, | ||
}; | ||
@@ -133,2 +143,5 @@ // functions cannot be serialized | ||
} | ||
if (inArray(value, ['', true, 'true'])) { | ||
return true; | ||
} | ||
return Boolean(value); | ||
@@ -141,6 +154,2 @@ }, | ||
} | ||
// adding accessors to reserved browser DOM props causes issues | ||
if(inArray(name, ['disabled'])) { | ||
property.noAccessor = true; | ||
} | ||
return property; | ||
@@ -183,26 +192,26 @@ } | ||
let settings = {}; | ||
each(properties, (propSettings, property) => { | ||
if (property == 'class' || propSettings.observe === false) { | ||
each(properties, (propSettings, propertyName) => { | ||
if (propertyName == 'class' || propSettings.observe === false) { | ||
return; | ||
} | ||
if(componentSpec && !get(componentSpec.allowedValues, property) && get(componentSpec.optionAttributes, property)) { | ||
// this property is used to lookup a setting like 'large' -> sizing | ||
// we dont record this into settings | ||
return; | ||
} | ||
property = kebabToCamel(property); | ||
const elementProp = this[property]; | ||
const attributeName = camelToKebab(propertyName); | ||
const elementProp = this[propertyName]; | ||
const setting = elementProp // check element setting | ||
?? this.defaultSettings[property] // check default setting on this component | ||
?? (componentSpec?.defaultSettings || {})[property] // check default setting on component spec | ||
?? this.defaultSettings[propertyName] // check default setting on this component | ||
?? (componentSpec?.defaultSettings || {})[propertyName] // check default setting on component spec | ||
; | ||
// only pass through setting if it is defined | ||
if(setting !== undefined) { | ||
settings[property] = setting; | ||
// if setting is a composite like emphasis="primary" | ||
// and this is "primary" we pass this as a boolean | ||
if(componentSpec && !get(componentSpec.allowedValues, attributeName) && get(componentSpec.optionAttributes, attributeName)) { | ||
settings[propertyName] = true; | ||
return; | ||
} | ||
settings[propertyName] = setting; | ||
} | ||
// boolean attribute case | ||
if (componentSpec && settings[elementProp] !== undefined) { | ||
settings[property] = true; | ||
settings[propertyName] = true; | ||
} | ||
@@ -270,7 +279,7 @@ }); | ||
const classes = []; | ||
// iterate through tracked attributes which can receive classes | ||
each(componentSpec.attributes, (attribute) => { | ||
const value = this[attribute]; | ||
const property = kebabToCamel(attribute); | ||
const value = this[property]; | ||
@@ -285,2 +294,6 @@ if(value) { | ||
} | ||
else if(value == attribute && allowedValues && inArray(value, allowedValues)) { | ||
// disabled="disabled" use case operates like boolean | ||
classes.push(attribute); | ||
} | ||
else if(allowedValues && inArray(value, allowedValues)) { | ||
@@ -287,0 +300,0 @@ // this is a variation like emphasis="primary" |
Possible typosquat attack
Supply chain riskThere is a package with a similar name that is downloaded much more often.
Did you mean |
---|
semantic-ui-less |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
52969
1533
1
+ Added@semantic-ui/query@0.2.0(transitive)
+ Added@semantic-ui/reactivity@0.2.0(transitive)
+ Added@semantic-ui/templating@0.2.0(transitive)
+ Added@semantic-ui/utils@0.2.0(transitive)
- Removed@semantic-ui/query@0.1.7(transitive)
- Removed@semantic-ui/reactivity@0.1.7(transitive)
- Removed@semantic-ui/templating@0.1.7(transitive)
- Removed@semantic-ui/utils@0.1.7(transitive)
Updated@semantic-ui/query@^0.2.0
Updated@semantic-ui/utils@^0.2.0