@semantic-ui/component
Advanced tools
Comparing version 0.0.25 to 0.0.26
@@ -15,8 +15,8 @@ { | ||
"dependencies": { | ||
"@semantic-ui/query": "^0.0.25", | ||
"@semantic-ui/reactivity": "^0.0.25", | ||
"@semantic-ui/templating": "^0.0.25", | ||
"@semantic-ui/utils": "^0.0.25" | ||
"@semantic-ui/query": "^0.0.26", | ||
"@semantic-ui/reactivity": "^0.0.26", | ||
"@semantic-ui/templating": "^0.0.26", | ||
"@semantic-ui/utils": "^0.0.26" | ||
}, | ||
"version": "0.0.25" | ||
"version": "0.0.26" | ||
} |
@@ -6,3 +6,3 @@ import { unsafeCSS } from 'lit'; | ||
import { adoptStylesheet } from './helpers/adopt-stylesheet.js'; | ||
import { adjustSettingFromAttribute } from './helpers/adjust-setting-from-attribute.js'; | ||
import { adjustPropertyFromAttribute } from './helpers/adjust-property-from-attribute.js'; | ||
import { WebComponentBase } from './web-component.js'; | ||
@@ -25,2 +25,3 @@ | ||
events = {}, | ||
keys = {}, | ||
@@ -70,2 +71,3 @@ createInstance = noop, | ||
events, | ||
keys, | ||
subTemplates, | ||
@@ -103,3 +105,3 @@ onCreated, | ||
this.settings = this.createSettingsProxy({componentSpec, properties: webComponent.properties}); | ||
this.setDefaultSettings(settings); | ||
this.setDefaultSettings({settings, componentSpec}); | ||
} | ||
@@ -142,3 +144,3 @@ | ||
const newValue = this[property]; | ||
adjustSettingFromAttribute(this, property, newValue, componentSpec); | ||
adjustPropertyFromAttribute(this, property, newValue, componentSpec); | ||
}); | ||
@@ -179,3 +181,3 @@ } | ||
super.attributeChangedCallback(attribute, oldValue, newValue); | ||
adjustSettingFromAttribute(this, attribute, newValue, componentSpec); | ||
adjustPropertyFromAttribute(this, attribute, newValue, componentSpec); | ||
this.call(onAttributeChanged, { args: [attribute, oldValue, newValue], }); | ||
@@ -182,0 +184,0 @@ } |
@@ -50,3 +50,2 @@ import { nothing } from 'lit'; | ||
}); | ||
// Return the initial result of the computation function | ||
@@ -53,0 +52,0 @@ return value; |
@@ -62,2 +62,5 @@ import { nothing, noChange } from 'lit'; | ||
let items = this.eachCondition.over() || []; | ||
if(!items?.map) { | ||
return; | ||
} | ||
items = items.map((item, index) => { | ||
@@ -75,2 +78,3 @@ if (isPlainObject(item) && !this.getItemID(item, index)) { | ||
const values = []; | ||
items = items || []; | ||
each(items, (item, index) => { | ||
@@ -91,3 +95,3 @@ keys[index] = this.getItemID(item, index); | ||
if (isPlainObject(item)) { | ||
return item._id || item.id || item.key || item.hash || item._hash || index; | ||
return item._id || item.id || item.value || item.key || item.hash || item._hash || index; | ||
} | ||
@@ -112,3 +116,3 @@ if (isString) { | ||
const sameData = isEqual(this.templateCachedData.get(itemID), eachData); | ||
if (sameIndex && sameData) { | ||
if (false && sameIndex && sameData) { | ||
// reuse the template nothing to rerender | ||
@@ -115,0 +119,0 @@ return { |
@@ -18,4 +18,7 @@ import { directive } from 'lit/directive.js'; | ||
}; | ||
const cloneTemplate = () => { | ||
const maybeCreateTemplate = () => { | ||
const templateName = getTemplateName(); | ||
// check if the template name is set and is the same as current | ||
if (this.template && this.templateName == templateName) { | ||
@@ -25,2 +28,4 @@ return false; | ||
this.templateName = templateName; | ||
// find template to render | ||
const template = subTemplates[templateName]; | ||
@@ -33,2 +38,3 @@ if (!template) { | ||
} | ||
// clone if it has changed | ||
this.template = template.clone({ data: unpackData(data) }); | ||
@@ -61,7 +67,7 @@ return true; | ||
} | ||
const isCloned = cloneTemplate(); // reactive reference | ||
const hasCreated = maybeCreateTemplate(); // reactive reference | ||
if (!comp.firstRun) { | ||
attachTemplate(); | ||
if (!isCloned) { | ||
this.template.setDataContext(unpackData(data)); | ||
if (!hasCreated) { | ||
this.template.setDataContext(unpackData(data), { rerender: false }); | ||
} | ||
@@ -71,3 +77,3 @@ this.setValue(renderTemplate()); | ||
}); | ||
cloneTemplate(); | ||
maybeCreateTemplate(); | ||
attachTemplate(); | ||
@@ -74,0 +80,0 @@ this.template.setDataContext(unpackData(data)); |
@@ -22,2 +22,3 @@ import { html } from 'lit'; | ||
this.data = data; | ||
this.renderTrees = []; | ||
this.subTemplates = subTemplates; | ||
@@ -167,3 +168,3 @@ this.resetHTML(); | ||
return reactiveData( | ||
() => this.lookupExpressionValue(expression, data), | ||
() => this.lookupExpressionValue(expression, this.data), | ||
{ ifDefined, unsafeHTML } | ||
@@ -290,3 +291,3 @@ ); | ||
renderContent({ ast, data, subTemplates }) { | ||
return new LitRenderer({ | ||
const tree = new LitRenderer({ | ||
ast, | ||
@@ -296,5 +297,22 @@ data, | ||
helpers: this.helpers, | ||
}).render(); | ||
}); | ||
this.renderTrees.push(tree); | ||
return tree.render(); | ||
} | ||
setData(data) { | ||
this.data = data; | ||
each(this.renderTrees, (tree) => { | ||
tree.updateData(data); | ||
}); | ||
} | ||
updateData(data) { | ||
each(data, (value, name) => { | ||
if(this.data[name] !== undefined && this.data[name] !== value) { | ||
this.data[name] = value; | ||
} | ||
}); | ||
} | ||
clearTemp() { | ||
@@ -301,0 +319,0 @@ delete this.lastHTML; // used to concat concurrent html |
import { LitElement } from 'lit'; | ||
import { each, isFunction, isNumber, isString, isPlainObject, keys, unique, isEqual, isServer, inArray, get, isBoolean, isArray } from '@semantic-ui/utils'; | ||
import { each, isFunction, isNumber, isString, isPlainObject, keys, unique, isServer, inArray, get, isBoolean, isArray } from '@semantic-ui/utils'; | ||
import { $ } from '@semantic-ui/query'; | ||
import { ReactiveVar } from '@semantic-ui/reactivity'; | ||
import { scopeStyles } from './helpers/scope-styles.js'; | ||
@@ -23,3 +22,3 @@ | ||
super(); | ||
this.useLight = true; | ||
this.useLight = false; | ||
this.renderCallbacks = []; | ||
@@ -177,35 +176,30 @@ } | ||
if (componentSpec) { | ||
properties.class = { | ||
type: String, | ||
}; | ||
each(componentSpec.attributes, (attributeValues, attribute) => { | ||
// this is an easy way to determine if this is a boolean or string attribute | ||
let sampleValue; | ||
if(inArray(attribute, componentSpec.contentAttributes)) { | ||
sampleValue = ''; | ||
} | ||
else if(inArray(attribute, componentSpec.settings)) { | ||
sampleValue = componentSpec.defaultSettings[attribute]; | ||
} | ||
else { | ||
sampleValue = attributeValues[0]; | ||
} | ||
properties[attribute] = WebComponentBase.getPropertySettings(sampleValue, attribute); | ||
properties.class = { type: String }; | ||
// emphasis="primary" but also setting props | ||
each(componentSpec.attributes, (name) => { | ||
const propertyType = componentSpec.propertyTypes[name]; | ||
properties[name] = WebComponentBase.getPropertySettings(name, propertyType); | ||
}); | ||
const reservedWords = ['settings', 'true', 'false']; | ||
each(componentSpec.reverseAttributes, (attributeValues, attribute) => { | ||
if(!inArray(attribute, reservedWords)) { | ||
properties[attribute] = { type: String, reflect: false }; | ||
} | ||
// these are functions that can only be set on the DOM el but do not have attributes | ||
each(componentSpec.properties, (name) => { | ||
const propertyType = componentSpec.propertyTypes[name]; | ||
properties[name] = WebComponentBase.getPropertySettings(name, propertyType); | ||
}); | ||
// primary -> emphasis="primary" | ||
each(componentSpec.optionAttributes, (attributeValues, attribute) => { | ||
properties[attribute] = { type: String, noAccessor: true }; | ||
}); | ||
} | ||
if (settings) { | ||
each(settings, (defaultValue, name) => { | ||
// expert mode (this is a settings object not a default value) | ||
if (defaultValue?.type) { | ||
properties[name] = settings; | ||
} | ||
else { | ||
properties[name] = WebComponentBase.getPropertySettings(defaultValue, name); | ||
} | ||
// this can either be a settings object or a default value | ||
// i.e. { foo: 'baz' } // basic | ||
// or { foo: { type: String, defaultValue: 'baz' } // expert | ||
properties[name] = (defaultValue?.type) | ||
? settings | ||
: WebComponentBase.getPropertySettings(name, defaultValue?.constructor) | ||
; | ||
}); | ||
@@ -216,65 +210,29 @@ } | ||
static getPropertySettings(value, name) { | ||
let property; | ||
if (isString(value)) { | ||
property = { | ||
type: String, | ||
attribute: true, | ||
}; | ||
static getPropertySettings(name, type = String) { | ||
let property = { | ||
type, | ||
attribute: true, | ||
//hasChanged: isEqual, | ||
}; | ||
// functions cannot be serialized | ||
if (type == Function) { | ||
property.attribute = false; | ||
} | ||
else if (isNumber(value)) { | ||
property = { | ||
type: Number, | ||
noAccessor: true, | ||
attribute: true, | ||
}; | ||
} | ||
else if (isBoolean(value)) { | ||
property = { | ||
type: Boolean, | ||
// we have to use an accessor if the name is reserved | ||
//noAccessor: inArray(name, ['focus', 'disabled']), | ||
attribute: true, | ||
// simplify the use case of setting setting="false" | ||
converter: { | ||
fromAttribute: (value, type) => { | ||
if (inArray(value, ['false', '0', 'null', 'undefined'])) { | ||
return false; | ||
} | ||
return Boolean(value); | ||
}, | ||
toAttribute: (value, type) => { | ||
return String(value); | ||
else if (type == Boolean) { | ||
property.converter = { | ||
fromAttribute: (value, type) => { | ||
if (inArray(value, ['false', '0', 'null', 'undefined'])) { | ||
return false; | ||
} | ||
return Boolean(value); | ||
}, | ||
toAttribute: (value, type) => { | ||
return String(value); | ||
} | ||
}; | ||
} | ||
else if (isArray(value)) { | ||
property = { | ||
type: Array, | ||
attribute: true, | ||
reflect: false, | ||
}; | ||
// adding accessors to reserved browser DOM props causes issues | ||
if(inArray(name, ['disabled'])) { | ||
property.noAccessor = true; | ||
} | ||
else if (isPlainObject(value)) { | ||
property = { | ||
type: Object, | ||
attribute: true, | ||
reflect: false, | ||
}; | ||
} | ||
else if (isFunction(value)) { | ||
property = { | ||
type: Function, | ||
attribute: false, | ||
reflect: false, | ||
}; | ||
} | ||
else { | ||
property = { | ||
type: String, | ||
attribute: true, | ||
}; | ||
} | ||
//property.hasChanged = isEqual; | ||
return property; | ||
@@ -290,3 +248,3 @@ } | ||
*/ | ||
setDefaultSettings(settings = {}) { | ||
setDefaultSettings({settings = {}, componentSpec}) { | ||
this.defaultSettings = settings; | ||
@@ -303,2 +261,8 @@ each(settings, (setting, name) => { | ||
}); | ||
if(componentSpec?.defaultValues) { | ||
this.defaultSettings = { | ||
...componentSpec.defaultValues, | ||
...this.defaultSettings | ||
}; | ||
} | ||
} | ||
@@ -308,3 +272,3 @@ | ||
/* | ||
This returns a list of settings which may include both html attributes and properties | ||
This returns a list of settings which may include both attributes and properties | ||
as specified in the spec for the component. It will extend them from default settings | ||
@@ -315,6 +279,6 @@ */ | ||
each(properties, (propSettings, property) => { | ||
if (property == 'class' || settings.observe === false) { | ||
if (property == 'class' || propSettings.observe === false) { | ||
return; | ||
} | ||
if(componentSpec && !get(componentSpec.attributes, property) && get(componentSpec.reverseAttributes, property)) { | ||
if(componentSpec && !get(componentSpec.allowedValues, property) && get(componentSpec.optionAttributes, property)) { | ||
// this property is used to lookup a setting like 'large' -> sizing | ||
@@ -324,3 +288,7 @@ // we dont record this into settings | ||
} | ||
const setting = this[property] ?? this.defaultSettings[property]; | ||
const elementProp = this[property]; | ||
const setting = elementProp // check element setting | ||
?? this.defaultSettings[property] // check default setting on this component | ||
?? (componentSpec?.defaultSettings || {})[property] // check default setting on component spec | ||
; | ||
// only pass through setting if it is defined | ||
@@ -331,4 +299,4 @@ if(setting !== undefined) { | ||
// boolean attribute case | ||
if (componentSpec && settings[this[property]] !== undefined) { | ||
settings[this[property]] = true; | ||
if (componentSpec && settings[elementProp] !== undefined) { | ||
settings[elementProp] = true; | ||
} | ||
@@ -339,4 +307,4 @@ }); | ||
/* This may get more complex if we choose to support | ||
reverse attribute lookups like setSetting('large', true); | ||
/* This may become more complex if we choose to support | ||
reverse attribute lookups like setSetting('large'); | ||
*/ | ||
@@ -376,2 +344,4 @@ setSetting(name, value) { | ||
getUIClasses({componentSpec, properties}) { | ||
// this is just a special feature of component specs and can be ignored otherwise | ||
if (!componentSpec) { | ||
@@ -381,33 +351,34 @@ return; | ||
const classes = []; | ||
each(properties, (propSettings, property) => { | ||
if (property == 'class' || propSettings.observe === false) { | ||
return; | ||
} | ||
if(componentSpec && !get(componentSpec.attributes, property) && get(componentSpec.reverseAttributes, property)) { | ||
return; | ||
} | ||
let value = this[property]; | ||
// if the setting has a string value use that as class name | ||
// i.e. sizing='large' => 'large' | ||
if(isString(value) && value) { | ||
if(get(componentSpec.attributes, property) && componentSpec.attributes[property].includes(value)) { | ||
// iterate through tracked attributes which can receive classes | ||
each(componentSpec.attributes, (attribute) => { | ||
const value = this[attribute]; | ||
if(value) { | ||
const allowedValues = componentSpec.allowedValues[attribute]; | ||
const propertyType = componentSpec.propertyTypes[attribute]; | ||
if(propertyType == Boolean) { | ||
// this is a variation like active=true | ||
// it receives the class "active" | ||
classes.push(attribute); | ||
} | ||
else if(allowedValues && inArray(value, allowedValues)) { | ||
// this is a variation like emphasis="primary" | ||
// it receives the class "primary" | ||
classes.push(value); | ||
} | ||
// components can opt-in to including the attribute as a default class | ||
if(componentSpec.attributeClasses.includes(property)) { | ||
classes.push(property); | ||
// components can opt-in to including the attribute if it has a value set | ||
// for instance "icon" if it has an icon set | ||
if(componentSpec.attributeClasses.includes(attribute)) { | ||
classes.push(attribute); | ||
} | ||
} | ||
}); | ||
// otherwise if this is a boolean property push the property name | ||
// i.e. <button primary="true" => 'primary' | ||
else if(isBoolean(value) || value === '') { | ||
classes.push(property); | ||
} | ||
}); | ||
const ignoredValues = ['true', 'false']; | ||
const classString = unique(classes) | ||
.filter(value => value && !inArray(value, ignoredValues)) | ||
.join(' '); | ||
let classString = unique(classes).join(' '); | ||
if(classString) { | ||
classString += ' '; | ||
} | ||
return classString; | ||
@@ -414,0 +385,0 @@ } |
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
51139
1518
+ Added@semantic-ui/query@0.0.26(transitive)
+ Added@semantic-ui/reactivity@0.0.26(transitive)
+ Added@semantic-ui/templating@0.0.26(transitive)
+ Added@semantic-ui/utils@0.0.26(transitive)
- Removed@semantic-ui/query@0.0.25(transitive)
- Removed@semantic-ui/reactivity@0.0.25(transitive)
- Removed@semantic-ui/templating@0.0.25(transitive)
- Removed@semantic-ui/utils@0.0.25(transitive)
Updated@semantic-ui/query@^0.0.26
Updated@semantic-ui/utils@^0.0.26