UNPKG

6.83 kBJavaScriptView Raw
1/**
2 * @license
3 * Copyright 2020 Google LLC
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6import { _$LH, } from './lit-html.js';
7const { _ChildPart: ChildPart } = _$LH;
8const ENABLE_SHADYDOM_NOPATCH = true;
9const wrap = ENABLE_SHADYDOM_NOPATCH &&
10 window.ShadyDOM?.inUse &&
11 window.ShadyDOM?.noPatch === true
12 ? window.ShadyDOM.wrap
13 : (node) => node;
14/**
15 * Tests if a value is a primitive value.
16 *
17 * See https://tc39.github.io/ecma262/#sec-typeof-operator
18 */
19export const isPrimitive = (value) => value === null || (typeof value != 'object' && typeof value != 'function');
20export const TemplateResultType = {
21 HTML: 1,
22 SVG: 2,
23};
24/**
25 * Tests if a value is a TemplateResult or a CompiledTemplateResult.
26 */
27export const isTemplateResult = (value, type) => type === undefined
28 ? // This property needs to remain unminified.
29 value?.['_$litType$'] !== undefined
30 : value?.['_$litType$'] === type;
31/**
32 * Tests if a value is a CompiledTemplateResult.
33 */
34export const isCompiledTemplateResult = (value) => {
35 return value?.['_$litType$']?.h != null;
36};
37/**
38 * Tests if a value is a DirectiveResult.
39 */
40export const isDirectiveResult = (value) =>
41// This property needs to remain unminified.
42value?.['_$litDirective$'] !== undefined;
43/**
44 * Retrieves the Directive class for a DirectiveResult
45 */
46export const getDirectiveClass = (value) =>
47// This property needs to remain unminified.
48value?.['_$litDirective$'];
49/**
50 * Tests whether a part has only a single-expression with no strings to
51 * interpolate between.
52 *
53 * Only AttributePart and PropertyPart can have multiple expressions.
54 * Multi-expression parts have a `strings` property and single-expression
55 * parts do not.
56 */
57export const isSingleExpression = (part) => part.strings === undefined;
58const createMarker = () => document.createComment('');
59/**
60 * Inserts a ChildPart into the given container ChildPart's DOM, either at the
61 * end of the container ChildPart, or before the optional `refPart`.
62 *
63 * This does not add the part to the containerPart's committed value. That must
64 * be done by callers.
65 *
66 * @param containerPart Part within which to add the new ChildPart
67 * @param refPart Part before which to add the new ChildPart; when omitted the
68 * part added to the end of the `containerPart`
69 * @param part Part to insert, or undefined to create a new part
70 */
71export const insertPart = (containerPart, refPart, part) => {
72 const container = wrap(containerPart._$startNode).parentNode;
73 const refNode = refPart === undefined ? containerPart._$endNode : refPart._$startNode;
74 if (part === undefined) {
75 const startNode = wrap(container).insertBefore(createMarker(), refNode);
76 const endNode = wrap(container).insertBefore(createMarker(), refNode);
77 part = new ChildPart(startNode, endNode, containerPart, containerPart.options);
78 }
79 else {
80 const endNode = wrap(part._$endNode).nextSibling;
81 const oldParent = part._$parent;
82 const parentChanged = oldParent !== containerPart;
83 if (parentChanged) {
84 part._$reparentDisconnectables?.(containerPart);
85 // Note that although `_$reparentDisconnectables` updates the part's
86 // `_$parent` reference after unlinking from its current parent, that
87 // method only exists if Disconnectables are present, so we need to
88 // unconditionally set it here
89 part._$parent = containerPart;
90 // Since the _$isConnected getter is somewhat costly, only
91 // read it once we know the subtree has directives that need
92 // to be notified
93 let newConnectionState;
94 if (part._$notifyConnectionChanged !== undefined &&
95 (newConnectionState = containerPart._$isConnected) !==
96 oldParent._$isConnected) {
97 part._$notifyConnectionChanged(newConnectionState);
98 }
99 }
100 if (endNode !== refNode || parentChanged) {
101 let start = part._$startNode;
102 while (start !== endNode) {
103 const n = wrap(start).nextSibling;
104 wrap(container).insertBefore(start, refNode);
105 start = n;
106 }
107 }
108 }
109 return part;
110};
111/**
112 * Sets the value of a Part.
113 *
114 * Note that this should only be used to set/update the value of user-created
115 * parts (i.e. those created using `insertPart`); it should not be used
116 * by directives to set the value of the directive's container part. Directives
117 * should return a value from `update`/`render` to update their part state.
118 *
119 * For directives that require setting their part value asynchronously, they
120 * should extend `AsyncDirective` and call `this.setValue()`.
121 *
122 * @param part Part to set
123 * @param value Value to set
124 * @param index For `AttributePart`s, the index to set
125 * @param directiveParent Used internally; should not be set by user
126 */
127export const setChildPartValue = (part, value, directiveParent = part) => {
128 part._$setValue(value, directiveParent);
129 return part;
130};
131// A sentinel value that can never appear as a part value except when set by
132// live(). Used to force a dirty-check to fail and cause a re-render.
133const RESET_VALUE = {};
134/**
135 * Sets the committed value of a ChildPart directly without triggering the
136 * commit stage of the part.
137 *
138 * This is useful in cases where a directive needs to update the part such
139 * that the next update detects a value change or not. When value is omitted,
140 * the next update will be guaranteed to be detected as a change.
141 *
142 * @param part
143 * @param value
144 */
145export const setCommittedValue = (part, value = RESET_VALUE) => (part._$committedValue = value);
146/**
147 * Returns the committed value of a ChildPart.
148 *
149 * The committed value is used for change detection and efficient updates of
150 * the part. It can differ from the value set by the template or directive in
151 * cases where the template value is transformed before being committed.
152 *
153 * - `TemplateResult`s are committed as a `TemplateInstance`
154 * - Iterables are committed as `Array<ChildPart>`
155 * - All other types are committed as the template value or value returned or
156 * set by a directive.
157 *
158 * @param part
159 */
160export const getCommittedValue = (part) => part._$committedValue;
161/**
162 * Removes a ChildPart from the DOM, including any of its content.
163 *
164 * @param part The Part to remove
165 */
166export const removePart = (part) => {
167 part._$notifyConnectionChanged?.(false, true);
168 let start = part._$startNode;
169 const end = wrap(part._$endNode).nextSibling;
170 while (start !== end) {
171 const n = wrap(start).nextSibling;
172 wrap(start).remove();
173 start = n;
174 }
175};
176export const clearPart = (part) => {
177 part._$clear();
178};
179//# sourceMappingURL=directive-helpers.js.map
\No newline at end of file