@pictogrammers/element
Version:
Web Component Element for TypeScript
831 lines • 120 kB
JavaScript
import './global.js';
import { Mutation, createProxy, addObserver, removeObserver, swapObserver, hasObserver, isProxy, getTarget } from './proxy.js';
class PropError extends Error {
constructor(message, ignore) {
super(message);
this.name = 'PropError';
// @ts-ignore
if (Error.captureStackTrace) {
// @ts-ignore
Error.captureStackTrace(this, ignore);
}
}
}
export const index = Symbol('index');
const init = Symbol('init');
const template = Symbol('template');
const style = Symbol('style');
const parent = Symbol('parent');
const renderList = Symbol('renderList');
export function getProxyValue(obj) {
return obj[isProxy] && obj[getTarget];
}
function extendTemplate(base, append) {
if (append && append.match(/<parent\/>/)) {
return append.replace(/<parent\/>/, base);
}
else if (base.match(/<child\/>/)) {
return base.replace(/<child\/>/, append || '');
}
else {
return `${base}${append || ''}`;
}
}
function camelToDash(str) {
return str.replace(/([a-zA-Z])(?=[A-Z])/g, '$1-').toLowerCase();
}
function dashToCamel(str) {
return str.replace(/-([a-z])/g, m => m[1].toUpperCase());
}
export function Component(config = {}) {
return function (cls, context) {
if (context.kind !== 'class') {
throw new Error('@Component() can only decorate a class');
}
// webpack removes class names, override name
Reflect.defineProperty(cls, 'name', {
value: config.selector,
writable: false,
configurable: false,
});
// ToDo: Clean up naming. cls is not used only render
if (cls[parent]) {
cls[parent] = [...cls[parent], cls];
if (cls.prototype.render) {
cls[renderList] = [...cls[renderList], cls.prototype.render];
}
if (config.style) {
cls[style] = [...cls[style], config.style];
}
cls[template] = extendTemplate(cls[parent][cls[parent].length - 1][template], config.template || null);
}
else if (cls.prototype instanceof HTMLElement) {
cls[parent] = [cls];
cls[renderList] = cls.prototype.render ? [cls.prototype.render] : [];
cls[style] = config.style ? [config.style] : [];
cls[template] = config.template || '';
}
else {
throw new Error(`Must extend from HTMLElement`);
}
const connectedCallback = cls.prototype.connectedCallback || (() => { });
const disconnectedCallback = cls.prototype.disconnectedCallback || (() => { });
cls.prototype.connectedCallback = function () {
if (!this[init] && config.template === undefined && config.style === undefined) {
if (config.useShadow === false) {
// Base class with no template
}
else {
this.attachShadow({ mode: 'open' });
}
}
else if (!this[init]) {
if (config.useShadow === false) {
throw new Error('unsupported');
}
else {
const $template = document.createElement('template');
$template.innerHTML = cls[template] || '';
const $node = document.importNode($template.content, true);
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.adoptedStyleSheets = cls[style].reduce((acc, value) => {
if (!value) {
return acc;
}
if (value instanceof CSSStyleSheet) {
acc.push(value);
return acc;
}
var s = new CSSStyleSheet();
s.replaceSync(value.toString());
acc.push(s);
return acc;
}, []);
shadowRoot.appendChild($node);
}
}
else if (this[init] && config.style) {
/*if (this.shadowRoot) {
const style = document.createElement('style');
style.appendChild(document.createTextNode(config.style));
this.appendChild(style);
}*/
// } else if (this[init] && config.template) {
// This is allowed now via <parent/>
// throw new Error('template from base class cannot be overriden. Fix: remove template from @Component');
}
else if (this[init] && config.selector && !config.template) {
throw new Error('You need to pass a template for an extended element.');
}
const tags = new Set();
for (const ele of this.shadowRoot.querySelectorAll('*')) {
if (ele.localName.indexOf('-') !== -1) {
tags.add(ele.localName);
}
}
const promises = Array.from(tags.values()).map(tag => {
return customElements.get(tag)
? Promise.resolve()
: customElements.whenDefined(tag);
});
const render = () => {
this.constructor[renderList].map((renderFn) => {
renderFn.call(this, cls.observedAttributes
? cls.observedAttributes.reduce((a, c) => {
const n = dashToCamel(c);
a[n] = true;
return a;
}, {})
: {});
});
};
if (promises.length === 0) {
this[init] = true;
connectedCallback.call(this);
render();
}
else {
Promise.all(promises).then(() => {
this[init] = true;
connectedCallback.call(this);
// dispatch slotchange
for (const slot of this.shadowRoot.querySelectorAll('slot')) {
slot.dispatchEvent(new CustomEvent('slotchange'));
}
render();
});
}
};
cls.prototype.disconnectedCallback = function () {
disconnectedCallback.call(this);
};
cls.prototype.attributeChangedCallback = function (name, oldValue, newValue) {
const normalizedName = dashToCamel(name);
this[normalizedName] = newValue;
};
// Base components may not define a selector
context.addInitializer(function () {
if (config.selector) {
if (window.customElements.get(config.selector)) {
throw new Error(`@Component() ${context.name} duplicate selector '${config.selector}'`);
}
window.customElements.define(config.selector, cls);
}
});
};
}
const transmute = Symbol('transmute');
export function TransmutePart(part, selector) {
return function (cls) {
if (cls.prototype[transmute]) {
cls.prototype[transmute][part] = selector;
}
else {
cls.prototype[transmute] = { [part]: selector };
}
};
}
function isArray(a) {
return (!!a) && (a.constructor === Array);
}
function isObject(a) {
return (!!a) && (a.constructor === Object);
}
function render(self, propertyKey) {
if (self[init]) {
self.constructor[renderList].map((renderFn) => {
renderFn.call(self, { [propertyKey]: true });
});
}
}
function getSymbolType(value) {
if (value === null) {
return 'null';
}
return isArray(value) ? 'array' : typeof value;
}
export function Prop(normalize) {
return function (_, context) {
const propertyKey = context.name;
const symbol = Symbol(propertyKey);
const symbolType = Symbol(`${propertyKey}:type`);
const symbolMeta = Symbol(`${propertyKey}:meta`);
context.addInitializer(function () {
if (context.private) {
return;
}
Reflect.defineProperty(this, propertyKey, {
get: () => {
if (this[symbolType] === 'object') {
if (this[symbol][isProxy]) {
return this[symbol];
}
else {
return createProxy(this[symbol]);
}
}
if (this[symbolType] === 'array') {
if (this[symbol][isProxy]) {
return this[symbol];
}
else {
return createProxy(this[symbol]);
}
}
return this[symbol];
},
set: (value) => {
// ToDo: cleanup
const newSymbolType = getSymbolType(normalize ? normalize(value) : value);
if (propertyKey !== 'index' && this[symbolType] !== newSymbolType
&& this[symbolType] !== 'null' && newSymbolType !== 'null') {
throw new Error(`@Prop() ${propertyKey} with type '${this[symbolType]}' cannot be set to ${newSymbolType}.`);
}
if (this[symbolType] === 'array') {
if (!isArray(value)) {
throw new PropError(`Array "${propertyKey}" (Prop) initialized already. Reassignments must be array type.`, Object.getOwnPropertyDescriptor(this, propertyKey)?.set);
}
const unproxyValue = value[isProxy] ? value[getTarget] : value;
if (this[symbol] === unproxyValue) {
throw new Error('Setting an array to itself is not allowed.');
}
// Unwrap proxied items (e.g. from items.filter(...)) so observers
// stay keyed by the raw item objects.
for (let i = 0; i < unproxyValue.length; i++) {
const item = unproxyValue[i];
if (item && item[isProxy]) {
unproxyValue[i] = item[getTarget];
}
}
const proxified = createProxy(this[symbol]);
if (proxified[hasObserver](this)) {
proxified[swapObserver](this, unproxyValue);
// render(this, propertyKey); // do we need to trigger this for arrays being remapped?
}
this[symbol] = unproxyValue;
}
else {
this[symbol] = normalize ? normalize(value) : value;
render(this, propertyKey);
}
}
});
});
return function (initialValue) {
if (initialValue === undefined && propertyKey !== 'index') {
throw new Error(`@Prop() ${propertyKey} must have an initial value defined.`);
}
else if (initialValue !== undefined && propertyKey === 'index') {
throw new Error(`@Prop() index must not have an initial value defined.`);
}
if (initialValue === true) {
throw new Error(`@Prop() ${propertyKey} boolean must initialize to false.`);
}
// Web Component, todo: refactor to only be called once
if (!context.private) {
const { constructor } = this;
constructor.observedAttributes ??= [];
if (!constructor.symbols) {
constructor.symbols = {};
}
const { symbols } = constructor;
const normalizedPropertyKey = camelToDash(propertyKey);
if (!symbols[propertyKey]) {
constructor.observedAttributes.push(normalizedPropertyKey);
symbols[propertyKey] = symbol;
}
}
// Rest
this[symbolType] = getSymbolType(initialValue);
if (this[symbolType] === 'array') {
this[symbol] = initialValue;
if (context.private) {
return createProxy(initialValue);
}
return new Proxy(initialValue, {
get: (target, key) => {
if (key === meta) {
return this[symbolMeta];
}
return Reflect.get(this[symbol], key);
},
set: (target, key, v) => {
if (key === meta) {
this[symbolMeta] = v;
return true;
}
const x = Reflect.set(target, key, v);
if (!(key === 'length' && this[symbol].length === v)) {
render(this, propertyKey);
}
this[symbol] = v;
return x;
}
});
}
// todo watch objects???
if (context.private) {
this[symbol] = normalize ? normalize(initialValue) : initialValue;
return this[symbol];
}
this[symbol] = normalize
? normalize(this.getAttribute(propertyKey) ?? initialValue)
: this.getAttribute(propertyKey) ?? initialValue;
return this[symbol];
};
};
}
export function Part() {
return function (_, context) {
const propertyKey = context.name;
const key = propertyKey.replace(/^\$/, '');
context.addInitializer(function () {
let cache = null;
Reflect.defineProperty(this, propertyKey, {
get() {
return cache ?? (cache = this.shadowRoot?.querySelector(`[part~=${key}]`));
}
});
});
};
}
/**
* Store data via a Map into LocalStorage
* @param key String
* @returns Value
*/
export function Local(key) {
return function (_, context) {
const propertyKey = context.name;
return function (initialValue) {
if (!(initialValue instanceof Map)) {
throw new Error('@Local(key) property must be type Map');
}
return new Proxy(initialValue, {
get(target, prop) {
switch (prop) {
case 'get':
return (k) => {
if (!initialValue.has(k)) {
throw new Error(`@Local(key) missing key ${k}`);
}
const storeKey = `${key}:${k}`;
if (window.localStorage.getItem(storeKey) === null) {
const keyValue = initialValue.get(k);
return Array.isArray(keyValue) || isObject(keyValue)
? JSON.parse(JSON.stringify(keyValue))
: keyValue;
}
else {
return JSON.parse(window.localStorage.getItem(storeKey) ?? 'null');
}
};
case 'set':
return (k, v) => {
if (!initialValue.has(k)) {
throw new Error(`@Local(key) missing key ${k}`);
}
const storeKey = `${key}:${k}`;
if (v === null || JSON.stringify(v) === JSON.stringify(initialValue.get(k))) {
window.localStorage.removeItem(storeKey);
}
else {
window.localStorage.setItem(storeKey, JSON.stringify(v));
}
};
default:
throw new Error(`@Local(key) supported method ${prop}`);
}
}
});
};
};
}
export function node(template, init) {
const $template = document.createElement('template');
$template.innerHTML = template;
const $node = document.importNode($template.content, true);
for (const [part, attributes] of Object.entries(init)) {
const $part = $node.querySelector(`[part~="${part}"]`);
if ($part) {
for (const [prop, value] of Object.entries(attributes)) {
if (value instanceof Function) {
const val = value();
if (val === null) {
$part.removeAttribute(prop);
}
else {
$part.setAttribute(prop, value());
}
}
else {
$part[prop] = value;
}
}
}
}
return $node;
}
export function normalizeInt(value) {
return parseInt(`${value}`, 10);
}
export function normalizeFloat(value) {
return parseFloat(`${value}`);
}
export function normalizeBoolean(value) {
return value === '' || value === true
? true
: value === null || value === false
? false
: value || true;
}
export function normalizeString(value) {
return `${value}`;
}
const trackProxy = Symbol('hasProxy');
function hasProxy(obj) {
if (obj === null || typeof obj !== "object")
return false;
return obj[trackProxy];
}
const meta = Symbol('meta');
function intersect(arr1, arr2) {
const set1 = new Set(arr1);
return arr2.filter(item => set1.has(item));
}
function difference(arr1, arr2) {
return arr1.filter(str => !arr2.includes(str));
}
const PROP_ALIAS = { id: 'itemId' };
function mapPropKey(key, allProps) {
const alias = PROP_ALIAS[key];
return alias && allProps.includes(alias) ? alias : key;
}
export function forEach({ container, items, type, create, connect, disconnect, update }) {
if (!Array.isArray(items)) {
throw new Error('forEach `items` must be an array');
}
const elementMap = new WeakMap();
// Tracks raw item objects in items-array order; used to recover pre-mutation state.
const localItems = [];
function raw(item) {
return item && item[isProxy] ? item[getTarget] : item;
}
function isRendered(rawItem) {
return elementMap.has(rawItem);
}
function renderedCountBefore(logicalIndex) {
let count = 0;
for (let i = 0; i < logicalIndex && i < localItems.length; i++) {
if (isRendered(localItems[i]))
count++;
}
return count;
}
function newItem(item, domIndex) {
const comp = type(item);
if (comp === null)
return null;
const $new = document.createElement(camelToDash(comp.name), comp);
const allProps = Object.keys(comp.symbols);
const props = intersect(Object.keys(item), allProps);
if (allProps.includes('index')) {
//@ts-ignore
$new['index'] = domIndex;
}
props.forEach((attr) => {
// index is already written
if (attr === 'index') {
return;
}
//@ts-ignore
$new[attr] = item[attr];
});
// Apply prop aliases (e.g., data `id` → component `itemId`) when not already set above
for (const [dataKey, compKey] of Object.entries(PROP_ALIAS)) {
if (dataKey in item && allProps.includes(compKey) && !props.includes(compKey)) {
//@ts-ignore
$new[compKey] = item[dataKey];
}
}
const rawItem = raw(item);
create && create($new, createProxy(rawItem));
createProxy(rawItem)[addObserver]($new, (prop, value) => {
// @ts-ignore
$new[mapPropKey(prop, allProps)] = value;
});
elementMap.set(rawItem, $new);
return $new;
}
// Add initial items
let initDomIndex = 0;
items.forEach((item) => {
const rawItem = raw(item);
localItems.push(rawItem);
const $new = newItem(item, initDomIndex);
if ($new === null)
return;
container.appendChild($new);
connect && connect($new, createProxy(rawItem));
initDomIndex++;
});
// Handle each mutation
items[addObserver](container, (target, prop, args) => {
if (prop === Mutation.swap) {
// Reconcile the newly assigned array against the current items by
// identity, reusing DOM nodes for items present in both arrays.
const newArr = args[0];
items = createProxy(newArr);
const newRaws = newArr.map((item) => raw(item));
const newSet = new Set(newRaws);
let changed = false;
// Remove items missing from the new array.
let write = 0;
for (let read = 0; read < localItems.length; read++) {
const rawItem = localItems[read];
if (newSet.has(rawItem)) {
localItems[write++] = rawItem;
continue;
}
if (isRendered(rawItem)) {
const $el = elementMap.get(rawItem);
disconnect && disconnect($el, createProxy(rawItem));
$el.remove();
createProxy(rawItem)[removeObserver]($el);
elementMap.delete(rawItem);
}
changed = true;
}
localItems.length = write;
// Reorder kept items when their relative order changed.
const newIndexes = new Map(newRaws.map((rawItem, i) => [rawItem, i]));
let ordered = true;
let previous = -1;
for (const rawItem of localItems) {
const newIndex = newIndexes.get(rawItem);
if (newIndex < previous) {
ordered = false;
break;
}
previous = newIndex;
}
if (!ordered) {
localItems.sort((a, b) => newIndexes.get(a) - newIndexes.get(b));
localItems.forEach((rawItem) => {
const $el = elementMap.get(rawItem);
if ($el)
container.appendChild($el);
});
changed = true;
}
// Insert added items, batching contiguous runs into single insertions.
const connectQueue = [];
for (let i = 0; i < newRaws.length; i++) {
if (localItems[i] === newRaws[i])
continue;
const anchor = i < localItems.length ? localItems[i] : undefined;
let runEnd = i;
while (runEnd < newRaws.length && newRaws[runEnd] !== anchor)
runEnd++;
const runRaws = newRaws.slice(i, runEnd);
const domStart = renderedCountBefore(i);
const nItems = [];
runRaws.forEach((rawItem) => {
const $new = newItem(rawItem, domStart + nItems.length);
if ($new !== null) {
nItems.push($new);
connectQueue.push([$new, rawItem]);
}
});
if (nItems.length > 0) {
if (domStart === 0) {
container.prepend(...nItems);
}
else {
container.children[domStart - 1].after(...nItems);
}
}
localItems.splice(i, 0, ...runRaws);
changed = true;
i = runEnd - 1;
}
// Single index pass instead of one per mutation.
if (changed) {
for (let i = 0; i < container.children.length; i++) {
// @ts-ignore
container.children[i].index = i;
}
}
connectQueue.forEach(([$el, rawItem]) => {
connect && connect($el, createProxy(rawItem));
});
return;
}
switch (prop) {
case Mutation.fill: {
const [value, start, end] = args;
const fillStart = start || 0;
const fillEnd = end || localItems.length;
let domFillIdx = renderedCountBefore(fillStart);
for (let i = fillStart; i < fillEnd; i++) {
if (isRendered(localItems[i])) {
const $child = container.children[domFillIdx];
const childAllProps = Object.keys($child.constructor?.symbols ?? {});
Object.keys(value).forEach((key) => {
// @ts-ignore
$child[mapPropKey(key, childAllProps)] = value[key];
});
domFillIdx++;
}
localItems[i] = value;
}
break;
}
case Mutation.pop: {
const poppedRaw = localItems[localItems.length - 1];
if (poppedRaw !== undefined && isRendered(poppedRaw)) {
const $el = elementMap.get(poppedRaw);
disconnect && disconnect($el, createProxy(poppedRaw));
$el.remove();
createProxy(poppedRaw)[removeObserver]($el);
elementMap.delete(poppedRaw);
}
localItems.pop();
break;
}
case Mutation.push: {
[...args].forEach((item) => {
const rawItem = raw(item);
localItems.push(rawItem);
const $new = newItem(item, container.children.length);
if ($new === null)
return;
container.appendChild($new);
connect && connect($new, createProxy(rawItem));
});
break;
}
case Mutation.reverse: {
for (var i = 1; i < container.children.length; i++) {
container.insertBefore(container.children[i], container.children[0]);
}
localItems.reverse();
break;
}
case Mutation.shift: {
const shiftedRaw = localItems[0];
if (shiftedRaw !== undefined && isRendered(shiftedRaw)) {
const $el = elementMap.get(shiftedRaw);
disconnect && disconnect($el, createProxy(shiftedRaw));
$el.remove();
createProxy(shiftedRaw)[removeObserver]($el);
elementMap.delete(shiftedRaw);
}
localItems.shift();
for (let i = 0; i < container.children.length; i++) {
// @ts-ignore
container.children[i].index = i;
}
break;
}
case Mutation.sort: {
target.forEach((item) => {
const rawItem = raw(item);
const $el = elementMap.get(rawItem);
if ($el)
container.appendChild($el);
});
for (let i = 0; i < container.children.length; i++) {
// @ts-ignore
container.children[i].index = i;
}
localItems.length = 0;
target.forEach((item) => localItems.push(raw(item)));
break;
}
case Mutation.splice: {
const [startIndex, deleteCount, ...newItems] = args;
if (startIndex < 0) {
throw new Error('invalid startIndex, must be greater than or equal to 0');
}
// Determine the DOM insertion/deletion point by counting rendered items before startIndex.
const domStart = renderedCountBefore(startIndex);
// Remove deleted items from DOM (always remove at domStart since children shift up).
const deletedRaws = localItems.slice(startIndex, startIndex + deleteCount);
deletedRaws.forEach((rawItem) => {
if (isRendered(rawItem)) {
const $el = elementMap.get(rawItem);
disconnect && disconnect($el, createProxy(rawItem));
$el.remove();
createProxy(rawItem)[removeObserver]($el);
elementMap.delete(rawItem);
}
});
// Create elements for new items, skipping null-typed ones.
const nItems = [];
newItems.forEach((item) => {
const $new = newItem(item, domStart + nItems.length);
if ($new !== null)
nItems.push($new);
});
if (nItems.length > 0) {
if (domStart === 0) {
container.prepend(...nItems);
}
else {
container.children[domStart - 1].after(...nItems);
}
}
// Update indices for all items from the insertion point onward.
for (let i = domStart; i < container.children.length; i++) {
// @ts-ignore
container.children[i].index = i;
}
// Fire connect for each newly rendered item.
let nIdx = 0;
newItems.forEach((item) => {
const rawItem = raw(item);
if (isRendered(rawItem)) {
connect && connect(nItems[nIdx++], createProxy(rawItem));
}
});
localItems.splice(startIndex, deleteCount, ...newItems.map(raw));
break;
}
case Mutation.unshift: {
const unshiftItems = [...args];
const firstChild = container.children.length ? container.children[0] : null;
const nItems = [];
unshiftItems.forEach((item) => {
const $new = newItem(item, nItems.length);
if ($new !== null)
nItems.push($new);
});
if (nItems.length > 0) {
if (firstChild) {
firstChild.before(...nItems);
}
else {
container.append(...nItems);
}
}
// Update indices for all items (new ones first, then existing).
for (let i = 0; i < container.children.length; i++) {
// @ts-ignore
container.children[i].index = i;
}
localItems.unshift(...unshiftItems.map(raw));
// Fire connect for each newly rendered item.
let nIdx = 0;
unshiftItems.forEach((item) => {
const rawItem = raw(item);
if (isRendered(rawItem)) {
connect && connect(nItems[nIdx++], createProxy(rawItem));
}
});
break;
}
}
});
}
// JEST
export function selectComponent(tagName) {
const component = document.querySelector(tagName);
const tags = new Set();
let shadowRoot;
try {
shadowRoot = component.shadowRoot;
}
catch (error) {
throw new Error('Add the component via document.body.appendChild(...) before selectComponent.');
}
for (const ele of shadowRoot.querySelectorAll('*')) {
if (ele.localName.indexOf('-') !== -1) {
tags.add(ele.localName);
}
}
for (var it = tags.values(), tag = null; tag = it.next().value;) {
if (!customElements.get(tag)) {
const namespaceMatch = tag.match(/^([^-]+)/);
if (namespaceMatch === null || namespaceMatch.length > 1) {
throw new Error('Failed to parse namespace.');
}
const namespace = namespaceMatch[1];
const componentMatch = tag.match(/^[^-]+-(.+)/);
if (componentMatch === null || componentMatch.length > 1) {
throw new Error('Failed to parse component name.');
}
const componentName = dashToCamel(componentMatch[1]);
throw new Error(`Missing \`import '../${componentName}/${componentName}';\` in spec.ts file.`);
}
}
return component;
}
export function selectPart(component, name) {
return component.shadowRoot.querySelector(`[part=${name}]`);
}
export function getProps(tag) {
const { symbols } = customElements.get(tag);
return Object.keys(symbols ?? {});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWxlbWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9lbGVtZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sYUFBYSxDQUFDO0FBQ3JCLE9BQU8sRUFDTCxRQUFRLEVBQ1IsV0FBVyxFQUNYLFdBQVcsRUFDWCxjQUFjLEVBQ2QsWUFBWSxFQUNaLFdBQVcsRUFDWCxPQUFPLEVBQ1AsU0FBUyxFQUNWLE1BQU0sWUFBWSxDQUFDO0FBY3BCLE1BQU0sU0FBVSxTQUFRLEtBQUs7SUFDM0IsWUFBWSxPQUFlLEVBQUUsTUFBVztRQUN0QyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZixJQUFJLENBQUMsSUFBSSxHQUFHLFdBQVcsQ0FBQztRQUN4QixhQUFhO1FBQ2IsSUFBSSxLQUFLLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUM1QixhQUFhO1lBQ2IsS0FBSyxDQUFDLGlCQUFpQixDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQztRQUN4QyxDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBRUQsTUFBTSxDQUFDLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUNyQyxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDNUIsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0FBQ3BDLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUM5QixNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDaEMsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO0FBRXhDLE1BQU0sVUFBVSxhQUFhLENBQUMsR0FBUTtJQUNwQyxPQUFPLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7QUFDeEMsQ0FBQztBQUVELFNBQVMsY0FBYyxDQUFDLElB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