first commit

This commit is contained in:
becarta
2025-05-16 00:17:42 +02:00
parent ea5c866137
commit bacf566ec9
6020 changed files with 1715262 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
import { directive, PartType } from '../directive.js';
import { AsyncReplaceDirective } from './async-replace.js';
import { clearPart, insertPart, setChildPartValue } from '../directive-helpers.js';
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
class AsyncAppendDirective extends AsyncReplaceDirective {
// Override AsyncReplace to narrow the allowed part type to ChildPart only
constructor(partInfo) {
super(partInfo);
if (partInfo.type !== PartType.CHILD) {
throw new Error('asyncAppend can only be used in child expressions');
}
}
// Override AsyncReplace to save the part since we need to append into it
update(part, params) {
this.__childPart = part;
return super.update(part, params);
}
// Override AsyncReplace to append rather than replace
commitValue(value, index) {
// When we get the first value, clear the part. This lets the
// previous value display until we can replace it.
if (index === 0) {
clearPart(this.__childPart);
}
// Create and insert a new part and set its value to the next value
const newPart = insertPart(this.__childPart);
setChildPartValue(newPart, value);
}
}
/**
* A directive that renders the items of an async iterable[1], appending new
* values after previous values, similar to the built-in support for iterables.
* This directive is usable only in child expressions.
*
* Async iterables are objects with a [Symbol.asyncIterator] method, which
* returns an iterator who's `next()` method returns a Promise. When a new
* value is available, the Promise resolves and the value is appended to the
* Part controlled by the directive. If another value other than this
* directive has been set on the Part, the iterable will no longer be listened
* to and new values won't be written to the Part.
*
* [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of
*
* @param value An async iterable
* @param mapper An optional function that maps from (value, index) to another
* value. Useful for generating templates for each item in the iterable.
*/
const asyncAppend = directive(AsyncAppendDirective);
export { asyncAppend };
//# sourceMappingURL=async-append.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"async-append.js","sources":["../../../src/directives/async-append.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport {ChildPart} from '../lit-html.js';\nimport {\n directive,\n DirectiveParameters,\n PartInfo,\n PartType,\n} from '../directive.js';\nimport {AsyncReplaceDirective} from './async-replace.js';\nimport {\n clearPart,\n insertPart,\n setChildPartValue,\n} from '../directive-helpers.js';\n\nclass AsyncAppendDirective extends AsyncReplaceDirective {\n private __childPart!: ChildPart;\n\n // Override AsyncReplace to narrow the allowed part type to ChildPart only\n constructor(partInfo: PartInfo) {\n super(partInfo);\n if (partInfo.type !== PartType.CHILD) {\n throw new Error('asyncAppend can only be used in child expressions');\n }\n }\n\n // Override AsyncReplace to save the part since we need to append into it\n override update(part: ChildPart, params: DirectiveParameters<this>) {\n this.__childPart = part;\n return super.update(part, params);\n }\n\n // Override AsyncReplace to append rather than replace\n protected override commitValue(value: unknown, index: number) {\n // When we get the first value, clear the part. This lets the\n // previous value display until we can replace it.\n if (index === 0) {\n clearPart(this.__childPart);\n }\n // Create and insert a new part and set its value to the next value\n const newPart = insertPart(this.__childPart);\n setChildPartValue(newPart, value);\n }\n}\n\n/**\n * A directive that renders the items of an async iterable[1], appending new\n * values after previous values, similar to the built-in support for iterables.\n * This directive is usable only in child expressions.\n *\n * Async iterables are objects with a [Symbol.asyncIterator] method, which\n * returns an iterator who's `next()` method returns a Promise. When a new\n * value is available, the Promise resolves and the value is appended to the\n * Part controlled by the directive. If another value other than this\n * directive has been set on the Part, the iterable will no longer be listened\n * to and new values won't be written to the Part.\n *\n * [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of\n *\n * @param value An async iterable\n * @param mapper An optional function that maps from (value, index) to another\n * value. Useful for generating templates for each item in the iterable.\n */\nexport const asyncAppend = directive(AsyncAppendDirective);\n\n/**\n * The type of the class that powers this directive. Necessary for naming the\n * directive's return type.\n */\nexport type {AsyncAppendDirective};\n"],"names":[],"mappings":";;;;AAAA;;;;AAIG;AAgBH,MAAM,oBAAqB,SAAQ,qBAAqB,CAAA;;AAItD,IAAA,WAAA,CAAY,QAAkB,EAAA;QAC5B,KAAK,CAAC,QAAQ,CAAC,CAAC;AAChB,QAAA,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,KAAK,EAAE;AACpC,YAAA,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;AACtE,SAAA;KACF;;IAGQ,MAAM,CAAC,IAAe,EAAE,MAAiC,EAAA;AAChE,QAAA,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;KACnC;;IAGkB,WAAW,CAAC,KAAc,EAAE,KAAa,EAAA;;;QAG1D,IAAI,KAAK,KAAK,CAAC,EAAE;AACf,YAAA,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AAC7B,SAAA;;QAED,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AAC7C,QAAA,iBAAiB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;KACnC;AACF,CAAA;AAED;;;;;;;;;;;;;;;;;AAiBG;MACU,WAAW,GAAG,SAAS,CAAC,oBAAoB;;;;"}

View File

@@ -0,0 +1,104 @@
import { noChange } from '../lit-html.js';
import { AsyncDirective } from '../async-directive.js';
import { PseudoWeakRef, Pauser, forAwaitOf } from './private-async-helpers.js';
import { directive } from '../directive.js';
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
class AsyncReplaceDirective extends AsyncDirective {
constructor() {
super(...arguments);
this.__weakThis = new PseudoWeakRef(this);
this.__pauser = new Pauser();
}
// @ts-expect-error value not used, but we want a nice parameter for docs
// eslint-disable-next-line @typescript-eslint/no-unused-vars
render(value, _mapper) {
return noChange;
}
update(_part, [value, mapper]) {
// If our initial render occurs while disconnected, ensure that the pauser
// and weakThis are in the disconnected state
if (!this.isConnected) {
this.disconnected();
}
// If we've already set up this particular iterable, we don't need
// to do anything.
if (value === this.__value) {
return;
}
this.__value = value;
let i = 0;
const { __weakThis: weakThis, __pauser: pauser } = this;
// Note, the callback avoids closing over `this` so that the directive
// can be gc'ed before the promise resolves; instead `this` is retrieved
// from `weakThis`, which can break the hard reference in the closure when
// the directive disconnects
forAwaitOf(value, async (v) => {
// The while loop here handles the case that the connection state
// thrashes, causing the pauser to resume and then get re-paused
while (pauser.get()) {
await pauser.get();
}
// If the callback gets here and there is no `this`, it means that the
// directive has been disconnected and garbage collected and we don't
// need to do anything else
const _this = weakThis.deref();
if (_this !== undefined) {
// Check to make sure that value is the still the current value of
// the part, and if not bail because a new value owns this part
if (_this.__value !== value) {
return false;
}
// As a convenience, because functional-programming-style
// transforms of iterables and async iterables requires a library,
// we accept a mapper function. This is especially convenient for
// rendering a template for each item.
if (mapper !== undefined) {
v = mapper(v, i);
}
_this.commitValue(v, i);
i++;
}
return true;
});
return noChange;
}
// Override point for AsyncAppend to append rather than replace
commitValue(value, _index) {
this.setValue(value);
}
disconnected() {
this.__weakThis.disconnect();
this.__pauser.pause();
}
reconnected() {
this.__weakThis.reconnect(this);
this.__pauser.resume();
}
}
/**
* A directive that renders the items of an async iterable[1], replacing
* previous values with new values, so that only one value is ever rendered
* at a time. This directive may be used in any expression type.
*
* Async iterables are objects with a `[Symbol.asyncIterator]` method, which
* returns an iterator who's `next()` method returns a Promise. When a new
* value is available, the Promise resolves and the value is rendered to the
* Part controlled by the directive. If another value other than this
* directive has been set on the Part, the iterable will no longer be listened
* to and new values won't be written to the Part.
*
* [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of
*
* @param value An async iterable
* @param mapper An optional function that maps from (value, index) to another
* value. Useful for generating templates for each item in the iterable.
*/
const asyncReplace = directive(AsyncReplaceDirective);
export { AsyncReplaceDirective, asyncReplace };
//# sourceMappingURL=async-replace.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,91 @@
import { render, nothing } from '../lit-html.js';
import { directive, Directive } from '../directive.js';
import { isTemplateResult, getCommittedValue, setCommittedValue, insertPart, clearPart, isCompiledTemplateResult } from '../directive-helpers.js';
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* The template strings array contents are not compatible between the two
* template result types as the compiled template contains a prepared string;
* only use the returned template strings array as a cache key.
*/
const getStringsFromTemplateResult = (result) => isCompiledTemplateResult(result) ? result['_$litType$'].h : result.strings;
class CacheDirective extends Directive {
constructor(partInfo) {
super(partInfo);
this._templateCache = new WeakMap();
}
render(v) {
// Return an array of the value to induce lit-html to create a ChildPart
// for the value that we can move into the cache.
return [v];
}
update(containerPart, [v]) {
const _valueKey = isTemplateResult(this._value)
? getStringsFromTemplateResult(this._value)
: null;
const vKey = isTemplateResult(v) ? getStringsFromTemplateResult(v) : null;
// If the previous value is a TemplateResult and the new value is not,
// or is a different Template as the previous value, move the child part
// into the cache.
if (_valueKey !== null && (vKey === null || _valueKey !== vKey)) {
// This is always an array because we return [v] in render()
const partValue = getCommittedValue(containerPart);
const childPart = partValue.pop();
let cachedContainerPart = this._templateCache.get(_valueKey);
if (cachedContainerPart === undefined) {
const fragment = document.createDocumentFragment();
cachedContainerPart = render(nothing, fragment);
cachedContainerPart.setConnected(false);
this._templateCache.set(_valueKey, cachedContainerPart);
}
// Move into cache
setCommittedValue(cachedContainerPart, [childPart]);
insertPart(cachedContainerPart, undefined, childPart);
}
// If the new value is a TemplateResult and the previous value is not,
// or is a different Template as the previous value, restore the child
// part from the cache.
if (vKey !== null) {
if (_valueKey === null || _valueKey !== vKey) {
const cachedContainerPart = this._templateCache.get(vKey);
if (cachedContainerPart !== undefined) {
// Move the cached part back into the container part value
const partValue = getCommittedValue(cachedContainerPart);
const cachedPart = partValue.pop();
// Move cached part back into DOM
clearPart(containerPart);
insertPart(containerPart, undefined, cachedPart);
setCommittedValue(containerPart, [cachedPart]);
}
}
// Because vKey is non null, v must be a TemplateResult.
this._value = v;
}
else {
this._value = undefined;
}
return this.render(v);
}
}
/**
* Enables fast switching between multiple templates by caching the DOM nodes
* and TemplateInstances produced by the templates.
*
* Example:
*
* ```js
* let checked = false;
*
* html`
* ${cache(checked ? html`input is checked` : html`input is not checked`)}
* `
* ```
*/
const cache = directive(CacheDirective);
export { cache };
//# sourceMappingURL=cache.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,43 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* Chooses and evaluates a template function from a list based on matching
* the given `value` to a case.
*
* Cases are structured as `[caseValue, func]`. `value` is matched to
* `caseValue` by strict equality. The first match is selected. Case values
* can be of any type including primitives, objects, and symbols.
*
* This is similar to a switch statement, but as an expression and without
* fallthrough.
*
* @example
*
* ```ts
* render() {
* return html`
* ${choose(this.section, [
* ['home', () => html`<h1>Home</h1>`],
* ['about', () => html`<h1>About</h1>`]
* ],
* () => html`<h1>Error</h1>`)}
* `;
* }
* ```
*/
const choose = (value, cases, defaultCase) => {
for (const c of cases) {
const caseValue = c[0];
if (caseValue === value) {
const fn = c[1];
return fn();
}
}
return defaultCase === null || defaultCase === void 0 ? void 0 : defaultCase();
};
export { choose };
//# sourceMappingURL=choose.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"choose.js","sources":["../../../src/directives/choose.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Chooses and evaluates a template function from a list based on matching\n * the given `value` to a case.\n *\n * Cases are structured as `[caseValue, func]`. `value` is matched to\n * `caseValue` by strict equality. The first match is selected. Case values\n * can be of any type including primitives, objects, and symbols.\n *\n * This is similar to a switch statement, but as an expression and without\n * fallthrough.\n *\n * @example\n *\n * ```ts\n * render() {\n * return html`\n * ${choose(this.section, [\n * ['home', () => html`<h1>Home</h1>`],\n * ['about', () => html`<h1>About</h1>`]\n * ],\n * () => html`<h1>Error</h1>`)}\n * `;\n * }\n * ```\n */\nexport const choose = <T, V>(\n value: T,\n cases: Array<[T, () => V]>,\n defaultCase?: () => V\n) => {\n for (const c of cases) {\n const caseValue = c[0];\n if (caseValue === value) {\n const fn = c[1];\n return fn();\n }\n }\n return defaultCase?.();\n};\n"],"names":[],"mappings":"AAAA;;;;AAIG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;AAwBG;AACU,MAAA,MAAM,GAAG,CACpB,KAAQ,EACR,KAA0B,EAC1B,WAAqB,KACnB;AACF,IAAA,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE;AACrB,QAAA,MAAM,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,SAAS,KAAK,KAAK,EAAE;AACvB,YAAA,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAChB,OAAO,EAAE,EAAE,CAAC;AACb,SAAA;AACF,KAAA;AACD,IAAA,OAAO,WAAW,KAAX,IAAA,IAAA,WAAW,KAAX,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,WAAW,EAAI,CAAC;AACzB;;;;"}

