foldkit-primitives 0.9.0 → 0.10.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.
Files changed (59) hide show
  1. package/README.md +31 -1
  2. package/dist/device/index.d.mts +69 -36
  3. package/dist/device/index.d.mts.map +1 -1
  4. package/dist/device/index.mjs +34 -34
  5. package/dist/device/index.mjs.map +1 -1
  6. package/dist/dom/index.d.mts +68 -19
  7. package/dist/dom/index.d.mts.map +1 -1
  8. package/dist/dom/index.mjs +32 -25
  9. package/dist/dom/index.mjs.map +1 -1
  10. package/dist/{editable-text-BbsPOATY.d.mts → editable-text-Dvm-Fuqs.d.mts} +65 -3
  11. package/dist/editable-text-Dvm-Fuqs.d.mts.map +1 -0
  12. package/dist/events/index.d.mts +52 -31
  13. package/dist/events/index.d.mts.map +1 -1
  14. package/dist/events/index.mjs +40 -28
  15. package/dist/events/index.mjs.map +1 -1
  16. package/dist/{follow-tab-stop-BDxyoUPQ.mjs → follow-tab-stop-Ci1tqAIW.mjs} +63 -61
  17. package/dist/follow-tab-stop-Ci1tqAIW.mjs.map +1 -0
  18. package/dist/{index-Cppf-lBx.d.mts → index-CmmxqSEi.d.mts} +34 -15
  19. package/dist/index-CmmxqSEi.d.mts.map +1 -0
  20. package/dist/index.d.mts +3 -3
  21. package/dist/index.mjs +3 -3
  22. package/dist/{input-modality-m6v7__Xs.mjs → input-modality-BXD383jg.mjs} +9 -9
  23. package/dist/input-modality-BXD383jg.mjs.map +1 -0
  24. package/dist/{input-modality-DGOhAknO.d.mts → input-modality-BY-bSrEc.d.mts} +9 -2
  25. package/dist/input-modality-BY-bSrEc.d.mts.map +1 -0
  26. package/dist/interaction/index.d.mts +118 -118
  27. package/dist/interaction/index.d.mts.map +1 -1
  28. package/dist/interaction/index.mjs +3 -3
  29. package/dist/interaction/index.mjs.map +1 -1
  30. package/dist/media/index.d.mts +24 -3
  31. package/dist/media/index.d.mts.map +1 -1
  32. package/dist/media/index.mjs +23 -13
  33. package/dist/media/index.mjs.map +1 -1
  34. package/dist/motion/index.d.mts +1 -1
  35. package/dist/motion/index.mjs +1 -2
  36. package/dist/{motion-DGGBZ0wt.mjs → motion-DmFDppRn.mjs} +20 -20
  37. package/dist/{motion-DGGBZ0wt.mjs.map → motion-DmFDppRn.mjs.map} +1 -1
  38. package/dist/net/index.d.mts +63 -25
  39. package/dist/net/index.d.mts.map +1 -1
  40. package/dist/net/index.mjs +31 -31
  41. package/dist/net/index.mjs.map +1 -1
  42. package/dist/observers/index.d.mts +25 -0
  43. package/dist/observers/index.d.mts.map +1 -1
  44. package/dist/observers/index.mjs +22 -22
  45. package/dist/observers/index.mjs.map +1 -1
  46. package/dist/state/index.d.mts +98 -44
  47. package/dist/state/index.d.mts.map +1 -1
  48. package/dist/state/index.mjs +39 -39
  49. package/dist/state/index.mjs.map +1 -1
  50. package/dist/time/index.d.mts +35 -5
  51. package/dist/time/index.d.mts.map +1 -1
  52. package/dist/time/index.mjs +20 -20
  53. package/dist/time/index.mjs.map +1 -1
  54. package/package.json +14 -14
  55. package/dist/editable-text-BbsPOATY.d.mts.map +0 -1
  56. package/dist/follow-tab-stop-BDxyoUPQ.mjs.map +0 -1
  57. package/dist/index-Cppf-lBx.d.mts.map +0 -1
  58. package/dist/input-modality-DGOhAknO.d.mts.map +0 -1
  59. package/dist/input-modality-m6v7__Xs.mjs.map +0 -1
