@foldkit/ui 0.141.1 → 0.142.0

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 (39) hide show
  1. package/README.md +2 -2
  2. package/dist/checkbox/index.d.ts +4 -0
  3. package/dist/checkbox/index.d.ts.map +1 -1
  4. package/dist/combobox/shared.d.ts.map +1 -1
  5. package/dist/combobox/shared.js +71 -73
  6. package/dist/datePicker/index.d.ts.map +1 -1
  7. package/dist/datePicker/index.js +76 -89
  8. package/dist/dialog/index.d.ts.map +1 -1
  9. package/dist/dialog/index.js +27 -29
  10. package/dist/listbox/multi.d.ts +2 -0
  11. package/dist/listbox/multi.d.ts.map +1 -1
  12. package/dist/listbox/public.d.ts +1 -1
  13. package/dist/listbox/public.d.ts.map +1 -1
  14. package/dist/listbox/public.js +1 -1
  15. package/dist/listbox/shared.d.ts +20 -0
  16. package/dist/listbox/shared.d.ts.map +1 -1
  17. package/dist/listbox/shared.js +83 -64
  18. package/dist/listbox/single.d.ts +2 -0
  19. package/dist/listbox/single.d.ts.map +1 -1
  20. package/dist/menu/index.d.ts.map +1 -1
  21. package/dist/menu/index.js +53 -55
  22. package/dist/popover/index.d.ts.map +1 -1
  23. package/dist/popover/index.js +33 -35
  24. package/dist/radioGroup/index.d.ts +137 -51
  25. package/dist/radioGroup/index.d.ts.map +1 -1
  26. package/dist/radioGroup/index.js +149 -60
  27. package/dist/radioGroup/public.d.ts +2 -2
  28. package/dist/radioGroup/public.d.ts.map +1 -1
  29. package/dist/radioGroup/public.js +1 -1
  30. package/dist/slider/index.d.ts +28 -0
  31. package/dist/slider/index.d.ts.map +1 -1
  32. package/dist/slider/index.js +11 -8
  33. package/dist/switch/index.d.ts +4 -0
  34. package/dist/switch/index.d.ts.map +1 -1
  35. package/dist/test/apps/disabledButton.d.ts.map +1 -1
  36. package/dist/test/apps/disabledButton.js +16 -10
  37. package/dist/toast/update.d.ts.map +1 -1
  38. package/dist/toast/update.js +44 -50
  39. package/package.json +6 -6
@@ -1,93 +1,179 @@
1
- import { Option, Schema as S } from 'effect';
2
- import type { Attribute, Html, HtmlBuilder } from 'foldkit/html';
1
+ import { Effect, Option, Schema as S } from 'effect';
2
+ import * as Command from 'foldkit/command';
3
+ import { type ChildAttribute, type Html } from 'foldkit/html';
4
+ import { type View as SubmodelView } from 'foldkit/submodel';
3
5
  /** Controls the radio group layout direction and which arrow keys navigate between options. */
4
6
  export declare const Orientation: S.Literals<readonly ["Horizontal", "Vertical"]>;
5
7
  export type Orientation = typeof Orientation.Type;
