@barefootjs/client 0.18.5 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/build.d.ts CHANGED
@@ -34,14 +34,21 @@ export interface CSRBuildOptions {
34
34
  * How the CLI produces `barefoot.js`. Defaults to `'treeshake'`, which
35
35
  * bundles only the runtime exports this project's compiled client JS
36
36
  * actually imports (plus the always-kept public mount API). Set to
37
+ * `'treeshake-exact'` to drop the always-kept set too — smaller output,
38
+ * but any hand-written page script the CLI never compiles (an inline
39
+ * `<script type="module">` calling `render`/`hydrate`/etc. directly) must
40
+ * list those names in `runtimeKeep` or they're silently dropped. Set to
37
41
  * `'full'` to copy the entire prebuilt runtime bundle verbatim, matching
38
42
  * pre-tree-shaking behavior.
39
43
  */
40
- runtimeBundle?: 'treeshake' | 'full';
44
+ runtimeBundle?: 'treeshake' | 'treeshake-exact' | 'full';
41
45
  /**
42
46
  * Extra `@barefootjs/client*` export names to force-keep in `barefoot.js`
43
- * under `runtimeBundle: 'treeshake'` — for names only ever referenced
44
- * from hand-written page scripts the CLI never compiles.
47
+ * under `runtimeBundle: 'treeshake'` or `'treeshake-exact'` — for names
48
+ * only ever referenced from hand-written page scripts the CLI never
49
+ * compiles. Required (not just useful) under `'treeshake-exact'`, which
50
+ * drops the always-kept public mount API those scripts would otherwise
51
+ * fall back on.
45
52
  */
46
53
  runtimeKeep?: string[];
47
54
  }
@@ -64,7 +71,7 @@ export declare function createConfig(options?: CSRBuildOptions): {
64
71
  bundleEntries: BundleEntry[] | undefined;
65
72
  outputLayout: OutputLayout | undefined;
66
73
  postBuild: ((ctx: PostBuildContext) => Promise<void> | void) | undefined;
67
- runtimeBundle: "full" | "treeshake" | undefined;
74
+ runtimeBundle: "full" | "treeshake" | "treeshake-exact" | undefined;
68
75
  runtimeKeep: string[] | undefined;
69
76
  };
70
77
  export { CSRAdapter } from './csr-adapter.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,eAAe,EAChB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEzD,MAAM,WAAW,eAAe;IAC9B,yDAAyD;IACzD,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,+BAA+B;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,sCAAsC;IACtC,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,wEAAwE;IACxE,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAC3D,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACxC,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,+DAA+D;IAC/D,aAAa,CAAC,EAAE,WAAW,EAAE,CAAA;IAC7B;;;;OAIG;IACH,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,oFAAoF;IACpF,cAAc,CAAC,EAAE,iBAAiB,CAAA;IAClC;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,WAAW,GAAG,MAAM,CAAA;IACpC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,eAAoB;;;;;;;;;;;;sBArCtC,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;;;EA2D5D;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,eAAe,EAChB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEzD,MAAM,WAAW,eAAe;IAC9B,yDAAyD;IACzD,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,+BAA+B;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,sCAAsC;IACtC,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,wEAAwE;IACxE,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAC3D,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACxC,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,+DAA+D;IAC/D,aAAa,CAAC,EAAE,WAAW,EAAE,CAAA;IAC7B;;;;OAIG;IACH,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,oFAAoF;IACpF,cAAc,CAAC,EAAE,iBAAiB,CAAA;IAClC;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,WAAW,GAAG,iBAAiB,GAAG,MAAM,CAAA;IACxD;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,eAAoB;;;;;;;;;;;;sBA5CtC,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;;;EAkE5D;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { createSignal, createEffect, createDisposableEffect, createMemo, createRoot, onCleanup, onMount, untrack, batch, setProfilerSink, beginTurn, endTurn, __bfReportOutput, createSearchParams, type SearchParamsInit, __bfSetServerEnvReader, type Reactive, type Signal, type Memo, type CleanupFn, type EffectFn, type ProfilerEventSink, type SubscriberKind, } from '@barefootjs/client/reactive';