View File

@@ -0,0 +1,93 @@
import { noChange } from '../lit-html.js';
import { directive, Directive, PartType } from '../directive.js';
/**
* @license
* Copyright 2018 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
class ClassMapDirective extends Directive {
constructor(partInfo) {
var _a;
super(partInfo);
if (partInfo.type !== PartType.ATTRIBUTE ||
partInfo.name !== 'class' ||
((_a = partInfo.strings) === null || _a === void 0 ? void 0 : _a.length) > 2) {
throw new Error('`classMap()` can only be used in the `class` attribute ' +
'and must be the only part in the attribute.');
}
}
render(classInfo) {
// Add spaces to ensure separation from static classes
return (' ' +
Object.keys(classInfo)
.filter((key) => classInfo[key])
.join(' ') +
' ');
}
update(part, [classInfo]) {
var _a, _b;
// Remember dynamic classes on the first render
if (this._previousClasses === undefined) {
this._previousClasses = new Set();
if (part.strings !== undefined) {
this._staticClasses = new Set(part.strings
.join(' ')
.split(/\s/)
.filter((s) => s !== ''));
}
for (const name in classInfo) {
if (classInfo[name] && !((_a = this._staticClasses) === null || _a === void 0 ? void 0 : _a.has(name))) {
this._previousClasses.add(name);
}
}
return this.render(classInfo);
}
const classList = part.element.classList;
// Remove old classes that no longer apply
// We use forEach() instead of for-of so that we don't require down-level
// iteration.
this._previousClasses.forEach((name) => {
if (!(name in classInfo)) {
classList.remove(name);
this._previousClasses.delete(name);
}
});
// Add or remove classes based on their classMap value
for (const name in classInfo) {
// We explicitly want a loose truthy check of `value` because it seems
// more convenient that '' and 0 are skipped.
const value = !!classInfo[name];
if (value !== this._previousClasses.has(name) &&
!((_b = this._staticClasses) === null || _b === void 0 ? void 0 : _b.has(name))) {
if (value) {
classList.add(name);
this._previousClasses.add(name);
}
else {
classList.remove(name);
this._previousClasses.delete(name);
}
}
}
return noChange;
}
}
/**
* A directive that applies dynamic CSS classes.
*
* This must be used in the `class` attribute and must be the only part used in
* the attribute. It takes each property in the `classInfo` argument and adds
* the property name to the element's `classList` if the property value is
* truthy; if the property value is falsey, the property name is removed from
* the element's `class`.
*
* For example `{foo: bar}` applies the class `foo` if the value of `bar` is
* truthy.
*
* @param classInfo
*/
const classMap = directive(ClassMapDirective);
export { classMap };
//# sourceMappingURL=class-map.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,83 @@
import { noChange } from '../lit-html.js';
import { directive, Directive } from '../directive.js';
/**
* @license
* Copyright 2018 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
// A sentinel that indicates guard() hasn't rendered anything yet
const initialValue = {};
class GuardDirective extends Directive {
constructor() {
super(...arguments);
this._previousValue = initialValue;
}
render(_value, f) {
return f();
}
update(_part, [value, f]) {
if (Array.isArray(value)) {
// Dirty-check arrays by item
if (Array.isArray(this._previousValue) &&
this._previousValue.length === value.length &&
value.every((v, i) => v === this._previousValue[i])) {
return noChange;
}
}
else if (this._previousValue === value) {
// Dirty-check non-arrays by identity
return noChange;
}
// Copy the value if it's an array so that if it's mutated we don't forget
// what the previous values were.
this._previousValue = Array.isArray(value) ? Array.from(value) : value;
const r = this.render(value, f);
return r;
}
}
/**
* Prevents re-render of a template function until a single value or an array of
* values changes.
*
* Values are checked against previous values with strict equality (`===`), and
* so the check won't detect nested property changes inside objects or arrays.
* Arrays values have each item checked against the previous value at the same
* index with strict equality. Nested arrays are also checked only by strict
* equality.
*
* Example:
*
* ```js
* html`
* <div>
* ${guard([user.id, company.id], () => html`...`)}
* </div>
* `
* ```
*
* In this case, the template only rerenders if either `user.id` or `company.id`
* changes.
*
* guard() is useful with immutable data patterns, by preventing expensive work
* until data updates.
*
* Example:
*
* ```js
* html`
* <div>
* ${guard([immutableItems], () => immutableItems.map(i => html`${i}`))}
* </div>
* `
* ```
*
* In this case, items are mapped over only when the array reference changes.
*
* @param value the value to check before re-rendering
* @param f the template function
*/
const guard = directive(GuardDirective);
export { guard };
//# sourceMappingURL=guard.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"guard.js","sources":["../../../src/directives/guard.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2018 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport {noChange, Part} from '../lit-html.js';\nimport {directive, Directive, DirectiveParameters} from '../directive.js';\n\n// A sentinel that indicates guard() hasn't rendered anything yet\nconst initialValue = {};\n\nclass GuardDirective extends Directive {\n private _previousValue: unknown = initialValue;\n\n render(_value: unknown, f: () => unknown) {\n return f();\n }\n\n override update(_part: Part, [value, f]: DirectiveParameters<this>) {\n if (Array.isArray(value)) {\n // Dirty-check arrays by item\n if (\n Array.isArray(this._previousValue) &&\n this._previousValue.length === value.length &&\n value.every((v, i) => v === (this._previousValue as Array<unknown>)[i])\n ) {\n return noChange;\n }\n } else if (this._previousValue === value) {\n // Dirty-check non-arrays by identity\n return noChange;\n }\n\n // Copy the value if it's an array so that if it's mutated we don't forget\n // what the previous values were.\n this._previousValue = Array.isArray(value) ? Array.from(value) : value;\n const r = this.render(value, f);\n return r;\n }\n}\n\n/**\n * Prevents re-render of a template function until a single value or an array of\n * values changes.\n *\n * Values are checked against previous values with strict equality (`===`), and\n * so the check won't detect nested property changes inside objects or arrays.\n * Arrays values have each item checked against the previous value at the same\n * index with strict equality. Nested arrays are also checked only by strict\n * equality.\n *\n * Example:\n *\n * ```js\n * html`\n * <div>\n * ${guard([user.id, company.id], () => html`...`)}\n * </div>\n * `\n * ```\n *\n * In this case, the template only rerenders if either `user.id` or `company.id`\n * changes.\n *\n * guard() is useful with immutable data patterns, by preventing expensive work\n * until data updates.\n *\n * Example:\n *\n * ```js\n * html`\n * <div>\n * ${guard([immutableItems], () => immutableItems.map(i => html`${i}`))}\n * </div>\n * `\n * ```\n *\n * In this case, items are mapped over only when the array reference changes.\n *\n * @param value the value to check before re-rendering\n * @param f the template function\n */\nexport const guard = directive(GuardDirective);\n\n/**\n * The type of the class that powers this directive. Necessary for naming the\n * directive's return type.\n */\nexport type {GuardDirective};\n"],"names":[],"mappings":";;;AAAA;;;;AAIG;AAKH;AACA,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB,MAAM,cAAe,SAAQ,SAAS,CAAA;AAAtC,IAAA,WAAA,GAAA;;QACU,IAAc,CAAA,cAAA,GAAY,YAAY,CAAC;KA2BhD;IAzBC,MAAM,CAAC,MAAe,EAAE,CAAgB,EAAA;QACtC,OAAO,CAAC,EAAE,CAAC;KACZ;AAEQ,IAAA,MAAM,CAAC,KAAW,EAAE,CAAC,KAAK,EAAE,CAAC,CAA4B,EAAA;AAChE,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;;AAExB,YAAA,IACE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC;AAClC,gBAAA,IAAI,CAAC,cAAc,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;AAC3C,gBAAA,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAM,IAAI,CAAC,cAAiC,CAAC,CAAC,CAAC,CAAC,EACvE;AACA,gBAAA,OAAO,QAAQ,CAAC;AACjB,aAAA;AACF,SAAA;AAAM,aAAA,IAAI,IAAI,CAAC,cAAc,KAAK,KAAK,EAAE;;AAExC,YAAA,OAAO,QAAQ,CAAC;AACjB,SAAA;;;QAID,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;QACvE,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AAChC,QAAA,OAAO,CAAC,CAAC;KACV;AACF,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCG;MACU,KAAK,GAAG,SAAS,CAAC,cAAc;;;;"}

