elements-kit 0.18.2 → 0.20.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 (156) hide show
  1. package/README.md +14 -0
  2. package/dist/await.d.mts +53 -0
  3. package/dist/await.mjs +70 -0
  4. package/dist/custom-elements.d.mts +1 -1
  5. package/dist/{element-xQwq4ulc.mjs → element-D3om9yA6.mjs} +71 -4
  6. package/dist/for.d.mts +20 -26
  7. package/dist/for.mjs +29 -4
  8. package/dist/fragment-ROPRBJQd.mjs +61 -0
  9. package/dist/hydrate/index.d.mts +41 -0
  10. package/dist/hydrate/index.mjs +2 -0
  11. package/dist/hydrate-6Qx4n4Su.mjs +380 -0
  12. package/dist/integrations/astro-client.d.mts +17 -0
  13. package/dist/integrations/astro-client.mjs +23 -0
  14. package/dist/integrations/astro-server.d.mts +15 -0
  15. package/dist/integrations/astro-server.mjs +39 -0
  16. package/dist/integrations/astro-slots.d.mts +12 -0
  17. package/dist/integrations/astro-slots.mjs +30 -0
  18. package/dist/integrations/astro.d.mts +46 -0
  19. package/dist/integrations/astro.mjs +64 -0
  20. package/dist/integrations/react.d.mts +1 -1
  21. package/dist/integrations/react.mjs +2 -2
  22. package/dist/jsx-runtime/index.d.mts +1 -1
  23. package/dist/jsx-runtime/index.mjs +2 -20
  24. package/dist/{lib-Dkc7cV5F.mjs → lib-DYypKhxk.mjs} +63 -5
  25. package/dist/render.mjs +1 -1
  26. package/dist/{scope-CnEvL9Nd.mjs → scope-zbEG299F.mjs} +1 -1
  27. package/dist/server/index.d.mts +43 -0
  28. package/dist/server/index.mjs +2 -0
  29. package/dist/server-iFSng50i.mjs +385 -0
  30. package/dist/signals/index.d.mts +2 -2
  31. package/dist/signals/index.mjs +5 -3
  32. package/dist/{slot-B8y0aEoz.d.mts → slot-BFWXeFRl.d.mts} +6 -0
  33. package/dist/{slot-Cne__au7.mjs → slot-Dvf30O0B.mjs} +12 -1
  34. package/dist/slot.d.mts +1 -1
  35. package/dist/slot.mjs +1 -1
  36. package/dist/{infer-B7T5hi_D.d.mts → types-ncUK9rki.d.mts} +140 -141
  37. package/dist/ui/overlay/index.css +70 -0
  38. package/dist/ui/overlay/index.d.mts +209 -0
  39. package/dist/ui/overlay/index.mjs +1001 -0
  40. package/dist/ui/overlay/overlay.css +332 -0
  41. package/dist/utilities/_observe.mjs +1 -1
  42. package/dist/utilities/active-element.d.mts +1 -1
  43. package/dist/utilities/active-element.mjs +1 -1
  44. package/dist/utilities/async.d.mts +19 -2
  45. package/dist/utilities/async.mjs +49 -2
  46. package/dist/utilities/context.mjs +1 -1
  47. package/dist/utilities/debounced.d.mts +1 -1
  48. package/dist/utilities/debounced.mjs +1 -1
  49. package/dist/utilities/dom-lifecycle.bench.mjs +3255 -1
  50. package/dist/utilities/dom-lifecycle.mjs +1 -1
  51. package/dist/utilities/element-rect.d.mts +1 -1
  52. package/dist/utilities/element-rect.mjs +1 -1
  53. package/dist/utilities/element-scroll.d.mts +1 -1
  54. package/dist/utilities/event-driven.d.mts +1 -1
  55. package/dist/utilities/event-driven.mjs +1 -1
  56. package/dist/utilities/event-listener.d.mts +1 -1
  57. package/dist/utilities/event-listener.mjs +1 -1
  58. package/dist/utilities/focus-within.d.mts +1 -1
  59. package/dist/utilities/focus-within.mjs +1 -1
  60. package/dist/utilities/form-object.d.mts +96 -0
  61. package/dist/utilities/form-object.mjs +285 -0
  62. package/dist/utilities/hover.d.mts +1 -1
  63. package/dist/utilities/hover.mjs +1 -1
  64. package/dist/utilities/interval.d.mts +1 -1
  65. package/dist/utilities/interval.mjs +1 -1
  66. package/dist/utilities/location.d.mts +1 -1
  67. package/dist/utilities/location.mjs +1 -1
  68. package/dist/utilities/media-devices.d.mts +1 -1
  69. package/dist/utilities/media-devices.mjs +1 -1
  70. package/dist/utilities/media-player.d.mts +1 -1
  71. package/dist/utilities/media-query.d.mts +1 -1
  72. package/dist/utilities/media-query.mjs +1 -1
  73. package/dist/utilities/network.d.mts +1 -1
  74. package/dist/utilities/network.mjs +1 -1
  75. package/dist/utilities/orientation.d.mts +1 -1
  76. package/dist/utilities/orientation.mjs +1 -1
  77. package/dist/utilities/previous.d.mts +1 -1
  78. package/dist/utilities/previous.mjs +1 -1
  79. package/dist/utilities/promise.d.mts +19 -2
  80. package/dist/utilities/promise.mjs +33 -3
  81. package/dist/utilities/retry.mjs +1 -1
  82. package/dist/utilities/routing.d.mts +1 -1
  83. package/dist/utilities/routing.mjs +1 -1
  84. package/dist/utilities/search-params.d.mts +1 -1
  85. package/dist/utilities/storage.d.mts +1 -1
  86. package/dist/utilities/throttled.d.mts +1 -1
  87. package/dist/utilities/throttled.mjs +1 -1
  88. package/dist/utilities/timeout.d.mts +1 -1
  89. package/dist/utilities/timeout.mjs +1 -1
  90. package/dist/utilities/window-focus.d.mts +1 -1
  91. package/dist/utilities/window-focus.mjs +1 -1
  92. package/dist/utilities/window-size.d.mts +1 -1
  93. package/dist/utilities/window-size.mjs +1 -1
  94. package/package.json +20 -5
  95. package/dist/benchmark.CX_oY03V-CSLAXL5f.mjs +0 -5145
  96. package/dist/magic-string.es-CXefOmkB.mjs +0 -1011
  97. package/dist/test.BmQO5GaM-Ddz9cDxc.mjs +0 -8266
  98. package/dist/utilities/active-element.test.d.mts +0 -1
  99. package/dist/utilities/active-element.test.mjs +0 -25
  100. package/dist/utilities/async.test.d.mts +0 -1
  101. package/dist/utilities/async.test.mjs +0 -275
  102. package/dist/utilities/context.test.d.mts +0 -1
  103. package/dist/utilities/context.test.mjs +0 -171
  104. package/dist/utilities/debounced.test.d.mts +0 -1
  105. package/dist/utilities/debounced.test.mjs +0 -68
  106. package/dist/utilities/dom-lifecycle.test.d.mts +0 -1
  107. package/dist/utilities/dom-lifecycle.test.mjs +0 -228
  108. package/dist/utilities/element-rect.test.d.mts +0 -1
  109. package/dist/utilities/element-rect.test.mjs +0 -101
  110. package/dist/utilities/element-scroll.test.d.mts +0 -1
  111. package/dist/utilities/element-scroll.test.mjs +0 -27
  112. package/dist/utilities/event-listener.test.d.mts +0 -1
  113. package/dist/utilities/event-listener.test.mjs +0 -60
  114. package/dist/utilities/focus-within.test.d.mts +0 -1
  115. package/dist/utilities/focus-within.test.mjs +0 -51
  116. package/dist/utilities/hover.test.d.mts +0 -1
  117. package/dist/utilities/hover.test.mjs +0 -54
  118. package/dist/utilities/intersection-observer.test.d.mts +0 -1
  119. package/dist/utilities/intersection-observer.test.mjs +0 -46
  120. package/dist/utilities/interval.test.d.mts +0 -1
  121. package/dist/utilities/interval.test.mjs +0 -115
  122. package/dist/utilities/location.test.d.mts +0 -1
  123. package/dist/utilities/location.test.mjs +0 -61
  124. package/dist/utilities/long-press.test.d.mts +0 -1
  125. package/dist/utilities/long-press.test.mjs +0 -54
  126. package/dist/utilities/media-devices.test.d.mts +0 -1
  127. package/dist/utilities/media-devices.test.mjs +0 -44
  128. package/dist/utilities/media-player.test.d.mts +0 -1
  129. package/dist/utilities/media-player.test.mjs +0 -102
  130. package/dist/utilities/mutation-observer.test.d.mts +0 -1
  131. package/dist/utilities/mutation-observer.test.mjs +0 -48
  132. package/dist/utilities/network.test.d.mts +0 -1
  133. package/dist/utilities/network.test.mjs +0 -30
  134. package/dist/utilities/on-click-outside.test.d.mts +0 -1
  135. package/dist/utilities/on-click-outside.test.mjs +0 -45
  136. package/dist/utilities/previous.test.d.mts +0 -1
  137. package/dist/utilities/previous.test.mjs +0 -90
  138. package/dist/utilities/promise.test.d.mts +0 -1
  139. package/dist/utilities/promise.test.mjs +0 -158
  140. package/dist/utilities/retry.test.d.mts +0 -1
  141. package/dist/utilities/retry.test.mjs +0 -85
  142. package/dist/utilities/routing.test.d.mts +0 -1
  143. package/dist/utilities/routing.test.mjs +0 -129
  144. package/dist/utilities/search-params.test.d.mts +0 -1
  145. package/dist/utilities/search-params.test.mjs +0 -37
  146. package/dist/utilities/ssr.test.d.mts +0 -1
  147. package/dist/utilities/ssr.test.mjs +0 -65
  148. package/dist/utilities/storage.test.d.mts +0 -1
  149. package/dist/utilities/storage.test.mjs +0 -139
  150. package/dist/utilities/throttled.test.d.mts +0 -1
  151. package/dist/utilities/throttled.test.mjs +0 -58
  152. package/dist/utilities/timeout.test.d.mts +0 -1
  153. package/dist/utilities/timeout.test.mjs +0 -121
  154. package/dist/utilities/window-size.test.d.mts +0 -1
  155. package/dist/utilities/window-size.test.mjs +0 -43
  156. /package/dist/{custom-elements-D5CgfNKc.d.mts → custom-elements-DK5VUcWA.d.mts} +0 -0
