@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,291 @@
1
+ /**
2
+ * RadioGroup keeps a selected value and active id in explicit state. Arrow movement skips disabled
3
+ * registered items, updates selection, and moves focus; each item renders a real radio input with
4
+ * ARIA state.
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 { EventHandler, html, } from "@typed/template";
19
+ import * as Collection from "./Collection.js";
20
+ import * as Composite from "./Composite.js";
21
+ import * as Dom from "./Dom.js";
22
+ /**
23
+ * Effect Schema used by makeState to encode, decode, and hydrate RadioGroup state.
24
+ *
25
+ * @remarks
26
+ * ## Why
27
+ *
28
+ * A public schema makes hydration and serialized state use the same runtime validation as direct
29
+ * construction.
30
+ *
31
+ * ## Ownership and lifetime
32
+ *
33
+ * This declaration is data or schema metadata and acquires no resources.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * import * as Schema from "effect/Schema";
38
+ * import * as RadioGroup from "@typed/ui/RadioGroup";
39
+ *
40
+ * const decodeState = Schema.decodeUnknownEffect(RadioGroup.StateSchema);
41
+ * ```
42
+ * @since 1.0.0
43
+ * @category schemas
44
+ */
45
+ export const StateSchema = Schema.Struct({
46
+ value: Schema.String,
47
+ activeId: Schema.NullOr(Schema.String),
48
+ orientation: Schema.Literals(["vertical"]),
49
+ loop: Schema.Boolean,
50
+ rtl: Schema.Boolean,
51
+ virtualFocus: Schema.Boolean,
52
+ });
53
+ /**
54
+ * Creates hydrated RadioGroup state. The caller supplies value; activeId defaults to that value
55
+ * and loop defaults true.
56
+ *
57
+ * @remarks
58
+ * ## Why
59
+ *
60
+ * State and collection ownership can be composed and tested independently from any renderer.
61
+ *
62
+ * ## Ownership and lifetime
63
+ *
64
+ * The returned Effect creates the RefSubject when run. That state is renderer-independent;
65
+ * collection registrations belong to the separate Scope that runs register or ref, not to state
66
+ * creation.
67
+ *
68
+ * @example
69
+ * ```ts
70
+ * import * as Effect from "effect/Effect";
71
+ * import * as RadioGroup from "@typed/ui/RadioGroup";
72
+ *
73
+ * const program = Effect.scoped(
74
+ * Effect.gen(function* () {
75
+ * const state = yield* RadioGroup.makeState({ value: "email" });
76
+ * const collection = yield* RadioGroup.makeCollection();
77
+ * return { state: yield* state, collection: yield* collection };
78
+ * }),
79
+ * );
80
+ * ```
81
+ * @since 1.0.0
82
+ * @category constructors
83
+ */
84
+ export function makeState(initial) {
85
+ return RefSubject.hydrate(StateSchema, {
86
+ value: initial.value,
87
+ activeId: initial.activeId ?? null,
88
+ orientation: "vertical",
89
+ loop: initial.loop ?? true,
90
+ rtl: false,
91
+ virtualFocus: false,
92
+ });
93
+ }
94
+ /**
95
+ * Creates a scoped Collection for RadioGroup items.
96
+ *
97
+ * @remarks
98
+ * ## Why
99
+ *
100
+ * State and collection ownership can be composed and tested independently from any renderer.
101
+ *
102
+ * ## Ownership and lifetime
103
+ *
104
+ * The returned Effect allocates the RefSubject in the caller's Scope. Each later registration is
105
+ * owned by the Scope that runs register, independently of this construction Effect.
106
+ *
107
+ * @example
108
+ * ```ts
109
+ * import * as Effect from "effect/Effect";
110
+ * import * as RadioGroup from "@typed/ui/RadioGroup";
111
+ *
112
+ * const program = Effect.scoped(
113
+ * Effect.gen(function* () {
114
+ * const collection = yield* RadioGroup.makeCollection();
115
+ * return yield* collection;
116
+ * }),
117
+ * );
118
+ * ```
119
+ * @since 1.0.0
120
+ * @category constructors
121
+ */
122
+ export const makeCollection = Collection.makeState;
123
+ /**
124
+ * Sets selected value and activeId to the same registered radio id.
125
+ *
126
+ * @remarks
127
+ * ## Why
128
+ *
129
+ * The operation exposes RadioGroup's transition directly so callers can compose it in Effect
130
+ * programs and native event handlers.
131
+ *
132
+ * ## Ownership and lifetime
133
+ *
134
+ * The returned Effect performs the update or DOM side effect only when run, preserves the declared
135
+ * error and service channels, and retains no resources after completion.
136
+ *
137
+ * ## Example
138
+ *
139
+ * Import with `import { setValue } from "@typed/ui/RadioGroup";` Extend the [RadioGroup.makeState
140
+ * runnable setup](/reference/%40typed%2Fui%2FRadioGroup%23makeState). Inside the linked Effect
141
+ * program invoke `yield* setValue(state, "phone", "phone")`, then read state to observe the checked
142
+ * value and active roving-focus id update together.
143
+ * @since 1.0.0
144
+ * @category combinators
145
+ */
146
+ export function setValue(state, value, activeId) {
147
+ return RefSubject.update(state, (current) => ({
148
+ ...current,
149
+ value,
150
+ activeId: activeId ?? current.activeId,
151
+ }));
152
+ }
153
+ function move(state, collection, direction) {
154
+ return Effect.gen(function* () {
155
+ const current = yield* state;
156
+ const items = yield* collection;
157
+ const activeId = current.activeId ?? items.find((item) => item.value === current.value)?.id ?? null;
158
+ const nextId = Composite.moveActiveId(items, { ...current, activeId }, direction);
159
+ const item = nextId === null ? undefined : items.find((item) => item.id === nextId);
160
+ if (item?.value === undefined)
161
+ return current;
162
+ const next = yield* setValue(state, item.value, item.id);
163
+ yield* Composite.focusActive({ state, collection });
164
+ return next;
165
+ });
166
+ }
167
+ function rootInternalProps(options) {
168
+ const onkeydown = options.collection === undefined
169
+ ? undefined
170
+ : EventHandler.make(Effect.fn(function* (event) {
171
+ const direction = Composite.keyMove(event, { orientation: "vertical" });
172
+ if (direction === undefined)
173
+ return;
174
+ event.preventDefault();
175
+ yield* move(options.state, options.collection, direction);
176
+ }));
177
+ return ({ property }) => ({
178
+ role: "radiogroup",
179
+ "aria-label": property("label", undefined),
180
+ onkeydown,
181
+ ref: options.state,
182
+ });
183
+ }
184
+ /**
185
+ * Renders the radiogroup and maps Arrow keys to selection and focus movement.
186
+ *
187
+ * @remarks
188
+ * ## Why
189
+ *
190
+ * The component applies the family behavior while leaving callers free to supply a custom host
191
+ * through the shared DOM boundary.
192
+ *
193
+ * ## Ownership and lifetime
194
+ *
195
+ * The returned Fx installs DOM refs, native listeners, state subscriptions, and optional
196
+ * collection registrations only when rendered. The rendering Scope removes those resources;
197
+ * unrelated nodes and attributes remain caller-owned.
198
+ *
199
+ * ## Example
200
+ *
201
+ * Import with `import { Root } from "@typed/ui/RadioGroup";` Extend the [RadioGroup.makeState
202
+ * runnable setup](/reference/%40typed%2Fui%2FRadioGroup%23makeState). Replace the linked program's
203
+ * final snapshot read with `Root({ state, label: "Contact method", content: "Choices" })`; render
204
+ * that Fx before the same Scope closes.
205
+ * @since 1.0.0
206
+ * @category components
207
+ */
208
+ export function Root(options, host) {
209
+ return Dom.renderHost()(options, host, rootInternalProps(options), options.content, (props, content) => {
210
+ return html `<div ...${props}>${content}</div>`;
211
+ });
212
+ }
213
+ function itemInternalProps(options) {
214
+ const checked = RefSubject.map(options.state, (state) => state.value === options.value);
215
+ const register = options.collection === undefined
216
+ ? undefined
217
+ : Collection.ref(options.collection, {
218
+ id: options.id,
219
+ value: options.value,
220
+ textValue: options.value,
221
+ disabled: options.disabled,
222
+ });
223
+ return () => ({
224
+ id: options.id,
225
+ type: "radio",
226
+ role: "radio",
227
+ name: options.name,
228
+ value: options.value,
229
+ "?disabled": options.disabled ?? false,
230
+ "aria-checked": checked,
231
+ "aria-disabled": options.disabled ?? false,
232
+ "?checked": checked,
233
+ ".checked": checked,
234
+ onchange: options.disabled === true
235
+ ? Effect.void
236
+ : setValue(options.state, options.value, options.id),
237
+ ref: Dom.composeRefs(register, options.ref),
238
+ });
239
+ }
240
+ /**
241
+ * Renders and optionally registers a native radio input synchronized with selected value.
242
+ *
243
+ * @remarks
244
+ * ## Why
245
+ *
246
+ * The component applies the family behavior while leaving callers free to supply a custom host
247
+ * through the shared DOM boundary.
248
+ *
249
+ * ## Ownership and lifetime
250
+ *
251
+ * The returned Fx installs DOM refs, native listeners, state subscriptions, and optional
252
+ * collection registrations only when rendered. The rendering Scope removes those resources;
253
+ * unrelated nodes and attributes remain caller-owned.
254
+ *
255
+ * ## Example
256
+ *
257
+ * Import with `import { Item } from "@typed/ui/RadioGroup";` Extend the [RadioGroup.makeState
258
+ * runnable setup](/reference/%40typed%2Fui%2FRadioGroup%23makeState). Replace the linked program's
259
+ * final snapshot read with `Item({ state, id: "email", value: "email", name: "contact" })`; render
260
+ * that Fx before the same Scope closes.
261
+ * @since 1.0.0
262
+ * @category components
263
+ */
264
+ export function Item(options, host) {
265
+ return Dom.renderHost()(options, host, itemInternalProps(options), "", (props) => html `<input ...${props} />`);
266
+ }
267
+ /**
268
+ * Consumer-facing alias of the canonical RadioGroup component with identical behavior and
269
+ * lifetime.
270
+ *
271
+ * @remarks
272
+ * ## Why
273
+ *
274
+ * The component applies the family behavior while leaving callers free to supply a custom host
275
+ * through the shared DOM boundary.
276
+ *
277
+ * ## Ownership and lifetime
278
+ *
279
+ * The alias acquires nothing. Rendering it has exactly the canonical component's Scope and DOM
280
+ * ownership contract.
281
+ *
282
+ * ## Example
283
+ *
284
+ * Import with `import { RadioGroup } from "@typed/ui/RadioGroup";` Extend the [RadioGroup.makeState
285
+ * runnable setup](/reference/%40typed%2Fui%2FRadioGroup%23makeState). Replace the linked program's
286
+ * final snapshot read with `RadioGroup({ state, label: "Contact method", content: "Choices" })`;
287
+ * render that Fx before the same Scope closes.
288
+ * @since 1.0.0
289
+ * @category components
290
+ */
291
+ export const RadioGroup = Root;
package/dist/Role.d.ts ADDED
@@ -0,0 +1,64 @@
1
+ import type * as Scope from "effect/Scope";
2
+ import type { Fx } from "@typed/fx/Fx";
3
+ import { type Renderable, type RenderEvent, type RenderTemplate } from "@typed/template";
4
+ import * as Dom from "./Dom.js";
5
+ import type { HostResult } from "./Dom/Types.js";
6
+ /**
7
+ * Options for assigning explicit ARIA semantics to a generic host.
8
+ * @remarks
9
+ * ## Why
10
+ * This primitive keeps role selection visible when no dedicated component
11
+ * matches the required semantic.
12
+ * ## Ownership and lifetime
13
+ * The model acquires no resources; dynamic values follow the rendered Scope.
14
+ * @since 1.0.0
15
+ * @category models
16
+ */
17
+ export interface RoleOptions extends Dom.HostOptions<HTMLDivElement> {
18
+ /** Content rendered inside the semantic host.
19
+ * @remarks
20
+ * ## Why
21
+ * Native content remains available to the accessibility tree.
22
+ * ## Ownership and lifetime
23
+ * Dynamic content follows the component Scope.
24
+ * @since 1.0.0
25
+ * @category content
26
+ */
27
+ readonly content: Renderable.Any;
28
+ /** The explicit ARIA role.
29
+ * @remarks
30
+ * ## Why
31
+ * Callers must choose semantics appropriate to their interaction model.
32
+ * ## Ownership and lifetime
33
+ * The reflected value retains no resources.
34
+ * @since 1.0.0
35
+ * @category accessibility
36
+ */
37
+ readonly role: Renderable.Any<string | null | undefined>;
38
+ }
39
+ declare function internalProps<const Options extends RoleOptions>({ property, }: Dom.InternalPropsHelpers<Options>): {
40
+ role: Exclude<Dom.Property<Options, "role">, Dom.Nullish> | undefined;
41
+ };
42
+ type RoleInternalProps<Options extends RoleOptions> = ReturnType<typeof internalProps<Options>>;
43
+ /**
44
+ * Renders a generic element with caller-selected ARIA semantics.
45
+ * @remarks
46
+ * ## Why
47
+ * It provides cooperative host composition without pretending every ARIA role
48
+ * has identical keyboard behavior; the caller remains responsible for the
49
+ * chosen role's complete accessibility contract.
50
+ * ## Ownership and lifetime
51
+ * Running the returned Fx owns dynamic attributes and content until its Effect
52
+ * Scope closes. A custom host must preserve the supplied role.
53
+ * @example
54
+ * ```ts
55
+ * import { Role } from "@typed/ui/Role"
56
+ *
57
+ * const status = Role({ role: "status", content: "Ready" })
58
+ * ```
59
+ * @since 1.0.0
60
+ * @category components
61
+ */
62
+ export declare function Role<const Options extends RoleOptions, const Host extends HostResult = never>(options: Options, host?: Dom.HostOverride<Dom.RenderHostProps<Options, RoleInternalProps<Options>>, Options["content"], Host>): Fx<RenderEvent, Renderable.Error<Options | Host>, Renderable.Services<Options | Host> | Scope.Scope | RenderTemplate>;
63
+ export {};
64
+ //# sourceMappingURL=Role.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Role.d.ts","sourceRoot":"","sources":["../src/Role.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAQ,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC/F,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAChC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,WAAY,SAAQ,GAAG,CAAC,WAAW,CAAC,cAAc,CAAC;IAClE;;;;;;;;OAQG;IACH,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC;IACjC;;;;;;;;OAQG;IACH,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;CAC1D;AAED,iBAAS,aAAa,CAAC,KAAK,CAAC,OAAO,SAAS,WAAW,EAAE,EACxD,QAAQ,GACT,EAAE,GAAG,CAAC,oBAAoB,CAAC,OAAO,CAAC;IACzB,IAAI;EACd;AAED,KAAK,iBAAiB,CAAC,OAAO,SAAS,WAAW,IAAI,UAAU,CAAC,OAAO,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;AAEhG;;;;;;;;;;;;;;;;;;GAkBG;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,iBAAiB,CAAC,OAAO,CAAC,CAAC,EACxD,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"}
package/dist/Role.js ADDED
@@ -0,0 +1,27 @@
1
+ import { html } from "@typed/template";
2
+ import * as Dom from "./Dom.js";
3
+ function internalProps({ property, }) {
4
+ return { role: property("role", undefined) };
5
+ }
6
+ /**
7
+ * Renders a generic element with caller-selected ARIA semantics.
8
+ * @remarks
9
+ * ## Why
10
+ * It provides cooperative host composition without pretending every ARIA role
11
+ * has identical keyboard behavior; the caller remains responsible for the
12
+ * chosen role's complete accessibility contract.
13
+ * ## Ownership and lifetime
14
+ * Running the returned Fx owns dynamic attributes and content until its Effect
15
+ * Scope closes. A custom host must preserve the supplied role.
16
+ * @example
17
+ * ```ts
18
+ * import { Role } from "@typed/ui/Role"
19
+ *
20
+ * const status = Role({ role: "status", content: "Ready" })
21
+ * ```
22
+ * @since 1.0.0
23
+ * @category components
24
+ */
25
+ export function Role(options, host) {
26
+ return Dom.renderHost()(options, host, internalProps, options.content, (props, content) => html `<div ...${props}>${content}</div>`);
27
+ }