View File

@@ -0,0 +1,17 @@
import { nothing } from '../lit-html.js';
/**
* @license
* Copyright 2018 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* For AttributeParts, sets the attribute if the value is defined and removes
* the attribute if the value is undefined.
*
* For other part types, this directive is a no-op.
*/
const ifDefined = (value) => value !== null && value !== void 0 ? value : nothing;
export { ifDefined };
//# sourceMappingURL=if-defined.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"if-defined.js","sources":["../../../src/directives/if-defined.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2018 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport {nothing} from '../lit-html.js';\n\n/**\n * For AttributeParts, sets the attribute if the value is defined and removes\n * the attribute if the value is undefined.\n *\n * For other part types, this directive is a no-op.\n */\nexport const ifDefined = <T>(value: T) => value ?? nothing;\n"],"names":[],"mappings":";;AAAA;;;;AAIG;AAIH;;;;;AAKG;AACU,MAAA,SAAS,GAAG,CAAI,KAAQ,KAAK,KAAK,aAAL,KAAK,KAAA,KAAA,CAAA,GAAL,KAAK,GAAI;;;;"}

View File

@@ -0,0 +1,21 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
function* join(items, joiner) {
const isFunction = typeof joiner === 'function';
if (items !== undefined) {
let i = -1;
for (const value of items) {
if (i > -1) {
yield isFunction ? joiner(i) : joiner;
}
i++;
yield value;
}
}
}
export { join };
//# sourceMappingURL=join.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"join.js","sources":["../../../src/directives/join.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Returns an iterable containing the values in `items` interleaved with the\n * `joiner` value.\n *\n * @example\n *\n * ```ts\n * render() {\n * return html`\n * ${join(items, html`<span class=\"separator\">|</span>`)}\n * `;\n * }\n */\nexport function join<I, J>(\n items: Iterable<I> | undefined,\n joiner: (index: number) => J\n): Iterable<I | J>;\nexport function join<I, J>(\n items: Iterable<I> | undefined,\n joiner: J\n): Iterable<I | J>;\nexport function* join<I, J>(items: Iterable<I> | undefined, joiner: J) {\n const isFunction = typeof joiner === 'function';\n if (items !== undefined) {\n let i = -1;\n for (const value of items) {\n if (i > -1) {\n yield isFunction ? joiner(i) : joiner;\n }\n i++;\n yield value;\n }\n }\n}\n"],"names":[],"mappings":"AAAA;;;;AAIG;UAuBc,IAAI,CAAO,KAA8B,EAAE,MAAS,EAAA;AACnE,IAAA,MAAM,UAAU,GAAG,OAAO,MAAM,KAAK,UAAU,CAAC;IAChD,IAAI,KAAK,KAAK,SAAS,EAAE;AACvB,QAAA,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACX,QAAA,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE;AACzB,YAAA,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE;AACV,gBAAA,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;AACvC,aAAA;AACD,YAAA,CAAC,EAAE,CAAC;AACJ,YAAA,MAAM,KAAK,CAAC;AACb,SAAA;AACF,KAAA;AACH;;;;"}

View File

@@ -0,0 +1,42 @@
import { nothing } from '../lit-html.js';
import { directive, Directive } from '../directive.js';
import { setCommittedValue } from '../directive-helpers.js';
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
class Keyed extends Directive {
constructor() {
super(...arguments);
this.key = nothing;
}
render(k, v) {
this.key = k;
return v;
}
update(part, [k, v]) {
if (k !== this.key) {
// Clear the part before returning a value. The one-arg form of
// setCommittedValue sets the value to a sentinel which forces a
// commit the next render.
setCommittedValue(part);
this.key = k;
}
return v;
}
}
/**
* Associates a renderable value with a unique key. When the key changes, the
* previous DOM is removed and disposed before rendering the next value, even
* if the value - such as a template - is the same.
*
* This is useful for forcing re-renders of stateful components, or working
* with code that expects new data to generate new HTML elements, such as some
* animation techniques.
*/
const keyed = directive(Keyed);
export { keyed };
//# sourceMappingURL=keyed.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"keyed.js","sources":["../../../src/directives/keyed.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport {nothing} from '../lit-html.js';\nimport {\n directive,\n Directive,\n ChildPart,\n DirectiveParameters,\n} from '../directive.js';\nimport {setCommittedValue} from '../directive-helpers.js';\n\nclass Keyed extends Directive {\n key: unknown = nothing;\n\n render(k: unknown, v: unknown) {\n this.key = k;\n return v;\n }\n\n override update(part: ChildPart, [k, v]: DirectiveParameters<this>) {\n if (k !== this.key) {\n // Clear the part before returning a value. The one-arg form of\n // setCommittedValue sets the value to a sentinel which forces a\n // commit the next render.\n setCommittedValue(part);\n this.key = k;\n }\n return v;\n }\n}\n\n/**\n * Associates a renderable value with a unique key. When the key changes, the\n * previous DOM is removed and disposed before rendering the next value, even\n * if the value - such as a template - is the same.\n *\n * This is useful for forcing re-renders of stateful components, or working\n * with code that expects new data to generate new HTML elements, such as some\n * animation techniques.\n */\nexport const keyed = directive(Keyed);\n\n/**\n * The type of the class that powers this directive. Necessary for naming the\n * directive's return type.\n */\nexport type {Keyed};\n"],"names":[],"mappings":";;;;AAAA;;;;AAIG;AAWH,MAAM,KAAM,SAAQ,SAAS,CAAA;AAA7B,IAAA,WAAA,GAAA;;QACE,IAAG,CAAA,GAAA,GAAY,OAAO,CAAC;KAiBxB;IAfC,MAAM,CAAC,CAAU,EAAE,CAAU,EAAA;AAC3B,QAAA,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;AACb,QAAA,OAAO,CAAC,CAAC;KACV;AAEQ,IAAA,MAAM,CAAC,IAAe,EAAE,CAAC,CAAC,EAAE,CAAC,CAA4B,EAAA;AAChE,QAAA,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE;;;;YAIlB,iBAAiB,CAAC,IAAI,CAAC,CAAC;AACxB,YAAA,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;AACd,SAAA;AACD,QAAA,OAAO,CAAC,CAAC;KACV;AACF,CAAA;AAED;;;;;;;;AAQG;MACU,KAAK,GAAG,SAAS,CAAC,KAAK;;;;"}

View File

@@ -0,0 +1,80 @@
import { noChange, nothing } from '../lit-html.js';
import { directive, Directive, PartType } from '../directive.js';
import { isSingleExpression, setCommittedValue } from '../directive-helpers.js';
/**
* @license
* Copyright 2020 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
class LiveDirective extends Directive {
constructor(partInfo) {
super(partInfo);
if (!(partInfo.type === PartType.PROPERTY ||
partInfo.type === PartType.ATTRIBUTE ||
partInfo.type === PartType.BOOLEAN_ATTRIBUTE)) {
throw new Error('The `live` directive is not allowed on child or event bindings');
}
if (!isSingleExpression(partInfo)) {
throw new Error('`live` bindings can only contain a single expression');
}
}
render(value) {
return value;
}
update(part, [value]) {
if (value === noChange || value === nothing) {
return value;
}
const element = part.element;
const name = part.name;
if (part.type === PartType.PROPERTY) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if (value === element[name]) {
return noChange;
}
}
else if (part.type === PartType.BOOLEAN_ATTRIBUTE) {
if (!!value === element.hasAttribute(name)) {
return noChange;
}
}
else if (part.type === PartType.ATTRIBUTE) {
if (element.getAttribute(name) === String(value)) {
return noChange;
}
}
// Resets the part's value, causing its dirty-check to fail so that it
// always sets the value.
setCommittedValue(part);
return value;
}
}
/**
* Checks binding values against live DOM values, instead of previously bound
* values, when determining whether to update the value.
*
* This is useful for cases where the DOM value may change from outside of
* lit-html, such as with a binding to an `<input>` element's `value` property,
* a content editable elements text, or to a custom element that changes it's
* own properties or attributes.
*
* In these cases if the DOM value changes, but the value set through lit-html
* bindings hasn't, lit-html won't know to update the DOM value and will leave
* it alone. If this is not what you want--if you want to overwrite the DOM
* value with the bound value no matter what--use the `live()` directive:
*
* ```js
* html`<input .value=${live(x)}>`
* ```
*
* `live()` performs a strict equality check against the live DOM value, and if
* the new value is equal to the live value, does nothing. This means that
* `live()` should not be used when the binding will cause a type conversion. If
* you use `live()` with an attribute binding, make sure that only strings are
* passed in, or the binding will update every render.
*/
const live = directive(LiveDirective);
export { live };
//# sourceMappingURL=live.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"live.js","sources":["../../../src/directives/live.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2020 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport {AttributePart, noChange, nothing} from '../lit-html.js';\nimport {\n directive,\n Directive,\n DirectiveParameters,\n PartInfo,\n PartType,\n} from '../directive.js';\nimport {isSingleExpression, setCommittedValue} from '../directive-helpers.js';\n\nclass LiveDirective extends Directive {\n constructor(partInfo: PartInfo) {\n super(partInfo);\n if (\n !(\n partInfo.type === PartType.PROPERTY ||\n partInfo.type === PartType.ATTRIBUTE ||\n partInfo.type === PartType.BOOLEAN_ATTRIBUTE\n )\n ) {\n throw new Error(\n 'The `live` directive is not allowed on child or event bindings'\n );\n }\n if (!isSingleExpression(partInfo)) {\n throw new Error('`live` bindings can only contain a single expression');\n }\n }\n\n render(value: unknown) {\n return value;\n }\n\n override update(part: AttributePart, [value]: DirectiveParameters<this>) {\n if (value === noChange || value === nothing) {\n return value;\n }\n const element = part.element;\n const name = part.name;\n\n if (part.type === PartType.PROPERTY) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (value === (element as any)[name]) {\n return noChange;\n }\n } else if (part.type === PartType.BOOLEAN_ATTRIBUTE) {\n if (!!value === element.hasAttribute(name)) {\n return noChange;\n }\n } else if (part.type === PartType.ATTRIBUTE) {\n if (element.getAttribute(name) === String(value)) {\n return noChange;\n }\n }\n // Resets the part's value, causing its dirty-check to fail so that it\n // always sets the value.\n setCommittedValue(part);\n return value;\n }\n}\n\n/**\n * Checks binding values against live DOM values, instead of previously bound\n * values, when determining whether to update the value.\n *\n * This is useful for cases where the DOM value may change from outside of\n * lit-html, such as with a binding to an `<input>` element's `value` property,\n * a content editable elements text, or to a custom element that changes it's\n * own properties or attributes.\n *\n * In these cases if the DOM value changes, but the value set through lit-html\n * bindings hasn't, lit-html won't know to update the DOM value and will leave\n * it alone. If this is not what you want--if you want to overwrite the DOM\n * value with the bound value no matter what--use the `live()` directive:\n *\n * ```js\n * html`<input .value=${live(x)}>`\n * ```\n *\n * `live()` performs a strict equality check against the live DOM value, and if\n * the new value is equal to the live value, does nothing. This means that\n * `live()` should not be used when the binding will cause a type conversion. If\n * you use `live()` with an attribute binding, make sure that only strings are\n * passed in, or the binding will update every render.\n */\nexport const live = directive(LiveDirective);\n\n/**\n * The type of the class that powers this directive. Necessary for naming the\n * directive's return type.\n */\nexport type {LiveDirective};\n"],"names":[],"mappings":";;;;AAAA;;;;AAIG;AAYH,MAAM,aAAc,SAAQ,SAAS,CAAA;AACnC,IAAA,WAAA,CAAY,QAAkB,EAAA;QAC5B,KAAK,CAAC,QAAQ,CAAC,CAAC;QAChB,IACE,EACE,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,QAAQ;AACnC,YAAA,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,SAAS;AACpC,YAAA,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,iBAAiB,CAC7C,EACD;AACA,YAAA,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE,CAAC;AACH,SAAA;AACD,QAAA,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,EAAE;AACjC,YAAA,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;AACzE,SAAA;KACF;AAED,IAAA,MAAM,CAAC,KAAc,EAAA;AACnB,QAAA,OAAO,KAAK,CAAC;KACd;AAEQ,IAAA,MAAM,CAAC,IAAmB,EAAE,CAAC,KAAK,CAA4B,EAAA;AACrE,QAAA,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,OAAO,EAAE;AAC3C,YAAA,OAAO,KAAK,CAAC;AACd,SAAA;AACD,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;AAC7B,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;AAEvB,QAAA,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,QAAQ,EAAE;;AAEnC,YAAA,IAAI,KAAK,KAAM,OAAe,CAAC,IAAI,CAAC,EAAE;AACpC,gBAAA,OAAO,QAAQ,CAAC;AACjB,aAAA;AACF,SAAA;AAAM,aAAA,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,iBAAiB,EAAE;YACnD,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE;AAC1C,gBAAA,OAAO,QAAQ,CAAC;AACjB,aAAA;AACF,SAAA;AAAM,aAAA,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,SAAS,EAAE;YAC3C,IAAI,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE;AAChD,gBAAA,OAAO,QAAQ,CAAC;AACjB,aAAA;AACF,SAAA;;;QAGD,iBAAiB,CAAC,IAAI,CAAC,CAAC;AACxB,QAAA,OAAO,KAAK,CAAC;KACd;AACF,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;AAuBG;MACU,IAAI,GAAG,SAAS,CAAC,aAAa;;;;"}

