@gyral/core 0.3.0 → 0.3.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 +57 -0
- package/NOTICE +19 -0
- package/README.md +36 -8
- package/dist/call.d.ts +32 -0
- package/dist/call.js +63 -0
- package/dist/call.js.map +1 -0
- package/dist/children.d.ts +25 -3
- package/dist/children.js +18 -1
- package/dist/children.js.map +1 -1
- package/dist/cli/gyral-types.d.ts +2 -0
- package/dist/cli/gyral-types.js +23 -0
- package/dist/cli/gyral-types.js.map +1 -0
- package/dist/command.d.ts +54 -12
- package/dist/command.js +25 -11
- package/dist/command.js.map +1 -1
- package/dist/compiler/ast.d.ts +2 -0
- package/dist/compiler/ast.js +5 -1
- package/dist/compiler/ast.js.map +1 -1
- package/dist/compiler/compile.d.ts +5 -2
- package/dist/compiler/compile.js +36 -17
- package/dist/compiler/compile.js.map +1 -1
- package/dist/compiler/component-entries.d.ts +7 -0
- package/dist/compiler/component-entries.js +42 -0
- package/dist/compiler/component-entries.js.map +1 -0
- package/dist/compiler/components.d.ts +4 -0
- package/dist/compiler/components.js +190 -0
- package/dist/compiler/components.js.map +1 -0
- package/dist/compiler/facts.d.ts +31 -0
- package/dist/compiler/facts.js +285 -0
- package/dist/compiler/facts.js.map +1 -0
- package/dist/compiler/features.d.ts +34 -0
- package/dist/compiler/features.js +158 -0
- package/dist/compiler/features.js.map +1 -0
- package/dist/compiler/hooks.d.ts +4 -0
- package/dist/compiler/hooks.js +144 -89
- package/dist/compiler/hooks.js.map +1 -1
- package/dist/compiler/loader-source.d.ts +14 -0
- package/dist/compiler/loader-source.js +86 -0
- package/dist/compiler/loader-source.js.map +1 -0
- package/dist/compiler/locate.d.ts +14 -0
- package/dist/compiler/locate.js +90 -0
- package/dist/compiler/locate.js.map +1 -0
- package/dist/compiler/parse5-check.d.ts +1 -1
- package/dist/compiler/parse5-check.js +8 -3
- package/dist/compiler/parse5-check.js.map +1 -1
- package/dist/compiler/prop-schemas.d.ts +4 -0
- package/dist/compiler/prop-schemas.js +108 -0
- package/dist/compiler/prop-schemas.js.map +1 -0
- package/dist/compiler/scan.d.ts +13 -3
- package/dist/compiler/scan.js +21 -13
- package/dist/compiler/scan.js.map +1 -1
- package/dist/compiler/scope.d.ts +8 -0
- package/dist/compiler/scope.js +116 -0
- package/dist/compiler/scope.js.map +1 -0
- package/dist/compiler/tag-map.d.ts +41 -0
- package/dist/compiler/tag-map.js +126 -0
- package/dist/compiler/tag-map.js.map +1 -0
- package/dist/components-ready.d.ts +7 -0
- package/dist/components-ready.js +19 -0
- package/dist/components-ready.js.map +1 -0
- package/dist/define.d.ts +12 -4
- package/dist/define.js +8 -12
- package/dist/define.js.map +1 -1
- package/dist/devtools-events.d.ts +8 -0
- package/dist/devtools-events.js.map +1 -1
- package/dist/devtools-off.d.ts +1 -0
- package/dist/devtools-off.js +1 -0
- package/dist/devtools-off.js.map +1 -1
- package/dist/devtools.d.ts +3 -0
- package/dist/devtools.js +14 -0
- package/dist/devtools.js.map +1 -1
- package/dist/drivers-scope.js.map +1 -1
- package/dist/element-internals.d.ts +1 -0
- package/dist/element-internals.js +11 -0
- package/dist/element-internals.js.map +1 -0
- package/dist/element-types.d.ts +7 -4
- package/dist/element-types.js.map +1 -1
- package/dist/element.js +80 -27
- package/dist/element.js.map +1 -1
- package/dist/error-view.d.ts +10 -0
- package/dist/error-view.js +30 -0
- package/dist/error-view.js.map +1 -0
- package/dist/errors.d.ts +21 -0
- package/dist/errors.js +47 -0
- package/dist/errors.js.map +1 -0
- package/dist/errors.json +289 -0
- package/dist/eslint/imports.d.ts +2 -0
- package/dist/eslint/imports.js +2 -2
- package/dist/eslint/imports.js.map +1 -1
- package/dist/eslint/index.d.ts +2 -1
- package/dist/eslint/index.js +11 -3
- package/dist/eslint/index.js.map +1 -1
- package/dist/eslint/template-rule.d.ts +1 -0
- package/dist/eslint/template-rule.js +15 -5
- package/dist/eslint/template-rule.js.map +1 -1
- package/dist/eslint/unused-intent-rule.d.ts +2 -0
- package/dist/eslint/unused-intent-rule.js +186 -0
- package/dist/eslint/unused-intent-rule.js.map +1 -0
- package/dist/features.d.ts +2 -2
- package/dist/features.js.map +1 -1
- package/dist/focus.d.ts +6 -0
- package/dist/focus.js +32 -2
- package/dist/focus.js.map +1 -1
- package/dist/form-associated.d.ts +46 -0
- package/dist/form-associated.js +77 -0
- package/dist/form-associated.js.map +1 -0
- package/dist/forms.d.ts +42 -30
- package/dist/forms.js +85 -41
- package/dist/forms.js.map +1 -1
- package/dist/frame-lane.d.ts +11 -0
- package/dist/frame-lane.js +28 -0
- package/dist/frame-lane.js.map +1 -0
- package/dist/head.d.ts +61 -0
- package/dist/head.js +85 -0
- package/dist/head.js.map +1 -0
- package/dist/host-model.d.ts +34 -5
- package/dist/host-model.js +146 -23
- package/dist/host-model.js.map +1 -1
- package/dist/hydration-client.js +2 -2
- package/dist/hydration-client.js.map +1 -1
- package/dist/hydration-loader.d.ts +13 -0
- package/dist/hydration-loader.js +58 -0
- package/dist/hydration-loader.js.map +1 -0
- package/dist/hydration-off.d.ts +8 -0
- package/dist/hydration-off.js +25 -0
- package/dist/hydration-off.js.map +1 -0
- package/dist/hydration.d.ts +0 -12
- package/dist/hydration.js +3 -52
- package/dist/hydration.js.map +1 -1
- package/dist/index.d.ts +21 -24
- package/dist/index.js +10 -19
- package/dist/index.js.map +1 -1
- package/dist/indexeddb-types.d.ts +97 -0
- package/dist/indexeddb-types.js +2 -0
- package/dist/indexeddb-types.js.map +1 -0
- package/dist/indexeddb.d.ts +5 -0
- package/dist/indexeddb.js +118 -0
- package/dist/indexeddb.js.map +1 -0
- package/dist/intent.d.ts +42 -20
- package/dist/intent.js +145 -107
- package/dist/intent.js.map +1 -1
- package/dist/internal/indexeddb-open.d.ts +8 -0
- package/dist/internal/indexeddb-open.js +96 -0
- package/dist/internal/indexeddb-open.js.map +1 -0
- package/dist/internal/indexeddb-transaction.d.ts +4 -0
- package/dist/internal/indexeddb-transaction.js +134 -0
- package/dist/internal/indexeddb-transaction.js.map +1 -0
- package/dist/internal/interpreter.d.ts +12 -4
- package/dist/internal/interpreter.js +36 -48
- package/dist/internal/interpreter.js.map +1 -1
- package/dist/internal/token.d.ts +1 -0
- package/dist/internal/token.js +7 -0
- package/dist/internal/token.js.map +1 -0
- package/dist/internal.d.ts +20 -0
- package/dist/internal.js +22 -0
- package/dist/internal.js.map +1 -0
- package/dist/invoker-fallback-used.d.ts +4 -0
- package/dist/invoker-fallback-used.js +10 -0
- package/dist/invoker-fallback-used.js.map +1 -0
- package/dist/invoker-fallback.d.ts +4 -0
- package/dist/invoker-fallback.js +15 -0
- package/dist/invoker-fallback.js.map +1 -0
- package/dist/light-dom.d.ts +1 -1
- package/dist/light-dom.js.map +1 -1
- package/dist/prop.d.ts +30 -7
- package/dist/prop.js +19 -0
- package/dist/prop.js.map +1 -1
- package/dist/props.d.ts +8 -3
- package/dist/props.js +22 -15
- package/dist/props.js.map +1 -1
- package/dist/retry.d.ts +15 -0
- package/dist/retry.js +48 -0
- package/dist/retry.js.map +1 -0
- package/dist/scheduler.d.ts +7 -3
- package/dist/scheduler.js +38 -56
- package/dist/scheduler.js.map +1 -1
- package/dist/script-json.d.ts +2 -0
- package/dist/script-json.js +13 -0
- package/dist/script-json.js.map +1 -0
- package/dist/server-component.d.ts +1 -1
- package/dist/server-component.js +45 -14
- package/dist/server-component.js.map +1 -1
- package/dist/server.d.ts +9 -3
- package/dist/server.js +12 -3
- package/dist/server.js.map +1 -1
- package/dist/settled.d.ts +4 -3
- package/dist/settled.js +48 -26
- package/dist/settled.js.map +1 -1
- package/dist/spec-features-used.d.ts +21 -0
- package/dist/spec-features-used.js +50 -0
- package/dist/spec-features-used.js.map +1 -0
- package/dist/spec-features.d.ts +28 -0
- package/dist/spec-features.js +42 -0
- package/dist/spec-features.js.map +1 -0
- package/dist/states.d.ts +3 -5
- package/dist/states.js +22 -8
- package/dist/states.js.map +1 -1
- package/dist/storage.d.ts +69 -0
- package/dist/storage.js +158 -0
- package/dist/storage.js.map +1 -0
- package/dist/store-binding.js +2 -2
- package/dist/store-binding.js.map +1 -1
- package/dist/store-scope.d.ts +2 -4
- package/dist/store-scope.js +6 -16
- package/dist/store-scope.js.map +1 -1
- package/dist/store.d.ts +2 -6
- package/dist/store.js +36 -8
- package/dist/store.js.map +1 -1
- package/dist/subscription.d.ts +35 -0
- package/dist/subscription.js +74 -0
- package/dist/subscription.js.map +1 -0
- package/dist/subscriptions.d.ts +26 -0
- package/dist/subscriptions.js +98 -0
- package/dist/subscriptions.js.map +1 -0
- package/dist/transitions.d.ts +4 -5
- package/dist/transitions.js +10 -4
- package/dist/transitions.js.map +1 -1
- package/dist/types.d.ts +141 -32
- package/dist/types.js.map +1 -1
- package/dist/use-dialogs.d.ts +2 -0
- package/dist/use-dialogs.js +9 -0
- package/dist/use-dialogs.js.map +1 -0
- package/dist/use-disposal.d.ts +2 -0
- package/dist/use-disposal.js +9 -0
- package/dist/use-disposal.js.map +1 -0
- package/dist/use-error-view.d.ts +2 -0
- package/dist/use-error-view.js +9 -0
- package/dist/use-error-view.js.map +1 -0
- package/dist/use-errored.d.ts +2 -0
- package/dist/use-errored.js +9 -0
- package/dist/use-errored.js.map +1 -0
- package/dist/use-form-associated.d.ts +2 -0
- package/dist/use-form-associated.js +7 -0
- package/dist/use-form-associated.js.map +1 -0
- package/dist/use-frame-lane.d.ts +2 -0
- package/dist/use-frame-lane.js +10 -0
- package/dist/use-frame-lane.js.map +1 -0
- package/dist/use-invokers.d.ts +2 -0
- package/dist/use-invokers.js +10 -0
- package/dist/use-invokers.js.map +1 -0
- package/dist/use-states.d.ts +2 -0
- package/dist/use-states.js +10 -0
- package/dist/use-states.js.map +1 -0
- package/dist/use-subscriptions.d.ts +2 -0
- package/dist/use-subscriptions.js +10 -0
- package/dist/use-subscriptions.js.map +1 -0
- package/dist/use-transitions.d.ts +2 -0
- package/dist/use-transitions.js +10 -0
- package/dist/use-transitions.js.map +1 -0
- package/dist/view/attributes.d.ts +5 -0
- package/dist/view/attributes.js +5 -0
- package/dist/view/attributes.js.map +1 -1
- package/dist/view/compiled.d.ts +1 -1
- package/dist/view/compiled.js +1 -1
- package/dist/view/compiled.js.map +1 -1
- package/dist/view/index.d.ts +9 -4
- package/dist/view/index.js +9 -3
- package/dist/view/index.js.map +1 -1
- package/dist/view/loc.d.ts +9 -0
- package/dist/view/loc.js +50 -0
- package/dist/view/loc.js.map +1 -0
- package/dist/view/message.d.ts +17 -0
- package/dist/view/message.js +40 -0
- package/dist/view/message.js.map +1 -0
- package/dist/view/messages.d.ts +43 -0
- package/dist/view/messages.js +84 -0
- package/dist/view/messages.js.map +1 -0
- package/dist/view/normalize/check.d.ts +5 -2
- package/dist/view/normalize/check.js +6 -3
- package/dist/view/normalize/check.js.map +1 -1
- package/dist/view/normalize/emit.d.ts +2 -0
- package/dist/view/normalize/emit.js +40 -11
- package/dist/view/normalize/emit.js.map +1 -1
- package/dist/view/normalize/errors.js +1 -1
- package/dist/view/normalize/errors.js.map +1 -1
- package/dist/view/normalize/id.d.ts +5 -2
- package/dist/view/normalize/id.js +9 -2
- package/dist/view/normalize/id.js.map +1 -1
- package/dist/view/normalize/normalize.d.ts +7 -4
- package/dist/view/normalize/normalize.js +15 -9
- package/dist/view/normalize/normalize.js.map +1 -1
- package/dist/view/normalize/rules.d.ts +9 -0
- package/dist/view/normalize/rules.js +35 -5
- package/dist/view/normalize/rules.js.map +1 -1
- package/dist/view/normalize/svg.d.ts +14 -0
- package/dist/view/normalize/svg.js +40 -0
- package/dist/view/normalize/svg.js.map +1 -0
- package/dist/view/normalize/tokens.d.ts +5 -1
- package/dist/view/normalize/tokens.js.map +1 -1
- package/dist/view/normalize/tree.d.ts +8 -2
- package/dist/view/normalize/tree.js +58 -13
- package/dist/view/normalize/tree.js.map +1 -1
- package/dist/view/normalize/types.d.ts +24 -4
- package/dist/view/normalize/types.js +4 -1
- package/dist/view/normalize/types.js.map +1 -1
- package/dist/view/normalize/whitespace.js +4 -3
- package/dist/view/normalize/whitespace.js.map +1 -1
- package/dist/view/prepare-stub.js +2 -2
- package/dist/view/prepare-stub.js.map +1 -1
- package/dist/view/prepare.d.ts +5 -2
- package/dist/view/prepare.js +9 -3
- package/dist/view/prepare.js.map +1 -1
- package/dist/view/registry.d.ts +15 -0
- package/dist/view/registry.js +10 -2
- package/dist/view/registry.js.map +1 -1
- package/dist/view/render/adopt-attr.js +7 -1
- package/dist/view/render/adopt-attr.js.map +1 -1
- package/dist/view/render/adopt.js +21 -4
- package/dist/view/render/adopt.js.map +1 -1
- package/dist/view/render/attr-parts.d.ts +12 -1
- package/dist/view/render/attr-parts.js +38 -5
- package/dist/view/render/attr-parts.js.map +1 -1
- package/dist/view/render/child-part.js +5 -2
- package/dist/view/render/child-part.js.map +1 -1
- package/dist/view/render/dispose.d.ts +3 -0
- package/dist/view/render/dispose.js +76 -0
- package/dist/view/render/dispose.js.map +1 -0
- package/dist/view/render/hook-part.d.ts +3 -1
- package/dist/view/render/hook-part.js +21 -5
- package/dist/view/render/hook-part.js.map +1 -1
- package/dist/view/render/hook-run.d.ts +2 -0
- package/dist/view/render/hook-run.js +72 -0
- package/dist/view/render/hook-run.js.map +1 -0
- package/dist/view/render/hooks.d.ts +74 -6
- package/dist/view/render/hooks.js +79 -17
- package/dist/view/render/hooks.js.map +1 -1
- package/dist/view/render/hydrate.js +2 -2
- package/dist/view/render/hydrate.js.map +1 -1
- package/dist/view/render/keyed.d.ts +6 -0
- package/dist/view/render/keyed.js +15 -0
- package/dist/view/render/keyed.js.map +1 -0
- package/dist/view/render/list.d.ts +1 -1
- package/dist/view/render/list.js.map +1 -1
- package/dist/view/render/mismatch.js +5 -3
- package/dist/view/render/mismatch.js.map +1 -1
- package/dist/view/render/modal.d.ts +3 -0
- package/dist/view/render/modal.js +39 -0
- package/dist/view/render/modal.js.map +1 -0
- package/dist/view/render/raw.d.ts +4 -1
- package/dist/view/render/raw.js +6 -2
- package/dist/view/render/raw.js.map +1 -1
- package/dist/view/render/render.d.ts +4 -1
- package/dist/view/render/render.js +17 -12
- package/dist/view/render/render.js.map +1 -1
- package/dist/view/render/toggles.d.ts +6 -0
- package/dist/view/render/toggles.js +6 -0
- package/dist/view/render/toggles.js.map +1 -0
- package/dist/view/render/values.d.ts +1 -1
- package/dist/view/render/values.js.map +1 -1
- package/dist/view/render/warn.d.ts +14 -0
- package/dist/view/render/warn.js +45 -0
- package/dist/view/render/warn.js.map +1 -1
- package/dist/view/server/component.d.ts +6 -3
- package/dist/view/server/component.js +29 -7
- package/dist/view/server/component.js.map +1 -1
- package/dist/view/server/index.d.ts +20 -0
- package/dist/view/server/index.js +12 -4
- package/dist/view/server/index.js.map +1 -1
- package/dist/view/server/tags.d.ts +13 -2
- package/dist/view/server/tags.js +13 -2
- package/dist/view/server/tags.js.map +1 -1
- package/dist/view/server/values.d.ts +2 -0
- package/dist/view/server/values.js +8 -0
- package/dist/view/server/values.js.map +1 -1
- package/dist/view/server/writer.d.ts +9 -4
- package/dist/view/server/writer.js +33 -18
- package/dist/view/server/writer.js.map +1 -1
- package/dist/view/template-element.d.ts +7 -0
- package/dist/view/template-element.js +25 -5
- package/dist/view/template-element.js.map +1 -1
- package/dist/view/template.d.ts +9 -2
- package/dist/view/template.js +61 -8
- package/dist/view/template.js.map +1 -1
- package/dist/view/trusted-html.d.ts +6 -0
- package/dist/view/trusted-html.js +34 -0
- package/dist/view/trusted-html.js.map +1 -0
- package/dist/vite.d.ts +38 -31
- package/dist/vite.js +206 -31
- package/dist/vite.js.map +1 -1
- package/package.json +34 -3
- package/dist/hooks/labelled-by.d.ts +0 -13
- package/dist/hooks/labelled-by.js +0 -51
- package/dist/hooks/labelled-by.js.map +0 -1
- package/dist/random.d.ts +0 -13
- package/dist/random.js +0 -19
- package/dist/random.js.map +0 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// JSON safe to inline in a <script> element. Its own module: head.ts (the head model) and the
|
|
2
|
+
// store seeds both use it, and keeping it out of store-scope.ts stops a bundler from turning
|
|
3
|
+
// the store registry into a shared chunk every page loads (gyral-dyn.35).
|
|
4
|
+
/** JSON for an inline `<script type="application/json">`: `</script>` and friends escaped. */
|
|
5
|
+
export function scriptSafeJson(value) {
|
|
6
|
+
return JSON.stringify(value)
|
|
7
|
+
.replaceAll('<', '\\u003c')
|
|
8
|
+
.replaceAll('>', '\\u003e')
|
|
9
|
+
.replaceAll('&', '\\u0026')
|
|
10
|
+
.replaceAll('
', '\\u2028')
|
|
11
|
+
.replaceAll('
', '\\u2029');
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=script-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"script-json.js","sourceRoot":"","sources":["../src/script-json.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,6FAA6F;AAC7F,0EAA0E;AAE1E,8FAA8F;AAC9F,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;SACzB,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC;SAC1B,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC;SAC1B,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC;SAC1B,UAAU,CAAC;CACf,EAAE,SAAS,CAAC;SACR,UAAU,CAAC;CACf,EAAE,SAAS,CAAC,CAAC;AACd,CAAC","sourcesContent":["// JSON safe to inline in a <script> element. Its own module: head.ts (the head model) and the\n// store seeds both use it, and keeping it out of store-scope.ts stops a bundler from turning\n// the store registry into a shared chunk every page loads (gyral-dyn.35).\n\n/** JSON for an inline `<script type=\"application/json\">`: `</script>` and friends escaped. */\nexport function scriptSafeJson(value: unknown): string {\n return JSON.stringify(value)\n .replaceAll('<', '\\\\u003c')\n .replaceAll('>', '\\\\u003e')\n .replaceAll('&', '\\\\u0026')\n .replaceAll('
', '\\\\u2028')\n .replaceAll('
', '\\\\u2029');\n}\n"]}
|
|
@@ -4,7 +4,7 @@ import { type ServerComponent } from './view/index.js';
|
|
|
4
4
|
export declare function serverComponent<S, M extends Tagged, P>(tag: string, spec: ComponentSpec<S, M, P>): ServerComponent;
|
|
5
5
|
/**
|
|
6
6
|
* Registers every spec define() recorded outside the browser (and not registered yet) in
|
|
7
|
-
* view/'s server registry. `@gyral/core/server` calls it before each render; client code never
|
|
7
|
+
* view/'s server registry. `@gyral/core/internal/server` calls it before each render; client code never
|
|
8
8
|
* imports this module.
|
|
9
9
|
*/
|
|
10
10
|
export declare function registerRecordedSpecs(): void;
|
package/dist/server-component.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// A spec as the server renderer sees it (view/05-element.md "Registration", view/06-server.md
|
|
2
2
|
// "Components"). Outside the browser `define()` records the spec (server-specs.ts) and
|
|
3
|
-
// `@gyral/core/server` registers one of these per spec in view/'s server registry. Rendering is
|
|
3
|
+
// `@gyral/core/internal/server` registers one of these per spec in view/'s server registry. Rendering is
|
|
4
4
|
// `view(init(props))`: props parsed from the start tag's attributes (always validated) and
|
|
5
5
|
// property holes (validated in development), `init`'s commands dropped (the client's `init`
|
|
6
6
|
// starts them after hydration, ADR 0012), then `initialMessages` through their reducers.
|
|
7
7
|
// `ctx.read` uses the nearest `<gyral-stores>` provider's registry, else the request's.
|
|
8
8
|
import { splitNext } from './command.js';
|
|
9
|
+
import { GyralError } from './errors.js';
|
|
9
10
|
import { makeSeed } from './hydration.js';
|
|
10
11
|
import { runInit } from './init.js';
|
|
11
12
|
import { intentNames } from './intent.js';
|
|
@@ -13,7 +14,7 @@ import { isLight } from './light-dom.js';
|
|
|
13
14
|
import { attributeOf, checkValue, missingRequired, parseAttribute, readProps, reportInvalid, } from './props.js';
|
|
14
15
|
import { recordedSpecs } from './server-specs.js';
|
|
15
16
|
import { serverScopeFor, StoreRegistry } from './store-scope.js';
|
|
16
|
-
import { DEV, registerServerComponent, serverComponent as registered, styleTexts, } from './view/index.js';
|
|
17
|
+
import { DEV, message, nothing, registerServerComponent, serverComponent as registered, styleTexts, } from './view/index.js';
|
|
17
18
|
/** Resolves props from a start tag: attributes always validated, properties in development. */
|
|
18
19
|
function propsFrom(tag, table, input) {
|
|
19
20
|
const values = {};
|
|
@@ -49,7 +50,7 @@ function propsFrom(tag, table, input) {
|
|
|
49
50
|
/** The server registry entry for `spec`. */
|
|
50
51
|
export function serverComponent(tag, spec) {
|
|
51
52
|
const table = (spec.props ?? {});
|
|
52
|
-
const reducers = spec.update;
|
|
53
|
+
const reducers = (spec.update ?? {});
|
|
53
54
|
const declared = new Set((spec.stores ?? []).map((store) => store.name));
|
|
54
55
|
const reader = (scope) => (store) => {
|
|
55
56
|
if (!declared.has(store.name)) {
|
|
@@ -59,9 +60,26 @@ export function serverComponent(tag, spec) {
|
|
|
59
60
|
const registry = scope instanceof StoreRegistry ? scope : serverScopeFor(tag, any);
|
|
60
61
|
return registry.get(any).state; // Sound: the ref carries this store's state type.
|
|
61
62
|
};
|
|
63
|
+
/**
|
|
64
|
+
* The rendering of a component that threw (ADR 0024): its error view (or nothing, also when
|
|
65
|
+
* the error view throws), no seed, and the GyralError the renderer reports.
|
|
66
|
+
*/
|
|
67
|
+
const failed = (phase, cause, state) => {
|
|
68
|
+
const error = new GyralError(phase, message(78, tag), cause, tag);
|
|
69
|
+
let view = nothing;
|
|
70
|
+
try {
|
|
71
|
+
if (spec.error !== undefined)
|
|
72
|
+
view = spec.error(error, state);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
view = nothing; // the error view failed too: the host stays empty
|
|
76
|
+
}
|
|
77
|
+
return { view, seed: { props: {} }, failed: error };
|
|
78
|
+
};
|
|
62
79
|
return {
|
|
63
80
|
tag,
|
|
64
81
|
light: isLight(spec),
|
|
82
|
+
delegatesFocus: typeof spec.shadow === 'object' && spec.shadow.delegatesFocus === true,
|
|
65
83
|
styles: isLight(spec) ? [] : styleTexts(spec.styles),
|
|
66
84
|
hydrate: spec.hydrate ?? 'load',
|
|
67
85
|
render(input) {
|
|
@@ -72,23 +90,36 @@ export function serverComponent(tag, spec) {
|
|
|
72
90
|
}
|
|
73
91
|
const props = readProps(values, table); // Sound: exactly the declared props.
|
|
74
92
|
const ctx = { props, read: reader(input.scope) };
|
|
75
|
-
|
|
76
|
-
let state
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
93
|
+
let initial;
|
|
94
|
+
let state;
|
|
95
|
+
try {
|
|
96
|
+
[initial] = splitNext(runInit(spec, props));
|
|
97
|
+
state = initial;
|
|
98
|
+
for (const msg of (input.initialMessages ?? [])) {
|
|
99
|
+
const reducer = reducers[msg._tag];
|
|
100
|
+
if (reducer !== undefined)
|
|
101
|
+
[state] = splitNext(reducer(state, msg, ctx));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (cause) {
|
|
105
|
+
return failed('init', cause, undefined);
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
return {
|
|
109
|
+
view: spec.view(state, intentNames, ctx),
|
|
110
|
+
seed: makeSeed(tag, state, initial, carried),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
catch (cause) {
|
|
114
|
+
return failed('view', cause, state);
|
|
81
115
|
}
|
|
82
|
-
return {
|
|
83
|
-
view: spec.view(state, intentNames, ctx),
|
|
84
|
-
seed: makeSeed(tag, state, initial, carried),
|
|
85
|
-
};
|
|
86
116
|
},
|
|
117
|
+
fallback: (cause) => failed('view', cause, undefined),
|
|
87
118
|
};
|
|
88
119
|
}
|
|
89
120
|
/**
|
|
90
121
|
* Registers every spec define() recorded outside the browser (and not registered yet) in
|
|
91
|
-
* view/'s server registry. `@gyral/core/server` calls it before each render; client code never
|
|
122
|
+
* view/'s server registry. `@gyral/core/internal/server` calls it before each render; client code never
|
|
92
123
|
* imports this module.
|
|
93
124
|
*/
|
|
94
125
|
export function registerRecordedSpecs() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-component.js","sourceRoot":"","sources":["../src/server-component.ts"],"names":[],"mappings":"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","sourcesContent":["// A spec as the server renderer sees it (view/05-element.md \"Registration\", view/06-server.md\n// \"Components\"). Outside the browser `define()` records the spec (server-specs.ts) and\n// `@gyral/core/server` registers one of these per spec in view/'s server registry. Rendering is\n// `view(init(props))`: props parsed from the start tag's attributes (always validated) and\n// property holes (validated in development), `init`'s commands dropped (the client's `init`\n// starts them after hydration, ADR 0012), then `initialMessages` through their reducers.\n// `ctx.read` uses the nearest `<gyral-stores>` provider's registry, else the request's.\nimport { splitNext, type Next } from './command.js';\nimport { makeSeed } from './hydration.js';\nimport { runInit } from './init.js';\nimport { intentNames } from './intent.js';\nimport { isLight } from './light-dom.js';\nimport {\n attributeOf,\n checkValue,\n missingRequired,\n parseAttribute,\n readProps,\n reportInvalid,\n type PropTable,\n} from './props.js';\nimport { recordedSpecs } from './server-specs.js';\nimport { serverScopeFor, StoreRegistry } from './store-scope.js';\nimport type { AnyStore, StoreRef } from './store.js';\nimport type { ComponentSpec, Ctx, IntentNames, Tagged } from './types.js';\nimport {\n DEV,\n registerServerComponent,\n serverComponent as registered,\n styleTexts,\n type ServerComponent,\n type ServerRenderInput,\n type ServerRendering,\n} from './view/index.js';\n\ntype Reducers<S> = Readonly<\n Record<string, ((s: S, m: Tagged, ctx: Ctx<object>) => Next<S, Tagged>) | undefined>\n>;\n\n/** Resolves props from a start tag: attributes always validated, properties in development. */\nfunction propsFrom(tag: string, table: PropTable, input: ServerRenderInput) {\n const values: Record<string, unknown> = {};\n const carried: Record<string, unknown> = {};\n for (const [name, def] of Object.entries(table)) {\n if (name in input.properties) {\n const value = input.properties[name];\n if (value === undefined) continue;\n const checked = DEV ? checkValue(tag, name, def, value) : { ok: true as const, value };\n if (checked.ok) values[name] = value;\n else reportInvalid(tag, name, 'a property', checked.issues);\n carried[name] = value; // no attribute carries it: the seed does\n continue;\n }\n const attr = attributeOf(name, def);\n if (attr === undefined) continue;\n const raw = input.attributes[attr];\n const parsed = parseAttribute(def, raw ?? null);\n if (parsed === undefined) continue;\n const checked = parsed.ok ? checkValue(tag, name, def, parsed.value) : parsed;\n if (checked.ok) values[name] = checked.value;\n else reportInvalid(tag, name, `the attribute ${attr}`, checked.issues);\n }\n return { values, carried };\n}\n\n/** The server registry entry for `spec`. */\nexport function serverComponent<S, M extends Tagged, P>(\n tag: string,\n spec: ComponentSpec<S, M, P>,\n): ServerComponent {\n const table = (spec.props ?? {}) as PropTable;\n const reducers = spec.update as unknown as Reducers<S>;\n const declared = new Set((spec.stores ?? []).map((store: AnyStore) => store.name));\n const reader =\n (scope: unknown) =>\n <T>(store: StoreRef<T>): T => {\n if (!declared.has(store.name)) {\n throw new Error(`<${tag}> uses store \"${store.name}\" without declaring it in spec.stores.`);\n }\n const any = store as unknown as AnyStore;\n const registry = scope instanceof StoreRegistry ? scope : serverScopeFor(tag, any);\n return registry.get(any).state as T; // Sound: the ref carries this store's state type.\n };\n return {\n tag,\n light: isLight(spec),\n styles: isLight(spec) ? [] : styleTexts(spec.styles),\n hydrate: spec.hydrate ?? 'load',\n render(input): ServerRendering {\n const { values, carried } = propsFrom(tag, table, input);\n const missing = missingRequired(values, table);\n if (missing.length > 0) {\n console.warn(`<${tag}> is missing required prop(s): ${missing.join(', ')}.`);\n }\n const props = readProps(values, table) as P; // Sound: exactly the declared props.\n const ctx = { props, read: reader(input.scope) } as Ctx<object>;\n const [initial] = splitNext(runInit(spec, props));\n let state = initial;\n for (const msg of (input.initialMessages ?? []) as Tagged[]) {\n const reducer = reducers[msg._tag];\n if (reducer !== undefined) [state] = splitNext(reducer(state, msg, ctx));\n }\n return {\n view: spec.view(state, intentNames as IntentNames<M>, ctx as Ctx<P>),\n seed: makeSeed(tag, state, initial, carried),\n };\n },\n };\n}\n\n/**\n * Registers every spec define() recorded outside the browser (and not registered yet) in\n * view/'s server registry. `@gyral/core/server` calls it before each render; client code never\n * imports this module.\n */\nexport function registerRecordedSpecs(): void {\n for (const [tag, spec] of recordedSpecs()) {\n if (registered(tag) !== undefined) continue;\n // Sound: define() recorded exactly this tag's ComponentSpec.\n registerServerComponent(serverComponent(tag, spec as ComponentSpec<unknown, Tagged, object>));\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"server-component.js","sourceRoot":"","sources":["../src/server-component.ts"],"names":[],"mappings":"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","sourcesContent":["// A spec as the server renderer sees it (view/05-element.md \"Registration\", view/06-server.md\n// \"Components\"). Outside the browser `define()` records the spec (server-specs.ts) and\n// `@gyral/core/internal/server` registers one of these per spec in view/'s server registry. Rendering is\n// `view(init(props))`: props parsed from the start tag's attributes (always validated) and\n// property holes (validated in development), `init`'s commands dropped (the client's `init`\n// starts them after hydration, ADR 0012), then `initialMessages` through their reducers.\n// `ctx.read` uses the nearest `<gyral-stores>` provider's registry, else the request's.\nimport { splitNext, type Next } from './command.js';\nimport { GyralError, type ErrorPhase } from './errors.js';\nimport { makeSeed } from './hydration.js';\nimport { runInit } from './init.js';\nimport { intentNames } from './intent.js';\nimport { isLight } from './light-dom.js';\nimport {\n attributeOf,\n checkValue,\n missingRequired,\n parseAttribute,\n readProps,\n reportInvalid,\n type PropTable,\n} from './props.js';\nimport { recordedSpecs } from './server-specs.js';\nimport { serverScopeFor, StoreRegistry } from './store-scope.js';\nimport type { AnyStore, StoreRef } from './store.js';\nimport type { ComponentSpec, Ctx, IntentNames, Tagged } from './types.js';\nimport {\n DEV,\n message,\n nothing,\n registerServerComponent,\n serverComponent as registered,\n styleTexts,\n type ServerComponent,\n type ServerRenderInput,\n type ServerRendering,\n} from './view/index.js';\n\ntype Reducers<S> = Readonly<\n Record<string, ((s: S, m: Tagged, ctx: Ctx<object>) => Next<S, Tagged>) | undefined>\n>;\n\n/** Resolves props from a start tag: attributes always validated, properties in development. */\nfunction propsFrom(tag: string, table: PropTable, input: ServerRenderInput) {\n const values: Record<string, unknown> = {};\n const carried: Record<string, unknown> = {};\n for (const [name, def] of Object.entries(table)) {\n if (name in input.properties) {\n const value = input.properties[name];\n if (value === undefined) continue;\n const checked = DEV ? checkValue(tag, name, def, value) : { ok: true as const, value };\n if (checked.ok) values[name] = value;\n else reportInvalid(tag, name, 'a property', checked.issues);\n carried[name] = value; // no attribute carries it: the seed does\n continue;\n }\n const attr = attributeOf(name, def);\n if (attr === undefined) continue;\n const raw = input.attributes[attr];\n const parsed = parseAttribute(def, raw ?? null);\n if (parsed === undefined) continue;\n const checked = parsed.ok ? checkValue(tag, name, def, parsed.value) : parsed;\n if (checked.ok) values[name] = checked.value;\n else reportInvalid(tag, name, `the attribute ${attr}`, checked.issues);\n }\n return { values, carried };\n}\n\n/** The server registry entry for `spec`. */\nexport function serverComponent<S, M extends Tagged, P>(\n tag: string,\n spec: ComponentSpec<S, M, P>,\n): ServerComponent {\n const table = (spec.props ?? {}) as PropTable;\n const reducers = (spec.update ?? {}) as unknown as Reducers<S>;\n const declared = new Set((spec.stores ?? []).map((store: AnyStore) => store.name));\n const reader =\n (scope: unknown) =>\n <T>(store: StoreRef<T>): T => {\n if (!declared.has(store.name)) {\n throw new Error(`<${tag}> uses store \"${store.name}\" without declaring it in spec.stores.`);\n }\n const any = store as unknown as AnyStore;\n const registry = scope instanceof StoreRegistry ? scope : serverScopeFor(tag, any);\n return registry.get(any).state as T; // Sound: the ref carries this store's state type.\n };\n /**\n * The rendering of a component that threw (ADR 0024): its error view (or nothing, also when\n * the error view throws), no seed, and the GyralError the renderer reports.\n */\n const failed = (phase: ErrorPhase, cause: unknown, state: S | undefined): ServerRendering => {\n const error = new GyralError(phase, message(78, tag), cause, tag);\n let view: ServerRendering['view'] = nothing;\n try {\n if (spec.error !== undefined) view = spec.error(error, state);\n } catch {\n view = nothing; // the error view failed too: the host stays empty\n }\n return { view, seed: { props: {} }, failed: error };\n };\n return {\n tag,\n light: isLight(spec),\n delegatesFocus: typeof spec.shadow === 'object' && spec.shadow.delegatesFocus === true,\n styles: isLight(spec) ? [] : styleTexts(spec.styles),\n hydrate: spec.hydrate ?? 'load',\n render(input): ServerRendering {\n const { values, carried } = propsFrom(tag, table, input);\n const missing = missingRequired(values, table);\n if (missing.length > 0) {\n console.warn(`<${tag}> is missing required prop(s): ${missing.join(', ')}.`);\n }\n const props = readProps(values, table) as P; // Sound: exactly the declared props.\n const ctx = { props, read: reader(input.scope) } as Ctx<object>;\n let initial: S;\n let state: S;\n try {\n [initial] = splitNext(runInit(spec, props));\n state = initial;\n for (const msg of (input.initialMessages ?? []) as Tagged[]) {\n const reducer = reducers[msg._tag];\n if (reducer !== undefined) [state] = splitNext(reducer(state, msg, ctx));\n }\n } catch (cause) {\n return failed('init', cause, undefined);\n }\n try {\n return {\n view: spec.view(state, intentNames as IntentNames<string>, ctx as Ctx<P>),\n seed: makeSeed(tag, state, initial, carried),\n };\n } catch (cause) {\n return failed('view', cause, state);\n }\n },\n fallback: (cause) => failed('view', cause, undefined),\n };\n}\n\n/**\n * Registers every spec define() recorded outside the browser (and not registered yet) in\n * view/'s server registry. `@gyral/core/internal/server` calls it before each render; client code never\n * imports this module.\n */\nexport function registerRecordedSpecs(): void {\n for (const [tag, spec] of recordedSpecs()) {\n if (registered(tag) !== undefined) continue;\n // Sound: define() recorded exactly this tag's ComponentSpec.\n registerServerComponent(serverComponent(tag, spec as ComponentSpec<unknown, Tagged, object>));\n }\n}\n"]}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ChildValue } from './view/index.js';
|
|
2
|
-
import { styleHash, styleHashSync, type ServerRenderOptions } from './view/server/index.js';
|
|
3
|
-
export type { ServerRenderOptions };
|
|
2
|
+
import { styleHash, styleHashSync, type ServerRenderOptions, type StyleValues } from './view/server/index.js';
|
|
3
|
+
export type { ServerRenderOptions, StyleValues };
|
|
4
4
|
export { styleHash, styleHashSync };
|
|
5
5
|
/**
|
|
6
6
|
* Whether `@gyral/core` resolved with the `development` condition (Vite's dev server and its
|
|
@@ -18,7 +18,7 @@ export declare function render(value: ChildValue, options?: ServerRenderOptions)
|
|
|
18
18
|
export declare function renderToString(value: ChildValue, options?: ServerRenderOptions): string;
|
|
19
19
|
/**
|
|
20
20
|
* `'sha256-…'` hashes of every registered shadow component's declarative-shadow-root `<style>`,
|
|
21
|
-
* for a `Content-Security-Policy` `style-src
|
|
21
|
+
* for a `Content-Security-Policy` `style-src`.
|
|
22
22
|
*/
|
|
23
23
|
export declare function styleHashes(): Promise<readonly string[]>;
|
|
24
24
|
/**
|
|
@@ -26,3 +26,9 @@ export declare function styleHashes(): Promise<readonly string[]>;
|
|
|
26
26
|
* (recorded specs registered first), for checking or building a CSP at render time.
|
|
27
27
|
*/
|
|
28
28
|
export declare function componentStyles(): ReadonlyMap<string, string>;
|
|
29
|
+
/**
|
|
30
|
+
* A number that changes whenever a component registers with the server renderer (recorded
|
|
31
|
+
* specs registered first), so its CSS, and the `<style>` hashes a CSP lists, may have changed.
|
|
32
|
+
* Caches built from `componentStyles()` key on it.
|
|
33
|
+
*/
|
|
34
|
+
export declare function registryVersion(): number;
|
package/dist/server.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
// `@gyral/core/server` (docs/design-docs/view/06-server.md): renders template results and Gyral
|
|
1
|
+
// `@gyral/core/internal/server` (docs/design-docs/view/06-server.md): renders template results and Gyral
|
|
2
2
|
// components to HTML without a DOM. Server-only: never import it from client code. Every
|
|
3
3
|
// render first registers the specs define() recorded outside the browser, and the
|
|
4
4
|
// `<gyral-stores>` provider.
|
|
5
5
|
import { registerRecordedSpecs } from './server-component.js';
|
|
6
6
|
import { storesProvider } from './stores-provider.js';
|
|
7
|
-
import { DEV, registerServerProvider } from './view/index.js';
|
|
7
|
+
import { DEV, registerServerProvider, serverRegistryVersion, } from './view/index.js';
|
|
8
8
|
import { componentStyles as styles, render as renderChunks, renderToString as renderString, styleHash, styleHashes as hashes, styleHashSync, } from './view/server/index.js';
|
|
9
9
|
export { styleHash, styleHashSync };
|
|
10
10
|
/**
|
|
@@ -33,7 +33,7 @@ export function renderToString(value, options) {
|
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
35
|
* `'sha256-…'` hashes of every registered shadow component's declarative-shadow-root `<style>`,
|
|
36
|
-
* for a `Content-Security-Policy` `style-src
|
|
36
|
+
* for a `Content-Security-Policy` `style-src`.
|
|
37
37
|
*/
|
|
38
38
|
export function styleHashes() {
|
|
39
39
|
prepare();
|
|
@@ -47,4 +47,13 @@ export function componentStyles() {
|
|
|
47
47
|
prepare();
|
|
48
48
|
return styles();
|
|
49
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* A number that changes whenever a component registers with the server renderer (recorded
|
|
52
|
+
* specs registered first), so its CSS, and the `<style>` hashes a CSP lists, may have changed.
|
|
53
|
+
* Caches built from `componentStyles()` key on it.
|
|
54
|
+
*/
|
|
55
|
+
export function registryVersion() {
|
|
56
|
+
prepare();
|
|
57
|
+
return serverRegistryVersion();
|
|
58
|
+
}
|
|
50
59
|
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,yGAAyG;AACzG,yFAAyF;AACzF,kFAAkF;AAClF,6BAA6B;AAC7B,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EACL,GAAG,EACH,sBAAsB,EACtB,qBAAqB,GAEtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,eAAe,IAAI,MAAM,EACzB,MAAM,IAAI,YAAY,EACtB,cAAc,IAAI,YAAY,EAC9B,SAAS,EACT,WAAW,IAAI,MAAM,EACrB,aAAa,GAGd,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;AAEpC;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAY,GAAG,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEjE,SAAS,OAAO;IACd,sBAAsB,CAAC,cAAc,CAAC,CAAC;IACvC,qBAAqB,EAAE,CAAC;AAC1B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,KAAiB,EAAE,OAA6B;IACrE,OAAO,EAAE,CAAC;IACV,OAAO,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AACtC,CAAC;AAED,0CAA0C;AAC1C,MAAM,UAAU,cAAc,CAAC,KAAiB,EAAE,OAA6B;IAC7E,OAAO,EAAE,CAAC;IACV,OAAO,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW;IACzB,OAAO,EAAE,CAAC;IACV,OAAO,MAAM,EAAE,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,EAAE,CAAC;IACV,OAAO,MAAM,EAAE,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,EAAE,CAAC;IACV,OAAO,qBAAqB,EAAE,CAAC;AACjC,CAAC","sourcesContent":["// `@gyral/core/internal/server` (docs/design-docs/view/06-server.md): renders template results and Gyral\n// components to HTML without a DOM. Server-only: never import it from client code. Every\n// render first registers the specs define() recorded outside the browser, and the\n// `<gyral-stores>` provider.\nimport { registerRecordedSpecs } from './server-component.js';\nimport { storesProvider } from './stores-provider.js';\nimport {\n DEV,\n registerServerProvider,\n serverRegistryVersion,\n type ChildValue,\n} from './view/index.js';\nimport {\n componentStyles as styles,\n render as renderChunks,\n renderToString as renderString,\n styleHash,\n styleHashes as hashes,\n styleHashSync,\n type ServerRenderOptions,\n type StyleValues,\n} from './view/server/index.js';\n\nexport type { ServerRenderOptions, StyleValues };\nexport { styleHash, styleHashSync };\n\n/**\n * Whether `@gyral/core` resolved with the `development` condition (Vite's dev server and its\n * SSR, Vitest): the default of `render`'s `dev` option (view/06-server.md \"Development markers\").\n */\nexport const development: boolean = DEV;\nexport { StoreRegistry, withStoreScope } from './store-scope.js';\n\nfunction prepare(): void {\n registerServerProvider(storesProvider);\n registerRecordedSpecs();\n}\n\n/**\n * Renders `value` to HTML chunks, synchronously and lazily: each step of the iterator writes up\n * to the next component boundary, running that component's `init` and view. Wrap each step in\n * `withStoreScope(registry, …)` to give components the request's stores (ADR 0013).\n */\nexport function render(value: ChildValue, options?: ServerRenderOptions): Iterable<string> {\n prepare();\n return renderChunks(value, options);\n}\n\n/** Renders `value` to one HTML string. */\nexport function renderToString(value: ChildValue, options?: ServerRenderOptions): string {\n prepare();\n return renderString(value, options);\n}\n\n/**\n * `'sha256-…'` hashes of every registered shadow component's declarative-shadow-root `<style>`,\n * for a `Content-Security-Policy` `style-src`.\n */\nexport function styleHashes(): Promise<readonly string[]> {\n prepare();\n return hashes();\n}\n\n/**\n * Tag → declarative-shadow-root `<style>` text of every registered shadow component with CSS\n * (recorded specs registered first), for checking or building a CSP at render time.\n */\nexport function componentStyles(): ReadonlyMap<string, string> {\n prepare();\n return styles();\n}\n\n/**\n * A number that changes whenever a component registers with the server renderer (recorded\n * specs registered first), so its CSS, and the `<style>` hashes a CSP lists, may have changed.\n * Caches built from `componentStyles()` key on it.\n */\nexport function registryVersion(): number {\n prepare();\n return serverRegistryVersion();\n}\n"]}
|
package/dist/settled.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Resolves once
|
|
3
|
-
* view-transition updates have run,
|
|
4
|
-
*
|
|
2
|
+
* Resolves once the page is quiet: every connected Gyral host has rendered its latest state,
|
|
3
|
+
* view-transition updates have run, focus commands and outputs have been delivered, and
|
|
4
|
+
* messages have stopped arriving (a stream's next value, already on its way in a microtask, is
|
|
5
|
+
* waited for; long-lived commands themselves are not). Rejects with the loop guard's error
|
|
5
6
|
* when rendering never settles in development (components feeding each other).
|
|
6
7
|
*
|
|
7
8
|
* el.send({ _tag: 'Increment' });
|
package/dist/settled.js
CHANGED
|
@@ -1,40 +1,62 @@
|
|
|
1
|
-
// `settled()` (docs/design-docs/view/04-scheduler.md "`settled()`"): wait until
|
|
1
|
+
// `settled()` (docs/design-docs/view/04-scheduler.md "`settled()`"): wait until the page is
|
|
2
2
|
// quiet. Implemented on the global scheduler: no host is dirty, no flush is scheduled, no
|
|
3
|
-
// view-transition update is pending, the post-render queue has run,
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
// view-transition update is pending, the post-render queue has run, outputs sent to parents
|
|
4
|
+
// have been delivered, and no message has reached a host or a store for QUIET_TURNS microtask
|
|
5
|
+
// turns in a row. Commands that are still running (streams that never end, requests waiting
|
|
6
|
+
// for a server) don't count: only the messages they deliver do. Timers are never advanced or
|
|
7
|
+
// waited for. Tests await it before asserting on the DOM.
|
|
8
|
+
import { activityCount, isQuiet, whenQuiet } from './scheduler.js';
|
|
9
|
+
import { message } from './view/index.js';
|
|
9
10
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
11
|
+
* Flushes and busy turns settled() waits through before it gives up. High enough for a finite
|
|
12
|
+
* burst (a progress stream, an async iterable over a list: a few hundred messages in a row),
|
|
13
|
+
* low enough that a stream that never stops, or components feeding each other, still fails
|
|
14
|
+
* fast instead of hanging a test.
|
|
12
15
|
*/
|
|
13
|
-
const
|
|
14
|
-
async function drain() {
|
|
15
|
-
for (let turn = 0; turn < DRAIN_TURNS; turn += 1)
|
|
16
|
-
await Promise.resolve();
|
|
17
|
-
}
|
|
16
|
+
const MAX_ROUNDS = 10_000;
|
|
18
17
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
18
|
+
* Consecutive microtask turns with no message and nothing to render before the page counts as
|
|
19
|
+
* quiet, so follow-ups that are already resolving (a driver that answered at once, a store
|
|
20
|
+
* notifying its subscribers in a microtask, a stream re-arming in one) reach a host first.
|
|
21
|
+
*/
|
|
22
|
+
const QUIET_TURNS = 8;
|
|
23
|
+
const cycle = () => new Error(message(34, MAX_ROUNDS));
|
|
24
|
+
/**
|
|
25
|
+
* Resolves once the page is quiet: every connected Gyral host has rendered its latest state,
|
|
26
|
+
* view-transition updates have run, focus commands and outputs have been delivered, and
|
|
27
|
+
* messages have stopped arriving (a stream's next value, already on its way in a microtask, is
|
|
28
|
+
* waited for; long-lived commands themselves are not). Rejects with the loop guard's error
|
|
22
29
|
* when rendering never settles in development (components feeding each other).
|
|
23
30
|
*
|
|
24
31
|
* el.send({ _tag: 'Increment' });
|
|
25
32
|
* await settled();
|
|
26
33
|
*/
|
|
27
34
|
export async function settled() {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
let rounds = 0;
|
|
36
|
+
let quietTurns = 0;
|
|
37
|
+
let seen = activityCount();
|
|
38
|
+
for (;;) {
|
|
39
|
+
if (!isQuiet()) {
|
|
40
|
+
// Ask for the flush's promise before it runs, so its outcome (a loop-guard error) reaches us.
|
|
41
|
+
if (++rounds > MAX_ROUNDS)
|
|
42
|
+
throw cycle();
|
|
43
|
+
await whenQuiet();
|
|
44
|
+
quietTurns = 0;
|
|
45
|
+
seen = activityCount();
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
await Promise.resolve();
|
|
49
|
+
const now = activityCount();
|
|
50
|
+
if (now !== seen) {
|
|
51
|
+
// A message arrived (its host may already have rendered): start the quiet window again.
|
|
52
|
+
if (++rounds > MAX_ROUNDS)
|
|
53
|
+
throw cycle();
|
|
54
|
+
seen = now;
|
|
55
|
+
quietTurns = 0;
|
|
56
|
+
}
|
|
57
|
+
else if (isQuiet() && ++quietTurns >= QUIET_TURNS) {
|
|
35
58
|
return;
|
|
59
|
+
}
|
|
36
60
|
}
|
|
37
|
-
throw new Error(`settled(): rendering did not settle after ${String(MAX_ROUNDS)} flushes. ` +
|
|
38
|
-
'Components are probably feeding each other props or messages in a cycle.');
|
|
39
61
|
}
|
|
40
62
|
//# sourceMappingURL=settled.js.map
|
package/dist/settled.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settled.js","sourceRoot":"","sources":["../src/settled.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"settled.js","sourceRoot":"","sources":["../src/settled.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,0FAA0F;AAC1F,4FAA4F;AAC5F,8FAA8F;AAC9F,4FAA4F;AAC5F,6FAA6F;AAC7F,0DAA0D;AAC1D,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C;;;;;GAKG;AACH,MAAM,UAAU,GAAG,MAAM,CAAC;AAE1B;;;;GAIG;AACH,MAAM,WAAW,GAAG,CAAC,CAAC;AAEtB,MAAM,KAAK,GAAG,GAAU,EAAE,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC;AAE9D;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO;IAC3B,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,IAAI,GAAG,aAAa,EAAE,CAAC;IAC3B,SAAS,CAAC;QACR,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YACf,8FAA8F;YAC9F,IAAI,EAAE,MAAM,GAAG,UAAU;gBAAE,MAAM,KAAK,EAAE,CAAC;YACzC,MAAM,SAAS,EAAE,CAAC;YAClB,UAAU,GAAG,CAAC,CAAC;YACf,IAAI,GAAG,aAAa,EAAE,CAAC;YACvB,SAAS;QACX,CAAC;QACD,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;QAC5B,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,wFAAwF;YACxF,IAAI,EAAE,MAAM,GAAG,UAAU;gBAAE,MAAM,KAAK,EAAE,CAAC;YACzC,IAAI,GAAG,GAAG,CAAC;YACX,UAAU,GAAG,CAAC,CAAC;QACjB,CAAC;aAAM,IAAI,OAAO,EAAE,IAAI,EAAE,UAAU,IAAI,WAAW,EAAE,CAAC;YACpD,OAAO;QACT,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["// `settled()` (docs/design-docs/view/04-scheduler.md \"`settled()`\"): wait until the page is\n// quiet. Implemented on the global scheduler: no host is dirty, no flush is scheduled, no\n// view-transition update is pending, the post-render queue has run, outputs sent to parents\n// have been delivered, and no message has reached a host or a store for QUIET_TURNS microtask\n// turns in a row. Commands that are still running (streams that never end, requests waiting\n// for a server) don't count: only the messages they deliver do. Timers are never advanced or\n// waited for. Tests await it before asserting on the DOM.\nimport { activityCount, isQuiet, whenQuiet } from './scheduler.js';\nimport { message } from './view/index.js';\n\n/**\n * Flushes and busy turns settled() waits through before it gives up. High enough for a finite\n * burst (a progress stream, an async iterable over a list: a few hundred messages in a row),\n * low enough that a stream that never stops, or components feeding each other, still fails\n * fast instead of hanging a test.\n */\nconst MAX_ROUNDS = 10_000;\n\n/**\n * Consecutive microtask turns with no message and nothing to render before the page counts as\n * quiet, so follow-ups that are already resolving (a driver that answered at once, a store\n * notifying its subscribers in a microtask, a stream re-arming in one) reach a host first.\n */\nconst QUIET_TURNS = 8;\n\nconst cycle = (): Error => new Error(message(34, MAX_ROUNDS));\n\n/**\n * Resolves once the page is quiet: every connected Gyral host has rendered its latest state,\n * view-transition updates have run, focus commands and outputs have been delivered, and\n * messages have stopped arriving (a stream's next value, already on its way in a microtask, is\n * waited for; long-lived commands themselves are not). Rejects with the loop guard's error\n * when rendering never settles in development (components feeding each other).\n *\n * el.send({ _tag: 'Increment' });\n * await settled();\n */\nexport async function settled(): Promise<void> {\n let rounds = 0;\n let quietTurns = 0;\n let seen = activityCount();\n for (;;) {\n if (!isQuiet()) {\n // Ask for the flush's promise before it runs, so its outcome (a loop-guard error) reaches us.\n if (++rounds > MAX_ROUNDS) throw cycle();\n await whenQuiet();\n quietTurns = 0;\n seen = activityCount();\n continue;\n }\n await Promise.resolve();\n const now = activityCount();\n if (now !== seen) {\n // A message arrived (its host may already have rendered): start the quiet window again.\n if (++rounds > MAX_ROUNDS) throw cycle();\n seen = now;\n quietTurns = 0;\n } else if (isQuiet() && ++quietTurns >= QUIET_TURNS) {\n return;\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type * as Full from './spec-features.js';
|
|
2
|
+
export declare let viewTransitions: typeof Full.viewTransitions;
|
|
3
|
+
export declare let frameLane: typeof Full.frameLane;
|
|
4
|
+
export declare let customStates: typeof Full.customStates;
|
|
5
|
+
export declare let formAssociation: typeof Full.formAssociation;
|
|
6
|
+
export declare let subscriptions: typeof Full.subscriptions;
|
|
7
|
+
export declare let errorView: typeof Full.errorView;
|
|
8
|
+
export declare let errored: typeof Full.errored;
|
|
9
|
+
export declare const useViewTransitions: (run: Full.ViewTransitions) => void;
|
|
10
|
+
export declare const useFrameLane: (lane: import("./frame-lane.js").FrameLane) => void;
|
|
11
|
+
export declare const useCustomStates: (sync: Full.CustomStates) => void;
|
|
12
|
+
export declare const useFormAssociation: (make: {
|
|
13
|
+
create<S, P>(host: HTMLElement, model: Pick<import("./host-model.js").HostModel<unknown, unknown>, "hasReducer" | "dispatch">, projection: import("./form-associated.js").FormAssociation<S, P> | undefined): void;
|
|
14
|
+
sync(host: HTMLElement, state: unknown, ctx: import("./types.js").Ctx<unknown>, root: ParentNode): void;
|
|
15
|
+
install: (Element: CustomElementConstructor, enabled: boolean) => void;
|
|
16
|
+
}) => void;
|
|
17
|
+
export declare const useSubscriptions: (make: typeof import("./subscriptions.js").subscriptionSet) => void;
|
|
18
|
+
export declare const useErrorView: (view: typeof import("./error-view.js").renderErrorView) => void;
|
|
19
|
+
export declare const useErrored: (send: typeof import("./error-view.js").sendErrored) => void;
|
|
20
|
+
/** Development: a spec field whose machinery the build left out (define(), element.ts). */
|
|
21
|
+
export declare const checkSpecFeatures: (tag: string, spec: object) => void;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { DEV } from './view/index.js';
|
|
2
|
+
export let viewTransitions;
|
|
3
|
+
export let frameLane;
|
|
4
|
+
export let customStates;
|
|
5
|
+
export let formAssociation;
|
|
6
|
+
export let subscriptions;
|
|
7
|
+
export let errorView;
|
|
8
|
+
export let errored;
|
|
9
|
+
export const useViewTransitions = ((run) => {
|
|
10
|
+
viewTransitions = run;
|
|
11
|
+
});
|
|
12
|
+
export const useFrameLane = ((lane) => {
|
|
13
|
+
frameLane = lane;
|
|
14
|
+
});
|
|
15
|
+
export const useCustomStates = ((sync) => {
|
|
16
|
+
customStates = sync;
|
|
17
|
+
});
|
|
18
|
+
export const useFormAssociation = ((make) => {
|
|
19
|
+
formAssociation = make;
|
|
20
|
+
});
|
|
21
|
+
export const useSubscriptions = ((make) => {
|
|
22
|
+
subscriptions = make;
|
|
23
|
+
});
|
|
24
|
+
export const useErrorView = ((view) => {
|
|
25
|
+
errorView = view;
|
|
26
|
+
});
|
|
27
|
+
export const useErrored = ((send) => {
|
|
28
|
+
errored = send;
|
|
29
|
+
});
|
|
30
|
+
/** Development: a spec field whose machinery the build left out (define(), element.ts). */
|
|
31
|
+
export const checkSpecFeatures = ((tag, spec) => {
|
|
32
|
+
if (!DEV)
|
|
33
|
+
return;
|
|
34
|
+
const slots = {
|
|
35
|
+
viewTransition: viewTransitions,
|
|
36
|
+
renderOnFrame: frameLane,
|
|
37
|
+
states: customStates,
|
|
38
|
+
formAssociated: formAssociation,
|
|
39
|
+
subscriptions,
|
|
40
|
+
error: errorView,
|
|
41
|
+
};
|
|
42
|
+
for (const [field, slot] of Object.entries(slots)) {
|
|
43
|
+
if (!(field in spec) || slot !== undefined)
|
|
44
|
+
continue;
|
|
45
|
+
console.warn(`gyral: <${tag}> declares ${field}, but the build found no module naming it, so its ` +
|
|
46
|
+
`code was left out and the component renders without it. Write the field name in your ` +
|
|
47
|
+
`source (view/05-element.md "Features register themselves").`);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=spec-features-used.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-features-used.js","sourceRoot":"","sources":["../src/spec-features-used.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAEtC,MAAM,CAAC,IAAI,eAA4C,CAAC;AACxD,MAAM,CAAC,IAAI,SAAgC,CAAC;AAC5C,MAAM,CAAC,IAAI,YAAsC,CAAC;AAClD,MAAM,CAAC,IAAI,eAA4C,CAAC;AACxD,MAAM,CAAC,IAAI,aAAwC,CAAC;AACpD,MAAM,CAAC,IAAI,SAAgC,CAAC;AAC5C,MAAM,CAAC,IAAI,OAA4B,CAAC;AAExC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;IACzC,eAAe,GAAG,GAAG,CAAC;AACxB,CAAC,CAA0C,CAAC;AAC5C,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;IACpC,SAAS,GAAG,IAAI,CAAC;AACnB,CAAC,CAAoC,CAAC;AACtC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;IACvC,YAAY,GAAG,IAAI,CAAC;AACtB,CAAC,CAAuC,CAAC;AACzC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;IAC1C,eAAe,GAAG,IAAI,CAAC;AACzB,CAAC,CAA0C,CAAC;AAC5C,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;IACxC,aAAa,GAAG,IAAI,CAAC;AACvB,CAAC,CAAwC,CAAC;AAC1C,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;IACpC,SAAS,GAAG,IAAI,CAAC;AACnB,CAAC,CAAoC,CAAC;AACtC,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;IAClC,OAAO,GAAG,IAAI,CAAC;AACjB,CAAC,CAAkC,CAAC;AAEpC,2FAA2F;AAC3F,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,GAAW,EAAE,IAAY,EAAQ,EAAE;IACpE,IAAI,CAAC,GAAG;QAAE,OAAO;IACjB,MAAM,KAAK,GAA4B;QACrC,cAAc,EAAE,eAAe;QAC/B,aAAa,EAAE,SAAS;QACxB,MAAM,EAAE,YAAY;QACpB,cAAc,EAAE,eAAe;QAC/B,aAAa;QACb,KAAK,EAAE,SAAS;KACjB,CAAC;IACF,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAClD,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QACrD,OAAO,CAAC,IAAI,CACV,WAAW,GAAG,cAAc,KAAK,oDAAoD;YACnF,uFAAuF;YACvF,6DAA6D,CAChE,CAAC;IACJ,CAAC;AACH,CAAC,CAAyC,CAAC","sourcesContent":["// `#spec-features` in builds with the Vite preset (the `gyral-compiled` condition, gyral-c5d.12):\n// the same exports as spec-features.ts, as slots. The build fills a slot (use-*.ts) when some\n// module it transforms names the spec field (compiler/features.ts), so apps without view\n// transitions, the frame lane or custom states don't bundle them. An unfilled slot degrades as\n// the platform would (ADR 0003 tier 1): no transition, the microtask lane, no custom states.\n// That happens only when a field's name is built at run time; development builds warn.\nimport type * as Full from './spec-features.js';\nimport { DEV } from './view/index.js';\n\nexport let viewTransitions: typeof Full.viewTransitions;\nexport let frameLane: typeof Full.frameLane;\nexport let customStates: typeof Full.customStates;\nexport let formAssociation: typeof Full.formAssociation;\nexport let subscriptions: typeof Full.subscriptions;\nexport let errorView: typeof Full.errorView;\nexport let errored: typeof Full.errored;\n\nexport const useViewTransitions = ((run) => {\n viewTransitions = run;\n}) satisfies typeof Full.useViewTransitions;\nexport const useFrameLane = ((lane) => {\n frameLane = lane;\n}) satisfies typeof Full.useFrameLane;\nexport const useCustomStates = ((sync) => {\n customStates = sync;\n}) satisfies typeof Full.useCustomStates;\nexport const useFormAssociation = ((make) => {\n formAssociation = make;\n}) satisfies typeof Full.useFormAssociation;\nexport const useSubscriptions = ((make) => {\n subscriptions = make;\n}) satisfies typeof Full.useSubscriptions;\nexport const useErrorView = ((view) => {\n errorView = view;\n}) satisfies typeof Full.useErrorView;\nexport const useErrored = ((send) => {\n errored = send;\n}) satisfies typeof Full.useErrored;\n\n/** Development: a spec field whose machinery the build left out (define(), element.ts). */\nexport const checkSpecFeatures = ((tag: string, spec: object): void => {\n if (!DEV) return;\n const slots: Record<string, unknown> = {\n viewTransition: viewTransitions,\n renderOnFrame: frameLane,\n states: customStates,\n formAssociated: formAssociation,\n subscriptions,\n error: errorView,\n };\n for (const [field, slot] of Object.entries(slots)) {\n if (!(field in spec) || slot !== undefined) continue;\n console.warn(\n `gyral: <${tag}> declares ${field}, but the build found no module naming it, so its ` +\n `code was left out and the component renders without it. Write the field name in your ` +\n `source (view/05-element.md \"Features register themselves\").`,\n );\n }\n}) satisfies typeof Full.checkSpecFeatures;\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type FrameLane } from './frame-lane.js';
|
|
2
|
+
import { formFeature } from './form-associated.js';
|
|
3
|
+
import { renderErrorView, sendErrored } from './error-view.js';
|
|
4
|
+
import { subscriptionSet } from './subscriptions.js';
|
|
5
|
+
/** Runs a flush inside a view transition (true), or declines (false: run it plainly). */
|
|
6
|
+
export type ViewTransitions = (update: () => void) => boolean;
|
|
7
|
+
/** Writes a host's boolean states to its CustomStateSet. */
|
|
8
|
+
export type CustomStates = (el: HTMLElement, states: Readonly<Record<string, boolean>>) => void;
|
|
9
|
+
export declare const viewTransitions: ViewTransitions | undefined;
|
|
10
|
+
export declare const frameLane: FrameLane | undefined;
|
|
11
|
+
export declare const customStates: CustomStates | undefined;
|
|
12
|
+
export declare const formAssociation: typeof formFeature | undefined;
|
|
13
|
+
/** Makes a host's subscription set (`subscriptions`, ADR 0025). */
|
|
14
|
+
export declare const subscriptions: typeof subscriptionSet | undefined;
|
|
15
|
+
/** Renders a component's `error` view (ADR 0024). */
|
|
16
|
+
export declare const errorView: typeof renderErrorView | undefined;
|
|
17
|
+
/** Sends `Errored` to a component that handles it (ADR 0024). */
|
|
18
|
+
export declare const errored: typeof sendErrored | undefined;
|
|
19
|
+
/** Registrations (use-*.ts) are for compiled builds; here everything is present. */
|
|
20
|
+
export declare const useViewTransitions: (run: ViewTransitions) => void;
|
|
21
|
+
export declare const useFrameLane: (lane: FrameLane) => void;
|
|
22
|
+
export declare const useCustomStates: (sync: CustomStates) => void;
|
|
23
|
+
export declare const useFormAssociation: (make: typeof formFeature) => void;
|
|
24
|
+
export declare const useSubscriptions: (make: typeof subscriptionSet) => void;
|
|
25
|
+
export declare const useErrorView: (view: typeof renderErrorView) => void;
|
|
26
|
+
export declare const useErrored: (send: typeof sendErrored) => void;
|
|
27
|
+
/** Development check for compiled builds (spec-features-used.ts); nothing to check here. */
|
|
28
|
+
export declare const checkSpecFeatures: (tag: string, spec: object) => void;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Optional machinery that apps reach through spec fields rather than an API call (view/05
|
|
2
|
+
// "Features register themselves", gyral-c5d.12): view transitions (`viewTransition`), the frame
|
|
3
|
+
// lane (`renderOnFrame`), custom states (`states`), subscriptions (`subscriptions`) and the error
|
|
4
|
+
// fallback (`error`, and the `Errored` message); and
|
|
5
|
+
// through markup: the dialog and popover bindings (`?modal`, `?popover-open`); and through a
|
|
6
|
+
// hook spec key: hook disposal (`dispose`). Core's
|
|
7
|
+
// `#spec-features` resolves here by
|
|
8
|
+
// default (the runtime path: no build step), so everything is present. Builds with the Vite
|
|
9
|
+
// preset (the `gyral-compiled` condition) resolve spec-features-used.ts instead, whose slots
|
|
10
|
+
// the build fills only for the fields some module names (use-*.ts, compiler/features.ts).
|
|
11
|
+
import { frameLane as lane } from './frame-lane.js';
|
|
12
|
+
import { syncStates } from './states.js';
|
|
13
|
+
import { formFeature } from './form-associated.js';
|
|
14
|
+
import { renderErrorView, sendErrored } from './error-view.js';
|
|
15
|
+
import { subscriptionSet } from './subscriptions.js';
|
|
16
|
+
import { startTransition } from './transitions.js';
|
|
17
|
+
import { applyToggle, commitTracked, useDisposableHooks, useToggles } from './view/index.js';
|
|
18
|
+
// `?modal`/`?popover-open` (view/02 "Dialogs and popovers"): present without a build step.
|
|
19
|
+
useToggles(applyToggle);
|
|
20
|
+
// Hooks with `dispose` (view/02 "Widgets with a lifecycle"): present without a build step.
|
|
21
|
+
useDisposableHooks(commitTracked);
|
|
22
|
+
export const viewTransitions = startTransition;
|
|
23
|
+
export const frameLane = lane;
|
|
24
|
+
export const customStates = syncStates;
|
|
25
|
+
export const formAssociation = formFeature;
|
|
26
|
+
/** Makes a host's subscription set (`subscriptions`, ADR 0025). */
|
|
27
|
+
export const subscriptions = subscriptionSet;
|
|
28
|
+
/** Renders a component's `error` view (ADR 0024). */
|
|
29
|
+
export const errorView = renderErrorView;
|
|
30
|
+
/** Sends `Errored` to a component that handles it (ADR 0024). */
|
|
31
|
+
export const errored = sendErrored;
|
|
32
|
+
/** Registrations (use-*.ts) are for compiled builds; here everything is present. */
|
|
33
|
+
export const useViewTransitions = () => undefined;
|
|
34
|
+
export const useFrameLane = () => undefined;
|
|
35
|
+
export const useCustomStates = () => undefined;
|
|
36
|
+
export const useFormAssociation = () => undefined;
|
|
37
|
+
export const useSubscriptions = () => undefined;
|
|
38
|
+
export const useErrorView = () => undefined;
|
|
39
|
+
export const useErrored = () => undefined;
|
|
40
|
+
/** Development check for compiled builds (spec-features-used.ts); nothing to check here. */
|
|
41
|
+
export const checkSpecFeatures = () => undefined;
|
|
42
|
+
//# sourceMappingURL=spec-features.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-features.js","sourceRoot":"","sources":["../src/spec-features.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,gGAAgG;AAChG,kGAAkG;AAClG,qDAAqD;AACrD,6FAA6F;AAC7F,mDAAmD;AACnD,oCAAoC;AACpC,4FAA4F;AAC5F,6FAA6F;AAC7F,0FAA0F;AAC1F,OAAO,EAAE,SAAS,IAAI,IAAI,EAAkB,MAAM,iBAAiB,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7F,2FAA2F;AAC3F,UAAU,CAAC,WAAW,CAAC,CAAC;AACxB,2FAA2F;AAC3F,kBAAkB,CAAC,aAAa,CAAC,CAAC;AAOlC,MAAM,CAAC,MAAM,eAAe,GAAgC,eAAe,CAAC;AAC5E,MAAM,CAAC,MAAM,SAAS,GAA0B,IAAI,CAAC;AACrD,MAAM,CAAC,MAAM,YAAY,GAA6B,UAAU,CAAC;AACjE,MAAM,CAAC,MAAM,eAAe,GAAmC,WAAW,CAAC;AAC3E,mEAAmE;AACnE,MAAM,CAAC,MAAM,aAAa,GAAuC,eAAe,CAAC;AACjF,qDAAqD;AACrD,MAAM,CAAC,MAAM,SAAS,GAAuC,eAAe,CAAC;AAC7E,iEAAiE;AACjE,MAAM,CAAC,MAAM,OAAO,GAAmC,WAAW,CAAC;AAEnE,oFAAoF;AACpF,MAAM,CAAC,MAAM,kBAAkB,GAAmC,GAAG,EAAE,CAAC,SAAS,CAAC;AAClF,MAAM,CAAC,MAAM,YAAY,GAA8B,GAAG,EAAE,CAAC,SAAS,CAAC;AACvE,MAAM,CAAC,MAAM,eAAe,GAAiC,GAAG,EAAE,CAAC,SAAS,CAAC;AAC7E,MAAM,CAAC,MAAM,kBAAkB,GAAuC,GAAG,EAAE,CAAC,SAAS,CAAC;AACtF,MAAM,CAAC,MAAM,gBAAgB,GAA2C,GAAG,EAAE,CAAC,SAAS,CAAC;AACxF,MAAM,CAAC,MAAM,YAAY,GAA2C,GAAG,EAAE,CAAC,SAAS,CAAC;AACpF,MAAM,CAAC,MAAM,UAAU,GAAuC,GAAG,EAAE,CAAC,SAAS,CAAC;AAE9E,4FAA4F;AAC5F,MAAM,CAAC,MAAM,iBAAiB,GAAwC,GAAG,EAAE,CAAC,SAAS,CAAC","sourcesContent":["// Optional machinery that apps reach through spec fields rather than an API call (view/05\n// \"Features register themselves\", gyral-c5d.12): view transitions (`viewTransition`), the frame\n// lane (`renderOnFrame`), custom states (`states`), subscriptions (`subscriptions`) and the error\n// fallback (`error`, and the `Errored` message); and\n// through markup: the dialog and popover bindings (`?modal`, `?popover-open`); and through a\n// hook spec key: hook disposal (`dispose`). Core's\n// `#spec-features` resolves here by\n// default (the runtime path: no build step), so everything is present. Builds with the Vite\n// preset (the `gyral-compiled` condition) resolve spec-features-used.ts instead, whose slots\n// the build fills only for the fields some module names (use-*.ts, compiler/features.ts).\nimport { frameLane as lane, type FrameLane } from './frame-lane.js';\nimport { syncStates } from './states.js';\nimport { formFeature } from './form-associated.js';\nimport { renderErrorView, sendErrored } from './error-view.js';\nimport { subscriptionSet } from './subscriptions.js';\nimport { startTransition } from './transitions.js';\nimport { applyToggle, commitTracked, useDisposableHooks, useToggles } from './view/index.js';\n\n// `?modal`/`?popover-open` (view/02 \"Dialogs and popovers\"): present without a build step.\nuseToggles(applyToggle);\n// Hooks with `dispose` (view/02 \"Widgets with a lifecycle\"): present without a build step.\nuseDisposableHooks(commitTracked);\n\n/** Runs a flush inside a view transition (true), or declines (false: run it plainly). */\nexport type ViewTransitions = (update: () => void) => boolean;\n/** Writes a host's boolean states to its CustomStateSet. */\nexport type CustomStates = (el: HTMLElement, states: Readonly<Record<string, boolean>>) => void;\n\nexport const viewTransitions: ViewTransitions | undefined = startTransition;\nexport const frameLane: FrameLane | undefined = lane;\nexport const customStates: CustomStates | undefined = syncStates;\nexport const formAssociation: typeof formFeature | undefined = formFeature;\n/** Makes a host's subscription set (`subscriptions`, ADR 0025). */\nexport const subscriptions: typeof subscriptionSet | undefined = subscriptionSet;\n/** Renders a component's `error` view (ADR 0024). */\nexport const errorView: typeof renderErrorView | undefined = renderErrorView;\n/** Sends `Errored` to a component that handles it (ADR 0024). */\nexport const errored: typeof sendErrored | undefined = sendErrored;\n\n/** Registrations (use-*.ts) are for compiled builds; here everything is present. */\nexport const useViewTransitions: (run: ViewTransitions) => void = () => undefined;\nexport const useFrameLane: (lane: FrameLane) => void = () => undefined;\nexport const useCustomStates: (sync: CustomStates) => void = () => undefined;\nexport const useFormAssociation: (make: typeof formFeature) => void = () => undefined;\nexport const useSubscriptions: (make: typeof subscriptionSet) => void = () => undefined;\nexport const useErrorView: (view: typeof renderErrorView) => void = () => undefined;\nexport const useErrored: (send: typeof sendErrored) => void = () => undefined;\n\n/** Development check for compiled builds (spec-features-used.ts); nothing to check here. */\nexport const checkSpecFeatures: (tag: string, spec: object) => void = () => undefined;\n"]}
|
package/dist/states.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
/** Writes a component's boolean states to its CustomStateSet. */
|
|
2
|
-
export type StateSync = (states: Readonly<Record<string, boolean>>) => void;
|
|
3
1
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Mirrors a component's boolean states onto its CustomStateSet. ElementInternals is attached
|
|
3
|
+
* lazily, once per element, by the first sync (view/05-element.md "ElementInternals").
|
|
6
4
|
*/
|
|
7
|
-
export declare function
|
|
5
|
+
export declare function syncStates(el: HTMLElement, states: Readonly<Record<string, boolean>>): void;
|