8
+ /** Schema for the radio group's private interaction state. The selected
9
+ * option is owned by the parent and passed in via `ViewInputs.selectedValue`,
10
+ * so it is not stored here. `maybeFocusedIndex` is the roving-tabindex
11
+ * cursor: `None` means keyboard focus follows the selection, and a read-only
12
+ * group stores `Some(index)` while focus diverges from it. */
13
+ export declare const Model: S.Struct<{
14
+ readonly id: S.String;
15
+ readonly maybeFocusedIndex: S.Option<S.Number>;
16
+ }>;
17
+ export type Model = typeof Model.Type;
18
+ /** Sent when an option is committed via click or keyboard. Commits the option
19
+ * as the new selection and moves focus onto it. */
20
+ export declare const SelectedOption: import("foldkit/schema").CallableTaggedStruct<"SelectedOption", {
21
+ index: S.Number;
22
+ value: S.String;
23
+ }>;
24
+ /** Sent when an option receives keyboard focus without being committed, which
25
+ * is how a read-only group navigates. */
26
+ export declare const FocusedOption: import("foldkit/schema").CallableTaggedStruct<"FocusedOption", {
27
+ index: S.Number;
28
+ }>;
29
+ /** Sent when the focus-option command completes. */
30
+ export declare const CompletedFocusOption: import("foldkit/schema").CallableTaggedStruct<"CompletedFocusOption", {}>;
31
+ /** Union of all messages the radio group can produce. */
32
+ export declare const Message: S.Union<[
33
+ typeof SelectedOption,
34
+ typeof FocusedOption,
35
+ typeof CompletedFocusOption
36
+ ]>;
37
+ export type SelectedOption = typeof SelectedOption.Type;
38
+ export type FocusedOption = typeof FocusedOption.Type;
39
+ export type Message = typeof Message.Type;
40
+ /** Sent to the parent when an option is committed via click or keyboard. Carries both the option's value (typed as `Value` via `RadioGroup.create<Value>()`) and its index. Generic at the type level; the schema stores `value: string` and the factory's fenced cast types it as `Value`. */
41
+ export declare const Selected: import("foldkit/schema").CallableTaggedStruct<"Selected", {
42
+ value: S.String;
43
+ index: S.Number;
44
+ }>;
45
+ export type Selected<Value extends string = string> = Readonly<{
46
+ readonly _tag: 'Selected';
47
+ readonly value: Value;
48
+ readonly index: number;
49
+ }>;
50
+ /** Union of out-messages the radio group can produce. Surfaced as the third element of `update`'s return tuple and pattern-matched by the parent. */
51
+ export declare const OutMessage: S.Union<readonly [import("foldkit/schema").CallableTaggedStruct<"Selected", {
52
+ value: S.String;
53
+ index: S.Number;
54
+ }>]>;
55
+ /** Generic over `Value extends string` so consumers using
56
+ * `RadioGroup.create<MyUnion>()` receive `value: MyUnion` in the
57
+ * `Selected` OutMessage. Defaults to `string`. */
58
+ export type OutMessage<Value extends string = string> = Selected<Value>;
59
+ /** Configuration for creating a radio group model with `init`. */
60
+ export type InitConfig = Readonly<{
61
+ id: string;
62
+ }>;
63
+ /** Creates an initial radio group model from a config. Focus follows the
64
+ * selected option until the user navigates a read-only group, so
65
+ * `maybeFocusedIndex` starts `None`. */
66
+ export declare const init: (config: InitConfig) => Model;
67
+ /** Moves focus to the option at the given index. */
68
+ export declare const FocusOption: Command.CommandDefinitionWithArgs<"FocusOption", {
69
+ id: S.String;
70
+ index: S.Number;
71
+ }, Effect.Effect<{
72
+ readonly _tag: "CompletedFocusOption";
73
+ }, never, never>>;
74
+ type UpdateReturn = readonly [
75
+ Model,
76
+ ReadonlyArray<Command.Command<Message>>,
77
+ Option.Option<OutMessage>
78
+ ];
79
+ /** Processes a radio group message and returns the next model, commands, and
80
+ * an optional OutMessage. `Selected` fires when an option is committed via
81
+ * click or keyboard; the parent stores the new value and passes it back in as
82
+ * `selectedValue`. */
83
+ export declare const update: (model: Model, message: Message) => UpdateReturn;
6
84
  /** Per-option render info passed to the consumer's `toView`. The consumer
7
85
  * spreads `option`, `label`, and `description` onto whichever elements carry
8
86
  * that role in their layout. Generic over `Value extends string` so
9
- * `option.value` carries the consumer's union type, and over `Message`
10
- * so the attribute bundles dispatch the parent's own Message.
87
+ * `option.value` carries the consumer's union type.
11
88
  *
12
89
  * The `option` bundle sets `type="button"` so that rendering the option as a
13
90
  * `button` element inside a `form` element selects without also submitting the
14
91
  * form. Setting it is harmless on the other elements an option might use, such
15
92
  * as a `div` or a `span`, because the builder assigns a DOM property rather
16
93
  * than an HTML attribute. Spread a later `h.Type` to override it. */
