@gyral/core 0.0.0 → 0.2.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.
Files changed (119) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/LICENSE +1 -1
  3. package/NOTICE +11 -0
  4. package/README.md +45 -5
  5. package/dist/accessible-name.d.ts +19 -0
  6. package/dist/accessible-name.js +56 -0
  7. package/dist/accessible-name.js.map +1 -0
  8. package/dist/children.d.ts +37 -0
  9. package/dist/children.js +49 -0
  10. package/dist/children.js.map +1 -0
  11. package/dist/command.d.ts +63 -0
  12. package/dist/command.js +26 -0
  13. package/dist/command.js.map +1 -0
  14. package/dist/define.d.ts +9 -0
  15. package/dist/define.js +338 -0
  16. package/dist/define.js.map +1 -0
  17. package/dist/devtools-events.d.ts +51 -0
  18. package/dist/devtools-events.js +3 -0
  19. package/dist/devtools-events.js.map +1 -0
  20. package/dist/devtools-off.d.ts +9 -0
  21. package/dist/devtools-off.js +10 -0
  22. package/dist/devtools-off.js.map +1 -0
  23. package/dist/devtools.d.ts +13 -0
  24. package/dist/devtools.js +68 -0
  25. package/dist/devtools.js.map +1 -0
  26. package/dist/drivers-scope.d.ts +15 -0
  27. package/dist/drivers-scope.js +48 -0
  28. package/dist/drivers-scope.js.map +1 -0
  29. package/dist/element-directive.d.ts +20 -0
  30. package/dist/element-directive.js +31 -0
  31. package/dist/element-directive.js.map +1 -0
  32. package/dist/element-types.d.ts +34 -0
  33. package/dist/element-types.js +2 -0
  34. package/dist/element-types.js.map +1 -0
  35. package/dist/focus.d.ts +39 -0
  36. package/dist/focus.js +42 -0
  37. package/dist/focus.js.map +1 -0
  38. package/dist/forms.d.ts +59 -0
  39. package/dist/forms.js +138 -0
  40. package/dist/forms.js.map +1 -0
  41. package/dist/hydration.d.ts +36 -0
  42. package/dist/hydration.js +72 -0
  43. package/dist/hydration.js.map +1 -0
  44. package/dist/index.d.ts +43 -0
  45. package/dist/index.js +37 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/init.d.ts +7 -0
  48. package/dist/init.js +10 -0
  49. package/dist/init.js.map +1 -0
  50. package/dist/intent.d.ts +25 -0
  51. package/dist/intent.js +157 -0
  52. package/dist/intent.js.map +1 -0
  53. package/dist/internal/interpreter.d.ts +8 -0
  54. package/dist/internal/interpreter.js +166 -0
  55. package/dist/internal/interpreter.js.map +1 -0
  56. package/dist/invalid.d.ts +21 -0
  57. package/dist/invalid.js +70 -0
  58. package/dist/invalid.js.map +1 -0
  59. package/dist/invokers.d.ts +15 -0
  60. package/dist/invokers.js +64 -0
  61. package/dist/invokers.js.map +1 -0
  62. package/dist/islands.d.ts +11 -0
  63. package/dist/islands.js +63 -0
  64. package/dist/islands.js.map +1 -0
  65. package/dist/json-safety.d.ts +8 -0
  66. package/dist/json-safety.js +68 -0
  67. package/dist/json-safety.js.map +1 -0
  68. package/dist/light-dom.d.ts +61 -0
  69. package/dist/light-dom.js +109 -0
  70. package/dist/light-dom.js.map +1 -0
  71. package/dist/lit-html-check.d.ts +6 -0
  72. package/dist/lit-html-check.js +48 -0
  73. package/dist/lit-html-check.js.map +1 -0
  74. package/dist/live-boolean.d.ts +22 -0
  75. package/dist/live-boolean.js +34 -0
  76. package/dist/live-boolean.js.map +1 -0
  77. package/dist/props.d.ts +26 -0
  78. package/dist/props.js +44 -0
  79. package/dist/props.js.map +1 -0
  80. package/dist/random.d.ts +13 -0
  81. package/dist/random.js +19 -0
  82. package/dist/random.js.map +1 -0
  83. package/dist/states.d.ts +7 -0
  84. package/dist/states.js +23 -0
  85. package/dist/states.js.map +1 -0
  86. package/dist/store-binding.d.ts +14 -0
  87. package/dist/store-binding.js +63 -0
  88. package/dist/store-binding.js.map +1 -0
  89. package/dist/store-scope.d.ts +40 -0
  90. package/dist/store-scope.js +146 -0
  91. package/dist/store-scope.js.map +1 -0
  92. package/dist/store.d.ts +114 -0
  93. package/dist/store.js +129 -0
  94. package/dist/store.js.map +1 -0
  95. package/dist/stores-provider.d.ts +6 -0
  96. package/dist/stores-provider.js +57 -0
  97. package/dist/stores-provider.js.map +1 -0
  98. package/dist/styles.d.ts +12 -0
  99. package/dist/styles.js +11 -0
  100. package/dist/styles.js.map +1 -0
  101. package/dist/template-whitespace.d.ts +7 -0
  102. package/dist/template-whitespace.js +192 -0
  103. package/dist/template-whitespace.js.map +1 -0
  104. package/dist/templates.d.ts +5 -0
  105. package/dist/templates.js +15 -0
  106. package/dist/templates.js.map +1 -0
  107. package/dist/textarea.d.ts +26 -0
  108. package/dist/textarea.js +85 -0
  109. package/dist/textarea.js.map +1 -0
  110. package/dist/transitions.d.ts +9 -0
  111. package/dist/transitions.js +26 -0
  112. package/dist/transitions.js.map +1 -0
  113. package/dist/types.d.ts +186 -0
  114. package/dist/types.js +2 -0
  115. package/dist/types.js.map +1 -0
  116. package/dist/vite.d.ts +25 -0
  117. package/dist/vite.js +37 -0
  118. package/dist/vite.js.map +1 -0
  119. package/package.json +41 -13