1
+ export { createSignal, createEffect, createDisposableEffect, createMemo, createSelector, createRoot, onCleanup, onMount, untrack, batch, setProfilerSink, beginTurn, endTurn, __bfReportOutput, createSearchParams, type SearchParamsInit, __bfSetServerEnvReader, type Reactive, type Signal, type Memo, type CleanupFn, type EffectFn, type ProfilerEventSink, type SubscriberKind, } from '@barefootjs/client/reactive';
2
2
  export { createRecordingSink, type ProfilerEvent, type ProfilerEventType, type RecordingSink, } from './profiler-events.ts';
3
3
  export { splitProps } from './split-props.ts';
4
4
  export { __slot, type SlotMarker } from './slot.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,sBAAsB,EACtB,UAAU,EACV,UAAU,EACV,SAAS,EACT,OAAO,EACP,OAAO,EACP,KAAK,EACL,eAAe,EACf,SAAS,EACT,OAAO,EACP,gBAAgB,EAMhB,kBAAkB,EAClB,KAAK,gBAAgB,EACrB,sBAAsB,EACtB,KAAK,QAAQ,EACb,KAAK,MAAM,EACX,KAAK,IAAI,EACT,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,iBAAiB,EACtB,KAAK,cAAc,GACpB,MAAM,6BAA6B,CAAA;AAEpC,OAAO,EACL,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,aAAa,GACnB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAE,MAAM,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAA;AAEnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,OAAO,EAAE,SAAS,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEnF,OAAO,EAAE,aAAa,EAAE,KAAK,OAAO,EAAE,MAAM,cAAc,CAAA;AAE1D,OAAO,EACL,UAAU,EACV,cAAc,EACd,YAAY,EACZ,WAAW,EACX,eAAe,EACf,wBAAwB,EACxB,KAAK,MAAM,EACX,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,UAAU,GAChB,MAAM,YAAY,CAAA;AAKnB,OAAO,EACL,KAAK,EACL,MAAM,EACN,KAAK,UAAU,EACf,KAAK,WAAW,GACjB,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,sBAAsB,EACtB,UAAU,EACV,cAAc,EACd,UAAU,EACV,SAAS,EACT,OAAO,EACP,OAAO,EACP,KAAK,EACL,eAAe,EACf,SAAS,EACT,OAAO,EACP,gBAAgB,EAMhB,kBAAkB,EAClB,KAAK,gBAAgB,EACrB,sBAAsB,EACtB,KAAK,QAAQ,EACb,KAAK,MAAM,EACX,KAAK,IAAI,EACT,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,iBAAiB,EACtB,KAAK,cAAc,GACpB,MAAM,6BAA6B,CAAA;AAEpC,OAAO,EACL,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,aAAa,GACnB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAE,MAAM,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAA;AAEnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,OAAO,EAAE,SAAS,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEnF,OAAO,EAAE,aAAa,EAAE,KAAK,OAAO,EAAE,MAAM,cAAc,CAAA;AAE1D,OAAO,EACL,UAAU,EACV,cAAc,EACd,YAAY,EACZ,WAAW,EACX,eAAe,EACf,wBAAwB,EACxB,KAAK,MAAM,EACX,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,UAAU,GAChB,MAAM,YAAY,CAAA;AAKnB,OAAO,EACL,KAAK,EACL,MAAM,EACN,KAAK,UAAU,EACf,KAAK,WAAW,GACjB,MAAM,eAAe,CAAA"}
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ import {
4
4
  createEffect,
5
5
  createDisposableEffect,
6
6
  createMemo,
7
+ createSelector,
7
8
  createRoot,
8
9
  onCleanup,
9
10
  onMount,
@@ -218,6 +219,7 @@ export {
218
219
  findSiblingSlot,
219
220
  endTurn,
220
221
  createSignal,
222
+ createSelector,
221
223
  createSearchParams,
222
224
  createRoot,
223
225
  createRecordingSink,
@@ -227,6 +227,27 @@ export declare function onMount(fn: () => void): void;
227
227
  * doubled() // 10
228
228
  */
229
229
  export declare function createMemo<T>(fn: () => T, __bfId?: string): Memo<T>;
230
+ /**
231
+ * O(changed) selection primitive (SolidJS-compatible `createSelector`).
232
+ *
233
+ * `class={selected() === row.id ? 'danger' : ''}` subscribes every row to the
234
+ * one `selected` signal — O(rows) effect runs per selection change. The
235
+ * selector inverts the fan-out: each row's effect subscribes to its OWN key,
236
+ * and an internal effect tracking `source()` dispatches only the keys whose
237
+ * `fn(key, value)` result actually flipped — two effect runs per selection
238
+ * change (deselected row + selected row) regardless of list size.
239
+ *
240
+ * The returned accessor is `Reactive<>`-branded, so the compiler's
241
+ * type-based reactivity analysis recognises `isSelected(row.id)` as a
242
+ * reactive expression exactly like a signal/memo read.
243
+ *
244
+ * @example
245
+ * const [selected, setSelected] = createSignal<number>(0)
246
+ * const isSelected = createSelector(selected)
247
+ * // inside a loop body:
248
+ * // <tr class={isSelected(row.id) ? 'danger' : ''}>
249
+ */
250
+ export declare function createSelector<T, U = T>(source: () => T, fn?: (key: U, value: T) => boolean): Reactive<(key: U) => boolean>;
230
251
  /**
231
252
  * Adapter/host hook: teach `@barefootjs/client` how to read the current
232
253
  * request's environment values during SSR. The reader receives an env key
@@ -1 +1 @@
1
- {"version":3,"file":"reactive.d.ts","sourceRoot":"","sources":["../src/reactive.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;GAIG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAA;CAAE,CAAA;AAE3D,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI;IACtB,yEAAyE;IACzE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjB,uDAAuD;IACvD,CAAC,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI;CAC1C,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,IAAI,CAAA;AAClC,MAAM,MAAM,QAAQ,GAAG,MAAM,IAAI,GAAG,SAAS,CAAA;AAC7C,MAAM,MAAM,IAAI,CAAC,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAA;AAavC,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAA;AAEvD;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,sFAAsF;IACtF,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IACnD,mEAAmE;IACnE,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1D,gFAAgF;IAChF,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7D,iDAAiD;IACjD,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAAA;IAC9D,2CAA2C;IAC3C,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IACvC,+DAA+D;IAC/D,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1D;;;;;;;;;;;;OAYG;IACH,YAAY,CAAC,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IAC3D,kDAAkD;IAClD,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IACzC,oEAAoE;IACpE,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,2CAA2C;IAC3C,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC;;;;OAIG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAChD,iDAAiD;IACjD,OAAO,IAAI,IAAI,CAAA;CAChB;AAiBD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,GAAG,IAAI,CAEpE;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAE/D;AAED,iEAAiE;AACjE,wBAAgB,OAAO,IAAI,IAAI,CAE9B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAIvD;AA8DD;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAmF3E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,GAAE,cAAyB,GAAG,IAAI,CA0BrG;AA+JD;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CA+B/D;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,IAAI,CA8BhF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,SAAS,GAAG,IAAI,CAS7C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAQzC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAWvC;AAaD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAE5C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAwBnE;AAmCD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC,GAAG,IAAI,GACnD,IAAI,CAEN;AAsFD;;4DAE4D;AAC5D,MAAM,MAAM,gBAAgB,GACxB,MAAM,GACN,eAAe,GACf,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC,CAAA;AAgE9C,wBAAgB,kBAAkB,IAAI,SAAS;IAC7C,QAAQ,CAAC,MAAM,eAAe,CAAC;IAC/B,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI;CACjC,CAEA"}
1
+ {"version":3,"file":"reactive.d.ts","sourceRoot":"","sources":["../src/reactive.ts"],"names":[],"mappings":"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"}
package/dist/reactive.js CHANGED
@@ -395,6 +395,51 @@ function createMemo(fn, __bfId) {
395
395
  }, id, "memo");
396
396
  return value;
397
397
  }
398
+ function createSelector(source, fn = (key, value) => key === value) {
399
+ const subs = new Map;
400
+ let value;
401
+ createEffect(() => {
402
+ const newValue = source();
403
+ const oldValue = value;
404
+ value = newValue;
405
+ let toRun = null;
406
+ for (const [key, keySubs] of subs) {
407
+ if (fn(key, newValue) !== fn(key, oldValue)) {
408
+ if (BatchDepth > 0) {
409
+ for (const effect of keySubs)
410
+ PendingEffects.add(effect);
411
+ } else {
412
+ if (!toRun)
413
+ toRun = new Set;
414
+ for (const effect of keySubs)
415
+ toRun.add(effect);
416
+ }
417
+ }
418
+ }
419
+ if (toRun) {
420
+ for (const effect of toRun)
421
+ runEffect(effect);
422
+ }
423
+ });
424
+ const selector = (key) => {
425
+ const listener = Listener;
426
+ if (listener) {
427
+ let keySubs = subs.get(key);
428
+ if (!keySubs) {
429
+ keySubs = new Set;
430
+ subs.set(key, keySubs);
431
+ }
432
+ keySubs.add(listener);
433
+ onCleanup(() => {
434
+ keySubs.delete(listener);
435
+ if (keySubs.size === 0)
436
+ subs.delete(key);
437
+ });
438
+ }
439
+ return fn(key, value);
440
+ };
441
+ return selector;
442
+ }
398
443
  var serverEnvReader = null;
399
444
  function __bfSetServerEnvReader(reader) {
400
445
  serverEnvReader = reader;
@@ -473,6 +518,7 @@ export {
473
518
  onCleanup,
474
519
  endTurn,
475
520
  createSignal,
521
+ createSelector,
476
522
  createSearchParams,
477
523
  createRoot,
478
524
  createMemo,
@@ -1,4 +1,4 @@
1
- export { createSignal, createEffect, createDisposableEffect, createMemo, createRoot, onCleanup, onMount, untrack, batch, setProfilerSink, beginTurn, endTurn, __bfReportOutput, createSearchParams, type SearchParamsInit, __bfSetServerEnvReader, type Reactive, type Signal, type Memo, type CleanupFn, type EffectFn, type ProfilerEventSink, type SubscriberKind, } from '@barefootjs/client/reactive';
1
+ export { createSignal, createEffect, createDisposableEffect, createMemo, createSelector, createRoot, onCleanup, onMount, untrack, batch, setProfilerSink, beginTurn, endTurn, __bfReportOutput, createSearchParams, type SearchParamsInit, __bfSetServerEnvReader, type Reactive, type Signal, type Memo, type CleanupFn, type EffectFn, type ProfilerEventSink, type SubscriberKind, } from '@barefootjs/client/reactive';
2
2
  export { createRecordingSink, type ProfilerEvent, type ProfilerEventType, type RecordingSink, } from '../profiler-events.ts';
3
3
  export { splitProps } from '../split-props.ts';
4
4
  export { __slot, type SlotMarker } from '../slot.ts';
@@ -16,7 +16,7 @@ export { createComponent, renderChild, getPropsUpdateFn, getComponentProps, pars
16
16
  export { applyRestAttrs } from './apply-rest-attrs.ts';
17
17
  export { spreadAttrs } from './spread-attrs.ts';
18
18
  export { styleToCss } from './style.ts';
19
- export { findScope, find, $, $c, $t, qsa, qsaChildScope, qsaChildScopes, cssEscape } from './query.ts';
19
+ export { findScope, find, $, $c, $t, qsa, qsaChildScope, qsaChildScopes, cssEscape, tAfter } from './query.ts';
20
20
  export { hydrate, rehydrateAll, rehydrateScope, disposeScope, flushHydration, getRegisteredDef } from './hydrate.ts';
21
21
  export { registerComponent, getComponentInit, initChild, upsertChild } from './registry.ts';
22
22
  export { insert, type BranchConfig, type BranchTemplateResult } from './insert.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,7 @@ import {
4
4
  createEffect as createEffect4,
5
5
  createDisposableEffect,
6
6
  createMemo,
7
+ createSelector,
7
8
  createRoot as createRoot3,
8
9
  onCleanup,
9
10
  onMount,
@@ -2707,6 +2708,7 @@ export {
2707
2708
  updateClientMarker,
2708
2709
  unwrap,
2709
2710
  untrack3 as untrack,
2711
+ textNodeAfterComment as tAfter,
2710
2712
  styleToCss,
2711
2713
  spreadAttrs,
2712
2714
  splitProps,
@@ -2756,6 +2758,7 @@ export {
2756
2758
  disposeScope,
2757
2759
  cssEscape,
2758
2760
  createSignal2 as createSignal,
2761
+ createSelector,
2759
2762
  createSearchParams,
2760
2763
  createRoot3 as createRoot,
2761
2764
  createRecordingSink,
@@ -83,4 +83,15 @@ export declare function $c(scope: Element | null, ...ids: string[]): (Element |
83
83
  * with early exit when all are found.
84
84
  */
85
85
  export declare function $t(scope: Element | null, ...ids: string[]): (Text | null)[];
86
+ /**
87
+ * Get or create the Text node immediately after a comment marker.
88
+ *
89
+ * Exported as `tAfter` for compiler-generated hoisted-loop codegen (#2143):
90
+ * when a loop row's text-marker position is known at compile time as a
91
+ * child-index path, the compiler resolves the `<!--bf:sN-->` Comment node
92
+ * directly (skipping `$t`'s TreeWalker scan) and calls this to get the
93
+ * same create-if-absent Text node `$t` would have returned.
94
+ */
95
+ export declare function textNodeAfterComment(comment: Comment): Text;
96
+ export { textNodeAfterComment as tAfter };
86
97
  //# sourceMappingURL=query.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/runtime/query.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,sFAAsF;AACtF,eAAO,MAAM,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAGJ,CAAA;AAqCnC;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,EACjC,OAAO,CAAC,EAAE,OAAO,GAChB,OAAO,GAAG,IAAI,CAoDhB;AA6HD;;;;;;;;;;GAUG;AACH,wBAAgB,IAAI,CAClB,KAAK,EAAE,OAAO,GAAG,IAAI,EACrB,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,OAAO,GACpB,OAAO,GAAG,IAAI,CA2BhB;AAuBD;;;;;;;GAOG;AACH,wBAAgB,GAAG,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CA0BxE;AA+CD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAU9E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CAO1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,CAAC,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAO7E;AAED;;;;;GAKG;AACH,wBAAgB,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAE9E;AA+FD;;;;;;;GAOG;AACH,wBAAgB,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAkC3E"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/runtime/query.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,sFAAsF;AACtF,eAAO,MAAM,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAGJ,CAAA;AAqCnC;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,EACjC,OAAO,CAAC,EAAE,OAAO,GAChB,OAAO,GAAG,IAAI,CAoDhB;AA6HD;;;;;;;;;;GAUG;AACH,wBAAgB,IAAI,CAClB,KAAK,EAAE,OAAO,GAAG,IAAI,EACrB,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,OAAO,GACpB,OAAO,GAAG,IAAI,CA2BhB;AAuBD;;;;;;;GAOG;AACH,wBAAgB,GAAG,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CA0BxE;AA+CD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAU9E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CAO1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,CAAC,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAO7E;AAED;;;;;GAKG;AACH,wBAAgB,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAE9E;AA+FD;;;;;;;GAOG;AACH,wBAAgB,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAkC3E;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAS3D;AAED,OAAO,EAAE,oBAAoB,IAAI,MAAM,EAAE,CAAA"}
@@ -554,6 +554,51 @@ function createMemo(fn, __bfId) {
554
554
  }, id, "memo");
555
555
  return value;
556
556
  }