17
- export type OptionInfo<Value extends string, Message> = Readonly<{
94
+ export type OptionInfo<Value extends string = string> = Readonly<{
18
95
  value: Value;
19
96
  index: number;
20
97
  isSelected: boolean;
21
98
  isActive: boolean;
22
99
  isDisabled: boolean;
23
- option: ReadonlyArray<Attribute<Message>>;
24
- label: ReadonlyArray<Attribute<Message>>;
25
- description: ReadonlyArray<Attribute<Message>>;
100
+ isReadOnly: boolean;
101
+ option: ReadonlyArray<ChildAttribute>;
102
+ label: ReadonlyArray<ChildAttribute>;
103
+ description: ReadonlyArray<ChildAttribute>;
26
104
  }>;
27
105
  /** Render-time payload published to the consumer's `toView`.
28
106
  *
29
107
  * - `group`: ARIA + role attributes for the wrapping radiogroup element.
30
- * - `options`: one entry per option in `options`, in the same order. Includes
31
- * the value, derived state, and the attribute bundles for the option
32
- * element, its label, and its description.
108
+ * - `options`: one entry per option in `viewInputs.options`, in the same
109
+ * order. Includes the value, derived state, and the attribute bundles for
110
+ * the option element, its label, and its description.
33
111
  * - `selectedValue`: the currently-selected value, if any. Convenient for the
34
112
  * consumer when rendering selected-state visuals next to the option
35
113
  * attributes.
36
114
  * - `hiddenInput`: when `name` was supplied, attributes for a hidden form
37
115
  * input carrying the selected value. The consumer renders the `<input>`
38
116
  * themselves. Empty array when `name` is undefined. */
39
- export type RenderInfo<Value extends string, Message> = Readonly<{
40
- group: ReadonlyArray<Attribute<Message>>;
41
- options: ReadonlyArray<OptionInfo<Value, Message>>;
117
+ export type RenderInfo<Value extends string = string> = Readonly<{
118
+ group: ReadonlyArray<ChildAttribute>;
119
+ options: ReadonlyArray<OptionInfo<Value>>;
42
120
  selectedValue: Option.Option<Value>;
43
- hiddenInput: ReadonlyArray<Attribute<Message>>;
121
+ hiddenInput: ReadonlyArray<ChildAttribute>;
44
122
  }>;
45
- /** Per-render view configuration for the stateless controlled {@link view}.
46
- * Generic over `Value extends string` (the option union) and `Message`
47
- * (the message `onSelect` dispatches).
123
+ /** Per-render view inputs passed to `view` via `h.submodel`'s `viewInputs`
124
+ * field. Generic over `Value extends string` so consumers using
125
+ * `RadioGroup.create<MyUnion>()` receive `option.value: MyUnion` in `toView`
126
+ * and `(value: MyUnion, index) => boolean` in `isOptionDisabled`, without
127
+ * casting.
48
128
  *
49
129
  * - `selectedValue`: the current selection, read straight from the parent
50
- * Model. The roving tabindex and checked state derive from it.
51
- * - `onSelect`: dispatched with the chosen value when an option is clicked or
52
- * navigated to. Handle it in the parent's `update` by storing the value.
53
- * The radio group manages focus itself, so the handler needs to do nothing
54
- * else.
55
- * - `toView`: receives the {@link RenderInfo} and lays out the group. */
56
- export type ViewConfig<Value extends string, Message> = Readonly<{
57
- id: string;
58
- selectedValue: Option.Option<Value>;
130
+ * Model. `aria-checked` and the `data-checked` marker derive from it, as
131
+ * does the roving tabindex whenever keyboard focus has not diverged.
132
+ * - `isReadOnly`: keeps the group navigable but not selectable. Arrow, Home,
133
+ * End, PageUp, and PageDown still move focus, and the group reports that
134
+ * focus through `FocusedOption`, so `data-active` and `tabindex` follow it.
135
+ * Space and clicking do nothing. */
136
+ export type ViewInputs<Value extends string = string> = Readonly<{
59
137
  options: ReadonlyArray<Value>;
60
- onSelect: (value: Value) => Message;
138
+ selectedValue: Option.Option<Value>;
61
139
  ariaLabel: string;
62
- toView: (render: RenderInfo<Value, Message>) => Html;
140
+ toView: (render: RenderInfo<Value>) => Html;
63
141
  orientation?: Orientation;
64
142
  isOptionDisabled?: (value: Value, index: number) => boolean;
65
143
  isDisabled?: boolean;
144
+ isReadOnly?: boolean;
66
145
  name?: string;
67
146
  }>;
68
- /** Renders an accessible radio group as a stateless controlled component. The
69
- * parent owns the selection (`selectedValue`) and receives the parent's own
70
- * Message via `onSelect` when an option is chosen. Moving focus onto the
71
- * newly-active option is the radio group's own concern: it happens inside the
72
- * component's click and keydown handlers, so the parent's `update` only stores
73
- * the value.
147
+ /** The `view` and `update` pair that `RadioGroup.create` returns, bound to one
148
+ * `Value` type. Name it to annotate a value that holds a created bundle,
149
+ * such as a field on a config object or a function parameter that takes
150
+ * the bundle rather than calling `create` itself. */
151
+ export type Bundle<Value extends string = string> = Readonly<{
152
+ view: SubmodelView<Model, Message, ViewInputs<Value>>;
153
+ update: (model: Model, message: Message) => readonly [
154
+ Model,
155
+ ReadonlyArray<Command.Command<Message>>,
156
+ Option.Option<OutMessage<Value>>
157
+ ];
158
+ }>;
159
+ /** Pairs the radio group `view` and `update` behind a single Value-typed
160
+ * entry point. Declare once at module scope so consumers receive
161
+ * `option.value: Value` in `toView` and the `Selected` OutMessage without an
162
+ * `as` cast:
74
163
  *
75
164
  * ```ts
76
- * // In view:
77
- * RadioGroup.view(
78
- * {
79
- * id: TOOL_RADIO_GROUP_ID,
80
- * selectedValue: Option.some(model.tool),
81
- * options: TOOLS,
82
- * ariaLabel: 'Tool',
83
- * onSelect: tool => SelectedTool({ tool }),
84
- * toView: ({ group, options }) => ...,
85
- * },
86
- * h,
87
- * )
165
+ * const PlanRadioGroup = RadioGroup.create<Plan>()
166
+ *
167
+ * // In view (selectedValue is the parent-owned selection):
168
+ * h.submodel({ view: PlanRadioGroup.view, viewInputs: { selectedValue, ... }, ... })
169
+ *
170
+ * // In update, fold the Selected OutMessage into your Model:
171
+ * const [next, commands, maybeOutMessage] = PlanRadioGroup.update(model, message)
172
+ * ```
88
173
  *
89
- * // In update:
90
- * SelectedTool: ({ tool }) => [evo(model, { tool: () => tool }), []],
91
- * ``` */
92
- export declare const view: <Value extends string, Message>(config: ViewConfig<Value, Message>, h: HtmlBuilder<Message>) => Html;
174
+ * The internal view stays typed `ReadonlyArray<string>`; consumers can
175
+ * pass a `ReadonlyArray<MyUnion>` (assignable) and the fenced cast inside
176
+ * `create` types `OptionInfo.value` as `MyUnion`. */
177
+ export declare const create: <Value extends string = string>() => Bundle<Value>;
178
+ export {};
93
179
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/radioGroup/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,MAAM,EAEN,MAAM,IAAI,CAAC,EAGZ,MAAM,QAAQ,CAAA;AACf,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAOhE,+FAA+F;AAC/F,eAAO,MAAM,WAAW,iDAAyC,CAAA;AACjE,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,IAAI,CAAA;AAYjD;;;;;;;;;;sEAUsE;AACtE,MAAM,MAAM,UAAU,CAAC,KAAK,SAAS,MAAM,EAAE,OAAO,IAAI,QAAQ,CAAC;IAC/D,KAAK,EAAE,KAAK,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,OAAO,CAAA;IACnB,QAAQ,EAAE,OAAO,CAAA;IACjB,UAAU,EAAE,OAAO,CAAA;IACnB,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;IACzC,KAAK,EAAE,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;IACxC,WAAW,EAAE,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;CAC/C,CAAC,CAAA;AAEF;;;;;;;;;;;0DAW0D;AAC1D,MAAM,MAAM,UAAU,CAAC,KAAK,SAAS,MAAM,EAAE,OAAO,IAAI,QAAQ,CAAC;IAC/D,KAAK,EAAE,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;IACxC,OAAO,EAAE,aAAa,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAA;IAClD,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACnC,WAAW,EAAE,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;CAC/C,CAAC,CAAA;AAEF;;;;;;;;;;0EAU0E;AAC1E,MAAM,MAAM,UAAU,CAAC,KAAK,SAAS,MAAM,EAAE,OAAO,IAAI,QAAQ,CAAC;IAC/D,EAAE,EAAE,MAAM,CAAA;IACV,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACnC,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,CAAA;IAC7B,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAA;IACnC,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACpD,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAA;IAC3D,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAC,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;;UAuBU;AACV,eAAO,MAAM,IAAI,GAAI,KAAK,SAAS,MAAM,EAAE,OAAO,EAChD,QAAQ,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,EAClC,GAAG,WAAW,CAAC,OAAO,CAAC,KACtB,IAkLF,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/radioGroup/index.ts"],"names":[],"mappings":"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"}
@@ -1,40 +1,84 @@
1
1
  import { brandViewResult as __foldkitBrandViewResult } from 'foldkit/brand'
2
- import { Array, Match as M, Option, Predicate, Schema as S, String, pipe, } from 'effect';
2
+ import { Array, Effect, Match as M, Option, Predicate, Schema as S, String, pipe, } from 'effect';
3
+ import * as Command from 'foldkit/command';
4
+ import * as Dom from 'foldkit/dom';
5
+ import { childAttributes } from 'foldkit/html';
6
+ import { m } from 'foldkit/message';
7
+ import { evo } from 'foldkit/struct';
8
+ import { defineView } from 'foldkit/submodel';
3
9
  import { idSelector } from '../internal/selectors.js';
4
10
  import { keyToIndex } from '../keyboard.js';
5
11
  // MODEL
6
12
  /** Controls the radio group layout direction and which arrow keys navigate between options. */
7
13
  export const Orientation = S.Literals(['Horizontal', 'Vertical']);
8
- // VIEW
14
+ /** Schema for the radio group's private interaction state. The selected
15
+ * option is owned by the parent and passed in via `ViewInputs.selectedValue`,
16
+ * so it is not stored here. `maybeFocusedIndex` is the roving-tabindex
17
+ * cursor: `None` means keyboard focus follows the selection, and a read-only
18
+ * group stores `Some(index)` while focus diverges from it. */
19
+ export const Model = S.Struct({
20
+ id: S.String,
21
+ maybeFocusedIndex: S.Option(S.Number),
22
+ });
23
+ // MESSAGE
24
+ /** Sent when an option is committed via click or keyboard. Commits the option
25
+ * as the new selection and moves focus onto it. */
26
+ export const SelectedOption = m('SelectedOption', {
27
+ index: S.Number,
28
+ value: S.String,
29
+ });
30
+ /** Sent when an option receives keyboard focus without being committed, which
31
+ * is how a read-only group navigates. */
32
+ export const FocusedOption = m('FocusedOption', { index: S.Number });
33
+ /** Sent when the focus-option command completes. */
34
+ export const CompletedFocusOption = m('CompletedFocusOption');
35
+ /** Union of all messages the radio group can produce. */
36
+ export const Message = S.Union([SelectedOption, FocusedOption, CompletedFocusOption]);
37
+ // OUT MESSAGE
38
+ /** Sent to the parent when an option is committed via click or keyboard. Carries both the option's value (typed as `Value` via `RadioGroup.create<Value>()`) and its index. Generic at the type level; the schema stores `value: string` and the factory's fenced cast types it as `Value`. */
39
+ export const Selected = m('Selected', {
40
+ value: S.String,
41
+ index: S.Number,
42
+ });
43
+ /** Union of out-messages the radio group can produce. Surfaced as the third element of `update`'s return tuple and pattern-matched by the parent. */
44
+ export const OutMessage = S.Union([Selected]);
45
+ /** Creates an initial radio group model from a config. Focus follows the
46
+ * selected option until the user navigates a read-only group, so
47
+ * `maybeFocusedIndex` starts `None`. */
48
+ export const init = (config) => (__foldkitBrandViewResult(({
49
+ id: config.id,
50
+ maybeFocusedIndex: Option.none(),
51
+ }), "@foldkit/ui/radioGroup/index.js#init"));
52
+ // UPDATE
9
53
  const optionId = (id, index) => __foldkitBrandViewResult((`${id}-option-${index}`), "@foldkit/ui/radioGroup/index.js#optionId");
10
54
  const labelId = (id, index) => __foldkitBrandViewResult((`${id}-option-${index}-label`), "@foldkit/ui/radioGroup/index.js#labelId");
11
55
  const descriptionId = (id, index) => __foldkitBrandViewResult((`${id}-option-${index}-description`), "@foldkit/ui/radioGroup/index.js#descriptionId");
12
- /** Renders an accessible radio group as a stateless controlled component. The
13
- * parent owns the selection (`selectedValue`) and receives the parent's own
14
- * Message via `onSelect` when an option is chosen. Moving focus onto the
15
- * newly-active option is the radio group's own concern: it happens inside the
16
- * component's click and keydown handlers, so the parent's `update` only stores
17
- * the value.
18
- *
19
- * ```ts
20
- * // In view:
21
- * RadioGroup.view(
22
- * {
23
- * id: TOOL_RADIO_GROUP_ID,
24
- * selectedValue: Option.some(model.tool),
25
- * options: TOOLS,
26
- * ariaLabel: 'Tool',
27
- * onSelect: tool => SelectedTool({ tool }),
28
- * toView: ({ group, options }) => ...,
29
- * },
30
- * h,
31
- * )
32
- *
33
- * // In update:
34
- * SelectedTool: ({ tool }) => [evo(model, { tool: () => tool }), []],
35
- * ``` */
36
- export const view = (config, h) => {
37
- const { id, selectedValue, options, onSelect, ariaLabel, toView, orientation = 'Vertical', isOptionDisabled: isOptionDisabledFn, isDisabled: isGroupDisabled = false, name, } = config;
56
+ /** Moves focus to the option at the given index. */
57
+ export const FocusOption = Command.define('FocusOption', {
58
+ args: { id: S.String, index: S.Number },
59
+ messages: [CompletedFocusOption],
60
+ execute: ({ id, index }) => __foldkitBrandViewResult((Dom.focus(idSelector(optionId(id, index))).pipe(Effect.ignore, Effect.as(CompletedFocusOption()))), "@foldkit/ui/radioGroup/index.js#execute"),
61
+ });
62
+ /** Processes a radio group message and returns the next model, commands, and
63
+ * an optional OutMessage. `Selected` fires when an option is committed via
64
+ * click or keyboard; the parent stores the new value and passes it back in as
65
+ * `selectedValue`. */
66
+ export const update = (model, message) => __foldkitBrandViewResult((M.value(message).pipe(M.withReturnType(), M.tagsExhaustive({
67
+ SelectedOption: ({ index, value }) => __foldkitBrandViewResult(([
68
+ evo(model, { maybeFocusedIndex: () => __foldkitBrandViewResult((Option.none()), "@foldkit/ui/radioGroup/index.js#maybeFocusedIndex") }),
69
+ [FocusOption({ id: model.id, index })],
70
+ Option.some(Selected({ value, index })),
71
+ ]), "@foldkit/ui/radioGroup/index.js#SelectedOption"),
72
+ FocusedOption: ({ index }) => __foldkitBrandViewResult(([
73
+ evo(model, { maybeFocusedIndex: () => __foldkitBrandViewResult((Option.some(index)), "@foldkit/ui/radioGroup/index.js#maybeFocusedIndex~2") }),
74
+ [FocusOption({ id: model.id, index })],
75
+ Option.none(),
76
+ ]), "@foldkit/ui/radioGroup/index.js#FocusedOption"),
77
+ CompletedFocusOption: () => __foldkitBrandViewResult(([model, [], Option.none()]), "@foldkit/ui/radioGroup/index.js#CompletedFocusOption"),
78
+ }))), "@foldkit/ui/radioGroup/index.js#update");
79
+ const internalView = defineView((model, viewInputs, h) => {
80
+ const { id, maybeFocusedIndex } = model;
81
+ const { options, selectedValue, ariaLabel, toView, orientation = 'Vertical', isOptionDisabled: isOptionDisabledFn, isDisabled: isGroupDisabled = false, isReadOnly = false, name, } = viewInputs;
38
82
  const isDisabled = (index) => {
39
83
  if (isGroupDisabled) {
40
84
  return __foldkitBrandViewResult((true), "@foldkit/ui/radioGroup/index.js#isDisabled");
@@ -42,40 +86,55 @@ export const view = (config, h) => {
42
86
  if (!isOptionDisabledFn) {
43
87
  return __foldkitBrandViewResult((false), "@foldkit/ui/radioGroup/index.js#isDisabled");
44
88
  }
45
- return __foldkitBrandViewResult((pipe(options, Array.get(index), Option.exists(option => __foldkitBrandViewResult((isOptionDisabledFn(option, index)), "@foldkit/ui/radioGroup/index.js#anonymous")))), "@foldkit/ui/radioGroup/index.js#isDisabled");
89
+ return __foldkitBrandViewResult((pipe(options, Array.get(index), Option.exists(option => __foldkitBrandViewResult((isOptionDisabledFn(option, index)), "@foldkit/ui/radioGroup/index.js#anonymous~2")))), "@foldkit/ui/radioGroup/index.js#isDisabled");
46
90
  };
47
- const selectedIndex = Option.flatMap(selectedValue, value => __foldkitBrandViewResult((Array.findFirstIndex(options, option => __foldkitBrandViewResult((option === value), "@foldkit/ui/radioGroup/index.js#anonymous~3"))), "@foldkit/ui/radioGroup/index.js#anonymous~2"));
48
- const firstEnabledIndex = pipe(options.length, Array.makeBy(index => __foldkitBrandViewResult((index), "@foldkit/ui/radioGroup/index.js#anonymous~4")), Array.findFirst(Predicate.not(isDisabled)), Option.getOrElse(() => __foldkitBrandViewResult((0), "@foldkit/ui/radioGroup/index.js#anonymous~5")));
91
+ const selectedIndex = Option.flatMap(selectedValue, value => __foldkitBrandViewResult((Array.findFirstIndex(options, option => __foldkitBrandViewResult((option === value), "@foldkit/ui/radioGroup/index.js#anonymous~4"))), "@foldkit/ui/radioGroup/index.js#anonymous~3"));
92
+ const firstEnabledIndex = pipe(options.length, Array.makeBy(index => __foldkitBrandViewResult((index), "@foldkit/ui/radioGroup/index.js#anonymous~5")), Array.findFirst(Predicate.not(isDisabled)), Option.getOrElse(() => __foldkitBrandViewResult((0), "@foldkit/ui/radioGroup/index.js#anonymous~6")));
49
93
  // NOTE: The selected index only becomes the roving tab stop when it is
50
94
  // enabled. A disabled selected option would otherwise be the group's sole
51
95
  // tab stop with no keydown handler, stranding keyboard navigation.
52
- const focusedIndex = pipe(selectedIndex, Option.filter(Predicate.not(isDisabled)), Option.getOrElse(() => __foldkitBrandViewResult((firstEnabledIndex), "@foldkit/ui/radioGroup/index.js#anonymous~6")));
96
+ const selectionTabStopIndex = pipe(selectedIndex, Option.filter(Predicate.not(isDisabled)), Option.getOrElse(() => __foldkitBrandViewResult((firstEnabledIndex), "@foldkit/ui/radioGroup/index.js#anonymous~7")));
97
+ const isNavigableIndex = (index) => __foldkitBrandViewResult((index < options.length && !isDisabled(index)), "@foldkit/ui/radioGroup/index.js#isNavigableIndex");
98
+ const focusedIndex = pipe(maybeFocusedIndex, Option.filter(isNavigableIndex), Option.getOrElse(() => __foldkitBrandViewResult((selectionTabStopIndex), "@foldkit/ui/radioGroup/index.js#anonymous~8")));
53
99
  const { nextKey, previousKey } = M.value(orientation).pipe(M.when('Horizontal', () => (__foldkitBrandViewResult(({
54
100
  nextKey: 'ArrowRight',
55
101
  previousKey: 'ArrowLeft',
56
- }), "@foldkit/ui/radioGroup/index.js#anonymous~7"))), M.when('Vertical', () => (__foldkitBrandViewResult(({
102
+ }), "@foldkit/ui/radioGroup/index.js#anonymous~9"))), M.when('Vertical', () => (__foldkitBrandViewResult(({
57
103
  nextKey: 'ArrowDown',
58
104
  previousKey: 'ArrowUp',
59
- }), "@foldkit/ui/radioGroup/index.js#anonymous~8"))), M.exhaustive);
105
+ }), "@foldkit/ui/radioGroup/index.js#anonymous~10"))), M.exhaustive);
60
106
  const resolveKeyIndex = keyToIndex(nextKey, previousKey, options.length, focusedIndex, isDisabled);
61
- const selectionAt = (index) => __foldkitBrandViewResult((pipe(options, Array.get(index), Option.map(value => (__foldkitBrandViewResult(({
62
- focusSelector: idSelector(optionId(id, index)),
63
- message: onSelect(value),
64
- }), "@foldkit/ui/radioGroup/index.js#anonymous~9"))))), "@foldkit/ui/radioGroup/index.js#selectionAt");
65
- const handleKeyDown = (currentIndex) => __foldkitBrandViewResult(((key) => __foldkitBrandViewResult((M.value(key).pipe(M.whenOr(nextKey, previousKey, 'Home', 'End', 'PageUp', 'PageDown', () => __foldkitBrandViewResult((selectionAt(resolveKeyIndex(key))), "@foldkit/ui/radioGroup/index.js#anonymous~11")), M.when(' ', () => __foldkitBrandViewResult((selectionAt(currentIndex)), "@foldkit/ui/radioGroup/index.js#anonymous~12")), M.orElse(() => __foldkitBrandViewResult((Option.none()), "@foldkit/ui/radioGroup/index.js#anonymous~13")))), "@foldkit/ui/radioGroup/index.js#anonymous~10")), "@foldkit/ui/radioGroup/index.js#handleKeyDown");
107
+ const optionSelectedAt = (index) => __foldkitBrandViewResult((pipe(options, Array.get(index), Option.map(value => __foldkitBrandViewResult((SelectedOption({ index, value })), "@foldkit/ui/radioGroup/index.js#anonymous~11")))), "@foldkit/ui/radioGroup/index.js#optionSelectedAt");
108
+ const handleSelectingKeyDown = (currentIndex, key) => __foldkitBrandViewResult((M.value(key).pipe(M.whenOr(nextKey, previousKey, 'Home', 'End', 'PageUp', 'PageDown', () => __foldkitBrandViewResult((optionSelectedAt(resolveKeyIndex(key))), "@foldkit/ui/radioGroup/index.js#anonymous~12")), M.when(' ', () => __foldkitBrandViewResult((optionSelectedAt(currentIndex)), "@foldkit/ui/radioGroup/index.js#anonymous~13")), M.orElse(() => __foldkitBrandViewResult((Option.none()), "@foldkit/ui/radioGroup/index.js#anonymous~14")))), "@foldkit/ui/radioGroup/index.js#handleSelectingKeyDown");
109
+ const handleReadOnlyKeyDown = (key) => __foldkitBrandViewResult((M.value(key).pipe(M.whenOr(nextKey, previousKey, 'Home', 'End', 'PageUp', 'PageDown', () => __foldkitBrandViewResult((Option.some(FocusedOption({ index: resolveKeyIndex(key) }))), "@foldkit/ui/radioGroup/index.js#anonymous~15")), M.orElse(() => __foldkitBrandViewResult((Option.none()), "@foldkit/ui/radioGroup/index.js#anonymous~16")))), "@foldkit/ui/radioGroup/index.js#handleReadOnlyKeyDown");
110
+ const handleKeyDown = (currentIndex) => __foldkitBrandViewResult(((key) => {
111
+ if (isReadOnly) {
112
+ return __foldkitBrandViewResult((handleReadOnlyKeyDown(key)), "@foldkit/ui/radioGroup/index.js#anonymous~17");
113
+ }
114
+ else {
115
+ return __foldkitBrandViewResult((handleSelectingKeyDown(currentIndex, key)), "@foldkit/ui/radioGroup/index.js#anonymous~17");
116
+ }
117
+ }), "@foldkit/ui/radioGroup/index.js#handleKeyDown");
66
118
  const optionInfos = Array.map(options, (value, index) => {
67
- const isSelected = Option.exists(selectedIndex, selectedIdx => __foldkitBrandViewResult((selectedIdx === index), "@foldkit/ui/radioGroup/index.js#anonymous~15"));
68
- const isFocusable = index === focusedIndex;
119
+ const isSelected = Option.exists(selectedIndex, selectedOptionIndex => __foldkitBrandViewResult((selectedOptionIndex === index), "@foldkit/ui/radioGroup/index.js#anonymous~19"));
120
+ const isActive = index === focusedIndex;
69
121
  const isOptionDisabledNow = isDisabled(index);
70
122
  const checkedAttributes = isSelected
71
123
  ? [h.DataAttribute('checked', '')]
72
124
  : [];
73
- const activeAttributes = isFocusable
74
- ? [h.DataAttribute('active', '')]
75
- : [];
125
+ const activeAttributes = isActive ? [h.DataAttribute('active', '')] : [];
76
126
  const disabledAttributes = isOptionDisabledNow
77
127
  ? [h.AriaDisabled(true), h.DataAttribute('disabled', '')]
78
128
  : [];
129
+ const readOnlyAttributes = isReadOnly
130
+ ? [h.DataAttribute('readonly', '')]
131
+ : [];
132
+ const clickAttributes = isOptionDisabledNow || isReadOnly
133
+ ? []
134
+ : [h.OnClick(SelectedOption({ index, value }))];
135
+ const keyDownAttributes = isOptionDisabledNow
136
+ ? []
137
+ : [h.OnKeyDownPreventDefault(handleKeyDown(index))];
79
138
  const optionAttributes = [
80
139
  h.Id(optionId(id, index)),
81
140
  h.Type('button'),
@@ -83,16 +142,13 @@ export const view = (config, h) => {
83
142
  h.AriaChecked(isSelected),
84
143
  h.AriaLabelledBy(labelId(id, index)),
85
144
  h.AriaDescribedBy(descriptionId(id, index)),
86
- h.Tabindex(isFocusable ? 0 : -1),
145
+ h.Tabindex(isActive ? 0 : -1),
87
146
  ...checkedAttributes,
88
147
  ...activeAttributes,
89
148
  ...disabledAttributes,
90
- ...(isOptionDisabledNow
91
- ? []
92
- : [
93
- h.OnClickFocus(idSelector(optionId(id, index)), onSelect(value)),
94
- h.OnKeyDownFocus(handleKeyDown(index)),
95
- ]),
149
+ ...readOnlyAttributes,
150
+ ...clickAttributes,
151
+ ...keyDownAttributes,
96
152
  ];
97
153
  const labelAttributes = [h.Id(labelId(id, index))];
98
154
  const descriptionAttributes = [h.Id(descriptionId(id, index))];
@@ -100,27 +156,60 @@ export const view = (config, h) => {
100
156
  value,
101
157
  index,
102
158
  isSelected,
103
- isActive: isFocusable,
159
+ isActive,
104
160
  isDisabled: isOptionDisabledNow,
105
- option: optionAttributes,
106
- label: labelAttributes,
107
- description: descriptionAttributes,
108
- }), "@foldkit/ui/radioGroup/index.js#anonymous~14");
161
+ isReadOnly,
162
+ option: childAttributes(optionAttributes),
163
+ label: childAttributes(labelAttributes),
164
+ description: childAttributes(descriptionAttributes),
165
+ }), "@foldkit/ui/radioGroup/index.js#anonymous~18");
109
166
  });