@@ -15,6 +15,17 @@ export type HistoryModel<Value> = {
15
15
  readonly future: ReadonlyArray<Value>;
16
16
  readonly group: string | null;
17
17
  };
18
+ declare const start: <Value>(present: Value) => HistoryModel<Value>;
19
+ declare const push: <Value>(model: HistoryModel<Value>, value: Value, options: {
20
+ readonly capacity: number;
21
+ readonly group?: string | null | undefined;
22
+ }) => HistoryModel<Value>;
23
+ declare const undo: <Value>(model: HistoryModel<Value>) => HistoryModel<Value>;
24
+ declare const redo: <Value>(model: HistoryModel<Value>) => HistoryModel<Value>;
25
+ declare const goTo: <Value>(model: HistoryModel<Value>, step: number) => HistoryModel<Value>;
26
+ declare const clear: <Value>(model: HistoryModel<Value>) => HistoryModel<Value>;
27
+ declare const close: <Value>(model: HistoryModel<Value>) => HistoryModel<Value>;
28
+ declare const revert: <Value>(model: HistoryModel<Value>, group: string) => HistoryModel<Value>;
18
29
  /** Whether Undo would move: the past is non-empty. */
19
30
  export declare const canUndo: <Value>(model: HistoryModel<Value>) => boolean;
20
31
  /** Whether Redo would move: the future is non-empty. */
@@ -22,26 +33,23 @@ export declare const canRedo: <Value>(model: HistoryModel<Value>) => boolean;
22
33
  /** The steps of a history as pure functions of its Model. */
23
34
  export declare const History: {
24
35
  /** A history whose present is `value`, with nothing to undo. */
25
- start: <Value>(present: Value) => HistoryModel<Value>;
36
+ start: typeof start;
26
37
  /** Records `value` as the present; the same `group` as the last push joins its step. */
27
- push: <Value>(model: HistoryModel<Value>, value: Value, options: {
28
- readonly capacity: number;
29
- readonly group?: string | null | undefined;
30
- }) => HistoryModel<Value>;
38
+ push: typeof push;
31
39
  /** One step back, or the Model as it was when there is none. */
32
- undo: <Value>(model: HistoryModel<Value>) => HistoryModel<Value>;
40
+ undo: typeof undo;
33
41
  /** One step forward, or the Model as it was when there is none. */
34
- redo: <Value>(model: HistoryModel<Value>) => HistoryModel<Value>;
42
+ redo: typeof redo;
35
43
  /**
36
44
  * The value at `step` made the present, counting every kept value from the
37
45
  * oldest (0), so the present is at `past.length`: what a click on a step's
38
46
  * thumbnail does. The Model as it was for the present or a step not kept.
39
47
  */
40
- goTo: <Value>(model: HistoryModel<Value>, step: number) => HistoryModel<Value>;
48
+ goTo: typeof goTo;
41
49
  /** Nothing to undo or redo, the present kept. */
42
- clear: <Value>(model: HistoryModel<Value>) => HistoryModel<Value>;
50
+ clear: typeof clear;
43
51
  /** The next push starts a step of its own, whatever its group: a group ends here. */
44
- close: <Value>(model: HistoryModel<Value>) => HistoryModel<Value>;
52
+ close: typeof close;
45
53
  /**
46
54
  * The step `group` is making taken back, and not redoable: what a cancelled
47
55
  * edit, or one that ended where it began, leaves. The Model as it was when
@@ -50,10 +58,23 @@ export declare const History: {
50
58
  * with a capacity of 0 nothing was kept, so the present stays and only the
51
59
  * group ends.
52
60
  */
53
- revert: <Value>(model: HistoryModel<Value>, group: string) => HistoryModel<Value>;
54
- canUndo: <Value>(model: HistoryModel<Value>) => boolean;
55
- canRedo: <Value>(model: HistoryModel<Value>) => boolean;
61
+ revert: typeof revert;
62
+ canUndo: typeof canUndo;
63
+ canRedo: typeof canRedo;
56
64
  };
