wc-context
Advanced tools
Comparing version 0.8.0 to 0.9.0
@@ -1,160 +0,44 @@ | ||
const orphanMap = {}; | ||
const resolved = Promise.resolve(); | ||
const orphanResolveQueue = { | ||
contexts: new Set(), | ||
running: false, | ||
add(context) { | ||
this.contexts.add(context); | ||
import { observeContext, unobserveContext, registerProvidedContext, notifyContextChange } from './core.js' | ||
if (!this.running) { | ||
this.running = true; | ||
resolved.then(() => { | ||
this.contexts.forEach(context => { | ||
const orphans = orphanMap[context]; | ||
orphans.forEach(orphan => { | ||
const event = sendContextEvent(orphan, context); | ||
const initializedElements = new WeakSet() | ||
if (event.detail.handled) { | ||
orphans.delete(orphan); | ||
} | ||
}); | ||
}); | ||
this.contexts.clear(); | ||
this.running = false; | ||
}); | ||
} | ||
} | ||
const withContext = (Base) => { | ||
return class extends Base { | ||
}; | ||
function addOrphan(el, name) { | ||
const orphans = orphanMap[name] || (orphanMap[name] = new Set()); | ||
orphans.add(el); | ||
} | ||
function removeOrphan(el, name) { | ||
const orphans = orphanMap[name]; | ||
if (orphans) { | ||
orphans.delete(el); | ||
} | ||
} | ||
function sendContextEvent(el, name) { | ||
const event = new CustomEvent(`context-request-${name}`, { | ||
detail: {}, | ||
bubbles: true, | ||
cancelable: true, | ||
composed: true | ||
}); | ||
el.dispatchEvent(event); | ||
return event; | ||
} | ||
function registerProvidedContext(el, name, providedContexts) { | ||
const observerMap = el.__wcContextObserverMap || (el.__wcContextObserverMap = {}); | ||
const observers = observerMap[name] || (observerMap[name] = []); | ||
const orphans = orphanMap[name]; | ||
el.addEventListener(`context-request-${name}`, event => { | ||
event.stopPropagation(); | ||
const targetEl = event.target; | ||
const value = providedContexts[name]; | ||
const context = targetEl.context; | ||
const oldValue = context[name]; | ||
if (oldValue !== value) { | ||
context[name] = value; | ||
if (targetEl.contextChangedCallback) { | ||
targetEl.contextChangedCallback(name, oldValue, value); | ||
} | ||
get context () { | ||
return this.__wcContext || (this.__wcContext = {}) | ||
} | ||
observers.push(targetEl); | ||
event.detail.handled = true; | ||
}); | ||
if (orphans && orphans.size) { | ||
orphanResolveQueue.add(name); | ||
} | ||
} | ||
function observeContext(el, name) { | ||
const event = sendContextEvent(el, name); | ||
if (!event.detail.handled) { | ||
addOrphan(el, name); | ||
} | ||
} | ||
function unobserveContext(el, name) { | ||
removeOrphan(el, name); | ||
} | ||
function notifyContextChange(el, name, value) { | ||
const observerMap = el.__wcContextObserverMap; | ||
const observers = observerMap && observerMap[name]; | ||
if (observers) { | ||
observers.forEach(observer => { | ||
const context = observer.context; | ||
const oldValue = context[name]; | ||
if (oldValue !== value) { | ||
context[name] = value; | ||
if (observer.contextChangedCallback) { | ||
observer.contextChangedCallback(name, oldValue, value); | ||
} | ||
} | ||
}); | ||
} | ||
} | ||
const initializedElements = new WeakSet(); | ||
const withContext = Base => { | ||
return class extends Base { | ||
get context() { | ||
return this.__wcContext || (this.__wcContext = {}); | ||
} | ||
connectedCallback() { | ||
super.connectedCallback(); | ||
const observedContexts = this.constructor.observedContexts; | ||
connectedCallback () { | ||
super.connectedCallback() | ||
const observedContexts = this.constructor.observedContexts | ||
if (observedContexts) { | ||
observedContexts.forEach(context => observeContext(this, context)); | ||
observedContexts.forEach(context => observeContext(this, context)) | ||
} | ||
if (!initializedElements.has(this)) { | ||
const providedContextConfigs = this.constructor.providedContexts; | ||
const providedContextConfigs = this.constructor.providedContexts | ||
if (providedContextConfigs) { | ||
const providedContexts = this.__wcProvidedContexts || (this.__wcProvidedContexts = {}); | ||
const mappedProps = this.__wcMappedProps || (this.__wcMappedProps = {}); | ||
const providedContexts = this.__wcProvidedContexts || (this.__wcProvidedContexts = {}) | ||
const mappedProps = this.__wcMappedProps || (this.__wcMappedProps = {}) | ||
Object.keys(providedContextConfigs).forEach(name => { | ||
const config = providedContextConfigs[name]; | ||
const property = typeof config === 'string' ? config : config.property; | ||
providedContexts[name] = property ? this[property] : config.value; | ||
const config = providedContextConfigs[name] | ||
const property = typeof config === 'string' ? config : config.property | ||
providedContexts[name] = property ? this[property] : config.value | ||
if (property) { | ||
mappedProps[name] = property; | ||
mappedProps[name] = property | ||
} | ||
registerProvidedContext(this, name, providedContexts); | ||
}); | ||
registerProvidedContext(this, name, providedContexts) | ||
}) | ||
} | ||
initializedElements.add(this); | ||
initializedElements.add(this) | ||
} | ||
} | ||
disconnectedCallback() { | ||
super.disconnectedCallback(); | ||
const observedContexts = this.constructor.observedContexts; | ||
disconnectedCallback () { | ||
super.disconnectedCallback() | ||
const observedContexts = this.constructor.observedContexts | ||
if (observedContexts) { | ||
observedContexts.forEach(context => unobserveContext(this, context)); | ||
observedContexts.forEach(context => unobserveContext(this, context)) | ||
} | ||
@@ -164,25 +48,20 @@ } | ||
shouldUpdate(changedProperties) { | ||
const shouldChange = super.shouldUpdate(changedProperties); | ||
const mappedProps = this.__wcMappedProps; | ||
const shouldChange = super.shouldUpdate(changedProperties) | ||
const mappedProps = this.__wcMappedProps | ||
if (mappedProps) { | ||
const providedContexts = this.__wcProvidedContexts || (this.__wcProvidedContexts = {}); | ||
const providedContexts = this.__wcProvidedContexts || (this.__wcProvidedContexts = {}) | ||
Object.keys(mappedProps).forEach(contextName => { | ||
const property = mappedProps[contextName]; | ||
const property = mappedProps[contextName] | ||
if (changedProperties.has(property)) { | ||
const value = this[property]; | ||
providedContexts[contextName] = value; | ||
notifyContextChange(this, contextName, value); | ||
const value = this[property] | ||
providedContexts[contextName] = value | ||
notifyContextChange(this, contextName, value) | ||
} | ||
}); | ||
} | ||
return shouldChange; | ||
}) | ||
} | ||
return shouldChange | ||
} | ||
} | ||
} | ||
}; | ||
}; | ||
export { withContext }; | ||
//# sourceMappingURL=lit-element.js.map | ||
export { withContext } |
{ | ||
"name": "wc-context", | ||
"version": "0.8.0", | ||
"description": "Simple context for HTML custom elements", | ||
"version": "0.9.0", | ||
"description": "Context for HTML custom elements / web components", | ||
"repository": "blikblum/wc-context", | ||
@@ -19,3 +19,36 @@ "author": "Luiz Américo Pereira Câmara", | ||
"main": "wc-context.js", | ||
"module": "wc-context.js" | ||
} | ||
"module": "wc-context.js", | ||
"files": [ | ||
"core.js", | ||
"lit-element.js", | ||
"skatejs.js", | ||
"wc-context.js" | ||
], | ||
"jest": { | ||
"modulePathIgnorePatterns": [ | ||
"<rootDir>/dist/", | ||
"<rootDir>/examples/" | ||
], | ||
"setupFilesAfterEnv": [ | ||
"<rootDir>/test/setup.js" | ||
], | ||
"testEnvironment": "jest-environment-jsdom-fourteen" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.7.5", | ||
"@babel/plugin-proposal-class-properties": "^7.7.4", | ||
"@babel/plugin-proposal-decorators": "^7.7.4", | ||
"@babel/preset-env": "^7.7.6", | ||
"babel-jest": "^24.9.0", | ||
"document-register-element": "^1.14.3", | ||
"jest": "^24.9.0", | ||
"jest-environment-jsdom-fourteen": "^1.0.1", | ||
"standard": "^14.3.1" | ||
}, | ||
"scripts": { | ||
"lint": "standard src test tools", | ||
"test": "jest", | ||
"test:watch": "jest --watch", | ||
"test:cover": "jest --coverage" | ||
} | ||
} |
@@ -8,4 +8,7 @@ # wc-context | ||
✓ Small and fast<br> | ||
✓ Small, fast and flexible<br> | ||
✓ No need to dedicated "provider" or "consumer" elements<br> | ||
✓ Ability to provide one or more contexts per element<br> | ||
✓ Integrates with lit-element and skatejs<br> | ||
✓ No Internet Explorer support<br> | ||
@@ -15,5 +18,5 @@ | ||
> Warning: the interface may change in future | ||
> Warning: the public interface may change in future | ||
The simplest way to use `wc-context` is through the `withContext` class mixin | ||
The simplest way to use `wc-context` is through the `withContext` class mixin | ||
@@ -74,8 +77,8 @@ Live examples: | ||
// @polymer/lit-element | ||
import { withContext, fromProp } from 'wc-context/lit-element' | ||
import { LitElement } from '@polymer/lit-element' | ||
import { withContext } from 'wc-context/lit-element' | ||
import { LitElement } from 'lit-element' | ||
const Component = withContext(LitElement) | ||
class Provider extends { | ||
class Provider extends Component { | ||
static get properties () { | ||
@@ -86,6 +89,6 @@ return { | ||
} | ||
constructor () { | ||
super() | ||
this.childContext = { | ||
theme: fromProp('value') | ||
static get providedContexts () { | ||
return { | ||
theme: {property: 'value'} | ||
} | ||
@@ -102,21 +105,25 @@ } | ||
// skatejs | ||
import withLit from '@skatejs/renderer-lit-html/dist/esnext' | ||
import { withUpdate, withRenderer } from 'skatejs/dist/esnext' | ||
import { withContext, fromProp, fromStateProp } from 'wc-context/skatejs' | ||
import Element from '@skatejs/element-lit-html' | ||
import { withContext } from 'wc-context/skatejs' | ||
const Component = withLit(withContext(withUpdate(withRenderer(HTMLElement)))) | ||
const Component = withContext(Element) | ||
class Provider extends { | ||
class Provider extends Component { | ||
static get props () { | ||
return { | ||
altTheme: String | ||
altTheme: String, | ||
theme: String | ||
} | ||
} | ||
static get providedContexts () { | ||
return { | ||
theme: {property: 'theme'} | ||
altTheme: {property: 'altTheme'} | ||
} | ||
} | ||
constructor () { | ||
super() | ||
this.childContext = { | ||
theme: fromStateProp('value'), | ||
altTheme: fromProp('altTheme') | ||
} | ||
this.state = {value: 'blue'} | ||
super() | ||
this.theme = 'blue' | ||
this.altTheme = 'yellow' | ||
@@ -126,3 +133,3 @@ } | ||
toggleTheme () { | ||
this.state = {value: 'newtheme'} | ||
this.theme = 'newtheme' | ||
this.altTheme = 'newalttheme' | ||
@@ -176,2 +183,2 @@ } | ||
MIT | ||
Copyright © 2018 Luiz Américo | ||
Copyright © 2019 Luiz Américo |
192
skatejs.js
@@ -1,185 +0,65 @@ | ||
const orphanMap = {}; | ||
const resolved = Promise.resolve(); | ||
const orphanResolveQueue = { | ||
contexts: new Set(), | ||
running: false, | ||
add(context) { | ||
this.contexts.add(context); | ||
import { observeContext, unobserveContext, registerProvidedContext, notifyContextChange } from './core.js' | ||
if (!this.running) { | ||
this.running = true; | ||
resolved.then(() => { | ||
this.contexts.forEach(context => { | ||
const orphans = orphanMap[context]; | ||
orphans.forEach(orphan => { | ||
const event = sendContextEvent(orphan, context); | ||
const initializedElements = new WeakSet() | ||
if (event.detail.handled) { | ||
orphans.delete(orphan); | ||
} | ||
}); | ||
}); | ||
this.contexts.clear(); | ||
this.running = false; | ||
}); | ||
} | ||
} | ||
const withContext = (Base) => { | ||
return class extends Base { | ||
}; | ||
function addOrphan(el, name) { | ||
const orphans = orphanMap[name] || (orphanMap[name] = new Set()); | ||
orphans.add(el); | ||
} | ||
function removeOrphan(el, name) { | ||
const orphans = orphanMap[name]; | ||
if (orphans) { | ||
orphans.delete(el); | ||
} | ||
} | ||
function sendContextEvent(el, name) { | ||
const event = new CustomEvent(`context-request-${name}`, { | ||
detail: {}, | ||
bubbles: true, | ||
cancelable: true, | ||
composed: true | ||
}); | ||
el.dispatchEvent(event); | ||
return event; | ||
} | ||
function registerProvidedContext(el, name, providedContexts) { | ||
const observerMap = el.__wcContextObserverMap || (el.__wcContextObserverMap = {}); | ||
const observers = observerMap[name] || (observerMap[name] = []); | ||
const orphans = orphanMap[name]; | ||
el.addEventListener(`context-request-${name}`, event => { | ||
event.stopPropagation(); | ||
const targetEl = event.target; | ||
const value = providedContexts[name]; | ||
const context = targetEl.context; | ||
const oldValue = context[name]; | ||
if (oldValue !== value) { | ||
context[name] = value; | ||
if (targetEl.contextChangedCallback) { | ||
targetEl.contextChangedCallback(name, oldValue, value); | ||
} | ||
get context () { | ||
return this.__wcContext || (this.__wcContext = {}) | ||
} | ||
observers.push(targetEl); | ||
event.detail.handled = true; | ||
}); | ||
if (orphans && orphans.size) { | ||
orphanResolveQueue.add(name); | ||
} | ||
} | ||
function observeContext(el, name) { | ||
const event = sendContextEvent(el, name); | ||
if (!event.detail.handled) { | ||
addOrphan(el, name); | ||
} | ||
} | ||
function unobserveContext(el, name) { | ||
removeOrphan(el, name); | ||
} | ||
function notifyContextChange(el, name, value) { | ||
const observerMap = el.__wcContextObserverMap; | ||
const observers = observerMap && observerMap[name]; | ||
if (observers) { | ||
observers.forEach(observer => { | ||
const context = observer.context; | ||
const oldValue = context[name]; | ||
if (oldValue !== value) { | ||
context[name] = value; | ||
if (observer.contextChangedCallback) { | ||
observer.contextChangedCallback(name, oldValue, value); | ||
} | ||
} | ||
}); | ||
} | ||
} | ||
const initializedElements = new WeakSet(); | ||
const withContext = Base => { | ||
return class extends Base { | ||
get context() { | ||
return this.__wcContext || (this.__wcContext = {}); | ||
} | ||
connectedCallback() { | ||
super.connectedCallback(); | ||
const observedContexts = this.constructor.observedContexts; | ||
connectedCallback () { | ||
super.connectedCallback() | ||
const observedContexts = this.constructor.observedContexts | ||
if (observedContexts) { | ||
observedContexts.forEach(context => observeContext(this, context)); | ||
observedContexts.forEach(context => observeContext(this, context)) | ||
} | ||
if (!initializedElements.has(this)) { | ||
const providedContextConfigs = this.constructor.providedContexts; | ||
const providedContextConfigs = this.constructor.providedContexts | ||
if (providedContextConfigs) { | ||
const providedContexts = this.__wcProvidedContexts || (this.__wcProvidedContexts = {}); | ||
const mappedProps = this.__wcMappedProps || (this.__wcMappedProps = {}); | ||
const providedContexts = this.__wcProvidedContexts || (this.__wcProvidedContexts = {}) | ||
const mappedProps = this.__wcMappedProps || (this.__wcMappedProps = {}) | ||
Object.keys(providedContextConfigs).forEach(name => { | ||
const config = providedContextConfigs[name]; | ||
const property = typeof config === 'string' ? config : config.property; | ||
providedContexts[name] = property ? this[property] : config.value; | ||
const config = providedContextConfigs[name] | ||
const property = typeof config === 'string' ? config : config.property | ||
providedContexts[name] = property ? this[property] : config.value | ||
if (property) { | ||
mappedProps[name] = property; | ||
mappedProps[name] = property | ||
} | ||
registerProvidedContext(this, name, providedContexts); | ||
}); | ||
registerProvidedContext(this, name, providedContexts) | ||
}) | ||
} | ||
initializedElements.add(this); | ||
initializedElements.add(this) | ||
} | ||
} | ||
disconnectedCallback() { | ||
super.disconnectedCallback(); | ||
const observedContexts = this.constructor.observedContexts; | ||
disconnectedCallback () { | ||
super.disconnectedCallback() | ||
const observedContexts = this.constructor.observedContexts | ||
if (observedContexts) { | ||
observedContexts.forEach(context => unobserveContext(this, context)); | ||
observedContexts.forEach(context => unobserveContext(this, context)) | ||
} | ||
} | ||
updated(props) { | ||
super.updated(props); | ||
const mappedProps = this.__wcMappedProps; | ||
updated (props) { | ||
super.updated(props) | ||
const mappedProps = this.__wcMappedProps | ||
if (mappedProps) { | ||
const providedContexts = this.__wcProvidedContexts || (this.__wcProvidedContexts = {}); | ||
const providedContexts = this.__wcProvidedContexts || (this.__wcProvidedContexts = {}) | ||
Object.keys(mappedProps).forEach(contextName => { | ||
const property = mappedProps[contextName]; | ||
const property = mappedProps[contextName] | ||
if (property in props) { | ||
const value = this[property]; | ||
providedContexts[contextName] = value; | ||
notifyContextChange(this, contextName, value); | ||
const value = this[property] | ||
providedContexts[contextName] = value | ||
notifyContextChange(this, contextName, value) | ||
} | ||
}); | ||
}) | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
}; | ||
export { withContext }; | ||
//# sourceMappingURL=skatejs.js.map | ||
export { withContext } |
@@ -1,167 +0,51 @@ | ||
const orphanMap = {}; | ||
const resolved = Promise.resolve(); | ||
const orphanResolveQueue = { | ||
contexts: new Set(), | ||
running: false, | ||
add(context) { | ||
this.contexts.add(context); | ||
import { observeContext, unobserveContext, registerProvidedContext, notifyContextChange } from './core.js' | ||
if (!this.running) { | ||
this.running = true; | ||
resolved.then(() => { | ||
this.contexts.forEach(context => { | ||
const orphans = orphanMap[context]; | ||
orphans.forEach(orphan => { | ||
const event = sendContextEvent(orphan, context); | ||
const initializedElements = new WeakSet() | ||
if (event.detail.handled) { | ||
orphans.delete(orphan); | ||
} | ||
}); | ||
}); | ||
this.contexts.clear(); | ||
this.running = false; | ||
}); | ||
} | ||
} | ||
const withContext = (Base) => { | ||
return class extends Base { | ||
}; | ||
function addOrphan(el, name) { | ||
const orphans = orphanMap[name] || (orphanMap[name] = new Set()); | ||
orphans.add(el); | ||
} | ||
function removeOrphan(el, name) { | ||
const orphans = orphanMap[name]; | ||
if (orphans) { | ||
orphans.delete(el); | ||
} | ||
} | ||
function sendContextEvent(el, name) { | ||
const event = new CustomEvent(`context-request-${name}`, { | ||
detail: {}, | ||
bubbles: true, | ||
cancelable: true, | ||
composed: true | ||
}); | ||
el.dispatchEvent(event); | ||
return event; | ||
} | ||
function registerProvidedContext(el, name, providedContexts) { | ||
const observerMap = el.__wcContextObserverMap || (el.__wcContextObserverMap = {}); | ||
const observers = observerMap[name] || (observerMap[name] = []); | ||
const orphans = orphanMap[name]; | ||
el.addEventListener(`context-request-${name}`, event => { | ||
event.stopPropagation(); | ||
const targetEl = event.target; | ||
const value = providedContexts[name]; | ||
const context = targetEl.context; | ||
const oldValue = context[name]; | ||
if (oldValue !== value) { | ||
context[name] = value; | ||
if (targetEl.contextChangedCallback) { | ||
targetEl.contextChangedCallback(name, oldValue, value); | ||
} | ||
get context () { | ||
return this.__wcContext || (this.__wcContext = {}) | ||
} | ||
observers.push(targetEl); | ||
event.detail.handled = true; | ||
}); | ||
if (orphans && orphans.size) { | ||
orphanResolveQueue.add(name); | ||
} | ||
} | ||
function observeContext(el, name) { | ||
const event = sendContextEvent(el, name); | ||
if (!event.detail.handled) { | ||
addOrphan(el, name); | ||
} | ||
} | ||
function unobserveContext(el, name) { | ||
removeOrphan(el, name); | ||
} | ||
function notifyContextChange(el, name, value) { | ||
const observerMap = el.__wcContextObserverMap; | ||
const observers = observerMap && observerMap[name]; | ||
if (observers) { | ||
observers.forEach(observer => { | ||
const context = observer.context; | ||
const oldValue = context[name]; | ||
if (oldValue !== value) { | ||
context[name] = value; | ||
if (observer.contextChangedCallback) { | ||
observer.contextChangedCallback(name, oldValue, value); | ||
} | ||
} | ||
}); | ||
} | ||
} | ||
const initializedElements = new WeakSet(); | ||
const withContext = Base => { | ||
return class extends Base { | ||
get context() { | ||
return this.__wcContext || (this.__wcContext = {}); | ||
updateProvidedContext (name, value) { | ||
const providedContexts = this.__wcProvidedContexts || (this.__wcProvidedContexts = {}) | ||
providedContexts[name] = value | ||
notifyContextChange(this, name, value) | ||
} | ||
updateProvidedContext(name, value) { | ||
const providedContexts = this.__wcProvidedContexts || (this.__wcProvidedContexts = {}); | ||
providedContexts[name] = value; | ||
notifyContextChange(this, name, value); | ||
} | ||
connectedCallback() { | ||
super.connectedCallback && super.connectedCallback(); | ||
const observedContexts = this.constructor.observedContexts; | ||
connectedCallback () { | ||
super.connectedCallback && super.connectedCallback() | ||
const observedContexts = this.constructor.observedContexts | ||
if (observedContexts) { | ||
observedContexts.forEach(context => observeContext(this, context)); | ||
observedContexts.forEach(context => observeContext(this, context)) | ||
} | ||
if (!initializedElements.has(this)) { | ||
const providedContextConfigs = this.constructor.providedContexts; | ||
const providedContextConfigs = this.constructor.providedContexts | ||
if (providedContextConfigs) { | ||
const providedContexts = this.__wcProvidedContexts || (this.__wcProvidedContexts = {}); | ||
const providedContexts = this.__wcProvidedContexts || (this.__wcProvidedContexts = {}) | ||
Object.keys(providedContextConfigs).forEach(name => { | ||
const config = providedContextConfigs[name]; | ||
const property = typeof config === 'string' ? config : config.property; | ||
providedContexts[name] = property ? this[property] : config.value; | ||
registerProvidedContext(this, name, providedContexts); | ||
}); | ||
const config = providedContextConfigs[name] | ||
const property = typeof config === 'string' ? config : config.property | ||
providedContexts[name] = property ? this[property] : config.value | ||
registerProvidedContext(this, name, providedContexts) | ||
}) | ||
} | ||
initializedElements.add(this); | ||
initializedElements.add(this) | ||
} | ||
} | ||
disconnectedCallback() { | ||
super.disconnectedCallback && super.disconnectedCallback(); | ||
const observedContexts = this.constructor.observedContexts; | ||
disconnectedCallback () { | ||
super.disconnectedCallback && super.disconnectedCallback() | ||
const observedContexts = this.constructor.observedContexts | ||
if (observedContexts) { | ||
observedContexts.forEach(context => unobserveContext(this, context)); | ||
observedContexts.forEach(context => unobserveContext(this, context)) | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
}; | ||
export { withContext }; | ||
//# sourceMappingURL=wc-context.js.map | ||
export { withContext } |
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
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
1
178
15438
9
7
249
1