167
+ const groupReadOnlyAttributes = isReadOnly
168
+ ? [h.AriaReadonly(true), h.DataAttribute('readonly', '')]
169
+ : [];
110
170
  const groupAttributes = [
111
171
  h.Role('radiogroup'),
112
172
  h.AriaOrientation(String.toLowerCase(orientation)),
113
173
  h.AriaLabel(ariaLabel),
174
+ ...groupReadOnlyAttributes,
114
175
  ];
115
176
  const hiddenInputAttributes = pipe(Option.fromNullishOr(name), Option.flatMap(inputName => __foldkitBrandViewResult((Option.map(selectedValue, value => __foldkitBrandViewResult(([
116
177
  h.Type('hidden'),
117
178
  h.Name(inputName),
118
179
  h.Value(value),
119
- ]), "@foldkit/ui/radioGroup/index.js#anonymous~17"))), "@foldkit/ui/radioGroup/index.js#anonymous~16")), Option.getOrElse(() => __foldkitBrandViewResult(([]), "@foldkit/ui/radioGroup/index.js#anonymous~18")));
180
+ ]), "@foldkit/ui/radioGroup/index.js#anonymous~21"))), "@foldkit/ui/radioGroup/index.js#anonymous~20")), Option.getOrElse(() => __foldkitBrandViewResult(([]), "@foldkit/ui/radioGroup/index.js#anonymous~22")));
120
181
  return __foldkitBrandViewResult((toView({
121
- group: groupAttributes,
182
+ group: childAttributes(groupAttributes),
122
183
  options: optionInfos,
123
184
  selectedValue,
124
- hiddenInput: hiddenInputAttributes,
125
- })), "@foldkit/ui/radioGroup/index.js#view");
185
+ hiddenInput: childAttributes(hiddenInputAttributes),
186
+ })), "@foldkit/ui/radioGroup/index.js#anonymous");
187
+ });
188
+ /** Pairs the radio group `view` and `update` behind a single Value-typed
189
+ * entry point. Declare once at module scope so consumers receive
190
+ * `option.value: Value` in `toView` and the `Selected` OutMessage without an
191
+ * `as` cast:
192
+ *
193
+ * ```ts
194
+ * const PlanRadioGroup = RadioGroup.create<Plan>()
195
+ *
196
+ * // In view (selectedValue is the parent-owned selection):
197
+ * h.submodel({ view: PlanRadioGroup.view, viewInputs: { selectedValue, ... }, ... })
198
+ *
199
+ * // In update, fold the Selected OutMessage into your Model:
200
+ * const [next, commands, maybeOutMessage] = PlanRadioGroup.update(model, message)
201
+ * ```
202
+ *
203
+ * The internal view stays typed `ReadonlyArray<string>`; consumers can
204
+ * pass a `ReadonlyArray<MyUnion>` (assignable) and the fenced cast inside
205
+ * `create` types `OptionInfo.value` as `MyUnion`. */
206
+ export const create = () => {
207
+ const cast = (result) =>
208
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
209
+ __foldkitBrandViewResult((result), "@foldkit/ui/radioGroup/index.js#cast");
210
+ return __foldkitBrandViewResult(({
211
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
212
+ view: internalView,
213
+ update: (model, message) => __foldkitBrandViewResult((cast(update(model, message))), "@foldkit/ui/radioGroup/index.js#update~2"),
214
+ }), "@foldkit/ui/radioGroup/index.js#create");
126
215
  };
