@barefootjs/client 0.14.0 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,188 @@
1
+ // ../shared/src/markers.ts
2
+ var BF_SCOPE = "bf-s";
3
+ var BF_SLOT = "bf";
4
+ var BF_HOST = "bf-h";
5
+ var BF_AT = "bf-m";
6
+ var BF_PROPS = "bf-p";
7
+ var BF_COND = "bf-c";
8
+ var BF_PORTAL_OWNER = "bf-po";
9
+ var BF_PORTAL_ID = "bf-pi";
10
+ var BF_PORTAL_PLACEHOLDER = "bf-pp";
11
+ var BF_PARENT_OWNED_PREFIX = "^";
12
+ var BF_SCOPE_COMMENT_PREFIX = "bf-scope:";
13
+ var BF_LOOP_START = "bf-loop";
14
+ var BF_LOOP_END = "bf-/loop";
15
+ var BF_LOOP_ITEM = "bf-loop-i";
16
+ function loopItemMarker(key) {
17
+ return `${BF_LOOP_ITEM}:${key}`;
18
+ }
19
+ function loopStartMarker(markerId) {
20
+ return `${BF_LOOP_START}:${markerId}`;
21
+ }
22
+ function loopEndMarker(markerId) {
23
+ return `${BF_LOOP_END}:${markerId}`;
24
+ }
25
+ var BF_KEY = "data-key";
26
+ var BF_PLACEHOLDER = "data-bf-ph";
27
+ var BF_ASYNC = "bf-async";
28
+ var BF_ASYNC_RESOLVE = "bf-async-resolve";
29
+ var BF_PARENT_SCOPE_PLACEHOLDER = "__BF_PARENT_SCOPE__";
30
+ var BF_SEAM_HYDRATE = "__bf_hydrate";
31
+ var BF_SEAM_HYDRATE_WITHIN = "__bf_hydrate_within";
32
+ var BF_SEAM_DISPOSE_WITHIN = "__bf_dispose_within";
33
+ var BF_SEAM_PUSH_SEARCH = "__bf_pushSearch";
34
+ // ../shared/src/dom-prop.ts
35
+ var BOOLEAN_ATTRS = new Set([
36
+ "checked",
37
+ "disabled",
38
+ "readonly",
39
+ "selected",
40
+ "required",
41
+ "hidden",
42
+ "autofocus",
43
+ "autoplay",
44
+ "controls",
45
+ "loop",
46
+ "muted",
47
+ "open",
48
+ "multiple",
49
+ "novalidate",
50
+ "formnovalidate"
51
+ ]);
52
+ var SVG_CAMEL_TO_KEBAB = {
53
+ strokeWidth: "stroke-width",
54
+ strokeLinecap: "stroke-linecap",
55
+ strokeLinejoin: "stroke-linejoin",
56
+ strokeDasharray: "stroke-dasharray",
57
+ strokeDashoffset: "stroke-dashoffset",
58
+ strokeMiterlimit: "stroke-miterlimit",
59
+ strokeOpacity: "stroke-opacity",
60
+ fillOpacity: "fill-opacity",
61
+ fillRule: "fill-rule",
62
+ stopColor: "stop-color",
63
+ stopOpacity: "stop-opacity",
64
+ textAnchor: "text-anchor",
65
+ dominantBaseline: "dominant-baseline",
66
+ alignmentBaseline: "alignment-baseline",
67
+ fontFamily: "font-family",
68
+ fontSize: "font-size",
69
+ fontWeight: "font-weight",
70
+ fontStyle: "font-style",
71
+ letterSpacing: "letter-spacing",
72
+ wordSpacing: "word-spacing",
73
+ pointerEvents: "pointer-events",
74
+ vectorEffect: "vector-effect",
75
+ colorInterpolation: "color-interpolation",
76
+ clipPath: "clip-path",
77
+ clipRule: "clip-rule",
78
+ markerStart: "marker-start",
79
+ markerMid: "marker-mid",
80
+ markerEnd: "marker-end"
81
+ };
82
+ var SVG_XML_CAMEL_ATTRS = new Set([
83
+ "allowReorder",
84
+ "attributeName",
85
+ "attributeType",
86
+ "autoReverse",
87
+ "baseFrequency",
88
+ "baseProfile",
89
+ "calcMode",
90
+ "clipPathUnits",
91
+ "contentScriptType",
92
+ "contentStyleType",
93
+ "diffuseConstant",
94
+ "edgeMode",
95
+ "externalResourcesRequired",
96
+ "filterRes",
97
+ "filterUnits",
98
+ "glyphRef",
99
+ "gradientTransform",
100
+ "gradientUnits",
101
+ "kernelMatrix",
102
+ "kernelUnitLength",
103
+ "keyPoints",
104
+ "keySplines",
105
+ "keyTimes",
106
+ "lengthAdjust",
107
+ "limitingConeAngle",
108
+ "markerHeight",
109
+ "markerUnits",
110
+ "markerWidth",
111
+ "maskContentUnits",
112
+ "maskUnits",
113
+ "numOctaves",
114
+ "pathLength",
115
+ "patternContentUnits",
116
+ "patternTransform",
117
+ "patternUnits",
118
+ "pointsAtX",
119
+ "pointsAtY",
120
+ "pointsAtZ",
121
+ "preserveAlpha",
122
+ "preserveAspectRatio",
123
+ "primitiveUnits",
124
+ "refX",
125
+ "refY",
126
+ "repeatCount",
127
+ "repeatDur",
128
+ "requiredExtensions",
129
+ "requiredFeatures",
130
+ "specularConstant",
131
+ "specularExponent",
132
+ "spreadMethod",
133
+ "startOffset",
134
+ "stdDeviation",
135
+ "stitchTiles",
136
+ "surfaceScale",
137
+ "systemLanguage",
138
+ "tableValues",
139
+ "targetX",
140
+ "targetY",
141
+ "textLength",
142
+ "viewBox",
143
+ "viewTarget",
144
+ "xChannelSelector",
145
+ "yChannelSelector",
146
+ "zoomAndPan"
147
+ ]);
148
+ function isEventProp(key) {
149
+ return key.length > 2 && key[0] === "o" && key[1] === "n" && key[2] >= "A" && key[2] <= "Z";
150
+ }
151
+ function classifyDOMProp(key) {
152
+ if (key === "children")
153
+ return { kind: "skip", attrName: key };
154
+ if (key === "ref")
155
+ return { kind: "ref", attrName: key };
156
+ if (key === "dangerouslySetInnerHTML")
157
+ return { kind: "innerHTML", attrName: key };
158
+ if (isEventProp(key))
159
+ return { kind: "event", attrName: key };
160
+ const attrName = toHTMLAttrNameRuntime(key);
161
+ if (attrName === "style")
162
+ return { kind: "style", attrName };
163
+ if (attrName === "value")
164
+ return { kind: "property", attrName };
165
+ if (attrName === "checked")
166
+ return { kind: "property", attrName };
167
+ if (BOOLEAN_ATTRS.has(attrName.toLowerCase()))
168
+ return { kind: "boolean", attrName };
169
+ return { kind: "attr", attrName };
170
+ }
171
+ function toHTMLAttrNameRuntime(key) {
172
+ if (key === "className")
173
+ return "class";
174
+ if (key === "htmlFor")
175
+ return "for";
176
+ const svgKebab = SVG_CAMEL_TO_KEBAB[key];
177
+ if (svgKebab !== undefined)
178
+ return svgKebab;
179
+ if (SVG_XML_CAMEL_ATTRS.has(key))
180
+ return key;
181
+ if (key.startsWith("data") || key.startsWith("aria")) {
182
+ return key.replace(/([A-Z])/g, "-$1").toLowerCase();
183
+ }
184
+ return key;
185
+ }
1
186
  // src/reactive.ts
