@gyral/core 0.2.0 → 0.3.1
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 +129 -0
- package/NOTICE +19 -0
- package/README.md +35 -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 +30 -5
- package/dist/children.js +26 -4
- 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 +31 -11
- package/dist/command.js.map +1 -1
- package/dist/compiler/ast.d.ts +23 -0
- package/dist/compiler/ast.js +149 -0
- package/dist/compiler/ast.js.map +1 -0
- package/dist/compiler/compile.d.ts +41 -0
- package/dist/compiler/compile.js +148 -0
- package/dist/compiler/compile.js.map +1 -0
- 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 +182 -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 +22 -0
- package/dist/compiler/hooks.js +241 -0
- package/dist/compiler/hooks.js.map +1 -0
- 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 +78 -0
- package/dist/compiler/locate.js.map +1 -0
- package/dist/compiler/parse5-check.d.ts +21 -0
- package/dist/compiler/parse5-check.js +60 -0
- package/dist/compiler/parse5-check.js.map +1 -0
- 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 +41 -0
- package/dist/compiler/scan.js +160 -0
- package/dist/compiler/scan.js.map +1 -0
- 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/source.d.ts +34 -0
- package/dist/compiler/source.js +114 -0
- package/dist/compiler/source.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 +13 -4
- package/dist/define.js +35 -331
- package/dist/define.js.map +1 -1
- package/dist/devtools-events.d.ts +13 -0
- package/dist/devtools-events.js.map +1 -1
- package/dist/devtools-off.d.ts +2 -0
- package/dist/devtools-off.js +2 -0
- package/dist/devtools-off.js.map +1 -1
- package/dist/devtools.d.ts +4 -0
- package/dist/devtools.js +17 -2
- package/dist/devtools.js.map +1 -1
- package/dist/drivers-scope.d.ts +1 -1
- package/dist/drivers-scope.js +1 -8
- 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 +11 -5
- package/dist/element-types.js.map +1 -1
- package/dist/element.d.ts +3 -0
- package/dist/element.js +322 -0
- package/dist/element.js.map +1 -0
- 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 +26 -0
- package/dist/eslint/imports.js +78 -0
- package/dist/eslint/imports.js.map +1 -0
- package/dist/eslint/index.d.ts +16 -0
- package/dist/eslint/index.js +23 -0
- package/dist/eslint/index.js.map +1 -0
- package/dist/eslint/locate.d.ts +33 -0
- package/dist/eslint/locate.js +132 -0
- package/dist/eslint/locate.js.map +1 -0
- package/dist/eslint/row-purity-rule.d.ts +2 -0
- package/dist/eslint/row-purity-rule.js +103 -0
- package/dist/eslint/row-purity-rule.js.map +1 -0
- package/dist/eslint/template-rule.d.ts +6 -0
- package/dist/eslint/template-rule.js +76 -0
- package/dist/eslint/template-rule.js.map +1 -0
- 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 +39 -0
- package/dist/features.js +2 -0
- package/dist/features.js.map +1 -0
- package/dist/focus.d.ts +13 -12
- package/dist/focus.js +44 -11
- 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/hooks/invalid.d.ts +14 -0
- package/dist/hooks/invalid.js +72 -0
- package/dist/hooks/invalid.js.map +1 -0
- package/dist/host-model.d.ts +77 -0
- package/dist/host-model.js +278 -0
- package/dist/host-model.js.map +1 -0
- package/dist/hydration-client.d.ts +9 -0
- package/dist/hydration-client.js +35 -0
- package/dist/hydration-client.js.map +1 -0
- 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 +3 -21
- package/dist/hydration.js +14 -63
- package/dist/hydration.js.map +1 -1
- package/dist/index.d.ts +24 -36
- package/dist/index.js +14 -32
- 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 +62 -17
- package/dist/intent.js +193 -100
- 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 +15 -1
- package/dist/internal/interpreter.js +42 -47
- 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/invokers-shim.d.ts +6 -0
- package/dist/invokers-shim.js +32 -0
- package/dist/invokers-shim.js.map +1 -0
- package/dist/invokers.d.ts +3 -5
- package/dist/invokers.js +11 -51
- package/dist/invokers.js.map +1 -1
- package/dist/islands.d.ts +0 -2
- package/dist/islands.js +4 -11
- package/dist/islands.js.map +1 -1
- package/dist/light-dom.d.ts +4 -53
- package/dist/light-dom.js +5 -100
- package/dist/light-dom.js.map +1 -1
- package/dist/prop.d.ts +89 -0
- package/dist/prop.js +41 -0
- package/dist/prop.js.map +1 -0
- package/dist/props.d.ts +57 -21
- package/dist/props.js +157 -34
- 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 +43 -0
- package/dist/scheduler.js +212 -0
- package/dist/scheduler.js.map +1 -0
- 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 +10 -0
- package/dist/server-component.js +133 -0
- package/dist/server-component.js.map +1 -0
- package/dist/server-specs.d.ts +6 -0
- package/dist/server-specs.js +13 -0
- package/dist/server-specs.js.map +1 -0
- package/dist/server.d.ts +34 -0
- package/dist/server.js +59 -0
- package/dist/server.js.map +1 -0
- package/dist/settled.d.ts +11 -0
- package/dist/settled.js +62 -0
- package/dist/settled.js.map +1 -0
- 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 -11
- 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.d.ts +6 -3
- package/dist/store-binding.js +7 -8
- package/dist/store-binding.js.map +1 -1
- package/dist/store-scope.d.ts +8 -11
- package/dist/store-scope.js +15 -40
- package/dist/store-scope.js.map +1 -1
- package/dist/store.d.ts +3 -0
- package/dist/store.js +45 -10
- package/dist/store.js.map +1 -1
- package/dist/stores-provider.d.ts +2 -6
- package/dist/stores-provider.js +21 -55
- package/dist/stores-provider.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 +5 -7
- package/dist/transitions.js +17 -20
- package/dist/transitions.js.map +1 -1
- package/dist/types.d.ts +142 -49
- 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 +11 -0
- package/dist/view/attributes.js +15 -0
- package/dist/view/attributes.js.map +1 -0
- package/dist/view/compiled.d.ts +1 -0
- package/dist/view/compiled.js +6 -0
- package/dist/view/compiled.js.map +1 -0
- package/dist/view/dev-off.d.ts +1 -0
- package/dist/view/dev-off.js +4 -0
- package/dist/view/dev-off.js.map +1 -0
- package/dist/view/dev.d.ts +1 -0
- package/dist/view/dev.js +5 -0
- package/dist/view/dev.js.map +1 -0
- package/dist/view/flags.d.ts +1 -0
- package/dist/view/flags.js +4 -0
- package/dist/view/flags.js.map +1 -0
- package/dist/view/index.d.ts +26 -0
- package/dist/view/index.js +27 -0
- package/dist/view/index.js.map +1 -0
- 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 +23 -0
- package/dist/view/normalize/check.js +81 -0
- package/dist/view/normalize/check.js.map +1 -0
- package/dist/view/normalize/emit.d.ts +15 -0
- package/dist/view/normalize/emit.js +165 -0
- package/dist/view/normalize/emit.js.map +1 -0
- package/dist/view/normalize/entities.d.ts +4 -0
- package/dist/view/normalize/entities.js +38 -0
- package/dist/view/normalize/entities.js.map +1 -0
- package/dist/view/normalize/errors.d.ts +9 -0
- package/dist/view/normalize/errors.js +19 -0
- package/dist/view/normalize/errors.js.map +1 -0
- package/dist/view/normalize/id.d.ts +10 -0
- package/dist/view/normalize/id.js +55 -0
- package/dist/view/normalize/id.js.map +1 -0
- package/dist/view/normalize/normalize.d.ts +18 -0
- package/dist/view/normalize/normalize.js +42 -0
- package/dist/view/normalize/normalize.js.map +1 -0
- package/dist/view/normalize/repairs.d.ts +24 -0
- package/dist/view/normalize/repairs.js +166 -0
- package/dist/view/normalize/repairs.js.map +1 -0
- package/dist/view/normalize/rules.d.ts +39 -0
- package/dist/view/normalize/rules.js +120 -0
- package/dist/view/normalize/rules.js.map +1 -0
- package/dist/view/normalize/shape.d.ts +5 -0
- package/dist/view/normalize/shape.js +38 -0
- package/dist/view/normalize/shape.js.map +1 -0
- package/dist/view/normalize/source.d.ts +13 -0
- package/dist/view/normalize/source.js +34 -0
- package/dist/view/normalize/source.js.map +1 -0
- 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/tag-states.d.ts +23 -0
- package/dist/view/normalize/tag-states.js +192 -0
- package/dist/view/normalize/tag-states.js.map +1 -0
- package/dist/view/normalize/tokenizer.d.ts +5 -0
- package/dist/view/normalize/tokenizer.js +233 -0
- package/dist/view/normalize/tokenizer.js.map +1 -0
- package/dist/view/normalize/tokens.d.ts +55 -0
- package/dist/view/normalize/tokens.js +24 -0
- package/dist/view/normalize/tokens.js.map +1 -0
- package/dist/view/normalize/tree.d.ts +65 -0
- package/dist/view/normalize/tree.js +235 -0
- package/dist/view/normalize/tree.js.map +1 -0
- package/dist/view/normalize/types.d.ts +146 -0
- package/dist/view/normalize/types.js +29 -0
- package/dist/view/normalize/types.js.map +1 -0
- package/dist/view/normalize/whitespace.d.ts +2 -0
- package/dist/{template-whitespace.js → view/normalize/whitespace.js} +27 -36
- package/dist/view/normalize/whitespace.js.map +1 -0
- package/dist/view/prepare-stub.d.ts +3 -0
- package/dist/view/prepare-stub.js +7 -0
- package/dist/view/prepare-stub.js.map +1 -0
- package/dist/view/prepare.d.ts +11 -0
- package/dist/view/prepare.js +63 -0
- package/dist/view/prepare.js.map +1 -0
- package/dist/view/registry.d.ts +78 -0
- package/dist/view/registry.js +27 -0
- package/dist/view/registry.js.map +1 -0
- package/dist/view/render/adopt-attr.d.ts +14 -0
- package/dist/view/render/adopt-attr.js +83 -0
- package/dist/view/render/adopt-attr.js.map +1 -0
- package/dist/view/render/adopt-plan.d.ts +10 -0
- package/dist/view/render/adopt-plan.js +26 -0
- package/dist/view/render/adopt-plan.js.map +1 -0
- package/dist/view/render/adopt.d.ts +3 -0
- package/dist/view/render/adopt.js +286 -0
- package/dist/view/render/adopt.js.map +1 -0
- package/dist/view/render/attr-parts.d.ts +72 -0
- package/dist/view/render/attr-parts.js +262 -0
- package/dist/view/render/attr-parts.js.map +1 -0
- package/dist/view/render/child-part.d.ts +51 -0
- package/dist/view/render/child-part.js +173 -0
- package/dist/view/render/child-part.js.map +1 -0
- package/dist/view/render/dev-check.d.ts +12 -0
- package/dist/view/render/dev-check.js +122 -0
- package/dist/view/render/dev-check.js.map +1 -0
- 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 +5 -0
- package/dist/view/render/hook-part.js +36 -0
- package/dist/view/render/hook-part.js.map +1 -0
- 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 +108 -0
- package/dist/view/render/hooks.js +108 -0
- package/dist/view/render/hooks.js.map +1 -0
- package/dist/view/render/hydrate.d.ts +10 -0
- package/dist/view/render/hydrate.js +33 -0
- package/dist/view/render/hydrate.js.map +1 -0
- package/dist/view/render/instance.d.ts +33 -0
- package/dist/view/render/instance.js +107 -0
- package/dist/view/render/instance.js.map +1 -0
- 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 +20 -0
- package/dist/view/render/list.js +156 -0
- package/dist/view/render/list.js.map +1 -0
- package/dist/view/render/mismatch.d.ts +10 -0
- package/dist/view/render/mismatch.js +55 -0
- package/dist/view/render/mismatch.js.map +1 -0
- 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/nodes.d.ts +10 -0
- package/dist/view/render/nodes.js +37 -0
- package/dist/view/render/nodes.js.map +1 -0
- package/dist/view/render/place.d.ts +18 -0
- package/dist/view/render/place.js +69 -0
- package/dist/view/render/place.js.map +1 -0
- package/dist/view/render/plan.d.ts +26 -0
- package/dist/view/render/plan.js +124 -0
- package/dist/view/render/plan.js.map +1 -0
- package/dist/view/render/raw.d.ts +21 -0
- package/dist/view/render/raw.js +72 -0
- package/dist/view/render/raw.js.map +1 -0
- package/dist/view/render/render.d.ts +15 -0
- package/dist/view/render/render.js +65 -0
- package/dist/view/render/render.js.map +1 -0
- package/dist/view/render/reorder.d.ts +4 -0
- package/dist/view/render/reorder.js +101 -0
- package/dist/view/render/reorder.js.map +1 -0
- package/dist/view/render/rows.d.ts +23 -0
- package/dist/view/render/rows.js +95 -0
- package/dist/view/render/rows.js.map +1 -0
- package/dist/view/render/seen.d.ts +11 -0
- package/dist/view/render/seen.js +17 -0
- package/dist/view/render/seen.js.map +1 -0
- 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 +29 -0
- package/dist/view/render/values.js +13 -0
- package/dist/view/render/values.js.map +1 -0
- package/dist/view/render/warn.d.ts +28 -0
- package/dist/view/render/warn.js +114 -0
- package/dist/view/render/warn.js.map +1 -0
- package/dist/view/server/component.d.ts +12 -0
- package/dist/view/server/component.js +64 -0
- package/dist/view/server/component.js.map +1 -0
- package/dist/view/server/escape.d.ts +10 -0
- package/dist/view/server/escape.js +34 -0
- package/dist/view/server/escape.js.map +1 -0
- package/dist/view/server/index.d.ts +48 -0
- package/dist/view/server/index.js +80 -0
- package/dist/view/server/index.js.map +1 -0
- package/dist/view/server/sha256.d.ts +2 -0
- package/dist/view/server/sha256.js +75 -0
- package/dist/view/server/sha256.js.map +1 -0
- package/dist/view/server/tags.d.ts +68 -0
- package/dist/view/server/tags.js +132 -0
- package/dist/view/server/tags.js.map +1 -0
- package/dist/view/server/values.d.ts +18 -0
- package/dist/view/server/values.js +94 -0
- package/dist/view/server/values.js.map +1 -0
- package/dist/view/server/writer.d.ts +21 -0
- package/dist/view/server/writer.js +170 -0
- package/dist/view/server/writer.js.map +1 -0
- package/dist/view/styles.d.ts +25 -0
- package/dist/view/styles.js +58 -0
- package/dist/view/styles.js.map +1 -0
- package/dist/view/template-element.d.ts +10 -0
- package/dist/view/template-element.js +45 -0
- package/dist/view/template-element.js.map +1 -0
- package/dist/view/template.d.ts +29 -0
- package/dist/view/template.js +84 -0
- package/dist/view/template.js.map +1 -0
- 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 +57 -11
- package/dist/vite.js +319 -27
- package/dist/vite.js.map +1 -1
- package/package.json +70 -4
- package/dist/accessible-name.d.ts +0 -19
- package/dist/accessible-name.js +0 -56
- package/dist/accessible-name.js.map +0 -1
- package/dist/element-directive.d.ts +0 -20
- package/dist/element-directive.js +0 -31
- package/dist/element-directive.js.map +0 -1
- package/dist/invalid.d.ts +0 -21
- package/dist/invalid.js +0 -70
- package/dist/invalid.js.map +0 -1
- package/dist/lit-html-check.d.ts +0 -6
- package/dist/lit-html-check.js +0 -48
- package/dist/lit-html-check.js.map +0 -1
- package/dist/live-boolean.d.ts +0 -22
- package/dist/live-boolean.js +0 -34
- package/dist/live-boolean.js.map +0 -1
- package/dist/random.d.ts +0 -13
- package/dist/random.js +0 -19
- package/dist/random.js.map +0 -1
- package/dist/styles.d.ts +0 -12
- package/dist/styles.js +0 -11
- package/dist/styles.js.map +0 -1
- package/dist/template-whitespace.d.ts +0 -7
- package/dist/template-whitespace.js.map +0 -1
- package/dist/templates.d.ts +0 -5
- package/dist/templates.js +0 -15
- package/dist/templates.js.map +0 -1
- package/dist/textarea.d.ts +0 -26
- package/dist/textarea.js +0 -85
- package/dist/textarea.js.map +0 -1
package/dist/intent.js
CHANGED
|
@@ -1,53 +1,84 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { loadInvokerShim } from '#invoker-fallback';
|
|
2
|
+
import { commandOf, invokersSupported } from './invokers.js';
|
|
3
|
+
import { isLightComponent } from './light-dom.js';
|
|
4
|
+
import { message } from './view/index.js';
|
|
5
|
+
/** Event a child component dispatches on its host to send an output up (ADR 0010); public. */
|
|
3
6
|
export const OUTPUT_EVENT = 'gyral-output';
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
* non-bubbling events such as `toggle` are seen too). Only `click`, `submit`, `input`,
|
|
7
|
-
* `change` and outputs are default triggers; the rest fire via `data-intent-on="…"`.
|
|
8
|
-
* Components may add more with `spec.events`.
|
|
9
|
-
*/
|
|
10
|
-
export const INTENT_EVENTS = [
|
|
7
|
+
/** Default triggers (`defaultTrigger`): every component root listens for these. */
|
|
8
|
+
export const DEFAULT_EVENTS = [
|
|
11
9
|
'click',
|
|
12
10
|
'submit',
|
|
13
11
|
'input',
|
|
14
12
|
'change',
|
|
13
|
+
OUTPUT_EVENT,
|
|
14
|
+
];
|
|
15
|
+
/**
|
|
16
|
+
* The events `data-intent-on` usually names. A component root listens (capture phase, so
|
|
17
|
+
* non-bubbling events such as `toggle` are seen too) for the defaults and for the events its
|
|
18
|
+
* templates name in `data-intent-<event>` attributes and static `data-intent-on` values; a
|
|
19
|
+
* template that binds `data-intent-on` dynamically adds all of these. Any other event with a
|
|
20
|
+
* bound intent takes a per-event attribute, `data-intent-pointerdown=${i.Press}`, whose name the
|
|
21
|
+
* template carries (view/05-element.md "Intent events").
|
|
22
|
+
*/
|
|
23
|
+
export const INTENT_EVENTS = [
|
|
24
|
+
...DEFAULT_EVENTS,
|
|
15
25
|
'keydown',
|
|
16
26
|
'keyup',
|
|
17
27
|
'focusin',
|
|
18
28
|
'focusout',
|
|
19
29
|
'toggle',
|
|
20
30
|
'command',
|
|
21
|
-
OUTPUT_EVENT,
|
|
22
31
|
];
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
/**
|
|
33
|
+
* A static `data-intent-<event>` attribute: a per-event intent (the event is in the name), or
|
|
34
|
+
* `data-intent-on` (its value is the event, or a quoted list of them separated by spaces).
|
|
35
|
+
*/
|
|
36
|
+
const INTENT_ATTR = /\sdata-intent-([\w-]+)=(["']?)(.*?)\2(?=[\s/>])/gi;
|
|
37
|
+
// Names separated by any whitespace; none empty, so no listener for "".
|
|
38
|
+
const eventList = (value) => value.match(/\S+/g) ?? [];
|
|
39
|
+
const eventsByTemplate = new WeakMap();
|
|
40
|
+
/**
|
|
41
|
+
* The intent events a template's (or `raw()` markup's) `data-intent-<event>` and
|
|
42
|
+
* `data-intent-on` attributes name. A bound attribute's name is in its part; a bound
|
|
43
|
+
* `data-intent-on` adds every intent event.
|
|
44
|
+
*/
|
|
45
|
+
export function eventsOf(markup) {
|
|
46
|
+
let events = eventsByTemplate.get(markup);
|
|
47
|
+
if (events === undefined) {
|
|
48
|
+
// Bound attributes are in the parts, by name: listed as ` name=* ` and matched like markup
|
|
49
|
+
// (other parts' names are never intent attributes; `*` marks a bound data-intent-on).
|
|
50
|
+
const bound = markup.parts?.map((p) => ` ${p[2]}=* `).join('') ?? '';
|
|
51
|
+
events = Array.from((markup.html + bound).matchAll(INTENT_ATTR)).flatMap(([, event, , value]) => event !== 'on'
|
|
52
|
+
? event
|
|
53
|
+
: value === '*'
|
|
54
|
+
? INTENT_EVENTS
|
|
55
|
+
: eventList(value));
|
|
56
|
+
eventsByTemplate.set(markup, events);
|
|
57
|
+
}
|
|
58
|
+
return events;
|
|
29
59
|
}
|
|
30
|
-
const
|
|
31
|
-
|
|
60
|
+
const isToggle = (el) => el instanceof HTMLInputElement && (el.type === 'checkbox' || el.type === 'radio');
|
|
61
|
+
const CLICK_INPUT_TYPES = /^(button|submit|reset|image)$/;
|
|
62
|
+
/**
|
|
63
|
+
* The event that fires an intent unless `data-intent-on` overrides it. Custom elements
|
|
64
|
+
* (autonomous: the name has a dash) talk to their parent via outputs.
|
|
65
|
+
*/
|
|
32
66
|
export function defaultTrigger(el) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
// Custom elements (autonomous: the name has a dash) talk to their parent via outputs.
|
|
45
|
-
if (el.localName.includes('-'))
|
|
46
|
-
return OUTPUT_EVENT;
|
|
47
|
-
return 'click';
|
|
67
|
+
const name = el.localName;
|
|
68
|
+
return name === 'form'
|
|
69
|
+
? 'submit'
|
|
70
|
+
: name === 'select' || isToggle(el)
|
|
71
|
+
? 'change'
|
|
72
|
+
: name === 'textarea' ||
|
|
73
|
+
(name === 'input' && !CLICK_INPUT_TYPES.test(el.type))
|
|
74
|
+
? 'input'
|
|
75
|
+
: name.includes('-')
|
|
76
|
+
? OUTPUT_EVENT
|
|
77
|
+
: 'click';
|
|
48
78
|
}
|
|
49
|
-
|
|
50
|
-
|
|
79
|
+
/** The events that fire `el`'s intent: its `data-intent-on` list, or its default trigger. */
|
|
80
|
+
function triggersOf(el) {
|
|
81
|
+
return eventList(el.getAttribute('data-intent-on') ?? defaultTrigger(el));
|
|
51
82
|
}
|
|
52
83
|
/** Every class `define()` creates, so intent lookup can tell where a component begins. */
|
|
53
84
|
const hostClasses = new WeakSet();
|
|
@@ -55,12 +86,27 @@ export function markGyralHost(ctor) {
|
|
|
55
86
|
hostClasses.add(ctor);
|
|
56
87
|
}
|
|
57
88
|
const isGyralHost = (node) => hostClasses.has(node.constructor);
|
|
89
|
+
/**
|
|
90
|
+
* The number of Gyral host ancestors of `el` in the composed tree (across shadow roots): the
|
|
91
|
+
* scheduler renders smaller depths first (view/04-scheduler.md "Marking").
|
|
92
|
+
*/
|
|
93
|
+
export function hostDepth(el) {
|
|
94
|
+
let depth = 0;
|
|
95
|
+
for (let node = el.parentNode; node !== null;) {
|
|
96
|
+
if (isGyralHost(node))
|
|
97
|
+
depth += 1;
|
|
98
|
+
node = node instanceof ShadowRoot ? node.host : node.parentNode;
|
|
99
|
+
}
|
|
100
|
+
return depth;
|
|
101
|
+
}
|
|
58
102
|
/**
|
|
59
103
|
* Does `node` belong to the component whose intent root is `root`? `root` is the component's
|
|
60
104
|
* shadow root, or the host itself for light-DOM components (ADR 0014). The node must be in the
|
|
61
|
-
* same tree (not inside a nested shadow root) with no
|
|
62
|
-
*
|
|
63
|
-
* the
|
|
105
|
+
* same tree (not inside a nested shadow root) with no light-DOM Gyral host between them: a
|
|
106
|
+
* light-DOM component owns its children (it rendered them). Children of a shadow-DOM host are
|
|
107
|
+
* the outer template's content, slotted into it, so they stay the outer component's (a form or
|
|
108
|
+
* a child component slotted into a card). The nested host element itself (with the parent's
|
|
109
|
+
* `data-intent` on it) still belongs to the parent.
|
|
64
110
|
*/
|
|
65
111
|
function ownedBy(node, root) {
|
|
66
112
|
const tree = root instanceof ShadowRoot ? root : root.getRootNode();
|
|
@@ -69,28 +115,11 @@ function ownedBy(node, root) {
|
|
|
69
115
|
for (let p = node.parentNode; p !== null; p = p.parentNode) {
|
|
70
116
|
if (p === root)
|
|
71
117
|
return true;
|
|
72
|
-
if (isGyralHost(p))
|
|
118
|
+
if (isGyralHost(p) && isLightComponent(p.constructor))
|
|
73
119
|
return false;
|
|
74
120
|
}
|
|
75
121
|
return false;
|
|
76
122
|
}
|
|
77
|
-
/**
|
|
78
|
-
* Finds the nearest `data-intent` element for this event that belongs to `root`. Elements
|
|
79
|
-
* inside nested components are ignored: that is component isolation.
|
|
80
|
-
*/
|
|
81
|
-
export function findIntentElement(event, root) {
|
|
82
|
-
for (const node of event.composedPath()) {
|
|
83
|
-
if (node === root)
|
|
84
|
-
return undefined;
|
|
85
|
-
if (node instanceof Element &&
|
|
86
|
-
node.hasAttribute('data-intent') &&
|
|
87
|
-
triggerOf(node) === event.type &&
|
|
88
|
-
ownedBy(node, root)) {
|
|
89
|
-
return node;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
return undefined;
|
|
93
|
-
}
|
|
94
123
|
function valueOf(el) {
|
|
95
124
|
if (el instanceof HTMLInputElement ||
|
|
96
125
|
el instanceof HTMLSelectElement ||
|
|
@@ -100,58 +129,122 @@ function valueOf(el) {
|
|
|
100
129
|
}
|
|
101
130
|
return undefined;
|
|
102
131
|
}
|
|
103
|
-
/**
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
132
|
+
/**
|
|
133
|
+
* Reads an event into an IntentInput for the nearest element on its path that names an intent
|
|
134
|
+
* for it and belongs to `root`: its `data-intent-<type>`, else its `data-intent` when the
|
|
135
|
+
* event is one of its triggers. With `after`, the search starts past that element (the intent
|
|
136
|
+
* whose parser declined). Elements inside nested components are ignored: that is component
|
|
137
|
+
* isolation. Form submissions are prevented and turned into FormData.
|
|
138
|
+
*/
|
|
139
|
+
export function readIntent(event, root, after) {
|
|
140
|
+
const path = event.composedPath();
|
|
141
|
+
// indexOf(undefined) is -1: without `after`, the whole path.
|
|
142
|
+
for (const target of path.slice(path.indexOf(after) + 1)) {
|
|
143
|
+
if (target === root)
|
|
144
|
+
return undefined;
|
|
145
|
+
if (!(target instanceof Element))
|
|
146
|
+
continue;
|
|
147
|
+
// An output is the dispatching child's own: only the element it was dispatched on (the
|
|
148
|
+
// child host, where the direct parent's `data-intent` sits) takes it, never an ancestor.
|
|
149
|
+
if (event.type === OUTPUT_EVENT && target !== path[0])
|
|
150
|
+
continue;
|
|
151
|
+
const name = target.getAttribute('data-intent-' + event.type) ??
|
|
152
|
+
(triggersOf(target).includes(event.type) ? target.getAttribute('data-intent') : null);
|
|
153
|
+
if (name === null || !ownedBy(target, root))
|
|
154
|
+
continue;
|
|
155
|
+
let formData;
|
|
156
|
+
if (target instanceof HTMLFormElement && event instanceof SubmitEvent) {
|
|
157
|
+
event.preventDefault();
|
|
158
|
+
formData = new FormData(target, event.submitter);
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
name,
|
|
162
|
+
event,
|
|
163
|
+
target,
|
|
164
|
+
value: valueOf(target),
|
|
165
|
+
checked: isToggle(target) ? target.checked : undefined,
|
|
166
|
+
formData,
|
|
167
|
+
detail: event instanceof CustomEvent ? event.detail : undefined,
|
|
168
|
+
// Read structurally too: only keyboard events carry `key` to elements.
|
|
169
|
+
key: event.key,
|
|
170
|
+
// ToggleEvent (popover, <details>) is not Baseline widely available: read it structurally.
|
|
171
|
+
newState: event.newState,
|
|
172
|
+
command: commandOf(event),
|
|
173
|
+
};
|
|
113
174
|
}
|
|
114
|
-
return
|
|
115
|
-
name,
|
|
116
|
-
event,
|
|
117
|
-
target,
|
|
118
|
-
value: valueOf(target),
|
|
119
|
-
checked: isToggle(target) ? target.checked : undefined,
|
|
120
|
-
formData,
|
|
121
|
-
detail: event instanceof CustomEvent ? event.detail : undefined,
|
|
122
|
-
key: event instanceof KeyboardEvent ? event.key : undefined,
|
|
123
|
-
newState: toggleState(event),
|
|
124
|
-
command: commandOf(event),
|
|
125
|
-
};
|
|
175
|
+
return undefined;
|
|
126
176
|
}
|
|
127
177
|
// Any property read returns its own name, so `intents.Increment === 'Increment'`.
|
|
128
178
|
// Types restrict reads to real message tags; a tag without a parser warns at event time.
|
|
129
179
|
export const intentNames = new Proxy({}, { get: (_target, key) => (typeof key === 'string' ? key : undefined) });
|
|
130
|
-
/**
|
|
131
|
-
|
|
132
|
-
|
|
180
|
+
/**
|
|
181
|
+
* A component's intent names as a module-level constant, so pure list rows can name intents
|
|
182
|
+
* without passing them through `pick` (view/03-lists.md "Rows must be pure"). The same object
|
|
183
|
+
* the view gets as `i`, typed by the component's class (ADR 0023). A row that names intents
|
|
184
|
+
* this way needs an explicit return type, or the row, the view and the class infer each other
|
|
185
|
+
* in a circle:
|
|
186
|
+
*
|
|
187
|
+
* const i = intentsOf<typeof TodoList>();
|
|
188
|
+
* const Row = (t: Todo): TemplateResult => html`<input value=${t.id} data-intent=${i.Toggle} />`;
|
|
189
|
+
*/
|
|
190
|
+
export function intentsOf() {
|
|
191
|
+
return intentNames;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Adds capture listeners for `types` to a component root, skipping those in `listening`. A
|
|
195
|
+
* root that listens for `command` in a browser without invoker commands loads the fallback
|
|
196
|
+
* (invokers-shim.ts, ADR 0003 tier 3); settled() waits for it.
|
|
197
|
+
*/
|
|
198
|
+
export function listenForIntents(root, listening, types, handler) {
|
|
199
|
+
for (const type of types) {
|
|
200
|
+
if (listening.has(type))
|
|
201
|
+
continue;
|
|
202
|
+
listening.add(type);
|
|
133
203
|
root.addEventListener(type, handler, { capture: true });
|
|
204
|
+
if (type === 'command' && !invokersSupported())
|
|
205
|
+
loadInvokerShim(root);
|
|
134
206
|
}
|
|
135
|
-
shimInvokers(root); // `command` intents in browsers without invoker commands
|
|
136
207
|
}
|
|
137
|
-
/**
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
208
|
+
/**
|
|
209
|
+
* Parses one event with its matching parser and delivers the message (sync or async). A
|
|
210
|
+
* parser that returns `undefined` synchronously declines: the next intent outward for the same
|
|
211
|
+
* event gets it, up to the component root. A promise can't decline. The model's `ctx()` is
|
|
212
|
+
* built only when a parser runs, so its props are those at event time.
|
|
213
|
+
*/
|
|
214
|
+
export function handleIntent(event, root, parsers, tag, model, deliver) {
|
|
215
|
+
for (let input; (input = readIntent(event, root, input?.target));) {
|
|
216
|
+
const { name } = input;
|
|
217
|
+
const parser = parsers[name];
|
|
218
|
+
if (parser === undefined) {
|
|
219
|
+
console.warn(message(11, tag, name));
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
// A parser that throws or rejects is reported (ADR 0024) and sends nothing.
|
|
223
|
+
const failed = (cause) => {
|
|
224
|
+
model.fail(cause, 'parse', message(12, tag, name), name);
|
|
225
|
+
};
|
|
226
|
+
let result;
|
|
227
|
+
try {
|
|
228
|
+
// `true`: the intent sends its own tag (types allow it only for field-less variants).
|
|
229
|
+
result =
|
|
230
|
+
parser === true
|
|
231
|
+
? { _tag: name }
|
|
232
|
+
: parser(input, model.ctx());
|
|
233
|
+
}
|
|
234
|
+
catch (cause) {
|
|
235
|
+
failed(cause);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
// The direct parent took a child's output: it goes no further (no outer component or page
|
|
239
|
+
// listener sees it, ADR 0010 addendum). A declining parser lets it go on.
|
|
240
|
+
if (event.type === OUTPUT_EVENT && result !== undefined)
|
|
241
|
+
event.stopPropagation();
|
|
242
|
+
if (result instanceof Promise)
|
|
243
|
+
return void result.then(deliver, failed);
|
|
244
|
+
if (result !== undefined) {
|
|
245
|
+
deliver(result);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
155
248
|
}
|
|
156
249
|
}
|
|
157
250
|
//# sourceMappingURL=intent.js.map
|
package/dist/intent.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intent.js","sourceRoot":"","sources":["../src/intent.ts"],"names":[],"mappings":"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","sourcesContent":["import { commandOf, shimInvokers } from './invokers.js';\nimport type { IntentInput, IntentParser, Tagged } from './types.js';\n\n/** Event a child component dispatches on its host to send an output up (ADR 0010). */\nexport const OUTPUT_EVENT = 'gyral-output';\n\n/**\n * Events the intent layer listens for on each component's shadow root (capture phase, so\n * non-bubbling events such as `toggle` are seen too). Only `click`, `submit`, `input`,\n * `change` and outputs are default triggers; the rest fire via `data-intent-on=\"…\"`.\n * Components may add more with `spec.events`.\n */\nexport const INTENT_EVENTS = [\n 'click',\n 'submit',\n 'input',\n 'change',\n 'keydown',\n 'keyup',\n 'focusin',\n 'focusout',\n 'toggle',\n 'command',\n OUTPUT_EVENT,\n] as const;\n\nconst isToggle = (el: Element): el is HTMLInputElement =>\n el instanceof HTMLInputElement && (el.type === 'checkbox' || el.type === 'radio');\n\n// ToggleEvent (popover, <details>) is not Baseline widely available; read it structurally.\nfunction toggleState(event: Event): 'open' | 'closed' | undefined {\n if (event.type !== 'toggle' || !('newState' in event)) return undefined;\n return event.newState === 'open' ? 'open' : 'closed';\n}\n\nconst CLICK_INPUT_TYPES = new Set(['button', 'submit', 'reset', 'image']);\n\n/** The event that fires an intent unless `data-intent-on` overrides it. */\nexport function defaultTrigger(el: Element): string {\n if (el instanceof HTMLFormElement) return 'submit';\n if (el instanceof HTMLSelectElement) return 'change';\n if (el instanceof HTMLTextAreaElement) return 'input';\n if (el instanceof HTMLInputElement) {\n if (CLICK_INPUT_TYPES.has(el.type)) return 'click';\n return el.type === 'checkbox' || el.type === 'radio' ? 'change' : 'input';\n }\n // Custom elements (autonomous: the name has a dash) talk to their parent via outputs.\n if (el.localName.includes('-')) return OUTPUT_EVENT;\n return 'click';\n}\n\nfunction triggerOf(el: Element): string {\n return el.getAttribute('data-intent-on') ?? defaultTrigger(el);\n}\n\n/** Every class `define()` creates, so intent lookup can tell where a component begins. */\nconst hostClasses = new WeakSet<object>();\n\nexport function markGyralHost(ctor: object): void {\n hostClasses.add(ctor);\n}\n\nconst isGyralHost = (node: Node): boolean => hostClasses.has(node.constructor);\n\n/**\n * Does `node` belong to the component whose intent root is `root`? `root` is the component's\n * shadow root, or the host itself for light-DOM components (ADR 0014). The node must be in the\n * same tree (not inside a nested shadow root) with no other Gyral host between them: a nested\n * component, light-DOM or shadow, owns its own content. The nested host element itself (with\n * the parent's `data-intent` on it) still belongs to the parent.\n */\nfunction ownedBy(node: Element, root: Node): boolean {\n const tree = root instanceof ShadowRoot ? root : root.getRootNode();\n if (node.getRootNode() !== tree) return false;\n for (let p = node.parentNode; p !== null; p = p.parentNode) {\n if (p === root) return true;\n if (isGyralHost(p)) return false;\n }\n return false;\n}\n\n/**\n * Finds the nearest `data-intent` element for this event that belongs to `root`. Elements\n * inside nested components are ignored: that is component isolation.\n */\nexport function findIntentElement(event: Event, root: Node): Element | undefined {\n for (const node of event.composedPath()) {\n if (node === root) return undefined;\n if (\n node instanceof Element &&\n node.hasAttribute('data-intent') &&\n triggerOf(node) === event.type &&\n ownedBy(node, root)\n ) {\n return node;\n }\n }\n return undefined;\n}\n\nfunction valueOf(el: Element): string | undefined {\n if (\n el instanceof HTMLInputElement ||\n el instanceof HTMLSelectElement ||\n el instanceof HTMLTextAreaElement ||\n el instanceof HTMLButtonElement\n ) {\n return el.value;\n }\n return undefined;\n}\n\n/** Reads an event into an IntentInput. Form submissions are prevented and turned into FormData. */\nexport function readIntent(event: Event, root: Node): IntentInput | undefined {\n const target = findIntentElement(event, root);\n const name = target?.getAttribute('data-intent');\n if (target === undefined || name == null) return undefined;\n let formData: FormData | undefined;\n if (target instanceof HTMLFormElement && event instanceof SubmitEvent) {\n event.preventDefault();\n formData = new FormData(target, event.submitter);\n }\n return {\n name,\n event,\n target,\n value: valueOf(target),\n checked: isToggle(target) ? target.checked : undefined,\n formData,\n detail: event instanceof CustomEvent ? (event.detail as unknown) : undefined,\n key: event instanceof KeyboardEvent ? event.key : undefined,\n newState: toggleState(event),\n command: commandOf(event),\n };\n}\n\n// Any property read returns its own name, so `intents.Increment === 'Increment'`.\n// Types restrict reads to real message tags; a tag without a parser warns at event time.\nexport const intentNames: unknown = new Proxy(\n {},\n { get: (_target, key) => (typeof key === 'string' ? key : undefined) },\n);\n\n/** Listens for intent events on a component root (capture phase: `toggle` doesn't bubble). */\nexport function listenForIntents(\n root: Node,\n extra: readonly string[],\n handler: (event: Event) => void,\n): void {\n for (const type of new Set([...INTENT_EVENTS, ...extra])) {\n root.addEventListener(type, handler, { capture: true });\n }\n shimInvokers(root); // `command` intents in browsers without invoker commands\n}\n\n/** Parses one event with its matching parser and delivers the message (sync or async). */\nexport function handleIntent<M>(\n event: Event,\n root: Node,\n parsers: Readonly<Record<string, IntentParser<M> | undefined>>,\n tag: string,\n deliver: (msg: Tagged | undefined) => void,\n): void {\n const input = readIntent(event, root);\n if (input === undefined) return;\n const parser = parsers[input.name];\n if (parser === undefined) {\n console.warn(`<${tag}> has no intent parser for data-intent=\"${input.name}\".`);\n return;\n }\n const result = parser(input) as Tagged | undefined | Promise<Tagged | undefined>;\n if (result instanceof Promise) {\n result.then(deliver, (error: unknown) => {\n console.error(`<${tag}> intent parser for \"${input.name}\" failed`, error);\n });\n } else {\n deliver(result);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"intent.js","sourceRoot":"","sources":["../src/intent.ts"],"names":[],"mappings":"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","sourcesContent":["import { loadInvokerShim } from '#invoker-fallback';\nimport { commandOf, invokersSupported } from './invokers.js';\nimport { isLightComponent } from './light-dom.js';\nimport type { IntentInput, IntentNames, IntentParser, ParserCtx, Tagged } from './types.js';\nimport { message, type Markup } from './view/index.js';\n\n/** Event a child component dispatches on its host to send an output up (ADR 0010); public. */\nexport const OUTPUT_EVENT = 'gyral-output';\n\n/** Default triggers (`defaultTrigger`): every component root listens for these. */\nexport const DEFAULT_EVENTS: readonly string[] = [\n 'click',\n 'submit',\n 'input',\n 'change',\n OUTPUT_EVENT,\n];\n\n/**\n * The events `data-intent-on` usually names. A component root listens (capture phase, so\n * non-bubbling events such as `toggle` are seen too) for the defaults and for the events its\n * templates name in `data-intent-<event>` attributes and static `data-intent-on` values; a\n * template that binds `data-intent-on` dynamically adds all of these. Any other event with a\n * bound intent takes a per-event attribute, `data-intent-pointerdown=${i.Press}`, whose name the\n * template carries (view/05-element.md \"Intent events\").\n */\nexport const INTENT_EVENTS: readonly string[] = [\n ...DEFAULT_EVENTS,\n 'keydown',\n 'keyup',\n 'focusin',\n 'focusout',\n 'toggle',\n 'command',\n];\n\n/**\n * A static `data-intent-<event>` attribute: a per-event intent (the event is in the name), or\n * `data-intent-on` (its value is the event, or a quoted list of them separated by spaces).\n */\nconst INTENT_ATTR = /\\sdata-intent-([\\w-]+)=([\"']?)(.*?)\\2(?=[\\s/>])/gi;\n// Names separated by any whitespace; none empty, so no listener for \"\".\nconst eventList = (value: string): string[] => value.match(/\\S+/g) ?? [];\nconst eventsByTemplate = new WeakMap<Markup, readonly string[]>();\n\n/**\n * The intent events a template's (or `raw()` markup's) `data-intent-<event>` and\n * `data-intent-on` attributes name. A bound attribute's name is in its part; a bound\n * `data-intent-on` adds every intent event.\n */\nexport function eventsOf(markup: Markup): readonly string[] {\n let events = eventsByTemplate.get(markup);\n if (events === undefined) {\n // Bound attributes are in the parts, by name: listed as ` name=* ` and matched like markup\n // (other parts' names are never intent attributes; `*` marks a bound data-intent-on).\n const bound = markup.parts?.map((p) => ` ${p[2] as string}=* `).join('') ?? '';\n events = Array.from((markup.html + bound).matchAll(INTENT_ATTR)).flatMap(\n ([, event, , value]) =>\n event !== 'on'\n ? (event as string)\n : value === '*'\n ? INTENT_EVENTS\n : eventList(value as string),\n );\n eventsByTemplate.set(markup, events);\n }\n return events;\n}\n\nconst isToggle = (el: Element): el is HTMLInputElement =>\n el instanceof HTMLInputElement && (el.type === 'checkbox' || el.type === 'radio');\n\nconst CLICK_INPUT_TYPES = /^(button|submit|reset|image)$/;\n\n/**\n * The event that fires an intent unless `data-intent-on` overrides it. Custom elements\n * (autonomous: the name has a dash) talk to their parent via outputs.\n */\nexport function defaultTrigger(el: Element): string {\n const name = el.localName;\n return name === 'form'\n ? 'submit'\n : name === 'select' || isToggle(el)\n ? 'change'\n : name === 'textarea' ||\n (name === 'input' && !CLICK_INPUT_TYPES.test((el as HTMLInputElement).type))\n ? 'input'\n : name.includes('-')\n ? OUTPUT_EVENT\n : 'click';\n}\n\n/** The events that fire `el`'s intent: its `data-intent-on` list, or its default trigger. */\nfunction triggersOf(el: Element): string[] {\n return eventList(el.getAttribute('data-intent-on') ?? defaultTrigger(el));\n}\n\n/** Every class `define()` creates, so intent lookup can tell where a component begins. */\nconst hostClasses = new WeakSet<object>();\n\nexport function markGyralHost(ctor: object): void {\n hostClasses.add(ctor);\n}\n\nconst isGyralHost = (node: Node): boolean => hostClasses.has(node.constructor);\n\n/**\n * The number of Gyral host ancestors of `el` in the composed tree (across shadow roots): the\n * scheduler renders smaller depths first (view/04-scheduler.md \"Marking\").\n */\nexport function hostDepth(el: Element): number {\n let depth = 0;\n for (let node: Node | null = el.parentNode; node !== null;) {\n if (isGyralHost(node)) depth += 1;\n node = node instanceof ShadowRoot ? node.host : node.parentNode;\n }\n return depth;\n}\n\n/**\n * Does `node` belong to the component whose intent root is `root`? `root` is the component's\n * shadow root, or the host itself for light-DOM components (ADR 0014). The node must be in the\n * same tree (not inside a nested shadow root) with no light-DOM Gyral host between them: a\n * light-DOM component owns its children (it rendered them). Children of a shadow-DOM host are\n * the outer template's content, slotted into it, so they stay the outer component's (a form or\n * a child component slotted into a card). The nested host element itself (with the parent's\n * `data-intent` on it) still belongs to the parent.\n */\nfunction ownedBy(node: Element, root: Node): boolean {\n const tree = root instanceof ShadowRoot ? root : root.getRootNode();\n if (node.getRootNode() !== tree) return false;\n for (let p = node.parentNode; p !== null; p = p.parentNode) {\n if (p === root) return true;\n if (isGyralHost(p) && isLightComponent(p.constructor)) return false;\n }\n return false;\n}\n\nfunction valueOf(el: Element): string | undefined {\n if (\n el instanceof HTMLInputElement ||\n el instanceof HTMLSelectElement ||\n el instanceof HTMLTextAreaElement ||\n el instanceof HTMLButtonElement\n ) {\n return el.value;\n }\n return undefined;\n}\n\n/**\n * Reads an event into an IntentInput for the nearest element on its path that names an intent\n * for it and belongs to `root`: its `data-intent-<type>`, else its `data-intent` when the\n * event is one of its triggers. With `after`, the search starts past that element (the intent\n * whose parser declined). Elements inside nested components are ignored: that is component\n * isolation. Form submissions are prevented and turned into FormData.\n */\nexport function readIntent(event: Event, root: Node, after?: Element): IntentInput | undefined {\n const path = event.composedPath();\n // indexOf(undefined) is -1: without `after`, the whole path.\n for (const target of path.slice(path.indexOf(after as Element) + 1)) {\n if (target === root) return undefined;\n if (!(target instanceof Element)) continue;\n // An output is the dispatching child's own: only the element it was dispatched on (the\n // child host, where the direct parent's `data-intent` sits) takes it, never an ancestor.\n if (event.type === OUTPUT_EVENT && target !== path[0]) continue;\n const name =\n target.getAttribute('data-intent-' + event.type) ??\n (triggersOf(target).includes(event.type) ? target.getAttribute('data-intent') : null);\n if (name === null || !ownedBy(target, root)) continue;\n let formData: FormData | undefined;\n if (target instanceof HTMLFormElement && event instanceof SubmitEvent) {\n event.preventDefault();\n formData = new FormData(target, event.submitter);\n }\n return {\n name,\n event,\n target,\n value: valueOf(target),\n checked: isToggle(target) ? target.checked : undefined,\n formData,\n detail: event instanceof CustomEvent ? (event.detail as unknown) : undefined,\n // Read structurally too: only keyboard events carry `key` to elements.\n key: (event as { readonly key?: string }).key,\n // ToggleEvent (popover, <details>) is not Baseline widely available: read it structurally.\n newState: (event as { readonly newState?: 'open' | 'closed' }).newState,\n command: commandOf(event),\n };\n }\n return undefined;\n}\n\n// Any property read returns its own name, so `intents.Increment === 'Increment'`.\n// Types restrict reads to real message tags; a tag without a parser warns at event time.\nexport const intentNames: unknown = new Proxy(\n {},\n { get: (_target, key) => (typeof key === 'string' ? key : undefined) },\n);\n\n/**\n * A component's intent names as a module-level constant, so pure list rows can name intents\n * without passing them through `pick` (view/03-lists.md \"Rows must be pure\"). The same object\n * the view gets as `i`, typed by the component's class (ADR 0023). A row that names intents\n * this way needs an explicit return type, or the row, the view and the class infer each other\n * in a circle:\n *\n * const i = intentsOf<typeof TodoList>();\n * const Row = (t: Todo): TemplateResult => html`<input value=${t.id} data-intent=${i.Toggle} />`;\n */\nexport function intentsOf<C extends { readonly intentNames?: string }>(): IntentNames<\n NonNullable<C['intentNames']>\n> {\n return intentNames as IntentNames<NonNullable<C['intentNames']>>;\n}\n\n/**\n * Adds capture listeners for `types` to a component root, skipping those in `listening`. A\n * root that listens for `command` in a browser without invoker commands loads the fallback\n * (invokers-shim.ts, ADR 0003 tier 3); settled() waits for it.\n */\nexport function listenForIntents(\n root: Node,\n listening: Set<string>,\n types: readonly string[],\n handler: (event: Event) => void,\n): void {\n for (const type of types) {\n if (listening.has(type)) continue;\n listening.add(type);\n root.addEventListener(type, handler, { capture: true });\n if (type === 'command' && !invokersSupported()) loadInvokerShim(root);\n }\n}\n\n/**\n * Parses one event with its matching parser and delivers the message (sync or async). A\n * parser that returns `undefined` synchronously declines: the next intent outward for the same\n * event gets it, up to the component root. A promise can't decline. The model's `ctx()` is\n * built only when a parser runs, so its props are those at event time.\n */\nexport function handleIntent<M>(\n event: Event,\n root: Node,\n parsers: Readonly<Record<string, IntentParser<M> | true | undefined>>,\n tag: string,\n model: {\n ctx(): ParserCtx<unknown>;\n fail(cause: unknown, phase: 'parse', text: string, msg?: string): unknown;\n },\n deliver: (msg: Tagged | undefined) => void,\n): void {\n for (let input: IntentInput | undefined; (input = readIntent(event, root, input?.target));) {\n const { name } = input;\n const parser = parsers[name];\n if (parser === undefined) {\n console.warn(message(11, tag, name));\n return;\n }\n // A parser that throws or rejects is reported (ADR 0024) and sends nothing.\n const failed = (cause: unknown): void => {\n model.fail(cause, 'parse', message(12, tag, name), name);\n };\n let result: Tagged | undefined | Promise<Tagged | undefined>;\n try {\n // `true`: the intent sends its own tag (types allow it only for field-less variants).\n result =\n parser === true\n ? { _tag: name }\n : (parser(input, model.ctx()) as Tagged | undefined | Promise<Tagged | undefined>);\n } catch (cause) {\n failed(cause);\n return;\n }\n // The direct parent took a child's output: it goes no further (no outer component or page\n // listener sees it, ADR 0010 addendum). A declining parser lets it go on.\n if (event.type === OUTPUT_EVENT && result !== undefined) event.stopPropagation();\n if (result instanceof Promise) return void result.then(deliver, failed);\n if (result !== undefined) {\n deliver(result);\n return;\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { IndexedDBError, IndexedDBOptions, IndexedDBStores } from '../indexeddb-types.js';
|
|
2
|
+
export declare class DatabaseFailure extends Error {
|
|
3
|
+
readonly error: IndexedDBError;
|
|
4
|
+
constructor(error: IndexedDBError);
|
|
5
|
+
}
|
|
6
|
+
export declare function databaseError(database: string, phase: 'encode' | 'open' | 'upgrade' | 'transaction', cause: unknown): DatabaseFailure;
|
|
7
|
+
/** Native open requests cannot be cancelled: retain handlers to abort/close late results. */
|
|
8
|
+
export declare function openDatabase<S extends IndexedDBStores>(options: IndexedDBOptions<S>, signal: AbortSignal): Promise<IDBDatabase>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
export class DatabaseFailure extends Error {
|
|
2
|
+
constructor(error) {
|
|
3
|
+
super(error._tag);
|
|
4
|
+
this.error = error;
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
export function databaseError(database, phase, cause) {
|
|
8
|
+
return new DatabaseFailure({
|
|
9
|
+
_tag: 'IndexedDBAccessError',
|
|
10
|
+
database,
|
|
11
|
+
phase,
|
|
12
|
+
name: cause instanceof Error ? cause.name : 'Error',
|
|
13
|
+
message: cause instanceof Error ? cause.message : String(cause),
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/** Native open requests cannot be cancelled: retain handlers to abort/close late results. */
|
|
17
|
+
export function openDatabase(options, signal) {
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
signal.throwIfAborted();
|
|
20
|
+
const factory = options.factory?.() ?? (typeof indexedDB === 'undefined' ? undefined : indexedDB);
|
|
21
|
+
if (factory === undefined)
|
|
22
|
+
throw new Error('IndexedDB is unavailable.');
|
|
23
|
+
signal.throwIfAborted();
|
|
24
|
+
const request = factory.open(options.database, options.version);
|
|
25
|
+
const state = { ended: false };
|
|
26
|
+
const end = (cause) => {
|
|
27
|
+
if (state.ended)
|
|
28
|
+
return;
|
|
29
|
+
state.ended = true;
|
|
30
|
+
signal.removeEventListener('abort', abort);
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- preserve AbortSignal reasons
|
|
32
|
+
reject(cause);
|
|
33
|
+
};
|
|
34
|
+
const abort = () => {
|
|
35
|
+
end(signal.reason);
|
|
36
|
+
abortUpgrade();
|
|
37
|
+
};
|
|
38
|
+
const abortUpgrade = () => {
|
|
39
|
+
try {
|
|
40
|
+
request.transaction?.abort();
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
/* Native abort may already be pending. */
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const cleanup = () => {
|
|
47
|
+
request.onblocked = null;
|
|
48
|
+
request.onupgradeneeded = null;
|
|
49
|
+
request.onerror = null;
|
|
50
|
+
request.onsuccess = null;
|
|
51
|
+
signal.removeEventListener('abort', abort);
|
|
52
|
+
};
|
|
53
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
54
|
+
request.onblocked = () => {
|
|
55
|
+
end(new DatabaseFailure({
|
|
56
|
+
_tag: 'IndexedDBBlockedError',
|
|
57
|
+
database: options.database,
|
|
58
|
+
version: options.version,
|
|
59
|
+
}));
|
|
60
|
+
};
|
|
61
|
+
request.onupgradeneeded = (event) => {
|
|
62
|
+
const transaction = request.transaction;
|
|
63
|
+
if (transaction === null)
|
|
64
|
+
return;
|
|
65
|
+
if (state.ended) {
|
|
66
|
+
abortUpgrade();
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
options.upgrade?.(request.result, event.oldVersion, event.newVersion ?? options.version, transaction);
|
|
71
|
+
}
|
|
72
|
+
catch (cause) {
|
|
73
|
+
end(databaseError(options.database, 'upgrade', cause));
|
|
74
|
+
abortUpgrade();
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
request.onerror = () => {
|
|
78
|
+
end(databaseError(options.database, 'open', request.error));
|
|
79
|
+
cleanup();
|
|
80
|
+
};
|
|
81
|
+
request.onsuccess = () => {
|
|
82
|
+
const db = request.result;
|
|
83
|
+
if (state.ended)
|
|
84
|
+
db.close();
|
|
85
|
+
else {
|
|
86
|
+
state.ended = true;
|
|
87
|
+
db.onversionchange = () => {
|
|
88
|
+
db.close();
|
|
89
|
+
};
|
|
90
|
+
resolve(db);
|
|
91
|
+
}
|
|
92
|
+
cleanup();
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=indexeddb-open.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indexeddb-open.js","sourceRoot":"","sources":["../../src/internal/indexeddb-open.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IndexedDBError, IndexedDBOptions, IndexedDBStores } from '../indexeddb-types.js';\n\nexport class DatabaseFailure extends Error {\n constructor(readonly error: IndexedDBError) {\n super(error._tag);\n }\n}\nexport function databaseError(\n database: string,\n phase: 'encode' | 'open' | 'upgrade' | 'transaction',\n cause: unknown,\n): DatabaseFailure {\n return new DatabaseFailure({\n _tag: 'IndexedDBAccessError',\n database,\n phase,\n name: cause instanceof Error ? cause.name : 'Error',\n message: cause instanceof Error ? cause.message : String(cause),\n });\n}\n\n/** Native open requests cannot be cancelled: retain handlers to abort/close late results. */\nexport function openDatabase<S extends IndexedDBStores>(\n options: IndexedDBOptions<S>,\n signal: AbortSignal,\n): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n signal.throwIfAborted();\n const factory =\n options.factory?.() ?? (typeof indexedDB === 'undefined' ? undefined : indexedDB);\n if (factory === undefined) throw new Error('IndexedDB is unavailable.');\n signal.throwIfAborted();\n const request = factory.open(options.database, options.version);\n const state = { ended: false };\n const end = (cause: unknown): void => {\n if (state.ended) return;\n state.ended = true;\n signal.removeEventListener('abort', abort);\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- preserve AbortSignal reasons\n reject(cause);\n };\n const abort = (): void => {\n end(signal.reason);\n abortUpgrade();\n };\n const abortUpgrade = (): void => {\n try {\n request.transaction?.abort();\n } catch {\n /* Native abort may already be pending. */\n }\n };\n const cleanup = (): void => {\n request.onblocked = null;\n request.onupgradeneeded = null;\n request.onerror = null;\n request.onsuccess = null;\n signal.removeEventListener('abort', abort);\n };\n signal.addEventListener('abort', abort, { once: true });\n request.onblocked = () => {\n end(\n new DatabaseFailure({\n _tag: 'IndexedDBBlockedError',\n database: options.database,\n version: options.version,\n }),\n );\n };\n request.onupgradeneeded = (event) => {\n const transaction = request.transaction;\n if (transaction === null) return;\n if (state.ended) {\n abortUpgrade();\n return;\n }\n try {\n options.upgrade?.(\n request.result,\n event.oldVersion,\n event.newVersion ?? options.version,\n transaction,\n );\n } catch (cause) {\n end(databaseError(options.database, 'upgrade', cause));\n abortUpgrade();\n }\n };\n request.onerror = () => {\n end(databaseError(options.database, 'open', request.error));\n cleanup();\n };\n request.onsuccess = () => {\n const db = request.result;\n if (state.ended) db.close();\n else {\n state.ended = true;\n db.onversionchange = () => {\n db.close();\n };\n resolve(db);\n }\n cleanup();\n };\n });\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { IndexedDBOperation, IndexedDBResult, IndexedDBStores } from '../indexeddb-types.js';
|
|
2
|
+
export type RawResult = IndexedDBResult<IndexedDBStores>;
|
|
3
|
+
/** Queue requests synchronously and resolve only from transaction complete. */
|
|
4
|
+
export declare function transact(db: IDBDatabase, operations: readonly IndexedDBOperation<IndexedDBStores>[], signal: AbortSignal): Promise<readonly RawResult[]>;
|