View File

@@ -0,0 +1,32 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* Returns an iterable containing the result of calling `f(value)` on each
* value in `items`.
*
* @example
*
* ```ts
* render() {
* return html`
* <ul>
* ${map(items, (i) => html`<li>${i}</li>`)}
* </ul>
* `;
* }
* ```
*/
function* map(items, f) {
if (items !== undefined) {
let i = 0;
for (const value of items) {
yield f(value, i++);
}
}
}
export { map };
//# sourceMappingURL=map.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"map.js","sources":["../../../src/directives/map.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Returns an iterable containing the result of calling `f(value)` on each\n * value in `items`.\n *\n * @example\n *\n * ```ts\n * render() {\n * return html`\n * <ul>\n * ${map(items, (i) => html`<li>${i}</li>`)}\n * </ul>\n * `;\n * }\n * ```\n */\nexport function* map<T>(\n items: Iterable<T> | undefined,\n f: (value: T, index: number) => unknown\n) {\n if (items !== undefined) {\n let i = 0;\n for (const value of items) {\n yield f(value, i++);\n }\n }\n}\n"],"names":[],"mappings":"AAAA;;;;AAIG;AAEH;;;;;;;;;;;;;;;AAeG;UACc,GAAG,CAClB,KAA8B,EAC9B,CAAuC,EAAA;IAEvC,IAAI,KAAK,KAAK,SAAS,EAAE;QACvB,IAAI,CAAC,GAAG,CAAC,CAAC;AACV,QAAA,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE;AACzB,YAAA,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;AACrB,SAAA;AACF,KAAA;AACH;;;;"}

View File

@@ -0,0 +1,87 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
// Note, this module is not included in package exports so that it's private to
// our first-party directives. If it ends up being useful, we can open it up and
// export it.
/**
* Helper to iterate an AsyncIterable in its own closure.
* @param iterable The iterable to iterate
* @param callback The callback to call for each value. If the callback returns
* `false`, the loop will be broken.
*/
const forAwaitOf = async (iterable, callback) => {
for await (const v of iterable) {
if ((await callback(v)) === false) {
return;
}
}
};
/**
* Holds a reference to an instance that can be disconnected and reconnected,
* so that a closure over the ref (e.g. in a then function to a promise) does
* not strongly hold a ref to the instance. Approximates a WeakRef but must
* be manually connected & disconnected to the backing instance.
*/
class PseudoWeakRef {
constructor(ref) {
this._ref = ref;
}
/**
* Disassociates the ref with the backing instance.
*/
disconnect() {
this._ref = undefined;
}
/**
* Reassociates the ref with the backing instance.
*/
reconnect(ref) {
this._ref = ref;
}
/**
* Retrieves the backing instance (will be undefined when disconnected)
*/
deref() {
return this._ref;
}
}
/**
* A helper to pause and resume waiting on a condition in an async function
*/
class Pauser {
constructor() {
this._promise = undefined;
this._resolve = undefined;
}
/**
* When paused, returns a promise to be awaited; when unpaused, returns
* undefined. Note that in the microtask between the pauser being resumed
* an an await of this promise resolving, the pauser could be paused again,
* hence callers should check the promise in a loop when awaiting.
* @returns A promise to be awaited when paused or undefined
*/
get() {
return this._promise;
}
/**
* Creates a promise to be awaited
*/
pause() {
var _a;
(_a = this._promise) !== null && _a !== void 0 ? _a : (this._promise = new Promise((resolve) => (this._resolve = resolve)));
}
/**
* Resolves the promise which may be awaited
*/
resume() {
var _a;
(_a = this._resolve) === null || _a === void 0 ? void 0 : _a.call(this);
this._promise = this._resolve = undefined;
}
}
export { Pauser, PseudoWeakRef, forAwaitOf };
//# sourceMappingURL=private-async-helpers.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"private-async-helpers.js","sources":["../../../src/directives/private-async-helpers.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n// Note, this module is not included in package exports so that it's private to\n// our first-party directives. If it ends up being useful, we can open it up and\n// export it.\n\n/**\n * Helper to iterate an AsyncIterable in its own closure.\n * @param iterable The iterable to iterate\n * @param callback The callback to call for each value. If the callback returns\n * `false`, the loop will be broken.\n */\nexport const forAwaitOf = async <T>(\n iterable: AsyncIterable<T>,\n callback: (value: T) => Promise<boolean>\n) => {\n for await (const v of iterable) {\n if ((await callback(v)) === false) {\n return;\n }\n }\n};\n\n/**\n * Holds a reference to an instance that can be disconnected and reconnected,\n * so that a closure over the ref (e.g. in a then function to a promise) does\n * not strongly hold a ref to the instance. Approximates a WeakRef but must\n * be manually connected & disconnected to the backing instance.\n */\nexport class PseudoWeakRef<T> {\n private _ref?: T;\n constructor(ref: T) {\n this._ref = ref;\n }\n /**\n * Disassociates the ref with the backing instance.\n */\n disconnect() {\n this._ref = undefined;\n }\n /**\n * Reassociates the ref with the backing instance.\n */\n reconnect(ref: T) {\n this._ref = ref;\n }\n /**\n * Retrieves the backing instance (will be undefined when disconnected)\n */\n deref() {\n return this._ref;\n }\n}\n\n/**\n * A helper to pause and resume waiting on a condition in an async function\n */\nexport class Pauser {\n private _promise?: Promise<void> = undefined;\n private _resolve?: () => void = undefined;\n /**\n * When paused, returns a promise to be awaited; when unpaused, returns\n * undefined. Note that in the microtask between the pauser being resumed\n * an an await of this promise resolving, the pauser could be paused again,\n * hence callers should check the promise in a loop when awaiting.\n * @returns A promise to be awaited when paused or undefined\n */\n get() {\n return this._promise;\n }\n /**\n * Creates a promise to be awaited\n */\n pause() {\n this._promise ??= new Promise((resolve) => (this._resolve = resolve));\n }\n /**\n * Resolves the promise which may be awaited\n */\n resume() {\n this._resolve?.();\n this._promise = this._resolve = undefined;\n }\n}\n"],"names":[],"mappings":"AAAA;;;;AAIG;AAEH;AACA;AACA;AAEA;;;;;AAKG;AACU,MAAA,UAAU,GAAG,OACxB,QAA0B,EAC1B,QAAwC,KACtC;AACF,IAAA,WAAW,MAAM,CAAC,IAAI,QAAQ,EAAE;QAC9B,IAAI,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAC,MAAM,KAAK,EAAE;YACjC,OAAO;AACR,SAAA;AACF,KAAA;AACH,EAAE;AAEF;;;;;AAKG;MACU,aAAa,CAAA;AAExB,IAAA,WAAA,CAAY,GAAM,EAAA;AAChB,QAAA,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;KACjB;AACD;;AAEG;IACH,UAAU,GAAA;AACR,QAAA,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;KACvB;AACD;;AAEG;AACH,IAAA,SAAS,CAAC,GAAM,EAAA;AACd,QAAA,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;KACjB;AACD;;AAEG;IACH,KAAK,GAAA;QACH,OAAO,IAAI,CAAC,IAAI,CAAC;KAClB;AACF,CAAA;AAED;;AAEG;MACU,MAAM,CAAA;AAAnB,IAAA,WAAA,GAAA;QACU,IAAQ,CAAA,QAAA,GAAmB,SAAS,CAAC;QACrC,IAAQ,CAAA,QAAA,GAAgB,SAAS,CAAC;KAwB3C;AAvBC;;;;;;AAMG;IACH,GAAG,GAAA;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC;KACtB;AACD;;AAEG;IACH,KAAK,GAAA;;QACH,CAAA,EAAA,GAAA,IAAI,CAAC,QAAQ,MAAb,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,IAAA,IAAI,CAAC,QAAQ,GAAK,IAAI,OAAO,CAAC,CAAC,OAAO,MAAM,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;KACvE;AACD;;AAEG;IACH,MAAM,GAAA;;AACJ,QAAA,CAAA,EAAA,GAAA,IAAI,CAAC,QAAQ,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,IAAA,CAAA,IAAA,CAAI,CAAC;QAClB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;KAC3C;AACF;;;;"}

