@gyral/core 0.1.0 → 0.3.0
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 +112 -0
- package/LICENSE +1 -1
- package/NOTICE +1 -1
- package/README.md +9 -7
- package/dist/children.d.ts +5 -2
- package/dist/children.js +8 -3
- package/dist/children.js.map +1 -1
- package/dist/command.js +6 -0
- package/dist/command.js.map +1 -1
- package/dist/compiler/ast.d.ts +21 -0
- package/dist/compiler/ast.js +145 -0
- package/dist/compiler/ast.js.map +1 -0
- package/dist/compiler/compile.d.ts +38 -0
- package/dist/compiler/compile.js +129 -0
- package/dist/compiler/compile.js.map +1 -0
- package/dist/compiler/hooks.d.ts +18 -0
- package/dist/compiler/hooks.js +186 -0
- package/dist/compiler/hooks.js.map +1 -0
- package/dist/compiler/parse5-check.d.ts +21 -0
- package/dist/compiler/parse5-check.js +55 -0
- package/dist/compiler/parse5-check.js.map +1 -0
- package/dist/compiler/scan.d.ts +31 -0
- package/dist/compiler/scan.js +152 -0
- package/dist/compiler/scan.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/define.d.ts +2 -2
- package/dist/define.js +35 -334
- package/dist/define.js.map +1 -1
- package/dist/devtools-events.d.ts +5 -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 +1 -0
- package/dist/devtools.js +3 -0
- 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-types.d.ts +5 -3
- package/dist/element-types.js.map +1 -1
- package/dist/element.d.ts +3 -0
- package/dist/element.js +269 -0
- package/dist/element.js.map +1 -0
- package/dist/eslint/imports.d.ts +24 -0
- package/dist/eslint/imports.js +78 -0
- package/dist/eslint/imports.js.map +1 -0
- package/dist/eslint/index.d.ts +15 -0
- package/dist/eslint/index.js +15 -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 +5 -0
- package/dist/eslint/template-rule.js +66 -0
- package/dist/eslint/template-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 +9 -2
- package/dist/focus.js +17 -2
- package/dist/focus.js.map +1 -1
- 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/hooks/labelled-by.d.ts +13 -0
- package/dist/hooks/labelled-by.js +51 -0
- package/dist/hooks/labelled-by.js.map +1 -0
- package/dist/host-model.d.ts +48 -0
- package/dist/host-model.js +155 -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.d.ts +13 -19
- package/dist/hydration.js +45 -45
- package/dist/hydration.js.map +1 -1
- package/dist/index.d.ts +9 -16
- package/dist/index.js +9 -16
- package/dist/index.js.map +1 -1
- package/dist/intent.d.ts +31 -8
- package/dist/intent.js +82 -27
- package/dist/intent.js.map +1 -1
- package/dist/internal/interpreter.d.ts +7 -1
- package/dist/internal/interpreter.js +118 -73
- package/dist/internal/interpreter.js.map +1 -1
- 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 +3 -52
- package/dist/light-dom.js +5 -100
- package/dist/light-dom.js.map +1 -1
- package/dist/prop.d.ts +66 -0
- package/dist/prop.js +22 -0
- package/dist/prop.js.map +1 -0
- package/dist/props.d.ts +52 -21
- package/dist/props.js +150 -34
- package/dist/props.js.map +1 -1
- package/dist/scheduler.d.ts +39 -0
- package/dist/scheduler.js +230 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/server-component.d.ts +10 -0
- package/dist/server-component.js +102 -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 +28 -0
- package/dist/server.js +50 -0
- package/dist/server.js.map +1 -0
- package/dist/settled.d.ts +10 -0
- package/dist/settled.js +40 -0
- package/dist/settled.js.map +1 -0
- package/dist/states.d.ts +3 -3
- package/dist/states.js +4 -7
- package/dist/states.js.map +1 -1
- package/dist/store-binding.d.ts +6 -3
- package/dist/store-binding.js +5 -6
- package/dist/store-binding.js.map +1 -1
- package/dist/store-scope.d.ts +6 -7
- package/dist/store-scope.js +11 -26
- package/dist/store-scope.js.map +1 -1
- package/dist/store.d.ts +3 -0
- package/dist/store.js +9 -2
- 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/transitions.d.ts +5 -6
- package/dist/transitions.js +11 -20
- package/dist/transitions.js.map +1 -1
- package/dist/types.d.ts +19 -23
- package/dist/types.js.map +1 -1
- package/dist/view/attributes.d.ts +6 -0
- package/dist/view/attributes.js +10 -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 +21 -0
- package/dist/view/index.js +21 -0
- package/dist/view/index.js.map +1 -0
- package/dist/view/normalize/check.d.ts +20 -0
- package/dist/view/normalize/check.js +78 -0
- package/dist/view/normalize/check.js.map +1 -0
- package/dist/view/normalize/emit.d.ts +13 -0
- package/dist/view/normalize/emit.js +136 -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 +7 -0
- package/dist/view/normalize/id.js +48 -0
- package/dist/view/normalize/id.js.map +1 -0
- package/dist/view/normalize/normalize.d.ts +15 -0
- package/dist/view/normalize/normalize.js +36 -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 +30 -0
- package/dist/view/normalize/rules.js +90 -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/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 +51 -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 +59 -0
- package/dist/view/normalize/tree.js +190 -0
- package/dist/view/normalize/tree.js.map +1 -0
- package/dist/view/normalize/types.d.ts +126 -0
- package/dist/view/normalize/types.js +26 -0
- package/dist/view/normalize/types.js.map +1 -0
- package/dist/view/normalize/whitespace.d.ts +2 -0
- package/dist/view/normalize/whitespace.js +182 -0
- 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 +8 -0
- package/dist/view/prepare.js +57 -0
- package/dist/view/prepare.js.map +1 -0
- package/dist/view/registry.d.ts +63 -0
- package/dist/view/registry.js +19 -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 +77 -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 +269 -0
- package/dist/view/render/adopt.js.map +1 -0
- package/dist/view/render/attr-parts.d.ts +61 -0
- package/dist/view/render/attr-parts.js +229 -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 +170 -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/hook-part.d.ts +3 -0
- package/dist/view/render/hook-part.js +20 -0
- package/dist/view/render/hook-part.js.map +1 -0
- package/dist/view/render/hooks.d.ts +40 -0
- package/dist/view/render/hooks.js +46 -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/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 +53 -0
- package/dist/view/render/mismatch.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 +18 -0
- package/dist/view/render/raw.js +68 -0
- package/dist/view/render/raw.js.map +1 -0
- package/dist/view/render/render.d.ts +12 -0
- package/dist/view/render/render.js +60 -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/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 +14 -0
- package/dist/view/render/warn.js +69 -0
- package/dist/view/render/warn.js.map +1 -0
- package/dist/view/server/component.d.ts +9 -0
- package/dist/view/server/component.js +42 -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 +28 -0
- package/dist/view/server/index.js +72 -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 +57 -0
- package/dist/view/server/tags.js +121 -0
- package/dist/view/server/tags.js.map +1 -0
- package/dist/view/server/values.d.ts +16 -0
- package/dist/view/server/values.js +86 -0
- package/dist/view/server/values.js.map +1 -0
- package/dist/view/server/writer.d.ts +16 -0
- package/dist/view/server/writer.js +155 -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 +3 -0
- package/dist/view/template-element.js +25 -0
- package/dist/view/template-element.js.map +1 -0
- package/dist/view/template.d.ts +21 -0
- package/dist/view/template.js +30 -0
- package/dist/view/template.js.map +1 -0
- package/dist/vite.d.ts +45 -6
- package/dist/vite.js +150 -25
- package/dist/vite.js.map +1 -1
- package/package.json +41 -7
- 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/internal/runtime.d.ts +0 -7
- package/dist/internal/runtime.js +0 -8
- package/dist/internal/runtime.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/live-boolean.d.ts +0 -22
- package/dist/live-boolean.js +0 -34
- package/dist/live-boolean.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/textarea.d.ts +0 -26
- package/dist/textarea.js +0 -85
- package/dist/textarea.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interpreter.js","sourceRoot":"","sources":["../../src/internal/interpreter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Data, Duration, Effect, Fiber, Schedule } from 'effect';\nimport { DEVTOOLS_ENABLED } from '#devtools';\nimport type { AnyDriver, Command, Concurrency, RetryPolicy } from '../command.js';\nimport type { CommandPhase, CommandTrace } from '../devtools-events.js';\nimport { fork } from './runtime.js';\n\nclass DriverFailure extends Data.TaggedError('DriverFailure')<{ readonly cause: unknown }> {}\n\ntype Running = Fiber.RuntimeFiber<void>;\n\n/** Runs commands for one connected element. Disposed on disconnect. */\nexport interface Interpreter<M> {\n readonly run: (cmd: Command<M>) => void;\n readonly dispose: () => void;\n}\n\nconst isRunning = (fiber: Running | undefined): fiber is Running =>\n fiber !== undefined && fiber.unsafePoll() === null;\n\nconst withRetry = <A>(\n attempt: Effect.Effect<A, DriverFailure>,\n policy: RetryPolicy | undefined,\n): Effect.Effect<A, DriverFailure> => {\n if (policy === undefined || policy.times <= 0) return attempt;\n const base = Duration.millis(policy.delayMs ?? 0);\n const delays: Schedule.Schedule<unknown> =\n policy.backoff === 'exponential' ? Schedule.exponential(base) : Schedule.spaced(base);\n return Effect.retry(attempt, delays.pipe(Schedule.intersect(Schedule.recurs(policy.times))));\n};\n\n/** Reports one command's lifecycle to devtools (ADR 0017); undefined in production. */\ntype Report = ((phase: CommandPhase, result?: unknown) => void) | undefined;\n\nconst execute = <M>(\n driver: AnyDriver,\n cmd: Command<M>,\n dispatch: (msg: M) => void,\n report: Report,\n): Effect.Effect<void> => {\n const deliver = (output: unknown): void => {\n try {\n const msg = cmd.onSuccess(output);\n if (msg !== undefined) dispatch(msg);\n } catch (defect) {\n console.error('gyral: command mapper threw', defect);\n }\n };\n const attempt = Effect.tryPromise({\n try: (signal) => {\n let settled = false;\n const emit = (output: unknown): void => {\n if (!settled && !signal.aborted) deliver(output);\n };\n // The input type was erased by command(); it was built for this driver's name.\n const result = Promise.resolve(driver.run(cmd.input as never, { signal, emit }));\n return result.finally(() => {\n settled = true;\n });\n },\n catch: (cause) => new DriverFailure({ cause }),\n });\n const traced =\n DEVTOOLS_ENABLED && report !== undefined\n ? withRetry(attempt, driver.retry).pipe(\n Effect.onInterrupt(() =>\n Effect.sync(() => {\n report('interrupted');\n }),\n ),\n )\n : withRetry(attempt, driver.retry);\n return traced.pipe(\n Effect.matchEffect({\n onSuccess: (output) => {\n if (DEVTOOLS_ENABLED) report?.('settled', output);\n return Effect.succeed(cmd.onSuccess(output));\n },\n onFailure: (failure) => {\n const error = driver.toError === undefined ? failure.cause : driver.toError(failure.cause);\n if (DEVTOOLS_ENABLED) report?.('failed', error);\n return cmd.onFailure === undefined\n ? Effect.logWarning(`gyral: unhandled failure from driver \"${driver.name}\"`, error).pipe(\n Effect.as(undefined),\n )\n : Effect.succeed(cmd.onFailure(error));\n },\n }),\n Effect.flatMap((msg) =>\n Effect.sync(() => {\n if (msg !== undefined) dispatch(msg);\n }),\n ),\n Effect.catchAllDefect((defect) => Effect.logError('gyral: command mapper threw', defect)),\n );\n};\n\nexport function makeInterpreter<M>(\n resolve: (driver: AnyDriver) => AnyDriver,\n dispatch: (msg: M) => void,\n trace?: CommandTrace,\n): Interpreter<M> {\n const reporter = (driver: string, lane: string, policy: Concurrency, input: unknown): Report =>\n trace === undefined\n ? undefined\n : (phase, result) => {\n trace({\n phase,\n driver,\n lane,\n policy,\n input,\n ...(result === undefined ? {} : { result }),\n });\n };\n const lanes = new Map<string, Running>();\n const all = new Set<Running>();\n let active = true;\n const guardedDispatch = (msg: M): void => {\n if (active) dispatch(msg);\n };\n\n const track = (lane: string, fiber: Running): void => {\n if (!isRunning(fiber)) return;\n lanes.set(lane, fiber);\n all.add(fiber);\n fiber.addObserver(() => {\n all.delete(fiber);\n if (lanes.get(lane) === fiber) lanes.delete(lane);\n });\n };\n\n const run = (cmd: Command<M>): void => {\n if (!active) return;\n const driver = resolve(cmd.driver);\n const lane = cmd.key ?? driver.name;\n const policy = cmd.concurrency ?? driver.concurrency ?? 'merge';\n const previous = lanes.get(lane);\n const inFlight = isRunning(previous) ? previous : undefined;\n const report = DEVTOOLS_ENABLED ? reporter(driver.name, lane, policy, cmd.input) : undefined;\n let program = execute(driver, cmd, guardedDispatch, report);\n if (inFlight !== undefined && policy === 'exhaust') {\n if (DEVTOOLS_ENABLED) report?.('dropped');\n return;\n }\n if (DEVTOOLS_ENABLED) report?.('issued');\n if (inFlight !== undefined) {\n if (policy === 'switch') program = Effect.zipRight(Fiber.interrupt(inFlight), program);\n if (policy === 'queue') program = Effect.zipRight(Fiber.await(inFlight), program);\n }\n track(lane, fork(program));\n };\n\n const dispose = (): void => {\n active = false;\n fork(Fiber.interruptAll([...all]));\n all.clear();\n lanes.clear();\n };\n\n return { run, dispose };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"interpreter.js","sourceRoot":"","sources":["../../src/internal/interpreter.ts"],"names":[],"mappings":"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","sourcesContent":["import { DEVTOOLS_ENABLED } from '#devtools';\nimport type { AnyDriver, Command, Concurrency, DriverOverrides, RetryPolicy } from '../command.js';\nimport type { CommandPhase, CommandTrace } from '../devtools-events.js';\nimport { providedDriver } from '../drivers-scope.js';\nimport type { FeatureHost } from '../features.js';\n\n// The command interpreter (ADR 0015: hand-written, no runtime dependencies). Each running command is a task with its own AbortController; lanes hold the\n// latest task per key. Interruption is `controller.abort()`, retry schedules are timers\n// that cancel on abort, and `queue` chains on the previous task's promise.\n\n/** Runs commands for one connected element. Disposed on disconnect. */\nexport interface Interpreter<M> {\n readonly run: (cmd: Command<M>) => void;\n readonly dispose: () => void;\n}\n\ninterface Task {\n readonly controller: AbortController;\n done: Promise<void>;\n running: boolean;\n}\n\n/** Reports one command's lifecycle to devtools (ADR 0017); undefined in production. */\ntype Report = ((phase: CommandPhase, result?: unknown) => void) | undefined;\n\n/** Rejects when `signal` aborts. Marked handled so a losing race never reports it. */\nconst aborted = (signal: AbortSignal): Promise<never> => {\n const promise = new Promise<never>((_resolve, reject) => {\n // Callers check `signal.aborted`, never the reason.\n const interrupt = (): void => {\n reject(signal.reason as Error);\n };\n if (signal.aborted) interrupt();\n else signal.addEventListener('abort', interrupt, { once: true });\n });\n promise.catch(() => undefined);\n return promise;\n};\n\n/** Waits `ms`, or rejects as soon as `signal` aborts. */\nconst sleep = (ms: number, signal: AbortSignal): Promise<void> =>\n Promise.race([\n new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, ms);\n signal.addEventListener(\n 'abort',\n () => {\n clearTimeout(timer);\n },\n { once: true },\n );\n }),\n aborted(signal),\n ]);\n\n/** Delay before retry number `retry` (0-based): fixed, or doubling from `delayMs`. */\nconst delayFor = (policy: RetryPolicy, retry: number): number => {\n const base = policy.delayMs ?? 0;\n return policy.backoff === 'exponential' ? base * 2 ** retry : base;\n};\n\nasync function attemptWithRetry(\n driver: AnyDriver,\n cmd: Command<unknown>,\n signal: AbortSignal,\n emit: (output: unknown) => void,\n): Promise<unknown> {\n const policy = driver.retry;\n for (let retry = 0; ; retry += 1) {\n try {\n // The input type was erased by command(); it was built for this driver's name.\n const result = Promise.resolve(driver.run(cmd.input as never, { signal, emit }));\n return await Promise.race([result, aborted(signal)]);\n } catch (cause) {\n if (signal.aborted || policy === undefined || retry >= policy.times) throw cause;\n await sleep(delayFor(policy, retry), signal);\n }\n }\n}\n\n/** Maps a result to a message and dispatches it; a throwing mapper is logged, not fatal. */\nconst deliver = <M>(map: () => M | undefined, dispatch: (msg: M) => void): void => {\n try {\n const msg = map();\n if (msg !== undefined) dispatch(msg);\n } catch (defect) {\n console.error('gyral: command mapper threw', defect);\n }\n};\n\nasync function execute<M>(\n driver: AnyDriver,\n cmd: Command<M>,\n signal: AbortSignal,\n dispatch: (msg: M) => void,\n report: Report,\n): Promise<void> {\n let settled = false;\n const emit = (output: unknown): void => {\n if (!settled && !signal.aborted) deliver(() => cmd.onSuccess(output), dispatch);\n };\n if (DEVTOOLS_ENABLED && report !== undefined) {\n signal.addEventListener(\n 'abort',\n () => {\n if (!settled) report('interrupted');\n },\n { once: true },\n );\n }\n let output: unknown;\n try {\n output = await attemptWithRetry(driver, cmd, signal, emit);\n } catch (cause) {\n if (signal.aborted) return; // interrupted: reported by the abort listener\n settled = true;\n const error = driver.toError === undefined ? cause : driver.toError(cause);\n if (DEVTOOLS_ENABLED) report?.('failed', error);\n if (cmd.onFailure === undefined) {\n console.warn(`gyral: unhandled failure from driver \"${driver.name}\"`, error);\n return;\n }\n const onFailure = cmd.onFailure;\n deliver(() => onFailure(error), dispatch);\n return;\n }\n if (signal.aborted) return;\n settled = true;\n if (DEVTOOLS_ENABLED) report?.('settled', output);\n deliver(() => cmd.onSuccess(output), dispatch);\n}\n\nexport function makeInterpreter<M>(\n resolve: (driver: AnyDriver) => AnyDriver,\n dispatch: (msg: M) => void,\n trace?: CommandTrace,\n): Interpreter<M> {\n const reporter = (driver: string, lane: string, policy: Concurrency, input: unknown): Report =>\n trace === undefined\n ? undefined\n : (phase, result) => {\n trace({\n phase,\n driver,\n lane,\n policy,\n input,\n ...(result === undefined ? {} : { result }),\n });\n };\n const lanes = new Map<string, Task>();\n const all = new Set<Task>();\n let active = true;\n const guardedDispatch = (msg: M): void => {\n if (active) dispatch(msg);\n };\n\n const start = (\n lane: string,\n driver: AnyDriver,\n cmd: Command<M>,\n report: Report,\n after?: Task,\n ): void => {\n const controller = new AbortController();\n const task: Task = { controller, running: true, done: Promise.resolve() };\n const body = async (): Promise<void> => {\n if (after !== undefined) await after.done;\n if (!controller.signal.aborted) {\n await execute(driver, cmd, controller.signal, guardedDispatch, report);\n }\n };\n task.done = body().finally(() => {\n task.running = false;\n all.delete(task);\n if (lanes.get(lane) === task) lanes.delete(lane);\n });\n lanes.set(lane, task);\n all.add(task);\n };\n\n const run = (cmd: Command<M>): void => {\n if (!active) return;\n const driver = resolve(cmd.driver);\n const lane = cmd.key ?? driver.name;\n const policy = cmd.concurrency ?? driver.concurrency ?? 'merge';\n const previous = lanes.get(lane);\n const inFlight = previous?.running === true ? previous : undefined;\n const report = DEVTOOLS_ENABLED ? reporter(driver.name, lane, policy, cmd.input) : undefined;\n if (inFlight !== undefined && policy === 'exhaust') {\n if (DEVTOOLS_ENABLED) report?.('dropped');\n return;\n }\n if (DEVTOOLS_ENABLED) report?.('issued');\n if (inFlight !== undefined && policy === 'switch') inFlight.controller.abort();\n start(\n lane,\n driver,\n cmd,\n report,\n inFlight !== undefined && policy === 'queue' ? inFlight : undefined,\n );\n };\n\n const dispose = (): void => {\n active = false;\n for (const task of all) task.controller.abort();\n all.clear();\n lanes.clear();\n };\n\n return { run, dispose };\n}\n\n/**\n * A component's interpreter (registered by `command()`, features.ts). Drivers resolve by name:\n * el.drivers → nearest provider → spec.drivers → the command's own (gyral-czi.35).\n */\nexport const hostInterpreter = <M>(\n el: FeatureHost,\n drivers: DriverOverrides | undefined,\n dispatch: (msg: M) => void,\n trace: CommandTrace | undefined,\n): Interpreter<M> =>\n makeInterpreter(\n (driver) =>\n el.drivers[driver.name] ??\n providedDriver(el, driver.name) ??\n drivers?.[driver.name] ??\n driver,\n dispatch,\n trace,\n );\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fallback for browsers without invoker commands: a click on a `command="--…"` invoker inside
|
|
3
|
+
* `root` dispatches a `command` event on its `commandfor` target (same tree scope), with the
|
|
4
|
+
* `command` and `source` properties a native `CommandEvent` has.
|
|
5
|
+
*/
|
|
6
|
+
export declare function shimInvokers(root: Node): void;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** The custom-command invoker an event passed through, if any. */
|
|
2
|
+
function invokerIn(event) {
|
|
3
|
+
for (const node of event.composedPath()) {
|
|
4
|
+
if (node instanceof Element &&
|
|
5
|
+
node.getAttribute('command')?.startsWith('--') === true &&
|
|
6
|
+
node.hasAttribute('commandfor')) {
|
|
7
|
+
return node;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Fallback for browsers without invoker commands: a click on a `command="--…"` invoker inside
|
|
14
|
+
* `root` dispatches a `command` event on its `commandfor` target (same tree scope), with the
|
|
15
|
+
* `command` and `source` properties a native `CommandEvent` has.
|
|
16
|
+
*/
|
|
17
|
+
export function shimInvokers(root) {
|
|
18
|
+
root.addEventListener('click', (event) => {
|
|
19
|
+
const invoker = invokerIn(event);
|
|
20
|
+
const id = invoker?.getAttribute('commandfor');
|
|
21
|
+
const command = invoker?.getAttribute('command');
|
|
22
|
+
if (invoker === undefined || id == null || command == null)
|
|
23
|
+
return;
|
|
24
|
+
const scope = invoker.getRootNode();
|
|
25
|
+
const target = scope.getElementById(id);
|
|
26
|
+
if (target === null)
|
|
27
|
+
return;
|
|
28
|
+
const info = { command, source: invoker };
|
|
29
|
+
target.dispatchEvent(Object.assign(new Event('command', { cancelable: true }), info));
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=invokers-shim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invokers-shim.js","sourceRoot":"","sources":["../src/invokers-shim.ts"],"names":[],"mappings":"AAKA,kEAAkE;AAClE,SAAS,SAAS,CAAC,KAAY;IAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,CAAC;QACxC,IACE,IAAI,YAAY,OAAO;YACvB,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI;YACvD,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,EAC/B,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,IAAU;IACrC,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QACvC,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,EAAE,GAAG,OAAO,EAAE,YAAY,CAAC,YAAY,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;QACjD,IAAI,OAAO,KAAK,SAAS,IAAI,EAAE,IAAI,IAAI,IAAI,OAAO,IAAI,IAAI;YAAE,OAAO;QACnE,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAA2B,CAAC;QAC7D,MAAM,MAAM,GAAG,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;QACxC,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO;QAC5B,MAAM,IAAI,GAAgB,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;QACvD,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IACxF,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["// The invoker-command fallback (gyral-czi.6, ADR 0003 tier 3): loaded with import() by a\n// component that listens for `command` intents in a browser without `CommandEvent`\n// (intent.ts). Remove it when invoker commands are widely available (2028-06-12).\nimport type { CommandInfo } from './invokers.js';\n\n/** The custom-command invoker an event passed through, if any. */\nfunction invokerIn(event: Event): Element | undefined {\n for (const node of event.composedPath()) {\n if (\n node instanceof Element &&\n node.getAttribute('command')?.startsWith('--') === true &&\n node.hasAttribute('commandfor')\n ) {\n return node;\n }\n }\n return undefined;\n}\n\n/**\n * Fallback for browsers without invoker commands: a click on a `command=\"--…\"` invoker inside\n * `root` dispatches a `command` event on its `commandfor` target (same tree scope), with the\n * `command` and `source` properties a native `CommandEvent` has.\n */\nexport function shimInvokers(root: Node): void {\n root.addEventListener('click', (event) => {\n const invoker = invokerIn(event);\n const id = invoker?.getAttribute('commandfor');\n const command = invoker?.getAttribute('command');\n if (invoker === undefined || id == null || command == null) return;\n const scope = invoker.getRootNode() as Document | ShadowRoot;\n const target = scope.getElementById(id);\n if (target === null) return;\n const info: CommandInfo = { command, source: invoker };\n target.dispatchEvent(Object.assign(new Event('command', { cancelable: true }), info));\n });\n}\n"]}
|
package/dist/invokers.d.ts
CHANGED
|
@@ -6,10 +6,8 @@ export interface CommandInfo {
|
|
|
6
6
|
}
|
|
7
7
|
/** Native invoker commands available? */
|
|
8
8
|
export declare const invokersSupported: () => boolean;
|
|
9
|
-
/** The command carried by a native `CommandEvent` or by Gyral's fallback event. */
|
|
10
|
-
export declare function commandOf(event: Event): CommandInfo | undefined;
|
|
11
9
|
/**
|
|
12
|
-
*
|
|
13
|
-
* `
|
|
10
|
+
* The command carried by a `CommandEvent`, or by Gyral's fallback event, which has the same
|
|
11
|
+
* `command` and `source` properties.
|
|
14
12
|
*/
|
|
15
|
-
export declare function
|
|
13
|
+
export declare function commandOf(event: Event): CommandInfo | undefined;
|
package/dist/invokers.js
CHANGED
|
@@ -5,60 +5,20 @@
|
|
|
5
5
|
//
|
|
6
6
|
// Browsers with invoker commands dispatch a `CommandEvent` on the target. Elsewhere (invokers
|
|
7
7
|
// are Baseline newly available, not widely) Gyral dispatches an equivalent `command` event when
|
|
8
|
-
// a custom-command (`--…`) invoker inside a component is clicked, so the same markup works
|
|
9
|
-
//
|
|
8
|
+
// a custom-command (`--…`) invoker inside a component is clicked, so the same markup works:
|
|
9
|
+
// invokers-shim.ts, an ADR 0003 tier-3 fallback loaded with import() only there, and only by
|
|
10
|
+
// components listening for `command`. Built-in commands (`show-modal`, …) are left to the
|
|
11
|
+
// browser.
|
|
10
12
|
/** Native invoker commands available? */
|
|
11
13
|
export const invokersSupported = () => 'CommandEvent' in globalThis;
|
|
12
|
-
/** The command carried by a native `CommandEvent` or by Gyral's fallback event. */
|
|
13
|
-
export function commandOf(event) {
|
|
14
|
-
if (event.type !== 'command')
|
|
15
|
-
return undefined;
|
|
16
|
-
if (event instanceof CustomEvent) {
|
|
17
|
-
const detail = event.detail;
|
|
18
|
-
return typeof detail?.command === 'string'
|
|
19
|
-
? { command: detail.command, source: detail.source }
|
|
20
|
-
: undefined;
|
|
21
|
-
}
|
|
22
|
-
const native = event;
|
|
23
|
-
return typeof native.command === 'string'
|
|
24
|
-
? {
|
|
25
|
-
command: native.command,
|
|
26
|
-
source: native.source instanceof Element ? native.source : undefined,
|
|
27
|
-
}
|
|
28
|
-
: undefined;
|
|
29
|
-
}
|
|
30
|
-
/** The custom-command invoker an event passed through, if any. */
|
|
31
|
-
function invokerIn(event) {
|
|
32
|
-
for (const node of event.composedPath()) {
|
|
33
|
-
if (node instanceof Element &&
|
|
34
|
-
node.getAttribute('command')?.startsWith('--') === true &&
|
|
35
|
-
node.hasAttribute('commandfor')) {
|
|
36
|
-
return node;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return undefined;
|
|
40
|
-
}
|
|
41
14
|
/**
|
|
42
|
-
*
|
|
43
|
-
* `
|
|
15
|
+
* The command carried by a `CommandEvent`, or by Gyral's fallback event, which has the same
|
|
16
|
+
* `command` and `source` properties.
|
|
44
17
|
*/
|
|
45
|
-
export function
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const id = invoker?.getAttribute('commandfor');
|
|
51
|
-
const command = invoker?.getAttribute('command');
|
|
52
|
-
if (invoker === undefined || id == null || command == null)
|
|
53
|
-
return;
|
|
54
|
-
const scope = invoker.getRootNode();
|
|
55
|
-
const target = scope.getElementById(id);
|
|
56
|
-
if (target === null)
|
|
57
|
-
return;
|
|
58
|
-
target.dispatchEvent(new CustomEvent('command', {
|
|
59
|
-
detail: { command, source: invoker },
|
|
60
|
-
cancelable: true,
|
|
61
|
-
}));
|
|
62
|
-
});
|
|
18
|
+
export function commandOf(event) {
|
|
19
|
+
const { type, command, source } = event;
|
|
20
|
+
return type === 'command' && typeof command === 'string'
|
|
21
|
+
? { command, source: source instanceof Element ? source : undefined }
|
|
22
|
+
: undefined;
|
|
63
23
|
}
|
|
64
24
|
//# sourceMappingURL=invokers.js.map
|
package/dist/invokers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invokers.js","sourceRoot":"","sources":["../src/invokers.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,EAAE;AACF,6EAA6E;AAC7E,mFAAmF;AACnF,EAAE;AACF,8FAA8F;AAC9F,gGAAgG;AAChG,4FAA4F;AAC5F,
|
|
1
|
+
{"version":3,"file":"invokers.js","sourceRoot":"","sources":["../src/invokers.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,EAAE;AACF,6EAA6E;AAC7E,mFAAmF;AACnF,EAAE;AACF,8FAA8F;AAC9F,gGAAgG;AAChG,4FAA4F;AAC5F,6FAA6F;AAC7F,0FAA0F;AAC1F,WAAW;AASX,yCAAyC;AACzC,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAY,EAAE,CAAC,cAAc,IAAI,UAAU,CAAC;AAE7E;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAY;IACpC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAwD,CAAC;IAC3F,OAAO,IAAI,KAAK,SAAS,IAAI,OAAO,OAAO,KAAK,QAAQ;QACtD,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE;QACrE,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC","sourcesContent":["// Invoker commands as an intent source (gyral-czi.6, ADR 0001 addendum, ADR 0003).\n//\n// <button type=\"button\" commandfor=\"cart\" command=\"--clear\">Clear</button>\n// <section id=\"cart\" data-intent=${i.Clear} data-intent-on=\"command\">…</section>\n//\n// Browsers with invoker commands dispatch a `CommandEvent` on the target. Elsewhere (invokers\n// are Baseline newly available, not widely) Gyral dispatches an equivalent `command` event when\n// a custom-command (`--…`) invoker inside a component is clicked, so the same markup works:\n// invokers-shim.ts, an ADR 0003 tier-3 fallback loaded with import() only there, and only by\n// components listening for `command`. Built-in commands (`show-modal`, …) are left to the\n// browser.\n\nexport interface CommandInfo {\n /** The command, e.g. `--clear`. */\n readonly command: string;\n /** The invoker (the button) that sent it. */\n readonly source: Element | undefined;\n}\n\n/** Native invoker commands available? */\nexport const invokersSupported = (): boolean => 'CommandEvent' in globalThis;\n\n/**\n * The command carried by a `CommandEvent`, or by Gyral's fallback event, which has the same\n * `command` and `source` properties.\n */\nexport function commandOf(event: Event): CommandInfo | undefined {\n const { type, command, source } = event as Event & { command?: unknown; source?: unknown };\n return type === 'command' && typeof command === 'string'\n ? { command, source: source instanceof Element ? source : undefined }\n : undefined;\n}\n"]}
|
package/dist/islands.d.ts
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
export type HydrateStrategy = 'load' | 'idle' | 'visible' | 'interaction';
|
|
3
3
|
/** Server-written strategy for a deferred island; removed when the island is released. */
|
|
4
4
|
export declare const ISLAND_ATTRIBUTE = "data-gyral-hydrate";
|
|
5
|
-
/** Server side: marks the host as an island unless it hydrates on load. */
|
|
6
|
-
export declare function markIsland(host: Element, strategy: HydrateStrategy | undefined): void;
|
|
7
5
|
/**
|
|
8
6
|
* Client side: if `host` is a deferred island, releases it when its strategy fires. Called on
|
|
9
7
|
* connect; scheduling happens once per element.
|
package/dist/islands.js
CHANGED
|
@@ -1,20 +1,13 @@
|
|
|
1
1
|
// Lazy hydration islands (gyral-4k7.4, ADR 0012 addendum). A server-rendered component may
|
|
2
2
|
// hydrate later than page load: when the browser is idle, when it scrolls into view, or when
|
|
3
|
-
// the user first reaches for it. The server marks it with
|
|
4
|
-
//
|
|
5
|
-
//
|
|
3
|
+
// the user first reaches for it. The server marks it with `defer-hydration` plus the strategy
|
|
4
|
+
// (view/06-server.md); the client removes `defer-hydration` when the strategy fires, and
|
|
5
|
+
// define() finishes connecting from attributeChangedCallback (view/07-hydration.md "Islands").
|
|
6
6
|
/** Server-written strategy for a deferred island; removed when the island is released. */
|
|
7
7
|
export const ISLAND_ATTRIBUTE = 'data-gyral-hydrate';
|
|
8
8
|
const DEFER = 'defer-hydration';
|
|
9
9
|
/** Events that mean the user is about to interact: they arrive before the click itself. */
|
|
10
10
|
const INTERACTION_EVENTS = ['pointerover', 'pointerdown', 'focusin', 'touchstart'];
|
|
11
|
-
/** Server side: marks the host as an island unless it hydrates on load. */
|
|
12
|
-
export function markIsland(host, strategy) {
|
|
13
|
-
if (strategy === undefined || strategy === 'load')
|
|
14
|
-
return;
|
|
15
|
-
host.setAttribute(DEFER, '');
|
|
16
|
-
host.setAttribute(ISLAND_ATTRIBUTE, strategy);
|
|
17
|
-
}
|
|
18
11
|
const scheduled = new WeakSet();
|
|
19
12
|
/** requestIdleCallback is not Baseline widely available; fall back to a short timeout. */
|
|
20
13
|
function whenIdle(run) {
|
|
@@ -35,7 +28,7 @@ export function scheduleIsland(host) {
|
|
|
35
28
|
scheduled.add(host);
|
|
36
29
|
const release = () => {
|
|
37
30
|
host.removeAttribute(ISLAND_ATTRIBUTE);
|
|
38
|
-
host.removeAttribute(DEFER); //
|
|
31
|
+
host.removeAttribute(DEFER); // attributeChangedCallback connects it now
|
|
39
32
|
};
|
|
40
33
|
if (strategy === 'idle') {
|
|
41
34
|
whenIdle(release);
|
package/dist/islands.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"islands.js","sourceRoot":"","sources":["../src/islands.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,6FAA6F;AAC7F,
|
|
1
|
+
{"version":3,"file":"islands.js","sourceRoot":"","sources":["../src/islands.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,6FAA6F;AAC7F,8FAA8F;AAC9F,yFAAyF;AACzF,+FAA+F;AAK/F,0FAA0F;AAC1F,MAAM,CAAC,MAAM,gBAAgB,GAAG,oBAAoB,CAAC;AACrD,MAAM,KAAK,GAAG,iBAAiB,CAAC;AAEhC,2FAA2F;AAC3F,MAAM,kBAAkB,GAAG,CAAC,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,CAAU,CAAC;AAE5F,MAAM,SAAS,GAAG,IAAI,OAAO,EAAW,CAAC;AAIzC,0FAA0F;AAC1F,SAAS,QAAQ,CAAC,GAAe;IAC/B,MAAM,IAAI,GAAI,UAAqD,CAAC,mBAAmB,CAAC;IACxF,IAAI,IAAI,KAAK,SAAS;QAAE,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;;QACxC,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;AACpC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAiB;IAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;IACrD,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO;IAClF,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpB,MAAM,OAAO,GAAG,GAAS,EAAE;QACzB,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC;QACvC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,2CAA2C;IAC1E,CAAC,CAAC;IACF,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACxB,QAAQ,CAAC,OAAO,CAAC,CAAC;IACpB,CAAC;SAAM,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,IAAI,oBAAoB,CAAC,CAAC,OAAO,EAAE,EAAE;YACpD,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC;gBAClD,QAAQ,CAAC,UAAU,EAAE,CAAC;gBACtB,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC,CAAC,CAAC;QACH,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,GAAS,EAAE;YACtB,UAAU,CAAC,KAAK,EAAE,CAAC;YACnB,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,KAAK,MAAM,IAAI,IAAI,kBAAkB,EAAE,CAAC;YACtC,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["// Lazy hydration islands (gyral-4k7.4, ADR 0012 addendum). A server-rendered component may\n// hydrate later than page load: when the browser is idle, when it scrolls into view, or when\n// the user first reaches for it. The server marks it with `defer-hydration` plus the strategy\n// (view/06-server.md); the client removes `defer-hydration` when the strategy fires, and\n// define() finishes connecting from attributeChangedCallback (view/07-hydration.md \"Islands\").\n\n/** When a server-rendered component hydrates. `load` (the default) means right away. */\nexport type HydrateStrategy = 'load' | 'idle' | 'visible' | 'interaction';\n\n/** Server-written strategy for a deferred island; removed when the island is released. */\nexport const ISLAND_ATTRIBUTE = 'data-gyral-hydrate';\nconst DEFER = 'defer-hydration';\n\n/** Events that mean the user is about to interact: they arrive before the click itself. */\nconst INTERACTION_EVENTS = ['pointerover', 'pointerdown', 'focusin', 'touchstart'] as const;\n\nconst scheduled = new WeakSet<Element>();\n\ntype IdleCallback = (callback: () => void, options?: { timeout: number }) => number;\n\n/** requestIdleCallback is not Baseline widely available; fall back to a short timeout. */\nfunction whenIdle(run: () => void): void {\n const idle = (globalThis as { requestIdleCallback?: IdleCallback }).requestIdleCallback;\n if (idle === undefined) setTimeout(run, 200);\n else idle(run, { timeout: 2000 });\n}\n\n/**\n * Client side: if `host` is a deferred island, releases it when its strategy fires. Called on\n * connect; scheduling happens once per element.\n */\nexport function scheduleIsland(host: HTMLElement): void {\n const strategy = host.getAttribute(ISLAND_ATTRIBUTE);\n if (strategy === null || !host.hasAttribute(DEFER) || scheduled.has(host)) return;\n scheduled.add(host);\n const release = (): void => {\n host.removeAttribute(ISLAND_ATTRIBUTE);\n host.removeAttribute(DEFER); // attributeChangedCallback connects it now\n };\n if (strategy === 'idle') {\n whenIdle(release);\n } else if (strategy === 'visible') {\n const observer = new IntersectionObserver((entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n observer.disconnect();\n release();\n }\n });\n observer.observe(host);\n } else {\n const controller = new AbortController();\n const once = (): void => {\n controller.abort();\n release();\n };\n for (const type of INTERACTION_EVENTS) {\n host.addEventListener(type, once, { capture: true, signal: controller.signal });\n }\n }\n}\n"]}
|
package/dist/light-dom.d.ts
CHANGED
|
@@ -1,61 +1,12 @@
|
|
|
1
|
-
import { type CSSResultGroup, type CSSResultOrNative } from 'lit';
|
|
2
|
-
import { type Styles } from './styles.js';
|
|
3
1
|
interface SpecLike {
|
|
4
2
|
readonly shadow?: boolean;
|
|
5
|
-
readonly styles?: Styles;
|
|
6
3
|
}
|
|
7
4
|
export declare const isLight: (spec: SpecLike) => boolean;
|
|
8
|
-
/**
|
|
9
|
-
export declare function componentStyles(spec: SpecLike, tag: string): CSSResultGroup;
|
|
10
|
-
/**
|
|
11
|
-
* Is this class a light-DOM Gyral component? Used by @gyral/ssr to render its view as plain
|
|
12
|
-
* children instead of Declarative Shadow DOM.
|
|
13
|
-
*/
|
|
5
|
+
/** Is this class a light-DOM Gyral component (`shadow: false`)? */
|
|
14
6
|
export declare function isLightComponent(ctor: unknown): boolean;
|
|
15
7
|
/**
|
|
16
|
-
* Server-rendered light hosts carry this attribute (ADR 0014 addendum
|
|
17
|
-
*
|
|
8
|
+
* Server-rendered light hosts carry this attribute (ADR 0014 addendum, view/06-server.md
|
|
9
|
+
* "Components"), so a parent's hydration walk leaves a light child's content alone (view/07).
|
|
18
10
|
*/
|
|
19
11
|
export declare const LIGHT_ATTRIBUTE = "data-gyral-light";
|
|
20
|
-
/** Prefix @gyral/ssr puts on Lit's markers inside light views so no hydrate() walk sees them. */
|
|
21
|
-
export declare const HIDDEN_MARKER = "gyral:";
|
|
22
|
-
/** Server side: marks a light host so the client can scope its markers. */
|
|
23
|
-
export declare function markLightHost(host: Element): void;
|
|
24
|
-
/**
|
|
25
|
-
* Client side, on a server-rendered light host's first update: turns the host's own hidden
|
|
26
|
-
* markers back into Lit's, leaving nested light hosts' markers hidden until they hydrate.
|
|
27
|
-
* Returns whether the host's root part marker was found (so Lit can hydrate in place).
|
|
28
|
-
*/
|
|
29
|
-
export declare function revealLightMarkers(host: Element): boolean;
|
|
30
|
-
/** Lit's public `hydrate()` from `@lit-labs/ssr-client`. */
|
|
31
|
-
export type Hydrate = (value: unknown, container: HTMLElement | DocumentFragment, options?: object) => void;
|
|
32
|
-
/**
|
|
33
|
-
* Where `@gyral/ssr/hydrate` registers Lit's public `hydrate()` (gyral-czi.38). A global
|
|
34
|
-
* symbol, not an import, so core doesn't depend on `@lit-labs/ssr-client` and apps without
|
|
35
|
-
* SSR don't ship it.
|
|
36
|
-
*/
|
|
37
|
-
export declare const HYDRATE_KEY: unique symbol;
|
|
38
|
-
/**
|
|
39
|
-
* Lit's `hydrate()`, if a server-rendered app loaded `@gyral/ssr/hydrate`. Used for light hosts
|
|
40
|
-
* and, since gyral-czi.41, for server-rendered shadow roots too: Gyral hydrates both itself, so
|
|
41
|
-
* it never depends on Lit's hydrate support having patched LitElement before Lit evaluated.
|
|
42
|
-
*/
|
|
43
|
-
export declare const hydrator: () => Hydrate | undefined;
|
|
44
|
-
/**
|
|
45
|
-
* First update of a server-rendered (declarative) shadow root: hydrate the server's view in
|
|
46
|
-
* place with Lit's public hydrate(), which leaves the root part on the shadow root so the
|
|
47
|
-
* render() inside LitElement's update() updates it instead of appending a second copy
|
|
48
|
-
* (gyral-czi.41). Without `@gyral/ssr/hydrate` loaded, clear the server's view and let Lit
|
|
49
|
-
* render fresh, adopting the styles Lit's own createRenderRoot would have.
|
|
50
|
-
*/
|
|
51
|
-
export declare function hydrateShadow(root: ShadowRoot, view: unknown, options: object, styles: CSSResultOrNative[]): void;
|
|
52
|
-
/**
|
|
53
|
-
* First update of a server-rendered light host: reveal this host's own hidden markers now (not
|
|
54
|
-
* on connect: a deferred child connects mid-way through its parent's hydrate walk), then call
|
|
55
|
-
* Lit's public hydrate(). It leaves the root part on the host, so the render() inside
|
|
56
|
-
* LitElement's update() updates it in place instead of appending a second copy. No Lit private
|
|
57
|
-
* fields: their names are mangled in Lit's production build (ADR 0014, gyral-czi.38). Without
|
|
58
|
-
* `@gyral/ssr/hydrate` loaded, clear the server's view and let Lit render fresh.
|
|
59
|
-
*/
|
|
60
|
-
export declare function hydrateLight(host: HTMLElement, view: unknown, options: object): void;
|
|
61
12
|
export {};
|
package/dist/light-dom.js
CHANGED
|
@@ -1,109 +1,14 @@
|
|
|
1
|
-
// Light-DOM render mode (docs/design-docs/0014-light-dom.md)
|
|
2
|
-
|
|
3
|
-
import { toCssResultGroup } from './styles.js';
|
|
1
|
+
// Light-DOM render mode (docs/design-docs/0014-light-dom.md): `shadow: false` renders the view
|
|
2
|
+
// as the host's own children, styled by document CSS.
|
|
4
3
|
export const isLight = (spec) => spec.shadow === false;
|
|
5
|
-
/**
|
|
6
|
-
export function componentStyles(spec, tag) {
|
|
7
|
-
if (!isLight(spec))
|
|
8
|
-
return spec.styles === undefined ? [] : toCssResultGroup(spec.styles);
|
|
9
|
-
if (spec.styles !== undefined) {
|
|
10
|
-
console.warn(`<${tag}> has shadow: false, so its styles are ignored; use document CSS.`);
|
|
11
|
-
}
|
|
12
|
-
return [];
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Is this class a light-DOM Gyral component? Used by @gyral/ssr to render its view as plain
|
|
16
|
-
* children instead of Declarative Shadow DOM.
|
|
17
|
-
*/
|
|
4
|
+
/** Is this class a light-DOM Gyral component (`shadow: false`)? */
|
|
18
5
|
export function isLightComponent(ctor) {
|
|
19
6
|
const spec = ctor?.spec;
|
|
20
7
|
return spec !== undefined && isLight(spec);
|
|
21
8
|
}
|
|
22
9
|
/**
|
|
23
|
-
* Server-rendered light hosts carry this attribute (ADR 0014 addendum
|
|
24
|
-
*
|
|
10
|
+
* Server-rendered light hosts carry this attribute (ADR 0014 addendum, view/06-server.md
|
|
11
|
+
* "Components"), so a parent's hydration walk leaves a light child's content alone (view/07).
|
|
25
12
|
*/
|
|
26
13
|
export const LIGHT_ATTRIBUTE = 'data-gyral-light';
|
|
27
|
-
/** Prefix @gyral/ssr puts on Lit's markers inside light views so no hydrate() walk sees them. */
|
|
28
|
-
export const HIDDEN_MARKER = 'gyral:';
|
|
29
|
-
const LIT_MARKER = /^(?:lit-part|\/lit-part|lit-node)\b/;
|
|
30
|
-
/** Server side: marks a light host so the client can scope its markers. */
|
|
31
|
-
export function markLightHost(host) {
|
|
32
|
-
host.setAttribute(LIGHT_ATTRIBUTE, '');
|
|
33
|
-
}
|
|
34
|
-
/** Is the comment inside `host`'s own light view, not a nested light host's? */
|
|
35
|
-
function ownedBy(comment, host) {
|
|
36
|
-
for (let el = comment.parentElement; el !== null; el = el.parentElement) {
|
|
37
|
-
if (el === host)
|
|
38
|
-
return true;
|
|
39
|
-
if (el.hasAttribute(LIGHT_ATTRIBUTE))
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Client side, on a server-rendered light host's first update: turns the host's own hidden
|
|
46
|
-
* markers back into Lit's, leaving nested light hosts' markers hidden until they hydrate.
|
|
47
|
-
* Returns whether the host's root part marker was found (so Lit can hydrate in place).
|
|
48
|
-
*/
|
|
49
|
-
export function revealLightMarkers(host) {
|
|
50
|
-
const walker = document.createTreeWalker(host, NodeFilter.SHOW_COMMENT);
|
|
51
|
-
const own = [];
|
|
52
|
-
for (let node = walker.nextNode(); node !== null; node = walker.nextNode()) {
|
|
53
|
-
const comment = node;
|
|
54
|
-
const data = comment.data.slice(HIDDEN_MARKER.length);
|
|
55
|
-
if (comment.data.startsWith(HIDDEN_MARKER) && LIT_MARKER.test(data) && ownedBy(comment, host)) {
|
|
56
|
-
own.push(comment);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
for (const comment of own)
|
|
60
|
-
comment.data = comment.data.slice(HIDDEN_MARKER.length);
|
|
61
|
-
return own[0]?.data.startsWith('lit-part') === true;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Where `@gyral/ssr/hydrate` registers Lit's public `hydrate()` (gyral-czi.38). A global
|
|
65
|
-
* symbol, not an import, so core doesn't depend on `@lit-labs/ssr-client` and apps without
|
|
66
|
-
* SSR don't ship it.
|
|
67
|
-
*/
|
|
68
|
-
export const HYDRATE_KEY = Symbol.for('gyral.hydrate');
|
|
69
|
-
/**
|
|
70
|
-
* Lit's `hydrate()`, if a server-rendered app loaded `@gyral/ssr/hydrate`. Used for light hosts
|
|
71
|
-
* and, since gyral-czi.41, for server-rendered shadow roots too: Gyral hydrates both itself, so
|
|
72
|
-
* it never depends on Lit's hydrate support having patched LitElement before Lit evaluated.
|
|
73
|
-
*/
|
|
74
|
-
export const hydrator = () => {
|
|
75
|
-
const fn = globalThis[HYDRATE_KEY];
|
|
76
|
-
return typeof fn === 'function' ? fn : undefined;
|
|
77
|
-
};
|
|
78
|
-
/**
|
|
79
|
-
* First update of a server-rendered (declarative) shadow root: hydrate the server's view in
|
|
80
|
-
* place with Lit's public hydrate(), which leaves the root part on the shadow root so the
|
|
81
|
-
* render() inside LitElement's update() updates it instead of appending a second copy
|
|
82
|
-
* (gyral-czi.41). Without `@gyral/ssr/hydrate` loaded, clear the server's view and let Lit
|
|
83
|
-
* render fresh, adopting the styles Lit's own createRenderRoot would have.
|
|
84
|
-
*/
|
|
85
|
-
export function hydrateShadow(root, view, options, styles) {
|
|
86
|
-
const hydrate = hydrator();
|
|
87
|
-
if (hydrate !== undefined) {
|
|
88
|
-
hydrate(view, root, options);
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
root.replaceChildren();
|
|
92
|
-
adoptStyles(root, styles);
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* First update of a server-rendered light host: reveal this host's own hidden markers now (not
|
|
96
|
-
* on connect: a deferred child connects mid-way through its parent's hydrate walk), then call
|
|
97
|
-
* Lit's public hydrate(). It leaves the root part on the host, so the render() inside
|
|
98
|
-
* LitElement's update() updates it in place instead of appending a second copy. No Lit private
|
|
99
|
-
* fields: their names are mangled in Lit's production build (ADR 0014, gyral-czi.38). Without
|
|
100
|
-
* `@gyral/ssr/hydrate` loaded, clear the server's view and let Lit render fresh.
|
|
101
|
-
*/
|
|
102
|
-
export function hydrateLight(host, view, options) {
|
|
103
|
-
const hydrate = hydrator();
|
|
104
|
-
if (hydrate !== undefined && revealLightMarkers(host))
|
|
105
|
-
hydrate(view, host, options);
|
|
106
|
-
else
|
|
107
|
-
host.replaceChildren();
|
|
108
|
-
}
|
|
109
14
|
//# sourceMappingURL=light-dom.js.map
|
package/dist/light-dom.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"light-dom.js","sourceRoot":"","sources":["../src/light-dom.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"light-dom.js","sourceRoot":"","sources":["../src/light-dom.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,sDAAsD;AAMtD,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAc,EAAW,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC;AAE1E,mEAAmE;AACnE,MAAM,UAAU,gBAAgB,CAAC,IAAa;IAC5C,MAAM,IAAI,GAAI,IAA4C,EAAE,IAAI,CAAC;IACjE,OAAO,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,kBAAkB,CAAC","sourcesContent":["// Light-DOM render mode (docs/design-docs/0014-light-dom.md): `shadow: false` renders the view\n// as the host's own children, styled by document CSS.\n\ninterface SpecLike {\n readonly shadow?: boolean;\n}\n\nexport const isLight = (spec: SpecLike): boolean => spec.shadow === false;\n\n/** Is this class a light-DOM Gyral component (`shadow: false`)? */\nexport function isLightComponent(ctor: unknown): boolean {\n const spec = (ctor as { readonly spec?: SpecLike } | null)?.spec;\n return spec !== undefined && isLight(spec);\n}\n\n/**\n * Server-rendered light hosts carry this attribute (ADR 0014 addendum, view/06-server.md\n * \"Components\"), so a parent's hydration walk leaves a light child's content alone (view/07).\n */\nexport const LIGHT_ATTRIBUTE = 'data-gyral-light';\n"]}
|
package/dist/prop.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
declare const OUTPUT: unique symbol;
|
|
3
|
+
export type PropKind = 'string' | 'number' | 'boolean' | 'json' | 'value';
|
|
4
|
+
/** One declared prop: what a builder returns. */
|
|
5
|
+
export interface Prop<T> {
|
|
6
|
+
readonly kind: PropKind;
|
|
7
|
+
/** The attribute name, `false` for property only, `undefined` for the kebab-case default. */
|
|
8
|
+
readonly attribute: string | false | undefined;
|
|
9
|
+
/** Refines (string/number/boolean) or defines (json/value) the accepted values. */
|
|
10
|
+
readonly schema: StandardSchemaV1 | undefined;
|
|
11
|
+
/** A missing value is a bug: warned once per instance at first render. */
|
|
12
|
+
readonly required: boolean;
|
|
13
|
+
/** Used whenever the element's value is missing (`boolean` props default to `false`). */
|
|
14
|
+
readonly default?: unknown;
|
|
15
|
+
/** Type-only: the value components see. Never set. */
|
|
16
|
+
readonly [OUTPUT]?: () => T;
|
|
17
|
+
}
|
|
18
|
+
/** The props type of a table of builders: `PropsOf<typeof props>`. */
|
|
19
|
+
export type PropsOf<T extends Readonly<Record<string, Prop<unknown>>>> = {
|
|
20
|
+
readonly [K in keyof T]: T[K] extends Prop<infer V> ? V : never;
|
|
21
|
+
};
|
|
22
|
+
interface Common {
|
|
23
|
+
/** Attribute name, or `false` for property only. Default: kebab-case of the prop name. */
|
|
24
|
+
readonly attribute?: string | false;
|
|
25
|
+
}
|
|
26
|
+
type Schema<O> = StandardSchemaV1<unknown, O>;
|
|
27
|
+
type Out<S extends StandardSchemaV1> = StandardSchemaV1.InferOutput<S>;
|
|
28
|
+
interface Required {
|
|
29
|
+
readonly required: true;
|
|
30
|
+
readonly default?: undefined;
|
|
31
|
+
}
|
|
32
|
+
interface Defaulted<T> {
|
|
33
|
+
readonly required?: false;
|
|
34
|
+
readonly default: T;
|
|
35
|
+
}
|
|
36
|
+
interface Optional {
|
|
37
|
+
readonly required?: false;
|
|
38
|
+
readonly default?: undefined;
|
|
39
|
+
}
|
|
40
|
+
type Refined<O> = Common & {
|
|
41
|
+
readonly schema?: Schema<O>;
|
|
42
|
+
};
|
|
43
|
+
interface Scalar<B> {
|
|
44
|
+
<O extends B = B>(opts: Refined<O> & (Required | Defaulted<NoInfer<O>>)): Prop<O>;
|
|
45
|
+
<O extends B = B>(opts?: Refined<O> & Optional): Prop<O | undefined>;
|
|
46
|
+
}
|
|
47
|
+
interface WithSchema {
|
|
48
|
+
<S extends StandardSchemaV1>(schema: S, opts: Common & (Required | Defaulted<NoInfer<Out<S>>>)): Prop<Out<S>>;
|
|
49
|
+
<S extends StandardSchemaV1>(schema: S, opts?: Common & Optional): Prop<Out<S> | undefined>;
|
|
50
|
+
}
|
|
51
|
+
/** The prop builders. */
|
|
52
|
+
export declare const prop: {
|
|
53
|
+
/** Attribute parsed as is. */
|
|
54
|
+
readonly string: Scalar<string>;
|
|
55
|
+
/** Attribute parsed with `Number(v)`; empty or `NaN` is invalid. */
|
|
56
|
+
readonly number: Scalar<number>;
|
|
57
|
+
/** Attribute present → `true`, absent → `false` (the default). */
|
|
58
|
+
readonly boolean: <O extends boolean = boolean>(opts?: Refined<O> & {
|
|
59
|
+
readonly default?: NoInfer<O>;
|
|
60
|
+
}) => Prop<O>;
|
|
61
|
+
/** Attribute parsed with `JSON.parse`, then the schema. */
|
|
62
|
+
readonly json: WithSchema;
|
|
63
|
+
/** Property only: no attribute. Validated in development. */
|
|
64
|
+
readonly value: WithSchema;
|
|
65
|
+
};
|
|
66
|
+
export {};
|
package/dist/prop.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { features } from './features.js';
|
|
2
|
+
import { propFeature } from './props.js';
|
|
3
|
+
function make(kind, opts = {}, schema) {
|
|
4
|
+
features.props = propFeature; // components can declare props now (features.ts)
|
|
5
|
+
const value = opts.default !== undefined ? opts.default : kind === 'boolean' ? false : undefined;
|
|
6
|
+
const base = {
|
|
7
|
+
kind,
|
|
8
|
+
attribute: kind === 'value' ? false : opts.attribute,
|
|
9
|
+
schema: schema ?? opts.schema,
|
|
10
|
+
required: opts.required === true,
|
|
11
|
+
};
|
|
12
|
+
return value === undefined ? base : { ...base, default: value };
|
|
13
|
+
}
|
|
14
|
+
/** The prop builders. */
|
|
15
|
+
export const prop = {
|
|
16
|
+
string: (opts) => make('string', opts),
|
|
17
|
+
number: (opts) => make('number', opts),
|
|
18
|
+
boolean: ((opts) => make('boolean', opts)),
|
|
19
|
+
json: (schema, opts) => make('json', opts, schema),
|
|
20
|
+
value: (schema, opts) => make('value', opts, schema),
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=prop.js.map
|
package/dist/prop.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prop.js","sourceRoot":"","sources":["../src/prop.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAqEzC,SAAS,IAAI,CAAC,IAAc,EAAE,OAAgB,EAAE,EAAE,MAAyB;IACzE,QAAQ,CAAC,KAAK,GAAG,WAAW,CAAC,CAAC,iDAAiD;IAC/E,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACjG,MAAM,IAAI,GAAG;QACX,IAAI;QACJ,SAAS,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS;QACpD,MAAM,EAAE,MAAM,IAAI,IAAI,CAAC,MAAM;QAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ,KAAK,IAAI;KACjC,CAAC;IACF,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAClE,CAAC;AAED,yBAAyB;AACzB,MAAM,CAAC,MAAM,IAAI,GAab;IACF,MAAM,EAAE,CAAC,IAAc,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC;IAChD,MAAM,EAAE,CAAC,IAAc,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC;IAChD,OAAO,EAAE,CAAC,CAAC,IAAc,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAqC;IACxF,IAAI,EAAE,CAAC,MAAwB,EAAE,IAAc,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC;IAC9E,KAAK,EAAE,CAAC,MAAwB,EAAE,IAAc,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC;CACjF,CAAC","sourcesContent":["// Prop builders (docs/design-docs/view/05-element.md \"Props\"): every component input is\n// declared with a builder over Standard Schema, so \"parse at boundaries\" covers attributes.\n//\n// props: {\n// label: prop.string({ required: true }), // attribute \"label\"\n// minPrice: prop.number({ default: 0 }), // attribute \"min-price\"\n// items: prop.value(v.array(Item), { default: [] }), // property only\n// }\n//\n// A prop's type is inferred from its schema's output. The honesty rule (ADR 0007) holds by\n// construction: a prop without `required` or `default` includes `undefined`.\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { features } from './features.js';\nimport { propFeature } from './props.js';\n\ndeclare const OUTPUT: unique symbol;\n\nexport type PropKind = 'string' | 'number' | 'boolean' | 'json' | 'value';\n\n/** One declared prop: what a builder returns. */\nexport interface Prop<T> {\n readonly kind: PropKind;\n /** The attribute name, `false` for property only, `undefined` for the kebab-case default. */\n readonly attribute: string | false | undefined;\n /** Refines (string/number/boolean) or defines (json/value) the accepted values. */\n readonly schema: StandardSchemaV1 | undefined;\n /** A missing value is a bug: warned once per instance at first render. */\n readonly required: boolean;\n /** Used whenever the element's value is missing (`boolean` props default to `false`). */\n readonly default?: unknown;\n /** Type-only: the value components see. Never set. */\n readonly [OUTPUT]?: () => T;\n}\n\n/** The props type of a table of builders: `PropsOf<typeof props>`. */\nexport type PropsOf<T extends Readonly<Record<string, Prop<unknown>>>> = {\n readonly [K in keyof T]: T[K] extends Prop<infer V> ? V : never;\n};\n\ninterface Common {\n /** Attribute name, or `false` for property only. Default: kebab-case of the prop name. */\n readonly attribute?: string | false;\n}\n\ntype Schema<O> = StandardSchemaV1<unknown, O>;\ntype Out<S extends StandardSchemaV1> = StandardSchemaV1.InferOutput<S>;\n\ninterface Required {\n readonly required: true;\n readonly default?: undefined;\n}\ninterface Defaulted<T> {\n readonly required?: false;\n readonly default: T;\n}\ninterface Optional {\n readonly required?: false;\n readonly default?: undefined;\n}\n\ntype Refined<O> = Common & { readonly schema?: Schema<O> };\n\ninterface Scalar<B> {\n <O extends B = B>(opts: Refined<O> & (Required | Defaulted<NoInfer<O>>)): Prop<O>;\n <O extends B = B>(opts?: Refined<O> & Optional): Prop<O | undefined>;\n}\n\ninterface WithSchema {\n <S extends StandardSchemaV1>(\n schema: S,\n opts: Common & (Required | Defaulted<NoInfer<Out<S>>>),\n ): Prop<Out<S>>;\n <S extends StandardSchemaV1>(schema: S, opts?: Common & Optional): Prop<Out<S> | undefined>;\n}\n\ninterface Options {\n readonly attribute?: string | false;\n readonly schema?: StandardSchemaV1;\n readonly required?: boolean;\n readonly default?: unknown;\n}\n\nfunction make(kind: PropKind, opts: Options = {}, schema?: StandardSchemaV1): Prop<unknown> {\n features.props = propFeature; // components can declare props now (features.ts)\n const value = opts.default !== undefined ? opts.default : kind === 'boolean' ? false : undefined;\n const base = {\n kind,\n attribute: kind === 'value' ? false : opts.attribute,\n schema: schema ?? opts.schema,\n required: opts.required === true,\n };\n return value === undefined ? base : { ...base, default: value };\n}\n\n/** The prop builders. */\nexport const prop: {\n /** Attribute parsed as is. */\n readonly string: Scalar<string>;\n /** Attribute parsed with `Number(v)`; empty or `NaN` is invalid. */\n readonly number: Scalar<number>;\n /** Attribute present → `true`, absent → `false` (the default). */\n readonly boolean: <O extends boolean = boolean>(\n opts?: Refined<O> & { readonly default?: NoInfer<O> },\n ) => Prop<O>;\n /** Attribute parsed with `JSON.parse`, then the schema. */\n readonly json: WithSchema;\n /** Property only: no attribute. Validated in development. */\n readonly value: WithSchema;\n} = {\n string: (opts?: Options) => make('string', opts),\n number: (opts?: Options) => make('number', opts),\n boolean: ((opts?: Options) => make('boolean', opts)) as <O extends boolean>() => Prop<O>,\n json: (schema: StandardSchemaV1, opts?: Options) => make('json', opts, schema),\n value: (schema: StandardSchemaV1, opts?: Options) => make('value', opts, schema),\n};\n"]}
|