@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
package/dist/define.js ADDED
@@ -0,0 +1,338 @@
1
+ import { isServer, LitElement } from 'lit';
2
+ import { providedDriver } from './drivers-scope.js';
3
+ import { DEVTOOLS_ENABLED, devCommands, devConnect, devHydrated, devOwner, devUpdate, } from '#devtools';
4
+ import { splitNext, } from './command.js';
5
+ import { dispatchOutput, EMIT } from './children.js';
6
+ import { FOCUS, focusAfterUpdate } from './focus.js';
7
+ import { fillEmptyTextParts, takeSeed, writeSeed } from './hydration.js';
8
+ import { markIsland, scheduleIsland } from './islands.js';
9
+ import { runInit } from './init.js';
10
+ import { handleIntent, intentNames, listenForIntents, markGyralHost } from './intent.js';
11
+ import { componentStyles, hydrateLight, hydrateShadow, isLight, markLightHost, } from './light-dom.js';
12
+ import { makeInterpreter } from './internal/interpreter.js';
13
+ import { missingRequired, readProps, readRawProps, restoreProps, sameProps, shadowedBuiltins, } from './props.js';
14
+ import { attachStates } from './states.js';
15
+ import { STORE_SEND } from './store.js';
16
+ import { StoreBinding } from './store-binding.js';
17
+ import { withViewTransition } from './transitions.js';
18
+ // Lit types `isServer` per build condition; widen it so both branches type-check (ADR 0012).
19
+ const onServer = isServer;
20
+ const DEFER_HYDRATION = 'defer-hydration';
21
+ /**
22
+ * Has Lit's hydrate support patched LitElement? It then defers `defer-hydration` elements
23
+ * itself. A bundler can evaluate Lit before `@gyral/ssr/hydrate`, so it may not have
24
+ * (gyral-czi.41); the patch adds an own static `observedAttributes` to LitElement.
25
+ */
26
+ const litDefers = () => Object.prototype.hasOwnProperty.call(LitElement, 'observedAttributes');
27
+ /**
28
+ * Compiles a Model-View-Intent spec into a custom element and registers it under `tag`.
29
+ * See docs/design-docs/0001-mvi-parsed-intent.md, 0006-effects-and-drivers.md, 0007-props.md
30
+ * 0008-forms.md and 0012-ssr.md.
31
+ */
32
+ export function define(tag, spec) {
33
+ const propTable = (spec.props ?? {});
34
+ const propNames = Object.keys(propTable);
35
+ const shadowed = onServer ? [] : shadowedBuiltins(propNames);
36
+ if (shadowed.length > 0) {
37
+ console.warn(`<${tag}> declares prop(s) that shadow built-in element properties: ` +
38
+ `${shadowed.join(', ')}. Setting them changes platform behaviour ` +
39
+ `(a prop named "hidden" hides the element). Rename them.`);
40
+ }
41
+ const parsers = spec.intent;
42
+ // Sound: #dispatch() only calls the reducer whose key equals msg._tag.
43
+ const reducers = spec.update;
44
+ class Element extends LitElement {
45
+ constructor() {
46
+ super(...arguments);
47
+ this.drivers = {};
48
+ this.stores = {};
49
+ this.initialMessages = [];
50
+ /** Reads, subscriptions and writes for spec.stores (ADR 0013). */
51
+ this.#binding = new StoreBinding(this, tag, spec.stores ?? [], () => this.stores, (store, state, prev) => {
52
+ this.#storeChanged(store, state, prev);
53
+ });
54
+ this.#listening = false;
55
+ this.#pending = [];
56
+ /** init's commands on the hydration path; started in firstUpdated (ADR 0012). */
57
+ this.#afterHydration = [];
58
+ /** Resumed from server markup; reported by the Hydrated message. */
59
+ this.#serverRendered = false;
60
+ /** The renderRoot is a server-rendered (declarative) shadow root to hydrate in place. */
61
+ this.#ssrShadow = false;
62
+ /** Mirrors spec.states onto CSS custom states; only attached when the spec asks. */
63
+ this.#syncStates = spec.states === undefined || onServer ? undefined : attachStates(this);
64
+ // el.drivers → nearest provider → spec.drivers → the command's own (gyral-czi.35).
65
+ this.#resolve = (driver) => this.drivers[driver.name] ??
66
+ providedDriver(this, driver.name) ??
67
+ spec.drivers?.[driver.name] ??
68
+ driver;
69
+ this.#onEvent = (event) => {
70
+ handleIntent(event, this.renderRoot, parsers, tag, this.#deliver);
71
+ };
72
+ this.#deliver = (msg) => {
73
+ if (msg !== undefined && this.isConnected)
74
+ this.#dispatch(msg);
75
+ };
76
+ }
77
+ static { this.properties = spec.props ?? {}; }
78
+ static { this.styles = componentStyles(spec, tag); }
79
+ static { this.spec = spec; }
80
+ static { this.tagName = tag; }
81
+ // Always observe `defer-hydration`, so Gyral can defer server-rendered children itself
82
+ // when Lit's hydrate support isn't installed (gyral-czi.41, ADR 0012).
83
+ static get observedAttributes() {
84
+ const base = super.observedAttributes;
85
+ return base.includes(DEFER_HYDRATION) ? base : [...base, DEFER_HYDRATION];
86
+ }
87
+ /** Reads, subscriptions and writes for spec.stores (ADR 0013). */
88
+ #binding;
89
+ #model;
90
+ /** Props as of the last init or PropsChanged; the `prev` of the next PropsChanged. */
91
+ #seenProps;
92
+ #listening;
93
+ #interpreter;
94
+ #pending;
95
+ /** init's commands on the hydration path; started in firstUpdated (ADR 0012). */
96
+ #afterHydration;
97
+ /** Resumed from server markup; reported by the Hydrated message. */
98
+ #serverRendered;
99
+ /** The renderRoot is a server-rendered (declarative) shadow root to hydrate in place. */
100
+ #ssrShadow;
101
+ /** The latest view-transition update, awaited by updateComplete. */
102
+ #transition;
103
+ /** Mirrors spec.states onto CSS custom states; only attached when the spec asks. */
104
+ #syncStates;
105
+ get state() {
106
+ if (this.#model === undefined) {
107
+ const missing = missingRequired(this, propTable);
108
+ if (missing.length > 0) {
109
+ console.warn(`<${tag}> is missing required prop(s): ${missing.join(', ')}.`);
110
+ }
111
+ this.#seenProps = this.#props();
112
+ this.#apply(runInit(spec, this.#seenProps));
113
+ for (const msg of this.initialMessages)
114
+ this.#dispatch(msg, false);
115
+ }
116
+ return this.#model.value;
117
+ }
118
+ send(msg) {
119
+ this.#dispatch(msg);
120
+ }
121
+ #dispatch(msg, render = true) {
122
+ const reducer = reducers[msg._tag];
123
+ if (reducer === undefined) {
124
+ // Framework messages have optional reducers; props and stores stay readable as context.
125
+ if (msg._tag !== 'PropsChanged' && msg._tag !== 'StoreChanged') {
126
+ console.warn(`<${tag}> has no update for message "${msg._tag}".`);
127
+ }
128
+ return;
129
+ }
130
+ const prev = this.state;
131
+ this.#apply(reducer(prev, msg, this.#ctx()));
132
+ if (DEVTOOLS_ENABLED)
133
+ devUpdate(this, tag, msg, prev, this.state);
134
+ if (!render)
135
+ return;
136
+ if (spec.viewTransition?.(prev, this.state, msg) === true) {
137
+ // The DOM change happens inside the transition callback (ADR 0001 addendum);
138
+ // updateComplete waits for it, so tests and callers see the new DOM.
139
+ this.#transition = withViewTransition(async () => {
140
+ this.requestUpdate();
141
+ await super.getUpdateComplete();
142
+ }).catch((error) => {
143
+ console.error(`<${tag}> view transition update failed`, error);
144
+ });
145
+ }
146
+ else {
147
+ this.requestUpdate();
148
+ }
149
+ }
150
+ async getUpdateComplete() {
151
+ await this.#transition;
152
+ return super.getUpdateComplete();
153
+ }
154
+ connectedCallback() {
155
+ this.#resumeFromSeed();
156
+ // A component server-rendered inside another's view waits (`defer-hydration`) for its
157
+ // parent to hydrate first. Lit's hydrate support, when installed, defers LitElement
158
+ // itself; otherwise Gyral holds back Lit's connect until the attribute goes.
159
+ const waiting = this.hasAttribute(DEFER_HYDRATION);
160
+ if (!waiting || litDefers())
161
+ super.connectedCallback();
162
+ if (waiting) {
163
+ scheduleIsland(this); // lazy islands release themselves (gyral-4k7.4)
164
+ return;
165
+ }
166
+ this.#connect();
167
+ }
168
+ attributeChangedCallback(name, old, value) {
169
+ super.attributeChangedCallback(name, old, value);
170
+ if (name !== DEFER_HYDRATION || value !== null || !this.isConnected)
171
+ return;
172
+ if (!litDefers())
173
+ super.connectedCallback(); // Lit's support would have connected it
174
+ this.#connect();
175
+ }
176
+ #connect() {
177
+ // Re-resolve on every connect: the nearest <gyral-stores> may differ after a move.
178
+ if (this.#binding.connect())
179
+ this.requestUpdate();
180
+ this.#interpreter = makeInterpreter(this.#resolve, (msg) => {
181
+ this.#dispatch(msg);
182
+ }, DEVTOOLS_ENABLED ? devCommands(() => devOwner(this, tag)) : undefined);
183
+ if (DEVTOOLS_ENABLED)
184
+ devConnect(this, tag, true);
185
+ const pending = this.#pending;
186
+ this.#pending = [];
187
+ for (const cmd of pending)
188
+ this.#interpreter.run(cmd);
189
+ if (this.#listening)
190
+ return;
191
+ listenForIntents(this.renderRoot, spec.events ?? [], this.#onEvent);
192
+ this.#listening = true;
193
+ }
194
+ disconnectedCallback() {
195
+ super.disconnectedCallback();
196
+ this.#binding.disconnect();
197
+ this.#interpreter?.dispose();
198
+ this.#interpreter = undefined;
199
+ if (DEVTOOLS_ENABLED)
200
+ devConnect(this, tag, false);
201
+ }
202
+ willUpdate(changed) {
203
+ super.willUpdate(changed);
204
+ if (onServer) {
205
+ // Server renders run constructor, willUpdate and render only (ADR 0012).
206
+ // init is pure, so the client can recompute an unchanged state from the props.
207
+ const [initial] = splitNext(runInit(spec, this.#props()));
208
+ writeSeed(this, this.state, readRawProps(this, propTable), propTable, { value: initial });
209
+ if (isLight(spec))
210
+ markLightHost(this);
211
+ markIsland(this, spec.hydrate);
212
+ return;
213
+ }
214
+ const prev = this.#seenProps;
215
+ if (prev === undefined)
216
+ return; // first render: init() sees the props
217
+ const props = this.#props();
218
+ if (sameProps(propNames, props, prev))
219
+ return;
220
+ this.#seenProps = props;
221
+ // Inside the update cycle, so the new state renders in this same pass.
222
+ this.#dispatch({ _tag: 'PropsChanged', props, prev }, false);
223
+ }
224
+ // Light-DOM mode (ADR 0014): render into the element itself. A server-rendered shadow root
225
+ // (Declarative Shadow DOM) is reused as is and hydrated in update() (gyral-czi.41): this
226
+ // bypasses Lit's hydrate-support patch on purpose, so hydration is correct whether or not
227
+ // that patch was installed before Lit evaluated (bundlers can reorder it; ADR 0012).
228
+ createRenderRoot() {
229
+ if (isLight(spec))
230
+ return this;
231
+ if (!onServer && this.shadowRoot !== null) {
232
+ this.#ssrShadow = true;
233
+ return this.shadowRoot;
234
+ }
235
+ return super.createRenderRoot();
236
+ }
237
+ update(changed) {
238
+ if (this.#ssrShadow && !this.hasUpdated) {
239
+ const styles = this.constructor.elementStyles;
240
+ hydrateShadow(this.renderRoot, this.render(), this.renderOptions, styles);
241
+ }
242
+ if (isLight(spec) && !this.hasUpdated && this.#serverRendered) {
243
+ hydrateLight(this, this.render(), this.renderOptions); // ADR 0014
244
+ }
245
+ super.update(changed);
246
+ }
247
+ render() {
248
+ return spec.view(this.state, intentNames, this.#ctx());
249
+ }
250
+ updated(changed) {
251
+ super.updated(changed);
252
+ if (spec.states !== undefined)
253
+ this.#syncStates?.(spec.states(this.state));
254
+ }
255
+ #apply(next) {
256
+ const [state, commands] = splitNext(next);
257
+ this.#model = { value: state };
258
+ if (onServer)
259
+ return; // commands never run on the server; the client's init starts them
260
+ for (const cmd of commands) {
261
+ if (cmd.driver === EMIT)
262
+ dispatchOutput(this, cmd.input);
263
+ else if (cmd.driver === STORE_SEND)
264
+ this.#binding.send(cmd.input);
265
+ else if (cmd.driver === FOCUS)
266
+ focusAfterUpdate(this, tag, cmd.input);
267
+ else if (this.#interpreter === undefined)
268
+ this.#pending.push(cmd);
269
+ else
270
+ this.#interpreter.run(cmd);
271
+ }
272
+ }
273
+ /**
274
+ * Hydration (ADR 0012): use the server's state and restore props that only travelled in the
275
+ * seed. init(props) runs again for its commands only, and they start after the hydrating
276
+ * render: a driver that answers synchronously must not change state before hydration.
277
+ */
278
+ #resumeFromSeed() {
279
+ if (this.#model !== undefined)
280
+ return;
281
+ const seed = takeSeed(this);
282
+ if (seed === undefined)
283
+ return;
284
+ restoreProps(this, propNames, seed.props);
285
+ this.#seenProps = this.#props();
286
+ const [initial, commands] = splitNext(runInit(spec, this.#seenProps));
287
+ // Sound: the seed is this component's own state, serialized by writeSeed() on the server;
288
+ // when absent, the server's state was exactly init(props) (seed deduplication).
289
+ this.#model = { value: 'state' in seed ? seed.state : initial };
290
+ this.#afterHydration = commands;
291
+ this.#serverRendered = true;
292
+ }
293
+ firstUpdated(changed) {
294
+ super.firstUpdated(changed);
295
+ if (this.#serverRendered)
296
+ fillEmptyTextParts(this.renderRoot); // gyral-4k7.12
297
+ if (DEVTOOLS_ENABLED)
298
+ devHydrated(this, tag, this.#serverRendered);
299
+ const commands = this.#afterHydration;
300
+ const wantsHydrated = reducers['Hydrated'] !== undefined;
301
+ if (commands.length === 0 && !wantsHydrated)
302
+ return;
303
+ this.#afterHydration = [];
304
+ // After the first (possibly hydrating) update has fully completed, so whatever these
305
+ // change starts a fresh update instead of diverging from the server markup.
306
+ void this.updateComplete.then(() => {
307
+ if (wantsHydrated) {
308
+ this.#dispatch({ _tag: 'Hydrated', serverRendered: this.#serverRendered });
309
+ }
310
+ if (commands.length > 0)
311
+ this.#apply([this.state, commands]);
312
+ });
313
+ }
314
+ // el.drivers → nearest provider → spec.drivers → the command's own (gyral-czi.35).
315
+ #resolve;
316
+ #onEvent;
317
+ #deliver;
318
+ #ctx() {
319
+ return { props: this.#props(), read: (store) => this.#binding.read(store) };
320
+ }
321
+ #storeChanged(store, state, prev) {
322
+ if (reducers['StoreChanged'] === undefined)
323
+ this.requestUpdate();
324
+ else
325
+ this.#dispatch({ _tag: 'StoreChanged', store: store.name, state, prev });
326
+ }
327
+ #props() {
328
+ // Sound: propNames are exactly the declared props, P's keys.
329
+ return readProps(this, propTable);
330
+ }
331
+ }
332
+ markGyralHost(Element);
333
+ if (customElements.get(tag) === undefined)
334
+ customElements.define(tag, Element);
335
+ // Sound: the declared props are reactive properties on every instance.
336
+ return Element;
337
+ }
338
+ //# sourceMappingURL=define.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"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","sourcesContent":["import { isServer, LitElement } from 'lit';\nimport { providedDriver } from './drivers-scope.js';\nimport {\n DEVTOOLS_ENABLED,\n devCommands,\n devConnect,\n devHydrated,\n devOwner,\n devUpdate,\n} from '#devtools';\nimport {\n splitNext,\n type AnyDriver,\n type Command,\n type DriverOverrides,\n type Next,\n} from './command.js';\nimport { dispatchOutput, EMIT } from './children.js';\nimport { FOCUS, focusAfterUpdate, type FocusInput } from './focus.js';\nimport type { GyralElement, GyralElementClass } from './element-types.js';\nimport { fillEmptyTextParts, takeSeed, writeSeed } from './hydration.js';\nimport { markIsland, scheduleIsland } from './islands.js';\nimport { runInit } from './init.js';\nimport { handleIntent, intentNames, listenForIntents, markGyralHost } from './intent.js';\nimport {\n componentStyles,\n hydrateLight,\n hydrateShadow,\n isLight,\n markLightHost,\n} from './light-dom.js';\nimport { makeInterpreter, type Interpreter } from './internal/interpreter.js';\nimport {\n missingRequired,\n readProps,\n readRawProps,\n restoreProps,\n sameProps,\n shadowedBuiltins,\n type PropTable,\n} from './props.js';\nimport { attachStates, type StateSync } from './states.js';\nimport { STORE_SEND, type AnyStore, type StoreOverrides, type StoreSendInput } from './store.js';\nimport { StoreBinding } from './store-binding.js';\nimport { withViewTransition } from './transitions.js';\nimport type {\n ComponentSpec,\n Ctx,\n IntentNames,\n IntentParser,\n IntentRejected,\n Tagged,\n} from './types.js';\n\nexport type { GyralElement, GyralElementClass } from './element-types.js';\n\n// Lit types `isServer` per build condition; widen it so both branches type-check (ADR 0012).\nconst onServer: boolean = isServer;\n\nconst DEFER_HYDRATION = 'defer-hydration';\n\n/**\n * Has Lit's hydrate support patched LitElement? It then defers `defer-hydration` elements\n * itself. A bundler can evaluate Lit before `@gyral/ssr/hydrate`, so it may not have\n * (gyral-czi.41); the patch adds an own static `observedAttributes` to LitElement.\n */\nconst litDefers = (): boolean =>\n Object.prototype.hasOwnProperty.call(LitElement, 'observedAttributes');\n\n/**\n * Compiles a Model-View-Intent spec into a custom element and registers it under `tag`.\n * See docs/design-docs/0001-mvi-parsed-intent.md, 0006-effects-and-drivers.md, 0007-props.md\n * 0008-forms.md and 0012-ssr.md.\n */\nexport function define<S, M extends Tagged, P extends object = object, O extends Tagged = never>(\n tag: string,\n spec: ComponentSpec<S, M, P>,\n): GyralElementClass<S, M, P, O> {\n const propTable = (spec.props ?? {}) as PropTable;\n const propNames = Object.keys(propTable);\n const shadowed = onServer ? [] : shadowedBuiltins(propNames);\n if (shadowed.length > 0) {\n console.warn(\n `<${tag}> declares prop(s) that shadow built-in element properties: ` +\n `${shadowed.join(', ')}. Setting them changes platform behaviour ` +\n `(a prop named \"hidden\" hides the element). Rename them.`,\n );\n }\n const parsers = spec.intent as Readonly<Record<string, IntentParser<M> | undefined>>;\n // Sound: #dispatch() only calls the reducer whose key equals msg._tag.\n const reducers = spec.update as unknown as Readonly<\n Record<string, ((state: S, msg: Tagged, ctx: Ctx<P>) => Next<S, M>) | undefined>\n >;\n\n class Element extends LitElement implements GyralElement<S, M> {\n static override properties = spec.props ?? {};\n static override styles = componentStyles(spec, tag);\n static readonly spec = spec;\n static readonly tagName = tag;\n\n // Always observe `defer-hydration`, so Gyral can defer server-rendered children itself\n // when Lit's hydrate support isn't installed (gyral-czi.41, ADR 0012).\n static override get observedAttributes(): string[] {\n const base = super.observedAttributes;\n return base.includes(DEFER_HYDRATION) ? base : [...base, DEFER_HYDRATION];\n }\n\n drivers: DriverOverrides = {};\n stores: StoreOverrides = {};\n initialMessages: readonly Tagged[] = [];\n\n /** Reads, subscriptions and writes for spec.stores (ADR 0013). */\n #binding = new StoreBinding(\n this,\n tag,\n spec.stores ?? [],\n () => this.stores,\n (store, state, prev) => {\n this.#storeChanged(store, state, prev);\n },\n );\n #model: { value: S } | undefined;\n /** Props as of the last init or PropsChanged; the `prev` of the next PropsChanged. */\n #seenProps: P | undefined;\n #listening = false;\n #interpreter: Interpreter<M | IntentRejected> | undefined;\n #pending: Command<M | IntentRejected>[] = [];\n /** init's commands on the hydration path; started in firstUpdated (ADR 0012). */\n #afterHydration: readonly Command<M | IntentRejected>[] = [];\n /** Resumed from server markup; reported by the Hydrated message. */\n #serverRendered = false;\n /** The renderRoot is a server-rendered (declarative) shadow root to hydrate in place. */\n #ssrShadow = false;\n /** The latest view-transition update, awaited by updateComplete. */\n #transition: Promise<void> | undefined;\n /** Mirrors spec.states onto CSS custom states; only attached when the spec asks. */\n #syncStates: StateSync | undefined =\n spec.states === undefined || onServer ? undefined : attachStates(this);\n\n get state(): S {\n if (this.#model === undefined) {\n const missing = missingRequired(this, propTable);\n if (missing.length > 0) {\n console.warn(`<${tag}> is missing required prop(s): ${missing.join(', ')}.`);\n }\n this.#seenProps = this.#props();\n this.#apply(runInit(spec, this.#seenProps));\n for (const msg of this.initialMessages) this.#dispatch(msg, false);\n }\n return (this.#model as { value: S }).value;\n }\n\n send(msg: M): void {\n this.#dispatch(msg);\n }\n\n #dispatch(msg: Tagged, render = true): void {\n const reducer = reducers[msg._tag];\n if (reducer === undefined) {\n // Framework messages have optional reducers; props and stores stay readable as context.\n if (msg._tag !== 'PropsChanged' && msg._tag !== 'StoreChanged') {\n console.warn(`<${tag}> has no update for message \"${msg._tag}\".`);\n }\n return;\n }\n const prev = this.state;\n this.#apply(reducer(prev, msg, this.#ctx()));\n if (DEVTOOLS_ENABLED) devUpdate(this, tag, msg, prev, this.state);\n if (!render) return;\n if (spec.viewTransition?.(prev, this.state, msg) === true) {\n // The DOM change happens inside the transition callback (ADR 0001 addendum);\n // updateComplete waits for it, so tests and callers see the new DOM.\n this.#transition = withViewTransition(async () => {\n this.requestUpdate();\n await super.getUpdateComplete();\n }).catch((error: unknown) => {\n console.error(`<${tag}> view transition update failed`, error);\n });\n } else {\n this.requestUpdate();\n }\n }\n\n protected override async getUpdateComplete(): Promise<boolean> {\n await this.#transition;\n return super.getUpdateComplete();\n }\n\n override connectedCallback(): void {\n this.#resumeFromSeed();\n // A component server-rendered inside another's view waits (`defer-hydration`) for its\n // parent to hydrate first. Lit's hydrate support, when installed, defers LitElement\n // itself; otherwise Gyral holds back Lit's connect until the attribute goes.\n const waiting = this.hasAttribute(DEFER_HYDRATION);\n if (!waiting || litDefers()) super.connectedCallback();\n if (waiting) {\n scheduleIsland(this); // lazy islands release themselves (gyral-4k7.4)\n return;\n }\n this.#connect();\n }\n\n override attributeChangedCallback(name: string, old: string | null, value: string | null) {\n super.attributeChangedCallback(name, old, value);\n if (name !== DEFER_HYDRATION || value !== null || !this.isConnected) return;\n if (!litDefers()) super.connectedCallback(); // Lit's support would have connected it\n this.#connect();\n }\n\n #connect(): void {\n // Re-resolve on every connect: the nearest <gyral-stores> may differ after a move.\n if (this.#binding.connect()) this.requestUpdate();\n this.#interpreter = makeInterpreter<M | IntentRejected>(\n this.#resolve,\n (msg) => {\n this.#dispatch(msg);\n },\n DEVTOOLS_ENABLED ? devCommands(() => devOwner(this, tag)) : undefined,\n );\n if (DEVTOOLS_ENABLED) devConnect(this, tag, true);\n const pending = this.#pending;\n this.#pending = [];\n for (const cmd of pending) this.#interpreter.run(cmd);\n if (this.#listening) return;\n listenForIntents(this.renderRoot, spec.events ?? [], this.#onEvent);\n this.#listening = true;\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.#binding.disconnect();\n this.#interpreter?.dispose();\n this.#interpreter = undefined;\n if (DEVTOOLS_ENABLED) devConnect(this, tag, false);\n }\n\n protected override willUpdate(changed: Map<PropertyKey, unknown>): void {\n super.willUpdate(changed);\n if (onServer) {\n // Server renders run constructor, willUpdate and render only (ADR 0012).\n // init is pure, so the client can recompute an unchanged state from the props.\n const [initial] = splitNext(runInit(spec, this.#props()));\n writeSeed(this, this.state, readRawProps(this, propTable), propTable, { value: initial });\n if (isLight(spec)) markLightHost(this);\n markIsland(this, spec.hydrate);\n return;\n }\n const prev = this.#seenProps;\n if (prev === undefined) return; // first render: init() sees the props\n const props = this.#props();\n if (sameProps(propNames, props, prev)) return;\n this.#seenProps = props;\n // Inside the update cycle, so the new state renders in this same pass.\n this.#dispatch({ _tag: 'PropsChanged', props, prev } as Tagged, false);\n }\n\n // Light-DOM mode (ADR 0014): render into the element itself. A server-rendered shadow root\n // (Declarative Shadow DOM) is reused as is and hydrated in update() (gyral-czi.41): this\n // bypasses Lit's hydrate-support patch on purpose, so hydration is correct whether or not\n // that patch was installed before Lit evaluated (bundlers can reorder it; ADR 0012).\n protected override createRenderRoot(): HTMLElement | DocumentFragment {\n if (isLight(spec)) return this;\n if (!onServer && this.shadowRoot !== null) {\n this.#ssrShadow = true;\n return this.shadowRoot;\n }\n return super.createRenderRoot();\n }\n\n protected override update(changed: Map<PropertyKey, unknown>): void {\n if (this.#ssrShadow && !this.hasUpdated) {\n const styles = (this.constructor as typeof LitElement).elementStyles;\n hydrateShadow(this.renderRoot as ShadowRoot, this.render(), this.renderOptions, styles);\n }\n if (isLight(spec) && !this.hasUpdated && this.#serverRendered) {\n hydrateLight(this, this.render(), this.renderOptions); // ADR 0014\n }\n super.update(changed);\n }\n\n protected override render(): unknown {\n return spec.view(this.state, intentNames as IntentNames<M>, this.#ctx());\n }\n\n protected override updated(changed: Map<PropertyKey, unknown>): void {\n super.updated(changed);\n if (spec.states !== undefined) this.#syncStates?.(spec.states(this.state));\n }\n\n #apply(next: Next<S, M>): void {\n const [state, commands] = splitNext(next);\n this.#model = { value: state };\n if (onServer) return; // commands never run on the server; the client's init starts them\n for (const cmd of commands) {\n if (cmd.driver === EMIT) dispatchOutput(this, cmd.input);\n else if (cmd.driver === STORE_SEND) this.#binding.send(cmd.input as StoreSendInput);\n else if (cmd.driver === FOCUS) focusAfterUpdate(this, tag, cmd.input as FocusInput);\n else if (this.#interpreter === undefined) this.#pending.push(cmd);\n else this.#interpreter.run(cmd);\n }\n }\n\n /**\n * Hydration (ADR 0012): use the server's state and restore props that only travelled in the\n * seed. init(props) runs again for its commands only, and they start after the hydrating\n * render: a driver that answers synchronously must not change state before hydration.\n */\n #resumeFromSeed(): void {\n if (this.#model !== undefined) return;\n const seed = takeSeed(this);\n if (seed === undefined) return;\n restoreProps(this, propNames, seed.props);\n this.#seenProps = this.#props();\n const [initial, commands] = splitNext(runInit(spec, this.#seenProps));\n // Sound: the seed is this component's own state, serialized by writeSeed() on the server;\n // when absent, the server's state was exactly init(props) (seed deduplication).\n this.#model = { value: 'state' in seed ? (seed.state as S) : initial };\n this.#afterHydration = commands;\n this.#serverRendered = true;\n }\n\n protected override firstUpdated(changed: Map<PropertyKey, unknown>): void {\n super.firstUpdated(changed);\n if (this.#serverRendered) fillEmptyTextParts(this.renderRoot); // gyral-4k7.12\n if (DEVTOOLS_ENABLED) devHydrated(this, tag, this.#serverRendered);\n const commands = this.#afterHydration;\n const wantsHydrated = reducers['Hydrated'] !== undefined;\n if (commands.length === 0 && !wantsHydrated) return;\n this.#afterHydration = [];\n // After the first (possibly hydrating) update has fully completed, so whatever these\n // change starts a fresh update instead of diverging from the server markup.\n void this.updateComplete.then(() => {\n if (wantsHydrated) {\n this.#dispatch({ _tag: 'Hydrated', serverRendered: this.#serverRendered } as Tagged);\n }\n if (commands.length > 0) this.#apply([this.state, commands]);\n });\n }\n\n // el.drivers → nearest provider → spec.drivers → the command's own (gyral-czi.35).\n #resolve = (driver: AnyDriver): AnyDriver =>\n this.drivers[driver.name] ??\n providedDriver(this, driver.name) ??\n spec.drivers?.[driver.name] ??\n driver;\n\n #onEvent = (event: Event): void => {\n handleIntent(event, this.renderRoot, parsers, tag, this.#deliver);\n };\n\n #deliver = (msg: Tagged | undefined): void => {\n if (msg !== undefined && this.isConnected) this.#dispatch(msg);\n };\n\n #ctx(): Ctx<P> {\n return { props: this.#props(), read: (store) => this.#binding.read(store) };\n }\n\n #storeChanged(store: AnyStore, state: unknown, prev: unknown): void {\n if (reducers['StoreChanged'] === undefined) this.requestUpdate();\n else this.#dispatch({ _tag: 'StoreChanged', store: store.name, state, prev } as Tagged);\n }\n\n #props(): P {\n // Sound: propNames are exactly the declared props, P's keys.\n return readProps(this, propTable) as P;\n }\n }\n\n markGyralHost(Element);\n if (customElements.get(tag) === undefined) customElements.define(tag, Element);\n // Sound: the declared props are reactive properties on every instance.\n return Element as unknown as GyralElementClass<S, M, P, O>;\n}\n"]}
@@ -0,0 +1,51 @@
1
+ import type { Concurrency } from './command.js';
2
+ import type { Tagged } from './types.js';
3
+ /** Where a listener installs itself: `globalThis.__GYRAL_DEVTOOLS__ = { emit }`. */
4
+ export declare const DEVTOOLS_GLOBAL = "__GYRAL_DEVTOOLS__";
5
+ /** A live component, identified for the timeline. `element` gives the panel its state. */
6
+ export interface DevComponentRef {
7
+ readonly tag: string;
8
+ readonly id: number;
9
+ readonly element: Element;
10
+ }
11
+ export type CommandPhase = 'issued' | 'dropped' | 'settled' | 'failed' | 'interrupted';
12
+ /** What the interpreter reports about one command (ADR 0006 lanes and policies). */
13
+ export interface CommandTraceEvent {
14
+ readonly phase: CommandPhase;
15
+ readonly driver: string;
16
+ readonly lane: string;
17
+ readonly policy: Concurrency;
18
+ readonly input: unknown;
19
+ /** Driver output (`settled`) or error (`failed`). */
20
+ readonly result?: unknown;
21
+ }
22
+ export type CommandTrace = (event: CommandTraceEvent) => void;
23
+ export type DevEvent = {
24
+ readonly at: number;
25
+ } & ({
26
+ readonly kind: 'connect' | 'disconnect';
27
+ readonly component: DevComponentRef;
28
+ } | {
29
+ readonly kind: 'update';
30
+ readonly component: DevComponentRef;
31
+ readonly msg: Tagged;
32
+ readonly prev: unknown;
33
+ readonly next: unknown;
34
+ } | {
35
+ readonly kind: 'hydrated';
36
+ readonly component: DevComponentRef;
37
+ readonly serverRendered: boolean;
38
+ } | ({
39
+ readonly kind: 'command';
40
+ readonly owner: string;
41
+ } & CommandTraceEvent) | {
42
+ readonly kind: 'store';
43
+ readonly store: string;
44
+ readonly msg: Tagged;
45
+ readonly prev: unknown;
46
+ readonly next: unknown;
47
+ });
48
+ /** Installed by a devtools panel (or a test) on `globalThis[DEVTOOLS_GLOBAL]`. */
49
+ export interface DevtoolsHook {
50
+ emit(event: DevEvent): void;
51
+ }
@@ -0,0 +1,3 @@
1
+ /** Where a listener installs itself: `globalThis.__GYRAL_DEVTOOLS__ = { emit }`. */
2
+ export const DEVTOOLS_GLOBAL = '__GYRAL_DEVTOOLS__';
3
+ //# sourceMappingURL=devtools-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devtools-events.js","sourceRoot":"","sources":["../src/devtools-events.ts"],"names":[],"mappings":"AAKA,oFAAoF;AACpF,MAAM,CAAC,MAAM,eAAe,GAAG,oBAAoB,CAAC","sourcesContent":["// The devtools event stream (ADR 0017). Types and the global hook name only: the emitting code\n// lives in devtools.ts (development builds) and devtools-off.ts (production builds).\nimport type { Concurrency } from './command.js';\nimport type { Tagged } from './types.js';\n\n/** Where a listener installs itself: `globalThis.__GYRAL_DEVTOOLS__ = { emit }`. */\nexport const DEVTOOLS_GLOBAL = '__GYRAL_DEVTOOLS__';\n\n/** A live component, identified for the timeline. `element` gives the panel its state. */\nexport interface DevComponentRef {\n readonly tag: string;\n readonly id: number;\n readonly element: Element;\n}\n\nexport type CommandPhase = 'issued' | 'dropped' | 'settled' | 'failed' | 'interrupted';\n\n/** What the interpreter reports about one command (ADR 0006 lanes and policies). */\nexport interface CommandTraceEvent {\n readonly phase: CommandPhase;\n readonly driver: string;\n readonly lane: string;\n readonly policy: Concurrency;\n readonly input: unknown;\n /** Driver output (`settled`) or error (`failed`). */\n readonly result?: unknown;\n}\n\nexport type CommandTrace = (event: CommandTraceEvent) => void;\n\nexport type DevEvent = { readonly at: number } & (\n | { readonly kind: 'connect' | 'disconnect'; readonly component: DevComponentRef }\n | {\n readonly kind: 'update';\n readonly component: DevComponentRef;\n readonly msg: Tagged;\n readonly prev: unknown;\n readonly next: unknown;\n }\n | {\n readonly kind: 'hydrated';\n readonly component: DevComponentRef;\n readonly serverRendered: boolean;\n }\n | ({ readonly kind: 'command'; readonly owner: string } & CommandTraceEvent)\n | {\n readonly kind: 'store';\n readonly store: string;\n readonly msg: Tagged;\n readonly prev: unknown;\n readonly next: unknown;\n }\n);\n\n/** Installed by a devtools panel (or a test) on `globalThis[DEVTOOLS_GLOBAL]`. */\nexport interface DevtoolsHook {\n emit(event: DevEvent): void;\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import type * as Dev from './devtools.js';
2
+ export declare const DEVTOOLS_ENABLED: boolean;
3
+ export declare const devConnect: typeof Dev.devConnect;
4
+ export declare const devUpdate: typeof Dev.devUpdate;
5
+ export declare const devHydrated: typeof Dev.devHydrated;
6
+ export declare const devStore: typeof Dev.devStore;
7
+ export declare const devCommands: typeof Dev.devCommands;
8
+ export declare const devOwner: typeof Dev.devOwner;
9
+ export declare const devLiveComponents: typeof Dev.devLiveComponents;
@@ -0,0 +1,10 @@
1
+ export const DEVTOOLS_ENABLED = false;
2
+ const noop = () => undefined;
3
+ export const devConnect = noop;
4
+ export const devUpdate = noop;
5
+ export const devHydrated = noop;
6
+ export const devStore = noop;
7
+ export const devCommands = () => noop;
8
+ export const devOwner = () => '';
9
+ export const devLiveComponents = () => [];
10
+ //# sourceMappingURL=devtools-off.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devtools-off.js","sourceRoot":"","sources":["../src/devtools-off.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,gBAAgB,GAAY,KAAK,CAAC;AAE/C,MAAM,IAAI,GAAG,GAAS,EAAE,CAAC,SAAS,CAAC;AAEnC,MAAM,CAAC,MAAM,UAAU,GAA0B,IAAI,CAAC;AACtD,MAAM,CAAC,MAAM,SAAS,GAAyB,IAAI,CAAC;AACpD,MAAM,CAAC,MAAM,WAAW,GAA2B,IAAI,CAAC;AACxD,MAAM,CAAC,MAAM,QAAQ,GAAwB,IAAI,CAAC;AAClD,MAAM,CAAC,MAAM,WAAW,GAA2B,GAAG,EAAE,CAAC,IAAI,CAAC;AAC9D,MAAM,CAAC,MAAM,QAAQ,GAAwB,GAAG,EAAE,CAAC,EAAE,CAAC;AACtD,MAAM,CAAC,MAAM,iBAAiB,GAAiC,GAAG,EAAE,CAAC,EAAE,CAAC","sourcesContent":["// Production build of the devtools hook (ADR 0017): the same names as devtools.ts, doing\n// nothing. Call sites guard with DEVTOOLS_ENABLED, a literal `false` here, so bundlers drop\n// them entirely. The `typeof Dev.x` annotations keep both modules' signatures in sync.\nimport type * as Dev from './devtools.js';\n\nexport const DEVTOOLS_ENABLED: boolean = false;\n\nconst noop = (): void => undefined;\n\nexport const devConnect: typeof Dev.devConnect = noop;\nexport const devUpdate: typeof Dev.devUpdate = noop;\nexport const devHydrated: typeof Dev.devHydrated = noop;\nexport const devStore: typeof Dev.devStore = noop;\nexport const devCommands: typeof Dev.devCommands = () => noop;\nexport const devOwner: typeof Dev.devOwner = () => '';\nexport const devLiveComponents: typeof Dev.devLiveComponents = () => [];\n"]}
@@ -0,0 +1,13 @@
1
+ import { type CommandTrace, type DevComponentRef } from './devtools-events.js';
2
+ import type { Tagged } from './types.js';
3
+ export declare const DEVTOOLS_ENABLED: boolean;
4
+ /** Components connected right now, for a panel that starts after they did. */
5
+ export declare function devLiveComponents(): readonly DevComponentRef[];
6
+ export declare function devConnect(element: Element, tag: string, connected: boolean): void;
7
+ export declare function devUpdate(element: Element, tag: string, msg: Tagged, prev: unknown, next: unknown): void;
8
+ export declare function devHydrated(element: Element, tag: string, serverRendered: boolean): void;
9
+ export declare function devStore(store: string, msg: Tagged, prev: unknown, next: unknown): void;
10
+ /** A command tracer for one owner (`<tag>#id` or `store:name`). */
11
+ export declare function devCommands(owner: () => string): CommandTrace;
12
+ /** The label the panel shows for a component's commands. */
13
+ export declare function devOwner(element: Element, tag: string): string;
@@ -0,0 +1,68 @@
1
+ // Development build of the devtools hook (ADR 0017). Resolved through the `#devtools` import
2
+ // with the `development` condition; production builds get devtools-off.ts instead, so the
3
+ // guarded call sites (`if (DEVTOOLS_ENABLED) …`) disappear from the bundle.
4
+ import { DEVTOOLS_GLOBAL, } from './devtools-events.js';
5
+ import { warnLeakingLitHtmlOnce } from './lit-html-check.js';
6
+ export const DEVTOOLS_ENABLED = true;
7
+ const hook = () => globalThis[DEVTOOLS_GLOBAL];
8
+ const ids = new WeakMap();
9
+ let nextId = 1;
10
+ function ref(element, tag) {
11
+ let id = ids.get(element);
12
+ if (id === undefined) {
13
+ id = nextId++;
14
+ ids.set(element, id);
15
+ }
16
+ return { tag, id, element };
17
+ }
18
+ // Builds nothing unless a listener is installed: zero cost in dev without devtools.
19
+ function emit(make) {
20
+ const listener = hook();
21
+ if (listener === undefined)
22
+ return;
23
+ try {
24
+ listener.emit(make());
25
+ }
26
+ catch (error) {
27
+ console.error('gyral devtools listener threw', error);
28
+ }
29
+ }
30
+ const now = () => performance.now();
31
+ /** Connected components, so a panel loaded later still lists them (dev builds only). */
32
+ const live = new Map();
33
+ /** Components connected right now, for a panel that starts after they did. */
34
+ export function devLiveComponents() {
35
+ return [...live].map(([element, tag]) => ref(element, tag));
36
+ }
37
+ export function devConnect(element, tag, connected) {
38
+ warnLeakingLitHtmlOnce();
39
+ if (connected)
40
+ live.set(element, tag);
41
+ else
42
+ live.delete(element);
43
+ emit(() => ({
44
+ kind: connected ? 'connect' : 'disconnect',
45
+ component: ref(element, tag),
46
+ at: now(),
47
+ }));
48
+ }
49
+ export function devUpdate(element, tag, msg, prev, next) {
50
+ emit(() => ({ kind: 'update', component: ref(element, tag), msg, prev, next, at: now() }));
51
+ }
52
+ export function devHydrated(element, tag, serverRendered) {
53
+ emit(() => ({ kind: 'hydrated', component: ref(element, tag), serverRendered, at: now() }));
54
+ }
55
+ export function devStore(store, msg, prev, next) {
56
+ emit(() => ({ kind: 'store', store, msg, prev, next, at: now() }));
57
+ }
58
+ /** A command tracer for one owner (`<tag>#id` or `store:name`). */
59
+ export function devCommands(owner) {
60
+ return (event) => {
61
+ emit(() => ({ kind: 'command', owner: owner(), ...event, at: now() }));
62
+ };
63
+ }
64
+ /** The label the panel shows for a component's commands. */
65
+ export function devOwner(element, tag) {
66
+ return `<${tag}>#${String(ref(element, tag).id)}`;
67
+ }
68
+ //# sourceMappingURL=devtools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devtools.js","sourceRoot":"","sources":["../src/devtools.ts"],"names":[],"mappings":"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","sourcesContent":["// Development build of the devtools hook (ADR 0017). Resolved through the `#devtools` import\n// with the `development` condition; production builds get devtools-off.ts instead, so the\n// guarded call sites (`if (DEVTOOLS_ENABLED) …`) disappear from the bundle.\nimport {\n DEVTOOLS_GLOBAL,\n type CommandTrace,\n type DevComponentRef,\n type DevEvent,\n type DevtoolsHook,\n} from './devtools-events.js';\nimport { warnLeakingLitHtmlOnce } from './lit-html-check.js';\nimport type { Tagged } from './types.js';\n\nexport const DEVTOOLS_ENABLED: boolean = true;\n\nconst hook = (): DevtoolsHook | undefined =>\n (globalThis as Record<string, unknown>)[DEVTOOLS_GLOBAL] as DevtoolsHook | undefined;\n\nconst ids = new WeakMap<Element, number>();\nlet nextId = 1;\n\nfunction ref(element: Element, tag: string): DevComponentRef {\n let id = ids.get(element);\n if (id === undefined) {\n id = nextId++;\n ids.set(element, id);\n }\n return { tag, id, element };\n}\n\n// Builds nothing unless a listener is installed: zero cost in dev without devtools.\nfunction emit(make: () => DevEvent): void {\n const listener = hook();\n if (listener === undefined) return;\n try {\n listener.emit(make());\n } catch (error) {\n console.error('gyral devtools listener threw', error);\n }\n}\n\nconst now = (): number => performance.now();\n\n/** Connected components, so a panel loaded later still lists them (dev builds only). */\nconst live = new Map<Element, string>();\n\n/** Components connected right now, for a panel that starts after they did. */\nexport function devLiveComponents(): readonly DevComponentRef[] {\n return [...live].map(([element, tag]) => ref(element, tag));\n}\n\nexport function devConnect(element: Element, tag: string, connected: boolean): void {\n warnLeakingLitHtmlOnce();\n if (connected) live.set(element, tag);\n else live.delete(element);\n emit(() => ({\n kind: connected ? 'connect' : 'disconnect',\n component: ref(element, tag),\n at: now(),\n }));\n}\n\nexport function devUpdate(\n element: Element,\n tag: string,\n msg: Tagged,\n prev: unknown,\n next: unknown,\n) {\n emit(() => ({ kind: 'update', component: ref(element, tag), msg, prev, next, at: now() }));\n}\n\nexport function devHydrated(element: Element, tag: string, serverRendered: boolean): void {\n emit(() => ({ kind: 'hydrated', component: ref(element, tag), serverRendered, at: now() }));\n}\n\nexport function devStore(store: string, msg: Tagged, prev: unknown, next: unknown): void {\n emit(() => ({ kind: 'store', store, msg, prev, next, at: now() }));\n}\n\n/** A command tracer for one owner (`<tag>#id` or `store:name`). */\nexport function devCommands(owner: () => string): CommandTrace {\n return (event) => {\n emit(() => ({ kind: 'command', owner: owner(), ...event, at: now() }));\n };\n}\n\n/** The label the panel shows for a component's commands. */\nexport function devOwner(element: Element, tag: string): string {\n return `<${tag}>#${String(ref(element, tag).id)}`;\n}\n"]}
@@ -0,0 +1,15 @@
1
+ import type { AnyDriver, DriverOverrides } from './command.js';
2
+ /** Provider element name: `<gyral-drivers .drivers=${{ http: fake }}>…</gyral-drivers>`. */
3
+ export declare const DRIVERS_ELEMENT = "gyral-drivers";
4
+ /**
5
+ * Makes `element` a driver provider for every Gyral component below it (including inside
6
+ * shadow roots). Returns a function that removes the overrides. Use it on a test container
7
+ * or an app root; a `<gyral-drivers>` element with a `.drivers` property works the same way.
8
+ */
9
+ export declare function provideDrivers(element: Element, drivers: DriverOverrides): () => void;
10
+ /**
11
+ * The override for `name` from the nearest provider that has one. Providers nest: an inner
12
+ * provider without that driver lets an outer one supply it. Commands never run on the server,
13
+ * so there is nothing to resolve there.
14
+ */
15
+ export declare function providedDriver(host: Element, name: string): AnyDriver | undefined;