@lushly-dev/fast-element 3.0.1-preview.0 → 3.0.1-preview.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/command/command.api.json +7857 -0
- package/dist/context/context.api.json +1084 -0
- package/dist/declarative/declarative.api.json +8130 -0
- package/dist/definition-schema/definition-schema.api.json +2689 -0
- package/dist/di/di.api.json +4945 -0
- package/dist/dts/arrays.d.ts +2 -0
- package/dist/dts/binding/binding.d.ts +59 -0
- package/dist/dts/binding/exports.d.ts +9 -0
- package/dist/dts/binding/normalize.d.ts +9 -0
- package/dist/dts/binding/one-time.d.ts +11 -0
- package/dist/dts/binding/one-way.d.ts +20 -0
- package/dist/dts/binding/signal.d.ts +36 -0
- package/dist/dts/binding/two-way.d.ts +44 -0
- package/dist/dts/command/behavior.d.ts +94 -0
- package/dist/dts/command/behaviors/confirm-behavior.d.ts +139 -0
- package/dist/dts/command/behaviors/undo-behavior.d.ts +178 -0
- package/dist/dts/command/command.d.ts +79 -0
- package/dist/dts/command/component-registry.d.ts +50 -0
- package/dist/dts/command/components/confirm-dialog.d.ts +117 -0
- package/dist/dts/command/index.d.ts +21 -0
- package/dist/dts/command/registry.d.ts +201 -0
- package/dist/dts/command/schema-validation.d.ts +45 -0
- package/dist/dts/command/types.d.ts +332 -0
- package/dist/dts/command/validation.d.ts +116 -0
- package/dist/dts/command/weak-ref.d.ts +11 -0
- package/dist/dts/components/attributes.d.ts +153 -0
- package/dist/dts/components/definition-schema-transforms.d.ts +9 -0
- package/dist/dts/components/element-controller.d.ts +349 -0
- package/dist/dts/components/element-hydration.d.ts +2 -0
- package/dist/dts/components/enable-hydration.d.ts +66 -0
- package/dist/dts/components/fast-definitions.d.ts +211 -0
- package/dist/dts/components/fast-element-registry.d.ts +23 -0
- package/dist/dts/components/fast-element.d.ts +91 -0
- package/dist/dts/components/hydration-tracker.d.ts +110 -0
- package/dist/dts/components/hydration.d.ts +52 -0
- package/dist/dts/components/schema.d.ts +205 -0
- package/dist/dts/context.d.ts +171 -0
- package/dist/dts/debug.d.ts +5 -0
- package/dist/dts/declarative/attribute-map.d.ts +58 -0
- package/dist/dts/declarative/debug.d.ts +4 -0
- package/dist/dts/declarative/index.d.ts +14 -0
- package/dist/dts/declarative/interfaces.d.ts +8 -0
- package/dist/dts/declarative/observer-map-utilities.d.ts +58 -0
- package/dist/dts/declarative/observer-map.d.ts +89 -0
- package/dist/dts/declarative/runtime.d.ts +5 -0
- package/dist/dts/declarative/syntax.d.ts +21 -0
- package/dist/dts/declarative/template-bridge.d.ts +33 -0
- package/dist/dts/declarative/template-parser.d.ts +98 -0
- package/dist/dts/declarative/template.d.ts +9 -0
- package/dist/dts/declarative/utilities.d.ts +358 -0
- package/dist/dts/definition-schema/api.d.ts +42 -0
- package/dist/dts/definition-schema/cem.d.ts +78 -0
- package/dist/dts/definition-schema/extension.d.ts +18 -0
- package/dist/dts/definition-schema/extract.d.ts +38 -0
- package/dist/dts/definition-schema/index.d.ts +9 -0
- package/dist/dts/definition-schema/storage.d.ts +35 -0
- package/dist/dts/definition-schema/types.d.ts +176 -0
- package/dist/dts/dev-mode.d.ts +13 -0
- package/dist/dts/di/di.d.ts +894 -0
- package/dist/dts/dom-policy.d.ts +101 -0
- package/dist/dts/dom.d.ts +88 -0
- package/dist/dts/hydration/diagnostics.d.ts +93 -0
- package/dist/dts/hydration/exports.d.ts +18 -0
- package/dist/dts/hydration/hydration-debugger.d.ts +35 -0
- package/dist/dts/hydration/messages.d.ts +62 -0
- package/dist/dts/hydration/runtime.d.ts +7 -0
- package/dist/dts/hydration/target-builder.d.ts +107 -0
- package/dist/dts/index.d.ts +51 -0
- package/dist/dts/index.debug.d.ts +1 -0
- package/dist/dts/index.rollup.d.ts +1 -0
- package/dist/dts/index.rollup.debug.d.ts +1 -0
- package/dist/dts/interfaces.d.ts +106 -0
- package/dist/dts/metadata.d.ts +26 -0
- package/dist/dts/observation/arrays.d.ts +248 -0
- package/dist/dts/observation/notifier.d.ts +127 -0
- package/dist/dts/observation/observable.d.ts +276 -0
- package/dist/dts/observation/update-queue.d.ts +40 -0
- package/dist/dts/observation/volatile.d.ts +9 -0
- package/dist/dts/platform.d.ts +87 -0
- package/dist/dts/registry.d.ts +2 -0
- package/dist/dts/render.d.ts +7 -0
- package/dist/dts/schema.d.ts +1 -0
- package/dist/dts/scoped/detection.d.ts +55 -0
- package/dist/dts/scoped/index.d.ts +68 -0
- package/dist/dts/scoped/mixin.d.ts +118 -0
- package/dist/dts/scoped/registry.d.ts +76 -0
- package/dist/dts/scoped/types.d.ts +48 -0
- package/dist/dts/state/exports.d.ts +3 -0
- package/dist/dts/state/reactive.d.ts +8 -0
- package/dist/dts/state/state.d.ts +141 -0
- package/dist/dts/state/visitor.d.ts +6 -0
- package/dist/dts/state/watch.d.ts +10 -0
- package/dist/dts/styles/css-directive.d.ts +50 -0
- package/dist/dts/styles/css.d.ts +34 -0
- package/dist/dts/styles/element-styles.d.ts +61 -0
- package/dist/dts/styles/host.d.ts +65 -0
- package/dist/dts/styles/style-strategy.d.ts +42 -0
- package/dist/dts/templating/children.d.ts +62 -0
- package/dist/dts/templating/compiler.d.ts +54 -0
- package/dist/dts/templating/html-binding-directive.d.ts +155 -0
- package/dist/dts/templating/html-directive.d.ts +218 -0
- package/dist/dts/templating/html.d.ts +1 -0
- package/dist/dts/templating/hydration-view.d.ts +130 -0
- package/dist/dts/templating/markup.d.ts +48 -0
- package/dist/dts/templating/node-observation.d.ts +99 -0
- package/dist/dts/templating/ref.d.ts +23 -0
- package/dist/dts/templating/render.d.ts +318 -0
- package/dist/dts/templating/repeat.d.ts +131 -0
- package/dist/dts/templating/slotted.d.ts +38 -0
- package/dist/dts/templating/template.d.ts +221 -0
- package/dist/dts/templating/view.d.ts +268 -0
- package/dist/dts/templating/when.d.ts +12 -0
- package/dist/dts/testing/exports.d.ts +3 -0
- package/dist/dts/testing/fakes.d.ts +16 -0
- package/dist/dts/testing/fixture.d.ts +84 -0
- package/dist/dts/testing/models.d.ts +20 -0
- package/dist/dts/testing/timeout.d.ts +7 -0
- package/dist/dts/trust/index.d.ts +8 -0
- package/dist/dts/trust/types.d.ts +48 -0
- package/dist/dts/trust/utils.d.ts +26 -0
- package/dist/dts/tsdoc-metadata.json +11 -0
- package/dist/dts/utilities.d.ts +76 -0
- package/dist/esm/arrays.js +1 -0
- package/dist/esm/binding/binding.js +18 -0
- package/dist/esm/binding/exports.js +6 -0
- package/dist/esm/binding/normalize.js +17 -0
- package/dist/esm/binding/one-time.js +21 -0
- package/dist/esm/binding/one-way.js +30 -0
- package/dist/esm/binding/signal.js +99 -0
- package/dist/esm/binding/two-way.js +109 -0
- package/dist/esm/command/behavior.js +155 -0
- package/dist/esm/command/behaviors/confirm-behavior.js +225 -0
- package/dist/esm/command/behaviors/undo-behavior.js +313 -0
- package/dist/esm/command/command.js +104 -0
- package/dist/esm/command/component-registry.js +107 -0
- package/dist/esm/command/components/confirm-dialog.js +370 -0
- package/dist/esm/command/index.js +22 -0
- package/dist/esm/command/registry.js +755 -0
- package/dist/esm/command/schema-validation.js +194 -0
- package/dist/esm/command/types.js +86 -0
- package/dist/esm/command/validation.js +508 -0
- package/dist/esm/command/weak-ref.js +5 -0
- package/dist/esm/components/attributes.js +219 -0
- package/dist/esm/components/definition-schema-transforms.js +23 -0
- package/dist/esm/components/element-controller.js +840 -0
- package/dist/esm/components/element-hydration.js +2 -0
- package/dist/esm/components/enable-hydration.js +123 -0
- package/dist/esm/components/fast-definitions.js +294 -0
- package/dist/esm/components/fast-element-registry.js +67 -0
- package/dist/esm/components/fast-element.js +82 -0
- package/dist/esm/components/hydration-tracker.js +211 -0
- package/dist/esm/components/hydration.js +187 -0
- package/dist/esm/components/schema.js +253 -0
- package/dist/esm/context.js +185 -0
- package/dist/esm/debug.js +71 -0
- package/dist/esm/declarative/attribute-map.js +122 -0
- package/dist/esm/declarative/debug.js +4 -0
- package/dist/esm/declarative/index.js +10 -0
- package/dist/esm/declarative/interfaces.js +9 -0
- package/dist/esm/declarative/observer-map-utilities.js +565 -0
- package/dist/esm/declarative/observer-map.js +216 -0
- package/dist/esm/declarative/runtime.js +14 -0
- package/dist/esm/declarative/syntax.js +36 -0
- package/dist/esm/declarative/template-bridge.js +160 -0
- package/dist/esm/declarative/template-parser.js +306 -0
- package/dist/esm/declarative/template.js +116 -0
- package/dist/esm/declarative/utilities.js +1069 -0
- package/dist/esm/definition-schema/api.js +129 -0
- package/dist/esm/definition-schema/cem.js +89 -0
- package/dist/esm/definition-schema/extension.js +53 -0
- package/dist/esm/definition-schema/extract.js +167 -0
- package/dist/esm/definition-schema/index.js +8 -0
- package/dist/esm/definition-schema/storage.js +58 -0
- package/dist/esm/definition-schema/types.js +8 -0
- package/dist/esm/dev-mode.js +22 -0
- package/dist/esm/di/di.js +1441 -0
- package/dist/esm/dom-policy.js +374 -0
- package/dist/esm/dom.js +101 -0
- package/dist/esm/hydration/diagnostics.js +50 -0
- package/dist/esm/hydration/exports.js +6 -0
- package/dist/esm/hydration/hydration-debugger.js +112 -0
- package/dist/esm/hydration/messages.js +84 -0
- package/dist/esm/hydration/runtime.js +33 -0
- package/dist/esm/hydration/target-builder.js +264 -0
- package/dist/esm/index.debug.js +3 -0
- package/dist/esm/index.js +49 -0
- package/dist/esm/index.rollup.debug.js +6 -0
- package/dist/esm/index.rollup.js +4 -0
- package/dist/esm/interfaces.js +55 -0
- package/dist/esm/metadata.js +57 -0
- package/dist/esm/observation/arrays.js +661 -0
- package/dist/esm/observation/notifier.js +162 -0
- package/dist/esm/observation/observable.js +324 -0
- package/dist/esm/observation/update-queue.js +56 -0
- package/dist/esm/observation/volatile.js +16 -0
- package/dist/esm/platform.js +98 -0
- package/dist/esm/registry.js +2 -0
- package/dist/esm/render.js +1 -0
- package/dist/esm/schema.js +1 -0
- package/dist/esm/scoped/detection.js +102 -0
- package/dist/esm/scoped/index.js +69 -0
- package/dist/esm/scoped/mixin.js +127 -0
- package/dist/esm/scoped/registry.js +125 -0
- package/dist/esm/scoped/types.js +4 -0
- package/dist/esm/state/exports.js +3 -0
- package/dist/esm/state/reactive.js +34 -0
- package/dist/esm/state/state.js +148 -0
- package/dist/esm/state/visitor.js +28 -0
- package/dist/esm/state/watch.js +36 -0
- package/dist/esm/styles/css-directive.js +36 -0
- package/dist/esm/styles/css.js +56 -0
- package/dist/esm/styles/element-styles.js +144 -0
- package/dist/esm/styles/host.js +1 -0
- package/dist/esm/styles/style-strategy.js +1 -0
- package/dist/esm/templating/children.js +67 -0
- package/dist/esm/templating/compiler.js +359 -0
- package/dist/esm/templating/html-binding-directive.js +288 -0
- package/dist/esm/templating/html-directive.js +113 -0
- package/dist/esm/templating/html.js +1 -0
- package/dist/esm/templating/hydration-view.js +228 -0
- package/dist/esm/templating/markup.js +83 -0
- package/dist/esm/templating/node-observation.js +84 -0
- package/dist/esm/templating/ref.js +21 -0
- package/dist/esm/templating/render.js +468 -0
- package/dist/esm/templating/repeat.js +434 -0
- package/dist/esm/templating/slotted.js +49 -0
- package/dist/esm/templating/template.js +206 -0
- package/dist/esm/templating/view.js +298 -0
- package/dist/esm/templating/when.js +22 -0
- package/dist/esm/testing/exports.js +3 -0
- package/dist/esm/testing/fakes.js +107 -0
- package/dist/esm/testing/fixture.js +86 -0
- package/dist/esm/testing/models.js +58 -0
- package/dist/esm/testing/timeout.js +24 -0
- package/dist/esm/trust/index.js +7 -0
- package/dist/esm/trust/types.js +6 -0
- package/dist/esm/trust/utils.js +126 -0
- package/dist/esm/utilities.js +140 -0
- package/dist/fast-element.api.json +26798 -0
- package/dist/fast-element.d.ts +3985 -0
- package/dist/fast-element.debug.js +7604 -0
- package/dist/fast-element.debug.min.js +3 -0
- package/dist/fast-element.js +7603 -0
- package/dist/fast-element.min.js +3 -0
- package/dist/fast-element.untrimmed.d.ts +4103 -0
- package/dist/observation/arrays/arrays.api.json +2621 -0
- package/dist/scoped/scoped.api.json +891 -0
- package/dist/trust/trust.api.json +629 -0
- package/package.json +21 -23
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { installHydrationDiagnostic } from "../hydration/diagnostics.js";
|
|
2
|
+
import { ensureHydrationRuntime } from "../hydration/runtime.js";
|
|
3
|
+
import { SourceLifetime } from "../observation/observable.js";
|
|
4
|
+
import { ElementController } from "./element-controller.js";
|
|
5
|
+
import { isHydratable } from "./hydration.js";
|
|
6
|
+
import { HydrationTracker, } from "./hydration-tracker.js";
|
|
7
|
+
export { StopHydration } from "./hydration-tracker.js";
|
|
8
|
+
/**
|
|
9
|
+
* No-op handler used during prerendered bind to discard the
|
|
10
|
+
* upgrade-time burst of attributeChangedCallbacks.
|
|
11
|
+
*/
|
|
12
|
+
function noopAttributeHandler() { }
|
|
13
|
+
let tracker = null;
|
|
14
|
+
let hookInstalled = false;
|
|
15
|
+
/**
|
|
16
|
+
* Enables hydration support for prerendered FAST elements.
|
|
17
|
+
*
|
|
18
|
+
* @remarks
|
|
19
|
+
* Call this before any FAST elements connect to the DOM. Hydration
|
|
20
|
+
* logic is not active unless this function is called, keeping
|
|
21
|
+
* `FASTElement` lightweight for client-side-only applications.
|
|
22
|
+
*
|
|
23
|
+
* Safe to call multiple times — the hydration hook is installed once
|
|
24
|
+
* and subsequent calls merge their options into the shared tracker.
|
|
25
|
+
* By default, the hook stops hydrating new prerendered elements after
|
|
26
|
+
* the initial hydration batch completes. Await the returned controller's
|
|
27
|
+
* `whenHydrated()` promise to run code after the active hydration batch
|
|
28
|
+
* completes.
|
|
29
|
+
*
|
|
30
|
+
* Set `stopHydration` to `StopHydration.never` for streaming scenarios
|
|
31
|
+
* that append hydratable Declarative Shadow DOM after the initial batch.
|
|
32
|
+
* In this mode, `whenHydrated` intentionally remains pending because
|
|
33
|
+
* hydration never reaches a global completion point.
|
|
34
|
+
*
|
|
35
|
+
* Pass `debugger: hydrationDebugger()` to swap the default minimal
|
|
36
|
+
* hydration mismatch error message for a rich "Expected / Received"
|
|
37
|
+
* report including the SSR HTML snippet and structured
|
|
38
|
+
* `expected`/`received` fields on `HydrationBindingError` /
|
|
39
|
+
* `HydrationTargetElementError`. The debugger module is tree-shaken
|
|
40
|
+
* out of production hydration bundles unless explicitly imported.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* import { enableHydration } from "@lushly-dev/fast-element/hydration.js";
|
|
45
|
+
*
|
|
46
|
+
* const hydration = enableHydration();
|
|
47
|
+
*
|
|
48
|
+
* await hydration.whenHydrated();
|
|
49
|
+
* console.log("hydration complete");
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @example Streaming Declarative Shadow DOM
|
|
53
|
+
* ```ts
|
|
54
|
+
* import { enableHydration, StopHydration } from "@lushly-dev/fast-element/hydration.js";
|
|
55
|
+
*
|
|
56
|
+
* enableHydration({
|
|
57
|
+
* stopHydration: StopHydration.never,
|
|
58
|
+
* });
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @example Rich hydration mismatch diagnostics
|
|
62
|
+
* ```ts
|
|
63
|
+
* import { enableHydration, hydrationDebugger } from "@lushly-dev/fast-element/hydration.js";
|
|
64
|
+
*
|
|
65
|
+
* enableHydration({ debugger: hydrationDebugger() });
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* @param options - Optional hydration behavior.
|
|
69
|
+
* @public
|
|
70
|
+
*/
|
|
71
|
+
export function enableHydration(options) {
|
|
72
|
+
ensureHydrationRuntime();
|
|
73
|
+
if (options === null || options === void 0 ? void 0 : options.debugger) {
|
|
74
|
+
installHydrationDiagnostic(options.debugger.diagnostic);
|
|
75
|
+
}
|
|
76
|
+
if (!hookInstalled) {
|
|
77
|
+
tracker = new HydrationTracker(options !== null && options !== void 0 ? options : {});
|
|
78
|
+
hookInstalled = true;
|
|
79
|
+
const activeTracker = tracker;
|
|
80
|
+
ElementController.installHydrationHook((controller, template, element, host) => {
|
|
81
|
+
if (!activeTracker.shouldHydrate || !isHydratable(template)) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
activeTracker.add(element);
|
|
85
|
+
try {
|
|
86
|
+
const firstChild = host.firstChild;
|
|
87
|
+
const lastChild = host.lastChild;
|
|
88
|
+
const view = template.hydrate(firstChild, lastChild, element);
|
|
89
|
+
controller.view = view;
|
|
90
|
+
const realHandler = controller.onAttributeChangedCallback;
|
|
91
|
+
controller.onAttributeChangedCallback = noopAttributeHandler;
|
|
92
|
+
try {
|
|
93
|
+
view._skipAttrUpdates = true;
|
|
94
|
+
view.isPrerendered = Promise.resolve(true);
|
|
95
|
+
view.isHydrated = Promise.resolve(true);
|
|
96
|
+
view.bind(controller.source);
|
|
97
|
+
view._skipAttrUpdates = false;
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
controller.onAttributeChangedCallback = realHandler;
|
|
101
|
+
}
|
|
102
|
+
view.sourceLifetime =
|
|
103
|
+
SourceLifetime.coupled;
|
|
104
|
+
controller.hasExistingShadowRoot = false;
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
activeTracker.remove(element);
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
else if (options && tracker) {
|
|
113
|
+
// Merge options into existing tracker for subsequent calls
|
|
114
|
+
tracker.mergeOptions(options);
|
|
115
|
+
}
|
|
116
|
+
return tracker;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The attribute used to defer hydration of an element.
|
|
120
|
+
* Retained for intersection observer viewport hydration rendering.
|
|
121
|
+
* @beta
|
|
122
|
+
*/
|
|
123
|
+
export const deferHydrationAttribute = "defer-hydration";
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { isFunction, isString } from "../interfaces.js";
|
|
2
|
+
import { Observable } from "../observation/observable.js";
|
|
3
|
+
import { ElementStyles } from "../styles/element-styles.js";
|
|
4
|
+
import { AttributeDefinition } from "./attributes.js";
|
|
5
|
+
import { fastElementRegistry } from "./fast-element-registry.js";
|
|
6
|
+
const defaultShadowOptions = { mode: "open" };
|
|
7
|
+
const defaultElementOptions = {};
|
|
8
|
+
const fastElementBaseTypes = new Set();
|
|
9
|
+
function normalizeShadowOptions(options) {
|
|
10
|
+
if (options === null) {
|
|
11
|
+
return void 0;
|
|
12
|
+
}
|
|
13
|
+
const normalized = Object.assign(Object.assign({}, defaultShadowOptions), options);
|
|
14
|
+
if (normalized.customElementRegistry === void 0 && normalized.registry !== void 0) {
|
|
15
|
+
normalized.customElementRegistry = normalized.registry;
|
|
16
|
+
}
|
|
17
|
+
if (normalized.registry === void 0 && normalized.customElementRegistry !== void 0) {
|
|
18
|
+
normalized.registry = normalized.customElementRegistry;
|
|
19
|
+
}
|
|
20
|
+
return normalized;
|
|
21
|
+
}
|
|
22
|
+
const templateResolvers = new WeakMap();
|
|
23
|
+
const pendingTemplateResolutions = new WeakMap();
|
|
24
|
+
const templateResolutionErrors = new WeakMap();
|
|
25
|
+
const extensionRegistries = new WeakMap();
|
|
26
|
+
const registeredExtensions = new Set();
|
|
27
|
+
const lateAttributeLookups = new WeakMap();
|
|
28
|
+
function isFASTElementTemplateResolver(value) {
|
|
29
|
+
return isFunction(value);
|
|
30
|
+
}
|
|
31
|
+
function isPromiseLike(value) {
|
|
32
|
+
return typeof (value === null || value === void 0 ? void 0 : value.then) === "function";
|
|
33
|
+
}
|
|
34
|
+
function finalizeResolvedTemplate(definition, template) {
|
|
35
|
+
pendingTemplateResolutions.delete(definition);
|
|
36
|
+
if (definition.template === void 0 && template !== void 0) {
|
|
37
|
+
definition.template = template;
|
|
38
|
+
}
|
|
39
|
+
if (definition.template !== void 0) {
|
|
40
|
+
templateResolutionErrors.delete(definition);
|
|
41
|
+
templateResolvers.delete(definition);
|
|
42
|
+
return definition.template;
|
|
43
|
+
}
|
|
44
|
+
return void 0;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Applies extension callbacks to a FAST element definition.
|
|
48
|
+
* @internal
|
|
49
|
+
*/
|
|
50
|
+
export function applyFASTElementExtensions(definition, registry = definition.registry, extensions) {
|
|
51
|
+
if (registeredExtensions.size === 0 && !(extensions === null || extensions === void 0 ? void 0 : extensions.length)) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const typedDefinition = definition;
|
|
55
|
+
let registries = extensionRegistries.get(typedDefinition);
|
|
56
|
+
if (registries === null || registries === void 0 ? void 0 : registries.has(registry)) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (registries === void 0) {
|
|
60
|
+
registries = new WeakSet();
|
|
61
|
+
extensionRegistries.set(typedDefinition, registries);
|
|
62
|
+
}
|
|
63
|
+
registries.add(registry);
|
|
64
|
+
for (const extension of registeredExtensions) {
|
|
65
|
+
extension(definition, registry);
|
|
66
|
+
}
|
|
67
|
+
for (const extension of extensions !== null && extensions !== void 0 ? extensions : []) {
|
|
68
|
+
if (!registeredExtensions.has(extension)) {
|
|
69
|
+
extension(definition, registry);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Registers an extension that applies to every subsequently defined FAST element.
|
|
75
|
+
* @param extension - The extension to register.
|
|
76
|
+
* @returns A callback that removes the extension registration.
|
|
77
|
+
* @internal
|
|
78
|
+
*/
|
|
79
|
+
export function registerFASTElementExtension(extension) {
|
|
80
|
+
registeredExtensions.add(extension);
|
|
81
|
+
return () => {
|
|
82
|
+
registeredExtensions.delete(extension);
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Tracks attribute definitions that were added after the element was already
|
|
87
|
+
* registered with the platform and therefore are not covered by the browser's
|
|
88
|
+
* static observedAttributes snapshot.
|
|
89
|
+
* @internal
|
|
90
|
+
*/
|
|
91
|
+
export function trackLateAttributeDefinition(definition, attribute) {
|
|
92
|
+
const typedDefinition = definition;
|
|
93
|
+
let lateAttributeLookup = lateAttributeLookups.get(typedDefinition);
|
|
94
|
+
if (lateAttributeLookup === void 0) {
|
|
95
|
+
const lookup = Object.create(null);
|
|
96
|
+
lateAttributeLookups.set(typedDefinition, lookup);
|
|
97
|
+
lateAttributeLookup = lookup;
|
|
98
|
+
}
|
|
99
|
+
lateAttributeLookup[attribute.attribute] = attribute;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Gets the attribute definitions that were added after platform registration.
|
|
103
|
+
* @internal
|
|
104
|
+
*/
|
|
105
|
+
export function getLateAttributeLookup(definition) {
|
|
106
|
+
var _a;
|
|
107
|
+
return ((_a = lateAttributeLookups.get(definition)) !== null && _a !== void 0 ? _a : null);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Resolves the concrete template for a FAST element definition when the
|
|
111
|
+
* definition was composed with a template resolver.
|
|
112
|
+
* @internal
|
|
113
|
+
*/
|
|
114
|
+
export function resolveFASTElementTemplate(definition) {
|
|
115
|
+
if (definition.template !== void 0) {
|
|
116
|
+
templateResolutionErrors.delete(definition);
|
|
117
|
+
return definition.template;
|
|
118
|
+
}
|
|
119
|
+
const pendingResolution = pendingTemplateResolutions.get(definition);
|
|
120
|
+
if (pendingResolution) {
|
|
121
|
+
return pendingResolution;
|
|
122
|
+
}
|
|
123
|
+
const templateResolver = templateResolvers.get(definition);
|
|
124
|
+
if (!templateResolver) {
|
|
125
|
+
return void 0;
|
|
126
|
+
}
|
|
127
|
+
templateResolutionErrors.delete(definition);
|
|
128
|
+
let template;
|
|
129
|
+
try {
|
|
130
|
+
template = templateResolver(definition);
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
templateResolutionErrors.set(definition, error);
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
if (isPromiseLike(template)) {
|
|
137
|
+
const resolution = Promise.resolve(template)
|
|
138
|
+
.then(resolvedTemplate => finalizeResolvedTemplate(definition, resolvedTemplate))
|
|
139
|
+
.catch(error => {
|
|
140
|
+
pendingTemplateResolutions.delete(definition);
|
|
141
|
+
templateResolutionErrors.set(definition, error);
|
|
142
|
+
throw error;
|
|
143
|
+
});
|
|
144
|
+
pendingTemplateResolutions.set(definition, resolution);
|
|
145
|
+
return resolution;
|
|
146
|
+
}
|
|
147
|
+
return finalizeResolvedTemplate(definition, template);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Indicates whether a definition still has a pending template resolver.
|
|
151
|
+
* @internal
|
|
152
|
+
*/
|
|
153
|
+
export function hasFASTElementTemplateResolver(definition) {
|
|
154
|
+
return templateResolvers.has(definition);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Gets any pending template resolution error for a FAST element definition.
|
|
158
|
+
* @internal
|
|
159
|
+
*/
|
|
160
|
+
export function getFASTElementTemplateError(definition) {
|
|
161
|
+
return templateResolutionErrors.get(definition);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Sets or clears the template resolution error for a FAST element definition.
|
|
165
|
+
* @internal
|
|
166
|
+
*/
|
|
167
|
+
export function setFASTElementTemplateError(definition, error) {
|
|
168
|
+
const typedDefinition = definition;
|
|
169
|
+
if (error === void 0) {
|
|
170
|
+
templateResolutionErrors.delete(typedDefinition);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
templateResolutionErrors.set(typedDefinition, error);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Defines metadata for a FASTElement.
|
|
177
|
+
* @public
|
|
178
|
+
*/
|
|
179
|
+
export class FASTElementDefinition {
|
|
180
|
+
/**
|
|
181
|
+
* Indicates if this element has been defined in at least one registry.
|
|
182
|
+
*/
|
|
183
|
+
get isDefined() {
|
|
184
|
+
return this.platformDefined;
|
|
185
|
+
}
|
|
186
|
+
constructor(type, nameOrConfig = type
|
|
187
|
+
.definition) {
|
|
188
|
+
var _a;
|
|
189
|
+
this.platformDefined = false;
|
|
190
|
+
if (isString(nameOrConfig)) {
|
|
191
|
+
nameOrConfig = { name: nameOrConfig };
|
|
192
|
+
}
|
|
193
|
+
this.type = type;
|
|
194
|
+
this.name = nameOrConfig.name;
|
|
195
|
+
this.registry = (_a = nameOrConfig.registry) !== null && _a !== void 0 ? _a : customElements;
|
|
196
|
+
if (isFASTElementTemplateResolver(nameOrConfig.template)) {
|
|
197
|
+
templateResolvers.set(this, nameOrConfig.template);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
this.template = nameOrConfig.template;
|
|
201
|
+
}
|
|
202
|
+
const proto = type.prototype;
|
|
203
|
+
const attributes = AttributeDefinition.collect(type, nameOrConfig.attributes);
|
|
204
|
+
const observedAttributes = new Array(attributes.length);
|
|
205
|
+
const propertyLookup = {};
|
|
206
|
+
const attributeLookup = {};
|
|
207
|
+
for (let i = 0, ii = attributes.length; i < ii; ++i) {
|
|
208
|
+
const current = attributes[i];
|
|
209
|
+
observedAttributes[i] = current.attribute;
|
|
210
|
+
propertyLookup[current.name] = current;
|
|
211
|
+
attributeLookup[current.attribute] = current;
|
|
212
|
+
Observable.defineProperty(proto, current);
|
|
213
|
+
}
|
|
214
|
+
Reflect.defineProperty(type, "observedAttributes", {
|
|
215
|
+
value: observedAttributes,
|
|
216
|
+
enumerable: true,
|
|
217
|
+
});
|
|
218
|
+
this.attributes = attributes;
|
|
219
|
+
this.propertyLookup = propertyLookup;
|
|
220
|
+
this.attributeLookup = attributeLookup;
|
|
221
|
+
this.shadowOptions = normalizeShadowOptions(nameOrConfig.shadowOptions);
|
|
222
|
+
this.elementOptions =
|
|
223
|
+
nameOrConfig.elementOptions === void 0
|
|
224
|
+
? defaultElementOptions
|
|
225
|
+
: Object.assign(Object.assign({}, defaultElementOptions), nameOrConfig.elementOptions);
|
|
226
|
+
this.styles = ElementStyles.normalize(nameOrConfig.styles);
|
|
227
|
+
this.schema = nameOrConfig.schema;
|
|
228
|
+
fastElementRegistry.register(this);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Defines a custom element based on this definition.
|
|
232
|
+
* @param registry - The element registry to define the element in.
|
|
233
|
+
* @param extensions - An optional array of extension callbacks to invoke
|
|
234
|
+
* with this definition before platform registration.
|
|
235
|
+
* @remarks
|
|
236
|
+
* This operation is idempotent per registry.
|
|
237
|
+
*/
|
|
238
|
+
define(registry = this.registry, extensions) {
|
|
239
|
+
const type = this.type;
|
|
240
|
+
if (!registry.get(this.name)) {
|
|
241
|
+
applyFASTElementExtensions(this, registry, extensions);
|
|
242
|
+
if (this.template === void 0 && templateResolvers.has(this)) {
|
|
243
|
+
void Promise.resolve()
|
|
244
|
+
.then(() => resolveFASTElementTemplate(this))
|
|
245
|
+
.then(template => {
|
|
246
|
+
if (template !== void 0 && !registry.get(this.name)) {
|
|
247
|
+
this.platformDefined = true;
|
|
248
|
+
registry.define(this.name, type, this.elementOptions);
|
|
249
|
+
}
|
|
250
|
+
})
|
|
251
|
+
.catch(error => {
|
|
252
|
+
setFASTElementTemplateError(this, error);
|
|
253
|
+
Observable.notify(this, "template");
|
|
254
|
+
});
|
|
255
|
+
return this;
|
|
256
|
+
}
|
|
257
|
+
this.platformDefined = true;
|
|
258
|
+
registry.define(this.name, type, this.elementOptions);
|
|
259
|
+
}
|
|
260
|
+
return this;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Creates an instance of FASTElementDefinition.
|
|
264
|
+
* @param type - The type this definition is being created for.
|
|
265
|
+
* @param nameOrDef - The name of the element to define or a config object
|
|
266
|
+
* that describes the element to define.
|
|
267
|
+
*/
|
|
268
|
+
static compose(type, nameOrDef) {
|
|
269
|
+
const definition = fastElementBaseTypes.has(type) || fastElementRegistry.getByType(type)
|
|
270
|
+
? new FASTElementDefinition(class extends type {
|
|
271
|
+
}, nameOrDef)
|
|
272
|
+
: new FASTElementDefinition(type, nameOrDef);
|
|
273
|
+
return Promise.resolve(definition);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Registers a FASTElement base type.
|
|
277
|
+
* @param type - The type to register as a base type.
|
|
278
|
+
* @internal
|
|
279
|
+
*/
|
|
280
|
+
static registerBaseType(type) {
|
|
281
|
+
fastElementBaseTypes.add(type);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Gets the element definition associated with the specified type.
|
|
286
|
+
* @param type - The custom element type to retrieve the definition for.
|
|
287
|
+
*/
|
|
288
|
+
FASTElementDefinition.getByType = fastElementRegistry.getByType;
|
|
289
|
+
/**
|
|
290
|
+
* Gets the element definition associated with the instance.
|
|
291
|
+
* @param instance - The custom element instance to retrieve the definition for.
|
|
292
|
+
*/
|
|
293
|
+
FASTElementDefinition.getForInstance = fastElementRegistry.getForInstance;
|
|
294
|
+
Observable.defineProperty(FASTElementDefinition.prototype, "template");
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Observable } from "../observation/observable.js";
|
|
2
|
+
import { createTypeRegistry } from "../platform.js";
|
|
3
|
+
const globalRegisteredTypes = {};
|
|
4
|
+
const registeredTypesByRegistry = new WeakMap();
|
|
5
|
+
const typeRegistry = createTypeRegistry();
|
|
6
|
+
/**
|
|
7
|
+
* The FAST custom element registry.
|
|
8
|
+
* @remarks
|
|
9
|
+
* This registry stores FAST element definitions by constructor so consumers can
|
|
10
|
+
* look up the `FASTElementDefinition` associated with an element type, instance,
|
|
11
|
+
* or registered tag name.
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
export const fastElementRegistry = Object.freeze({
|
|
15
|
+
register(definition) {
|
|
16
|
+
if (!typeRegistry.register(definition)) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
const registeredTypes = getRegisteredTypes(definition.registry);
|
|
20
|
+
if (!Object.prototype.hasOwnProperty.call(registeredTypes, definition.name)) {
|
|
21
|
+
Observable.defineProperty(registeredTypes, definition.name);
|
|
22
|
+
}
|
|
23
|
+
registeredTypes[definition.name] = definition.type;
|
|
24
|
+
return true;
|
|
25
|
+
},
|
|
26
|
+
getByType: typeRegistry.getByType,
|
|
27
|
+
getForInstance: typeRegistry.getForInstance,
|
|
28
|
+
whenRegistered,
|
|
29
|
+
});
|
|
30
|
+
function getRegisteredTypes(registry = customElements) {
|
|
31
|
+
if (registry === customElements) {
|
|
32
|
+
return globalRegisteredTypes;
|
|
33
|
+
}
|
|
34
|
+
let registeredTypes = registeredTypesByRegistry.get(registry);
|
|
35
|
+
if (!registeredTypes) {
|
|
36
|
+
registeredTypes = {};
|
|
37
|
+
registeredTypesByRegistry.set(registry, registeredTypes);
|
|
38
|
+
}
|
|
39
|
+
return registeredTypes;
|
|
40
|
+
}
|
|
41
|
+
function getDefinitionForType(type) {
|
|
42
|
+
return type === void 0 ? void 0 : fastElementRegistry.getByType(type);
|
|
43
|
+
}
|
|
44
|
+
function whenRegistered(name, registry = customElements) {
|
|
45
|
+
const registeredTypes = getRegisteredTypes(registry);
|
|
46
|
+
if (!Object.prototype.hasOwnProperty.call(registeredTypes, name)) {
|
|
47
|
+
Observable.defineProperty(registeredTypes, name);
|
|
48
|
+
}
|
|
49
|
+
const definition = getDefinitionForType(registeredTypes[name]);
|
|
50
|
+
if (definition !== void 0) {
|
|
51
|
+
return Promise.resolve(definition);
|
|
52
|
+
}
|
|
53
|
+
return new Promise(resolve => {
|
|
54
|
+
const notifier = Observable.getNotifier(registeredTypes);
|
|
55
|
+
const subscriber = {
|
|
56
|
+
handleChange: () => {
|
|
57
|
+
const definition = getDefinitionForType(registeredTypes[name]);
|
|
58
|
+
if (definition === void 0) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
notifier.unsubscribe(subscriber, name);
|
|
62
|
+
resolve(definition);
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
notifier.subscribe(subscriber, name);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { isFunction } from "../interfaces.js";
|
|
2
|
+
import { ElementController } from "./element-controller.js";
|
|
3
|
+
import { applyFASTElementExtensions, FASTElementDefinition, resolveFASTElementTemplate, } from "./fast-definitions.js";
|
|
4
|
+
/* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
|
|
5
|
+
function createFASTElement(BaseType) {
|
|
6
|
+
const type = class extends BaseType {
|
|
7
|
+
constructor() {
|
|
8
|
+
/* eslint-disable-next-line */
|
|
9
|
+
super();
|
|
10
|
+
ElementController.forCustomElement(this);
|
|
11
|
+
}
|
|
12
|
+
$emit(type, detail, options) {
|
|
13
|
+
return this.$fastController.emit(type, detail, options);
|
|
14
|
+
}
|
|
15
|
+
connectedCallback() {
|
|
16
|
+
this.$fastController.connect();
|
|
17
|
+
}
|
|
18
|
+
disconnectedCallback() {
|
|
19
|
+
this.$fastController.disconnect();
|
|
20
|
+
}
|
|
21
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
22
|
+
this.$fastController.onAttributeChangedCallback(name, oldValue, newValue);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
FASTElementDefinition.registerBaseType(type);
|
|
26
|
+
return type;
|
|
27
|
+
}
|
|
28
|
+
function isPromiseLike(value) {
|
|
29
|
+
return typeof (value === null || value === void 0 ? void 0 : value.then) === "function";
|
|
30
|
+
}
|
|
31
|
+
function define(type, nameOrDef, extensions) {
|
|
32
|
+
if (Array.isArray(nameOrDef)) {
|
|
33
|
+
extensions = nameOrDef;
|
|
34
|
+
nameOrDef = undefined;
|
|
35
|
+
}
|
|
36
|
+
const composePromise = isFunction(type)
|
|
37
|
+
? FASTElementDefinition.compose(type, nameOrDef)
|
|
38
|
+
: FASTElementDefinition.compose(this, type);
|
|
39
|
+
return composePromise.then(def => {
|
|
40
|
+
applyFASTElementExtensions(def, def.registry, extensions);
|
|
41
|
+
const template = resolveFASTElementTemplate(def);
|
|
42
|
+
if (isPromiseLike(template)) {
|
|
43
|
+
return template.then(() => def.define().type);
|
|
44
|
+
}
|
|
45
|
+
return def.define().type;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function from(BaseType) {
|
|
49
|
+
return createFASTElement(BaseType);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* A minimal base class for FASTElements that also provides
|
|
53
|
+
* static helpers for working with FASTElements.
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
56
|
+
export const FASTElement = Object.assign(createFASTElement(HTMLElement), {
|
|
57
|
+
/**
|
|
58
|
+
* Creates a new FASTElement base class inherited from the
|
|
59
|
+
* provided base type.
|
|
60
|
+
* @param BaseType - The base element type to inherit from.
|
|
61
|
+
*/
|
|
62
|
+
from,
|
|
63
|
+
/**
|
|
64
|
+
* Defines a platform custom element based on the provided type and definition.
|
|
65
|
+
* @param type - The custom element type to define.
|
|
66
|
+
* @param nameOrDef - The name of the element to define or a definition object
|
|
67
|
+
* that describes the element to define.
|
|
68
|
+
*/
|
|
69
|
+
define,
|
|
70
|
+
});
|
|
71
|
+
/**
|
|
72
|
+
* Decorator: Defines a platform custom element based on `FASTElement`.
|
|
73
|
+
* @param nameOrDef - The name of the element to define or a definition object
|
|
74
|
+
* that describes the element to define.
|
|
75
|
+
* @public
|
|
76
|
+
*/
|
|
77
|
+
export function customElement(nameOrDef) {
|
|
78
|
+
/* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
|
|
79
|
+
return function (type) {
|
|
80
|
+
define(type, nameOrDef);
|
|
81
|
+
};
|
|
82
|
+
}
|