@@ -290,10 +290,10 @@ let activeSub;
290
290
  let activeOwner;
291
291
  /** Ring-buffer of effects waiting to be flushed. */
292
292
  const queued = [];
293
- const SIGNAL = Symbol("signal");
294
- const COMPUTED = Symbol("computed");
295
- const EFFECT = Symbol("effect");
296
- const EFFECT_SCOPE = Symbol("effectScope");
293
+ const SIGNAL = Symbol.for("elements-kit.signal");
294
+ const COMPUTED = Symbol.for("elements-kit.computed");
295
+ const EFFECT = Symbol.for("elements-kit.effect");
296
+ const EFFECT_SCOPE = Symbol.for("elements-kit.effectScope");
297
297
  const { link, unlink, propagate, checkDirty, shallowPropagate } = createReactiveSystem({
298
298
  /**
299
299
  * Called by the graph engine when a Mutable+Dirty node needs to recompute.
@@ -509,7 +509,65 @@ function computed(getter) {
509
509
  * stop(); // final cleanup: abort the last fetch
510
510
  * ```
511
511
  */
512
+ /**
513
+ * @internal Method key for settling a reactive async wrapper from a
514
+ * serialized server snapshot (hydration seeding). Lives here so
515
+ * `utilities/promise`, `utilities/async` and `hydrate` can share it without
516
+ * a utility-to-utility dependency.
517
+ */
518
+ const SEED = Symbol.for("elements-kit.seed");
519
+ /**
520
+ * @internal Method key for the hydrate claim protocol: the claim walk hands
521
+ * each async wrapper its ek-data record (or undefined). The wrapper decides —
522
+ * seed and discard any deferred run, or execute the deferred run now.
523
+ */
524
+ const CLAIM = Symbol.for("elements-kit.claim");
525
+ /**
526
+ * @internal Brand stamped on dynamic-region getters that rendered as async
527
+ * insertion points on the server (Await boundaries). The value carries
528
+ * the number of ek-data ids the server consumed for the region and a
529
+ * pending-probe — the hydrate walk advances its counter and keeps the
530
+ * server content while the region is pending instead of flashing the
531
+ * fallback.
532
+ */
533
+ const ASYNC_REGION = Symbol.for("elements-kit.async-region");
534
+ const MODE_STATE = Symbol.for("elements-kit.mode-state");
535
+ const modeState = globalThis[MODE_STATE] ??= {
536
+ deferAsyncRuns: false,
537
+ inertEffects: false
538
+ };
539
+ /**
540
+ * @internal While true (hydrate evaluation phase), `Async.run()` records
541
+ * intent instead of executing — the claim walk or the post-walk flush decides
542
+ * whether the fetcher actually runs. Returns the previous flag.
543
+ */
544
+ function setDeferAsyncRuns(value) {
545
+ const prev = modeState.deferAsyncRuns;
546
+ modeState.deferAsyncRuns = value;
547
+ return prev;
548
+ }
549
+ /** @internal */
550
+ function shouldDeferAsyncRuns() {
551
+ return modeState.deferAsyncRuns;
552
+ }
553
+ /** @internal True during server rendering (see {@link setInertEffects}). */
554
+ function effectsInert() {
555
+ return modeState.inertEffects;
556
+ }
557
+ /**
558
+ * Toggle inert-effect mode. While inert, `effect()` neither executes its body
559
+ * nor tracks dependencies — it returns a no-op stop function. Used by the
560
+ * server renderer: a server render is a one-shot snapshot, effects are
561
+ * client-only. Returns the previous flag so callers can restore it.
562
+ */
563
+ function setInertEffects(value) {
564
+ const prev = modeState.inertEffects;
565
+ modeState.inertEffects = value;
566
+ return prev;
567
+ }
568
+ const inertStop = () => {};
512
569
  function effect(fn) {
570
+ if (modeState.inertEffects) return inertStop;
513
571
  const e = {
514
572
  fn,
515
573
  subs: void 0,
@@ -997,4 +1055,4 @@ function purgeDeps(sub) {
997
1055
  while (dep !== void 0) dep = unlink(dep, sub);
998
1056
  }
999
1057
  //#endregion
1000
- export { batch as a, effectScope as c, isEffectScope as d, isSignal as f, untracked as g, trigger as h, SIGNAL as i, isComputed as l, signal as m, EFFECT as n, computed as o, onCleanup as p, EFFECT_SCOPE as r, effect as s, COMPUTED as t, isEffect as u };
1058
+ export { untracked as C, trigger as S, onCleanup as _, EFFECT_SCOPE as a, shouldDeferAsyncRuns as b, batch as c, effectScope as d, effectsInert as f, isSignal as g, isEffectScope as h, EFFECT as i, computed as l, isEffect as m, CLAIM as n, SEED as o, isComputed as p, COMPUTED as r, SIGNAL as s, ASYNC_REGION as t, effect as u, setDeferAsyncRuns as v, signal as x, setInertEffects as y };
package/dist/render.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as scope } from "./scope-CnEvL9Nd.mjs";
1
+ import { t as scope } from "./scope-zbEG299F.mjs";
2
2
  //#region src/render.ts
3
3
  /**
4
4
  * Mount a node into `target` with a scoped lifetime.
@@ -1,4 +1,4 @@
1
- import { c as effectScope, g as untracked } from "./lib-Dkc7cV5F.mjs";
1
+ import { C as untracked, d as effectScope } from "./lib-DYypKhxk.mjs";
2
2
  //#region src/signals/scope.ts
3
3
  /**
4
4
  * Run `setup` inside a fresh `effectScope`. Returns `[result, stop]`.
@@ -0,0 +1,43 @@
1
+ //#region src/server/index.d.ts
2
+ /**
3
+ * Render a component tree to a streaming HTML response in any JavaScript
4
+ * runtime — no DOM required.
5
+ *
6
+ * Pass a thunk, not evaluated JSX: JSX evaluates eagerly, so the server
7
+ * renderer must be installed before the first jsx call runs.
8
+ *
9
+ * Streaming is in-order: all HTML preceding an async insertion point
10
+ * (`promise`/`async` reactive values used as children) flushes immediately;
11
+ * the stream then awaits the value and continues. Resolved values are
12
+ * serialized into a `<script type="application/json" id="ek-data">` tag at
13
+ * the end of the stream so the client hydration pass reuses them instead of
14
+ * refetching.
15
+ *
16
+ * Server semantics: signal/computed reads are a one-shot snapshot (no
17
+ * subscriptions), effects do not run, `on:` handlers and `ref` are skipped —
18
+ * interactivity attaches on the client via `elements-kit/hydrate`.
19
+ *
20
+ * Errors — including rejected async values — propagate and abort the stream.
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * export default {
25
+ * fetch: () => new Response(renderToStream(() => <App />), {
26
+ * headers: { "content-type": "text/html" },
27
+ * }),
28
+ * };
29
+ * ```
30
+ */
31
+ declare function renderToStream(app: () => unknown): ReadableStream<Uint8Array>;
32
+ /**
33
+ * Render a component tree to a complete HTML string. Convenience wrapper
34
+ * around {@link renderToStream} — same semantics, buffered to one string.
35
+ *
36
+ * @example
37
+ * ```tsx
38
+ * const html = await renderToString(() => <App />);
39
+ * ```
40
+ */
41
+ declare function renderToString(app: () => unknown): Promise<string>;
42
+ //#endregion
43
+ export { renderToStream, renderToString };
@@ -0,0 +1,2 @@
1
+ import { n as renderToString, t as renderToStream } from "../server-iFSng50i.mjs";
2
+ export { renderToStream, renderToString };
@@ -0,0 +1,385 @@
1
+ import { C as untracked, y as setInertEffects } from "./lib-DYypKhxk.mjs";
2
+ import { isReactive, resolveProps } from "./signals/index.mjs";
3
+ import { isReactivePromiseLike } from "./utilities/promise.mjs";
4
+ import { isAsyncLike } from "./utilities/async.mjs";
5
+ import { c as BooleanAttributes, l as ChildProperties, r as setRenderer, s as AttrAliases, u as Properties } from "./element-D3om9yA6.mjs";
6
+ import { isForComponent } from "./for.mjs";
7
+ import { n as isFragmentComponent } from "./fragment-ROPRBJQd.mjs";
8
+ //#region src/server/escape.ts
9
+ function escapeDelim(s, delim, escDelim) {
10
+ let iDelim = s.indexOf(delim);
11
+ let iAmp = s.indexOf("&");
12
+ if (iDelim < 0 && iAmp < 0) return s;
13
+ let left = 0;
14
+ let out = "";
15
+ while (iDelim >= 0 && iAmp >= 0) if (iDelim < iAmp) {
16
+ if (left < iDelim) out += s.substring(left, iDelim);
17
+ out += escDelim;
18
+ left = iDelim + 1;
19
+ iDelim = s.indexOf(delim, left);
20
+ } else {
21
+ if (left < iAmp) out += s.substring(left, iAmp);
22
+ out += "&amp;";
23
+ left = iAmp + 1;
24
+ iAmp = s.indexOf("&", left);
25
+ }
26
+ if (iDelim >= 0) do {
27
+ if (left < iDelim) out += s.substring(left, iDelim);
28
+ out += escDelim;
29
+ left = iDelim + 1;
30
+ iDelim = s.indexOf(delim, left);
31
+ } while (iDelim >= 0);
32
+ else while (iAmp >= 0) {
33
+ if (left < iAmp) out += s.substring(left, iAmp);
34
+ out += "&amp;";
35
+ left = iAmp + 1;
36
+ iAmp = s.indexOf("&", left);
37
+ }
38
+ return left < s.length ? out + s.substring(left) : out;
39
+ }
40
+ /** Escape a text node. */
41
+ function escapeHtml(value) {
42
+ return escapeDelim(value, "<", "&lt;");
43
+ }
44
+ /** Escape a double-quoted attribute value. */
45
+ function escapeAttr(value) {
46
+ return escapeDelim(value, "\"", "&quot;");
47
+ }
48
+ /** Neutralize `<\/script>` sequences inside an inline JSON script payload. */
49
+ function escapeScriptJson(json) {
50
+ return json.replace(/<\//g, "<\\/");
51
+ }
52
+ //#endregion
53
+ //#region src/server/jsx.ts
54
+ /**
55
+ * Server output node. Nested jsx calls return `SNode`s so the children walk
56
+ * can distinguish pre-rendered markup (spliced verbatim) from user strings
57
+ * (escaped).
58
+ */
59
+ var SNode = class {
60
+ chunks;
61
+ constructor(chunks) {
62
+ this.chunks = chunks;
63
+ }
64
+ };
65
+ /**
66
+ * An async insertion point. The stream awaits it in document order and
67
+ * assigns its serialization id at emit time — ids must follow document
68
+ * order (not jsx-evaluation order, which is children-first) so the hydrate
69
+ * walk, which runs in document order, aligns with them.
70
+ */
71
+ var AsyncChunk = class {
72
+ instance;
73
+ constructor(instance) {
74
+ this.instance = instance;
75
+ }
76
+ };
77
+ /** Normalize an arbitrary resolved value into chunks (used by the stream). */
78
+ function resolveChildChunks(value) {
79
+ return child(value);
80
+ }
81
+ const SLOT_OPEN = "<!--{-->";
82
+ const SLOT_CLOSE = "<!--}-->";
83
+ const FOR_OPEN = "<!--<For>-->";
84
+ const FOR_CLOSE = "<!--</For>-->";
85
+ const VoidElements = new Set([
86
+ "area",
87
+ "base",
88
+ "br",
89
+ "col",
90
+ "embed",
91
+ "hr",
92
+ "img",
93
+ "input",
94
+ "link",
95
+ "meta",
96
+ "param",
97
+ "source",
98
+ "track",
99
+ "wbr"
100
+ ]);
101
+ const PropertyAttrAliases = {
102
+ className: "class",
103
+ defaultValue: "value",
104
+ defaultChecked: "checked",
105
+ defaultSelected: "selected",
106
+ defaultMuted: "muted",
107
+ indeterminate: null
108
+ };
109
+ function serverJsx(type, props) {
110
+ if (typeof type === "string") return element(type, props);
111
+ if (isFragmentComponent(type)) {
112
+ if (props.html) {
113
+ const source = props.children;
114
+ const value = typeof source === "function" ? untracked(source) : source;
115
+ return new SNode([
116
+ SLOT_OPEN,
117
+ value == null ? "" : String(value),
118
+ SLOT_CLOSE
119
+ ]);
120
+ }
121
+ return new SNode(childList(props.children));
122
+ }
123
+ if (isForComponent(type)) return forElement(props);
124
+ if (typeof type === "function" && !type.prototype?.render) return new SNode(child(type(resolveProps(props))));
125
+ const name = typeof type === "function" ? type.name ?? "anonymous" : String(type);
126
+ throw new Error(`Server rendering does not support class components ("${name}"); v1 supports intrinsic elements, function components, Fragment and For.`);
127
+ }
128
+ function element(tag, props) {
129
+ let attrs = "";
130
+ let classBase;
131
+ const classToggles = [];
132
+ let styleBase;
133
+ const styleEntries = [];
134
+ let childrenValue;
135
+ let textValue;
136
+ for (const [key, rawValue] of Object.entries(props)) {
137
+ if (key === "children") {
138
+ childrenValue = rawValue;
139
+ continue;
140
+ }
141
+ if (key === "ref") continue;
142
+ const colonIdx = key.indexOf(":");
143
+ const ns = colonIdx > 0 ? key.slice(0, colonIdx) : "";
144
+ if (ns === "on") continue;
145
+ const value = isReactive(rawValue) ? untracked(rawValue) : rawValue;
146
+ if (ns) {
147
+ const name = key.slice(colonIdx + 1);
148
+ if (ns === "prop") continue;
149
+ if (ns === "class") {
150
+ if (value) classToggles.push(name);
151
+ continue;
152
+ }
153
+ if (ns === "style") {
154
+ if (value != null && value !== false) styleEntries.push(`${name}:${String(value)}`);
155
+ continue;
156
+ }
157
+ if (ns === "xlink" || ns === "xml") {
158
+ attrs += attr(key, value);
159
+ continue;
160
+ }
161
+ }
162
+ if (key === "class") {
163
+ classBase = value == null ? void 0 : String(value);
164
+ continue;
165
+ }
166
+ if (key === "style") {
167
+ styleBase = styleToString(value);
168
+ continue;
169
+ }
170
+ if (ChildProperties.has(key)) {
171
+ if (key === "innerHTML") throw new Error("innerHTML is not supported in server rendering — there is no raw HTML sink.");
172
+ textValue = value;
173
+ continue;
174
+ }
175
+ if (Properties.has(key)) {
176
+ const alias = PropertyAttrAliases[key];
177
+ if (alias === null) continue;
178
+ if (alias === "class") {
179
+ classBase = value == null ? void 0 : String(value);
180
+ continue;
181
+ }
182
+ attrs += attr(alias ?? key.toLowerCase(), value);
183
+ continue;
184
+ }
185
+ attrs += attr(AttrAliases[key] ?? key, value);
186
+ }
187
+ const classes = [...classBase !== void 0 && classBase !== "" ? [classBase] : [], ...classToggles];
188
+ if (classBase !== void 0 || classToggles.length > 0) attrs += attr("class", classes.join(" "));
189
+ const styles = [...styleBase ? [styleBase] : [], ...styleEntries];
190
+ if (styles.length > 0) attrs += attr("style", styles.join(";"));
191
+ const open = `<${tag}${attrs}>`;
192
+ if (VoidElements.has(tag)) return new SNode([open]);
193
+ return new SNode([
194
+ open,
195
+ ...textValue != null ? [escapeHtml(String(textValue))] : childList(childrenValue),
196
+ `</${tag}>`
197
+ ]);
198
+ }
199
+ function attr(name, value) {
200
+ if (BooleanAttributes.has(name)) return value ? ` ${name}` : "";
201
+ if (value == null || value === false) return "";
202
+ if (value === true || value === "") return ` ${name}`;
203
+ return ` ${name}="${escapeAttr(String(value))}"`;
204
+ }
205
+ function styleToString(value) {
206
+ if (value == null || value === false) return void 0;
207
+ if (typeof value === "string") return value;
208
+ if (typeof value === "object") return Object.entries(value).filter(([, v]) => v != null && v !== false).map(([k, v]) => `${k.includes("-") ? k : k.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`)}:${String(v)}`).join(";");
209
+ return String(value);
210
+ }
211
+ function childList(raw) {
212
+ if (raw == null) return [];
213
+ if (Array.isArray(raw)) return raw.flat(Infinity).flatMap(child);
214
+ return child(raw);
215
+ }
216
+ function child(c) {
217
+ if (c == null || typeof c === "boolean") return [];
218
+ if (c instanceof SNode) return [c];
219
+ if (isReactivePromiseLike(c) || isAsyncLike(c)) return asyncChild(c);
220
+ if (typeof c === "function") return [
221
+ SLOT_OPEN,
222
+ ...child(untracked(c)),
223
+ SLOT_CLOSE
224
+ ];
225
+ if (typeof c === "string") return [escapeHtml(c)];
226
+ if (typeof c === "number" || typeof c === "bigint") return [String(c)];
227
+ if (Array.isArray(c)) return c.flat(Infinity).flatMap(child);
228
+ return [escapeHtml(String(c))];
229
+ }
230
+ function asyncChild(p) {
231
+ return [
232
+ SLOT_OPEN,
233
+ new AsyncChunk(p),
234
+ SLOT_CLOSE
235
+ ];
236
+ }
237
+ function forElement(props) {
238
+ const each = props.each;
239
+ const items = untracked(() => typeof each === "function" ? each() : each);
240
+ const by = props.by ?? ((_item, index) => index);
241
+ const render = props.children;
242
+ const chunks = [FOR_OPEN];
243
+ (items ?? []).forEach((item, index) => {
244
+ const key = encodeURIComponent(String(by(item, index)));
245
+ chunks.push(`<!--[${key}]-->`, ...child(render(item, index)), `<!--[/${key}]-->`);
246
+ });
247
+ chunks.push(FOR_CLOSE);
248
+ return new SNode(chunks);
249
+ }
250
+ //#endregion
251
+ //#region src/server/index.ts
252
+ /**
253
+ * Render a component tree to a streaming HTML response in any JavaScript
254
+ * runtime — no DOM required.
255
+ *
256
+ * Pass a thunk, not evaluated JSX: JSX evaluates eagerly, so the server
257
+ * renderer must be installed before the first jsx call runs.
258
+ *
259
+ * Streaming is in-order: all HTML preceding an async insertion point
260
+ * (`promise`/`async` reactive values used as children) flushes immediately;
261
+ * the stream then awaits the value and continues. Resolved values are
262
+ * serialized into a `<script type="application/json" id="ek-data">` tag at
263
+ * the end of the stream so the client hydration pass reuses them instead of
264
+ * refetching.
265
+ *
266
+ * Server semantics: signal/computed reads are a one-shot snapshot (no
267
+ * subscriptions), effects do not run, `on:` handlers and `ref` are skipped —
268
+ * interactivity attaches on the client via `elements-kit/hydrate`.
269
+ *
270
+ * Errors — including rejected async values — propagate and abort the stream.
271
+ *
272
+ * @example
273
+ * ```tsx
274
+ * export default {
275
+ * fetch: () => new Response(renderToStream(() => <App />), {
276
+ * headers: { "content-type": "text/html" },
277
+ * }),
278
+ * };
279
+ * ```
280
+ */
281
+ function renderToStream(app) {
282
+ const encoder = new TextEncoder();
283
+ return new ReadableStream({ async start(controller) {
284
+ try {
285
+ const ctx = {
286
+ records: [],
287
+ counter: 0
288
+ };
289
+ const root = evaluate(app);
290
+ let buffer = "";
291
+ const flush = () => {
292
+ if (buffer.length === 0) return;
293
+ controller.enqueue(encoder.encode(buffer));
294
+ buffer = "";
295
+ };
296
+ const emit = async (node) => {
297
+ if (node == null || typeof node === "boolean") return;
298
+ if (typeof node === "string") {
299
+ buffer += node;
300
+ return;
301
+ }
302
+ if (node instanceof SNode) {
303
+ for (const chunk of node.chunks) await emit(chunk);
304
+ return;
305
+ }
306
+ if (node instanceof AsyncChunk) {
307
+ flush();
308
+ const id = ctx.counter++;
309
+ const value = await node.instance;
310
+ ctx.records.push({
311
+ id,
312
+ value
313
+ });
314
+ const prevInert = setInertEffects(true);
315
+ setRenderer({ jsx: serverJsx });
316
+ let chunks;
317
+ try {
318
+ chunks = resolveChildChunks(value);
319
+ } finally {
320
+ setRenderer(null);
321
+ setInertEffects(prevInert);
322
+ }
323
+ for (const chunk of chunks) await emit(chunk);
324
+ return;
325
+ }
326
+ buffer += String(node);
327
+ };
328
+ await emit(root);
329
+ if (ctx.records.length > 0) buffer += serializeRecords(ctx.records);
330
+ flush();
331
+ controller.close();
332
+ } catch (error) {
333
+ controller.error(error);
334
+ }
335
+ } });
336
+ }
337
+ /**
338
+ * Render a component tree to a complete HTML string. Convenience wrapper
339
+ * around {@link renderToStream} — same semantics, buffered to one string.
340
+ *
341
+ * @example
342
+ * ```tsx
343
+ * const html = await renderToString(() => <App />);
344
+ * ```
345
+ */
346
+ async function renderToString(app) {
347
+ const reader = renderToStream(app).getReader();
348
+ const decoder = new TextDecoder();
349
+ let out = "";
350
+ for (;;) {
351
+ const { done, value } = await reader.read();
352
+ if (done) break;
353
+ out += decoder.decode(value, { stream: true });
354
+ }
355
+ return out;
356
+ }
357
+ /** Run `app` with the server renderer installed and effects inert. */
358
+ function evaluate(app) {
359
+ const prevInert = setInertEffects(true);
360
+ setRenderer({ jsx: serverJsx });
361
+ try {
362
+ return app();
363
+ } finally {
364
+ setRenderer(null);
365
+ setInertEffects(prevInert);
366
+ }
367
+ }
368
+ function serializeRecords(records) {
369
+ const parts = [];
370
+ for (const record of records) {
371
+ if (typeof record.value === "function") continue;
372
+ let json;
373
+ try {
374
+ json = JSON.stringify({ value: record.value });
375
+ } catch {
376
+ continue;
377
+ }
378
+ if (json === void 0) continue;
379
+ parts.push(`"${record.id}":${json}`);
380
+ }
381
+ if (parts.length === 0) return "";
382
+ return `<script type="application/json" id="ek-data">${escapeScriptJson(`{${parts.join(",")}}`)}<\/script>`;
383
+ }
384
+ //#endregion
385
+ export { serverJsx as i, renderToString as n, SNode as r, renderToStream as t };
@@ -1,2 +1,2 @@
1
- import { A as SIGNAL, B as signal, C as isReactive, D as COMPUTED, E as resolveProps, F as isComputed, H as untracked, I as isEffect, L as isEffectScope, M as computed, N as effect, O as EFFECT, P as effectScope, R as isSignal, S as Updater, T as resolve, V as trigger, b as MaybeReactive, j as batch, k as EFFECT_SCOPE, w as reactive, x as Signal, y as Computed, z as onCleanup } from "../infer-B7T5hi_D.mjs";
2
- export { COMPUTED, Computed, EFFECT, EFFECT_SCOPE, MaybeReactive, SIGNAL, Signal, Updater, batch, computed, effect, effectScope, isComputed, isEffect, isEffectScope, isReactive, isSignal, onCleanup, reactive, resolve, resolveProps, signal, trigger, untracked };
1
+ import { A as EFFECT_SCOPE, B as isSignal, C as isReactive, D as CLAIM, E as resolveProps, F as effect, H as signal, I as effectScope, L as isComputed, M as SIGNAL, N as batch, O as COMPUTED, P as computed, R as isEffect, S as Updater, T as resolve, U as trigger, V as onCleanup, W as untracked, b as MaybeReactive, j as SEED, k as EFFECT, w as reactive, x as Signal, y as Computed, z as isEffectScope } from "../types-ncUK9rki.mjs";
2
+ export { CLAIM, COMPUTED, Computed, EFFECT, EFFECT_SCOPE, MaybeReactive, SEED, SIGNAL, Signal, Updater, batch, computed, effect, effectScope, isComputed, isEffect, isEffectScope, isReactive, isSignal, onCleanup, reactive, resolve, resolveProps, signal, trigger, untracked };
@@ -1,4 +1,4 @@
1
- import { a as batch, c as effectScope, d as isEffectScope, f as isSignal, g as untracked, h as trigger, i as SIGNAL, l as isComputed, m as signal, n as EFFECT, o as computed, p as onCleanup, r as EFFECT_SCOPE, s as effect, t as COMPUTED, u as isEffect } from "../lib-Dkc7cV5F.mjs";
1
+ import { C as untracked, S as trigger, _ as onCleanup, a as EFFECT_SCOPE, c as batch, d as effectScope, g as isSignal, h as isEffectScope, i as EFFECT, l as computed, m as isEffect, n as CLAIM, o as SEED, p as isComputed, r as COMPUTED, s as SIGNAL, u as effect, x as signal } from "../lib-DYypKhxk.mjs";
2
2
  import "../polyfill-CdZVCxdo.mjs";
3
3
  //#region src/signals/index.ts
4
4
  /**
@@ -108,7 +108,9 @@ function resolve(value) {
108
108
  * props.label(); // "n"
109
109
  * ```
110
110
  */
111
+ const RESOLVED_PROPS = Symbol.for("elements-kit.resolved-props");
111
112
  function resolveProps(raw) {
113
+ if (raw[RESOLVED_PROPS]) return raw;
112
114
  const ownKeys = Reflect.ownKeys(raw);
113
115
  const ownKeySet = new Set(ownKeys);
114
116
  const cache = /* @__PURE__ */ new Map();
@@ -122,7 +124,7 @@ function resolveProps(raw) {
122
124
  return getter;
123
125
  };
124
126
  return new Proxy(raw, {
125
- get: (_target, key) => get(key),
127
+ get: (_target, key) => key === RESOLVED_PROPS ? true : get(key),
126
128
  has: (_target, key) => ownKeySet.has(key),
127
129
  ownKeys: () => ownKeys,
128
130
  getOwnPropertyDescriptor: (_target, key) => ownKeySet.has(key) ? {
@@ -134,4 +136,4 @@ function resolveProps(raw) {
134
136
  });
135
137
  }
136
138
  //#endregion
137
- export { COMPUTED, EFFECT, EFFECT_SCOPE, SIGNAL, batch, computed, effect, effectScope, isComputed, isEffect, isEffectScope, isReactive, isSignal, onCleanup, reactive, resolve, resolveProps, signal, trigger, untracked };
139
+ export { CLAIM, COMPUTED, EFFECT, EFFECT_SCOPE, SEED, SIGNAL, batch, computed, effect, effectScope, isComputed, isEffect, isEffectScope, isReactive, isSignal, onCleanup, reactive, resolve, resolveProps, signal, trigger, untracked };
@@ -18,6 +18,12 @@ declare global {
18
18
  */
19
19
  declare class Slot {
20
20
  #private;
21
+ /**
22
+ * Bind a slot to an existing marker pair (server-rendered comments) instead
23
+ * of creating new ones. Used by the hydrate claim pass: content between the
24
+ * markers is adopted as the slot's current content.
25
+ */
26
+ static claim(start: Comment, end: Comment): Slot;
21
27
  /**
22
28
  * Render the slot as a DocumentFragment.
23
29
  * If not yet mounted, inserts the comment markers and optional default content.
@@ -18,11 +18,22 @@ function resolveNode(c) {
18
18
  * A lightweight slot that reserves a region in the DOM using comment markers.
19
19
  * Content between the markers can be replaced dynamically without wrapper elements.
20
20
  */
21
- var Slot = class {
21
+ var Slot = class Slot {
22
22
  #start;
23
23
  #end;
24
24
  #pending;
25
25
  /**
26
+ * Bind a slot to an existing marker pair (server-rendered comments) instead
27
+ * of creating new ones. Used by the hydrate claim pass: content between the
28
+ * markers is adopted as the slot's current content.
29
+ */
30
+ static claim(start, end) {
31
+ const slot = new Slot();
32
+ slot.#start = start;
33
+ slot.#end = end;
34
+ return slot;
35
+ }
36
+ /**
26
37
  * Render the slot as a DocumentFragment.
27
38
  * If not yet mounted, inserts the comment markers and optional default content.
28
39
  * If already mounted, extracts and returns the current content WITHOUT disposing
package/dist/slot.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { n as Slot, t as SLOTS } from "./slot-B8y0aEoz.mjs";
1
+ import { n as Slot, t as SLOTS } from "./slot-BFWXeFRl.mjs";
2
2
  export { SLOTS, Slot };
package/dist/slot.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { n as Slot, t as SLOTS } from "./slot-Cne__au7.mjs";
1
+ import { n as Slot, t as SLOTS } from "./slot-Dvf30O0B.mjs";
2
2
  export { SLOTS, Slot };