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

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,366 @@
1
+ /**
2
+ * Toolbar is a roving-focus composite with toolbar and button roles. Orientation and RTL control
3
+ * Arrow-key order; Home and End select the document-order endpoints.
4
+ *
5
+ * @remarks
6
+ * The module keeps policy, state transitions, and DOM rendering separable so applications can use
7
+ * the state and pure operations without mounting UI, or supply custom hosts without replacing native
8
+ * events and browser-owned focus.
9
+ *
10
+ * @since 1.0.0
11
+ * @category modules
12
+ * @packageDocumentation
13
+ */
14
+ import * as Effect from "effect/Effect";
15
+ import type * as Scope from "effect/Scope";
16
+ import * as Schema from "effect/Schema";
17
+ import type { Fx } from "@typed/fx/Fx";
18
+ import { RefSubject } from "@typed/fx";
19
+ import { EventHandler, type Renderable, type RenderEvent, type RenderTemplate } from "@typed/template";
20
+ import * as Collection from "./Collection.js";
21
+ import * as Composite from "./Composite.js";
22
+ import * as Dom from "./Dom.js";
23
+ import type { HostResult } from "./Dom/Types.js";
24
+ /**
25
+ * Complete renderer-independent state for Toolbar.
26
+ *
27
+ * @remarks
28
+ * ## Why
29
+ *
30
+ * Applications can inspect, update, and test Toolbar behavior without mounting or coupling the
31
+ * state to a renderer.
32
+ *
33
+ * ## Ownership and lifetime
34
+ *
35
+ * This declaration is data or schema metadata and acquires no resources.
36
+ *
37
+ * ## Example
38
+ *
39
+ * Import with `import type { State } from "@typed/ui/Toolbar";` Extend the [Toolbar.makeState
40
+ * runnable setup](/reference/%40typed%2Fui%2FToolbar%23makeState). Inside the linked program,
41
+ * `const snapshot: State = yield* state` exposes toolbar focus policy.
42
+ * @since 1.0.0
43
+ * @category models
44
+ */
45
+ export interface State extends Composite.State {
46
+ }
47
+ /**
48
+ * Initial Toolbar values. Uses Composite defaults unless overridden.
49
+ *
50
+ * @remarks
51
+ * ## Why
52
+ *
53
+ * Making initialization explicit documents hydration-sensitive defaults and lets servers and
54
+ * clients construct matching state.
55
+ *
56
+ * ## Ownership and lifetime
57
+ *
58
+ * This declaration is data or schema metadata and acquires no resources.
59
+ *
60
+ * ## Example
61
+ *
62
+ * Import with `import type { InitialState } from "@typed/ui/Toolbar";` Extend the
63
+ * [Toolbar.makeState runnable setup](/reference/%40typed%2Fui%2FToolbar%23makeState). Construct a
64
+ * vertical toolbar with
65
+ * `const initial: InitialState = { orientation: "vertical" }; const state = yield* Toolbar.makeState(initial)`.
66
+ * @since 1.0.0
67
+ * @category models
68
+ */
69
+ export type InitialState = Composite.InitialState;
70
+ /**
71
+ * Effect Schema used by makeState to encode, decode, and hydrate Toolbar state.
72
+ *
73
+ * @remarks
74
+ * ## Why
75
+ *
76
+ * A public schema makes hydration and serialized state use the same runtime validation as direct
77
+ * construction.
78
+ *
79
+ * ## Ownership and lifetime
80
+ *
81
+ * This declaration is data or schema metadata and acquires no resources.
82
+ *
83
+ * @example
84
+ * ```ts
85
+ * import * as Schema from "effect/Schema";
86
+ * import * as Toolbar from "@typed/ui/Toolbar";
87
+ *
88
+ * const decodeState = Schema.decodeUnknownEffect(Toolbar.StateSchema);
89
+ * ```
90
+ * @since 1.0.0
91
+ * @category schemas
92
+ */
93
+ export declare const StateSchema: Schema.Struct<{
94
+ readonly activeId: Schema.NullOr<Schema.String>;
95
+ readonly orientation: Schema.Literals<readonly ["horizontal", "vertical", "both"]>;
96
+ readonly loop: Schema.Boolean;
97
+ readonly rtl: Schema.Boolean;
98
+ readonly virtualFocus: Schema.Boolean;
99
+ }>;
100
+ /**
101
+ * Creates hydrated Toolbar state. Uses Composite defaults unless overridden.
102
+ *
103
+ * @remarks
104
+ * ## Why
105
+ *
106
+ * State and collection ownership can be composed and tested independently from any renderer.
107
+ *
108
+ * ## Ownership and lifetime
109
+ *
110
+ * The returned Effect creates the RefSubject when run. That state is renderer-independent;
111
+ * collection registrations belong to the separate Scope that runs register or ref, not to state
112
+ * creation.
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * import * as Effect from "effect/Effect";
117
+ * import * as Toolbar from "@typed/ui/Toolbar";
118
+ *
119
+ * const program = Effect.scoped(
120
+ * Effect.gen(function* () {
121
+ * const state = yield* Toolbar.makeState({});
122
+ * const collection = yield* Toolbar.makeCollection();
123
+ * return { state: yield* state, collection: yield* collection };
124
+ * }),
125
+ * );
126
+ * ```
127
+ * @since 1.0.0
128
+ * @category constructors
129
+ */
130
+ export declare function makeState(initial?: InitialState): Effect.Effect<RefSubject.HydratedRefSubject<{
131
+ readonly activeId: string | null;
132
+ readonly orientation: "both" | "horizontal" | "vertical";
133
+ readonly loop: boolean;
134
+ readonly rtl: boolean;
135
+ readonly virtualFocus: boolean;
136
+ }, Schema.SchemaError, never, never>, never, Scope.Scope>;
137
+ /**
138
+ * Creates a scoped Collection for Toolbar items.
139
+ *
140
+ * @remarks
141
+ * ## Why
142
+ *
143
+ * State and collection ownership can be composed and tested independently from any renderer.
144
+ *
145
+ * ## Ownership and lifetime
146
+ *
147
+ * The returned Effect allocates the RefSubject in the caller's Scope. Each later registration is
148
+ * owned by the Scope that runs register, independently of this construction Effect.
149
+ *
150
+ * @example
151
+ * ```ts
152
+ * import * as Effect from "effect/Effect";
153
+ * import * as Toolbar from "@typed/ui/Toolbar";
154
+ *
155
+ * const program = Effect.scoped(
156
+ * Effect.gen(function* () {
157
+ * const collection = yield* Toolbar.makeCollection();
158
+ * return yield* collection;
159
+ * }),
160
+ * );
161
+ * ```
162
+ * @since 1.0.0
163
+ * @category constructors
164
+ */
165
+ export declare const makeCollection: (initial?: Collection.State<string, Element>) => Effect.Effect<RefSubject.RefSubject<Collection.State<string, Element>, never, never>, never, Scope.Scope>;
166
+ /**
167
+ * Inputs accepted by Toolbar.Root in addition to the shared DOM host options.
168
+ *
169
+ * @remarks
170
+ * ## Why
171
+ *
172
+ * The options type makes required state, content, accessible relationships, and custom-host inputs
173
+ * visible before rendering.
174
+ *
175
+ * ## Ownership and lifetime
176
+ *
177
+ * This declaration is data or schema metadata and acquires no resources.
178
+ *
179
+ * ## Example
180
+ *
181
+ * Import with `import type { RootOptions } from "@typed/ui/Toolbar";` Extend the [Toolbar.makeState
182
+ * runnable setup](/reference/%40typed%2Fui%2FToolbar%23makeState). Enable toolbar movement with
183
+ * `const options: RootOptions = { state, collection, label: "Formatting", content: "Buttons" }`.
184
+ * @since 1.0.0
185
+ * @category models
186
+ */
187
+ export interface RootOptions extends Dom.HostOptions<HTMLDivElement> {
188
+ /**
189
+ * Renderer-independent RefSubject state consumed by this component or operation.
190
+ * @since 1.0.0
191
+ * @category models
192
+ */
193
+ readonly state: RefSubject.HydratedRefSubject<State, Schema.SchemaError>;
194
+ /**
195
+ * Item registry used for collection-driven keyboard behavior and mounted ordering.
196
+ * @since 1.0.0
197
+ * @category models
198
+ */
199
+ readonly collection?: RefSubject.RefSubject<Collection.State<string>>;
200
+ /**
201
+ * Renderable child content for the component host.
202
+ * @since 1.0.0
203
+ * @category models
204
+ */
205
+ readonly content: Renderable.Any;
206
+ /**
207
+ * Accessible label rendered through aria-label.
208
+ * @since 1.0.0
209
+ * @category models
210
+ */
211
+ readonly label?: Renderable.Any<string | null | undefined>;
212
+ }
213
+ declare function rootProps<const Options extends RootOptions>(options: Options): ({ property }: Dom.InternalPropsHelpers<Options>) => {
214
+ readonly role: "toolbar";
215
+ readonly "aria-label": Exclude<Dom.Property<Options, "label">, Dom.Nullish> | undefined;
216
+ readonly "aria-orientation": RefSubject.Computed<Composite.Orientation, Schema.SchemaError, never>;
217
+ readonly tabindex: RefSubject.Computed<-1 | 0, Schema.SchemaError, never>;
218
+ readonly onfocus: Effect.Effect<void, Schema.SchemaError, never> | undefined;
219
+ readonly onkeydown: EventHandler.EventHandler<KeyboardEvent, Schema.SchemaError, never> | undefined;
220
+ readonly ref: RefSubject.HydratedRefSubject<State, Schema.SchemaError, never, never>;
221
+ };
222
+ type RootProps<Options extends RootOptions> = ReturnType<ReturnType<typeof rootProps<Options>>>;
223
+ /**
224
+ * Renders the toolbar root and moves roving focus through registered items in DOM order.
225
+ *
226
+ * @remarks
227
+ * ## Why
228
+ *
229
+ * The component applies the family behavior while leaving callers free to supply a custom host
230
+ * through the shared DOM boundary.
231
+ *
232
+ * ## Ownership and lifetime
233
+ *
234
+ * The returned Fx installs DOM refs, native listeners, state subscriptions, and optional
235
+ * collection registrations only when rendered. The rendering Scope removes those resources;
236
+ * unrelated nodes and attributes remain caller-owned.
237
+ *
238
+ * ## Example
239
+ *
240
+ * Import with `import { Root } from "@typed/ui/Toolbar";` Extend the [Toolbar.makeState runnable
241
+ * setup](/reference/%40typed%2Fui%2FToolbar%23makeState). Replace the linked program's final
242
+ * snapshot read with `Root({ state, label: "Formatting", content: "Buttons" })`; render that Fx
243
+ * before the same Scope closes.
244
+ * @since 1.0.0
245
+ * @category components
246
+ */
247
+ export declare function Root<const Options extends RootOptions, const Host extends HostResult = never>(options: Options, host?: Dom.HostOverride<Dom.RenderHostProps<Options, RootProps<Options>>, Options["content"], Host>): Fx<RenderEvent, Renderable.Error<Options | Host>, Renderable.Services<Options | Host> | Scope.Scope | RenderTemplate>;
248
+ /**
249
+ * Consumer-facing alias of the canonical Toolbar component with identical behavior and lifetime.
250
+ *
251
+ * @remarks
252
+ * ## Why
253
+ *
254
+ * The component applies the family behavior while leaving callers free to supply a custom host
255
+ * through the shared DOM boundary.
256
+ *
257
+ * ## Ownership and lifetime
258
+ *
259
+ * The alias acquires nothing. Rendering it has exactly the canonical component's Scope and DOM
260
+ * ownership contract.
261
+ *
262
+ * ## Example
263
+ *
264
+ * Import with `import { Toolbar } from "@typed/ui/Toolbar";` Extend the [Toolbar.makeState runnable
265
+ * setup](/reference/%40typed%2Fui%2FToolbar%23makeState). Replace the linked program's final
266
+ * snapshot read with `Toolbar({ state, label: "Formatting", content: "Buttons" })`; render that Fx
267
+ * before the same Scope closes.
268
+ * @since 1.0.0
269
+ * @category components
270
+ */
271
+ export declare const Toolbar: typeof Root;
272
+ /**
273
+ * Inputs accepted by Toolbar.Item in addition to the shared DOM host options.
274
+ *
275
+ * @remarks
276
+ * ## Why
277
+ *
278
+ * The options type makes required state, content, accessible relationships, and custom-host inputs
279
+ * visible before rendering.
280
+ *
281
+ * ## Ownership and lifetime
282
+ *
283
+ * This declaration is data or schema metadata and acquires no resources.
284
+ *
285
+ * ## Example
286
+ *
287
+ * Import with `import type { ItemOptions } from "@typed/ui/Toolbar";` Extend the [Toolbar.makeState
288
+ * runnable setup](/reference/%40typed%2Fui%2FToolbar%23makeState). A toolbar control is
289
+ * `const options: ItemOptions = { state, collection, id: "bold", content: "Bold" }`.
290
+ * @since 1.0.0
291
+ * @category models
292
+ */
293
+ export interface ItemOptions extends Dom.HostOptions<HTMLDivElement> {
294
+ /**
295
+ * Renderer-independent RefSubject state consumed by this component or operation.
296
+ * @since 1.0.0
297
+ * @category models
298
+ */
299
+ readonly state: RefSubject.HydratedRefSubject<State, Schema.SchemaError>;
300
+ /**
301
+ * Item registry used for collection-driven keyboard behavior and mounted ordering.
302
+ * @since 1.0.0
303
+ * @category models
304
+ */
305
+ readonly collection?: RefSubject.RefSubject<Collection.State<string>>;
306
+ /**
307
+ * Stable id used for collection identity and ARIA relationships.
308
+ * @since 1.0.0
309
+ * @category models
310
+ */
311
+ readonly id: string;
312
+ /**
313
+ * Renderable child content for the component host.
314
+ * @since 1.0.0
315
+ * @category models
316
+ */
317
+ readonly content: Renderable.Any;
318
+ /**
319
+ * Search text used by typeahead independently of rendered markup.
320
+ * @since 1.0.0
321
+ * @category models
322
+ */
323
+ readonly textValue?: string;
324
+ /**
325
+ * Flag used by collection movement and widget handlers to skip activation by default.
326
+ * @since 1.0.0
327
+ * @category models
328
+ */
329
+ readonly disabled?: boolean;
330
+ }
331
+ declare function itemProps<const Options extends ItemOptions>(options: Options): () => {
332
+ readonly id: string;
333
+ readonly role: "button";
334
+ readonly "aria-disabled": boolean;
335
+ readonly tabindex: RefSubject.Computed<-1 | 0, Schema.SchemaError, never>;
336
+ readonly onfocus: Effect.Effect<void, never, never> | Effect.Effect<State, Schema.SchemaError, never>;
337
+ readonly ref: ((element: Element & HTMLDivElement & RefSubject.HydrationElement) => Effect.Effect<void, any, any>) | undefined;
338
+ };
339
+ type ItemProps<Options extends ItemOptions> = ReturnType<ReturnType<typeof itemProps<Options>>>;
340
+ /**
341
+ * Renders and optionally registers a toolbar button; focus activates it unless disabled.
342
+ *
343
+ * @remarks
344
+ * ## Why
345
+ *
346
+ * The component applies the family behavior while leaving callers free to supply a custom host
347
+ * through the shared DOM boundary.
348
+ *
349
+ * ## Ownership and lifetime
350
+ *
351
+ * The returned Fx installs DOM refs, native listeners, state subscriptions, and optional
352
+ * collection registrations only when rendered. The rendering Scope removes those resources;
353
+ * unrelated nodes and attributes remain caller-owned.
354
+ *
355
+ * ## Example
356
+ *
357
+ * Import with `import { Item } from "@typed/ui/Toolbar";` Extend the [Toolbar.makeState runnable
358
+ * setup](/reference/%40typed%2Fui%2FToolbar%23makeState). Replace the linked program's final
359
+ * snapshot read with `Item({ state, id: "bold", content: "Bold" })`; render that Fx before the same
360
+ * Scope closes.
361
+ * @since 1.0.0
362
+ * @category components
363
+ */
364
+ export declare function Item<const Options extends ItemOptions, const Host extends HostResult = never>(options: Options, host?: Dom.HostOverride<Dom.RenderHostProps<Options, ItemProps<Options>>, Options["content"], Host>): Fx<RenderEvent, Renderable.Error<Options | Host>, Renderable.Services<Options | Host> | Scope.Scope | RenderTemplate>;
365
+ export {};
366
+ //# sourceMappingURL=Toolbar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../src/Toolbar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EACL,YAAY,EAEZ,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,cAAc,EACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAChC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,KAAM,SAAQ,SAAS,CAAC,KAAK;CAAG;AACjD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,CAAC,YAAY,CAAC;AAClD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,WAAW;;;;;;EAAwB,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,YAAiB;;;;;;0DAEnD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,cAAc,4JAA+B,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,WAAY,SAAQ,GAAG,CAAC,WAAW,CAAC,cAAc,CAAC;IAClE;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;IACzE;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACtE;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;CAC5D;AAED,iBAAS,SAAS,CAAC,KAAK,CAAC,OAAO,SAAS,WAAW,EAAE,OAAO,EAAE,OAAO,kBAuC9C,GAAG,CAAC,oBAAoB,CAAC,OAAO,CAAC;mBAE7C,SAAS;;;;;;;EAQpB;AACD,KAAK,SAAS,CAAC,OAAO,SAAS,WAAW,IAAI,UAAU,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAEhG;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,IAAI,CAAC,KAAK,CAAC,OAAO,SAAS,WAAW,EAAE,KAAK,CAAC,IAAI,SAAS,UAAU,GAAG,KAAK,EAC3F,OAAO,EAAE,OAAO,EAChB,IAAI,CAAC,EAAE,GAAG,CAAC,YAAY,CACrB,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,EAChD,OAAO,CAAC,SAAS,CAAC,EAClB,IAAI,CACL,GACA,EAAE,CACH,WAAW,EACX,UAAU,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,EAChC,UAAU,CAAC,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,GAAG,cAAc,CACnE,CAUA;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,OAAO,aAAO,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,WAAY,SAAQ,GAAG,CAAC,WAAW,CAAC,cAAc,CAAC;IAClE;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;IACzE;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACtE;;;;OAIG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,iBAAS,SAAS,CAAC,KAAK,CAAC,OAAO,SAAS,WAAW,EAAE,OAAO,EAAE,OAAO;aAgBhE,EAAE;aACF,IAAI,EAAE,QAAQ;aACd,eAAe;aACf,QAAQ;aACR,OAAO;aACP,GAAG;EAER;AACD,KAAK,SAAS,CAAC,OAAO,SAAS,WAAW,IAAI,UAAU,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAEhG;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,IAAI,CAAC,KAAK,CAAC,OAAO,SAAS,WAAW,EAAE,KAAK,CAAC,IAAI,SAAS,UAAU,GAAG,KAAK,EAC3F,OAAO,EAAE,OAAO,EAChB,IAAI,CAAC,EAAE,GAAG,CAAC,YAAY,CACrB,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,EAChD,OAAO,CAAC,SAAS,CAAC,EAClB,IAAI,CACL,GACA,EAAE,CACH,WAAW,EACX,UAAU,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,EAChC,UAAU,CAAC,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,GAAG,cAAc,CACnE,CAcA"}
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Toolbar is a roving-focus composite with toolbar and button roles. Orientation and RTL control
3
+ * Arrow-key order; Home and End select the document-order endpoints.
4
+ *
5
+ * @remarks
6
+ * The module keeps policy, state transitions, and DOM rendering separable so applications can use
7
+ * the state and pure operations without mounting UI, or supply custom hosts without replacing native
8
+ * events and browser-owned focus.
9
+ *
10
+ * @since 1.0.0
11
+ * @category modules
12
+ * @packageDocumentation
13
+ */
14
+ import * as Effect from "effect/Effect";
15
+ import { RefSubject } from "@typed/fx";
16
+ import { EventHandler, html, } from "@typed/template";
17
+ import * as Collection from "./Collection.js";
18
+ import * as Composite from "./Composite.js";
19
+ import * as Dom from "./Dom.js";
20
+ /**
21
+ * Effect Schema used by makeState to encode, decode, and hydrate Toolbar state.
22
+ *
23
+ * @remarks
24
+ * ## Why
25
+ *
26
+ * A public schema makes hydration and serialized state use the same runtime validation as direct
27
+ * construction.
28
+ *
29
+ * ## Ownership and lifetime
30
+ *
31
+ * This declaration is data or schema metadata and acquires no resources.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * import * as Schema from "effect/Schema";
36
+ * import * as Toolbar from "@typed/ui/Toolbar";
37
+ *
38
+ * const decodeState = Schema.decodeUnknownEffect(Toolbar.StateSchema);
39
+ * ```
40
+ * @since 1.0.0
41
+ * @category schemas
42
+ */
43
+ export const StateSchema = Composite.StateSchema;
44
+ /**
45
+ * Creates hydrated Toolbar state. Uses Composite defaults unless overridden.
46
+ *
47
+ * @remarks
48
+ * ## Why
49
+ *
50
+ * State and collection ownership can be composed and tested independently from any renderer.
51
+ *
52
+ * ## Ownership and lifetime
53
+ *
54
+ * The returned Effect creates the RefSubject when run. That state is renderer-independent;
55
+ * collection registrations belong to the separate Scope that runs register or ref, not to state
56
+ * creation.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * import * as Effect from "effect/Effect";
61
+ * import * as Toolbar from "@typed/ui/Toolbar";
62
+ *
63
+ * const program = Effect.scoped(
64
+ * Effect.gen(function* () {
65
+ * const state = yield* Toolbar.makeState({});
66
+ * const collection = yield* Toolbar.makeCollection();
67
+ * return { state: yield* state, collection: yield* collection };
68
+ * }),
69
+ * );
70
+ * ```
71
+ * @since 1.0.0
72
+ * @category constructors
73
+ */
74
+ export function makeState(initial = {}) {
75
+ return Composite.makeState(initial);
76
+ }
77
+ /**
78
+ * Creates a scoped Collection for Toolbar items.
79
+ *
80
+ * @remarks
81
+ * ## Why
82
+ *
83
+ * State and collection ownership can be composed and tested independently from any renderer.
84
+ *
85
+ * ## Ownership and lifetime
86
+ *
87
+ * The returned Effect allocates the RefSubject in the caller's Scope. Each later registration is
88
+ * owned by the Scope that runs register, independently of this construction Effect.
89
+ *
90
+ * @example
91
+ * ```ts
92
+ * import * as Effect from "effect/Effect";
93
+ * import * as Toolbar from "@typed/ui/Toolbar";
94
+ *
95
+ * const program = Effect.scoped(
96
+ * Effect.gen(function* () {
97
+ * const collection = yield* Toolbar.makeCollection();
98
+ * return yield* collection;
99
+ * }),
100
+ * );
101
+ * ```
102
+ * @since 1.0.0
103
+ * @category constructors
104
+ */
105
+ export const makeCollection = Collection.makeState;
106
+ function rootProps(options) {
107
+ const onfocus = options.collection === undefined
108
+ ? undefined
109
+ : Effect.gen(function* () {
110
+ if ((yield* options.state).activeId !== null)
111
+ return;
112
+ yield* Composite.moveAndFocus({ state: options.state, collection: options.collection }, "first");
113
+ });
114
+ const onkeydown = options.collection === undefined
115
+ ? undefined
116
+ : EventHandler.make(Effect.fn(function* (event) {
117
+ if (event.key === "Enter" || event.key === " ") {
118
+ const activeId = (yield* options.state).activeId;
119
+ const item = activeId === null
120
+ ? undefined
121
+ : (yield* options.collection).find((candidate) => candidate.id === activeId);
122
+ const click = item?.disabled === true ? undefined : Reflect.get(item?.element ?? {}, "click");
123
+ if (typeof click === "function") {
124
+ event.preventDefault();
125
+ yield* Effect.sync(() => click.call(item.element));
126
+ }
127
+ return;
128
+ }
129
+ const direction = Composite.keyMove(event, yield* options.state);
130
+ if (direction === undefined)
131
+ return;
132
+ event.preventDefault();
133
+ yield* Composite.moveAndFocus({ state: options.state, collection: options.collection }, direction);
134
+ }));
135
+ return ({ property }) => ({
136
+ role: "toolbar",
137
+ "aria-label": property("label", undefined),
138
+ "aria-orientation": RefSubject.map(options.state, (state) => state.orientation),
139
+ tabindex: Composite.rootTabIndex(options.state),
140
+ onfocus,
141
+ onkeydown,
142
+ ref: options.state,
143
+ });
144
+ }
145
+ /**
146
+ * Renders the toolbar root and moves roving focus through registered items in DOM order.
147
+ *
148
+ * @remarks
149
+ * ## Why
150
+ *
151
+ * The component applies the family behavior while leaving callers free to supply a custom host
152
+ * through the shared DOM boundary.
153
+ *
154
+ * ## Ownership and lifetime
155
+ *
156
+ * The returned Fx installs DOM refs, native listeners, state subscriptions, and optional
157
+ * collection registrations only when rendered. The rendering Scope removes those resources;
158
+ * unrelated nodes and attributes remain caller-owned.
159
+ *
160
+ * ## Example
161
+ *
162
+ * Import with `import { Root } from "@typed/ui/Toolbar";` Extend the [Toolbar.makeState runnable
163
+ * setup](/reference/%40typed%2Fui%2FToolbar%23makeState). Replace the linked program's final
164
+ * snapshot read with `Root({ state, label: "Formatting", content: "Buttons" })`; render that Fx
165
+ * before the same Scope closes.
166
+ * @since 1.0.0
167
+ * @category components
168
+ */
169
+ export function Root(options, host) {
170
+ return Dom.renderHost()(options, host, rootProps(options), options.content, (props, content) => {
171
+ return html `<div ...${props}>${content}</div>`;
172
+ });
173
+ }
174
+ /**
175
+ * Consumer-facing alias of the canonical Toolbar component with identical behavior and lifetime.
176
+ *
177
+ * @remarks
178
+ * ## Why
179
+ *
180
+ * The component applies the family behavior while leaving callers free to supply a custom host
181
+ * through the shared DOM boundary.
182
+ *
183
+ * ## Ownership and lifetime
184
+ *
185
+ * The alias acquires nothing. Rendering it has exactly the canonical component's Scope and DOM
186
+ * ownership contract.
187
+ *
188
+ * ## Example
189
+ *
190
+ * Import with `import { Toolbar } from "@typed/ui/Toolbar";` Extend the [Toolbar.makeState runnable
191
+ * setup](/reference/%40typed%2Fui%2FToolbar%23makeState). Replace the linked program's final
192
+ * snapshot read with `Toolbar({ state, label: "Formatting", content: "Buttons" })`; render that Fx
193
+ * before the same Scope closes.
194
+ * @since 1.0.0
195
+ * @category components
196
+ */
197
+ export const Toolbar = Root;
198
+ function itemProps(options) {
199
+ const activate = options.disabled === true
200
+ ? Effect.void
201
+ : RefSubject.update(options.state, (state) => ({ ...state, activeId: options.id }));
202
+ const register = options.collection === undefined
203
+ ? undefined
204
+ : Collection.ref(options.collection, {
205
+ id: options.id,
206
+ value: options.id,
207
+ textValue: options.textValue ?? options.id,
208
+ disabled: options.disabled,
209
+ });
210
+ return () => ({
211
+ id: options.id,
212
+ role: "button",
213
+ "aria-disabled": options.disabled ?? false,
214
+ tabindex: Composite.tabIndex(options.state, options.id),
215
+ onfocus: activate,
216
+ ref: Dom.composeRefs(register, options.ref),
217
+ });
218
+ }
219
+ /**
220
+ * Renders and optionally registers a toolbar button; focus activates it unless disabled.
221
+ *
222
+ * @remarks
223
+ * ## Why
224
+ *
225
+ * The component applies the family behavior while leaving callers free to supply a custom host
226
+ * through the shared DOM boundary.
227
+ *
228
+ * ## Ownership and lifetime
229
+ *
230
+ * The returned Fx installs DOM refs, native listeners, state subscriptions, and optional
231
+ * collection registrations only when rendered. The rendering Scope removes those resources;
232
+ * unrelated nodes and attributes remain caller-owned.
233
+ *
234
+ * ## Example
235
+ *
236
+ * Import with `import { Item } from "@typed/ui/Toolbar";` Extend the [Toolbar.makeState runnable
237
+ * setup](/reference/%40typed%2Fui%2FToolbar%23makeState). Replace the linked program's final
238
+ * snapshot read with `Item({ state, id: "bold", content: "Bold" })`; render that Fx before the same
239
+ * Scope closes.
240
+ * @since 1.0.0
241
+ * @category components
242
+ */
243
+ export function Item(options, host) {
244
+ return Dom.renderHost()(options, host, itemProps(options), options.content, (props, content) => html `<div ...${props}>${content}</div>`);
245
+ }