View File

@@ -0,0 +1,15 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
function* range(startOrEnd, end, step = 1) {
const start = end === undefined ? 0 : startOrEnd;
end !== null && end !== void 0 ? end : (end = startOrEnd);
for (let i = start; step > 0 ? i < end : end < i; i += step) {
yield i;
}
}
export { range };
//# sourceMappingURL=range.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"range.js","sources":["../../../src/directives/range.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Returns an iterable of integers from `start` to `end` (exclusive)\n * incrementing by `step`.\n *\n * If `start` is omitted, the range starts at `0`. `step` defaults to `1`.\n *\n * @example\n *\n * ```ts\n * render() {\n * return html`\n * ${map(range(8), () => html`<div class=\"cell\"></div>`)}\n * `;\n * }\n * ```\n */\nexport function range(end: number): Iterable<number>;\nexport function range(\n start: number,\n end: number,\n step?: number\n): Iterable<number>;\nexport function* range(startOrEnd: number, end?: number, step = 1) {\n const start = end === undefined ? 0 : startOrEnd;\n end ??= startOrEnd;\n for (let i = start; step > 0 ? i < end : end < i; i += step) {\n yield i;\n }\n}\n"],"names":[],"mappings":"AAAA;;;;AAIG;AAwBG,UAAW,KAAK,CAAC,UAAkB,EAAE,GAAY,EAAE,IAAI,GAAG,CAAC,EAAA;AAC/D,IAAA,MAAM,KAAK,GAAG,GAAG,KAAK,SAAS,GAAG,CAAC,GAAG,UAAU,CAAC;IACjD,GAAG,KAAA,IAAA,IAAH,GAAG,KAAH,KAAA,CAAA,GAAA,GAAG,IAAH,GAAG,GAAK,UAAU,CAAC,CAAA;IACnB,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,EAAE;AAC3D,QAAA,MAAM,CAAC,CAAC;AACT,KAAA;AACH;;;;"}

View File