557
+ function createSelector(source, fn = (key, value) => key === value) {
558
+ const subs = new Map;
559
+ let value;
560
+ createEffect(() => {
561
+ const newValue = source();
562
+ const oldValue = value;
563
+ value = newValue;
564
+ let toRun = null;
565
+ for (const [key, keySubs] of subs) {
566
+ if (fn(key, newValue) !== fn(key, oldValue)) {
567
+ if (BatchDepth > 0) {
568
+ for (const effect of keySubs)
569
+ PendingEffects.add(effect);
570
+ } else {
571
+ if (!toRun)
572
+ toRun = new Set;
573
+ for (const effect of keySubs)
574
+ toRun.add(effect);
575
+ }
576
+ }
577
+ }
578
+ if (toRun) {
579
+ for (const effect of toRun)
580
+ runEffect(effect);
581
+ }
582
+ });
583
+ const selector = (key) => {
584
+ const listener = Listener;
585
+ if (listener) {
586
+ let keySubs = subs.get(key);
587
+ if (!keySubs) {
588
+ keySubs = new Set;
589
+ subs.set(key, keySubs);
590
+ }
591
+ keySubs.add(listener);
592
+ onCleanup(() => {
593
+ keySubs.delete(listener);
594
+ if (keySubs.size === 0)
595
+ subs.delete(key);
596
+ });
597
+ }
598
+ return fn(key, value);
599
+ };
600
+ return selector;
601
+ }
557
602
  var serverEnvReader = null;