65
+ /**
66
+ * Undo/redo as a bundle factory: the past, present, and future of one value
67
+ * live in the Model, so every step replays. Pushing records, even an unchanged
68
+ * value; skipping duplicates is the application's policy, not the stack's.
69
+ *
70
+ * A push may name a `group`. Consecutive pushes of the same group are one step:
71
+ * the present moves and nothing new is recorded, so typing a word undoes as a
72
+ * whole. Grouping needs no clock; the application names what belongs together.
73
+ *
74
+ * The steps are also pure functions (`History.push`, `undo`, `redo`, `goTo`, `clear`),
75
+ * for a parent that records an edit in the same transition that makes it
76
+ * rather than dispatching a Message to a placed bundle.
77
+ */
57
78
  export declare const history: <const Name extends string, Value>(config: {
58
79
  readonly name: Name;
59
80
  readonly value: Schema.Codec<Value, unknown>;
@@ -61,28 +82,28 @@ export declare const history: <const Name extends string, Value>(config: {
61
82
  }) => Bundle.Bundle<Name, {
62
83
  readonly initial: Value;
63
84
  }, HistoryModel<Value>, {
85
+ readonly _tag: "Clear";
86
+ } | {
87
+ readonly _tag: "GoTo";
88
+ readonly step: number;
89
+ } | {
64
90
  readonly _tag: "Push";
65
91
  readonly value: Value;
66
92
  readonly group?: string | undefined;
67
- } | {
68
- readonly _tag: "Undo";
69
93
  } | {
70
94
  readonly _tag: "Redo";
71
95
  } | {
72
- readonly _tag: "GoTo";
73
- readonly step: number;
74
- } | {
75
- readonly _tag: "Clear";
96
+ readonly _tag: "Undo";
76
97
  }, never, never, never, void, {}, {}> & {
77
98
  Message: import("foldkit/message").MessageUnion<{
78
99
  readonly Push: {
79
- readonly value: Schema.Codec<Value, unknown, never, never>;
80
- readonly group: Schema.optional<Schema.String>;
100
+ value: Schema.Codec<Value, unknown, never, never>;
101
+ group: Schema.optional<Schema.String>;
81
102
  };
82
103
  readonly Undo: {};
83
104
  readonly Redo: {};
84
105
  readonly GoTo: {
85
- readonly step: Schema.Number;
106
+ step: Schema.Number;
86
107
  };
87
108
  readonly Clear: {};
88
109
  }>;
@@ -95,10 +116,16 @@ export declare const LocaleModel: Schema.Struct<{
95
116
  export type LocaleModel = typeof LocaleModel.Type;
96
117
  export declare const LocaleMessage: import("foldkit/message").MessageUnion<{
97
118
  readonly SetLocale: {
98
- readonly locale: Schema.String;
119
+ locale: Schema.String;
99
120
  };
100
121
  }>;
101
122
  export type LocaleMessage = typeof LocaleMessage.Type;
123
+ /**
124
+ * Locale as a bundle: the current locale string in the Model. Starts from
125
+ * `navigator.language` where available, falling back to the configured
126
+ * default; changes arrive as Messages. No subscriptions: language changes
127
+ * take effect on reload.
128
+ */
102
129
  export declare const Locale: Bundle.Bundle<"Locale", {
103
130
  readonly default: string;
104
131
  }, {
@@ -117,15 +144,15 @@ export declare const PaginationModel: Schema.Struct<{
117
144
  export type PaginationModel = typeof PaginationModel.Type;
118
145
  export declare const PaginationMessage: import("foldkit/message").MessageUnion<{
119
146
  readonly GoToPage: {
120
- readonly page: Schema.Number;
147
+ page: Schema.Number;
121
148
  };
122
149
  readonly NextPage: {};
123
150
  readonly PrevPage: {};
124
151
  readonly SetPerPage: {
125
- readonly perPage: Schema.Number;
152
+ perPage: Schema.Number;
126
153
  };
127
154
  readonly SetTotal: {
128
- readonly total: Schema.NullOr<Schema.Number>;
155
+ total: Schema.NullOr<Schema.Number>;
129
156
  };
130
157
  }>;
131
158
  export type PaginationMessage = typeof PaginationMessage.Type;
@@ -133,6 +160,11 @@ export type PaginationMessage = typeof PaginationMessage.Type;
133
160
  export declare const pageCount: (model: PaginationModel) => number | null;
134
161
  /** The offset of the first item on the page, for a slice or a query. */
135
162
  export declare const offset: (model: PaginationModel) => number;
163
+ /**
164
+ * Pagination as a bundle: the page, page size, and total live in the Model,
165
+ * so page changes replay and every transition clamps into range. Pure logic,
166
+ * no streams: data loading stays the application's job.
167
+ */
136
168
  export declare const Pagination: Bundle.Bundle<"Pagination", {
137
169
  readonly perPage: number;
138
170
  readonly total?: number | null | undefined;
@@ -172,41 +204,47 @@ export declare const SelectionSetModel: Schema.Struct<{
172
204
  export type SelectionSetModel = typeof SelectionSetModel.Type;
173
205
  export declare const SelectionSetMessage: import("foldkit/message").MessageUnion<{
174
206
  readonly Select: {
175
- readonly id: Schema.String;
207
+ id: Schema.String;
176
208
  };
177
209
  readonly Deselect: {
178
- readonly id: Schema.String;
210
+ id: Schema.String;
179
211
  };
180
212
  readonly Toggle: {
181
- readonly id: Schema.String;
213
+ id: Schema.String;
182
214
  };
183
215
  readonly ReplaceAll: {
184
- readonly ids: Schema.$Array<Schema.String>;
216
+ ids: Schema.$Array<Schema.String>;
185
217
  };
186
218
  readonly Clear: {};
187
219
  }>;
188
220
  export type SelectionSetMessage = typeof SelectionSetMessage.Type;
189
221
  /** Whether the id is currently selected. */
190
222
  export declare const isSelected: (model: SelectionSetModel, id: string) => boolean;
223
+ /**
224
+ * A selection set as a bundle: the selected ids in the Model, changed one at
225
+ * a time or replaced whole. Order follows first selection; toggling moves a
226
+ * reselected id to the end. Pure logic, no streams.
227
+ */
191
228
  export declare const SelectionSet: Bundle.Bundle<"SelectionSet", void, {
192
229
  readonly selected: readonly string[];
193
230
  }, {
194
231
  readonly _tag: "Clear";
195
232
  } | {
196
- readonly _tag: "Select";
233
+ readonly _tag: "Deselect";
197
234
  readonly id: string;
198
235
  } | {
199
- readonly _tag: "Deselect";
236
+ readonly _tag: "ReplaceAll";
237
+ readonly ids: readonly string[];
238
+ } | {
239
+ readonly _tag: "Select";
200
240
  readonly id: string;
201
241
  } | {
202
242
  readonly _tag: "Toggle";
203
243
  readonly id: string;
204
- } | {
205
- readonly _tag: "ReplaceAll";
206
- readonly ids: readonly string[];
207
244
  }, never, never, never, void, {}, {}>;
208
245
  //#endregion
209
246
  //#region src/state/virtual.d.ts
247
+ /** The rows to draw: a half-open range of indexes. */
210
248
  export interface VirtualWindow {
211
249
  /** First visible row index, inclusive. */
212
250
  readonly start: number;
@@ -246,21 +284,21 @@ export declare const VirtualModel: Schema.Struct<{
246
284
  export type VirtualModel = typeof VirtualModel.Type;
247
285
  export declare const VirtualMessage: import("foldkit/message").MessageUnion<{
248
286
  readonly Scrolled: {
249
- readonly top: Schema.Number;
287
+ top: Schema.Number;
250
288
  };
251
289
  readonly Measured: {
252
- readonly key: Schema.String;
253
- readonly height: Schema.Number;
290
+ key: Schema.String;
291
+ height: Schema.Number;
254
292
  };
255
293
  /** Drops heights for keys no longer listed: the bundle never sees the key
256
294
  order, so the application tells it what left. */
257
295
  readonly Prune: {
258
- readonly keys: Schema.$Array<Schema.String>;
296
+ keys: Schema.$Array<Schema.String>;
259
297
  };
260
298
  /** Fires when scrolling has been silent for `settleMs`: only the latest
261
299
  generation counts, so a fling's intermediate timers emit nothing. */
262
300
  readonly Settled: {
263
- readonly generation: Schema.Number;
301
+ generation: Schema.Number;
264
302
  };
265
303
  }>;
266
304
  export type VirtualMessage = typeof VirtualMessage.Type;
@@ -286,6 +324,20 @@ export declare const distanceToEnd: (model: VirtualModel, keys: ReadonlyArray<st
286
324
  * to zero.
287
325
  */
288
326
  export declare const isAtEnd: (model: VirtualModel, keys: ReadonlyArray<string>, viewportHeight: number, threshold?: number) => boolean;
327
+ /**
328
+ * Windowing math for virtualized lists as pure functions: which rows to
329
+ * render, how tall the scrollable area is, and where each row starts. Row
330
+ * heights come from measured values with a per-row estimate fallback, so
331
+ * unmeasured rows still occupy space and measuring later only corrects.
332
+ * Keys are strings; heights are non-negative, and non-finite measurements
333
+ * fall back to the estimate instead of poisoning the sums.
334
+ *
335
+ * The `Virtual` bundle below owns the scroll position and the measured
336
+ * heights; `Viewport` reports container scrolls and `MeasureRow` reports
337
+ * row heights, both as Mounts on the elements they observe. The application
338
+ * renders `windowFor(...)` rows with its own views (keyed, so `each`
339
+ * placements keep identity) inside a spacer of `totalHeight(...)`.
340
+ */
289
341
  export declare const Virtual: Bundle.Bundle<"Virtual", {
290
342
  readonly estimatedHeight: number;
291
343
  readonly overscan: number;
@@ -312,14 +364,14 @@ export declare const Virtual: Bundle.Bundle<"Virtual", {
312
364
  readonly key: string;
313
365
  readonly height: number;
314
366
  } | {
315
- readonly _tag: "Settled";
316
- readonly generation: number;
367
+ readonly _tag: "Prune";
368
+ readonly keys: readonly string[];
317
369
  } | {
318
370
  readonly _tag: "Scrolled";
319
371
  readonly top: number;
320
372
  } | {
321
- readonly _tag: "Prune";
322
- readonly keys: readonly string[];
373
+ readonly _tag: "Settled";
374
+ readonly generation: number;
323
375
  }, never, never, never, void, {}, {}>;
324
376
  export declare const ViewportScrolled: Schema.TaggedStruct<"ViewportScrolled", {
325
377
  readonly top: Schema.Number;
@@ -362,6 +414,7 @@ export declare const stickyHeader: (sections: ReadonlyArray<{
362
414
  readonly key: string;
363
415
  readonly index: number;
364
416
  }>, startIndex: number) => string | null;
417
+ /** Where `masonry` puts one item: its column and its box, in pixels. */
365
418
  export interface MasonryPlacement {
366
419
  readonly key: string;
367
420
  readonly column: number;
@@ -387,4 +440,5 @@ export declare const masonry: (keys: ReadonlyArray<string>, heights: Readonly<Re
387
440
  readonly totalHeight: number;
388
441
  };
389
442
  //#endregion
443
+ export {};
390
444
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/state/history.ts","../../src/state/locale.ts","../../src/state/pagination.ts","../../src/state/range.ts","../../src/state/selection.ts","../../src/state/virtual.ts"],"mappings":";;;;qBAiBa,eAAgB,OAAO,OAAO,OAAO,MAAM,oBAAe,OAAA;;;;;;;YAQ3D,aAAa;WACd,MAAM,cAAc;WACpB,SAAS;WACT,QAAQ,cAAc;WACtB;;;qBA2FE,UAAW,OAAO,OAAO,aAAa;;qBAGtC,UAAW,OAAO,OAAO,aAAa;;qBAGtC;;EA9FE,QAAA,OAAK,SAAW,UAAQ,aAAa;;EAetC,OAAA,OAAK,OACV,aAAa,QAAM,OACnB,OAAK;aACQ;aAA2B;QAC9C,aAAa;;EAcF,OAAA,OAAK,OAAS,aAAa,WAAS,aAAa;;EAWjD,OAAA,OAAK,OAAS,aAAa,WAAS,aAAa;;;;;;EAWjD,OAAA,OAAK,OAAS,aAAa,QAAM,iBAAiB,aAAa;;EAY9D,QAAA,OAAK,OAAS,aAAa,WAAS,aAAa;;EAKjD,QAAA,OAAK,OAAS,aAAa,WAAS,aAAa;;;;;;;;;EAGhD,SAAA,OAAK,OAAS,aAAa,QAAM,kBAAkB,aAAa;EAaxD,UAAA,OAAK,OAAS,aAAa;EAG3B,UAAA,OAAK,OAAS,aAAa;;qBAmCtC,gBAAiB,qBAAqB,OAAO;WAC/C,MAAM;WACN,OAAO,OAAO,MAAM;WACpB;MACV,OAAA,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBCxJY,aAAW,OAAA;;;YACZ,qBAAqB,YAAY;qBAEhC,yCAAa;;qBAAb,OAAA;;;YACD,uBAAuB,cAAc;qBAEpC,QAAM,OAAA;;;;;;;;;;qBCNN,iBAAe,OAAA;;;;;YAKhB,yBAAyB,gBAAgB;qBAExC,6CAAiB;;;;;;;;;;;;;YAOlB,2BAA2B,kBAAkB;;qBAU5C,YAAa,OAAO;;qBAIpB,SAAU,OAAO;qBAEjB,YAAU,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBCjCV,QAAS,eAAe,aAAa,kBAAW;;;qBCGhD,mBAAiB,OAAA;;;YAClB,2BAA2B,kBAAkB;qBAE5C,+CAAmB;;;;;;;;;;;;;;;YAOpB,6BAA6B,oBAAoB;;qBAMhD,aAAc,OAAO,mBAAmB;qBAGxC,cAAY,OAAA;;;;;;;;;;;;;;;;;;;iBCTR;;WAEN;;WAEA;;;iBAIM;WACN;WACA;WACA;WACA;;;qBAmEE,cACX,MAAM,uBACN,SAAS,SAAS,yBAClB,QAAQ;;qBAcG,YACX,eACA,MAAM,uBACN,SAAS,SAAS,yBAClB,QAAQ;;;;;;;;qBAUG,eACX,MAAM,uBACN,SAAS,SAAS,yBAClB,QAAQ,eACR,mBACA,wBACA,qBACC;qBAmBU,cAAY,OAAA;;;;;;;;;;;YAWb,sBAAsB,aAAa;qBAElC,0CAAc;;;;;;;;;;;;;;;;;;;YAUf,wBAAwB,eAAe;;;;;;;qBAetC,YACX,OAAO,cACP,MAAM,uBACN,2BACC;WAA2B;;;;;;;qBAkBjB,gBACX,OAAO,cACP,MAAM,uBACN;;;;;;;qBAYW,UACX,OAAO,cACP,MAAM,uBACN,wBACA;qBAYW,SAAO,OAAA;WAKU;WACP;WACL;WACS;WACF;WACD;WACQ;WACF,iBAAA,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAyG1B,kBAAgB,OAAA;;;YACjB,0BAA0B,iBAAiB;;;;;;qBAO1C,UAAQ,MAAA;;;;qBAeR,aAAW,OAAA;;;;YAIZ,qBAAqB,YAAY;;;;;;qBAShC,YAAU,MAAA;;;;;;;;;;;;;;qBAgCV,eACX,UAAU;WAAyB;WAAsB;IACzD;iBAae;WACN;WACA;WACA;WACA;WACA;WACA;;;;;;;;;qBAUE,UACX,MAAM,uBACN,SAAS,SAAS,yBAClB;WACW;WACA;WACA;WACA;;WAEC,YAAY,cAAc;WAA4B"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/state/history.ts","../../src/state/locale.ts","../../src/state/pagination.ts","../../src/state/range.ts","../../src/state/selection.ts","../../src/state/virtual.ts"],"mappings":"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"}
@@ -4,19 +4,6 @@ import * as Mount from "foldkit/mount";
4
4
  import { defineMessageUnion } from "foldkit/message";
5
5
  import { Bundle } from "foldkit-bundle";
6
6
  //#region src/state/history.ts
7
- /**
8
- * Undo/redo as a bundle factory: the past, present, and future of one value
9
- * live in the Model, so every step replays. Pushing records, even an unchanged
10
- * value; skipping duplicates is the application's policy, not the stack's.
11
- *
12
- * A push may name a `group`. Consecutive pushes of the same group are one step:
13
- * the present moves and nothing new is recorded, so typing a word undoes as a
14
- * whole. Grouping needs no clock; the application names what belongs together.
15
- *
16
- * The steps are also pure functions (`History.push`, `undo`, `redo`, `goTo`, `clear`),
17
- * for a parent that records an edit in the same transition that makes it
18
- * rather than dispatching a Message to a placed bundle.
19
- */
20
7
  const HistoryModel = (value) => Schema.Struct({
21
8
  past: Schema.Array(value),
22
9
  present: value,
@@ -134,6 +121,19 @@ const History = {
134
121
  canUndo,
135
122
  canRedo
136
123
  };
124
+ /**
125
+ * Undo/redo as a bundle factory: the past, present, and future of one value
126
+ * live in the Model, so every step replays. Pushing records, even an unchanged
127
+ * value; skipping duplicates is the application's policy, not the stack's.
128
+ *
129
+ * A push may name a `group`. Consecutive pushes of the same group are one step:
130
+ * the present moves and nothing new is recorded, so typing a word undoes as a
131
+ * whole. Grouping needs no clock; the application names what belongs together.
132
+ *
133
+ * The steps are also pure functions (`History.push`, `undo`, `redo`, `goTo`, `clear`),
134
+ * for a parent that records an edit in the same transition that makes it
135
+ * rather than dispatching a Message to a placed bundle.
136
+ */
137
137
  const history = (config) => {
138
138
  const capacity = checkCapacity(config.name, config.capacity ?? 100);
139
139
  const Model = HistoryModel(config.value);
@@ -166,14 +166,14 @@ const history = (config) => {
166
166
  };
167
167
  //#endregion
168
168
  //#region src/state/locale.ts
169
+ const LocaleModel = Schema.Struct({ locale: Schema.String });
170
+ const LocaleMessage = defineMessageUnion({ SetLocale: { locale: Schema.String } });
169
171
  /**
170
172
  * Locale as a bundle: the current locale string in the Model. Starts from
171
173
  * `navigator.language` where available, falling back to the configured
172
174
  * default; changes arrive as Messages. No subscriptions: language changes
173
175
  * take effect on reload.
174
176
  */
175
- const LocaleModel = Schema.Struct({ locale: Schema.String });
176
- const LocaleMessage = defineMessageUnion({ SetLocale: { locale: Schema.String } });
177
177
  const Locale = Bundle.make("Locale", {
178
178
  Model: LocaleModel,
179
179
  Message: LocaleMessage,
@@ -186,11 +186,6 @@ const Locale = Bundle.make("Locale", {
186
186
  });
187
187
  //#endregion
188
188
  //#region src/state/pagination.ts
189
- /**
190
- * Pagination as a bundle: the page, page size, and total live in the Model,
191
- * so page changes replay and every transition clamps into range. Pure logic,
192
- * no streams: data loading stays the application's job.
193
- */
194
189
  const PaginationModel = Schema.Struct({
195
190
  page: Schema.Number,
196
191
  perPage: Schema.Number,
@@ -213,6 +208,11 @@ const clampPage = (page, perPage, total) => {
213
208
  const pageCount = (model) => model.total === null ? null : Math.max(1, Math.ceil(model.total / model.perPage));
214
209
  /** The offset of the first item on the page, for a slice or a query. */
215
210
  const offset = (model) => (model.page - 1) * model.perPage;
211
+ /**
212
+ * Pagination as a bundle: the page, page size, and total live in the Model,
213
+ * so page changes replay and every transition clamps into range. Pure logic,
214
+ * no streams: data loading stays the application's job.
215
+ */
216
216
  const Pagination = Bundle.make("Pagination", {
217
217
  Model: PaginationModel,
218
218
  Message: PaginationMessage,
@@ -268,11 +268,6 @@ const range = (start, end, step = 1) => {
268
268
  };
269
269
  //#endregion
270
270
  //#region src/state/selection.ts
271
- /**
272
- * A selection set as a bundle: the selected ids in the Model, changed one at
273
- * a time or replaced whole. Order follows first selection; toggling moves a
274
- * reselected id to the end. Pure logic, no streams.
275
- */
276
271
  const SelectionSetModel = Schema.Struct({ selected: Schema.Array(Schema.String) });
277
272
  const SelectionSetMessage = defineMessageUnion({
278
273
  Select: { id: Schema.String },
@@ -284,6 +279,11 @@ const SelectionSetMessage = defineMessageUnion({
284
279
  const without = (selected, id) => selected.filter((other) => other !== id);
285
280
  /** Whether the id is currently selected. */
286
281
  const isSelected = (model, id) => model.selected.includes(id);
282
+ /**
283
+ * A selection set as a bundle: the selected ids in the Model, changed one at
284
+ * a time or replaced whole. Order follows first selection; toggling moves a
285
+ * reselected id to the end. Pure logic, no streams.
286
+ */
287
287
  const SelectionSet = Bundle.make("SelectionSet", {
288
288
  Model: SelectionSetModel,
289
289
  Message: SelectionSetMessage,
@@ -301,20 +301,6 @@ const SelectionSet = Bundle.make("SelectionSet", {
301
301
  });
302
302
  //#endregion
303
303
  //#region src/state/virtual.ts
304
- /**
305
- * Windowing math for virtualized lists as pure functions: which rows to
306
- * render, how tall the scrollable area is, and where each row starts. Row
307
- * heights come from measured values with a per-row estimate fallback, so
308
- * unmeasured rows still occupy space and measuring later only corrects.
309
- * Keys are strings; heights are non-negative, and non-finite measurements
310
- * fall back to the estimate instead of poisoning the sums.
311
- *
312
- * The `Virtual` bundle below owns the scroll position and the measured
313
- * heights; `Viewport` reports container scrolls and `MeasureRow` reports
314
- * row heights, both as Mounts on the elements they observe. The application
315
- * renders `windowFor(...)` rows with its own views (keyed, so `each`
316
- * placements keep identity) inside a spacer of `totalHeight(...)`.
317
- */
318
304
  const saneHeight = (height, estimatedHeight) => Number.isFinite(height) && height >= 0 ? height : estimatedHeight;
319
305
  const heightAt = (index, heights, keys, layout) => {
320
306
  const key = keys[index];
@@ -442,6 +428,20 @@ const isAtEnd = (model, keys, viewportHeight, threshold = 0) => {
442
428
  };
443
429
  const saneTop = (top) => Number.isFinite(top) ? Math.max(0, top) : null;
444
430
  const saneMeasured = (height) => Number.isFinite(height) && height >= 0 ? height : null;
431
+ /**
432
+ * Windowing math for virtualized lists as pure functions: which rows to
433
+ * render, how tall the scrollable area is, and where each row starts. Row
434
+ * heights come from measured values with a per-row estimate fallback, so
435
+ * unmeasured rows still occupy space and measuring later only corrects.
436
+ * Keys are strings; heights are non-negative, and non-finite measurements
437
+ * fall back to the estimate instead of poisoning the sums.
438
+ *
439
+ * The `Virtual` bundle below owns the scroll position and the measured
440
+ * heights; `Viewport` reports container scrolls and `MeasureRow` reports
441
+ * row heights, both as Mounts on the elements they observe. The application
442
+ * renders `windowFor(...)` rows with its own views (keyed, so `each`
443
+ * placements keep identity) inside a spacer of `totalHeight(...)`.
444
+ */
445
445
  const Virtual = Bundle.make("Virtual", {
446
446
  Model: VirtualModel,
447
447
  Message: VirtualMessage,