@typed/ui 1.0.0-beta.4 → 1.0.0-beta.5

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 (157) hide show
  1. package/README.md +53 -9
  2. package/dist/Alert.d.ts +78 -0
  3. package/dist/Alert.d.ts.map +1 -0
  4. package/dist/Alert.js +37 -0
  5. package/dist/Button.d.ts +144 -0
  6. package/dist/Button.d.ts.map +1 -0
  7. package/dist/Button.js +38 -0
  8. package/dist/Carousel.d.ts +547 -0
  9. package/dist/Carousel.d.ts.map +1 -0
  10. package/dist/Carousel.js +387 -0
  11. package/dist/Checkbox.d.ts +203 -0
  12. package/dist/Checkbox.d.ts.map +1 -0
  13. package/dist/Checkbox.js +140 -0
  14. package/dist/Collection.d.ts +254 -0
  15. package/dist/Collection.d.ts.map +1 -0
  16. package/dist/Collection.js +218 -0
  17. package/dist/Combobox.d.ts +516 -0
  18. package/dist/Combobox.d.ts.map +1 -0
  19. package/dist/Combobox.js +371 -0
  20. package/dist/Component.d.ts +127 -0
  21. package/dist/Component.d.ts.map +1 -0
  22. package/dist/Component.js +60 -0
  23. package/dist/Composite.d.ts +823 -0
  24. package/dist/Composite.d.ts.map +1 -0
  25. package/dist/Composite.js +615 -0
  26. package/dist/Dialog.d.ts +544 -0
  27. package/dist/Dialog.d.ts.map +1 -0
  28. package/dist/Dialog.js +355 -0
  29. package/dist/Disclosure.d.ts +219 -0
  30. package/dist/Disclosure.d.ts.map +1 -0
  31. package/dist/Disclosure.js +128 -0
  32. package/dist/Dom/Events.d.ts +122 -0
  33. package/dist/Dom/Events.d.ts.map +1 -0
  34. package/dist/Dom/Events.js +192 -0
  35. package/dist/Dom/Props.d.ts +161 -0
  36. package/dist/Dom/Props.d.ts.map +1 -0
  37. package/dist/Dom/Props.js +110 -0
  38. package/dist/Dom/Refs.d.ts +58 -0
  39. package/dist/Dom/Refs.d.ts.map +1 -0
  40. package/dist/Dom/Refs.js +61 -0
  41. package/dist/Dom/Render.d.ts +59 -0
  42. package/dist/Dom/Render.d.ts.map +1 -0
  43. package/dist/Dom/Render.js +71 -0
  44. package/dist/Dom/Types.d.ts +570 -0
  45. package/dist/Dom/Types.d.ts.map +1 -0
  46. package/dist/Dom/Types.js +1 -0
  47. package/dist/Dom/index.d.ts +20 -0
  48. package/dist/Dom/index.d.ts.map +1 -0
  49. package/dist/Dom/index.js +8 -0
  50. package/dist/Dom.d.ts +14 -0
  51. package/dist/Dom.d.ts.map +1 -0
  52. package/dist/Dom.js +13 -0
  53. package/dist/Focusable.d.ts +85 -0
  54. package/dist/Focusable.d.ts.map +1 -0
  55. package/dist/Focusable.js +35 -0
  56. package/dist/Form.d.ts +1695 -0
  57. package/dist/Form.d.ts.map +1 -0
  58. package/dist/Form.js +987 -0
  59. package/dist/Grid.d.ts +569 -0
  60. package/dist/Grid.d.ts.map +1 -0
  61. package/dist/Grid.js +379 -0
  62. package/dist/Group.d.ts +147 -0
  63. package/dist/Group.d.ts.map +1 -0
  64. package/dist/Group.js +63 -0
  65. package/dist/Heading.d.ts +86 -0
  66. package/dist/Heading.d.ts.map +1 -0
  67. package/dist/Heading.js +48 -0
  68. package/dist/Hovercard.d.ts +297 -0
  69. package/dist/Hovercard.d.ts.map +1 -0
  70. package/dist/Hovercard.js +188 -0
  71. package/dist/HttpRouter.d.ts +129 -6
  72. package/dist/HttpRouter.d.ts.map +1 -1
  73. package/dist/HttpRouter.js +196 -53
  74. package/dist/Link.d.ts +67 -28
  75. package/dist/Link.d.ts.map +1 -1
  76. package/dist/Link.js +91 -37
  77. package/dist/Listbox.d.ts +437 -0
  78. package/dist/Listbox.d.ts.map +1 -0
  79. package/dist/Listbox.js +316 -0
  80. package/dist/Menu.d.ts +972 -0
  81. package/dist/Menu.d.ts.map +1 -0
  82. package/dist/Menu.js +731 -0
  83. package/dist/Menubar.d.ts +367 -0
  84. package/dist/Menubar.d.ts.map +1 -0
  85. package/dist/Menubar.js +265 -0
  86. package/dist/Meter.d.ts +217 -0
  87. package/dist/Meter.d.ts.map +1 -0
  88. package/dist/Meter.js +94 -0
  89. package/dist/NativeDetails.d.ts +41 -0
  90. package/dist/NativeDetails.d.ts.map +1 -0
  91. package/dist/NativeDetails.js +40 -0
  92. package/dist/NativeDialog.d.ts +64 -0
  93. package/dist/NativeDialog.d.ts.map +1 -0
  94. package/dist/NativeDialog.js +50 -0
  95. package/dist/NativePopover.d.ts +41 -0
  96. package/dist/NativePopover.d.ts.map +1 -0
  97. package/dist/NativePopover.js +46 -0
  98. package/dist/Popover.d.ts +241 -0
  99. package/dist/Popover.d.ts.map +1 -0
  100. package/dist/Popover.js +141 -0
  101. package/dist/RadioGroup.d.ts +432 -0
  102. package/dist/RadioGroup.d.ts.map +1 -0
  103. package/dist/RadioGroup.js +291 -0
  104. package/dist/Role.d.ts +64 -0
  105. package/dist/Role.d.ts.map +1 -0
  106. package/dist/Role.js +27 -0
  107. package/dist/Select.d.ts +529 -0
  108. package/dist/Select.d.ts.map +1 -0
  109. package/dist/Select.js +407 -0
  110. package/dist/Separator.d.ts +54 -0
  111. package/dist/Separator.d.ts.map +1 -0
  112. package/dist/Separator.js +26 -0
  113. package/dist/Slider.d.ts +188 -0
  114. package/dist/Slider.d.ts.map +1 -0
  115. package/dist/Slider.js +96 -0
  116. package/dist/SpinButton.d.ts +188 -0
  117. package/dist/SpinButton.d.ts.map +1 -0
  118. package/dist/SpinButton.js +96 -0
  119. package/dist/Storybook.d.ts +76 -0
  120. package/dist/Storybook.d.ts.map +1 -0
  121. package/dist/Storybook.js +102 -0
  122. package/dist/Switch.d.ts +187 -0
  123. package/dist/Switch.d.ts.map +1 -0
  124. package/dist/Switch.js +116 -0
  125. package/dist/Tab.d.ts +26 -0
  126. package/dist/Tab.d.ts.map +1 -0
  127. package/dist/Tab.js +25 -0
  128. package/dist/Tabs.d.ts +591 -0
  129. package/dist/Tabs.d.ts.map +1 -0
  130. package/dist/Tabs.js +346 -0
  131. package/dist/Toolbar.d.ts +366 -0
  132. package/dist/Toolbar.d.ts.map +1 -0
  133. package/dist/Toolbar.js +245 -0
  134. package/dist/Tooltip.d.ts +296 -0
  135. package/dist/Tooltip.d.ts.map +1 -0
  136. package/dist/Tooltip.js +172 -0
  137. package/dist/Tree.d.ts +591 -0
  138. package/dist/Tree.d.ts.map +1 -0
  139. package/dist/Tree.js +434 -0
  140. package/dist/TreeGrid.d.ts +645 -0
  141. package/dist/TreeGrid.d.ts.map +1 -0
  142. package/dist/TreeGrid.js +420 -0
  143. package/dist/VisuallyHidden.d.ts +54 -0
  144. package/dist/VisuallyHidden.d.ts.map +1 -0
  145. package/dist/VisuallyHidden.js +27 -0
  146. package/dist/WindowSplitter.d.ts +376 -0
  147. package/dist/WindowSplitter.d.ts.map +1 -0
  148. package/dist/WindowSplitter.js +222 -0
  149. package/dist/index.d.ts +49 -0
  150. package/dist/index.d.ts.map +1 -1
  151. package/dist/index.js +49 -0
  152. package/package.json +45 -18
  153. package/src/HttpRouter.test.ts +0 -256
  154. package/src/HttpRouter.ts +0 -165
  155. package/src/Link.test.ts +0 -84
  156. package/src/Link.ts +0 -107
  157. package/src/index.ts +0 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Composite.d.ts","sourceRoot":"","sources":["../src/Composite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,615 @@