2
187
  var profilerSink = null;
3
188
  var signalSeq = 0;
@@ -275,6 +460,40 @@ function createMemo(fn, __bfId) {
275
460
  }, id, "memo");
276
461
  return value;
277
462
  }
463
+ var serverEnvReader = null;
464
+ function __bfSetServerEnvReader(reader) {
465
+ serverEnvReader = reader;
466
+ }
467
+ function resolveServerEnv(key) {
468
+ if (serverEnvReader) {
469
+ const v = serverEnvReader(key);
470
+ if (v !== undefined)
471
+ return v;
472
+ }
473
+ const seam = globalThis.__bf_serverEnvReader;
474
+ return typeof seam === "function" ? seam(key) : undefined;
475
+ }
476
+ function createEnvSignal(key, readClient, parse, pushSeam) {
477
+ let getRaw = null;
478
+ function ensureClientSignal() {
479
+ if (!getRaw) {
480
+ const [get, set] = createSignal(readClient());
481
+ getRaw = get;
482
+ const w = window;
483
+ w[pushSeam] = (next) => {
484
+ set(next);
485
+ };
486
+ }
487
+ return getRaw();
488
+ }
489
+ return () => {
490
+ if (typeof window === "undefined") {
491
+ return parse(resolveServerEnv(key) ?? "");
492
+ }
493
+ return parse(ensureClientSignal());
494
+ };
495
+ }
496
+ var searchParams = createEnvSignal("search", () => window.location.search, (raw) => new URLSearchParams(raw), BF_SEAM_PUSH_SEARCH);
278
497
  // src/profiler-events.ts