@@ -1,3 +1,3 @@
1
- export { view, Orientation } from './index.js';
2
- export type { ViewConfig, RenderInfo, OptionInfo } from './index.js';
1
+ export { init, create, Model, Message, OutMessage, Selected, SelectedOption, FocusedOption, CompletedFocusOption, FocusOption, Orientation, } from './index.js';
2
+ export type { InitConfig, ViewInputs, RenderInfo, OptionInfo, Bundle, } from './index.js';
3
3
  //# sourceMappingURL=public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/radioGroup/public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE9C,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/radioGroup/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,KAAK,EACL,OAAO,EACP,UAAU,EACV,QAAQ,EACR,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,WAAW,EACX,WAAW,GACZ,MAAM,YAAY,CAAA;AAEnB,YAAY,EACV,UAAU,EACV,UAAU,EACV,UAAU,EACV,UAAU,EACV,MAAM,GACP,MAAM,YAAY,CAAA"}
@@ -1 +1 @@
1
- export { view, Orientation } from './index.js';
1
+ export { init, create, Model, Message, OutMessage, Selected, SelectedOption, FocusedOption, CompletedFocusOption, FocusOption, Orientation, } from './index.js';
@@ -280,7 +280,21 @@ export type ViewInputs = Readonly<{
280
280
  ariaLabel?: string;
281
281
  ariaLabelledBy?: string;
282
282
  formatValue?: (value: number) => string;
283
+ /** Marks the Slider unavailable with `aria-disabled="true"` and
284
+ * `data-disabled`. The thumb remains focusable, following Foldkit's
285
+ * convention that unavailable controls stay discoverable by keyboard and
286
+ * assistive technology. */
283
287
  isDisabled?: boolean;
288
+ /** Prevents value changes while exposing read-only semantics with
289
+ * `aria-readonly="true"` and `data-readonly`. The thumb remains focusable.
290
+ * Independent of `isDisabled`: setting both emits both attribute sets, and
291
+ * either one removes the pointer and keyboard handlers.
292
+ *
293
+ * A drag already in flight is not interrupted. The handlers this flag
294
+ * removes are what start a drag, and the pointermove Subscription runs off
295
+ * `dragState` in the Model until pointerup. `isDisabled` behaves the same
296
+ * way. */
297
+ isReadOnly?: boolean;
284
298
  name?: string;
285
299
  /** Resolves the root that holds the slider track when looking it up by its
286
300
  * `data-slider-track-id` attribute. Defaults to `document`. Provide a
@@ -330,7 +344,21 @@ export declare const view: import("foldkit/submodel").View<{
330
344
  ariaLabel?: string;
331
345
  ariaLabelledBy?: string;
332
346
  formatValue?: (value: number) => string;
347
+ /** Marks the Slider unavailable with `aria-disabled="true"` and
348
+ * `data-disabled`. The thumb remains focusable, following Foldkit's
349
+ * convention that unavailable controls stay discoverable by keyboard and
350
+ * assistive technology. */
333
351
  isDisabled?: boolean;
352
+ /** Prevents value changes while exposing read-only semantics with
353
+ * `aria-readonly="true"` and `data-readonly`. The thumb remains focusable.
354
+ * Independent of `isDisabled`: setting both emits both attribute sets, and
355
+ * either one removes the pointer and keyboard handlers.
356
+ *
357
+ * A drag already in flight is not interrupted. The handlers this flag
358
+ * removes are what start a drag, and the pointermove Subscription runs off
359
+ * `dragState` in the Model until pointerup. `isDisabled` behaves the same
360
+ * way. */
361
+ isReadOnly?: boolean;
334
362
  name?: string;
335
363
  /** Resolves the root that holds the slider track when looking it up by its
336
364
  * `data-slider-track-id` attribute. Defaults to `document`. Provide a
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/slider/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/slider/index.ts"],"names":[],"mappings":"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"}