@dbp-toolkit/language-select
Advanced tools
Comparing version
{ | ||
"root": true, | ||
"extends": "./../../eslint.common.json" | ||
} |
@@ -1,623 +0,153 @@ | ||
import { t as templateCaches$1, m as marker, T as Template, a as TemplateResult, A as AdapterLitElement, L as LanguageSelect, h as html, d as defineCustomElement } from './shared/language-select.baef0a1f.es.js'; | ||
import { a as Logger, S as ScopedElementsMixin, A as AdapterLitElement, L as LanguageSelect, h as html, d as defineCustomElement, c as createInstance, s as setOverrides } from './shared/language-select.3e05fcd8.es.js'; | ||
const appliedClassMixins = new WeakMap(); | ||
class Provider extends HTMLElement { | ||
constructor() { | ||
super(); | ||
this.callbackStore = []; | ||
this.root = false; | ||
/** Vefify if the Mixin was previously applyed | ||
* @private | ||
* @param {function} mixin Mixin being applyed | ||
* @param {object} superClass Class receiving the new mixin | ||
* @returns {boolean} | ||
*/ | ||
function wasMixinPreviouslyApplied(mixin, superClass) { | ||
let klass = superClass; | ||
while (klass) { | ||
if (appliedClassMixins.get(klass) === mixin) { | ||
return true; | ||
// Previously we used direct properties like this["lang"] (instead of this.properties["lang"]) for storing the | ||
// properties, but the "lang" property seems to be updated before the event from the MutationObserver, so we | ||
// cannot observe a value change directly (as workaround we use another property (e.g. "langValue") instead of "lang") | ||
this.properties = {}; | ||
// We need to store our own "last values" because we cannot be sure what the MutationObserver detects | ||
this.lastProperties = {}; | ||
Logger.debug('Provider constructor()'); | ||
} | ||
klass = Object.getPrototypeOf(klass); | ||
} | ||
return false; | ||
} | ||
/** Apply each mixin in the chain to make sure they are not applied more than once to the final class. | ||
* @export | ||
* @param {function} mixin Mixin to be applyed | ||
* @returns {object} Mixed class with mixin applied | ||
*/ | ||
function dedupeMixin(mixin) { | ||
return superClass => { | ||
if (wasMixinPreviouslyApplied(mixin, superClass)) { | ||
return superClass; | ||
getProperty(name) { | ||
return this.properties[name]; | ||
} | ||
const mixedClass = mixin(superClass); | ||
appliedClassMixins.set(mixedClass, mixin); | ||
return mixedClass; | ||
}; | ||
} | ||
/** | ||
* Cache class that allows to search in a cache hierarchy. | ||
* @template T, Q | ||
*/ | ||
class Cache { | ||
/** | ||
* Creates a Cache instance | ||
* @param {Cache} [parent] | ||
*/ | ||
constructor(parent) { | ||
this._parent = parent; | ||
this._cache = new Map(); | ||
} | ||
/** | ||
* Returns a boolean indicating whether an element with the specified key exists or not. | ||
* | ||
* @param {T} key - The key of the element to test for presence in the Cache object. | ||
* @return {boolean} | ||
*/ | ||
has(key) { | ||
return !!(this._cache.has(key) || (this._parent && this._parent._cache.has(key))); | ||
} | ||
/** | ||
* Adds or updates an element with a specified key and a value to a Cache object. | ||
* | ||
* @param {T} key - The key of the element to add to the Cache object. | ||
* @param {Q} value - The value of the element to add to the Cache object. | ||
* @return {Cache<T, Q>} the cache object | ||
*/ | ||
set(key, value) { | ||
this._cache.set(key, value); | ||
return this; | ||
} | ||
/** | ||
* Returns a specified element from a Map object. If the value that is associated to the provided key is an | ||
* object, then you will get a reference to that object and any change made to that object will effectively modify | ||
* it inside the Map object. | ||
* | ||
* @param {T} key - The key of the element to return from the Cache object. | ||
* @return {Q} | ||
*/ | ||
get(key) { | ||
return this._cache.get(key) || (this._parent && this._parent._cache.get(key)); | ||
} | ||
} | ||
/** | ||
* Global counter to scope the custom elements | ||
* | ||
* @type {number} | ||
*/ | ||
let counter = Math.round(Math.random() * 100000); | ||
/** | ||
* Allowed tag name chars | ||
* | ||
* @type {string} | ||
*/ | ||
const chars = `-|\\.|[0-9]|[a-z]`; | ||
/** | ||
* Regular expression to check if a value is a valid tag name | ||
* | ||
* @type {RegExp} | ||
*/ | ||
const tagRegExp = new RegExp(`[a-z](${chars})*-(${chars})*`); | ||
/** | ||
* Checks if the tag name is valid | ||
* | ||
* @param {string} tag | ||
* @returns {boolean} | ||
*/ | ||
const isValid = tag => tagRegExp.exec(tag) !== null; | ||
/** | ||
* Checks if the tag is already registered | ||
* | ||
* @param {string} name | ||
* @param {CustomElementRegistry} registry | ||
* @returns {boolean} | ||
*/ | ||
const isTagRegistered = (name, registry) => !!registry.get(name); | ||
/** | ||
* Given a tag name scopes it with a number suffix | ||
* | ||
* @param {string} tagName | ||
* @param {CustomElementRegistry} registry | ||
* @returns {string} scoped tag name | ||
*/ | ||
const incrementTagName = (tagName, registry) => { | ||
const newTagName = `${tagName}-${(counter += 1)}`; | ||
if (isTagRegistered(newTagName, registry)) { | ||
return incrementTagName(tagName, registry); | ||
} | ||
return newTagName; | ||
}; | ||
/** | ||
* Creates a unique scoped tag name | ||
* | ||
* @exports | ||
* @param {string} tagName - tag name to scope | ||
* @param {CustomElementRegistry} registry | ||
* @returns {string} scoped tag name | ||
*/ | ||
function createUniqueTag(tagName, registry = customElements) { | ||
if (!isValid(tagName)) { | ||
throw new Error('tagName is invalid'); | ||
} | ||
return incrementTagName(tagName, registry); | ||
} | ||
/** | ||
* The global cache for tag names | ||
* | ||
* @type {WeakMap<typeof HTMLElement, string>} | ||
*/ | ||
const globalTagsCache = new WeakMap(); | ||
/** | ||
* Adds a tag to the global tags cache | ||
* | ||
* @param {string} tag | ||
* @param {typeof HTMLElement} klass | ||
*/ | ||
const addToGlobalTagsCache = (tag, klass) => globalTagsCache.set(klass, tag); | ||
/** | ||
* Gets a tag from the global tags cache | ||
* | ||
* @exports | ||
* @param {typeof HTMLElement} klass | ||
* @returns {undefined|string} | ||
*/ | ||
const getFromGlobalTagsCache = klass => globalTagsCache.get(klass); | ||
/** | ||
* Checks if klass is a subclass of HTMLElement | ||
* | ||
* @param {typeof HTMLElement} klass | ||
* @returns {boolean} | ||
*/ | ||
const extendsHTMLElement = klass => Object.prototype.isPrototypeOf.call(HTMLElement, klass); | ||
/** | ||
* Defines a custom element | ||
* | ||
* @param {string} tagName | ||
* @param {typeof HTMLElement} klass | ||
* @param {CustomElementRegistry} registry | ||
*/ | ||
const defineElement = (tagName, klass, registry = customElements) => { | ||
addToGlobalTagsCache(tagName, klass); | ||
registry.define(tagName, class extends klass {}); | ||
}; | ||
/** | ||
* Stores a lazy element in the cache to be used in future | ||
* | ||
* @param {string} tagName | ||
* @param {CustomElementRegistry} registry | ||
* @param {import('./Cache.js').Cache<string, string>} tagsCache | ||
* @returns {string} | ||
*/ | ||
const storeLazyElementInCache = (tagName, registry, tagsCache) => { | ||
const tag = createUniqueTag(tagName, registry); | ||
if (!tagsCache) { | ||
throw new Error('Lazy scoped elements requires the use of tags cache'); | ||
} | ||
tagsCache.set(tagName, tag); | ||
return tag; | ||
}; | ||
/** | ||
* Define a scoped custom element storing the scoped tag name in the cache | ||
* | ||
* @param {string} tagName | ||
* @param {typeof HTMLElement} klass | ||
* @param {import('./Cache.js').Cache<string, string>} tagsCache | ||
* @returns {string} | ||
*/ | ||
const defineElementAndStoreInCache = (tagName, klass, tagsCache) => { | ||
const registry = customElements; | ||
if (!extendsHTMLElement(klass)) { | ||
return storeLazyElementInCache(tagName, registry, tagsCache); | ||
} | ||
if (klass === customElements.get(tagName)) { | ||
addToGlobalTagsCache(tagName, klass); | ||
return tagName; | ||
} | ||
const tag = createUniqueTag(tagName, registry); | ||
// @ts-ignore | ||
// we extend it just in case the class has been defined manually | ||
defineElement(tag, klass, registry); | ||
return tag; | ||
}; | ||
/** | ||
* Gets a scoped tag name from the cache or generates a new one and defines the element if needed | ||
* | ||
* @exports | ||
* @param {string} tagName | ||
* @param {typeof HTMLElement} klass | ||
* @param {import('./Cache.js').Cache<string, string>} tagsCache | ||
* @returns {string} | ||
*/ | ||
function registerElement(tagName, klass, tagsCache = undefined) { | ||
const tag = | ||
getFromGlobalTagsCache(klass) || | ||
(tagsCache && tagsCache.get(tagName)) || | ||
defineElementAndStoreInCache(tagName, klass, tagsCache); | ||
return tag; | ||
} | ||
/** | ||
* Defines a lazy element | ||
* | ||
* @param {string} tagName | ||
* @param {typeof HTMLElement} klass | ||
* @param {import('./Cache.js').Cache<string, string>} tagsCache | ||
*/ | ||
function defineScopedElement(tagName, klass, tagsCache) { | ||
const tag = tagsCache.get(tagName); | ||
if (tag) { | ||
if (customElements.get(tag) === undefined) { | ||
defineElement(tag, klass, customElements); | ||
setProperty(name, value) { | ||
this.lastProperties[name] = value; | ||
this.properties[name] = value; | ||
} | ||
} else { | ||
tagsCache.set(tagName, registerElement(tagName, klass, tagsCache)); | ||
} | ||
} | ||
/** | ||
* @typedef {import('./types').ScopedElementsMap} ScopedElementsMap | ||
*/ | ||
/** | ||
* Allowed tag name chars | ||
* | ||
* @type {string} | ||
*/ | ||
const chars$1 = `-|\\.|[0-9]|[a-z]`; | ||
/** | ||
* Regular Expression to find a custom element tag | ||
* | ||
* @type {RegExp} | ||
*/ | ||
const re = new RegExp(`<\\/?([a-z](${chars$1})*-(${chars$1})*)`, 'g'); | ||
/** | ||
* The global cache of processed string arrays | ||
* | ||
* @type {Cache<TemplateStringsArray, TemplateStringsArray>} | ||
*/ | ||
const globalCache = new Cache(); | ||
/** | ||
* Find custom element tags in the string | ||
* | ||
* @param {string} str | ||
* @returns {RegExpExecArray[]} | ||
*/ | ||
const matchAll = str => { | ||
const matches = []; | ||
let result; | ||
// eslint-disable-next-line no-cond-assign | ||
while ((result = re.exec(str)) !== null) { | ||
matches.push(result); | ||
} | ||
return matches; | ||
}; | ||
/** | ||
* Transforms a string array into another one with resolved scoped elements and caches it for future references | ||
* | ||
* @param {TemplateStringsArray} strings | ||
* @param {ScopedElementsMap} scopedElements | ||
* @param {Cache<TemplateStringsArray, TemplateStringsArray>} templateCache | ||
* @param {Cache<string, string>} tagsCache | ||
* @returns {TemplateStringsArray} | ||
*/ | ||
const transformTemplate = (strings, scopedElements, templateCache, tagsCache) => { | ||
const transformedStrings = strings.map(str => { | ||
let acc = str; | ||
const matches = matchAll(str); | ||
for (let i = matches.length - 1; i >= 0; i -= 1) { | ||
const item = matches[i]; | ||
const [block, tagName] = item; | ||
const tag = registerElement(tagName, scopedElements[tagName], tagsCache); | ||
const start = item.index + block.length - tagName.length; | ||
const end = start + tagName.length; | ||
const isClosingTag = block.indexOf('</') === 0; | ||
acc = | ||
acc.slice(0, start) + | ||
(isClosingTag ? tag : `${tag} data-tag-name="${tagName}"`) + | ||
acc.slice(end); | ||
hasPropertyChanged(name, value) { | ||
return this.lastProperties[name] !== value; | ||
} | ||
return acc; | ||
}); | ||
// @ts-ignore | ||
// noinspection JSCheckFunctionSignatures | ||
templateCache.set(strings, transformedStrings); | ||
// @ts-ignore | ||
// noinspection JSValidateTypes | ||
return transformedStrings; | ||
}; | ||
/** | ||
* Obtains the cached strings array with resolved scoped elements or creates it | ||
* | ||
* @exports | ||
* @param {TemplateStringsArray} strings | ||
* @param {ScopedElementsMap} scopedElements | ||
* @param {import('./Cache.js').Cache<TemplateStringsArray, TemplateStringsArray>} templateCache | ||
* @param {import('./Cache.js').Cache<string, string>} tagsCache | ||
* @returns {TemplateStringsArray} | ||
*/ | ||
function transform(strings, scopedElements, templateCache = globalCache, tagsCache) { | ||
return ( | ||
templateCache.get(strings) || | ||
transformTemplate(strings, scopedElements, templateCache, tagsCache) | ||
); | ||
} | ||
const getTemplateCacheKey = (type, scopeName) => `${type}--${scopeName}`; | ||
let compatibleShadyCSSVersion = true; | ||
// @ts-ignore | ||
const { ShadyCSS } = window; | ||
if (typeof ShadyCSS === 'undefined') { | ||
compatibleShadyCSSVersion = false; | ||
} else if (typeof ShadyCSS.prepareTemplateDom === 'undefined') { | ||
compatibleShadyCSSVersion = false; | ||
} | ||
/** | ||
* Template factory which scopes template DOM using ShadyCSS. | ||
* @param scopeName {string} | ||
*/ | ||
const shadyTemplateFactory = scopeName => result => { | ||
const cacheKey = getTemplateCacheKey(result.type, scopeName); | ||
let templateCache = templateCaches$1.get(cacheKey); | ||
if (templateCache === undefined) { | ||
templateCache = { | ||
stringsArray: new WeakMap(), | ||
keyString: new Map(), | ||
}; | ||
templateCaches$1.set(cacheKey, templateCache); | ||
} | ||
let template = templateCache.stringsArray.get(result.strings); | ||
if (template !== undefined) { | ||
return template; | ||
} | ||
const key = result.strings.join(marker); | ||
template = templateCache.keyString.get(key); | ||
if (template === undefined) { | ||
const element = result.getTemplateElement(); | ||
if (compatibleShadyCSSVersion) { | ||
ShadyCSS.prepareTemplateDom(element, scopeName); | ||
hasProperty(name) { | ||
return Object.hasOwnProperty.call(this.properties, name); | ||
} | ||
template = new Template(result, element); | ||
templateCache.keyString.set(key, template); | ||
} | ||
templateCache.stringsArray.set(result.strings, template); | ||
return template; | ||
}; | ||
/* eslint-disable no-use-before-define */ | ||
connectedCallback() { | ||
Logger.debug('Provider(' + this.id + ') connectedCallback()'); | ||
/** | ||
* @typedef {import('./types').ScopedElementsMixin} ScopedElementsMixin | ||
* @typedef {import('./types').ScopedElementsMap} ScopedElementsMap | ||
* @typedef {import("lit-element").LitElement} LitElement | ||
* @typedef {import('lit-html/lib/shady-render').ShadyRenderOptions} ShadyRenderOptions | ||
* @typedef {function(TemplateResult, Element|DocumentFragment|ShadowRoot, ShadyRenderOptions): void} RenderFunction | ||
*/ | ||
const that = this; | ||
/** | ||
* Template caches | ||
* | ||
* @type {WeakMap<Function, Cache<TemplateStringsArray, TemplateStringsArray>>} | ||
*/ | ||
const templateCaches = new WeakMap(); | ||
this.addEventListener('dbp-subscribe', function (e) { | ||
const name = e.detail.name; | ||
if (that.hasProperty(name) || that.root) { | ||
Logger.debug('Provider(' + that.id + ') eventListener("dbp-subscribe",..) name "' + name + '" found.'); | ||
that.callbackStore.push({name: name, callback: e.detail.callback, sender: e.detail.sender}); | ||
/** | ||
* Retrieves or creates a templateCache for a specific key | ||
* | ||
* @param {Function} key | ||
* @returns {Cache<TemplateStringsArray, TemplateStringsArray>} | ||
*/ | ||
const getTemplateCache = key => { | ||
if (!templateCaches.has(key)) { | ||
// @ts-ignore | ||
templateCaches.set(key, new Cache(templateCaches.get(key.constructor))); | ||
} | ||
e.detail.callback(that.getProperty(name)); | ||
e.stopPropagation(); | ||
} | ||
}, false); | ||
return templateCaches.get(key); | ||
}; | ||
this.addEventListener('dbp-unsubscribe', function (e) { | ||
const name = e.detail.name; | ||
const sender = e.detail.sender; | ||
if (that.hasProperty(name) || that.root) { | ||
Logger.debug('Provider(' + that.id + ') eventListener("dbp-unsubscribe",..) name "' + name + '" found.'); | ||
that.callbackStore.forEach(item => { | ||
if (item.sender === sender && item.name === name) { | ||
const index = that.callbackStore.indexOf(item); | ||
that.callbackStore.splice(index, 1); | ||
Logger.debug('Provider(' + that.id + ') eventListener for name "' + name + '" removed.'); | ||
} | ||
}); | ||
/** | ||
* Tags caches | ||
* | ||
* @type {WeakMap<object, Cache<string, string>>} | ||
*/ | ||
const tagsCaches = new WeakMap(); | ||
e.stopPropagation(); | ||
} | ||
}, false); | ||
/** | ||
* Retrieves or creates a tagsCache for a specific key | ||
* @param {object} key | ||
* @returns {Cache<string, string>} | ||
*/ | ||
const getTagsCache = key => { | ||
if (!tagsCaches.has(key)) { | ||
tagsCaches.set(key, new Cache(tagsCaches.get(key.constructor))); | ||
} | ||
// listen to property changes | ||
this.addEventListener('dbp-set-property', function (e) { | ||
const name = e.detail.name; | ||
const value = e.detail.value; | ||
return tagsCaches.get(key); | ||
}; | ||
if (that.hasProperty(name) || that.root) { | ||
Logger.debug('Provider(' + that.id + ') eventListener("dbp-set-property",..) name "' + name + '" found.'); | ||
that.setProperty(name, value); | ||
/** | ||
* Transforms an array of TemplateResults or arrays into another one with resolved scoped elements | ||
* | ||
* @param {ReadonlyArray} items | ||
* @param {ScopedElementsMap} scopedElements | ||
* @param {Cache<TemplateStringsArray, TemplateStringsArray>} templateCache | ||
* @param {Cache<string, string>} tagsCache | ||
* @returns {ReadonlyArray} | ||
*/ | ||
const transformArray = (items, scopedElements, templateCache, tagsCache) => | ||
items.map(value => { | ||
if (value instanceof TemplateResult) { | ||
return transformTemplate$1(value, scopedElements, templateCache, tagsCache); | ||
} | ||
that.callbackStore.forEach(item => { | ||
if (item.name === name) { | ||
item.callback(value); | ||
} | ||
}); | ||
if (Array.isArray(value)) { | ||
return transformArray(value, scopedElements, templateCache, tagsCache); | ||
} | ||
e.stopPropagation(); | ||
} | ||
}, false); | ||
return value; | ||
}); | ||
// Options for the observer (which mutations to observe) | ||
const config = { attributes: true, childList: false, subtree: false }; | ||
/** | ||
* Transforms a TemplateResult into another one with resolved scoped elements | ||
* | ||
* @param {TemplateResult} template | ||
* @param {ScopedElementsMap} scopedElements | ||
* @param {Cache<TemplateStringsArray, TemplateStringsArray>} templateCache | ||
* @param {Cache<string, string>} tagsCache | ||
* @returns {TemplateResult} | ||
*/ | ||
const transformTemplate$1 = (template, scopedElements, templateCache, tagsCache) => | ||
new TemplateResult( | ||
transform(template.strings, scopedElements, templateCache, tagsCache), | ||
transformArray(template.values, scopedElements, templateCache, tagsCache), | ||
template.type, | ||
template.processor, | ||
); | ||
// Callback function to execute when mutations are observed | ||
const callback = function(mutationsList, observer) { | ||
// Use traditional 'for loops' for IE 11 | ||
for(const mutation of mutationsList) { | ||
if (mutation.type === 'attributes') { | ||
const name = mutation.attributeName; | ||
const value = that.getAttribute(name); | ||
/** | ||
* Gets an instance of the ScopedElementsTemplateFactory | ||
* | ||
* @param {string} scopeName | ||
* @param {ScopedElementsMap} scopedElements | ||
* @param {Cache<TemplateStringsArray, TemplateStringsArray>} templateCache | ||
* @param {Cache<string, string>} tagsCache | ||
* @returns {function(any): any} | ||
*/ | ||
const scopedElementsTemplateFactory = ( | ||
scopeName, | ||
scopedElements, | ||
templateCache, | ||
tagsCache, | ||
) => template => { | ||
const newTemplate = transformTemplate$1(template, scopedElements, templateCache, tagsCache); | ||
if (that.hasPropertyChanged(name, value)) { | ||
Logger.debug('Provider (' + that.id + ') observed attribute "' + name + '" changed'); | ||
that.setProperty(name, value); | ||
return shadyTemplateFactory(scopeName)(newTemplate); | ||
}; | ||
that.callbackStore.forEach(item => { | ||
if (item.name === name) { | ||
item.callback(value); | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
}; | ||
/** @type {ScopedElementsMixin} */ | ||
const ScopedElementsMixinImplementation = superclass => | ||
class ScopedElementsHost extends superclass { | ||
/** | ||
* Obtains the scoped elements definitions map | ||
* | ||
* @returns {ScopedElementsMap} | ||
*/ | ||
static get scopedElements() { | ||
return {}; | ||
} | ||
// Create an observer instance linked to the callback function | ||
const observer = new MutationObserver(callback); | ||
/** @override */ | ||
static render(template, container, options) { | ||
if (!options || typeof options !== 'object' || !options.scopeName) { | ||
throw new Error('The `scopeName` option is required.'); | ||
} | ||
const { scopeName, eventContext } = options; | ||
// Start observing the target node for configured mutations | ||
observer.observe(this, config); | ||
const templateCache = getTemplateCache(eventContext); | ||
const tagsCache = getTagsCache(eventContext); | ||
const { scopedElements } = this; | ||
// get all *not observed* attributes | ||
if (this.hasAttributes()) { | ||
const attrs = this.attributes; | ||
for(let i = attrs.length - 1; i >= 0; i--) { | ||
if (['id', 'class', 'style', 'data-tag-name'].includes(attrs[i].name)) { | ||
continue; | ||
} | ||
return super.render(template, container, { | ||
...options, | ||
templateFactory: scopedElementsTemplateFactory( | ||
scopeName, | ||
scopedElements, | ||
templateCache, | ||
tagsCache, | ||
), | ||
}); | ||
this.setProperty(attrs[i].name, attrs[i].value); | ||
Logger.debug('Provider (' + that.id + ') found attribute "' + attrs[i].name + '" = "' + attrs[i].value + '"'); | ||
} | ||
} | ||
} | ||
/** | ||
* Defines a scoped element | ||
* | ||
* @param {string} tagName | ||
* @param {typeof HTMLElement} klass | ||
*/ | ||
defineScopedElement(tagName, klass) { | ||
return defineScopedElement(tagName, klass, getTagsCache(this)); | ||
get id() { | ||
return this.getAttribute('id'); | ||
} | ||
} | ||
/** | ||
* Returns a scoped tag name | ||
* | ||
* @deprecated Please, use the instance method instead of the static one. This static method is not able to | ||
* obtain the tagName of lazy defined elements, while the instance one is. | ||
* @param {string} tagName | ||
* @returns {string|undefined} | ||
*/ | ||
static getScopedTagName(tagName) { | ||
// @ts-ignore | ||
const klass = this.scopedElements[tagName]; | ||
return klass | ||
? registerElement(tagName, klass, getTagsCache(this)) | ||
: getTagsCache(this).get(tagName); | ||
// This is an example on how to override translations at runtime | ||
let OVERRIDES = { | ||
'de': { | ||
'translation': { | ||
'demo': 'Überschrieben' | ||
} | ||
}, | ||
'en': { | ||
'translation': { | ||
'demo': 'Overridden' | ||
} | ||
} | ||
}; | ||
/** | ||
* Returns a scoped tag name | ||
* | ||
* @param {string} tagName | ||
* @returns {string|undefined} | ||
*/ | ||
getScopedTagName(tagName) { | ||
// @ts-ignore | ||
const klass = this.constructor.scopedElements[tagName]; | ||
return klass | ||
? registerElement(tagName, klass, getTagsCache(this)) | ||
: getTagsCache(this).get(tagName); | ||
} | ||
}; | ||
const ScopedElementsMixin = dedupeMixin(ScopedElementsMixinImplementation); | ||
class LanguageSelectDisplay extends AdapterLitElement { | ||
@@ -628,2 +158,4 @@ | ||
this.lang = 'de'; | ||
this._i18n = createInstance(); | ||
setOverrides(this._i18n, OVERRIDES); | ||
} | ||
@@ -637,4 +169,14 @@ | ||
update(changedProperties) { | ||
changedProperties.forEach((oldValue, propName) => { | ||
switch (propName) { | ||
case 'lang': | ||
this._i18n.changeLanguage(this.lang); | ||
} | ||
}); | ||
super.update(changedProperties); | ||
} | ||
render() { | ||
return html`${this.lang}`; | ||
return html`<b>${this.lang}: ${this._i18n.t('demo')}</b>`; | ||
} | ||
@@ -653,2 +195,3 @@ } | ||
'dbp-language-select-display': LanguageSelectDisplay, | ||
'dbp-provider': Provider, | ||
}; | ||
@@ -659,12 +202,14 @@ } | ||
return html` | ||
Select 1: <dbp-language-select subscribe="lang"></dbp-language-select> | ||
<br> | ||
<br> | ||
Select 2: <dbp-language-select subscribe="lang"></dbp-language-select> | ||
<br> | ||
<br> | ||
Current language 1: <dbp-language-select-display subscribe="lang"></dbp-language-select-display> | ||
<br> | ||
<br> | ||
Current language 2: <dbp-language-select-display subscribe="lang"></dbp-language-select-display> | ||
<dbp-provider lang=""> | ||
Select 1: <dbp-language-select subscribe="lang"></dbp-language-select> | ||
<br> | ||
<br> | ||
Select 2: <dbp-language-select subscribe="lang"></dbp-language-select> | ||
<br> | ||
<br> | ||
Current language 1: <dbp-language-select-display subscribe="lang"></dbp-language-select-display> | ||
<br> | ||
<br> | ||
Current language 2: <dbp-language-select-display subscribe="lang"></dbp-language-select-display> | ||
</dbp-provider> | ||
`; | ||
@@ -671,0 +216,0 @@ } |
@@ -1,4 +0,4 @@ | ||
import { d as defineCustomElement, L as LanguageSelect } from './shared/language-select.baef0a1f.es.js'; | ||
import { d as defineCustomElement, L as LanguageSelect } from './shared/language-select.3e05fcd8.es.js'; | ||
defineCustomElement('dbp-language-select', LanguageSelect); | ||
//# sourceMappingURL=dbp-language-select.js.map |
@@ -9,2 +9,3 @@ module.exports = { | ||
removeUnusedKeys: true, | ||
func: {list: ['i18n.t', '_i18n.t']}, | ||
lngs: ['en','de'], | ||
@@ -11,0 +12,0 @@ resource: { |
{ | ||
"name": "@dbp-toolkit/language-select", | ||
"homepage": "https://gitlab.tugraz.at/dbp/web-components/toolkit/-/tree/master/packages/language-select", | ||
"version": "0.2.2", | ||
"version": "0.2.3", | ||
"main": "src/index.js", | ||
@@ -17,8 +17,8 @@ "license": "LGPL-2.1-or-later", | ||
"devDependencies": { | ||
"@rollup/plugin-commonjs": "^17.0.0", | ||
"@esm-bundle/chai": "^4.2.0", | ||
"@rollup/plugin-commonjs": "^19.0.0", | ||
"@rollup/plugin-json": "^4.1.0", | ||
"@rollup/plugin-node-resolve": "^11.0.0", | ||
"chai": "^4.2.0", | ||
"@rollup/plugin-node-resolve": "^13.0.0", | ||
"eslint": "^7.3.1", | ||
"eslint-plugin-jsdoc": "^31.0.0", | ||
"eslint-plugin-jsdoc": "^35.0.0", | ||
"i18next-scanner": "^3.0.0", | ||
@@ -29,3 +29,3 @@ "karma": "^6.0.0", | ||
"karma-mocha": "^2.0.1", | ||
"mocha": "^8.0.1", | ||
"mocha": "^9.0.0", | ||
"rollup": "^2.33.3", | ||
@@ -39,3 +39,3 @@ "rollup-plugin-copy": "^3.1.0", | ||
"@dbp-toolkit/common": "^0.2.2", | ||
"@open-wc/scoped-elements": "^1.3.2", | ||
"@open-wc/scoped-elements": "^1.3.3", | ||
"lit-element": "^2.4.0" | ||
@@ -58,3 +58,3 @@ }, | ||
}, | ||
"gitHead": "b599340edfeb6cf3ea26ef418a4e281146abe884" | ||
"gitHead": "cfe0f21eb1ffb5a4ad95a096bd6995fdffc86bfe" | ||
} |
@@ -16,2 +16,9 @@ # Language Select Web Component | ||
Or directly via CDN: | ||
```html | ||
<dbp-language-select></dbp-language-select> | ||
<script type="module" src="https://unpkg.com/@dbp-toolkit/language-select@0.2.2/dist/dbp-language-select.js"></script> | ||
``` | ||
## Attributes | ||
@@ -18,0 +25,0 @@ |
@@ -22,9 +22,2 @@ import glob from 'glob'; | ||
}, | ||
onwarn: function (warning, warn) { | ||
// ignore chai warnings | ||
if (warning.code === 'CIRCULAR_DEPENDENCY') { | ||
return; | ||
} | ||
warn(warning); | ||
}, | ||
plugins: [ | ||
@@ -31,0 +24,0 @@ del({ |
@@ -6,3 +6,18 @@ import {html} from 'lit-element'; | ||
import {AdapterLitElement} from "@dbp-toolkit/provider/src/adapter-lit-element"; | ||
import {Provider} from "@dbp-toolkit/provider"; | ||
import {createInstance, setOverrides} from './i18n.js'; | ||
// This is an example on how to override translations at runtime | ||
let OVERRIDES = { | ||
'de': { | ||
'translation': { | ||
'demo': 'Überschrieben' | ||
} | ||
}, | ||
'en': { | ||
'translation': { | ||
'demo': 'Overridden' | ||
} | ||
} | ||
}; | ||
@@ -14,2 +29,4 @@ class LanguageSelectDisplay extends AdapterLitElement { | ||
this.lang = 'de'; | ||
this._i18n = createInstance(); | ||
setOverrides(this._i18n, OVERRIDES); | ||
} | ||
@@ -23,4 +40,14 @@ | ||
update(changedProperties) { | ||
changedProperties.forEach((oldValue, propName) => { | ||
switch (propName) { | ||
case 'lang': | ||
this._i18n.changeLanguage(this.lang); | ||
} | ||
}); | ||
super.update(changedProperties); | ||
} | ||
render() { | ||
return html`${this.lang}`; | ||
return html`<b>${this.lang}: ${this._i18n.t('demo')}</b>`; | ||
} | ||
@@ -39,2 +66,3 @@ } | ||
'dbp-language-select-display': LanguageSelectDisplay, | ||
'dbp-provider': Provider, | ||
}; | ||
@@ -45,12 +73,14 @@ } | ||
return html` | ||
Select 1: <dbp-language-select subscribe="lang"></dbp-language-select> | ||
<br> | ||
<br> | ||
Select 2: <dbp-language-select subscribe="lang"></dbp-language-select> | ||
<br> | ||
<br> | ||
Current language 1: <dbp-language-select-display subscribe="lang"></dbp-language-select-display> | ||
<br> | ||
<br> | ||
Current language 2: <dbp-language-select-display subscribe="lang"></dbp-language-select-display> | ||
<dbp-provider lang=""> | ||
Select 1: <dbp-language-select subscribe="lang"></dbp-language-select> | ||
<br> | ||
<br> | ||
Select 2: <dbp-language-select subscribe="lang"></dbp-language-select> | ||
<br> | ||
<br> | ||
Current language 1: <dbp-language-select-display subscribe="lang"></dbp-language-select-display> | ||
<br> | ||
<br> | ||
Current language 2: <dbp-language-select-display subscribe="lang"></dbp-language-select-display> | ||
</dbp-provider> | ||
`; | ||
@@ -57,0 +87,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import {createInstance} from '@dbp-toolkit/common/i18next.js'; | ||
import {createInstance as _createInstance, setOverrides} from '@dbp-toolkit/common/i18next.js'; | ||
@@ -6,2 +6,6 @@ import de from './i18n/de/translation.json'; | ||
export const i18n = createInstance({en: en, de: de}, 'de', 'en'); | ||
export function createInstance() { | ||
return _createInstance({en: en, de: de}, 'de', 'en'); | ||
} | ||
export {setOverrides}; |
@@ -5,3 +5,4 @@ { | ||
"de-action": "Auf Deutsch anzeigen", | ||
"en-action": "Auf Englisch anzeigen" | ||
"en-action": "Auf Englisch anzeigen", | ||
"demo": "Hallo Welt" | ||
} |
@@ -5,3 +5,4 @@ { | ||
"de-action": "Switch to German", | ||
"en-action": "Switch to English" | ||
"en-action": "Switch to English", | ||
"demo": "Hello World" | ||
} |
import {html, css} from 'lit-element'; | ||
import {i18n} from './i18n.js'; | ||
import {createInstance} from './i18n.js'; | ||
import * as commonStyles from '@dbp-toolkit/common/styles'; | ||
import {AdapterLitElement} from "@dbp-toolkit/provider/src/adapter-lit-element"; | ||
/** | ||
@@ -16,7 +17,8 @@ * Emits a dbp-language-changed event where event.detail.lang is the new selected language | ||
this._i18n = createInstance(); | ||
// for the i18next scanner | ||
i18n.t('de'); | ||
i18n.t('de-action'); | ||
i18n.t('en'); | ||
i18n.t('en-action'); | ||
this._i18n.t('de'); | ||
this._i18n.t('de-action'); | ||
this._i18n.t('en'); | ||
this._i18n.t('en-action'); | ||
} | ||
@@ -62,3 +64,3 @@ | ||
// In case of more than two this doesn't make that much sense, but for now.. | ||
i18n.changeLanguage(this.next); | ||
this._i18n.changeLanguage(this.next); | ||
} | ||
@@ -111,3 +113,3 @@ } | ||
render() { | ||
var linkTitle = i18n.t(this.next + '-action'); | ||
var linkTitle = this._i18n.t(this.next + '-action'); | ||
return html` | ||
@@ -114,0 +116,0 @@ <a href="#" title="${linkTitle}" @click=${this.onClick}>${this.next.toUpperCase()}</a> |
@@ -1,2 +0,2 @@ | ||
import {assert, expect} from 'chai'; | ||
import {assert, expect} from '@esm-bundle/chai'; | ||
@@ -3,0 +3,0 @@ import '../src/dbp-language-select.js'; |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
791925
8.35%6528
10.29%51
15.91%