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.
- package/README.md +31 -1
- package/dist/device/index.d.mts +69 -36
- package/dist/device/index.d.mts.map +1 -1
- package/dist/device/index.mjs +34 -34
- package/dist/device/index.mjs.map +1 -1
- package/dist/dom/index.d.mts +68 -19
- package/dist/dom/index.d.mts.map +1 -1
- package/dist/dom/index.mjs +32 -25
- package/dist/dom/index.mjs.map +1 -1
- package/dist/{editable-text-BbsPOATY.d.mts → editable-text-Dvm-Fuqs.d.mts} +65 -3
- package/dist/editable-text-Dvm-Fuqs.d.mts.map +1 -0
- package/dist/events/index.d.mts +52 -31
- package/dist/events/index.d.mts.map +1 -1
- package/dist/events/index.mjs +40 -28
- package/dist/events/index.mjs.map +1 -1
- package/dist/{follow-tab-stop-BDxyoUPQ.mjs → follow-tab-stop-Ci1tqAIW.mjs} +63 -61
- package/dist/follow-tab-stop-Ci1tqAIW.mjs.map +1 -0
- package/dist/{index-Cppf-lBx.d.mts → index-CmmxqSEi.d.mts} +34 -15
- package/dist/index-CmmxqSEi.d.mts.map +1 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +3 -3
- package/dist/{input-modality-m6v7__Xs.mjs → input-modality-BXD383jg.mjs} +9 -9
- package/dist/input-modality-BXD383jg.mjs.map +1 -0
- package/dist/{input-modality-DGOhAknO.d.mts → input-modality-BY-bSrEc.d.mts} +9 -2
- package/dist/input-modality-BY-bSrEc.d.mts.map +1 -0
- package/dist/interaction/index.d.mts +118 -118
- package/dist/interaction/index.d.mts.map +1 -1
- package/dist/interaction/index.mjs +3 -3
- package/dist/interaction/index.mjs.map +1 -1
- package/dist/media/index.d.mts +24 -3
- package/dist/media/index.d.mts.map +1 -1
- package/dist/media/index.mjs +23 -13
- package/dist/media/index.mjs.map +1 -1
- package/dist/motion/index.d.mts +1 -1
- package/dist/motion/index.mjs +1 -2
- package/dist/{motion-DGGBZ0wt.mjs → motion-DmFDppRn.mjs} +20 -20
- package/dist/{motion-DGGBZ0wt.mjs.map → motion-DmFDppRn.mjs.map} +1 -1
- package/dist/net/index.d.mts +63 -25
- package/dist/net/index.d.mts.map +1 -1
- package/dist/net/index.mjs +31 -31
- package/dist/net/index.mjs.map +1 -1
- package/dist/observers/index.d.mts +25 -0
- package/dist/observers/index.d.mts.map +1 -1
- package/dist/observers/index.mjs +22 -22
- package/dist/observers/index.mjs.map +1 -1
- package/dist/state/index.d.mts +98 -44
- package/dist/state/index.d.mts.map +1 -1
- package/dist/state/index.mjs +39 -39
- package/dist/state/index.mjs.map +1 -1
- package/dist/time/index.d.mts +35 -5
- package/dist/time/index.d.mts.map +1 -1
- package/dist/time/index.mjs +20 -20
- package/dist/time/index.mjs.map +1 -1
- package/package.json +14 -14
- package/dist/editable-text-BbsPOATY.d.mts.map +0 -1
- package/dist/follow-tab-stop-BDxyoUPQ.mjs.map +0 -1
- package/dist/index-Cppf-lBx.d.mts.map +0 -1
- package/dist/input-modality-DGOhAknO.d.mts.map +0 -1
- package/dist/input-modality-m6v7__Xs.mjs.map +0 -1
package/dist/state/index.d.mts
CHANGED
|
@@ -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:
|
|
36
|
+
start: typeof start;
|
|
26
37
|
/** Records `value` as the present; the same `group` as the last push joins its step. */
|
|
27
|
-
push:
|
|
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:
|
|
40
|
+
undo: typeof undo;
|
|
33
41
|
/** One step forward, or the Model as it was when there is none. */
|
|
34
|
-
redo:
|
|
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:
|
|
48
|
+
goTo: typeof goTo;
|
|
41
49
|
/** Nothing to undo or redo, the present kept. */
|
|
42
|
-
clear:
|
|
50
|
+
clear: typeof clear;
|
|
43
51
|
/** The next push starts a step of its own, whatever its group: a group ends here. */
|
|
44
|
-
close:
|
|
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:
|
|
54
|
-
canUndo:
|
|
55
|
-
canRedo:
|
|
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: "
|
|
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
|
-
|
|
80
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
147
|
+
page: Schema.Number;
|
|
121
148
|
};
|
|
122
149
|
readonly NextPage: {};
|
|
123
150
|
readonly PrevPage: {};
|
|
124
151
|
readonly SetPerPage: {
|
|
125
|
-
|
|
152
|
+
perPage: Schema.Number;
|
|
126
153
|
};
|
|
127
154
|
readonly SetTotal: {
|
|
128
|
-
|
|
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
|
-
|
|
207
|
+
id: Schema.String;
|
|
176
208
|
};
|
|
177
209
|
readonly Deselect: {
|
|
178
|
-
|
|
210
|
+
id: Schema.String;
|
|
179
211
|
};
|
|
180
212
|
readonly Toggle: {
|
|
181
|
-
|
|
213
|
+
id: Schema.String;
|
|
182
214
|
};
|
|
183
215
|
readonly ReplaceAll: {
|
|
184
|
-
|
|
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: "
|
|
233
|
+
readonly _tag: "Deselect";
|
|
197
234
|
readonly id: string;
|
|
198
235
|
} | {
|
|
199
|
-
readonly _tag: "
|
|
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
|
-
|
|
287
|
+
top: Schema.Number;
|
|
250
288
|
};
|
|
251
289
|
readonly Measured: {
|
|
252
|
-
|
|
253
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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: "
|
|
316
|
-
readonly
|
|
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: "
|
|
322
|
-
readonly
|
|
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":";;;;
|
|
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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"}
|
package/dist/state/index.mjs
CHANGED
|
@@ -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,
|