@@ -0,0 +1,127 @@
import { nothing } from '../lit-html.js';
import { AsyncDirective } from '../async-directive.js';
import { directive } from '../directive.js';
/**
* @license
* Copyright 2020 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* Creates a new Ref object, which is container for a reference to an element.
*/
const createRef = () => new Ref();
/**
* An object that holds a ref value.
*/
class Ref {
}
// When callbacks are used for refs, this map tracks the last value the callback
// was called with, for ensuring a directive doesn't clear the ref if the ref
// has already been rendered to a new spot. It is double-keyed on both the
// context (`options.host`) and the callback, since we auto-bind class methods
// to `options.host`.
const lastElementForContextAndCallback = new WeakMap();
class RefDirective extends AsyncDirective {
render(_ref) {
return nothing;
}
update(part, [ref]) {
var _a;
const refChanged = ref !== this._ref;
if (refChanged && this._ref !== undefined) {
// The ref passed to the directive has changed;
// unset the previous ref's value
this._updateRefValue(undefined);
}
if (refChanged || this._lastElementForRef !== this._element) {
// We either got a new ref or this is the first render;
// store the ref/element & update the ref value
this._ref = ref;
this._context = (_a = part.options) === null || _a === void 0 ? void 0 : _a.host;
this._updateRefValue((this._element = part.element));
}
return nothing;
}
_updateRefValue(element) {
var _a;
if (typeof this._ref === 'function') {
// If the current ref was called with a previous value, call with
// `undefined`; We do this to ensure callbacks are called in a consistent
// way regardless of whether a ref might be moving up in the tree (in
// which case it would otherwise be called with the new value before the
// previous one unsets it) and down in the tree (where it would be unset
// before being set). Note that element lookup is keyed by
// both the context and the callback, since we allow passing unbound
// functions that are called on options.host, and we want to treat
// these as unique "instances" of a function.
const context = (_a = this._context) !== null && _a !== void 0 ? _a : globalThis;
let lastElementForCallback = lastElementForContextAndCallback.get(context);
if (lastElementForCallback === undefined) {
lastElementForCallback = new WeakMap();
lastElementForContextAndCallback.set(context, lastElementForCallback);
}
if (lastElementForCallback.get(this._ref) !== undefined) {
this._ref.call(this._context, undefined);
}
lastElementForCallback.set(this._ref, element);
// Call the ref with the new element value
if (element !== undefined) {
this._ref.call(this._context, element);
}
}
else {
this._ref.value = element;
}
}
get _lastElementForRef() {
var _a, _b, _c;
return typeof this._ref === 'function'
? (_b = lastElementForContextAndCallback
.get((_a = this._context) !== null && _a !== void 0 ? _a : globalThis)) === null || _b === void 0 ? void 0 : _b.get(this._ref)
: (_c = this._ref) === null || _c === void 0 ? void 0 : _c.value;
}
disconnected() {
// Only clear the box if our element is still the one in it (i.e. another
// directive instance hasn't rendered its element to it before us); that
// only happens in the event of the directive being cleared (not via manual
// disconnection)
if (this._lastElementForRef === this._element) {
this._updateRefValue(undefined);
}
}
reconnected() {
// If we were manually disconnected, we can safely put our element back in
// the box, since no rendering could have occurred to change its state
this._updateRefValue(this._element);
}
}
/**
* Sets the value of a Ref object or calls a ref callback with the element it's
* bound to.
*
* A Ref object acts as a container for a reference to an element. A ref
* callback is a function that takes an element as its only argument.
*
* The ref directive sets the value of the Ref object or calls the ref callback
* during rendering, if the referenced element changed.
*
* Note: If a ref callback is rendered to a different element position or is
* removed in a subsequent render, it will first be called with `undefined`,
* followed by another call with the new element it was rendered to (if any).
*
* ```js
* // Using Ref object
* const inputRef = createRef();
* render(html`<input ${ref(inputRef)}>`, container);
* inputRef.value.focus();
*
* // Using callback
* const callback = (inputElement) => inputElement.focus();
* render(html`<input ${ref(callback)}>`, container);
* ```
*/
const ref = directive(RefDirective);
export { createRef, ref };
//# sourceMappingURL=ref.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,417 @@
import { noChange } from '../lit-html.js';
import { directive, Directive, PartType } from '../directive.js';
import { getCommittedValue, setChildPartValue, insertPart, removePart, setCommittedValue } from '../directive-helpers.js';
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
// Helper for generating a map of array item to its index over a subset
// of an array (used to lazily generate `newKeyToIndexMap` and
// `oldKeyToIndexMap`)
const generateMap = (list, start, end) => {
const map = new Map();
for (let i = start; i <= end; i++) {
map.set(list[i], i);
}
return map;
};
class RepeatDirective extends Directive {
constructor(partInfo) {
super(partInfo);
if (partInfo.type !== PartType.CHILD) {
throw new Error('repeat() can only be used in text expressions');
}
}
_getValuesAndKeys(items, keyFnOrTemplate, template) {
let keyFn;
if (template === undefined) {
template = keyFnOrTemplate;
}
else if (keyFnOrTemplate !== undefined) {
keyFn = keyFnOrTemplate;
}
const keys = [];
const values = [];
let index = 0;
for (const item of items) {
keys[index] = keyFn ? keyFn(item, index) : index;
values[index] = template(item, index);
index++;
}
return {
values,
keys,
};
}
render(items, keyFnOrTemplate, template) {
return this._getValuesAndKeys(items, keyFnOrTemplate, template).values;
}
update(containerPart, [items, keyFnOrTemplate, template]) {
var _a;
// Old part & key lists are retrieved from the last update (which may
// be primed by hydration)
const oldParts = getCommittedValue(containerPart);
const { values: newValues, keys: newKeys } = this._getValuesAndKeys(items, keyFnOrTemplate, template);
// We check that oldParts, the committed value, is an Array as an
// indicator that the previous value came from a repeat() call. If
// oldParts is not an Array then this is the first render and we return
// an array for lit-html's array handling to render, and remember the
// keys.
if (!Array.isArray(oldParts)) {
this._itemKeys = newKeys;
return newValues;
}
// In SSR hydration it's possible for oldParts to be an array but for us
// to not have item keys because the update() hasn't run yet. We set the
// keys to an empty array. This will cause all oldKey/newKey comparisons
// to fail and execution to fall to the last nested brach below which
// reuses the oldPart.
const oldKeys = ((_a = this._itemKeys) !== null && _a !== void 0 ? _a : (this._itemKeys = []));
// New part list will be built up as we go (either reused from
// old parts or created for new keys in this update). This is
// saved in the above cache at the end of the update.
const newParts = [];
// Maps from key to index for current and previous update; these
// are generated lazily only when needed as a performance
// optimization, since they are only required for multiple
// non-contiguous changes in the list, which are less common.
let newKeyToIndexMap;
let oldKeyToIndexMap;
// Head and tail pointers to old parts and new values
let oldHead = 0;
let oldTail = oldParts.length - 1;
let newHead = 0;
let newTail = newValues.length - 1;
// Overview of O(n) reconciliation algorithm (general approach
// based on ideas found in ivi, vue, snabbdom, etc.):
//
// * We start with the list of old parts and new values (and
// arrays of their respective keys), head/tail pointers into
// each, and we build up the new list of parts by updating
// (and when needed, moving) old parts or creating new ones.
// The initial scenario might look like this (for brevity of
// the diagrams, the numbers in the array reflect keys
// associated with the old parts or new values, although keys
// and parts/values are actually stored in parallel arrays
// indexed using the same head/tail pointers):
//
// oldHead v v oldTail
// oldKeys: [0, 1, 2, 3, 4, 5, 6]
// newParts: [ , , , , , , ]
// newKeys: [0, 2, 1, 4, 3, 7, 6] <- reflects the user's new
// item order
// newHead ^ ^ newTail
//
// * Iterate old & new lists from both sides, updating,
// swapping, or removing parts at the head/tail locations
// until neither head nor tail can move.
//
// * Example below: keys at head pointers match, so update old
// part 0 in-place (no need to move it) and record part 0 in
// the `newParts` list. The last thing we do is advance the
// `oldHead` and `newHead` pointers (will be reflected in the
// next diagram).
//
// oldHead v v oldTail
// oldKeys: [0, 1, 2, 3, 4, 5, 6]
// newParts: [0, , , , , , ] <- heads matched: update 0
// newKeys: [0, 2, 1, 4, 3, 7, 6] and advance both oldHead
// & newHead
// newHead ^ ^ newTail
//
// * Example below: head pointers don't match, but tail
// pointers do, so update part 6 in place (no need to move
// it), and record part 6 in the `newParts` list. Last,
// advance the `oldTail` and `oldHead` pointers.
//
// oldHead v v oldTail
// oldKeys: [0, 1, 2, 3, 4, 5, 6]
// newParts: [0, , , , , , 6] <- tails matched: update 6
// newKeys: [0, 2, 1, 4, 3, 7, 6] and advance both oldTail
// & newTail
// newHead ^ ^ newTail
//
// * If neither head nor tail match; next check if one of the
// old head/tail items was removed. We first need to generate
// the reverse map of new keys to index (`newKeyToIndexMap`),
// which is done once lazily as a performance optimization,
// since we only hit this case if multiple non-contiguous
// changes were made. Note that for contiguous removal
// anywhere in the list, the head and tails would advance
// from either end and pass each other before we get to this
// case and removals would be handled in the final while loop
// without needing to generate the map.
//
// * Example below: The key at `oldTail` was removed (no longer
// in the `newKeyToIndexMap`), so remove that part from the
// DOM and advance just the `oldTail` pointer.
//
// oldHead v v oldTail
// oldKeys: [0, 1, 2, 3, 4, 5, 6]
// newParts: [0, , , , , , 6] <- 5 not in new map: remove
// newKeys: [0, 2, 1, 4, 3, 7, 6] 5 and advance oldTail
// newHead ^ ^ newTail
//
// * Once head and tail cannot move, any mismatches are due to
// either new or moved items; if a new key is in the previous
// "old key to old index" map, move the old part to the new
// location, otherwise create and insert a new part. Note
// that when moving an old part we null its position in the
// oldParts array if it lies between the head and tail so we
// know to skip it when the pointers get there.
//
// * Example below: neither head nor tail match, and neither
// were removed; so find the `newHead` key in the
// `oldKeyToIndexMap`, and move that old part's DOM into the
// next head position (before `oldParts[oldHead]`). Last,
// null the part in the `oldPart` array since it was
// somewhere in the remaining oldParts still to be scanned
// (between the head and tail pointers) so that we know to
// skip that old part on future iterations.
//
// oldHead v v oldTail
// oldKeys: [0, 1, -, 3, 4, 5, 6]
// newParts: [0, 2, , , , , 6] <- stuck: update & move 2
// newKeys: [0, 2, 1, 4, 3, 7, 6] into place and advance
// newHead
// newHead ^ ^ newTail
//
// * Note that for moves/insertions like the one above, a part
// inserted at the head pointer is inserted before the
// current `oldParts[oldHead]`, and a part inserted at the
// tail pointer is inserted before `newParts[newTail+1]`. The
// seeming asymmetry lies in the fact that new parts are
// moved into place outside in, so to the right of the head
// pointer are old parts, and to the right of the tail
// pointer are new parts.
//
// * We always restart back from the top of the algorithm,
// allowing matching and simple updates in place to
// continue...
//
// * Example below: the head pointers once again match, so
// simply update part 1 and record it in the `newParts`
// array. Last, advance both head pointers.
//
// oldHead v v oldTail
// oldKeys: [0, 1, -, 3, 4, 5, 6]
// newParts: [0, 2, 1, , , , 6] <- heads matched: update 1
// newKeys: [0, 2, 1, 4, 3, 7, 6] and advance both oldHead
// & newHead
// newHead ^ ^ newTail
//
// * As mentioned above, items that were moved as a result of
// being stuck (the final else clause in the code below) are
// marked with null, so we always advance old pointers over
// these so we're comparing the next actual old value on
// either end.
//
// * Example below: `oldHead` is null (already placed in
// newParts), so advance `oldHead`.
//
// oldHead v v oldTail
// oldKeys: [0, 1, -, 3, 4, 5, 6] <- old head already used:
// newParts: [0, 2, 1, , , , 6] advance oldHead
// newKeys: [0, 2, 1, 4, 3, 7, 6]
// newHead ^ ^ newTail
//
// * Note it's not critical to mark old parts as null when they
// are moved from head to tail or tail to head, since they
// will be outside the pointer range and never visited again.
//
// * Example below: Here the old tail key matches the new head
// key, so the part at the `oldTail` position and move its
// DOM to the new head position (before `oldParts[oldHead]`).
// Last, advance `oldTail` and `newHead` pointers.
//
// oldHead v v oldTail
// oldKeys: [0, 1, -, 3, 4, 5, 6]
// newParts: [0, 2, 1, 4, , , 6] <- old tail matches new
// newKeys: [0, 2, 1, 4, 3, 7, 6] head: update & move 4,
// advance oldTail & newHead
// newHead ^ ^ newTail
//
// * Example below: Old and new head keys match, so update the
// old head part in place, and advance the `oldHead` and
// `newHead` pointers.
//
// oldHead v oldTail
// oldKeys: [0, 1, -, 3, 4, 5, 6]
// newParts: [0, 2, 1, 4, 3, ,6] <- heads match: update 3
// newKeys: [0, 2, 1, 4, 3, 7, 6] and advance oldHead &
// newHead
// newHead ^ ^ newTail
//
// * Once the new or old pointers move past each other then all
// we have left is additions (if old list exhausted) or
// removals (if new list exhausted). Those are handled in the
// final while loops at the end.
//
// * Example below: `oldHead` exceeded `oldTail`, so we're done
// with the main loop. Create the remaining part and insert
// it at the new head position, and the update is complete.
//
// (oldHead > oldTail)
// oldKeys: [0, 1, -, 3, 4, 5, 6]
// newParts: [0, 2, 1, 4, 3, 7 ,6] <- create and insert 7
// newKeys: [0, 2, 1, 4, 3, 7, 6]
// newHead ^ newTail
//
// * Note that the order of the if/else clauses is not
// important to the algorithm, as long as the null checks
// come first (to ensure we're always working on valid old
// parts) and that the final else clause comes last (since
// that's where the expensive moves occur). The order of
// remaining clauses is is just a simple guess at which cases
// will be most common.
//
// * Note, we could calculate the longest
// increasing subsequence (LIS) of old items in new position,
// and only move those not in the LIS set. However that costs
// O(nlogn) time and adds a bit more code, and only helps
// make rare types of mutations require fewer moves. The
// above handles removes, adds, reversal, swaps, and single
// moves of contiguous items in linear time, in the minimum
// number of moves. As the number of multiple moves where LIS
// might help approaches a random shuffle, the LIS
// optimization becomes less helpful, so it seems not worth
// the code at this point. Could reconsider if a compelling
// case arises.
while (oldHead <= oldTail && newHead <= newTail) {
if (oldParts[oldHead] === null) {
// `null` means old part at head has already been used
// below; skip
oldHead++;
}
else if (oldParts[oldTail] === null) {
// `null` means old part at tail has already been used
// below; skip
oldTail--;
}
else if (oldKeys[oldHead] === newKeys[newHead]) {
// Old head matches new head; update in place
newParts[newHead] = setChildPartValue(oldParts[oldHead], newValues[newHead]);
oldHead++;
newHead++;
}
else if (oldKeys[oldTail] === newKeys[newTail]) {
// Old tail matches new tail; update in place
newParts[newTail] = setChildPartValue(oldParts[oldTail], newValues[newTail]);
oldTail--;
newTail--;
}
else if (oldKeys[oldHead] === newKeys[newTail]) {
// Old head matches new tail; update and move to new tail
newParts[newTail] = setChildPartValue(oldParts[oldHead], newValues[newTail]);
insertPart(containerPart, newParts[newTail + 1], oldParts[oldHead]);
oldHead++;
newTail--;
}
else if (oldKeys[oldTail] === newKeys[newHead]) {
// Old tail matches new head; update and move to new head
newParts[newHead] = setChildPartValue(oldParts[oldTail], newValues[newHead]);
insertPart(containerPart, oldParts[oldHead], oldParts[oldTail]);
oldTail--;
newHead++;
}
else {
if (newKeyToIndexMap === undefined) {
// Lazily generate key-to-index maps, used for removals &
// moves below
newKeyToIndexMap = generateMap(newKeys, newHead, newTail);
oldKeyToIndexMap = generateMap(oldKeys, oldHead, oldTail);
}
if (!newKeyToIndexMap.has(oldKeys[oldHead])) {
// Old head is no longer in new list; remove
removePart(oldParts[oldHead]);
oldHead++;
}
else if (!newKeyToIndexMap.has(oldKeys[oldTail])) {
// Old tail is no longer in new list; remove
removePart(oldParts[oldTail]);
oldTail--;
}
else {
// Any mismatches at this point are due to additions or
// moves; see if we have an old part we can reuse and move
// into place
const oldIndex = oldKeyToIndexMap.get(newKeys[newHead]);
const oldPart = oldIndex !== undefined ? oldParts[oldIndex] : null;
if (oldPart === null) {
// No old part for this value; create a new one and
// insert it
const newPart = insertPart(containerPart, oldParts[oldHead]);
setChildPartValue(newPart, newValues[newHead]);
newParts[newHead] = newPart;
}
else {
// Reuse old part
newParts[newHead] = setChildPartValue(oldPart, newValues[newHead]);
insertPart(containerPart, oldParts[oldHead], oldPart);
// This marks the old part as having been used, so that
// it will be skipped in the first two checks above
oldParts[oldIndex] = null;
}
newHead++;
}
}
}
// Add parts for any remaining new values
while (newHead <= newTail) {
// For all remaining additions, we insert before last new
// tail, since old pointers are no longer valid
const newPart = insertPart(containerPart, newParts[newTail + 1]);
setChildPartValue(newPart, newValues[newHead]);
newParts[newHead++] = newPart;
}
// Remove any remaining unused old parts
while (oldHead <= oldTail) {
const oldPart = oldParts[oldHead++];
if (oldPart !== null) {
removePart(oldPart);
}
}
// Save order of new parts for next round
this._itemKeys = newKeys;
// Directly set part value, bypassing it's dirty-checking
setCommittedValue(containerPart, newParts);
return noChange;
}
}
/**
* A directive that repeats a series of values (usually `TemplateResults`)
* generated from an iterable, and updates those items efficiently when the
* iterable changes based on user-provided `keys` associated with each item.
*
* Note that if a `keyFn` is provided, strict key-to-DOM mapping is maintained,
* meaning previous DOM for a given key is moved into the new position if
* needed, and DOM will never be reused with values for different keys (new DOM
* will always be created for new keys). This is generally the most efficient
* way to use `repeat` since it performs minimum unnecessary work for insertions
* and removals.
*
* The `keyFn` takes two parameters, the item and its index, and returns a unique key value.
*
* ```js
* html`
* <ol>
* ${repeat(this.items, (item) => item.id, (item, index) => {
* return html`<li>${index}: ${item.name}</li>`;
* })}
* </ol>
* `
* ```
*
* **Important**: If providing a `keyFn`, keys *must* be unique for all items in a
* given call to `repeat`. The behavior when two or more items have the same key
* is undefined.
*
* If no `keyFn` is provided, this directive will perform similar to mapping
* items to values, and DOM will be reused against potentially different items.
*/
const repeat = directive(RepeatDirective);
export { repeat };
//# sourceMappingURL=repeat.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,116 @@
import { noChange } from '../lit-html.js';
import { directive, Directive, PartType } from '../directive.js';
/**
* @license
* Copyright 2018 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
const important = 'important';
// The leading space is important
const importantFlag = ' !' + important;
// How many characters to remove from a value, as a negative number
const flagTrim = 0 - importantFlag.length;
class StyleMapDirective extends Directive {
constructor(partInfo) {
var _a;
super(partInfo);
if (partInfo.type !== PartType.ATTRIBUTE ||
partInfo.name !== 'style' ||
((_a = partInfo.strings) === null || _a === void 0 ? void 0 : _a.length) > 2) {
throw new Error('The `styleMap` directive must be used in the `style` attribute ' +
'and must be the only part in the attribute.');
}
}
render(styleInfo) {
return Object.keys(styleInfo).reduce((style, prop) => {
const value = styleInfo[prop];
if (value == null) {
return style;
}
// Convert property names from camel-case to dash-case, i.e.:
// `backgroundColor` -> `background-color`
// Vendor-prefixed names need an extra `-` appended to front:
// `webkitAppearance` -> `-webkit-appearance`
// Exception is any property name containing a dash, including
// custom properties; we assume these are already dash-cased i.e.:
// `--my-button-color` --> `--my-button-color`
prop = prop.includes('-')
? prop
: prop
.replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g, '-$&')
.toLowerCase();
return style + `${prop}:${value};`;
}, '');
}
update(part, [styleInfo]) {
const { style } = part.element;
if (this._previousStyleProperties === undefined) {
this._previousStyleProperties = new Set();
for (const name in styleInfo) {
this._previousStyleProperties.add(name);
}
return this.render(styleInfo);
}
// Remove old properties that no longer exist in styleInfo
// We use forEach() instead of for-of so that re don't require down-level
// iteration.
this._previousStyleProperties.forEach((name) => {
// If the name isn't in styleInfo or it's null/undefined
if (styleInfo[name] == null) {
this._previousStyleProperties.delete(name);
if (name.includes('-')) {
style.removeProperty(name);
}
else {
// Note reset using empty string (vs null) as IE11 does not always
// reset via null (https://developer.mozilla.org/en-US/docs/Web/API/ElementCSSInlineStyle/style#setting_styles)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
style[name] = '';
}
}
});
// Add or update properties
for (const name in styleInfo) {
const value = styleInfo[name];
if (value != null) {
this._previousStyleProperties.add(name);
const isImportant = typeof value === 'string' && value.endsWith(importantFlag);
if (name.includes('-') || isImportant) {
style.setProperty(name, isImportant
? value.slice(0, flagTrim)
: value, isImportant ? important : '');
}
else {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
style[name] = value;
}
}
}
return noChange;
}
}
/**
* A directive that applies CSS properties to an element.
*
* `styleMap` can only be used in the `style` attribute and must be the only
* expression in the attribute. It takes the property names in the
* {@link StyleInfo styleInfo} object and adds the properties to the inline
* style of the element.
*
* Property names with dashes (`-`) are assumed to be valid CSS
* property names and set on the element's style object using `setProperty()`.
* Names without dashes are assumed to be camelCased JavaScript property names
* and set on the element's style object using property assignment, allowing the
* style object to translate JavaScript-style names to CSS property names.
*
* For example `styleMap({backgroundColor: 'red', 'border-top': '5px', '--size':
* '0'})` sets the `background-color`, `border-top` and `--size` properties.
*
* @param styleInfo
* @see {@link https://lit.dev/docs/templates/directives/#stylemap styleMap code samples on Lit.dev}
*/
const styleMap = directive(StyleMapDirective);
export { styleMap };
//# sourceMappingURL=style-map.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,34 @@
import { noChange } from '../lit-html.js';
import { directive, Directive, PartType } from '../directive.js';
/**
* @license
* Copyright 2020 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
class TemplateContentDirective extends Directive {
constructor(partInfo) {
super(partInfo);
if (partInfo.type !== PartType.CHILD) {
throw new Error('templateContent can only be used in child bindings');
}
}
render(template) {
if (this._previousTemplate === template) {
return noChange;
}
this._previousTemplate = template;
return document.importNode(template.content, true);
}
}
/**
* Renders the content of a template element as HTML.
*
* Note, the template should be developer controlled and not user controlled.
* Rendering a user-controlled template with this directive
* could lead to cross-site-scripting vulnerabilities.
*/
const templateContent = directive(TemplateContentDirective);
export { templateContent };
//# sourceMappingURL=template-content.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"template-content.js","sources":["../../../src/directives/template-content.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2020 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport {noChange} from '../lit-html.js';\nimport {directive, Directive, PartInfo, PartType} from '../directive.js';\n\nclass TemplateContentDirective extends Directive {\n private _previousTemplate?: HTMLTemplateElement;\n\n constructor(partInfo: PartInfo) {\n super(partInfo);\n if (partInfo.type !== PartType.CHILD) {\n throw new Error('templateContent can only be used in child bindings');\n }\n }\n\n render(template: HTMLTemplateElement) {\n if (this._previousTemplate === template) {\n return noChange;\n }\n this._previousTemplate = template;\n return document.importNode(template.content, true);\n }\n}\n\n/**\n * Renders the content of a template element as HTML.\n *\n * Note, the template should be developer controlled and not user controlled.\n * Rendering a user-controlled template with this directive\n * could lead to cross-site-scripting vulnerabilities.\n */\nexport const templateContent = directive(TemplateContentDirective);\n\n/**\n * The type of the class that powers this directive. Necessary for naming the\n * directive's return type.\n */\nexport type {TemplateContentDirective};\n"],"names":[],"mappings":";;;AAAA;;;;AAIG;AAKH,MAAM,wBAAyB,SAAQ,SAAS,CAAA;AAG9C,IAAA,WAAA,CAAY,QAAkB,EAAA;QAC5B,KAAK,CAAC,QAAQ,CAAC,CAAC;AAChB,QAAA,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,KAAK,EAAE;AACpC,YAAA,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;AACvE,SAAA;KACF;AAED,IAAA,MAAM,CAAC,QAA6B,EAAA;AAClC,QAAA,IAAI,IAAI,CAAC,iBAAiB,KAAK,QAAQ,EAAE;AACvC,YAAA,OAAO,QAAQ,CAAC;AACjB,SAAA;AACD,QAAA,IAAI,CAAC,iBAAiB,GAAG,QAAQ,CAAC;QAClC,OAAO,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;KACpD;AACF,CAAA;AAED;;;;;;AAMG;MACU,eAAe,GAAG,SAAS,CAAC,wBAAwB;;;;"}