279
498
  function createRecordingSink() {
280
499
  const events = [];
@@ -404,187 +623,6 @@ function forwardProps(source, overrides, excludeKeys) {
404
623
  function unwrap(prop) {
405
624
  return typeof prop === "function" ? prop() : prop;
406
625
  }
407
- // ../shared/src/markers.ts
408
- var BF_SCOPE = "bf-s";
409
- var BF_SLOT = "bf";
410
- var BF_HOST = "bf-h";
411
- var BF_AT = "bf-m";
412
- var BF_PROPS = "bf-p";
413
- var BF_COND = "bf-c";
414
- var BF_PORTAL_OWNER = "bf-po";
415
- var BF_PORTAL_ID = "bf-pi";
416
- var BF_PORTAL_PLACEHOLDER = "bf-pp";
417
- var BF_PARENT_OWNED_PREFIX = "^";
418
- var BF_SCOPE_COMMENT_PREFIX = "bf-scope:";
419
- var BF_LOOP_START = "bf-loop";
420
- var BF_LOOP_END = "bf-/loop";
421
- var BF_LOOP_ITEM = "bf-loop-i";
422
- function loopItemMarker(key) {
423
- return `${BF_LOOP_ITEM}:${key}`;
424
- }
425
- function loopStartMarker(markerId) {
426
- return `${BF_LOOP_START}:${markerId}`;
427
- }
428
- function loopEndMarker(markerId) {
429
- return `${BF_LOOP_END}:${markerId}`;
430
- }
431
- var BF_KEY = "data-key";
432
- var BF_PLACEHOLDER = "data-bf-ph";
433
- var BF_ASYNC = "bf-async";
434
- var BF_ASYNC_RESOLVE = "bf-async-resolve";
435
- var BF_PARENT_SCOPE_PLACEHOLDER = "__BF_PARENT_SCOPE__";
436
- // ../shared/src/dom-prop.ts
437
- var BOOLEAN_ATTRS = new Set([
438
- "checked",
439
- "disabled",
440
- "readonly",
441
- "selected",
442
- "required",
443
- "hidden",
444
- "autofocus",
445
- "autoplay",
446
- "controls",
447
- "loop",
448
- "muted",
449
- "open",
450
- "multiple",
451
- "novalidate",
452
- "formnovalidate"
453
- ]);
454
- var SVG_CAMEL_TO_KEBAB = {
455
- strokeWidth: "stroke-width",
456
- strokeLinecap: "stroke-linecap",
457
- strokeLinejoin: "stroke-linejoin",
458
- strokeDasharray: "stroke-dasharray",
459
- strokeDashoffset: "stroke-dashoffset",
460
- strokeMiterlimit: "stroke-miterlimit",
461
- strokeOpacity: "stroke-opacity",
462
- fillOpacity: "fill-opacity",
463
- fillRule: "fill-rule",
464
- stopColor: "stop-color",
465
- stopOpacity: "stop-opacity",
466
- textAnchor: "text-anchor",
467
- dominantBaseline: "dominant-baseline",
468
- alignmentBaseline: "alignment-baseline",
469
- fontFamily: "font-family",
470
- fontSize: "font-size",
471
- fontWeight: "font-weight",
472
- fontStyle: "font-style",
473
- letterSpacing: "letter-spacing",
474
- wordSpacing: "word-spacing",
475
- pointerEvents: "pointer-events",
476
- vectorEffect: "vector-effect",
477
- colorInterpolation: "color-interpolation",
478
- clipPath: "clip-path",
479
- clipRule: "clip-rule",
480
- markerStart: "marker-start",
481
- markerMid: "marker-mid",
482
- markerEnd: "marker-end"
483
- };
484
- var SVG_XML_CAMEL_ATTRS = new Set([
485
- "allowReorder",
486
- "attributeName",
487
- "attributeType",
488
- "autoReverse",
489
- "baseFrequency",
490
- "baseProfile",
491
- "calcMode",
492
- "clipPathUnits",
493
- "contentScriptType",
494
- "contentStyleType",
495
- "diffuseConstant",
496
- "edgeMode",
497
- "externalResourcesRequired",
498
- "filterRes",
499
- "filterUnits",
500
- "glyphRef",
501
- "gradientTransform",
502
- "gradientUnits",
503
- "kernelMatrix",
504
- "kernelUnitLength",
505
- "keyPoints",
506
- "keySplines",
507
- "keyTimes",
508
- "lengthAdjust",
509
- "limitingConeAngle",
510
- "markerHeight",
511
- "markerUnits",
512
- "markerWidth",
513
- "maskContentUnits",
514
- "maskUnits",
515
- "numOctaves",
516
- "pathLength",
517
- "patternContentUnits",
518
- "patternTransform",
519
- "patternUnits",
520
- "pointsAtX",
521
- "pointsAtY",
522
- "pointsAtZ",
523
- "preserveAlpha",
524
- "preserveAspectRatio",
525
- "primitiveUnits",
526
- "refX",
527
- "refY",
528
- "repeatCount",
529
- "repeatDur",
530
- "requiredExtensions",
531
- "requiredFeatures",
532
- "specularConstant",
533
- "specularExponent",
534
- "spreadMethod",
535
- "startOffset",
536
- "stdDeviation",
537
- "stitchTiles",
538
- "surfaceScale",
539
- "systemLanguage",
540
- "tableValues",
541
- "targetX",
542
- "targetY",
543
- "textLength",
544
- "viewBox",
545
- "viewTarget",
546
- "xChannelSelector",
547
- "yChannelSelector",
548
- "zoomAndPan"
549
- ]);
550
- function isEventProp(key) {
551
- return key.length > 2 && key[0] === "o" && key[1] === "n" && key[2] >= "A" && key[2] <= "Z";
552
- }
553
- function classifyDOMProp(key) {
554
- if (key === "children")
555
- return { kind: "skip", attrName: key };
556
- if (key === "ref")
557
- return { kind: "ref", attrName: key };
558
- if (key === "dangerouslySetInnerHTML")
559
- return { kind: "innerHTML", attrName: key };
560
- if (isEventProp(key))
561
- return { kind: "event", attrName: key };
562
- const attrName = toHTMLAttrNameRuntime(key);
563
- if (attrName === "style")
564
- return { kind: "style", attrName };
565
- if (attrName === "value")
566
- return { kind: "property", attrName };
567
- if (attrName === "checked")
568
- return { kind: "property", attrName };
569
- if (BOOLEAN_ATTRS.has(attrName.toLowerCase()))
570
- return { kind: "boolean", attrName };
571
- return { kind: "attr", attrName };
572
- }
573
- function toHTMLAttrNameRuntime(key) {
574
- if (key === "className")
575
- return "class";
576
- if (key === "htmlFor")
577
- return "for";
578
- const svgKebab = SVG_CAMEL_TO_KEBAB[key];
579
- if (svgKebab !== undefined)
580
- return svgKebab;
581
- if (SVG_XML_CAMEL_ATTRS.has(key))
582
- return key;
583
- if (key.startsWith("data") || key.startsWith("aria")) {
584
- return key.replace(/([A-Z])/g, "-$1").toLowerCase();
585
- }
586
- return key;
587
- }
588
626
  // src/context.ts
589
627
  function createContext(defaultValue) {
590
628
  return {
@@ -1159,6 +1197,55 @@ function flushHydration() {
1159
1197
  rafScheduled = false;
1160
1198
  walkAllInDocumentOrder();
1161
1199
  }
1200
+ function rehydrateScope(root) {
1201
+ if (typeof document === "undefined")
1202
+ return;
1203
+ hydrateElementScope(root);
1204
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT);
1205
+ while (walker.nextNode()) {
1206
+ const node = walker.currentNode;
1207
+ if (node.nodeType === Node.ELEMENT_NODE) {
1208
+ hydrateElementScope(node);
1209
+ } else if (node.nodeType === Node.COMMENT_NODE) {
1210
+ hydrateCommentScope(node);
1211
+ }
1212
+ }
1213
+ }
1214
+ function disposeScope(root) {
1215
+ if (typeof document === "undefined")
1216
+ return;
1217
+ disposeOneScope(root);
1218
+ clearChildScopeMark(root);
1219
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT);
1220
+ while (walker.nextNode()) {
1221
+ const node = walker.currentNode;
1222
+ if (node.nodeType === Node.ELEMENT_NODE) {
1223
+ disposeOneScope(node);
1224
+ clearChildScopeMark(node);
1225
+ } else if (node.nodeType === Node.COMMENT_NODE) {
1226
+ clearCommentScopeFlag(node);
1227
+ }
1228
+ }
1229
+ }
1230
+ function disposeOneScope(el) {
1231
+ const dispose = scopeDisposers.get(el);
1232
+ if (dispose) {
1233
+ scopeDisposers.delete(el);
1234
+ hydratedScopes.delete(el);
1235
+ dispose();
1236
+ }
1237
+ }
1238
+ function clearChildScopeMark(el) {
1239
+ if (el.hasAttribute(BF_HOST))
1240
+ hydratedScopes.delete(el);
1241
+ }
1242
+ function clearCommentScopeFlag(comment) {
1243
+ if (!comment.nodeValue?.startsWith(BF_SCOPE_COMMENT_PREFIX))
1244
+ return;
1245
+ const flagged = comment;
1246
+ if (flagged.__bfInitialized)
1247
+ flagged.__bfInitialized = false;
1248
+ }
1162
1249
  function walkAllInDocumentOrder() {
1163
1250
  if (typeof document === "undefined")
1164
1251
  return;
@@ -1186,10 +1273,14 @@ function parseProps(json, where) {
1186
1273
  return {};
1187
1274
  }
1188
1275
  }
1276
+ var scopeDisposers = new WeakMap;
1189
1277
  function runInit(scope, def, props) {
1190
1278
  const prevScope = setCurrentScope(scope);
1191
1279
  try {
1192
- def.init(scope, props);
1280
+ createRoot((dispose) => {
1281
+ scopeDisposers.set(scope, dispose);
1282
+ def.init(scope, props);
1283
+ });
1193
1284
  } finally {
1194
1285
  setCurrentScope(prevScope);
1195
1286
  }
@@ -2733,7 +2824,9 @@ function setupStreaming() {
2733
2824
  return;
2734
2825
  const w = window;
2735
2826
  w.__bf_swap = __bf_swap;
2736
- w.__bf_hydrate = rehydrateAll;
2827
+ w[BF_SEAM_HYDRATE] = rehydrateAll;
2828
+ w[BF_SEAM_HYDRATE_WITHIN] = rehydrateScope;
2829
+ w[BF_SEAM_DISPOSE_WITHIN] = disposeScope;
2737
2830
  }
2738
2831
  export {
2739
2832
  useContext,
@@ -2748,8 +2841,10 @@ export {
2748
2841
  setupStreaming,
2749
2842
  setProfilerSink,
2750
2843
  setCurrentScope,
2844
+ searchParams,
2751
2845
  renderChild,
2752
2846
  render,
2847
+ rehydrateScope,
2753
2848
  rehydrateAll,
2754
2849
  registerTemplate,
2755
2850
  registerComponent,
@@ -2786,6 +2881,7 @@ export {
2786
2881
  escapeText,
2787
2882
  escapeAttr,
2788
2883
  endTurn,
2884
+ disposeScope,
2789
2885
  cssEscape,
2790
2886
  createSignal,
2791
2887
  createRoot,
@@ -2804,6 +2900,7 @@ export {
2804
2900
  __bf_swap,
2805
2901
  __bfText,
2806
2902
  __bfSlot,
2903
+ __bfSetServerEnvReader,
2807
2904
  __bfReportOutput,
2808
2905
  $t,
2809
2906
  $c,
@@ -28,7 +28,11 @@ export declare function __bf_swap(id: string): void;
28
28
  * Makes `__bf_swap` available as `window.__bf_swap` so that inline
29
29
  * `<script>__bf_swap("a0")</script>` tags in streaming chunks can call it.
30
30
  *
31
- * Also exposes `window.__bf_hydrate` for manual re-hydration triggers.
31
+ * Also exposes re-hydration / disposal seams for an out-of-tree client
32
+ * router (`@barefootjs/router`):
33
+ * - `window.__bf_hydrate` — re-hydrate the whole document
34
+ * - `window.__bf_hydrate_within` — re-hydrate only a swapped subtree
35
+ * - `window.__bf_dispose_within` — dispose the islands in a subtree
32
36
  *
33
37
  * Call this once, early in the page (before any streaming chunks arrive).
34
38
  */
@@ -1 +1 @@
1
- {"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["../../src/runtime/streaming.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAmB1C;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAMrC"}
1
+ {"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["../../src/runtime/streaming.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAWH;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAmB1C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAUrC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/client",
3
- "version": "0.14.0",
3
+ "version": "0.15.1",
4
4
  "description": "BarefootJS client package: reactive primitives (SSR-safe) plus browser runtime under the `/runtime` subpath (compiler target)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -55,7 +55,7 @@
55
55
  "directory": "packages/client"
56
56
  },
57
57
  "dependencies": {
58
- "@barefootjs/shared": "0.14.0"
58
+ "@barefootjs/shared": "0.15.1"
59
59
  },
60
60
  "peerDependencies": {
61
61
  "@barefootjs/jsx": ">=0.2.0"
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Compiler built-in JSX tags: `<Async>` and `<Region>`.
3
+ *
4
+ * These are recognised by the BarefootJS compiler **structurally** — by
5
+ * their import from `@barefootjs/client` (`ir.metadata.imports`), never by
6
+ * a bare capitalized tag-name match — and are compiled away: `<Async>`
7
+ * lowers to a streaming boundary (e.g. Hono `<Suspense>`) and `<Region>`
8
+ * lowers to a `bf-region` page-lifecycle boundary (spec/router.md). No
9
+ * runtime value survives in the emitted output; the compiler also elides
10
+ * the import on emit so it never lingers as a phantom runtime import.
11
+ *
12
+ * The real exports here exist so authors can `import { Async, Region }`
13
+ * with full prop-checking and completion, the same way Solid imports
14
+ * `<Show>` / `<Suspense>` from `solid-js`. Importing them is what tells the
15
+ * compiler the tag is the built-in (and keeps a user's own `<Async>` /
16
+ * `<Region>` component from colliding with it).
17
+ *
18
+ * If one of these ever executes, the JSX was rendered outside the
19
+ * BarefootJS compiler pipeline — that's a bug. See
20
+ * piconic-ai/barefootjs#1915.
21
+ */
22
+
23
+ function compiledAway(name: string): never {
24
+ throw new Error(
25
+ `[barefootjs] <${name}> is a compiler built-in and is compiled away. ` +
26
+ `If you are seeing this at runtime, the JSX was rendered without going ` +
27
+ `through the BarefootJS compiler — please report a bug.`,
28
+ )
29
+ }
30
+
31
+ export interface AsyncProps {
32
+ /** UI rendered while the streamed children resolve. */
33
+ fallback: unknown
34
+ /** Content streamed in once resolved. */
35
+ children?: unknown
36
+ }
37
+
38
+ export interface RegionProps {
39
+ /** The page-lifecycle subtree the router disposes / re-hydrates on navigation. */
40
+ children?: unknown
41
+ }
42
+
43
+ /**
44
+ * Streaming async boundary. Lowered by the compiler to the adapter's
45
+ * streaming primitive (Hono `<Suspense>`); `fallback` is shown until the
46
+ * children resolve. Compiled away — never executes at runtime.
47
+ */
48
+ // Return type is `any` so the built-in satisfies every adapter's
49
+ // `JSX.Element` regardless of the active `jsxImportSource`.
50
+ export function Async(_props: AsyncProps): any {
51
+ return compiledAway('Async')
52
+ }
53
+
54
+ /**
55
+ * Page-lifecycle boundary (spec/router.md). Lowered by the compiler to a
56
+ * wrapper element carrying a deterministic `bf-region` marker the client
57
+ * router matches on. Compiled away — never executes at runtime.
58
+ */
59
+ // Return type is `any` so the built-in satisfies every adapter's
60
+ // `JSX.Element` regardless of the active `jsxImportSource`.
61
+ export function Region(_props: RegionProps): any {
62
+ return compiledAway('Region')
63
+ }
package/src/index.ts CHANGED
@@ -15,6 +15,12 @@ export {
15
15
  beginTurn,
16
16
  endTurn,
17
17
  __bfReportOutput,
18
+ // Request-scoped reactive environment signals (spec/router.md "The wedge").
19
+ // `searchParams` lives in the shared reactive module too, so this entry and
20
+ // the `/runtime` entry resolve to ONE signal instance. `createEnvSignal` stays
21
+ // internal; `__bfSetServerEnvReader` is the keyed adapter/host hook for SSR.
22
+ searchParams,
23
+ __bfSetServerEnvReader,
18
24
  type Reactive,
19
25
  type Signal,
20
26
  type Memo,
@@ -53,3 +59,13 @@ export {
53
59
  type PortalOptions,
54
60
  type Renderable,
55
61
  } from './shims.ts'
62
+
63
+ // Compiler built-ins (`<Async>` / `<Region>`) — recognised by their import
64
+ // here and compiled away. Importing them is what scopes the recognition; the
65
+ // compiler elides the import on emit. See ./builtins.ts and #1915.
66
+ export {
67
+ Async,
68
+ Region,
69
+ type AsyncProps,
70
+ type RegionProps,
71
+ } from './builtins.ts'