@foldkit/ui 0.112.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 (201) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +67 -0
  3. package/dist/anchor.d.ts +38 -0
  4. package/dist/anchor.d.ts.map +1 -0
  5. package/dist/anchor.js +142 -0
  6. package/dist/animation/index.d.ts +49 -0
  7. package/dist/animation/index.d.ts.map +1 -0
  8. package/dist/animation/index.js +75 -0
  9. package/dist/animation/public.d.ts +3 -0
  10. package/dist/animation/public.d.ts.map +1 -0
  11. package/dist/animation/public.js +1 -0
  12. package/dist/animation/schema.d.ts +43 -0
  13. package/dist/animation/schema.d.ts.map +1 -0
  14. package/dist/animation/schema.js +41 -0
  15. package/dist/animation/update.d.ts +24 -0
  16. package/dist/animation/update.d.ts.map +1 -0
  17. package/dist/animation/update.js +67 -0
  18. package/dist/button/index.d.ts +17 -0
  19. package/dist/button/index.d.ts.map +1 -0
  20. package/dist/button/index.js +22 -0
  21. package/dist/button/public.d.ts +3 -0
  22. package/dist/button/public.d.ts.map +1 -0
  23. package/dist/button/public.js +1 -0
  24. package/dist/calendar/index.d.ts +462 -0
  25. package/dist/calendar/index.d.ts.map +1 -0
  26. package/dist/calendar/index.js +825 -0
  27. package/dist/calendar/public.d.ts +3 -0
  28. package/dist/calendar/public.d.ts.map +1 -0
  29. package/dist/calendar/public.js +1 -0
  30. package/dist/checkbox/index.d.ts +119 -0
  31. package/dist/checkbox/index.d.ts.map +1 -0
  32. package/dist/checkbox/index.js +111 -0
  33. package/dist/checkbox/public.d.ts +3 -0
  34. package/dist/checkbox/public.d.ts.map +1 -0
  35. package/dist/checkbox/public.js +1 -0
  36. package/dist/combobox/multi.d.ts +183 -0
  37. package/dist/combobox/multi.d.ts.map +1 -0
  38. package/dist/combobox/multi.js +81 -0
  39. package/dist/combobox/multiPublic.d.ts +3 -0
  40. package/dist/combobox/multiPublic.d.ts.map +1 -0
  41. package/dist/combobox/multiPublic.js +1 -0
  42. package/dist/combobox/public.d.ts +7 -0
  43. package/dist/combobox/public.d.ts.map +1 -0
  44. package/dist/combobox/public.js +3 -0
  45. package/dist/combobox/shared.d.ts +423 -0
  46. package/dist/combobox/shared.d.ts.map +1 -0
  47. package/dist/combobox/shared.js +708 -0
  48. package/dist/combobox/single.d.ts +198 -0
  49. package/dist/combobox/single.d.ts.map +1 -0
  50. package/dist/combobox/single.js +106 -0
  51. package/dist/datePicker/index.d.ts +457 -0
  52. package/dist/datePicker/index.d.ts.map +1 -0
  53. package/dist/datePicker/index.js +318 -0
  54. package/dist/datePicker/public.d.ts +3 -0
  55. package/dist/datePicker/public.d.ts.map +1 -0
  56. package/dist/datePicker/public.js +1 -0
  57. package/dist/dialog/index.d.ts +160 -0
  58. package/dist/dialog/index.d.ts.map +1 -0
  59. package/dist/dialog/index.js +211 -0
  60. package/dist/dialog/public.d.ts +3 -0
  61. package/dist/dialog/public.d.ts.map +1 -0
  62. package/dist/dialog/public.js +1 -0
  63. package/dist/disclosure/index.d.ts +110 -0
  64. package/dist/disclosure/index.d.ts.map +1 -0
  65. package/dist/disclosure/index.js +111 -0
  66. package/dist/disclosure/public.d.ts +3 -0
  67. package/dist/disclosure/public.d.ts.map +1 -0
  68. package/dist/disclosure/public.js +1 -0
  69. package/dist/dragAndDrop/index.d.ts +540 -0
  70. package/dist/dragAndDrop/index.d.ts.map +1 -0
  71. package/dist/dragAndDrop/index.js +535 -0
  72. package/dist/dragAndDrop/public.d.ts +3 -0
  73. package/dist/dragAndDrop/public.d.ts.map +1 -0
  74. package/dist/dragAndDrop/public.js +1 -0
  75. package/dist/fieldset/index.d.ts +21 -0
  76. package/dist/fieldset/index.d.ts.map +1 -0
  77. package/dist/fieldset/index.js +25 -0
  78. package/dist/fieldset/public.d.ts +3 -0
  79. package/dist/fieldset/public.d.ts.map +1 -0
  80. package/dist/fieldset/public.js +1 -0
  81. package/dist/fileDrop/index.d.ts +109 -0
  82. package/dist/fileDrop/index.d.ts.map +1 -0
  83. package/dist/fileDrop/index.js +127 -0
  84. package/dist/fileDrop/public.d.ts +3 -0
  85. package/dist/fileDrop/public.d.ts.map +1 -0
  86. package/dist/fileDrop/public.js +1 -0
  87. package/dist/group.d.ts +8 -0
  88. package/dist/group.d.ts.map +1 -0
  89. package/dist/group.js +13 -0
  90. package/dist/index.d.ts +25 -0
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +24 -0
  93. package/dist/input/index.d.ts +26 -0
  94. package/dist/input/index.d.ts.map +1 -0
  95. package/dist/input/index.js +43 -0
  96. package/dist/input/public.d.ts +3 -0
  97. package/dist/input/public.d.ts.map +1 -0
  98. package/dist/input/public.js +1 -0
  99. package/dist/internal/optionExtensions.d.ts +6 -0
  100. package/dist/internal/optionExtensions.d.ts.map +1 -0
  101. package/dist/internal/optionExtensions.js +2 -0
  102. package/dist/keyboard.d.ts +6 -0
  103. package/dist/keyboard.d.ts.map +1 -0
  104. package/dist/keyboard.js +9 -0
  105. package/dist/listbox/multi.d.ts +189 -0
  106. package/dist/listbox/multi.d.ts.map +1 -0
  107. package/dist/listbox/multi.js +65 -0
  108. package/dist/listbox/multiPublic.d.ts +3 -0
  109. package/dist/listbox/multiPublic.d.ts.map +1 -0
  110. package/dist/listbox/multiPublic.js +1 -0
  111. package/dist/listbox/public.d.ts +7 -0
  112. package/dist/listbox/public.d.ts.map +1 -0
  113. package/dist/listbox/public.js +3 -0
  114. package/dist/listbox/shared.d.ts +432 -0
  115. package/dist/listbox/shared.d.ts.map +1 -0
  116. package/dist/listbox/shared.js +670 -0
  117. package/dist/listbox/single.d.ts +207 -0
  118. package/dist/listbox/single.d.ts.map +1 -0
  119. package/dist/listbox/single.js +73 -0
  120. package/dist/menu/index.d.ts +368 -0
  121. package/dist/menu/index.d.ts.map +1 -0
  122. package/dist/menu/index.js +682 -0
  123. package/dist/menu/public.d.ts +4 -0
  124. package/dist/menu/public.d.ts.map +1 -0
  125. package/dist/menu/public.js +1 -0
  126. package/dist/popover/index.d.ts +267 -0
  127. package/dist/popover/index.d.ts.map +1 -0
  128. package/dist/popover/index.js +346 -0
  129. package/dist/popover/public.d.ts +4 -0
  130. package/dist/popover/public.d.ts.map +1 -0
  131. package/dist/popover/public.js +1 -0
  132. package/dist/radioGroup/index.d.ts +169 -0
  133. package/dist/radioGroup/index.d.ts.map +1 -0
  134. package/dist/radioGroup/index.js +197 -0
  135. package/dist/radioGroup/public.d.ts +3 -0
  136. package/dist/radioGroup/public.d.ts.map +1 -0
  137. package/dist/radioGroup/public.js +1 -0
  138. package/dist/select/index.d.ts +24 -0
  139. package/dist/select/index.d.ts.map +1 -0
  140. package/dist/select/index.js +40 -0
  141. package/dist/select/public.d.ts +3 -0
  142. package/dist/select/public.d.ts.map +1 -0
  143. package/dist/select/public.js +1 -0
  144. package/dist/slider/index.d.ts +318 -0
  145. package/dist/slider/index.d.ts.map +1 -0
  146. package/dist/slider/index.js +337 -0
  147. package/dist/slider/public.d.ts +3 -0
  148. package/dist/slider/public.d.ts.map +1 -0
  149. package/dist/slider/public.js +1 -0
  150. package/dist/switch/index.d.ts +99 -0
  151. package/dist/switch/index.d.ts.map +1 -0
  152. package/dist/switch/index.js +107 -0
  153. package/dist/switch/public.d.ts +3 -0
  154. package/dist/switch/public.d.ts.map +1 -0
  155. package/dist/switch/public.js +1 -0
  156. package/dist/tabs/index.d.ts +155 -0
  157. package/dist/tabs/index.d.ts.map +1 -0
  158. package/dist/tabs/index.js +185 -0
  159. package/dist/tabs/public.d.ts +3 -0
  160. package/dist/tabs/public.d.ts.map +1 -0
  161. package/dist/tabs/public.js +1 -0
  162. package/dist/test/apps/disabledButton.d.ts +38 -0
  163. package/dist/test/apps/disabledButton.d.ts.map +1 -0
  164. package/dist/test/apps/disabledButton.js +71 -0
  165. package/dist/textarea/index.d.ts +26 -0
  166. package/dist/textarea/index.d.ts.map +1 -0
  167. package/dist/textarea/index.js +44 -0
  168. package/dist/textarea/public.d.ts +3 -0
  169. package/dist/textarea/public.d.ts.map +1 -0
  170. package/dist/textarea/public.js +1 -0
  171. package/dist/toast/index.d.ts +608 -0
  172. package/dist/toast/index.d.ts.map +1 -0
  173. package/dist/toast/index.js +146 -0
  174. package/dist/toast/public.d.ts +4 -0
  175. package/dist/toast/public.d.ts.map +1 -0
  176. package/dist/toast/public.js +1 -0
  177. package/dist/toast/schema.d.ts +154 -0
  178. package/dist/toast/schema.d.ts.map +1 -0
  179. package/dist/toast/schema.js +93 -0
  180. package/dist/toast/update.d.ts +510 -0
  181. package/dist/toast/update.d.ts.map +1 -0
  182. package/dist/toast/update.js +225 -0
  183. package/dist/tooltip/index.d.ts +170 -0
  184. package/dist/tooltip/index.d.ts.map +1 -0
  185. package/dist/tooltip/index.js +253 -0
  186. package/dist/tooltip/public.d.ts +4 -0
  187. package/dist/tooltip/public.d.ts.map +1 -0
  188. package/dist/tooltip/public.js +1 -0
  189. package/dist/typeahead.d.ts +4 -0
  190. package/dist/typeahead.d.ts.map +1 -0
  191. package/dist/typeahead.js +14 -0
  192. package/dist/virtualList/index.d.ts +203 -0
  193. package/dist/virtualList/index.d.ts.map +1 -0
  194. package/dist/virtualList/index.js +392 -0
  195. package/dist/virtualList/public.d.ts +3 -0
  196. package/dist/virtualList/public.d.ts.map +1 -0
  197. package/dist/virtualList/public.js +1 -0
  198. package/dist/vitest-setup.d.ts +2 -0
  199. package/dist/vitest-setup.d.ts.map +1 -0
  200. package/dist/vitest-setup.js +2 -0
  201. package/package.json +161 -0