View File

@@ -0,0 +1,64 @@
import { nothing, noChange } from '../lit-html.js';
import { Directive, PartType, directive } from '../directive.js';
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
const HTML_RESULT = 1;
class UnsafeHTMLDirective extends Directive {
constructor(partInfo) {
super(partInfo);
this._value = nothing;
if (partInfo.type !== PartType.CHILD) {
throw new Error(`${this.constructor.directiveName}() can only be used in child bindings`);
}
}
render(value) {
if (value === nothing || value == null) {
this._templateResult = undefined;
return (this._value = value);
}
if (value === noChange) {
return value;
}
if (typeof value != 'string') {
throw new Error(`${this.constructor.directiveName}() called with a non-string value`);
}
if (value === this._value) {
return this._templateResult;
}
this._value = value;
const strings = [value];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
strings.raw = strings;
// WARNING: impersonating a TemplateResult like this is extremely
// dangerous. Third-party directives should not do this.
return (this._templateResult = {
// Cast to a known set of integers that satisfy ResultType so that we
// don't have to export ResultType and possibly encourage this pattern.
// This property needs to remain unminified.
['_$litType$']: this.constructor
.resultType,
strings,
values: [],
});
}
}
UnsafeHTMLDirective.directiveName = 'unsafeHTML';
UnsafeHTMLDirective.resultType = HTML_RESULT;
/**
* Renders the result as HTML, rather than text.
*
* The values `undefined`, `null`, and `nothing`, will all result in no content
* (empty string) being rendered.
*
* Note, this is unsafe to use with any user-provided input that hasn't been
* sanitized or escaped, as it may lead to cross-site-scripting
* vulnerabilities.
*/
const unsafeHTML = directive(UnsafeHTMLDirective);
export { UnsafeHTMLDirective, unsafeHTML };
//# sourceMappingURL=unsafe-html.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"unsafe-html.js","sources":["../../../src/directives/unsafe-html.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport {nothing, TemplateResult, noChange} from '../lit-html.js';\nimport {directive, Directive, PartInfo, PartType} from '../directive.js';\n\nconst HTML_RESULT = 1;\n\nexport class UnsafeHTMLDirective extends Directive {\n static directiveName = 'unsafeHTML';\n static resultType = HTML_RESULT;\n\n private _value: unknown = nothing;\n private _templateResult?: TemplateResult;\n\n constructor(partInfo: PartInfo) {\n super(partInfo);\n if (partInfo.type !== PartType.CHILD) {\n throw new Error(\n `${\n (this.constructor as typeof UnsafeHTMLDirective).directiveName\n }() can only be used in child bindings`\n );\n }\n }\n\n render(value: string | typeof nothing | typeof noChange | undefined | null) {\n if (value === nothing || value == null) {\n this._templateResult = undefined;\n return (this._value = value);\n }\n if (value === noChange) {\n return value;\n }\n if (typeof value != 'string') {\n throw new Error(\n `${\n (this.constructor as typeof UnsafeHTMLDirective).directiveName\n }() called with a non-string value`\n );\n }\n if (value === this._value) {\n return this._templateResult;\n }\n this._value = value;\n const strings = [value] as unknown as TemplateStringsArray;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (strings as any).raw = strings;\n // WARNING: impersonating a TemplateResult like this is extremely\n // dangerous. Third-party directives should not do this.\n return (this._templateResult = {\n // Cast to a known set of integers that satisfy ResultType so that we\n // don't have to export ResultType and possibly encourage this pattern.\n // This property needs to remain unminified.\n ['_$litType$']: (this.constructor as typeof UnsafeHTMLDirective)\n .resultType as 1 | 2,\n strings,\n values: [],\n });\n }\n}\n\n/**\n * Renders the result as HTML, rather than text.\n *\n * The values `undefined`, `null`, and `nothing`, will all result in no content\n * (empty string) being rendered.\n *\n * Note, this is unsafe to use with any user-provided input that hasn't been\n * sanitized or escaped, as it may lead to cross-site-scripting\n * vulnerabilities.\n */\nexport const unsafeHTML = directive(UnsafeHTMLDirective);\n"],"names":[],"mappings":";;;AAAA;;;;AAIG;AAKH,MAAM,WAAW,GAAG,CAAC,CAAC;AAEhB,MAAO,mBAAoB,SAAQ,SAAS,CAAA;AAOhD,IAAA,WAAA,CAAY,QAAkB,EAAA;QAC5B,KAAK,CAAC,QAAQ,CAAC,CAAC;QAJV,IAAM,CAAA,MAAA,GAAY,OAAO,CAAC;AAKhC,QAAA,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,KAAK,EAAE;YACpC,MAAM,IAAI,KAAK,CACb,CACG,EAAA,IAAI,CAAC,WAA0C,CAAC,aACnD,CAAuC,qCAAA,CAAA,CACxC,CAAC;AACH,SAAA;KACF;AAED,IAAA,MAAM,CAAC,KAAmE,EAAA;AACxE,QAAA,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,IAAI,IAAI,EAAE;AACtC,YAAA,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;AACjC,YAAA,QAAQ,IAAI,CAAC,MAAM,GAAG,KAAK,EAAE;AAC9B,SAAA;QACD,IAAI,KAAK,KAAK,QAAQ,EAAE;AACtB,YAAA,OAAO,KAAK,CAAC;AACd,SAAA;AACD,QAAA,IAAI,OAAO,KAAK,IAAI,QAAQ,EAAE;YAC5B,MAAM,IAAI,KAAK,CACb,CACG,EAAA,IAAI,CAAC,WAA0C,CAAC,aACnD,CAAmC,iCAAA,CAAA,CACpC,CAAC;AACH,SAAA;AACD,QAAA,IAAI,KAAK,KAAK,IAAI,CAAC,MAAM,EAAE;YACzB,OAAO,IAAI,CAAC,eAAe,CAAC;AAC7B,SAAA;AACD,QAAA,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;AACpB,QAAA,MAAM,OAAO,GAAG,CAAC,KAAK,CAAoC,CAAC;;AAE1D,QAAA,OAAe,CAAC,GAAG,GAAG,OAAO,CAAC;;;AAG/B,QAAA,QAAQ,IAAI,CAAC,eAAe,GAAG;;;;AAI7B,YAAA,CAAC,YAAY,GAAI,IAAI,CAAC,WAA0C;iBAC7D,UAAmB;YACtB,OAAO;AACP,YAAA,MAAM,EAAE,EAAE;AACX,SAAA,EAAE;KACJ;;AAlDM,mBAAa,CAAA,aAAA,GAAG,YAAY,CAAC;AAC7B,mBAAU,CAAA,UAAA,GAAG,WAAW,CAAC;AAoDlC;;;;;;;;;AASG;MACU,UAAU,GAAG,SAAS,CAAC,mBAAmB;;;;"}