@@ -0,0 +1,85 @@
1
+ // <textarea> support (gyral-czi.34). Lit can't bind inside <textarea>: its content is raw
2
+ // text, so `html\`<textarea>${v}</textarea>\`` throws during SSR ("Unexpected final
3
+ // partIndex") and never updates in the browser. `textarea()` renders the element as a static,
4
+ // escaped template (correct no-JS markup and a hydration match), then keeps it in sync by
5
+ // setting properties and attributes on the same element.
6
+ import { noChange } from 'lit';
7
+ import { Directive, directive, PartType } from 'lit/directive.js';
8
+ import { html as staticHtml, unsafeStatic } from 'lit/static-html.js';
9
+ const escapeText = (s) => s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
10
+ const escapeAttr = (s) => escapeText(s).replace(/"/g, '&quot;');
11
+ const ATTR_NAME = /^[a-zA-Z_:][-a-zA-Z0-9_:.]*$/;
12
+ function attrMarkup(attrs) {
13
+ return Object.entries(attrs ?? {})
14
+ .map(([name, value]) => {
15
+ if (!ATTR_NAME.test(name))
16
+ throw new Error(`textarea(): invalid attribute name "${name}"`);
17
+ if (value === false || value === null || value === undefined)
18
+ return '';
19
+ return value === true ? ` ${name}` : ` ${name}="${escapeAttr(String(value))}"`;
20
+ })
21
+ .join('');
22
+ }
23
+ /** The markup the server writes, and the client's first render: escaped, no bindings inside. */
24
+ export function textareaMarkup({ value, attrs }) {
25
+ return `<textarea${attrMarkup(attrs)}>${escapeText(value)}</textarea>`;
26
+ }
27
+ function findTextarea(part) {
28
+ for (let node = part.startNode?.nextSibling; node && node !== part.endNode; node = node.nextSibling) {
29
+ if (node instanceof HTMLTextAreaElement)
30
+ return node;
31
+ }
32
+ return undefined;
33
+ }
34
+ function syncAttributes(el, attrs) {
35
+ for (const [name, value] of Object.entries(attrs ?? {})) {
36
+ if (value === false || value === null || value === undefined)
37
+ el.removeAttribute(name);
38
+ else
39
+ el.setAttribute(name, value === true ? '' : String(value));
40
+ }
41
+ }
42
+ class TextareaDirective extends Directive {
43
+ /** The model value last applied, so typing isn't overwritten by an unchanged model. */
44
+ #applied;
45
+ constructor(info) {
46
+ super(info);
47
+ if (info.type !== PartType.CHILD) {
48
+ throw new Error('textarea() must be used in a child position: html`${textarea({…})}`');
49
+ }
50
+ }
51
+ render(options) {
52
+ return staticHtml `${unsafeStatic(textareaMarkup(options))}`;
53
+ }
54
+ update(part, [options]) {
55
+ const el = findTextarea(part);
56
+ if (el === undefined) {
57
+ // First render (client) or hydration (server markup already in place): same template.
58
+ this.#applied = options.value;
59
+ return this.render(options);
60
+ }
61
+ syncAttributes(el, options.attrs);
62
+ if (this.#applied === undefined) {
63
+ // Hydration: the server's element is already here. Keep whatever the user typed before
64
+ // the script loaded; only later model changes write the value.
65
+ this.#applied = options.value;
66
+ return noChange;
67
+ }
68
+ if (options.value !== this.#applied) {
69
+ this.#applied = options.value;
70
+ if (el.value !== options.value)
71
+ el.value = options.value;
72
+ }
73
+ return noChange;
74
+ }
75
+ }
76
+ /**
77
+ * A `<textarea>` whose content comes from the model, safe for SSR and hydration:
78
+ *
79
+ * ${textarea({ value: s.message, attrs: { name: 'message', rows: 5, required: true,
80
+ * 'data-intent': i.Message } })}
81
+ *
82
+ * Text typed before or after hydration is kept until the model's value changes.
83
+ */
84
+ export const textarea = directive(TextareaDirective);
85
+ //# sourceMappingURL=textarea.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textarea.js","sourceRoot":"","sources":["../src/textarea.ts"],"names":[],"mappings":"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","sourcesContent":["// <textarea> support (gyral-czi.34). Lit can't bind inside <textarea>: its content is raw\n// text, so `html\\`<textarea>${v}</textarea>\\`` throws during SSR (\"Unexpected final\n// partIndex\") and never updates in the browser. `textarea()` renders the element as a static,\n// escaped template (correct no-JS markup and a hydration match), then keeps it in sync by\n// setting properties and attributes on the same element.\nimport { noChange } from 'lit';\nimport { Directive, directive, PartType, type ChildPart, type PartInfo } from 'lit/directive.js';\nimport { html as staticHtml, unsafeStatic } from 'lit/static-html.js';\n\nexport type TextareaAttribute = string | number | boolean | null | undefined;\n\nexport interface TextareaOptions {\n /** The model's value. Applied to the live element only when the model changes. */\n readonly value: string;\n /** Attributes such as name, id, rows, required, maxlength, data-intent, aria-invalid. */\n readonly attrs?: Readonly<Record<string, TextareaAttribute>>;\n}\n\nconst escapeText = (s: string): string =>\n s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\nconst escapeAttr = (s: string): string => escapeText(s).replace(/\"/g, '&quot;');\nconst ATTR_NAME = /^[a-zA-Z_:][-a-zA-Z0-9_:.]*$/;\n\nfunction attrMarkup(attrs: TextareaOptions['attrs']): string {\n return Object.entries(attrs ?? {})\n .map(([name, value]) => {\n if (!ATTR_NAME.test(name)) throw new Error(`textarea(): invalid attribute name \"${name}\"`);\n if (value === false || value === null || value === undefined) return '';\n return value === true ? ` ${name}` : ` ${name}=\"${escapeAttr(String(value))}\"`;\n })\n .join('');\n}\n\n/** The markup the server writes, and the client's first render: escaped, no bindings inside. */\nexport function textareaMarkup({ value, attrs }: TextareaOptions): string {\n return `<textarea${attrMarkup(attrs)}>${escapeText(value)}</textarea>`;\n}\n\nfunction findTextarea(part: ChildPart): HTMLTextAreaElement | undefined {\n for (\n let node = part.startNode?.nextSibling;\n node && node !== part.endNode;\n node = node.nextSibling\n ) {\n if (node instanceof HTMLTextAreaElement) return node;\n }\n return undefined;\n}\n\nfunction syncAttributes(el: HTMLTextAreaElement, attrs: TextareaOptions['attrs']): void {\n for (const [name, value] of Object.entries(attrs ?? {})) {\n if (value === false || value === null || value === undefined) el.removeAttribute(name);\n else el.setAttribute(name, value === true ? '' : String(value));\n }\n}\n\nclass TextareaDirective extends Directive {\n /** The model value last applied, so typing isn't overwritten by an unchanged model. */\n #applied: string | undefined;\n\n constructor(info: PartInfo) {\n super(info);\n if (info.type !== PartType.CHILD) {\n throw new Error('textarea() must be used in a child position: html`${textarea({…})}`');\n }\n }\n\n override render(options: TextareaOptions): unknown {\n return staticHtml`${unsafeStatic(textareaMarkup(options))}`;\n }\n\n override update(part: ChildPart, [options]: [TextareaOptions]): unknown {\n const el = findTextarea(part);\n if (el === undefined) {\n // First render (client) or hydration (server markup already in place): same template.\n this.#applied = options.value;\n return this.render(options);\n }\n syncAttributes(el, options.attrs);\n if (this.#applied === undefined) {\n // Hydration: the server's element is already here. Keep whatever the user typed before\n // the script loaded; only later model changes write the value.\n this.#applied = options.value;\n return noChange;\n }\n if (options.value !== this.#applied) {\n this.#applied = options.value;\n if (el.value !== options.value) el.value = options.value;\n }\n return noChange;\n }\n}\n\n/**\n * A `<textarea>` whose content comes from the model, safe for SSR and hydration:\n *\n * ${textarea({ value: s.message, attrs: { name: 'message', rows: 5, required: true,\n * 'data-intent': i.Message } })}\n *\n * Text typed before or after hydration is kept until the model's value changes.\n */\nexport const textarea = directive(TextareaDirective);\n"]}
@@ -0,0 +1,9 @@
1
+ /** True when a view transition may run now (API present, motion not reduced). */
2
+ export declare function canTransition(): boolean;
3
+ /**
4
+ * Runs `update` inside `document.startViewTransition` when allowed, otherwise directly.
5
+ * `update` must resolve once the DOM reflects the new state. The returned promise settles when
6
+ * `update` has run. A transition skipped by a newer one still runs its update (per spec); its
7
+ * rejected `ready` is expected and swallowed.
8
+ */
9
+ export declare function withViewTransition(update: () => Promise<void>): Promise<void>;
@@ -0,0 +1,26 @@
1
+ // View Transitions for define() components (ADR 0001 addendum). An ADR 0003 enhancement:
2
+ // without the API, or with reduced motion requested, updates render normally.
3
+ const supportsViewTransitions = (doc) => 'startViewTransition' in doc;
4
+ const ignore = () => undefined;
5
+ /** True when a view transition may run now (API present, motion not reduced). */
6
+ export function canTransition() {
7
+ if (typeof document === 'undefined' || !supportsViewTransitions(document))
8
+ return false;
9
+ return !window.matchMedia('(prefers-reduced-motion: reduce)').matches;
10
+ }
11
+ /**
12
+ * Runs `update` inside `document.startViewTransition` when allowed, otherwise directly.
13
+ * `update` must resolve once the DOM reflects the new state. The returned promise settles when
14
+ * `update` has run. A transition skipped by a newer one still runs its update (per spec); its
15
+ * rejected `ready` is expected and swallowed.
16
+ */
17
+ export function withViewTransition(update) {
18
+ if (!canTransition() || !supportsViewTransitions(document))
19
+ return update();
20
+ return new Promise((resolve, reject) => {
21
+ const transition = document.startViewTransition(() => update().then(resolve, reject));
22
+ transition.ready.catch(ignore);
23
+ transition.finished.catch(ignore);
24
+ });
25
+ }
26
+ //# sourceMappingURL=transitions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transitions.js","sourceRoot":"","sources":["../src/transitions.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,8EAA8E;AAW9E,MAAM,uBAAuB,GAAG,CAAC,GAAa,EAA4C,EAAE,CAC1F,qBAAqB,IAAI,GAAG,CAAC;AAE/B,MAAM,MAAM,GAAG,GAAS,EAAE,CAAC,SAAS,CAAC;AAErC,iFAAiF;AACjF,MAAM,UAAU,aAAa;IAC3B,IAAI,OAAO,QAAQ,KAAK,WAAW,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IACxF,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,kCAAkC,CAAC,CAAC,OAAO,CAAC;AACxE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAA2B;IAC5D,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC;QAAE,OAAO,MAAM,EAAE,CAAC;IAC5E,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,UAAU,GAAG,QAAQ,CAAC,mBAAmB,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QACtF,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/B,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["// View Transitions for define() components (ADR 0001 addendum). An ADR 0003 enhancement:\n// without the API, or with reduced motion requested, updates render normally.\n\ninterface ViewTransitionLike {\n readonly ready: Promise<unknown>;\n readonly finished: Promise<unknown>;\n}\n\ninterface ViewTransitionDocument {\n startViewTransition(update: () => Promise<void>): ViewTransitionLike;\n}\n\nconst supportsViewTransitions = (doc: Document): doc is Document & ViewTransitionDocument =>\n 'startViewTransition' in doc;\n\nconst ignore = (): void => undefined;\n\n/** True when a view transition may run now (API present, motion not reduced). */\nexport function canTransition(): boolean {\n if (typeof document === 'undefined' || !supportsViewTransitions(document)) return false;\n return !window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\n/**\n * Runs `update` inside `document.startViewTransition` when allowed, otherwise directly.\n * `update` must resolve once the DOM reflects the new state. The returned promise settles when\n * `update` has run. A transition skipped by a newer one still runs its update (per spec); its\n * rejected `ready` is expected and swallowed.\n */\nexport function withViewTransition(update: () => Promise<void>): Promise<void> {\n if (!canTransition() || !supportsViewTransitions(document)) return update();\n return new Promise((resolve, reject) => {\n const transition = document.startViewTransition(() => update().then(resolve, reject));\n transition.ready.catch(ignore);\n transition.finished.catch(ignore);\n });\n}\n"]}
@@ -0,0 +1,186 @@
1
+ import type { PropertyDeclaration } from 'lit';
2
+ import type { Styles } from './styles.js';
3
+ import type { CommandInfo } from './invokers.js';
4
+ import type { HydrateStrategy } from './islands.js';
5
+ import type { DriverOverrides, Next } from './command.js';
6
+ import type { AnyStore, StoreChanged, StoreRef } from './store.js';
7
+ /** Every message is a tagged object; the tag is also the intent name used in markup. */
8
+ export interface Tagged {
9
+ readonly _tag: string;
10
+ }
11
+ /** What the intent layer sees when a `data-intent` element fires its trigger event. */
12
+ export interface IntentInput {
13
+ /** The `data-intent` value (a message tag). */
14
+ readonly name: string;
15
+ readonly event: Event;
16
+ /** The element carrying `data-intent`. */
17
+ readonly target: Element;
18
+ /** `value` of the input, select, textarea or button that carries the intent. */
19
+ readonly value: string | undefined;
20
+ /** `checked` for checkbox and radio inputs. */
21
+ readonly checked: boolean | undefined;
22
+ /** Submitted data (including the submitter button) when the intent is on a `<form>`. */
23
+ readonly formData: FormData | undefined;
24
+ /** The output a child component emitted, when the intent is on a child element. */
25
+ readonly detail: unknown;
26
+ /** `KeyboardEvent.key` for `keydown`/`keyup` intents. */
27
+ readonly key: string | undefined;
28
+ /** For `toggle` intents (popover, `<details>`): the state it changed to. */
29
+ readonly newState: 'open' | 'closed' | undefined;
30
+ /** For `command` intents: the invoker's command (e.g. `--clear`) and source (gyral-czi.6). */
31
+ readonly command: CommandInfo | undefined;
32
+ }
33
+ /** Reads a declared store's current state, typed by the store (ADR 0013). */
34
+ export type StoreReader = <S>(store: StoreRef<S>) => S;
35
+ /** Read-only context handed to every reducer and to the view (ADR 0007, 0013). */
36
+ export interface Ctx<P> {
37
+ /** Props from above. */
38
+ readonly props: P;
39
+ /** Stores from the side: `read(cart).lines`. The store must be in `spec.stores`. */
40
+ readonly read: StoreReader;
41
+ }
42
+ /** Framework message: declared props changed after the first render (ADR 0007). */
43
+ export interface PropsChanged<P> {
44
+ readonly _tag: 'PropsChanged';
45
+ readonly props: P;
46
+ readonly prev: P;
47
+ }
48
+ /**
49
+ * Framework message: the component is live in the browser (ADR 0012 addendum). Sent once,
50
+ * after the first client render has completed, to every client-side instance. Use it for
51
+ * progressive enhancement: render the no-JS form on the server and in the first client render
52
+ * (so hydration matches), then switch to the enhanced UI in the `Hydrated` reducer.
53
+ */
54
+ export interface Hydrated {
55
+ readonly _tag: 'Hydrated';
56
+ /** `true` when the instance resumed from server-rendered markup (a hydration seed). */
57
+ readonly serverRendered: boolean;
58
+ }
59
+ /** One validation problem. `path` is dot-joined and matches the field's `name`. */
60
+ export interface FieldIssue {
61
+ readonly path: string;
62
+ readonly message: string;
63
+ }
64
+ /** Submitted text values of a form (Files are dropped: they can't be re-filled). */
65
+ export type FormFields = Readonly<Record<string, string | readonly string[]>>;
66
+ /** Framework message: an intent's input failed schema validation (ADR 0008). */
67
+ export interface IntentRejected {
68
+ readonly _tag: 'IntentRejected';
69
+ /** The `data-intent` name whose input was rejected. */
70
+ readonly intent: string;
71
+ readonly issues: readonly FieldIssue[];
72
+ /**
73
+ * For `form()` rejections: what the user submitted, so the view can re-fill the form. On
74
+ * the no-JS path (ADR 0008 server half) the server re-renders the page from this.
75
+ */
76
+ readonly values?: FormFields | undefined;
77
+ }
78
+ type ParseResult<M> = M | IntentRejected | undefined;
79
+ /**
80
+ * Parses a platform event into one message variant, `IntentRejected`, or `undefined` to
81
+ * ignore it. May be async because schema validation may be.
82
+ */
83
+ export type IntentParser<M> = (input: IntentInput) => ParseResult<M> | Promise<ParseResult<M>>;
84
+ type Variant<M extends Tagged, K extends M['_tag']> = Extract<M, {
85
+ readonly _tag: K;
86
+ }>;
87
+ /** Intent parsers keyed by the message tag they produce. Messages from drivers need none. */
88
+ export type Intents<M extends Tagged> = {
89
+ readonly [K in M['_tag']]?: IntentParser<Variant<M, K>>;
90
+ };
91
+ type Reducer<S, M, Msg, P> = (state: S, msg: Msg, ctx: Ctx<P>) => Next<S, M>;
92
+ /**
93
+ * One pure reducer per message tag (exhaustive by construction), plus optional reducers
94
+ * for framework messages. Reducers may return commands.
95
+ */
96
+ export type Update<S, M extends Tagged, P = object> = {
97
+ readonly [K in M['_tag']]: Reducer<S, M, Variant<M, K>, P>;
98
+ } & {
99
+ readonly PropsChanged?: Reducer<S, M, PropsChanged<P>, P>;
100
+ readonly IntentRejected?: Reducer<S, M, IntentRejected, P>;
101
+ readonly StoreChanged?: Reducer<S, M, StoreChanged, P>;
102
+ readonly Hydrated?: Reducer<S, M, Hydrated, P>;
103
+ };
104
+ /** Typed intent names handed to the view, so `data-intent=${i.Increment}` is checked. */
105
+ export type IntentNames<M extends Tagged> = {
106
+ readonly [K in M['_tag']]: K;
107
+ };
108
+ /**
109
+ * One prop's declaration: Lit's `PropertyDeclaration` plus Gyral's honesty rule (ADR 0007
110
+ * addendum). A prop is `undefined` until a parent, an attribute or a hydration seed sets it,
111
+ * so a prop whose type excludes `undefined` must say how that is guaranteed:
112
+ * - `required: true`: a missing value is a bug, reported once per instance at first render;
113
+ * - `default: value`: used whenever the element's value is `undefined`.
114
+ * A prop whose type includes `undefined` needs neither.
115
+ */
116
+ export type PropDeclaration<T> = PropertyDeclaration & (undefined extends T ? {
117
+ readonly required?: false;
118
+ readonly default?: T;
119
+ } : {
120
+ readonly required: true;
121
+ readonly default?: undefined;
122
+ } | {
123
+ readonly required?: false;
124
+ readonly default: T;
125
+ });
126
+ export type PropDeclarations<P> = {
127
+ readonly [K in keyof P]-?: PropDeclaration<P[K]>;
128
+ };
129
+ /** State of a component that keeps none (a pure view of its props). Its `init` is optional. */
130
+ export type Stateless = Readonly<Record<string, never>>;
131
+ /** Initial model state (and optional commands), computed from props on first render. */
132
+ type Init<S, M, P> = (props: P) => Next<S, M>;
133
+ type InitField<S, M extends Tagged, P> = Stateless extends S ? {
134
+ readonly init?: Init<S, M, P>;
135
+ } : {
136
+ readonly init: Init<S, M, P>;
137
+ };
138
+ export type ComponentSpec<S, M extends Tagged, P> = SpecBody<S, M, P> & InitField<S, M, P>;
139
+ interface SpecBody<S, M extends Tagged, P> {
140
+ /** Lit reactive property declarations: the component's inputs. */
141
+ readonly props?: PropDeclarations<P>;
142
+ /** INTENT: platform events to messages. */
143
+ readonly intent: Intents<M>;
144
+ /** MODEL: pure state transitions. */
145
+ readonly update: Update<S, M, P>;
146
+ /** VIEW: pure function of state and props. Name intents in markup; never attach closures. */
147
+ readonly view: (state: S, intents: IntentNames<M>, ctx: Ctx<P>) => unknown;
148
+ /**
149
+ * Shadow-root styles: `css` templates, plain CSS strings, `CSSStyleSheet`s, or arrays of
150
+ * them. Ignored (with a warning) when `shadow: false`.
151
+ */
152
+ readonly styles?: Styles;
153
+ /**
154
+ * `false` renders the view as the element's own light-DOM children (ADR 0014): document CSS
155
+ * applies, and the server writes plain children instead of a `<template shadowrootmode>`.
156
+ * For page-level components (listings, articles). No `<slot>`s and no `styles`. Default `true`.
157
+ */
158
+ readonly shadow?: boolean;
159
+ /**
160
+ * When a server-rendered instance hydrates (gyral-4k7.4): `load` (default), `idle`,
161
+ * `visible` (scrolled into view) or `interaction` (first pointer/focus). Client-only
162
+ * renders are unaffected.
163
+ */
164
+ readonly hydrate?: HydrateStrategy;
165
+ /** Extra event types that may trigger intents via `data-intent-on` (e.g. `pointerdown`). */
166
+ readonly events?: readonly string[];
167
+ /** Driver substitutions by name, for every instance (ADR 0006). */
168
+ readonly drivers?: DriverOverrides;
169
+ /**
170
+ * Stores this component reads with `ctx.read(store)` and writes with `send(store, msg)`.
171
+ * Their changes re-render it (and reach the optional `StoreChanged` reducer). ADR 0013.
172
+ */
173
+ readonly stores?: readonly AnyStore[];
174
+ /**
175
+ * Return `true` to render this state change inside a View Transition (route changes, list
176
+ * reorders). Skipped without browser support or when reduced motion is requested.
177
+ */
178
+ readonly viewTransition?: (prev: S, next: S, msg: Tagged) => boolean;
179
+ /**
180
+ * Boolean facts about the state, exposed to CSS as custom states:
181
+ * `states: (s) => ({ loading: s._tag === 'Loading' })` enables `:host(:state(loading))` and
182
+ * `gy-x:state(loading)`. Applied after each render; feature-detected; not on the server.
183
+ */
184
+ readonly states?: (state: S) => Readonly<Record<string, boolean>>;
185
+ }
186
+ export {};
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { PropertyDeclaration } from 'lit';\nimport type { Styles } from './styles.js';\nimport type { CommandInfo } from './invokers.js';\nimport type { HydrateStrategy } from './islands.js';\nimport type { DriverOverrides, Next } from './command.js';\nimport type { AnyStore, StoreChanged, StoreRef } from './store.js';\n\n/** Every message is a tagged object; the tag is also the intent name used in markup. */\nexport interface Tagged {\n readonly _tag: string;\n}\n\n/** What the intent layer sees when a `data-intent` element fires its trigger event. */\nexport interface IntentInput {\n /** The `data-intent` value (a message tag). */\n readonly name: string;\n readonly event: Event;\n /** The element carrying `data-intent`. */\n readonly target: Element;\n /** `value` of the input, select, textarea or button that carries the intent. */\n readonly value: string | undefined;\n /** `checked` for checkbox and radio inputs. */\n readonly checked: boolean | undefined;\n /** Submitted data (including the submitter button) when the intent is on a `<form>`. */\n readonly formData: FormData | undefined;\n /** The output a child component emitted, when the intent is on a child element. */\n readonly detail: unknown;\n /** `KeyboardEvent.key` for `keydown`/`keyup` intents. */\n readonly key: string | undefined;\n /** For `toggle` intents (popover, `<details>`): the state it changed to. */\n readonly newState: 'open' | 'closed' | undefined;\n /** For `command` intents: the invoker's command (e.g. `--clear`) and source (gyral-czi.6). */\n readonly command: CommandInfo | undefined;\n}\n\n/** Reads a declared store's current state, typed by the store (ADR 0013). */\nexport type StoreReader = <S>(store: StoreRef<S>) => S;\n\n/** Read-only context handed to every reducer and to the view (ADR 0007, 0013). */\nexport interface Ctx<P> {\n /** Props from above. */\n readonly props: P;\n /** Stores from the side: `read(cart).lines`. The store must be in `spec.stores`. */\n readonly read: StoreReader;\n}\n\n/** Framework message: declared props changed after the first render (ADR 0007). */\nexport interface PropsChanged<P> {\n readonly _tag: 'PropsChanged';\n readonly props: P;\n readonly prev: P;\n}\n\n/**\n * Framework message: the component is live in the browser (ADR 0012 addendum). Sent once,\n * after the first client render has completed, to every client-side instance. Use it for\n * progressive enhancement: render the no-JS form on the server and in the first client render\n * (so hydration matches), then switch to the enhanced UI in the `Hydrated` reducer.\n */\nexport interface Hydrated {\n readonly _tag: 'Hydrated';\n /** `true` when the instance resumed from server-rendered markup (a hydration seed). */\n readonly serverRendered: boolean;\n}\n\n/** One validation problem. `path` is dot-joined and matches the field's `name`. */\nexport interface FieldIssue {\n readonly path: string;\n readonly message: string;\n}\n\n/** Submitted text values of a form (Files are dropped: they can't be re-filled). */\nexport type FormFields = Readonly<Record<string, string | readonly string[]>>;\n\n/** Framework message: an intent's input failed schema validation (ADR 0008). */\nexport interface IntentRejected {\n readonly _tag: 'IntentRejected';\n /** The `data-intent` name whose input was rejected. */\n readonly intent: string;\n readonly issues: readonly FieldIssue[];\n /**\n * For `form()` rejections: what the user submitted, so the view can re-fill the form. On\n * the no-JS path (ADR 0008 server half) the server re-renders the page from this.\n */\n // `| undefined` so schemas with plain optional fields (valibot `optional`) can produce it.\n readonly values?: FormFields | undefined;\n}\n\ntype ParseResult<M> = M | IntentRejected | undefined;\n\n/**\n * Parses a platform event into one message variant, `IntentRejected`, or `undefined` to\n * ignore it. May be async because schema validation may be.\n */\nexport type IntentParser<M> = (input: IntentInput) => ParseResult<M> | Promise<ParseResult<M>>;\n\ntype Variant<M extends Tagged, K extends M['_tag']> = Extract<M, { readonly _tag: K }>;\n\n/** Intent parsers keyed by the message tag they produce. Messages from drivers need none. */\nexport type Intents<M extends Tagged> = {\n readonly [K in M['_tag']]?: IntentParser<Variant<M, K>>;\n};\n\ntype Reducer<S, M, Msg, P> = (state: S, msg: Msg, ctx: Ctx<P>) => Next<S, M>;\n\n/**\n * One pure reducer per message tag (exhaustive by construction), plus optional reducers\n * for framework messages. Reducers may return commands.\n */\nexport type Update<S, M extends Tagged, P = object> = {\n readonly [K in M['_tag']]: Reducer<S, M, Variant<M, K>, P>;\n} & {\n readonly PropsChanged?: Reducer<S, M, PropsChanged<P>, P>;\n readonly IntentRejected?: Reducer<S, M, IntentRejected, P>;\n readonly StoreChanged?: Reducer<S, M, StoreChanged, P>;\n readonly Hydrated?: Reducer<S, M, Hydrated, P>;\n};\n\n/** Typed intent names handed to the view, so `data-intent=${i.Increment}` is checked. */\nexport type IntentNames<M extends Tagged> = { readonly [K in M['_tag']]: K };\n\n/**\n * One prop's declaration: Lit's `PropertyDeclaration` plus Gyral's honesty rule (ADR 0007\n * addendum). A prop is `undefined` until a parent, an attribute or a hydration seed sets it,\n * so a prop whose type excludes `undefined` must say how that is guaranteed:\n * - `required: true`: a missing value is a bug, reported once per instance at first render;\n * - `default: value`: used whenever the element's value is `undefined`.\n * A prop whose type includes `undefined` needs neither.\n */\nexport type PropDeclaration<T> = PropertyDeclaration &\n (undefined extends T\n ? { readonly required?: false; readonly default?: T }\n : | { readonly required: true; readonly default?: undefined }\n | { readonly required?: false; readonly default: T });\n\nexport type PropDeclarations<P> = { readonly [K in keyof P]-?: PropDeclaration<P[K]> };\n\n/** State of a component that keeps none (a pure view of its props). Its `init` is optional. */\nexport type Stateless = Readonly<Record<string, never>>;\n\n/** Initial model state (and optional commands), computed from props on first render. */\ntype Init<S, M, P> = (props: P) => Next<S, M>;\n\n// `init` may be omitted only when an empty object is a valid state (Stateless, all-optional).\ntype InitField<S, M extends Tagged, P> = Stateless extends S\n ? { readonly init?: Init<S, M, P> }\n : { readonly init: Init<S, M, P> };\n\nexport type ComponentSpec<S, M extends Tagged, P> = SpecBody<S, M, P> & InitField<S, M, P>;\n\ninterface SpecBody<S, M extends Tagged, P> {\n /** Lit reactive property declarations: the component's inputs. */\n readonly props?: PropDeclarations<P>;\n /** INTENT: platform events to messages. */\n readonly intent: Intents<M>;\n /** MODEL: pure state transitions. */\n readonly update: Update<S, M, P>;\n /** VIEW: pure function of state and props. Name intents in markup; never attach closures. */\n readonly view: (state: S, intents: IntentNames<M>, ctx: Ctx<P>) => unknown;\n /**\n * Shadow-root styles: `css` templates, plain CSS strings, `CSSStyleSheet`s, or arrays of\n * them. Ignored (with a warning) when `shadow: false`.\n */\n readonly styles?: Styles;\n /**\n * `false` renders the view as the element's own light-DOM children (ADR 0014): document CSS\n * applies, and the server writes plain children instead of a `<template shadowrootmode>`.\n * For page-level components (listings, articles). No `<slot>`s and no `styles`. Default `true`.\n */\n readonly shadow?: boolean;\n /**\n * When a server-rendered instance hydrates (gyral-4k7.4): `load` (default), `idle`,\n * `visible` (scrolled into view) or `interaction` (first pointer/focus). Client-only\n * renders are unaffected.\n */\n readonly hydrate?: HydrateStrategy;\n /** Extra event types that may trigger intents via `data-intent-on` (e.g. `pointerdown`). */\n readonly events?: readonly string[];\n /** Driver substitutions by name, for every instance (ADR 0006). */\n readonly drivers?: DriverOverrides;\n /**\n * Stores this component reads with `ctx.read(store)` and writes with `send(store, msg)`.\n * Their changes re-render it (and reach the optional `StoreChanged` reducer). ADR 0013.\n */\n readonly stores?: readonly AnyStore[];\n /**\n * Return `true` to render this state change inside a View Transition (route changes, list\n * reorders). Skipped without browser support or when reduced motion is requested.\n */\n readonly viewTransition?: (prev: S, next: S, msg: Tagged) => boolean;\n /**\n * Boolean facts about the state, exposed to CSS as custom states:\n * `states: (s) => ({ loading: s._tag === 'Loading' })` enables `:host(:state(loading))` and\n * `gy-x:state(loading)`. Applied after each render; feature-detected; not on the server.\n */\n readonly states?: (state: S) => Readonly<Record<string, boolean>>;\n}\n"]}
package/dist/vite.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ /** Every Lit package: resolve exactly one copy, even when Gyral is linked from elsewhere. */
2
+ export declare const LIT_PACKAGES: readonly string[];
3
+ /**
4
+ * Lit modules that Gyral imports or re-exports. Pre-bundling them up front stops Vite from
5
+ * discovering them mid-run, which reloads the page and fails the first browser test run.
6
+ */
7
+ export declare const LIT_PREBUNDLE: readonly string[];
8
+ export interface GyralViteOptions {
9
+ /** More modules to pre-bundle (e.g. 'lit/directives/unsafe-html.js'). */
10
+ readonly optimize?: readonly string[];
11
+ }
12
+ export interface GyralViteConfig {
13
+ readonly resolve: {
14
+ readonly dedupe: string[];
15
+ };
16
+ readonly optimizeDeps: {
17
+ readonly include: string[];
18
+ };
19
+ }
20
+ /**
21
+ * Spread into a Vite config, or into each Vitest project:
22
+ *
23
+ * export default defineConfig({ ...gyralVitePreset(), build: { … } });
24
+ */
25
+ export declare function gyralVitePreset(options?: GyralViteOptions): GyralViteConfig;
package/dist/vite.js ADDED
@@ -0,0 +1,37 @@
1
+ // Vite / Vitest settings every Gyral app needs (gyral-a7r, docs/references/consumer-setup.md).
2
+ // Plain data, no imports: safe to load from vite.config.ts and vitest.config.ts.
3
+ /** Every Lit package: resolve exactly one copy, even when Gyral is linked from elsewhere. */
4
+ export const LIT_PACKAGES = [
5
+ 'lit',
6
+ 'lit-html',
7
+ 'lit-element',
8
+ '@lit/reactive-element',
9
+ '@lit-labs/ssr',
10
+ '@lit-labs/ssr-client',
11
+ ];
12
+ /**
13
+ * Lit modules that Gyral imports or re-exports. Pre-bundling them up front stops Vite from
14
+ * discovering them mid-run, which reloads the page and fails the first browser test run.
15
+ */
16
+ export const LIT_PREBUNDLE = [
17
+ 'lit',
18
+ 'lit/directive.js',
19
+ 'lit/static-html.js',
20
+ 'lit/directives/class-map.js',
21
+ 'lit/directives/keyed.js',
22
+ 'lit/directives/live.js',
23
+ 'lit/directives/repeat.js',
24
+ 'lit/directives/style-map.js',
25
+ ];
26
+ /**
27
+ * Spread into a Vite config, or into each Vitest project:
28
+ *
29
+ * export default defineConfig({ ...gyralVitePreset(), build: { … } });
30
+ */
31
+ export function gyralVitePreset(options = {}) {
32
+ return {
33
+ resolve: { dedupe: [...LIT_PACKAGES] },
34
+ optimizeDeps: { include: [...new Set([...LIT_PREBUNDLE, ...(options.optimize ?? [])])] },
35
+ };
36
+ }
37
+ //# sourceMappingURL=vite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite.js","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,iFAAiF;AAEjF,6FAA6F;AAC7F,MAAM,CAAC,MAAM,YAAY,GAAsB;IAC7C,KAAK;IACL,UAAU;IACV,aAAa;IACb,uBAAuB;IACvB,eAAe;IACf,sBAAsB;CACvB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAsB;IAC9C,KAAK;IACL,kBAAkB;IAClB,oBAAoB;IACpB,6BAA6B;IAC7B,yBAAyB;IACzB,wBAAwB;IACxB,0BAA0B;IAC1B,6BAA6B;CAC9B,CAAC;AAYF;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,UAA4B,EAAE;IAC5D,OAAO;QACL,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,YAAY,CAAC,EAAE;QACtC,YAAY,EAAE,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,aAAa,EAAE,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;KACzF,CAAC;AACJ,CAAC","sourcesContent":["// Vite / Vitest settings every Gyral app needs (gyral-a7r, docs/references/consumer-setup.md).\n// Plain data, no imports: safe to load from vite.config.ts and vitest.config.ts.\n\n/** Every Lit package: resolve exactly one copy, even when Gyral is linked from elsewhere. */\nexport const LIT_PACKAGES: readonly string[] = [\n 'lit',\n 'lit-html',\n 'lit-element',\n '@lit/reactive-element',\n '@lit-labs/ssr',\n '@lit-labs/ssr-client',\n];\n\n/**\n * Lit modules that Gyral imports or re-exports. Pre-bundling them up front stops Vite from\n * discovering them mid-run, which reloads the page and fails the first browser test run.\n */\nexport const LIT_PREBUNDLE: readonly string[] = [\n 'lit',\n 'lit/directive.js',\n 'lit/static-html.js',\n 'lit/directives/class-map.js',\n 'lit/directives/keyed.js',\n 'lit/directives/live.js',\n 'lit/directives/repeat.js',\n 'lit/directives/style-map.js',\n];\n\nexport interface GyralViteOptions {\n /** More modules to pre-bundle (e.g. 'lit/directives/unsafe-html.js'). */\n readonly optimize?: readonly string[];\n}\n\nexport interface GyralViteConfig {\n readonly resolve: { readonly dedupe: string[] };\n readonly optimizeDeps: { readonly include: string[] };\n}\n\n/**\n * Spread into a Vite config, or into each Vitest project:\n *\n * export default defineConfig({ ...gyralVitePreset(), build: { … } });\n */\nexport function gyralVitePreset(options: GyralViteOptions = {}): GyralViteConfig {\n return {\n resolve: { dedupe: [...LIT_PACKAGES] },\n optimizeDeps: { include: [...new Set([...LIT_PREBUNDLE, ...(options.optimize ?? [])])] },\n };\n}\n"]}
package/package.json CHANGED
@@ -1,16 +1,10 @@
1
1
  {
2
2
  "name": "@gyral/core",
3
- "version": "0.0.0",
4
- "description": "Coming soon — https://gyral.dev",
5
- "keywords": [
6
- "gyral",
7
- "web-components",
8
- "lit",
9
- "mvi"
10
- ],
3
+ "version": "0.2.0",
4
+ "description": "Gyral core: Model-View-Intent web components on Lit and the web platform. Inspired by Cycle.js.",
11
5
  "license": "MIT",
12
- "author": "The Zoop Troop, Inc.",
13
- "homepage": "https://gyral.dev",
6
+ "author": "Mike Zupper",
7
+ "homepage": "https://github.com/gyraljs/gyral/tree/main/packages/core#readme",
14
8
  "repository": {
15
9
  "type": "git",
16
10
  "url": "git+https://github.com/gyraljs/gyral.git",
@@ -19,7 +13,41 @@
19
13
  "bugs": {
20
14
  "url": "https://github.com/gyraljs/gyral/issues"
21
15
  },
22
- "publishConfig": {
23
- "access": "public"
16
+ "type": "module",
17
+ "sideEffects": false,
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "default": "./dist/index.js"
22
+ },
23
+ "./vite": {
24
+ "types": "./dist/vite.d.ts",
25
+ "default": "./dist/vite.js"
26
+ }
27
+ },
28
+ "imports": {
29
+ "#devtools": {
30
+ "development": "./dist/devtools.js",
31
+ "default": "./dist/devtools-off.js"
32
+ }
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "README.md",
37
+ "LICENSE",
38
+ "NOTICE",
39
+ "CHANGELOG.md"
40
+ ],
41
+ "dependencies": {
42
+ "@standard-schema/spec": "1.1.0"
43
+ },
44
+ "peerDependencies": {
45
+ "lit": "^3.3.0"
46
+ },
47
+ "devDependencies": {
48
+ "lit": "3.3.3"
49
+ },
50
+ "scripts": {
51
+ "build": "node ../../scripts/build-package.mjs"
24
52
  }
25
- }
53
+ }