@@ -0,0 +1,189 @@
1
+ import { Option, Schema as S } from 'effect';
2
+ import type * as Command from 'foldkit/command';
3
+ import type { Reflect, View as SubmodelView } from 'foldkit/submodel';
4
+ import { type BaseInitConfig, type BaseViewInputs, type Message, type OutMessage } from './shared.js';
5
+ /** Schema for the multi-select listbox component's state, tracking open/closed status, active item, selected items, activation trigger, and typeahead search. */
6
+ export declare const Model: S.Struct<{
7
+ readonly selectedItems: S.$Array<S.String>;
8
+ readonly id: S.String;
9
+ readonly isOpen: S.Boolean;
10
+ readonly isAnimated: S.Boolean;
11
+ readonly isModal: S.Boolean;
12
+ readonly orientation: S.Literals<readonly ["Vertical", "Horizontal"]>;
13
+ readonly animation: S.Struct<{
14
+ readonly id: S.String;
15
+ readonly isShowing: S.Boolean;
16
+ readonly transitionState: S.Literals<readonly ["Idle", "EnterStart", "EnterAnimating", "LeaveStart", "LeaveAnimating"]>;
17
+ }>;
18
+ readonly maybeActiveItemIndex: S.Option<S.Number>;
19
+ readonly activationTrigger: S.Literals<readonly ["Pointer", "Keyboard"]>;
20
+ readonly searchQuery: S.String;
21
+ readonly searchVersion: S.Number;
22
+ readonly maybeLastPointerPosition: S.Option<S.Struct<{
23
+ readonly screenX: S.Number;
24
+ readonly screenY: S.Number;
25
+ }>>;
26
+ readonly maybeLastButtonPointerType: S.Option<S.String>;
27
+ }>;
28
+ export type Model = typeof Model.Type;
29
+ /** Configuration for creating a multi-select listbox model with `init`. `isAnimated` enables CSS transition coordination (default `false`). `isModal` locks page scroll and inerts other elements when open (default `false`). `selectedItems` sets the initial selection (default `[]`). */
30
+ export type InitConfig = BaseInitConfig & Readonly<{
31
+ selectedItems?: ReadonlyArray<string>;
32
+ }>;
33
+ /** Creates an initial multi-select listbox model from a config. Defaults to closed with no active item and no selection. */
34
+ export declare const init: (config: InitConfig) => Model;
35
+ /** Processes a listbox message and returns the next model, commands, and optional OutMessage. Stays open on selection and toggles item membership (multi-select behavior); emits a `Selected({ value, wasAdded })` OutMessage indicating whether the value was added or removed. */
36
+ export declare const update: (model: {
37
+ readonly selectedItems: readonly string[];
38
+ readonly id: string;
39
+ readonly isOpen: boolean;
40
+ readonly isAnimated: boolean;
41
+ readonly isModal: boolean;
42
+ readonly orientation: "Horizontal" | "Vertical";
43
+ readonly animation: {
44
+ readonly id: string;
45
+ readonly isShowing: boolean;
46
+ readonly transitionState: "Idle" | "EnterStart" | "EnterAnimating" | "LeaveStart" | "LeaveAnimating";
47
+ };
48
+ readonly maybeActiveItemIndex: Option.Option<number>;
49
+ readonly activationTrigger: "Pointer" | "Keyboard";
50
+ readonly searchQuery: string;
51
+ readonly searchVersion: number;
52
+ readonly maybeLastPointerPosition: Option.Option<{
53
+ readonly screenX: number;
54
+ readonly screenY: number;
55
+ }>;
56
+ readonly maybeLastButtonPointerType: Option.Option<string>;
57
+ }, message: Message) => readonly [{
58
+ readonly selectedItems: readonly string[];
59
+ readonly id: string;
60
+ readonly isOpen: boolean;
61
+ readonly isAnimated: boolean;
62
+ readonly isModal: boolean;
63
+ readonly orientation: "Horizontal" | "Vertical";
64
+ readonly animation: {
65
+ readonly id: string;
66
+ readonly isShowing: boolean;
67
+ readonly transitionState: "Idle" | "EnterStart" | "EnterAnimating" | "LeaveStart" | "LeaveAnimating";
68
+ };
69
+ readonly maybeActiveItemIndex: Option.Option<number>;
70
+ readonly activationTrigger: "Pointer" | "Keyboard";
71
+ readonly searchQuery: string;
72
+ readonly searchVersion: number;
73
+ readonly maybeLastPointerPosition: Option.Option<{
74
+ readonly screenX: number;
75
+ readonly screenY: number;
76
+ }>;
77
+ readonly maybeLastButtonPointerType: Option.Option<string>;
78
+ }, readonly Readonly<{
79
+ name: string;
80
+ args?: Record<string, unknown>;
81
+ effect: import("effect/Effect").Effect<{
82
+ readonly _tag: "CompletedFocusButton";
83
+ } | {
84
+ readonly _tag: "CompletedLockScroll";
85
+ } | {
86
+ readonly _tag: "CompletedUnlockScroll";
87
+ } | {
88
+ readonly _tag: "CompletedInertOthers";
89
+ } | {
90
+ readonly _tag: "CompletedRestoreInert";
91
+ } | {
92
+ readonly _tag: "IgnoredMouseClick";
93
+ } | {
94
+ readonly _tag: "SuppressedSpaceScroll";
95
+ } | {
96
+ readonly _tag: "Closed";
97
+ } | {
98
+ readonly _tag: "DeactivatedItem";
99
+ } | {
100
+ readonly _tag: "CompletedScrollIntoView";
101
+ } | {
102
+ readonly _tag: "CompletedClickItem";
103
+ } | {
104
+ readonly _tag: "Opened";
105
+ readonly maybeActiveItemIndex: Option.Option<number>;
106
+ } | {
107
+ readonly _tag: "BlurredItems";
108
+ } | {
109
+ readonly _tag: "ActivatedItem";
110
+ readonly index: number;
111
+ readonly activationTrigger: "Pointer" | "Keyboard";
112
+ } | {
113
+ readonly _tag: "SelectedItem";
114
+ readonly item: string;
115
+ } | {
116
+ readonly _tag: "RequestedItemClick";
117
+ readonly index: number;
118
+ } | {
119
+ readonly _tag: "Searched";
120
+ readonly key: string;
121
+ readonly maybeTargetIndex: Option.Option<number>;
122
+ } | {
123
+ readonly _tag: "ClearedSearch";
124
+ readonly version: number;
125
+ } | {
126
+ readonly _tag: "MovedPointerOverItem";
127
+ readonly index: number;
128
+ readonly screenX: number;
129
+ readonly screenY: number;
130
+ } | {
131
+ readonly _tag: "CompletedFocusItems";
132
+ } | {
133
+ readonly _tag: "CompletedAnchorListbox";
134
+ } | {
135
+ readonly _tag: "CompletedPortalListboxBackdrop";
136
+ } | {
137
+ readonly _tag: "GotAnimationMessage";
138
+ readonly message: {
139
+ readonly _tag: "Showed";
140
+ } | {
141
+ readonly _tag: "Hid";
142
+ } | {
143
+ readonly _tag: "AdvancedAnimationFrame";
144
+ } | {
145
+ readonly _tag: "EndedAnimation";
146
+ };
147
+ } | {
148
+ readonly _tag: "PressedPointerOnButton";
149
+ readonly pointerType: string;
150
+ readonly button: number;
151
+ }, never, never>;
152
+ }>[], Option.Option<Readonly<{
153
+ readonly _tag: "Selected";
154
+ readonly value: string;
155
+ readonly wasAdded: boolean;
156
+ }>>];
157
+ type UpdateReturn = ReturnType<typeof update>;
158
+ /** Programmatically opens the listbox, updating the model and returning
159
+ * focus and modal commands. Use this in domain-event handlers to open the listbox. */
160
+ export declare const open: (model: Model) => UpdateReturn;
161
+ /** Programmatically closes the listbox, updating the model and returning
162
+ * focus and modal commands. Use this in domain-event handlers to close the listbox. */
163
+ export declare const close: (model: Model) => UpdateReturn;
164
+ /** Programmatically toggles an item in the multi-select listbox. Emits `Selected({ value, wasAdded })`. */
165
+ export declare const selectItem: (model: Model, item: string) => UpdateReturn;
166
+ /** Reflects an externally-sourced selection set onto the model without
167
+ * emitting an OutMessage or running selection side effects. Use this to
168
+ * mirror external truth (URL parameters, restored storage, a server push)
169
+ * onto the listbox's selected items. Contrast with `selectItem`, which
170
+ * toggles a single item as a user *choice* and emits `Selected`. Returns
171
+ * the model directly because it produces no commands and no OutMessage. */
172
+ export declare const reflectSelectedItems: Reflect<Model, ReadonlyArray<string>>;
173
+ /** Per-render view inputs passed to the view via `h.submodel`'s `viewInputs` field. */
174
+ export type ViewInputs<Item, Value extends string = string> = BaseViewInputs<Item, Value>;
175
+ /** Pairs the multi-select listbox's `view` and `update` (and programmatic
176
+ * helpers) behind a single Item-typed entry point. Same shape as
177
+ * `Listbox.create`. Two type params support object-typed items via
178
+ * `itemToValue`: `Value` defaults to `Item` when `Item extends string`,
179
+ * else `string`. */
180
+ export declare const create: <Item = string, Value extends string = Item extends string ? Item : string>() => Readonly<{
181
+ view: SubmodelView<Model, Message, BaseViewInputs<Item, Value>>;
182
+ update: (model: Model, message: Message) => readonly [Model, ReadonlyArray<Command.Command<Message>>, Option.Option<OutMessage<Value>>];
183
+ selectItem: (model: Model, item: Value) => readonly [Model, ReadonlyArray<Command.Command<Message>>, Option.Option<OutMessage<Value>>];
184
+ open: (model: Model) => readonly [Model, ReadonlyArray<Command.Command<Message>>, Option.Option<OutMessage<Value>>];
185
+ close: (model: Model) => readonly [Model, ReadonlyArray<Command.Command<Message>>, Option.Option<OutMessage<Value>>];
186
+ reflectSelectedItems: Reflect<Model, ReadonlyArray<Value>>;
187
+ }>;
188
+ export {};
189
+ //# sourceMappingURL=multi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multi.d.ts","sourceRoot":"","sources":["../../src/listbox/multi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import { Array, Function, Option, Schema as S, pipe } from 'effect';
2
+ import { evo } from 'foldkit/struct';
3
+ import { BaseModel, Closed, Opened, SelectedItem, Selected as SharedSelected, baseInit, makeUpdate, makeView, } from './shared.js';
4
+ // MODEL
5
+ /** Schema for the multi-select listbox component's state, tracking open/closed status, active item, selected items, activation trigger, and typeahead search. */
6
+ export const Model = S.Struct({
7
+ ...BaseModel.fields,
8
+ selectedItems: S.Array(S.String),
9
+ });
10
+ /** Creates an initial multi-select listbox model from a config. Defaults to closed with no active item and no selection. */
11
+ export const init = (config) => ({
12
+ ...baseInit(config),
13
+ selectedItems: config.selectedItems ?? [],
14
+ });
15
+ // UPDATE
16
+ /** Processes a listbox message and returns the next model, commands, and optional OutMessage. Stays open on selection and toggles item membership (multi-select behavior); emits a `Selected({ value, wasAdded })` OutMessage indicating whether the value was added or removed. */
17
+ export const update = makeUpdate((model, item) => {
18
+ const wasAdded = !Array.contains(model.selectedItems, item);
19
+ const nextSelectedItems = wasAdded
20
+ ? Array.append(model.selectedItems, item)
21
+ : Array.filter(model.selectedItems, selected => selected !== item);
22
+ return [
23
+ evo(model, { selectedItems: () => nextSelectedItems }),
24
+ [],
25
+ Option.some(SharedSelected({ value: item, wasAdded })),
26
+ ];
27
+ });
28
+ /** Programmatically opens the listbox, updating the model and returning
29
+ * focus and modal commands. Use this in domain-event handlers to open the listbox. */
30
+ export const open = (model) => update(model, Opened({ maybeActiveItemIndex: Option.none() }));
31
+ /** Programmatically closes the listbox, updating the model and returning
32
+ * focus and modal commands. Use this in domain-event handlers to close the listbox. */
33
+ export const close = (model) => update(model, Closed());
34
+ /** Programmatically toggles an item in the multi-select listbox. Emits `Selected({ value, wasAdded })`. */
35
+ export const selectItem = (model, item) => update(model, SelectedItem({ item }));
36
+ /** Reflects an externally-sourced selection set onto the model without
37
+ * emitting an OutMessage or running selection side effects. Use this to
38
+ * mirror external truth (URL parameters, restored storage, a server push)
39
+ * onto the listbox's selected items. Contrast with `selectItem`, which
40
+ * toggles a single item as a user *choice* and emits `Selected`. Returns
41
+ * the model directly because it produces no commands and no OutMessage. */
42
+ export const reflectSelectedItems = Function.dual(2, (model, items) => evo(model, { selectedItems: () => items }));
43
+ const internalView = makeView({
44
+ isItemSelected: (model, itemValue) => Array.contains(model.selectedItems, itemValue),
45
+ selectedItemIndex: (model, items, itemToValue) => pipe(model.selectedItems, Array.head, Option.flatMap(selectedItem => Array.findFirstIndex(items, item => itemToValue(item) === selectedItem))),
46
+ ariaMultiSelectable: true,
47
+ });
48
+ /** Pairs the multi-select listbox's `view` and `update` (and programmatic
49
+ * helpers) behind a single Item-typed entry point. Same shape as
50
+ * `Listbox.create`. Two type params support object-typed items via
51
+ * `itemToValue`: `Value` defaults to `Item` when `Item extends string`,
52
+ * else `string`. */
53
+ export const create = () => {
54
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
55
+ const typedUpdate = update;
56
+ return {
57
+ view: internalView(),
58
+ update: typedUpdate,
59
+ selectItem: (model, item) => typedUpdate(model, SelectedItem({ item })),
60
+ open: model => typedUpdate(model, Opened({ maybeActiveItemIndex: Option.none() })),
61
+ close: model => typedUpdate(model, Closed()),
62
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
63
+ reflectSelectedItems: reflectSelectedItems,
64
+ };
65
+ };
@@ -0,0 +1,3 @@
1
+ export { init, create, Model } from './multi.js';
2
+ export type { InitConfig, ViewInputs } from './multi.js';
3
+ //# sourceMappingURL=multiPublic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multiPublic.d.ts","sourceRoot":"","sources":["../../src/listbox/multiPublic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAChD,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1 @@
1
+ export { init, create, Model } from './multi.js';
@@ -0,0 +1,7 @@
1
+ export { init, create, Model } from './single.js';
2
+ export { Message, OutMessage, Selected, Orientation, SelectedItem, CompletedLockScroll, CompletedUnlockScroll, CompletedInertOthers, CompletedRestoreInert, CompletedFocusButton, CompletedFocusItems, CompletedScrollIntoView, CompletedClickItem, CompletedAnchorListbox, CompletedPortalListboxBackdrop, AnchorListbox, PortalListboxBackdrop, ClearedSearch, GotAnimationMessage, LockScroll, UnlockScroll, InertOthers, RestoreInert, FocusButton, FocusItems, ScrollIntoView, ClickItem, DelayClearSearch, DetectMovementOrAnimationEnd, } from './shared.js';
3
+ export type { ActivationTrigger, Opened, Closed, BlurredItems, ActivatedItem, DeactivatedItem, MovedPointerOverItem, RequestedItemClick, Searched, PressedPointerOnButton, IgnoredMouseClick, SuppressedSpaceScroll, ItemConfig, GroupHeading, } from './shared.js';
4
+ export type { InitConfig, ViewInputs } from './single.js';
5
+ export type { AnchorConfig } from '../anchor.js';
6
+ export * as Multi from './multiPublic.js';
7
+ //# sourceMappingURL=public.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/listbox/public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAEjD,OAAO,EACL,OAAO,EACP,UAAU,EACV,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,EACtB,8BAA8B,EAC9B,aAAa,EACb,qBAAqB,EACrB,aAAa,EACb,mBAAmB,EACnB,UAAU,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,WAAW,EACX,UAAU,EACV,cAAc,EACd,SAAS,EACT,gBAAgB,EAChB,4BAA4B,GAC7B,MAAM,aAAa,CAAA;AAEpB,YAAY,EACV,iBAAiB,EACjB,MAAM,EACN,MAAM,EACN,YAAY,EACZ,aAAa,EACb,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,QAAQ,EACR,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,UAAU,EACV,YAAY,GACb,MAAM,aAAa,CAAA;AAEpB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAEzD,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAEhD,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAA"}
@@ -0,0 +1,3 @@
1
+ export { init, create, Model } from './single.js';
2
+ export { Message, OutMessage, Selected, Orientation, SelectedItem, CompletedLockScroll, CompletedUnlockScroll, CompletedInertOthers, CompletedRestoreInert, CompletedFocusButton, CompletedFocusItems, CompletedScrollIntoView, CompletedClickItem, CompletedAnchorListbox, CompletedPortalListboxBackdrop, AnchorListbox, PortalListboxBackdrop, ClearedSearch, GotAnimationMessage, LockScroll, UnlockScroll, InertOthers, RestoreInert, FocusButton, FocusItems, ScrollIntoView, ClickItem, DelayClearSearch, DetectMovementOrAnimationEnd, } from './shared.js';
3
+ export * as Multi from './multiPublic.js';