View File

@@ -0,0 +1,27 @@
import { directive } from '../directive.js';
import { UnsafeHTMLDirective } from './unsafe-html.js';
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
const SVG_RESULT = 2;
class UnsafeSVGDirective extends UnsafeHTMLDirective {
}
UnsafeSVGDirective.directiveName = 'unsafeSVG';
UnsafeSVGDirective.resultType = SVG_RESULT;
/**
* Renders the result as SVG, rather than text.
*
* The values `undefined`, `null`, and `nothing`, will all result in no content
* (empty string) being rendered.
*
* Note, this is unsafe to use with any user-provided input that hasn't been
* sanitized or escaped, as it may lead to cross-site-scripting
* vulnerabilities.
*/
const unsafeSVG = directive(UnsafeSVGDirective);
export { unsafeSVG };
//# sourceMappingURL=unsafe-svg.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"unsafe-svg.js","sources":["../../../src/directives/unsafe-svg.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport {directive} from '../directive.js';\nimport {UnsafeHTMLDirective} from './unsafe-html.js';\n\nconst SVG_RESULT = 2;\n\nclass UnsafeSVGDirective extends UnsafeHTMLDirective {\n static override directiveName = 'unsafeSVG';\n static override resultType = SVG_RESULT;\n}\n\n/**\n * Renders the result as SVG, rather than text.\n *\n * The values `undefined`, `null`, and `nothing`, will all result in no content\n * (empty string) being rendered.\n *\n * Note, this is unsafe to use with any user-provided input that hasn't been\n * sanitized or escaped, as it may lead to cross-site-scripting\n * vulnerabilities.\n */\nexport const unsafeSVG = directive(UnsafeSVGDirective);\n\n/**\n * The type of the class that powers this directive. Necessary for naming the\n * directive's return type.\n */\nexport type {UnsafeSVGDirective};\n"],"names":[],"mappings":";;;AAAA;;;;AAIG;AAKH,MAAM,UAAU,GAAG,CAAC,CAAC;AAErB,MAAM,kBAAmB,SAAQ,mBAAmB,CAAA;;AAClC,kBAAa,CAAA,aAAA,GAAG,WAAW,CAAC;AAC5B,kBAAU,CAAA,UAAA,GAAG,UAAU,CAAC;AAG1C;;;;;;;;;AASG;MACU,SAAS,GAAG,SAAS,CAAC,kBAAkB;;;;"}

View File

@@ -0,0 +1,128 @@
import { noChange } from '../lit-html.js';
import { isPrimitive } from '../directive-helpers.js';
import { AsyncDirective } from '../async-directive.js';
import { PseudoWeakRef, Pauser } from './private-async-helpers.js';
import { directive } from '../directive.js';
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
const isPromise = (x) => {
return !isPrimitive(x) && typeof x.then === 'function';
};
// Effectively infinity, but a SMI.
const _infinity = 0x3fffffff;
class UntilDirective extends AsyncDirective {
constructor() {
super(...arguments);
this.__lastRenderedIndex = _infinity;
this.__values = [];
this.__weakThis = new PseudoWeakRef(this);
this.__pauser = new Pauser();
}
render(...args) {
var _a;
return (_a = args.find((x) => !isPromise(x))) !== null && _a !== void 0 ? _a : noChange;
}
update(_part, args) {
const previousValues = this.__values;
let previousLength = previousValues.length;
this.__values = args;
const weakThis = this.__weakThis;
const pauser = this.__pauser;
// If our initial render occurs while disconnected, ensure that the pauser
// and weakThis are in the disconnected state
if (!this.isConnected) {
this.disconnected();
}
for (let i = 0; i < args.length; i++) {
// If we've rendered a higher-priority value already, stop.
if (i > this.__lastRenderedIndex) {
break;
}
const value = args[i];
// Render non-Promise values immediately
if (!isPromise(value)) {
this.__lastRenderedIndex = i;
// Since a lower-priority value will never overwrite a higher-priority
// synchronous value, we can stop processing now.
return value;
}
// If this is a Promise we've already handled, skip it.
if (i < previousLength && value === previousValues[i]) {
continue;
}
// We have a Promise that we haven't seen before, so priorities may have
// changed. Forget what we rendered before.
this.__lastRenderedIndex = _infinity;
previousLength = 0;
// Note, the callback avoids closing over `this` so that the directive
// can be gc'ed before the promise resolves; instead `this` is retrieved
// from `weakThis`, which can break the hard reference in the closure when
// the directive disconnects
Promise.resolve(value).then(async (result) => {
// If we're disconnected, wait until we're (maybe) reconnected
// The while loop here handles the case that the connection state
// thrashes, causing the pauser to resume and then get re-paused
while (pauser.get()) {
await pauser.get();
}
// If the callback gets here and there is no `this`, it means that the
// directive has been disconnected and garbage collected and we don't
// need to do anything else
const _this = weakThis.deref();
if (_this !== undefined) {
const index = _this.__values.indexOf(value);
// If state.values doesn't contain the value, we've re-rendered without
// the value, so don't render it. Then, only render if the value is
// higher-priority than what's already been rendered.
if (index > -1 && index < _this.__lastRenderedIndex) {
_this.__lastRenderedIndex = index;
_this.setValue(result);
}
}
});
}
return noChange;
}
disconnected() {
this.__weakThis.disconnect();
this.__pauser.pause();
}
reconnected() {
this.__weakThis.reconnect(this);
this.__pauser.resume();
}
}
/**
* Renders one of a series of values, including Promises, to a Part.
*
* Values are rendered in priority order, with the first argument having the
* highest priority and the last argument having the lowest priority. If a
* value is a Promise, low-priority values will be rendered until it resolves.
*
* The priority of values can be used to create placeholder content for async
* data. For example, a Promise with pending content can be the first,
* highest-priority, argument, and a non_promise loading indicator template can
* be used as the second, lower-priority, argument. The loading indicator will
* render immediately, and the primary content will render when the Promise
* resolves.
*
* Example:
*
* ```js
* const content = fetch('./content.txt').then(r => r.text());
* html`${until(content, html`<span>Loading...</span>`)}`
* ```
*/
const until = directive(UntilDirective);
/**
* The type of the class that powers this directive. Necessary for naming the
* directive's return type.
*/
// export type {UntilDirective};
export { UntilDirective, until };
//# sourceMappingURL=until.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,11 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
function when(condition, trueCase, falseCase) {
return condition ? trueCase() : falseCase === null || falseCase === void 0 ? void 0 : falseCase();
}
export { when };
//# sourceMappingURL=when.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"when.js","sources":["../../../src/directives/when.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * When `condition` is true, returns the result of calling `trueCase()`, else\n * returns the result of calling `falseCase()` if `falseCase` is defined.\n *\n * This is a convenience wrapper around a ternary expression that makes it a\n * little nicer to write an inline conditional without an else.\n *\n * @example\n *\n * ```ts\n * render() {\n * return html`\n * ${when(this.user, () => html`User: ${this.user.username}`, () => html`Sign In...`)}\n * `;\n * }\n * ```\n */\nexport function when<T, F>(\n condition: true,\n trueCase: () => T,\n falseCase?: () => F\n): T;\nexport function when<T, F = undefined>(\n condition: false,\n trueCase: () => T,\n falseCase?: () => F\n): F;\nexport function when<T, F = undefined>(\n condition: unknown,\n trueCase: () => T,\n falseCase?: () => F\n): T | F;\nexport function when(\n condition: unknown,\n trueCase: () => unknown,\n falseCase?: () => unknown\n): unknown {\n return condition ? trueCase() : falseCase?.();\n}\n"],"names":[],"mappings":"AAAA;;;;AAIG;SAkCa,IAAI,CAClB,SAAkB,EAClB,QAAuB,EACvB,SAAyB,EAAA;AAEzB,IAAA,OAAO,SAAS,GAAG,QAAQ,EAAE,GAAG,SAAS,KAAT,IAAA,IAAA,SAAS,KAAT,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,SAAS,EAAI,CAAC;AAChD;;;;"}