558
603
  function __bfSetServerEnvReader(reader) {
559
604
  serverEnvReader = reader;
@@ -3063,6 +3108,7 @@ export {
3063
3108
  updateClientMarker,
3064
3109
  unwrap,
3065
3110
  untrack,
3111
+ textNodeAfterComment as tAfter,
3066
3112
  styleToCss,
3067
3113
  spreadAttrs,
3068
3114
  splitProps,
@@ -3112,6 +3158,7 @@ export {
3112
3158
  disposeScope,
3113
3159
  cssEscape,
3114
3160
  createSignal,
3161
+ createSelector,
3115
3162
  createSearchParams,
3116
3163
  createRoot,
3117
3164
  createRecordingSink,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/client",
3
- "version": "0.18.5",
3
+ "version": "0.19.0",
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.18.5"
58
+ "@barefootjs/shared": "0.19.0"
59
59
  },
60
60
  "peerDependencies": {
61
61
  "@barefootjs/jsx": ">=0.2.0"
package/src/build.ts CHANGED
@@ -62,14 +62,21 @@ export interface CSRBuildOptions {
62
62
  * How the CLI produces `barefoot.js`. Defaults to `'treeshake'`, which
63
63
  * bundles only the runtime exports this project's compiled client JS
64
64
  * actually imports (plus the always-kept public mount API). Set to
65
+ * `'treeshake-exact'` to drop the always-kept set too — smaller output,
66
+ * but any hand-written page script the CLI never compiles (an inline
67
+ * `<script type="module">` calling `render`/`hydrate`/etc. directly) must
68
+ * list those names in `runtimeKeep` or they're silently dropped. Set to
65
69
  * `'full'` to copy the entire prebuilt runtime bundle verbatim, matching
66
70
  * pre-tree-shaking behavior.
67
71
  */
68
- runtimeBundle?: 'treeshake' | 'full'
72
+ runtimeBundle?: 'treeshake' | 'treeshake-exact' | 'full'
69
73
  /**
70
74
  * Extra `@barefootjs/client*` export names to force-keep in `barefoot.js`
71
- * under `runtimeBundle: 'treeshake'` — for names only ever referenced
72
- * from hand-written page scripts the CLI never compiles.
75
+ * under `runtimeBundle: 'treeshake'` or `'treeshake-exact'` — for names
76
+ * only ever referenced from hand-written page scripts the CLI never
77
+ * compiles. Required (not just useful) under `'treeshake-exact'`, which
78
+ * drops the always-kept public mount API those scripts would otherwise
79
+ * fall back on.
73
80
  */
74
81
  runtimeKeep?: string[]
75
82
  }
package/src/index.ts CHANGED
@@ -6,6 +6,7 @@ export {
6
6
  createEffect,
7
7
  createDisposableEffect,
8
8
  createMemo,
9
+ createSelector,
9
10
  createRoot,
10
11
  onCleanup,
11
12
  onMount,
package/src/reactive.ts CHANGED
@@ -734,6 +734,86 @@ export function createMemo<T>(fn: () => T, __bfId?: string): Memo<T> {
734
734
  return value
735
735
  }
736
736
 
737
+ /**
738
+ * O(changed) selection primitive (SolidJS-compatible `createSelector`).
739
+ *
740
+ * `class={selected() === row.id ? 'danger' : ''}` subscribes every row to the
741
+ * one `selected` signal — O(rows) effect runs per selection change. The
742
+ * selector inverts the fan-out: each row's effect subscribes to its OWN key,
743
+ * and an internal effect tracking `source()` dispatches only the keys whose
744
+ * `fn(key, value)` result actually flipped — two effect runs per selection
745
+ * change (deselected row + selected row) regardless of list size.
746
+ *
747
+ * The returned accessor is `Reactive<>`-branded, so the compiler's
748
+ * type-based reactivity analysis recognises `isSelected(row.id)` as a
749
+ * reactive expression exactly like a signal/memo read.
750
+ *
751
+ * @example
752
+ * const [selected, setSelected] = createSignal<number>(0)
753
+ * const isSelected = createSelector(selected)
754
+ * // inside a loop body:
755
+ * // <tr class={isSelected(row.id) ? 'danger' : ''}>
756
+ */
757
+ export function createSelector<T, U = T>(
758
+ source: () => T,
759
+ fn: (key: U, value: T) => boolean = ((key: U, value: T) => (key as unknown) === (value as unknown)) as (key: U, value: T) => boolean,
760
+ ): Reactive<(key: U) => boolean> {
761
+ // Per-key subscriber sets, created lazily on first tracked read of a key
762
+ // and self-pruned to empty via onCleanup — keys from replaced list items
763
+ // (e.g. clear + recreate cycles) don't accumulate.
764
+ const subs = new Map<U, Set<EffectContext>>()
765
+ let value: T
766
+
767
+ createEffect(() => {
768
+ const newValue = source()
769
+ const oldValue = value
770
+ value = newValue
771
+ // Collect-then-run: a re-running subscriber unsubscribes and immediately
772
+ // re-subscribes its key (onCleanup below), which deletes and re-inserts
773
+ // Map entries. A live Map iterator REVISITS a key deleted and re-added
774
+ // during iteration, so dispatching inline would re-flip the same key
775
+ // forever. Finish the sweep over `subs` first, then dispatch — this also
776
+ // gives the same fixed-at-dispatch-time semantics as a signal write's
777
+ // subscriber snapshot. The Set dedupes an effect subscribed to several
778
+ // flipped keys (possible with a custom `fn`), matching PendingEffects.
779
+ let toRun: Set<EffectContext> | null = null
780
+ for (const [key, keySubs] of subs) {
781
+ if (fn(key, newValue) !== fn(key, oldValue)) {
782
+ if (BatchDepth > 0) {
783
+ for (const effect of keySubs) PendingEffects.add(effect)
784
+ } else {
785
+ if (!toRun) toRun = new Set()
786
+ for (const effect of keySubs) toRun.add(effect)
787
+ }
788
+ }
789
+ }
790
+ if (toRun) {
791
+ for (const effect of toRun) runEffect(effect)
792
+ }
793
+ })
794
+
795
+ const selector = (key: U): boolean => {
796
+ const listener = Listener
797
+ if (listener) {
798
+ let keySubs = subs.get(key)
799
+ if (!keySubs) {
800
+ keySubs = new Set()
801
+ subs.set(key, keySubs)
802
+ }
803
+ keySubs.add(listener)
804
+ // Runs on both re-run and disposal of the subscribing effect; a re-run
805
+ // that still reads this key immediately re-subscribes.
806
+ onCleanup(() => {
807
+ keySubs.delete(listener)
808
+ if (keySubs.size === 0) subs.delete(key)
809
+ })
810
+ }
811
+ return fn(key, value)
812
+ }
813
+
814
+ return selector as Reactive<(key: U) => boolean>
815
+ }
816
+
737
817
 
738
818
  // ---------------------------------------------------------------------------
739
819
  // Request-scoped environment signals (router v0.5, spec/router.md "The wedge")
@@ -13,6 +13,7 @@ export {
13
13
  createEffect,
14
14
  createDisposableEffect,
15
15
  createMemo,
16
+ createSelector,
16
17
  createRoot,
17
18
  onCleanup,
18
19
  onMount,
@@ -101,7 +102,7 @@ export { spreadAttrs } from './spread-attrs.ts'
101
102
  export { styleToCss } from './style.ts'
102
103
 
103
104
  // Runtime helpers
104
- export { findScope, find, $, $c, $t, qsa, qsaChildScope, qsaChildScopes, cssEscape } from './query.ts'
105
+ export { findScope, find, $, $c, $t, qsa, qsaChildScope, qsaChildScopes, cssEscape, tAfter } from './query.ts'
105
106
  export { hydrate, rehydrateAll, rehydrateScope, disposeScope, flushHydration, getRegisteredDef } from './hydrate.ts'
106
107
  export { registerComponent, getComponentInit, initChild, upsertChild } from './registry.ts'
107
108
  export { insert, type BranchConfig, type BranchTemplateResult } from './insert.ts'
@@ -593,8 +593,14 @@ export function $t(scope: Element | null, ...ids: string[]): (Text | null)[] {
593
593
 
594
594
  /**
595
595
  * Get or create the Text node immediately after a comment marker.
596
+ *
597
+ * Exported as `tAfter` for compiler-generated hoisted-loop codegen (#2143):
598
+ * when a loop row's text-marker position is known at compile time as a
599
+ * child-index path, the compiler resolves the `<!--bf:sN-->` Comment node
600
+ * directly (skipping `$t`'s TreeWalker scan) and calls this to get the
601
+ * same create-if-absent Text node `$t` would have returned.
596
602
  */
597
- function textNodeAfterComment(comment: Comment): Text {
603
+ export function textNodeAfterComment(comment: Comment): Text {
598
604
  const next = comment.nextSibling
599
605
  if (next?.nodeType === Node.TEXT_NODE) {
600
606
  return next as Text
@@ -605,6 +611,8 @@ function textNodeAfterComment(comment: Comment): Text {
605
611
  return textNode
606
612
  }
607
613
 
614
+ export { textNodeAfterComment as tAfter }
615
+
608
616
  /**
609
617
  * Check if a comment node belongs to the given scope (not inside a nested child scope).
610
618
  */