@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.
- package/LICENSE +21 -0
- package/README.md +67 -0
- package/dist/anchor.d.ts +38 -0
- package/dist/anchor.d.ts.map +1 -0
- package/dist/anchor.js +142 -0
- package/dist/animation/index.d.ts +49 -0
- package/dist/animation/index.d.ts.map +1 -0
- package/dist/animation/index.js +75 -0
- package/dist/animation/public.d.ts +3 -0
- package/dist/animation/public.d.ts.map +1 -0
- package/dist/animation/public.js +1 -0
- package/dist/animation/schema.d.ts +43 -0
- package/dist/animation/schema.d.ts.map +1 -0
- package/dist/animation/schema.js +41 -0
- package/dist/animation/update.d.ts +24 -0
- package/dist/animation/update.d.ts.map +1 -0
- package/dist/animation/update.js +67 -0
- package/dist/button/index.d.ts +17 -0
- package/dist/button/index.d.ts.map +1 -0
- package/dist/button/index.js +22 -0
- package/dist/button/public.d.ts +3 -0
- package/dist/button/public.d.ts.map +1 -0
- package/dist/button/public.js +1 -0
- package/dist/calendar/index.d.ts +462 -0
- package/dist/calendar/index.d.ts.map +1 -0
- package/dist/calendar/index.js +825 -0
- package/dist/calendar/public.d.ts +3 -0
- package/dist/calendar/public.d.ts.map +1 -0
- package/dist/calendar/public.js +1 -0
- package/dist/checkbox/index.d.ts +119 -0
- package/dist/checkbox/index.d.ts.map +1 -0
- package/dist/checkbox/index.js +111 -0
- package/dist/checkbox/public.d.ts +3 -0
- package/dist/checkbox/public.d.ts.map +1 -0
- package/dist/checkbox/public.js +1 -0
- package/dist/combobox/multi.d.ts +183 -0
- package/dist/combobox/multi.d.ts.map +1 -0
- package/dist/combobox/multi.js +81 -0
- package/dist/combobox/multiPublic.d.ts +3 -0
- package/dist/combobox/multiPublic.d.ts.map +1 -0
- package/dist/combobox/multiPublic.js +1 -0
- package/dist/combobox/public.d.ts +7 -0
- package/dist/combobox/public.d.ts.map +1 -0
- package/dist/combobox/public.js +3 -0
- package/dist/combobox/shared.d.ts +423 -0
- package/dist/combobox/shared.d.ts.map +1 -0
- package/dist/combobox/shared.js +708 -0
- package/dist/combobox/single.d.ts +198 -0
- package/dist/combobox/single.d.ts.map +1 -0
- package/dist/combobox/single.js +106 -0
- package/dist/datePicker/index.d.ts +457 -0
- package/dist/datePicker/index.d.ts.map +1 -0
- package/dist/datePicker/index.js +318 -0
- package/dist/datePicker/public.d.ts +3 -0
- package/dist/datePicker/public.d.ts.map +1 -0
- package/dist/datePicker/public.js +1 -0
- package/dist/dialog/index.d.ts +160 -0
- package/dist/dialog/index.d.ts.map +1 -0
- package/dist/dialog/index.js +211 -0
- package/dist/dialog/public.d.ts +3 -0
- package/dist/dialog/public.d.ts.map +1 -0
- package/dist/dialog/public.js +1 -0
- package/dist/disclosure/index.d.ts +110 -0
- package/dist/disclosure/index.d.ts.map +1 -0
- package/dist/disclosure/index.js +111 -0
- package/dist/disclosure/public.d.ts +3 -0
- package/dist/disclosure/public.d.ts.map +1 -0
- package/dist/disclosure/public.js +1 -0
- package/dist/dragAndDrop/index.d.ts +540 -0
- package/dist/dragAndDrop/index.d.ts.map +1 -0
- package/dist/dragAndDrop/index.js +535 -0
- package/dist/dragAndDrop/public.d.ts +3 -0
- package/dist/dragAndDrop/public.d.ts.map +1 -0
- package/dist/dragAndDrop/public.js +1 -0
- package/dist/fieldset/index.d.ts +21 -0
- package/dist/fieldset/index.d.ts.map +1 -0
- package/dist/fieldset/index.js +25 -0
- package/dist/fieldset/public.d.ts +3 -0
- package/dist/fieldset/public.d.ts.map +1 -0
- package/dist/fieldset/public.js +1 -0
- package/dist/fileDrop/index.d.ts +109 -0
- package/dist/fileDrop/index.d.ts.map +1 -0
- package/dist/fileDrop/index.js +127 -0
- package/dist/fileDrop/public.d.ts +3 -0
- package/dist/fileDrop/public.d.ts.map +1 -0
- package/dist/fileDrop/public.js +1 -0
- package/dist/group.d.ts +8 -0
- package/dist/group.d.ts.map +1 -0
- package/dist/group.js +13 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/input/index.d.ts +26 -0
- package/dist/input/index.d.ts.map +1 -0
- package/dist/input/index.js +43 -0
- package/dist/input/public.d.ts +3 -0
- package/dist/input/public.d.ts.map +1 -0
- package/dist/input/public.js +1 -0
- package/dist/internal/optionExtensions.d.ts +6 -0
- package/dist/internal/optionExtensions.d.ts.map +1 -0
- package/dist/internal/optionExtensions.js +2 -0
- package/dist/keyboard.d.ts +6 -0
- package/dist/keyboard.d.ts.map +1 -0
- package/dist/keyboard.js +9 -0
- package/dist/listbox/multi.d.ts +189 -0
- package/dist/listbox/multi.d.ts.map +1 -0
- package/dist/listbox/multi.js +65 -0
- package/dist/listbox/multiPublic.d.ts +3 -0
- package/dist/listbox/multiPublic.d.ts.map +1 -0
- package/dist/listbox/multiPublic.js +1 -0
- package/dist/listbox/public.d.ts +7 -0
- package/dist/listbox/public.d.ts.map +1 -0
- package/dist/listbox/public.js +3 -0
- package/dist/listbox/shared.d.ts +432 -0
- package/dist/listbox/shared.d.ts.map +1 -0
- package/dist/listbox/shared.js +670 -0
- package/dist/listbox/single.d.ts +207 -0
- package/dist/listbox/single.d.ts.map +1 -0
- package/dist/listbox/single.js +73 -0
- package/dist/menu/index.d.ts +368 -0
- package/dist/menu/index.d.ts.map +1 -0
- package/dist/menu/index.js +682 -0
- package/dist/menu/public.d.ts +4 -0
- package/dist/menu/public.d.ts.map +1 -0
- package/dist/menu/public.js +1 -0
- package/dist/popover/index.d.ts +267 -0
- package/dist/popover/index.d.ts.map +1 -0
- package/dist/popover/index.js +346 -0
- package/dist/popover/public.d.ts +4 -0
- package/dist/popover/public.d.ts.map +1 -0
- package/dist/popover/public.js +1 -0
- package/dist/radioGroup/index.d.ts +169 -0
- package/dist/radioGroup/index.d.ts.map +1 -0
- package/dist/radioGroup/index.js +197 -0
- package/dist/radioGroup/public.d.ts +3 -0
- package/dist/radioGroup/public.d.ts.map +1 -0
- package/dist/radioGroup/public.js +1 -0
- package/dist/select/index.d.ts +24 -0
- package/dist/select/index.d.ts.map +1 -0
- package/dist/select/index.js +40 -0
- package/dist/select/public.d.ts +3 -0
- package/dist/select/public.d.ts.map +1 -0
- package/dist/select/public.js +1 -0
- package/dist/slider/index.d.ts +318 -0
- package/dist/slider/index.d.ts.map +1 -0
- package/dist/slider/index.js +337 -0
- package/dist/slider/public.d.ts +3 -0
- package/dist/slider/public.d.ts.map +1 -0
- package/dist/slider/public.js +1 -0
- package/dist/switch/index.d.ts +99 -0
- package/dist/switch/index.d.ts.map +1 -0
- package/dist/switch/index.js +107 -0
- package/dist/switch/public.d.ts +3 -0
- package/dist/switch/public.d.ts.map +1 -0
- package/dist/switch/public.js +1 -0
- package/dist/tabs/index.d.ts +155 -0
- package/dist/tabs/index.d.ts.map +1 -0
- package/dist/tabs/index.js +185 -0
- package/dist/tabs/public.d.ts +3 -0
- package/dist/tabs/public.d.ts.map +1 -0
- package/dist/tabs/public.js +1 -0
- package/dist/test/apps/disabledButton.d.ts +38 -0
- package/dist/test/apps/disabledButton.d.ts.map +1 -0
- package/dist/test/apps/disabledButton.js +71 -0
- package/dist/textarea/index.d.ts +26 -0
- package/dist/textarea/index.d.ts.map +1 -0
- package/dist/textarea/index.js +44 -0
- package/dist/textarea/public.d.ts +3 -0
- package/dist/textarea/public.d.ts.map +1 -0
- package/dist/textarea/public.js +1 -0
- package/dist/toast/index.d.ts +608 -0
- package/dist/toast/index.d.ts.map +1 -0
- package/dist/toast/index.js +146 -0
- package/dist/toast/public.d.ts +4 -0
- package/dist/toast/public.d.ts.map +1 -0
- package/dist/toast/public.js +1 -0
- package/dist/toast/schema.d.ts +154 -0
- package/dist/toast/schema.d.ts.map +1 -0
- package/dist/toast/schema.js +93 -0
- package/dist/toast/update.d.ts +510 -0
- package/dist/toast/update.d.ts.map +1 -0
- package/dist/toast/update.js +225 -0
- package/dist/tooltip/index.d.ts +170 -0
- package/dist/tooltip/index.d.ts.map +1 -0
- package/dist/tooltip/index.js +253 -0
- package/dist/tooltip/public.d.ts +4 -0
- package/dist/tooltip/public.d.ts.map +1 -0
- package/dist/tooltip/public.js +1 -0
- package/dist/typeahead.d.ts +4 -0
- package/dist/typeahead.d.ts.map +1 -0
- package/dist/typeahead.js +14 -0
- package/dist/virtualList/index.d.ts +203 -0
- package/dist/virtualList/index.d.ts.map +1 -0
- package/dist/virtualList/index.js +392 -0
- package/dist/virtualList/public.d.ts +3 -0
- package/dist/virtualList/public.d.ts.map +1 -0
- package/dist/virtualList/public.js +1 -0
- package/dist/vitest-setup.d.ts +2 -0
- package/dist/vitest-setup.d.ts.map +1 -0
- package/dist/vitest-setup.js +2 -0
- package/package.json +161 -0
|
@@ -0,0 +1,207 @@
|
|
|
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 listbox component's state, tracking open/closed status, active item, selected item, activation trigger, and typeahead search. */
|
|
6
|
+
export declare const Model: S.Struct<{
|
|
7
|
+
readonly maybeSelectedItem: S.Option<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 single-select listbox model with `init`. `isAnimated` enables CSS transition coordination (default `false`). `isModal` locks page scroll and inerts other elements when open (default `false`). `selectedItem` sets the initial selection (default none). */
|
|
30
|
+
export type InitConfig = BaseInitConfig & Readonly<{
|
|
31
|
+
selectedItem?: string;
|
|
32
|
+
}>;
|
|
33
|
+
/** Creates an initial single-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. Closes the listbox on selection (single-select behavior); emits a `Selected({ value, wasAdded: true })` OutMessage. */
|
|
36
|
+
export declare const update: (model: {
|
|
37
|
+
readonly maybeSelectedItem: Option.Option<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 maybeSelectedItem: Option.Option<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 selects an item in the single-select listbox, closing the listbox and emitting a `Selected({ value, wasAdded: true })` OutMessage. */
|
|
165
|
+
export declare const selectItem: (model: Model, item: string) => UpdateReturn;
|
|
166
|
+
/** Reflects an externally-sourced selection onto the model without
|
|
167
|
+
* emitting an OutMessage or running the user-selection side effects (no
|
|
168
|
+
* close, no focus). Use this to mirror external truth (a URL parameter,
|
|
169
|
+
* restored storage, a server push) onto the listbox's selection.
|
|
170
|
+
* Contrast with `selectItem`, which represents a user or programmatic
|
|
171
|
+
* *choice*: it closes the listbox, restores focus, and emits `Selected`.
|
|
172
|
+
* `reflect` returns the model directly because it produces no commands and
|
|
173
|
+
* no OutMessage, so a parent reflecting external state cannot
|
|
174
|
+
* accidentally echo it back out. */
|
|
175
|
+
export declare const reflectSelectedItem: Reflect<Model, Option.Option<string>>;
|
|
176
|
+
/** Per-render view inputs passed to the view via `h.submodel`'s `viewInputs` field. */
|
|
177
|
+
export type ViewInputs<Item, Value extends string = string> = BaseViewInputs<Item, Value>;
|
|
178
|
+
/** Pairs the single-select listbox's `view` and `update` (and programmatic
|
|
179
|
+
* helpers) behind a single Item-typed entry point. Declaring the listbox
|
|
180
|
+
* once at module scope ensures the view's `Item` type and the update's
|
|
181
|
+
* OutMessage `item` type can't drift:
|
|
182
|
+
*
|
|
183
|
+
* ```ts
|
|
184
|
+
* const ColorListbox = Listbox.create<Color>()
|
|
185
|
+
*
|
|
186
|
+
* // In view:
|
|
187
|
+
* h.submodel({ view: ColorListbox.view, ... })
|
|
188
|
+
*
|
|
189
|
+
* // In update:
|
|
190
|
+
* const [next, commands, maybeOutMessage] = ColorListbox.update(model, message)
|
|
191
|
+
* // maybeOutMessage: Option<Listbox.OutMessage<Color>>
|
|
192
|
+
* ```
|
|
193
|
+
*
|
|
194
|
+
* Two type params support object-typed items with an `itemToValue`
|
|
195
|
+
* extractor: pass `<Person, string>` when items are objects whose
|
|
196
|
+
* extracted value is a plain string. `Value` defaults to `Item` when
|
|
197
|
+
* `Item extends string`, else defaults to `string`. */
|
|
198
|
+
export declare const create: <Item = string, Value extends string = Item extends string ? Item : string>() => Readonly<{
|
|
199
|
+
view: SubmodelView<Model, Message, BaseViewInputs<Item, Value>>;
|
|
200
|
+
update: (model: Model, message: Message) => readonly [Model, ReadonlyArray<Command.Command<Message>>, Option.Option<OutMessage<Value>>];
|
|
201
|
+
selectItem: (model: Model, item: Value) => readonly [Model, ReadonlyArray<Command.Command<Message>>, Option.Option<OutMessage<Value>>];
|
|
202
|
+
open: (model: Model) => readonly [Model, ReadonlyArray<Command.Command<Message>>, Option.Option<OutMessage<Value>>];
|
|
203
|
+
close: (model: Model) => readonly [Model, ReadonlyArray<Command.Command<Message>>, Option.Option<OutMessage<Value>>];
|
|
204
|
+
reflectSelectedItem: Reflect<Model, Option.Option<Value>>;
|
|
205
|
+
}>;
|
|
206
|
+
export {};
|
|
207
|
+
//# sourceMappingURL=single.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"single.d.ts","sourceRoot":"","sources":["../../src/listbox/single.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Array, Function, Option, Schema as S } 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 listbox component's state, tracking open/closed status, active item, selected item, activation trigger, and typeahead search. */
|
|
6
|
+
export const Model = S.Struct({
|
|
7
|
+
...BaseModel.fields,
|
|
8
|
+
maybeSelectedItem: S.Option(S.String),
|
|
9
|
+
});
|
|
10
|
+
/** Creates an initial single-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
|
+
maybeSelectedItem: Option.fromNullishOr(config.selectedItem),
|
|
14
|
+
});
|
|
15
|
+
// UPDATE
|
|
16
|
+
/** Processes a listbox message and returns the next model, commands, and optional OutMessage. Closes the listbox on selection (single-select behavior); emits a `Selected({ value, wasAdded: true })` OutMessage. */
|
|
17
|
+
export const update = makeUpdate((model, item, context) => context.closeWithFocus(evo(model, { maybeSelectedItem: () => Option.some(item) }), Option.some(SharedSelected({ value: item, wasAdded: true }))));
|
|
18
|
+
/** Programmatically opens the listbox, updating the model and returning
|
|
19
|
+
* focus and modal commands. Use this in domain-event handlers to open the listbox. */
|
|
20
|
+
export const open = (model) => update(model, Opened({ maybeActiveItemIndex: Option.none() }));
|
|
21
|
+
/** Programmatically closes the listbox, updating the model and returning
|
|
22
|
+
* focus and modal commands. Use this in domain-event handlers to close the listbox. */
|
|
23
|
+
export const close = (model) => update(model, Closed());
|
|
24
|
+
/** Programmatically selects an item in the single-select listbox, closing the listbox and emitting a `Selected({ value, wasAdded: true })` OutMessage. */
|
|
25
|
+
export const selectItem = (model, item) => update(model, SelectedItem({ item }));
|
|
26
|
+
/** Reflects an externally-sourced selection onto the model without
|
|
27
|
+
* emitting an OutMessage or running the user-selection side effects (no
|
|
28
|
+
* close, no focus). Use this to mirror external truth (a URL parameter,
|
|
29
|
+
* restored storage, a server push) onto the listbox's selection.
|
|
30
|
+
* Contrast with `selectItem`, which represents a user or programmatic
|
|
31
|
+
* *choice*: it closes the listbox, restores focus, and emits `Selected`.
|
|
32
|
+
* `reflect` returns the model directly because it produces no commands and
|
|
33
|
+
* no OutMessage, so a parent reflecting external state cannot
|
|
34
|
+
* accidentally echo it back out. */
|
|
35
|
+
export const reflectSelectedItem = Function.dual(2, (model, maybeItem) => evo(model, { maybeSelectedItem: () => maybeItem }));
|
|
36
|
+
const internalView = makeView({
|
|
37
|
+
isItemSelected: (model, itemValue) => Option.exists(model.maybeSelectedItem, selectedItem => selectedItem === itemValue),
|
|
38
|
+
selectedItemIndex: (model, items, itemToValue) => Option.flatMap(model.maybeSelectedItem, selectedItem => Array.findFirstIndex(items, item => itemToValue(item) === selectedItem)),
|
|
39
|
+
ariaMultiSelectable: false,
|
|
40
|
+
});
|
|
41
|
+
/** Pairs the single-select listbox's `view` and `update` (and programmatic
|
|
42
|
+
* helpers) behind a single Item-typed entry point. Declaring the listbox
|
|
43
|
+
* once at module scope ensures the view's `Item` type and the update's
|
|
44
|
+
* OutMessage `item` type can't drift:
|
|
45
|
+
*
|
|
46
|
+
* ```ts
|
|
47
|
+
* const ColorListbox = Listbox.create<Color>()
|
|
48
|
+
*
|
|
49
|
+
* // In view:
|
|
50
|
+
* h.submodel({ view: ColorListbox.view, ... })
|
|
51
|
+
*
|
|
52
|
+
* // In update:
|
|
53
|
+
* const [next, commands, maybeOutMessage] = ColorListbox.update(model, message)
|
|
54
|
+
* // maybeOutMessage: Option<Listbox.OutMessage<Color>>
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* Two type params support object-typed items with an `itemToValue`
|
|
58
|
+
* extractor: pass `<Person, string>` when items are objects whose
|
|
59
|
+
* extracted value is a plain string. `Value` defaults to `Item` when
|
|
60
|
+
* `Item extends string`, else defaults to `string`. */
|
|
61
|
+
export const create = () => {
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
63
|
+
const typedUpdate = update;
|
|
64
|
+
return {
|
|
65
|
+
view: internalView(),
|
|
66
|
+
update: typedUpdate,
|
|
67
|
+
selectItem: (model, item) => typedUpdate(model, SelectedItem({ item })),
|
|
68
|
+
open: model => typedUpdate(model, Opened({ maybeActiveItemIndex: Option.none() })),
|
|
69
|
+
close: model => typedUpdate(model, Closed()),
|
|
70
|
+
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
71
|
+
reflectSelectedItem: reflectSelectedItem,
|
|
72
|
+
};
|
|
73
|
+
};
|
|
@@ -0,0 +1,368 @@
|
|
|
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 * as Mount from 'foldkit/mount';
|
|
5
|
+
import { type View as SubmodelView } from 'foldkit/submodel';
|
|
6
|
+
import { AnchorConfig } from '../anchor.js';
|
|
7
|
+
import { groupContiguous } from '../group.js';
|
|
8
|
+
import { resolveTypeaheadMatch } from '../typeahead.js';
|
|
9
|
+
/** Schema for the activation trigger: whether the user interacted via mouse or keyboard. */
|
|
10
|
+
export declare const ActivationTrigger: S.Literals<readonly ["Pointer", "Keyboard"]>;
|
|
11
|
+
export type ActivationTrigger = typeof ActivationTrigger.Type;
|
|
12
|
+
/** Schema for the menu component's state, tracking open/closed status, active item, activation trigger, and typeahead search. */
|
|
13
|
+
export declare const Model: S.Struct<{
|
|
14
|
+
readonly id: S.String;
|
|
15
|
+
readonly isOpen: S.Boolean;
|
|
16
|
+
readonly isAnimated: S.Boolean;
|
|
17
|
+
readonly isModal: S.Boolean;
|
|
18
|
+
readonly animation: S.Struct<{
|
|
19
|
+
readonly id: S.String;
|
|
20
|
+
readonly isShowing: S.Boolean;
|
|
21
|
+
readonly transitionState: S.Literals<readonly ["Idle", "EnterStart", "EnterAnimating", "LeaveStart", "LeaveAnimating"]>;
|
|
22
|
+
}>;
|
|
23
|
+
readonly maybeActiveItemIndex: S.Option<S.Number>;
|
|
24
|
+
readonly activationTrigger: S.Literals<readonly ["Pointer", "Keyboard"]>;
|
|
25
|
+
readonly searchQuery: S.String;
|
|
26
|
+
readonly searchVersion: S.Number;
|
|
27
|
+
readonly maybeLastPointerPosition: S.Option<S.Struct<{
|
|
28
|
+
readonly screenX: S.Number;
|
|
29
|
+
readonly screenY: S.Number;
|
|
30
|
+
}>>;
|
|
31
|
+
readonly maybeLastButtonPointerType: S.Option<S.String>;
|
|
32
|
+
readonly maybePointerOrigin: S.Option<S.Struct<{
|
|
33
|
+
readonly screenX: S.Number;
|
|
34
|
+
readonly screenY: S.Number;
|
|
35
|
+
readonly timeStamp: S.Number;
|
|
36
|
+
}>>;
|
|
37
|
+
}>;
|
|
38
|
+
export type Model = typeof Model.Type;
|
|
39
|
+
/** Sent when the menu opens via button click or keyboard. Contains an optional initial active item index: None for pointer, Some for keyboard. */
|
|
40
|
+
export declare const Opened: import("foldkit/schema").CallableTaggedStruct<"Opened", {
|
|
41
|
+
maybeActiveItemIndex: S.Option<S.Number>;
|
|
42
|
+
}>;
|
|
43
|
+
/** Sent when the menu closes via Escape key or backdrop click. */
|
|
44
|
+
export declare const Closed: import("foldkit/schema").CallableTaggedStruct<"Closed", {}>;
|
|
45
|
+
/** Sent when the menu items container loses focus. */
|
|
46
|
+
export declare const BlurredItems: import("foldkit/schema").CallableTaggedStruct<"BlurredItems", {}>;
|
|
47
|
+
/** Sent when an item is highlighted via arrow keys or mouse hover. Includes activation trigger. */
|
|
48
|
+
export declare const ActivatedItem: import("foldkit/schema").CallableTaggedStruct<"ActivatedItem", {
|
|
49
|
+
index: S.Number;
|
|
50
|
+
activationTrigger: S.Literals<readonly ["Pointer", "Keyboard"]>;
|
|
51
|
+
}>;
|
|
52
|
+
/** Sent when the mouse leaves an enabled item. */
|
|
53
|
+
export declare const DeactivatedItem: import("foldkit/schema").CallableTaggedStruct<"DeactivatedItem", {}>;
|
|
54
|
+
/** Sent when an item is selected via Enter, Space, or click. */
|
|
55
|
+
export declare const SelectedItem: import("foldkit/schema").CallableTaggedStruct<"SelectedItem", {
|
|
56
|
+
index: S.Number;
|
|
57
|
+
item: S.String;
|
|
58
|
+
}>;
|
|
59
|
+
/** Sent when Enter or Space is pressed on the active item, triggering a programmatic click on the DOM element. */
|
|
60
|
+
export declare const RequestedItemClick: import("foldkit/schema").CallableTaggedStruct<"RequestedItemClick", {
|
|
61
|
+
index: S.Number;
|
|
62
|
+
}>;
|
|
63
|
+
/** Sent when a printable character is typed for typeahead search. */
|
|
64
|
+
export declare const Searched: import("foldkit/schema").CallableTaggedStruct<"Searched", {
|
|
65
|
+
key: S.String;
|
|
66
|
+
maybeTargetIndex: S.Option<S.Number>;
|
|
67
|
+
}>;
|
|
68
|
+
/** Sent after the search debounce period to clear the accumulated query. */
|
|
69
|
+
export declare const ClearedSearch: import("foldkit/schema").CallableTaggedStruct<"ClearedSearch", {
|
|
70
|
+
version: S.Number;
|
|
71
|
+
}>;
|
|
72
|
+
/** Sent when the pointer moves over a menu item, carrying screen coordinates for tracked-pointer comparison. */
|
|
73
|
+
export declare const MovedPointerOverItem: import("foldkit/schema").CallableTaggedStruct<"MovedPointerOverItem", {
|
|
74
|
+
index: S.Number;
|
|
75
|
+
screenX: S.Number;
|
|
76
|
+
screenY: S.Number;
|
|
77
|
+
}>;
|
|
78
|
+
/** Sent when the focus-items command completes after opening the menu. */
|
|
79
|
+
export declare const CompletedFocusItems: import("foldkit/schema").CallableTaggedStruct<"CompletedFocusItems", {}>;
|
|
80
|
+
/** Sent when the focus-button command completes after closing or selecting. */
|
|
81
|
+
export declare const CompletedFocusButton: import("foldkit/schema").CallableTaggedStruct<"CompletedFocusButton", {}>;
|
|
82
|
+
/** Sent when the scroll lock command completes. */
|
|
83
|
+
export declare const CompletedLockScroll: import("foldkit/schema").CallableTaggedStruct<"CompletedLockScroll", {}>;
|
|
84
|
+
/** Sent when the scroll unlock command completes. */
|
|
85
|
+
export declare const CompletedUnlockScroll: import("foldkit/schema").CallableTaggedStruct<"CompletedUnlockScroll", {}>;
|
|
86
|
+
/** Sent when the inert-others command completes. */
|
|
87
|
+
export declare const CompletedInertOthers: import("foldkit/schema").CallableTaggedStruct<"CompletedInertOthers", {}>;
|
|
88
|
+
/** Sent when the restore-inert command completes. */
|
|
89
|
+
export declare const CompletedRestoreInert: import("foldkit/schema").CallableTaggedStruct<"CompletedRestoreInert", {}>;
|
|
90
|
+
/** Sent when the scroll-into-view command completes after keyboard activation. */
|
|
91
|
+
export declare const CompletedScrollIntoView: import("foldkit/schema").CallableTaggedStruct<"CompletedScrollIntoView", {}>;
|
|
92
|
+
/** Sent when the programmatic click command completes. */
|
|
93
|
+
export declare const CompletedClickItem: import("foldkit/schema").CallableTaggedStruct<"CompletedClickItem", {}>;
|
|
94
|
+
/** Sent when a mouse click on the button is ignored because pointer-down already handled the toggle. */
|
|
95
|
+
export declare const IgnoredMouseClick: import("foldkit/schema").CallableTaggedStruct<"IgnoredMouseClick", {}>;
|
|
96
|
+
/** Sent when a Space key-up is captured to prevent page scrolling. */
|
|
97
|
+
export declare const SuppressedSpaceScroll: import("foldkit/schema").CallableTaggedStruct<"SuppressedSpaceScroll", {}>;
|
|
98
|
+
/** Sent when the menu items panel mounts and Floating UI has positioned it. Update no-ops; the side effect is the act of positioning, surfaced for DevTools observability. */
|
|
99
|
+
export declare const CompletedAnchorMenu: import("foldkit/schema").CallableTaggedStruct<"CompletedAnchorMenu", {}>;
|
|
100
|
+
/** Sent when the menu backdrop mounts and is portaled to the document body. Update no-ops; surfaces the portal side effect for DevTools. */
|
|
101
|
+
export declare const CompletedPortalMenuBackdrop: import("foldkit/schema").CallableTaggedStruct<"CompletedPortalMenuBackdrop", {}>;
|
|
102
|
+
/** Wraps an Animation submodel message for delegation. */
|
|
103
|
+
export declare const GotAnimationMessage: import("foldkit/schema").CallableTaggedStruct<"GotAnimationMessage", {
|
|
104
|
+
message: S.Union<[import("foldkit/schema").CallableTaggedStruct<"Showed", {}>, import("foldkit/schema").CallableTaggedStruct<"Hid", {}>, import("foldkit/schema").CallableTaggedStruct<"AdvancedAnimationFrame", {}>, import("foldkit/schema").CallableTaggedStruct<"EndedAnimation", {}>]>;
|
|
105
|
+
}>;
|
|
106
|
+
/** Sent when the user presses a pointer device on the menu button. Records pointer type and toggles for mouse. */
|
|
107
|
+
export declare const PressedPointerOnButton: import("foldkit/schema").CallableTaggedStruct<"PressedPointerOnButton", {
|
|
108
|
+
pointerType: S.String;
|
|
109
|
+
button: S.Number;
|
|
110
|
+
screenX: S.Number;
|
|
111
|
+
screenY: S.Number;
|
|
112
|
+
timeStamp: S.Number;
|
|
113
|
+
}>;
|
|
114
|
+
/** Sent when the user releases a pointer on the items container, enabling drag-to-select for mouse. */
|
|
115
|
+
export declare const ReleasedPointerOnItems: import("foldkit/schema").CallableTaggedStruct<"ReleasedPointerOnItems", {
|
|
116
|
+
screenX: S.Number;
|
|
117
|
+
screenY: S.Number;
|
|
118
|
+
timeStamp: S.Number;
|
|
119
|
+
}>;
|
|
120
|
+
/** Union of all messages the menu component can produce. */
|
|
121
|
+
export declare const Message: S.Union<[
|
|
122
|
+
typeof Opened,
|
|
123
|
+
typeof Closed,
|
|
124
|
+
typeof BlurredItems,
|
|
125
|
+
typeof ActivatedItem,
|
|
126
|
+
typeof DeactivatedItem,
|
|
127
|
+
typeof SelectedItem,
|
|
128
|
+
typeof MovedPointerOverItem,
|
|
129
|
+
typeof RequestedItemClick,
|
|
130
|
+
typeof Searched,
|
|
131
|
+
typeof ClearedSearch,
|
|
132
|
+
typeof CompletedFocusItems,
|
|
133
|
+
typeof CompletedFocusButton,
|
|
134
|
+
typeof CompletedLockScroll,
|
|
135
|
+
typeof CompletedUnlockScroll,
|
|
136
|
+
typeof CompletedInertOthers,
|
|
137
|
+
typeof CompletedRestoreInert,
|
|
138
|
+
typeof CompletedScrollIntoView,
|
|
139
|
+
typeof CompletedClickItem,
|
|
140
|
+
typeof IgnoredMouseClick,
|
|
141
|
+
typeof SuppressedSpaceScroll,
|
|
142
|
+
typeof CompletedAnchorMenu,
|
|
143
|
+
typeof CompletedPortalMenuBackdrop,
|
|
144
|
+
typeof GotAnimationMessage,
|
|
145
|
+
typeof PressedPointerOnButton,
|
|
146
|
+
typeof ReleasedPointerOnItems
|
|
147
|
+
]>;
|
|
148
|
+
export type Message = typeof Message.Type;
|
|
149
|
+
/** Sent to the parent when a menu item is selected. Carries both the selected value (from the `viewInputs.items` array supplied at view time) and its index. The menu has already closed when this fires; the parent does not need to dispatch `Menu.close`. */
|
|
150
|
+
export declare const Selected: import("foldkit/schema").CallableTaggedStruct<"Selected", {
|
|
151
|
+
value: S.String;
|
|
152
|
+
index: S.Number;
|
|
153
|
+
}>;
|
|
154
|
+
export type Selected<Value extends string = string> = Readonly<{
|
|
155
|
+
readonly _tag: 'Selected';
|
|
156
|
+
readonly value: Value;
|
|
157
|
+
readonly index: number;
|
|
158
|
+
}>;
|
|
159
|
+
/** Union of out-messages the menu component can produce. Surfaced as the third element of `update`'s return tuple and pattern-matched by the parent. */
|
|
160
|
+
export declare const OutMessage: S.Union<readonly [import("foldkit/schema").CallableTaggedStruct<"Selected", {
|
|
161
|
+
value: S.String;
|
|
162
|
+
index: S.Number;
|
|
163
|
+
}>]>;
|
|
164
|
+
/** Generic over `Value extends string` so consumers using the typed
|
|
165
|
+
* `Menu.create<MyUnion>()` factory receive `value: MyUnion` in the
|
|
166
|
+
* `Selected` OutMessage. Defaults to `string`. */
|
|
167
|
+
export type OutMessage<Value extends string = string> = Selected<Value>;
|
|
168
|
+
export type Opened = typeof Opened.Type;
|
|
169
|
+
export type Closed = typeof Closed.Type;
|
|
170
|
+
export type BlurredItems = typeof BlurredItems.Type;
|
|
171
|
+
export type ActivatedItem = typeof ActivatedItem.Type;
|
|
172
|
+
export type DeactivatedItem = typeof DeactivatedItem.Type;
|
|
173
|
+
export type SelectedItem = typeof SelectedItem.Type;
|
|
174
|
+
export type MovedPointerOverItem = typeof MovedPointerOverItem.Type;
|
|
175
|
+
export type RequestedItemClick = typeof RequestedItemClick.Type;
|
|
176
|
+
export type Searched = typeof Searched.Type;
|
|
177
|
+
export type ClearedSearch = typeof ClearedSearch.Type;
|
|
178
|
+
export type IgnoredMouseClick = typeof IgnoredMouseClick.Type;
|
|
179
|
+
export type SuppressedSpaceScroll = typeof SuppressedSpaceScroll.Type;
|
|
180
|
+
export type PressedPointerOnButton = typeof PressedPointerOnButton.Type;
|
|
181
|
+
export type ReleasedPointerOnItems = typeof ReleasedPointerOnItems.Type;
|
|
182
|
+
/** Configuration for creating a menu model with `init`. `isAnimated` enables animation coordination (default `false`). `isModal` locks page scroll and inerts other elements when open (default `false`). */
|
|
183
|
+
export type InitConfig = Readonly<{
|
|
184
|
+
id: string;
|
|
185
|
+
isAnimated?: boolean;
|
|
186
|
+
isModal?: boolean;
|
|
187
|
+
}>;
|
|
188
|
+
/** Creates an initial menu model from a config. Defaults to closed with no active item. */
|
|
189
|
+
export declare const init: (config: InitConfig) => Model;
|
|
190
|
+
type UpdateReturn = readonly [
|
|
191
|
+
Model,
|
|
192
|
+
ReadonlyArray<Command.Command<Message>>,
|
|
193
|
+
Option.Option<OutMessage>
|
|
194
|
+
];
|
|
195
|
+
/** Prevents page scrolling while the menu is open. */
|
|
196
|
+
export declare const LockScroll: Command.CommandDefinitionNoArgs<"LockScroll", Effect.Effect<{
|
|
197
|
+
readonly _tag: "CompletedLockScroll";
|
|
198
|
+
}, never, never>>;
|
|
199
|
+
/** Re-enables page scrolling after the menu closes. */
|
|
200
|
+
export declare const UnlockScroll: Command.CommandDefinitionNoArgs<"UnlockScroll", Effect.Effect<{
|
|
201
|
+
readonly _tag: "CompletedUnlockScroll";
|
|
202
|
+
}, never, never>>;
|
|
203
|
+
/** Marks all elements outside the menu as inert for modal behavior. */
|
|
204
|
+
export declare const InertOthers: Command.CommandDefinitionWithArgs<"InertOthers", {
|
|
205
|
+
id: S.String;
|
|
206
|
+
}, Effect.Effect<{
|
|
207
|
+
readonly _tag: "CompletedInertOthers";
|
|
208
|
+
}, never, never>>;
|
|
209
|
+
/** Removes the inert attribute from elements outside the menu. */
|
|
210
|
+
export declare const RestoreInert: Command.CommandDefinitionWithArgs<"RestoreInert", {
|
|
211
|
+
id: S.String;
|
|
212
|
+
}, Effect.Effect<{
|
|
213
|
+
readonly _tag: "CompletedRestoreInert";
|
|
214
|
+
}, never, never>>;
|
|
215
|
+
/** Moves focus to the menu items container after opening. */
|
|
216
|
+
export declare const FocusItems: Command.CommandDefinitionWithArgs<"FocusItems", {
|
|
217
|
+
id: S.String;
|
|
218
|
+
}, Effect.Effect<{
|
|
219
|
+
readonly _tag: "CompletedFocusItems";
|
|
220
|
+
}, never, never>>;
|
|
221
|
+
/** Moves focus back to the menu button after closing. */
|
|
222
|
+
export declare const FocusButton: Command.CommandDefinitionWithArgs<"FocusButton", {
|
|
223
|
+
id: S.String;
|
|
224
|
+
}, Effect.Effect<{
|
|
225
|
+
readonly _tag: "CompletedFocusButton";
|
|
226
|
+
}, never, never>>;
|
|
227
|
+
/** Scrolls the active menu item into view after keyboard navigation. */
|
|
228
|
+
export declare const ScrollIntoView: Command.CommandDefinitionWithArgs<"ScrollIntoView", {
|
|
229
|
+
id: S.String;
|
|
230
|
+
index: S.Number;
|
|
231
|
+
}, Effect.Effect<{
|
|
232
|
+
readonly _tag: "CompletedScrollIntoView";
|
|
233
|
+
}, never, never>>;
|
|
234
|
+
/** Programmatically clicks the active menu item's DOM element. */
|
|
235
|
+
export declare const ClickItem: Command.CommandDefinitionWithArgs<"ClickItem", {
|
|
236
|
+
id: S.String;
|
|
237
|
+
index: S.Number;
|
|
238
|
+
}, Effect.Effect<{
|
|
239
|
+
readonly _tag: "CompletedClickItem";
|
|
240
|
+
}, never, never>>;
|
|
241
|
+
/** Waits for the typeahead search debounce period before clearing the query. */
|
|
242
|
+
export declare const DelayClearSearch: Command.CommandDefinitionWithArgs<"DelayClearSearch", {
|
|
243
|
+
version: S.Number;
|
|
244
|
+
}, Effect.Effect<{
|
|
245
|
+
readonly _tag: "ClearedSearch";
|
|
246
|
+
readonly version: number;
|
|
247
|
+
}, never, never>>;
|
|
248
|
+
/** Detects whether the menu button moved or the leave animation ended. Whichever comes first; both outcomes signal the Animation submodel that leave is complete. */
|
|
249
|
+
export declare const DetectMovementOrAnimationEnd: Command.CommandDefinitionWithArgs<"DetectMovementOrAnimationEnd", {
|
|
250
|
+
id: S.String;
|
|
251
|
+
}, Effect.Effect<{
|
|
252
|
+
readonly _tag: "GotAnimationMessage";
|
|
253
|
+
readonly message: {
|
|
254
|
+
readonly _tag: "Showed";
|
|
255
|
+
} | {
|
|
256
|
+
readonly _tag: "Hid";
|
|
257
|
+
} | {
|
|
258
|
+
readonly _tag: "AdvancedAnimationFrame";
|
|
259
|
+
} | {
|
|
260
|
+
readonly _tag: "EndedAnimation";
|
|
261
|
+
};
|
|
262
|
+
}, never, never>>;
|
|
263
|
+
/** Processes a menu message and returns the next model and commands. */
|
|
264
|
+
export declare const update: (model: Model, message: Message) => UpdateReturn;
|
|
265
|
+
/** The anchor-positioning Mount this Menu renders on its panel. The panel is
|
|
266
|
+
* always anchored to the button via Floating UI and portaled to the document
|
|
267
|
+
* body (opt out of portaling with `anchor.portal: false`), so it escapes
|
|
268
|
+
* ancestor stacking contexts and overflow clipping. Exposed so Scene tests
|
|
269
|
+
* can call `Scene.Mount.resolve(AnchorMenu, CompletedAnchorMenu())`. */
|
|
270
|
+
export declare const AnchorMenu: Mount.MountDefinitionWithArgs<"AnchorMenu", {
|
|
271
|
+
buttonId: S.String;
|
|
272
|
+
anchor: S.Struct<{
|
|
273
|
+
readonly placement: S.optional<S.Literals<readonly ["top", "right", "bottom", "left", "top-start", "top-end", "right-start", "right-end", "bottom-start", "bottom-end", "left-start", "left-end"]>>;
|
|
274
|
+
readonly gap: S.optional<S.Number>;
|
|
275
|
+
readonly offset: S.optional<S.Number>;
|
|
276
|
+
readonly padding: S.optional<S.Number>;
|
|
277
|
+
readonly portal: S.optional<S.Boolean>;
|
|
278
|
+
}>;
|
|
279
|
+
}, {
|
|
280
|
+
readonly _tag: "CompletedAnchorMenu";
|
|
281
|
+
}>;
|
|
282
|
+
/** The backdrop-portaling Mount this Menu renders. Exposed so Scene tests can
|
|
283
|
+
* call `Scene.Mount.resolve(PortalMenuBackdrop, CompletedPortalMenuBackdrop())` to
|
|
284
|
+
* acknowledge the mount produced by the rendered backdrop. */
|
|
285
|
+
export declare const PortalMenuBackdrop: Mount.MountDefinitionNoArgs<"PortalMenuBackdrop", {
|
|
286
|
+
readonly _tag: "CompletedPortalMenuBackdrop";
|
|
287
|
+
}>;
|
|
288
|
+
/** Programmatically opens the menu, updating the model and returning
|
|
289
|
+
* focus and modal commands. Use this in domain-event handlers to open the menu. */
|
|
290
|
+
export declare const open: (model: Model) => UpdateReturn;
|
|
291
|
+
/** Programmatically closes the menu, updating the model and returning
|
|
292
|
+
* focus and modal commands. Use this in domain-event handlers to close the menu. */
|
|
293
|
+
export declare const close: (model: Model) => UpdateReturn;
|
|
294
|
+
/** Programmatically selects a menu item, closing the menu and returning
|
|
295
|
+
* focus commands plus a `Selected` OutMessage. Use this in domain-event handlers. */
|
|
296
|
+
export declare const selectItem: (model: Model, item: string, index: number) => UpdateReturn;
|
|
297
|
+
/** Configuration for an individual menu item's appearance. */
|
|
298
|
+
export type ItemConfig = Readonly<{
|
|
299
|
+
className?: string;
|
|
300
|
+
content: Html;
|
|
301
|
+
}>;
|
|
302
|
+
/** Configuration for a group heading rendered above a group of items. */
|
|
303
|
+
export type GroupHeading = Readonly<{
|
|
304
|
+
content: Html;
|
|
305
|
+
className?: string;
|
|
306
|
+
}>;
|
|
307
|
+
/** Per-render view inputs passed to `view` via `h.submodel`'s `viewInputs` field.
|
|
308
|
+
*
|
|
309
|
+
* The Menu emits a `Selected({ value, index })` OutMessage on commit.
|
|
310
|
+
* The menu has already closed by the time this fires; consumers
|
|
311
|
+
* pattern-match it in their `GotMenuMessage` handler to react. */
|
|
312
|
+
export type ViewInputs<Item extends string> = Readonly<{
|
|
313
|
+
items: ReadonlyArray<Item>;
|
|
314
|
+
itemToConfig: (item: Item, context: Readonly<{
|
|
315
|
+
isActive: boolean;
|
|
316
|
+
isDisabled: boolean;
|
|
317
|
+
}>) => ItemConfig;
|
|
318
|
+
isItemDisabled?: (item: Item, index: number) => boolean;
|
|
319
|
+
itemToSearchText?: (item: Item, index: number) => string;
|
|
320
|
+
isButtonDisabled?: boolean;
|
|
321
|
+
buttonContent: Html;
|
|
322
|
+
buttonClassName?: string;
|
|
323
|
+
buttonAttributes?: ReadonlyArray<ChildAttribute>;
|
|
324
|
+
itemsClassName?: string;
|
|
325
|
+
itemsAttributes?: ReadonlyArray<ChildAttribute>;
|
|
326
|
+
itemsScrollClassName?: string;
|
|
327
|
+
itemsScrollAttributes?: ReadonlyArray<ChildAttribute>;
|
|
328
|
+
backdropClassName?: string;
|
|
329
|
+
backdropAttributes?: ReadonlyArray<ChildAttribute>;
|
|
330
|
+
className?: string;
|
|
331
|
+
attributes?: ReadonlyArray<ChildAttribute>;
|
|
332
|
+
itemGroupKey?: (item: Item, index: number) => string;
|
|
333
|
+
groupToHeading?: (groupKey: string) => GroupHeading | undefined;
|
|
334
|
+
groupClassName?: string;
|
|
335
|
+
groupAttributes?: ReadonlyArray<ChildAttribute>;
|
|
336
|
+
separatorClassName?: string;
|
|
337
|
+
separatorAttributes?: ReadonlyArray<ChildAttribute>;
|
|
338
|
+
anchor?: AnchorConfig;
|
|
339
|
+
}>;
|
|
340
|
+
export { groupContiguous, resolveTypeaheadMatch };
|
|
341
|
+
/** Headless menu view with typeahead search, keyboard navigation,
|
|
342
|
+
* and aria-activedescendant focus management. Obtained from
|
|
343
|
+
* `Menu.create<MyItem>().view`; not exported directly. */
|
|
344
|
+
type ViewForItem<Item extends string> = SubmodelView<Model, Message, ViewInputs<Item>>;
|
|
345
|
+
/** Pairs the menu's `view` and `update` (and programmatic helpers)
|
|
346
|
+
* behind a single Item-typed entry point. Declaring the menu once at
|
|
347
|
+
* module scope ensures the view's `Item` type and the OutMessage's
|
|
348
|
+
* `item` type can't drift:
|
|
349
|
+
*
|
|
350
|
+
* ```ts
|
|
351
|
+
* const ActionMenu = Menu.create<Action>()
|
|
352
|
+
*
|
|
353
|
+
* // In view:
|
|
354
|
+
* h.submodel({ view: ActionMenu.view, ... })
|
|
355
|
+
*
|
|
356
|
+
* // In update:
|
|
357
|
+
* const [next, commands, maybeOutMessage] = ActionMenu.update(model.menu, message)
|
|
358
|
+
* // maybeOutMessage: Option<Menu.OutMessage<Action>>
|
|
359
|
+
* ```
|
|
360
|
+
*/
|
|
361
|
+
export declare const create: <Item extends string = string>() => Readonly<{
|
|
362
|
+
view: ViewForItem<Item>;
|
|
363
|
+
update: (model: Model, message: Message) => readonly [Model, ReadonlyArray<Command.Command<Message>>, Option.Option<OutMessage<Item>>];
|
|
364
|
+
selectItem: (model: Model, item: Item, index: number) => readonly [Model, ReadonlyArray<Command.Command<Message>>, Option.Option<OutMessage<Item>>];
|
|
365
|
+
open: (model: Model) => readonly [Model, ReadonlyArray<Command.Command<Message>>, Option.Option<OutMessage<Item>>];
|
|
366
|
+
close: (model: Model) => readonly [Model, ReadonlyArray<Command.Command<Message>>, Option.Option<OutMessage<Item>>];
|
|
367
|
+
}>;
|
|
368
|
+
//# sourceMappingURL=index.d.ts.map
|