1
+ /**
2
+ * Composite contains the reusable policy behind roving tabindex and virtual focus. Its pure
3
+ * helpers define orientation, RTL, wrapping, disabled-item, typeahead, and DOM-order rules; Effect
4
+ * helpers perform focus and scrolling only when run.
5
+ *
6
+ * @remarks
7
+ * The module keeps policy, state transitions, and DOM rendering separable so applications can use
8
+ * the state and pure operations without mounting UI, or supply custom hosts without replacing native
9
+ * events and browser-owned focus.
10
+ *
11
+ * @since 1.0.0
12
+ * @category modules
13
+ * @packageDocumentation
14
+ */
15
+ import * as Effect from "effect/Effect";
16
+ import * as Schema from "effect/Schema";
17
+ import { RefSubject } from "@typed/fx";
18
+ import * as Collection from "./Collection.js";
19
+ /**
20
+ * Effect Schema used by makeState to encode, decode, and hydrate Composite state.
21
+ *
22
+ * @remarks
23
+ * ## Why
24
+ *
25
+ * A public schema makes hydration and serialized state use the same runtime validation as direct
26
+ * construction.
27
+ *
28
+ * ## Ownership and lifetime
29
+ *
30
+ * This declaration is data or schema metadata and acquires no resources.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * import * as Schema from "effect/Schema";
35
+ * import * as Composite from "@typed/ui/Composite";
36
+ *
37
+ * const decodeState = Schema.decodeUnknownEffect(Composite.StateSchema);
38
+ * ```
39
+ * @since 1.0.0
40
+ * @category schemas
41
+ */
42
+ export const StateSchema = Schema.Struct({
43
+ activeId: Schema.NullOr(Schema.String),
44
+ orientation: Schema.Literals(["horizontal", "vertical", "both"]),
45
+ loop: Schema.Boolean,
46
+ rtl: Schema.Boolean,
47
+ virtualFocus: Schema.Boolean,
48
+ });
49
+ /**
50
+ * Creates hydrated Composite state. activeId defaults to null, orientation to horizontal, loop to
51
+ * true, RTL and virtual focus to false.
52
+ *
53
+ * @remarks
54
+ * ## Why
55
+ *
56
+ * State and collection ownership can be composed and tested independently from any renderer.
57
+ *
58
+ * ## Ownership and lifetime
59
+ *
60
+ * The returned Effect creates the RefSubject when run. That state is renderer-independent;
61
+ * collection registrations belong to the separate Scope that runs register or ref, not to state
62
+ * creation.
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * import * as Effect from "effect/Effect";
67
+ * import * as Collection from "@typed/ui/Collection";
68
+ * import * as Composite from "@typed/ui/Composite";
69
+ *
70
+ * const program = Effect.scoped(
71
+ * Effect.gen(function* () {
72
+ * const state = yield* Composite.makeState({});
73
+ * const collection = yield* Collection.makeState<string>();
74
+ * return { state: yield* state, collection: yield* collection };
75
+ * }),
76
+ * );
77
+ * ```
78
+ * @since 1.0.0
79
+ * @category constructors
80
+ */
81
+ export function makeState(initial = {}) {
82
+ return RefSubject.hydrate(StateSchema, {
83
+ activeId: initial.activeId ?? null,
84
+ orientation: initial.orientation ?? "horizontal",
85
+ loop: initial.loop ?? true,
86
+ rtl: initial.rtl ?? false,
87
+ virtualFocus: initial.virtualFocus ?? false,
88
+ });
89
+ }
90
+ /**
91
+ * Computes the next active id and updates state; collection and state failures/services are
92
+ * preserved in the returned Effect.
93
+ *
94
+ * @remarks
95
+ * ## Why
96
+ *
97
+ * The operation exposes Composite's transition directly so callers can compose it in Effect
98
+ * programs and native event handlers.
99
+ *
100
+ * ## Ownership and lifetime
101
+ *
102
+ * The returned Effect performs the update or DOM side effect only when run, preserves the declared
103
+ * error and service channels, and retains no resources after completion.
104
+ *
105
+ * ## Example
106
+ *
107
+ * Import with `import { move } from "@typed/ui/Composite";` Extend the [Composite.makeState
108
+ * runnable setup](/reference/%40typed%2Fui%2FComposite%23makeState). Inside the linked Effect
109
+ * program invoke `yield* move({ state, collection }, "next")`, then read state to observe the next
110
+ * enabled registered id selected under the current loop policy.
111
+ * @since 1.0.0
112
+ * @category combinators
113
+ */
114
+ export function move(options, direction) {
115
+ return Effect.gen(function* () {
116
+ const current = yield* options.state;
117
+ const activeId = moveActiveId(yield* options.collection, current, direction, options.includeDisabled);
118
+ return yield* RefSubject.update(options.state, (state) => ({ ...state, activeId }));
119
+ });
120
+ }
121
+ /**
122
+ * Derives 0 only for the active item under roving focus; virtual-focus items always receive -1.
123
+ *
124
+ * @remarks
125
+ * ## Why
126
+ *
127
+ * The operation exposes Composite's transition directly so callers can compose it in Effect
128
+ * programs and native event handlers.
129
+ *
130
+ * ## Ownership and lifetime
131
+ *
132
+ * Creating the Computed value acquires nothing eagerly. The Scope that subscribes to it owns
133
+ * observation of the source RefSubject.
134
+ *
135
+ * ## Example
136
+ *
137
+ * Import with `import { tabIndex } from "@typed/ui/Composite";` Extend the [Composite.makeState
138
+ * runnable setup](/reference/%40typed%2Fui%2FComposite%23makeState). Inside the linked Effect
139
+ * program read `const value = yield* tabIndex(state, "item-2")`; it is `0` only while that item
140
+ * owns roving focus and is `-1` under virtual focus.
141
+ * @since 1.0.0
142
+ * @category combinators
143
+ */
144
+ export function tabIndex(state, id) {
145
+ return RefSubject.map(state, (current) => current.virtualFocus ? -1 : current.activeId === id ? 0 : -1);
146
+ }
147
+ /**
148
+ * Derives activeId only under virtual focus, otherwise undefined.
149
+ *
150
+ * @remarks
151
+ * ## Why
152
+ *
153
+ * The operation exposes Composite's transition directly so callers can compose it in Effect
154
+ * programs and native event handlers.
155
+ *
156
+ * ## Ownership and lifetime
157
+ *
158
+ * Creating the Computed value acquires nothing eagerly. The Scope that subscribes to it owns
159
+ * observation of the source RefSubject.
160
+ *
161
+ * ## Example
162
+ *
163
+ * Import with `import { activeDescendant } from "@typed/ui/Composite";` Extend the
164
+ * [Composite.makeState runnable setup](/reference/%40typed%2Fui%2FComposite%23makeState). Inside
165
+ * the linked Effect program read `const id = yield* activeDescendant(state)`; it is the active id
166
+ * only under virtual focus and otherwise `undefined`.
167
+ * @since 1.0.0
168
+ * @category combinators
169
+ */
170
+ export function activeDescendant(state) {
171
+ return RefSubject.map(state, (current) => current.virtualFocus && current.activeId ? current.activeId : undefined);
172
+ }
173
+ /**
174
+ * Derives 0 when the root owns focus and -1 once a roving-focus item is active.
175
+ *
176
+ * @remarks
177
+ * ## Why
178
+ *
179
+ * The operation exposes Composite's transition directly so callers can compose it in Effect
180
+ * programs and native event handlers.
181
+ *
182
+ * ## Ownership and lifetime
183
+ *
184
+ * Creating the Computed value acquires nothing eagerly. The Scope that subscribes to it owns
185
+ * observation of the source RefSubject.
186
+ *
187
+ * ## Example
188
+ *
189
+ * Import with `import { rootTabIndex } from "@typed/ui/Composite";` Extend the [Composite.makeState
190
+ * runnable setup](/reference/%40typed%2Fui%2FComposite%23makeState). Inside the linked Effect
191
+ * program read `const value = yield* rootTabIndex(state)`; it is `0` while the root owns focus and
192
+ * `-1` after a roving-focus item becomes active.
193
+ * @since 1.0.0
194
+ * @category combinators
195
+ */
196
+ export function rootTabIndex(state) {
197
+ return RefSubject.map(state, (current) => current.virtualFocus || current.activeId === null ? 0 : -1);
198
+ }
199
+ /**
200
+ * Maps Home/End and orientation-aware Arrow keys to movement, reversing horizontal arrows for RTL.
201
+ *
202
+ * @remarks
203
+ * ## Why
204
+ *
205
+ * Separating this deterministic policy from event wiring lets applications test it directly and
206
+ * reuse it in custom composites.
207
+ *
208
+ * ## Ownership and lifetime
209
+ *
210
+ * This is a synchronous calculation. It acquires no resources and does not mutate the input array,
211
+ * state, event, or DOM.
212
+ *
213
+ * @example
214
+ * ```ts
215
+ * import * as Composite from "@typed/ui/Composite";
216
+ *
217
+ * const direction = Composite.keyMove({ key: "ArrowLeft" }, { orientation: "horizontal", rtl: true });
218
+ * ```
219
+ * @since 1.0.0
220
+ * @category combinators
221
+ */
222
+ export function keyMove(event, options) {
223
+ if (event.key === "Home")
224
+ return "first";
225
+ if (event.key === "End")
226
+ return "last";
227
+ const orientation = options.orientation ?? "horizontal";
228
+ const rtl = options.rtl ?? false;
229
+ if (orientation !== "vertical" && event.key === "ArrowRight")
230
+ return rtl ? "previous" : "next";
231
+ if (orientation !== "vertical" && event.key === "ArrowLeft")
232
+ return rtl ? "next" : "previous";
233
+ if (orientation !== "horizontal" && event.key === "ArrowDown")
234
+ return "next";
235
+ if (orientation !== "horizontal" && event.key === "ArrowUp")
236
+ return "previous";
237
+ return undefined;
238
+ }
239
+ /**
240
+ * Prevents the native key default only when keyMove recognizes the key, then updates active state.
241
+ *
242
+ * @remarks
243
+ * ## Why
244
+ *
245
+ * The operation exposes Composite's transition directly so callers can compose it in Effect
246
+ * programs and native event handlers.
247
+ *
248
+ * ## Ownership and lifetime
249
+ *
250
+ * The returned Effect performs the update or DOM side effect only when run, preserves the declared
251
+ * error and service channels, and retains no resources after completion.
252
+ *
253
+ * ## Example
254
+ *
255
+ * Import with `import { moveByKey } from "@typed/ui/Composite";` Extend the [Composite.makeState
256
+ * runnable setup](/reference/%40typed%2Fui%2FComposite%23makeState). Inside the linked Effect
257
+ * program run `yield* moveByKey({ key: "ArrowDown" }, { state, collection })`, then read state to
258
+ * observe the active id selected by the current orientation and RTL policy.
259
+ * @since 1.0.0
260
+ * @category combinators
261
+ */
262
+ export function moveByKey(event, options) {
263
+ return Effect.gen(function* () {
264
+ const direction = keyMove(event, yield* options.state);
265
+ if (direction === undefined)
266
+ return false;
267
+ event.preventDefault?.();
268
+ yield* move(options, direction);
269
+ return true;
270
+ });
271
+ }
272
+ /**
273
+ * Moves active state, then focuses and scrolls the mounted active item when virtual focus is
274
+ * disabled.
275
+ *
276
+ * @remarks
277
+ * ## Why
278
+ *
279
+ * The operation exposes Composite's transition directly so callers can compose it in Effect
280
+ * programs and native event handlers.
281
+ *
282
+ * ## Ownership and lifetime
283
+ *
284
+ * The returned Effect performs the update or DOM side effect only when run, preserves the declared
285
+ * error and service channels, and retains no resources after completion.
286
+ *
287
+ * ## Example
288
+ *
289
+ * Import with `import { moveAndFocus } from "@typed/ui/Composite";` Extend the [Composite.makeState
290
+ * runnable setup](/reference/%40typed%2Fui%2FComposite%23makeState). Inside the linked Effect
291
+ * program run `yield* moveAndFocus({ state, collection }, "next")`; the returned state names the
292
+ * next id and its registered element receives native focus.
293
+ * @since 1.0.0
294
+ * @category combinators
295
+ */
296
+ export function moveAndFocus(options, direction) {
297
+ return Effect.tap(move(options, direction), Effect.andThen(focusActive(options), scrollActive(options)));
298
+ }
299
+ /**
300
+ * Focuses the registered active element unless state uses virtual focus or has no active id.
301
+ *
302
+ * @remarks
303
+ * ## Why
304
+ *
305
+ * The operation exposes Composite's transition directly so callers can compose it in Effect
306
+ * programs and native event handlers.
307
+ *
308
+ * ## Ownership and lifetime
309
+ *
310
+ * The returned Effect performs the update or DOM side effect only when run, preserves the declared
311
+ * error and service channels, and retains no resources after completion.
312
+ *
313
+ * ## Example
314
+ *
315
+ * Import with `import { focusActive } from "@typed/ui/Composite";` Extend the [Composite.makeState
316
+ * runnable setup](/reference/%40typed%2Fui%2FComposite%23makeState). Inside the linked Effect
317
+ * program run `yield* focusActive({ state, collection })`; the active registered element receives
318
+ * native focus, with no state transition when no matching element exists.
319
+ * @since 1.0.0
320
+ * @category combinators
321
+ */
322
+ export function focusActive(options) {
323
+ return Effect.gen(function* () {
324
+ const state = yield* options.state;
325
+ if (state.virtualFocus || state.activeId === null)
326
+ return;
327
+ const item = (yield* options.collection).find((item) => item.id === state.activeId);
328
+ yield* focusElement(item?.element);
329
+ });
330
+ }
331
+ /**
332
+ * Calls an existing platform focus method inside Effect.sync and otherwise does nothing.
333
+ *
334
+ * @remarks
335
+ * ## Why
336
+ *
337
+ * The operation exposes Composite's transition directly so callers can compose it in Effect
338
+ * programs and native event handlers.
339
+ *
340
+ * ## Ownership and lifetime
341
+ *
342
+ * The returned Effect performs the update or DOM side effect only when run, preserves the declared
343
+ * error and service channels, and retains no resources after completion.
344
+ *
345
+ * @example
346
+ * ```ts
347
+ * import * as Composite from "@typed/ui/Composite";
348
+ *
349
+ * const focused = Composite.focusElement(document.querySelector("button") ?? undefined);
350
+ * ```
351
+ * @since 1.0.0
352
+ * @category combinators
353
+ */
354
+ export function focusElement(element) {
355
+ return Effect.sync(() => {
356
+ const focus = element === undefined ? undefined : Reflect.get(element, "focus");
357
+ if (typeof focus === "function")
358
+ focus.call(element);
359
+ });
360
+ }
361
+ /**
362
+ * Calls scrollIntoView with nearest block/inline alignment for the mounted active item.
363
+ *
364
+ * @remarks
365
+ * ## Why
366
+ *
367
+ * The operation exposes Composite's transition directly so callers can compose it in Effect
368
+ * programs and native event handlers.
369
+ *
370
+ * ## Ownership and lifetime
371
+ *
372
+ * The returned Effect performs the update or DOM side effect only when run, preserves the declared
373
+ * error and service channels, and retains no resources after completion.
374
+ *
375
+ * ## Example
376
+ *
377
+ * Import with `import { scrollActive } from "@typed/ui/Composite";` Extend the [Composite.makeState
378
+ * runnable setup](/reference/%40typed%2Fui%2FComposite%23makeState). Inside the linked Effect
379
+ * program run `yield* scrollActive({ state, collection })`; the active registered element receives
380
+ * `scrollIntoView({ block: "nearest", inline: "nearest" })` when that method is available.
381
+ * @since 1.0.0
382
+ * @category combinators
383
+ */
384
+ export function scrollActive(options) {
385
+ return Effect.gen(function* () {
386
+ const activeId = (yield* options.state).activeId;
387
+ if (activeId === null)
388
+ return;
389
+ const element = (yield* options.collection).find((item) => item.id === activeId)?.element;
390
+ const scrollIntoView = element === undefined ? undefined : Reflect.get(element, "scrollIntoView");
391
+ if (typeof scrollIntoView === "function") {
392
+ scrollIntoView.call(element, { block: "nearest", inline: "nearest" });
393
+ }
394
+ });
395
+ }
396
+ /**
397
+ * Returns the first enabled item id in DOM order whose textValue starts with the query.
398
+ *
399
+ * @remarks
400
+ * ## Why
401
+ *
402
+ * Separating this deterministic policy from event wiring lets applications test it directly and
403
+ * reuse it in custom composites.
404
+ *
405
+ * ## Ownership and lifetime
406
+ *
407
+ * This is a synchronous calculation. It acquires no resources and does not mutate the input array,
408
+ * state, event, or DOM.
409
+ *
410
+ * @example
411
+ * ```ts
412
+ * import * as Composite from "@typed/ui/Composite";
413
+ *
414
+ * const id = Composite.typeahead([{ id: "alpha", textValue: "Alpha" }], "al");
415
+ * ```
416
+ * @since 1.0.0
417
+ * @category combinators
418
+ */
419
+ export function typeahead(items, search, text = (item) => item.textValue ?? item.id, includeDisabled = false) {
420
+ return typeaheadFrom(items, search, null, text, includeDisabled);
421
+ }
422
+ /**
423
+ * Returns only the id selected by typeahead, or null when no item matches.
424
+ *
425
+ * @remarks
426
+ * ## Why
427
+ *
428
+ * Separating this deterministic policy from event wiring lets applications test it directly and
429
+ * reuse it in custom composites.
430
+ *
431
+ * ## Ownership and lifetime
432
+ *
433
+ * This is a synchronous calculation. It acquires no resources and does not mutate the input array,
434
+ * state, event, or DOM.
435
+ *
436
+ * @example
437
+ * ```ts
438
+ * import * as Composite from "@typed/ui/Composite";
439
+ *
440
+ * const id = Composite.typeaheadFrom([{ id: "alpha", textValue: "Alpha" }], "al", null);
441
+ * ```
442
+ * @since 1.0.0
443
+ * @category combinators
444
+ */
445
+ export function typeaheadFrom(items, search, activeId, text = (item) => item.textValue ?? item.id, includeDisabled = false) {
446
+ const query = search.trim().toLocaleLowerCase();
447
+ if (query.length === 0)
448
+ return null;
449
+ const enabled = orderedItems(items, includeDisabled);
450
+ const index = activeId === null ? -1 : enabled.findIndex((item) => item.id === activeId);
451
+ const ordered = index === -1 ? enabled : [...enabled.slice(index + 1), ...enabled.slice(0, index + 1)];
452
+ const item = ordered.find((item) => text(item).toLocaleLowerCase().startsWith(query));
453
+ return item?.id ?? null;
454
+ }
455
+ /**
456
+ * Returns an unmodified one-character key exactly as provided; modified and multi-character keys
457
+ * return null.
458
+ *
459
+ * @remarks
460
+ * ## Why
461
+ *
462
+ * Separating this deterministic policy from event wiring lets applications test it directly and
463
+ * reuse it in custom composites.
464
+ *
465
+ * ## Ownership and lifetime
466
+ *
467
+ * This is a synchronous calculation. It acquires no resources and does not mutate the input array,
468
+ * state, event, or DOM.
469
+ *
470
+ * @example
471
+ * ```ts
472
+ * import * as Composite from "@typed/ui/Composite";
473
+ *
474
+ * const key = Composite.typeaheadKey({ key: "A" });
475
+ * ```
476
+ * @since 1.0.0
477
+ * @category combinators
478
+ */
479
+ export function typeaheadKey(event) {
480
+ if (event.altKey || event.ctrlKey || event.metaKey)
481
+ return null;
482
+ return event.key.length === 1 ? event.key : null;
483
+ }
484
+ /**
485
+ * Appends within the timeout window and starts a new query after the buffer expires.
486
+ *
487
+ * @remarks
488
+ * ## Why
489
+ *
490
+ * Separating this deterministic policy from event wiring lets applications test it directly and
491
+ * reuse it in custom composites.
492
+ *
493
+ * ## Ownership and lifetime
494
+ *
495
+ * This is a synchronous calculation. It acquires no resources and does not mutate the input array,
496
+ * state, event, or DOM.
497
+ *
498
+ * @example
499
+ * ```ts
500
+ * import * as Composite from "@typed/ui/Composite";
501
+ *
502
+ * const buffer = Composite.updateTypeaheadBuffer({ value: "a", updatedAt: 100 }, "b", 200);
503
+ * ```
504
+ * @since 1.0.0
505
+ * @category combinators
506
+ */
507
+ export function updateTypeaheadBuffer(buffer, key, now, timeout = 500) {
508
+ return {
509
+ value: now - buffer.updatedAt > timeout ? key : buffer.value + key,
510
+ updatedAt: now,
511
+ };
512
+ }
513
+ /**
514
+ * Sorts a copy by mounted DOM order and then removes disabled items.
515
+ *
516
+ * @remarks
517
+ * ## Why
518
+ *
519
+ * Separating this deterministic policy from event wiring lets applications test it directly and
520
+ * reuse it in custom composites.
521
+ *
522
+ * ## Ownership and lifetime
523
+ *
524
+ * This is a synchronous calculation. It acquires no resources and does not mutate the input array,
525
+ * state, event, or DOM.
526
+ *
527
+ * @example
528
+ * ```ts
529
+ * import * as Composite from "@typed/ui/Composite";
530
+ *
531
+ * const items = Composite.orderedEnabledItems([{ id: "a" }, { id: "b", disabled: true }]);
532
+ * ```
533
+ * @since 1.0.0
534
+ * @category combinators
535
+ */
536
+ export function orderedEnabledItems(items) {
537
+ return Collection.enabledItems(Collection.byDomOrder(items));
538
+ }
539
+ /**
540
+ * Returns the id reached by first/last/next/previous with optional disabled inclusion and loop
541
+ * policy.
542
+ *
543
+ * @remarks
544
+ * ## Why
545
+ *
546
+ * Separating this deterministic policy from event wiring lets applications test it directly and
547
+ * reuse it in custom composites.
548
+ *
549
+ * ## Ownership and lifetime
550
+ *
551
+ * This is a synchronous calculation. It acquires no resources and does not mutate the input array,
552
+ * state, event, or DOM.
553
+ *
554
+ * @example
555
+ * ```ts
556
+ * import * as Composite from "@typed/ui/Composite";
557
+ *
558
+ * const id = Composite.moveActiveId([{ id: "a" }, { id: "b" }], { activeId: "a", loop: true }, "next");
559
+ * ```
560
+ * @since 1.0.0
561
+ * @category combinators
562
+ */
563
+ export function moveActiveId(items, state, direction, includeDisabled = false) {
564
+ return moveActiveItem(items, state, direction, includeDisabled)?.id ?? null;
565
+ }
566
+ /**
567
+ * Returns the full item selected by moveActiveId, or undefined when no item is reachable.
568
+ *
569
+ * @remarks
570
+ * ## Why
571
+ *
572
+ * Separating this deterministic policy from event wiring lets applications test it directly and
573
+ * reuse it in custom composites.
574
+ *
575
+ * ## Ownership and lifetime
576
+ *
577
+ * This is a synchronous calculation. It acquires no resources and does not mutate the input array,
578
+ * state, event, or DOM.
579
+ *
580
+ * @example
581
+ * ```ts
582
+ * import * as Composite from "@typed/ui/Composite";
583
+ *
584
+ * const item = Composite.moveActiveItem([{ id: "a" }, { id: "b" }], { activeId: "a", loop: true }, "next");
585
+ * ```
586
+ * @since 1.0.0
587
+ * @category combinators
588
+ */
589
+ export function moveActiveItem(items, state, direction, includeDisabled = false) {
590
+ const enabled = orderedItems(items, includeDisabled);
591
+ if (enabled.length === 0)
592
+ return undefined;
593
+ if (direction === "first")
594
+ return enabled[0];
595
+ if (direction === "last")
596
+ return enabled[enabled.length - 1];
597
+ const index = activeIndex(enabled, state.activeId, direction, state.loop);
598
+ return enabled[index];
599
+ }
600
+ function orderedItems(items, includeDisabled) {
601
+ return includeDisabled ? Collection.byDomOrder(items) : orderedEnabledItems(items);
602
+ }
603
+ function activeIndex(items, activeId, direction, loop) {
604
+ if (activeId === null)
605
+ return direction === "previous" && loop ? items.length - 1 : 0;
606
+ const current = items.findIndex((item) => item.id === activeId);
607
+ if (current === -1)
608
+ return direction === "previous" && loop ? items.length - 1 : 0;
609
+ const index = current;
610
+ const delta = direction === "next" ? 1 : -1;
611
+ const next = index + delta;
612
+ if (loop)
613
+ return (next + items.length) % items.length;
614
+ return Math.min(Math.max(next, 0), items.length - 1);
615
+ }