foldkit 0.36.2 → 0.37.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/README.md +4 -5
- package/dist/command/index.d.ts +36 -2
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +11 -1
- package/dist/command/public.d.ts +1 -0
- package/dist/command/public.d.ts.map +1 -1
- package/dist/command/public.js +1 -1
- package/dist/devtools/overlay.d.ts.map +1 -1
- package/dist/devtools/overlay.js +16 -15
- package/dist/devtools/store.d.ts +2 -2
- package/dist/devtools/store.d.ts.map +1 -1
- package/dist/devtools/store.js +2 -2
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +10 -4
- package/dist/task/dom.d.ts +1 -9
- package/dist/task/dom.d.ts.map +1 -1
- package/dist/task/dom.js +81 -111
- package/dist/ui/combobox/multi.d.ts +56 -53
- package/dist/ui/combobox/multi.d.ts.map +1 -1
- package/dist/ui/combobox/shared.d.ts +63 -60
- package/dist/ui/combobox/shared.d.ts.map +1 -1
- package/dist/ui/combobox/shared.js +11 -10
- package/dist/ui/combobox/single.d.ts +56 -53
- package/dist/ui/combobox/single.d.ts.map +1 -1
- package/dist/ui/dialog/index.d.ts +2 -2
- package/dist/ui/dialog/index.d.ts.map +1 -1
- package/dist/ui/dialog/index.js +10 -7
- package/dist/ui/disclosure/index.d.ts +2 -2
- package/dist/ui/disclosure/index.d.ts.map +1 -1
- package/dist/ui/disclosure/index.js +3 -2
- package/dist/ui/listbox/multi.d.ts +65 -62
- package/dist/ui/listbox/multi.d.ts.map +1 -1
- package/dist/ui/listbox/shared.d.ts +71 -68
- package/dist/ui/listbox/shared.d.ts.map +1 -1
- package/dist/ui/listbox/shared.js +14 -13
- package/dist/ui/listbox/single.d.ts +65 -62
- package/dist/ui/listbox/single.d.ts.map +1 -1
- package/dist/ui/menu/index.d.ts +2 -2
- package/dist/ui/menu/index.d.ts.map +1 -1
- package/dist/ui/menu/index.js +17 -16
- package/dist/ui/popover/index.d.ts +2 -2
- package/dist/ui/popover/index.d.ts.map +1 -1
- package/dist/ui/popover/index.js +12 -11
- package/dist/ui/radioGroup/index.d.ts +2 -2
- package/dist/ui/radioGroup/index.d.ts.map +1 -1
- package/dist/ui/radioGroup/index.js +2 -1
- package/dist/ui/tabs/index.d.ts +2 -2
- package/dist/ui/tabs/index.d.ts.map +1 -1
- package/dist/ui/tabs/index.js +3 -2
- package/package.json +1 -1
package/dist/task/dom.js
CHANGED
|
@@ -13,7 +13,6 @@ const FOCUSABLE_SELECTOR = Array.join([
|
|
|
13
13
|
], ', ');
|
|
14
14
|
/**
|
|
15
15
|
* Focuses an element matching the given selector.
|
|
16
|
-
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to focus.
|
|
17
16
|
* Fails with `ElementNotFound` if the selector does not match an `HTMLElement`.
|
|
18
17
|
*
|
|
19
18
|
* @example
|
|
@@ -21,29 +20,22 @@ const FOCUSABLE_SELECTOR = Array.join([
|
|
|
21
20
|
* Task.focus('#email-input').pipe(Effect.ignore, Effect.as(CompletedInputFocus()))
|
|
22
21
|
* ```
|
|
23
22
|
*/
|
|
24
|
-
export const focus = (selector) => Effect.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
else {
|
|
32
|
-
resume(Effect.fail(new ElementNotFound({ selector })));
|
|
33
|
-
}
|
|
34
|
-
});
|
|
23
|
+
export const focus = (selector) => Effect.suspend(() => {
|
|
24
|
+
const element = document.querySelector(selector);
|
|
25
|
+
if (element instanceof HTMLElement) {
|
|
26
|
+
element.focus();
|
|
27
|
+
return Effect.void;
|
|
28
|
+
}
|
|
29
|
+
return Effect.fail(new ElementNotFound({ selector }));
|
|
35
30
|
});
|
|
36
31
|
/**
|
|
37
32
|
* Opens a dialog element using `show()` with high z-index, focus trapping,
|
|
38
33
|
* and Escape key handling. Uses `show()` instead of `showModal()` so that
|
|
39
34
|
* DevTools (and any other high-z-index overlay) remains interactive — the
|
|
40
35
|
* Dialog component provides its own backdrop, scroll locking, and transitions.
|
|
41
|
-
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to show.
|
|
42
36
|
* Fails with `ElementNotFound` if the selector does not match an `HTMLDialogElement`.
|
|
43
37
|
*
|
|
44
|
-
* Pass `focusSelector` to focus an element inside the dialog
|
|
45
|
-
* as `show()` — required on mobile browsers where `focus()` is ignored outside
|
|
46
|
-
* the original user-gesture call stack.
|
|
38
|
+
* Pass `focusSelector` to focus an element inside the dialog when it opens.
|
|
47
39
|
*
|
|
48
40
|
* @example
|
|
49
41
|
* ```typescript
|
|
@@ -51,43 +43,39 @@ export const focus = (selector) => Effect.async(resume => {
|
|
|
51
43
|
* Task.showModal('#my-dialog', { focusSelector: '#search-input' }).pipe(Effect.ignore, Effect.as(CompletedDialogShow()))
|
|
52
44
|
* ```
|
|
53
45
|
*/
|
|
54
|
-
export const showModal = (selector, options) => Effect.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
M.value(event.key).pipe(M.when('Escape', () => {
|
|
68
|
-
if (event.defaultPrevented) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
event.preventDefault();
|
|
72
|
-
element.dispatchEvent(new Event('cancel', { cancelable: true }));
|
|
73
|
-
}), M.when('Tab', () => {
|
|
74
|
-
trapFocusWithinDialog(event, element);
|
|
75
|
-
}), M.orElse(Function.constVoid));
|
|
76
|
-
};
|
|
77
|
-
document.addEventListener('keydown', handleKeydown);
|
|
78
|
-
dialogCleanups.set(element, () => document.removeEventListener('keydown', handleKeydown));
|
|
79
|
-
if (options?.focusSelector) {
|
|
80
|
-
const focusTarget = element.querySelector(options.focusSelector);
|
|
81
|
-
if (focusTarget instanceof HTMLElement) {
|
|
82
|
-
focusTarget.focus();
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
resume(Effect.void);
|
|
46
|
+
export const showModal = (selector, options) => Effect.suspend(() => {
|
|
47
|
+
const element = document.querySelector(selector);
|
|
48
|
+
if (!(element instanceof HTMLDialogElement)) {
|
|
49
|
+
return Effect.fail(new ElementNotFound({ selector }));
|
|
50
|
+
}
|
|
51
|
+
element.style.position = 'fixed';
|
|
52
|
+
element.style.inset = '0';
|
|
53
|
+
openDialogCount++;
|
|
54
|
+
element.style.zIndex = String(BASE_DIALOG_Z_INDEX + openDialogCount);
|
|
55
|
+
element.show();
|
|
56
|
+
const handleKeydown = (event) => {
|
|
57
|
+
if (!element.open) {
|
|
58
|
+
return;
|
|
86
59
|
}
|
|
87
|
-
|
|
88
|
-
|
|
60
|
+
M.value(event.key).pipe(M.when('Escape', () => {
|
|
61
|
+
if (event.defaultPrevented) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
event.preventDefault();
|
|
65
|
+
element.dispatchEvent(new Event('cancel', { cancelable: true }));
|
|
66
|
+
}), M.when('Tab', () => {
|
|
67
|
+
trapFocusWithinDialog(event, element);
|
|
68
|
+
}), M.orElse(Function.constVoid));
|
|
69
|
+
};
|
|
70
|
+
document.addEventListener('keydown', handleKeydown);
|
|
71
|
+
dialogCleanups.set(element, () => document.removeEventListener('keydown', handleKeydown));
|
|
72
|
+
if (options?.focusSelector) {
|
|
73
|
+
const focusTarget = element.querySelector(options.focusSelector);
|
|
74
|
+
if (focusTarget instanceof HTMLElement) {
|
|
75
|
+
focusTarget.focus();
|
|
89
76
|
}
|
|
90
|
-
}
|
|
77
|
+
}
|
|
78
|
+
return Effect.void;
|
|
91
79
|
});
|
|
92
80
|
const trapFocusWithinDialog = (event, dialog) => {
|
|
93
81
|
const focusable = Array.fromIterable(dialog.querySelectorAll(FOCUSABLE_SELECTOR));
|
|
@@ -107,7 +95,6 @@ const trapFocusWithinDialog = (event, dialog) => {
|
|
|
107
95
|
/**
|
|
108
96
|
* Closes a dialog element using `.close()`.
|
|
109
97
|
* Cleans up the keyboard handlers installed by `showModal`.
|
|
110
|
-
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to close.
|
|
111
98
|
* Fails with `ElementNotFound` if the selector does not match an `HTMLDialogElement`.
|
|
112
99
|
*
|
|
113
100
|
* @example
|
|
@@ -115,27 +102,22 @@ const trapFocusWithinDialog = (event, dialog) => {
|
|
|
115
102
|
* Task.closeModal('#my-dialog').pipe(Effect.ignore, Effect.as(CompletedDialogClose()))
|
|
116
103
|
* ```
|
|
117
104
|
*/
|
|
118
|
-
export const closeModal = (selector) => Effect.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
dialogCleanups.delete(element);
|
|
128
|
-
}
|
|
129
|
-
resume(Effect.void);
|
|
105
|
+
export const closeModal = (selector) => Effect.suspend(() => {
|
|
106
|
+
const element = document.querySelector(selector);
|
|
107
|
+
if (element instanceof HTMLDialogElement) {
|
|
108
|
+
element.close();
|
|
109
|
+
openDialogCount = Math.max(0, openDialogCount - 1);
|
|
110
|
+
const cleanup = dialogCleanups.get(element);
|
|
111
|
+
if (cleanup) {
|
|
112
|
+
cleanup();
|
|
113
|
+
dialogCleanups.delete(element);
|
|
130
114
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
});
|
|
115
|
+
return Effect.void;
|
|
116
|
+
}
|
|
117
|
+
return Effect.fail(new ElementNotFound({ selector }));
|
|
135
118
|
});
|
|
136
119
|
/**
|
|
137
120
|
* Programmatically clicks an element matching the given selector.
|
|
138
|
-
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to click.
|
|
139
121
|
* Fails with `ElementNotFound` if the selector does not match an `HTMLElement`.
|
|
140
122
|
*
|
|
141
123
|
* @example
|
|
@@ -143,21 +125,16 @@ export const closeModal = (selector) => Effect.async(resume => {
|
|
|
143
125
|
* Task.clickElement('#menu-item-2').pipe(Effect.ignore, Effect.as(CompletedItemClick()))
|
|
144
126
|
* ```
|
|
145
127
|
*/
|
|
146
|
-
export const clickElement = (selector) => Effect.
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
else {
|
|
154
|
-
resume(Effect.fail(new ElementNotFound({ selector })));
|
|
155
|
-
}
|
|
156
|
-
});
|
|
128
|
+
export const clickElement = (selector) => Effect.suspend(() => {
|
|
129
|
+
const element = document.querySelector(selector);
|
|
130
|
+
if (element instanceof HTMLElement) {
|
|
131
|
+
element.click();
|
|
132
|
+
return Effect.void;
|
|
133
|
+
}
|
|
134
|
+
return Effect.fail(new ElementNotFound({ selector }));
|
|
157
135
|
});
|
|
158
136
|
/**
|
|
159
137
|
* Scrolls an element into view by selector using `{ block: 'nearest' }`.
|
|
160
|
-
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to scroll.
|
|
161
138
|
* Fails with `ElementNotFound` if the selector does not match an `HTMLElement`.
|
|
162
139
|
*
|
|
163
140
|
* @example
|
|
@@ -165,21 +142,16 @@ export const clickElement = (selector) => Effect.async(resume => {
|
|
|
165
142
|
* Task.scrollIntoView('#active-item').pipe(Effect.ignore, Effect.as(CompletedScrollIntoView()))
|
|
166
143
|
* ```
|
|
167
144
|
*/
|
|
168
|
-
export const scrollIntoView = (selector) => Effect.
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
else {
|
|
176
|
-
resume(Effect.fail(new ElementNotFound({ selector })));
|
|
177
|
-
}
|
|
178
|
-
});
|
|
145
|
+
export const scrollIntoView = (selector) => Effect.suspend(() => {
|
|
146
|
+
const element = document.querySelector(selector);
|
|
147
|
+
if (element instanceof HTMLElement) {
|
|
148
|
+
element.scrollIntoView({ block: 'nearest' });
|
|
149
|
+
return Effect.void;
|
|
150
|
+
}
|
|
151
|
+
return Effect.fail(new ElementNotFound({ selector }));
|
|
179
152
|
});
|
|
180
153
|
/**
|
|
181
154
|
* Focuses the next or previous focusable element in the document relative to the element matching the given selector.
|
|
182
|
-
* Uses requestAnimationFrame to ensure the DOM is updated before querying focus order.
|
|
183
155
|
* Fails with `ElementNotFound` if the selector does not match an `HTMLElement`.
|
|
184
156
|
*
|
|
185
157
|
* @example
|
|
@@ -187,22 +159,20 @@ export const scrollIntoView = (selector) => Effect.async(resume => {
|
|
|
187
159
|
* Task.advanceFocus('#menu-button', 'Next').pipe(Effect.ignore, Effect.as(CompletedFocusAdvance()))
|
|
188
160
|
* ```
|
|
189
161
|
*/
|
|
190
|
-
export const advanceFocus = (selector, direction) => Effect.
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
resume(Effect.void);
|
|
207
|
-
});
|
|
162
|
+
export const advanceFocus = (selector, direction) => Effect.suspend(() => {
|
|
163
|
+
const reference = document.querySelector(selector);
|
|
164
|
+
if (!(reference instanceof HTMLElement)) {
|
|
165
|
+
return Effect.fail(new ElementNotFound({ selector }));
|
|
166
|
+
}
|
|
167
|
+
const focusableElements = Array.fromIterable(document.querySelectorAll(FOCUSABLE_SELECTOR));
|
|
168
|
+
const referenceElementIndex = Array.findFirstIndex(focusableElements, Equal.equals(reference));
|
|
169
|
+
if (Option.isNone(referenceElementIndex)) {
|
|
170
|
+
return Effect.fail(new ElementNotFound({ selector }));
|
|
171
|
+
}
|
|
172
|
+
const offsetReferenceElementIndex = M.value(direction).pipe(M.when('Next', () => Number.increment), M.when('Previous', () => Number.decrement), M.exhaustive)(referenceElementIndex.value);
|
|
173
|
+
const nextElement = Array.get(focusableElements, offsetReferenceElementIndex);
|
|
174
|
+
if (Option.isSome(nextElement)) {
|
|
175
|
+
nextElement.value.focus();
|
|
176
|
+
}
|
|
177
|
+
return Effect.void;
|
|
208
178
|
});
|
|
@@ -65,61 +65,64 @@ export declare const update: (model: {
|
|
|
65
65
|
}>;
|
|
66
66
|
} & {
|
|
67
67
|
readonly selectedItems: readonly string[];
|
|
68
|
-
}, readonly
|
|
69
|
-
readonly
|
|
70
|
-
readonly
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
} | {
|
|
74
|
-
|
|
75
|
-
} | {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
68
|
+
}, readonly {
|
|
69
|
+
readonly name: string;
|
|
70
|
+
readonly effect: import("effect/Effect").Effect<{
|
|
71
|
+
readonly _tag: "Opened";
|
|
72
|
+
readonly maybeActiveItemIndex: import("effect/Option").Option<number>;
|
|
73
|
+
} | {
|
|
74
|
+
readonly _tag: "Closed";
|
|
75
|
+
} | {
|
|
76
|
+
readonly _tag: "ClosedByTab";
|
|
77
|
+
} | {
|
|
78
|
+
readonly _tag: "ActivatedItem";
|
|
79
|
+
readonly index: number;
|
|
80
|
+
readonly activationTrigger: "Pointer" | "Keyboard";
|
|
81
|
+
readonly maybeImmediateSelection: import("effect/Option").Option<{
|
|
82
|
+
readonly item: string;
|
|
83
|
+
readonly displayText: string;
|
|
84
|
+
}>;
|
|
85
|
+
} | {
|
|
86
|
+
readonly _tag: "DeactivatedItem";
|
|
87
|
+
} | {
|
|
88
|
+
readonly _tag: "SelectedItem";
|
|
80
89
|
readonly item: string;
|
|
81
90
|
readonly displayText: string;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
} | {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
} | {
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
} | {
|
|
118
|
-
readonly _tag: "UpdatedInputValue";
|
|
119
|
-
readonly value: string;
|
|
120
|
-
} | {
|
|
121
|
-
readonly _tag: "PressedToggleButton";
|
|
122
|
-
}>[]];
|
|
91
|
+
} | {
|
|
92
|
+
readonly _tag: "MovedPointerOverItem";
|
|
93
|
+
readonly index: number;
|
|
94
|
+
readonly screenX: number;
|
|
95
|
+
readonly screenY: number;
|
|
96
|
+
} | {
|
|
97
|
+
readonly _tag: "RequestedItemClick";
|
|
98
|
+
readonly index: number;
|
|
99
|
+
} | {
|
|
100
|
+
readonly _tag: "CompletedScrollLock";
|
|
101
|
+
} | {
|
|
102
|
+
readonly _tag: "CompletedScrollUnlock";
|
|
103
|
+
} | {
|
|
104
|
+
readonly _tag: "CompletedInertSetup";
|
|
105
|
+
} | {
|
|
106
|
+
readonly _tag: "CompletedInertTeardown";
|
|
107
|
+
} | {
|
|
108
|
+
readonly _tag: "CompletedInputFocus";
|
|
109
|
+
} | {
|
|
110
|
+
readonly _tag: "CompletedScrollIntoView";
|
|
111
|
+
} | {
|
|
112
|
+
readonly _tag: "CompletedItemClick";
|
|
113
|
+
} | {
|
|
114
|
+
readonly _tag: "AdvancedTransitionFrame";
|
|
115
|
+
} | {
|
|
116
|
+
readonly _tag: "EndedTransition";
|
|
117
|
+
} | {
|
|
118
|
+
readonly _tag: "DetectedInputMovement";
|
|
119
|
+
} | {
|
|
120
|
+
readonly _tag: "UpdatedInputValue";
|
|
121
|
+
readonly value: string;
|
|
122
|
+
} | {
|
|
123
|
+
readonly _tag: "PressedToggleButton";
|
|
124
|
+
}, never, never>;
|
|
125
|
+
}[]];
|
|
123
126
|
/** Configuration for rendering a multi-select combobox with `view`. */
|
|
124
127
|
export type ViewConfig<Message, Item extends string> = BaseViewConfig<Message, Item, Model>;
|
|
125
128
|
/** Renders a headless multi-select combobox with keyboard navigation, selection tracking, and aria-activedescendant focus management. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multi.d.ts","sourceRoot":"","sources":["../../../src/ui/combobox/multi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAE3C,OAAO,EAAE,KAAK,IAAI,EAAc,MAAM,YAAY,CAAA;AAElD,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,cAAc,EAKpB,MAAM,UAAU,CAAA;AAIjB,yIAAyI;AACzI,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;GAEjB,CAAA;AAED,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,8RAA8R;AAC9R,MAAM,MAAM,UAAU,GAAG,cAAc,GACrC,QAAQ,CAAC;IACP,aAAa,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CACtC,CAAC,CAAA;AAEJ,2IAA2I;AAC3I,eAAO,MAAM,IAAI,GAAI,QAAQ,UAAU,KAAG,KAGxC,CAAA;AAcF,yJAAyJ;AACzJ,eAAO,MAAM,MAAM
|
|
1
|
+
{"version":3,"file":"multi.d.ts","sourceRoot":"","sources":["../../../src/ui/combobox/multi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAE3C,OAAO,EAAE,KAAK,IAAI,EAAc,MAAM,YAAY,CAAA;AAElD,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,cAAc,EAKpB,MAAM,UAAU,CAAA;AAIjB,yIAAyI;AACzI,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;GAEjB,CAAA;AAED,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,8RAA8R;AAC9R,MAAM,MAAM,UAAU,GAAG,cAAc,GACrC,QAAQ,CAAC;IACP,aAAa,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CACtC,CAAC,CAAA;AAEJ,2IAA2I;AAC3I,eAAO,MAAM,IAAI,GAAI,QAAQ,UAAU,KAAG,KAGxC,CAAA;AAcF,yJAAyJ;AACzJ,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAwBjB,CAAA;AAIF,uEAAuE;AACvE,MAAM,MAAM,UAAU,CAAC,OAAO,EAAE,IAAI,SAAS,MAAM,IAAI,cAAc,CACnE,OAAO,EACP,IAAI,EACJ,KAAK,CACN,CAAA;AAED,yIAAyI;AACzI,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAIf,CAAA;AAEF;6EAC6E;AAC7E,eAAO,MAAM,IAAI,GAAI,OAAO,EAAE,IAAI,SAAS,MAAM,EAC/C,cAAc,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC,KACnE,CAAC,CACF,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,cAAc,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,WAAW,CAAC,KACzD,IAAI,CAgBR,CAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Option, Schema as S } from 'effect';
|
|
2
|
-
import
|
|
1
|
+
import { Effect, Option, Schema as S } from 'effect';
|
|
2
|
+
import * as Command from '../../command';
|
|
3
3
|
import { type Attribute, type Html } from '../../html';
|
|
4
4
|
import type { AnchorConfig } from '../anchor';
|
|
5
5
|
import { groupContiguous } from '../group';
|
|
@@ -150,71 +150,74 @@ export declare const itemId: (id: string, index: number) => string;
|
|
|
150
150
|
export declare const closedBaseModel: <Model extends BaseModel>(model: Model) => Model;
|
|
151
151
|
/** Context passed to the `handleSelectedItem` handler with commands for focus management and modal cleanup. */
|
|
152
152
|
export type SelectedItemContext = Readonly<{
|
|
153
|
-
focusInput: Command<Message>;
|
|
154
|
-
maybeNextFrame: Option.Option<Command<Message>>;
|
|
155
|
-
maybeUnlockScroll: Option.Option<Command<Message>>;
|
|
156
|
-
maybeRestoreInert: Option.Option<Command<Message>>;
|
|
153
|
+
focusInput: Command.Command<Message>;
|
|
154
|
+
maybeNextFrame: Option.Option<Command.Command<Message>>;
|
|
155
|
+
maybeUnlockScroll: Option.Option<Command.Command<Message>>;
|
|
156
|
+
maybeRestoreInert: Option.Option<Command.Command<Message>>;
|
|
157
157
|
}>;
|
|
158
158
|
/** Creates a combobox update function from variant-specific handlers. Shared logic (open, close, activate, transition) is handled internally; only close, selection, and immediate-activation behavior varies by variant. */
|
|
159
159
|
export declare const makeUpdate: <Model extends BaseModel>(handlers: Readonly<{
|
|
160
160
|
handleClose: (model: Model) => Model;
|
|
161
|
-
handleSelectedItem: (model: Model, item: string, displayText: string, context: SelectedItemContext) => [Model, ReadonlyArray<Command<Message>>];
|
|
161
|
+
handleSelectedItem: (model: Model, item: string, displayText: string, context: SelectedItemContext) => [Model, ReadonlyArray<Command.Command<Message>>];
|
|
162
162
|
handleImmediateActivation: (model: Model, item: string, displayText: string) => Model;
|
|
163
|
-
}>) => (model: Model, message: Message) => [Model, readonly
|
|
164
|
-
readonly
|
|
165
|
-
readonly
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
} | {
|
|
169
|
-
|
|
170
|
-
} | {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
163
|
+
}>) => (model: Model, message: Message) => [Model, readonly {
|
|
164
|
+
readonly name: string;
|
|
165
|
+
readonly effect: Effect.Effect<{
|
|
166
|
+
readonly _tag: "Opened";
|
|
167
|
+
readonly maybeActiveItemIndex: Option.Option<number>;
|
|
168
|
+
} | {
|
|
169
|
+
readonly _tag: "Closed";
|
|
170
|
+
} | {
|
|
171
|
+
readonly _tag: "ClosedByTab";
|
|
172
|
+
} | {
|
|
173
|
+
readonly _tag: "ActivatedItem";
|
|
174
|
+
readonly index: number;
|
|
175
|
+
readonly activationTrigger: "Pointer" | "Keyboard";
|
|
176
|
+
readonly maybeImmediateSelection: Option.Option<{
|
|
177
|
+
readonly item: string;
|
|
178
|
+
readonly displayText: string;
|
|
179
|
+
}>;
|
|
180
|
+
} | {
|
|
181
|
+
readonly _tag: "DeactivatedItem";
|
|
182
|
+
} | {
|
|
183
|
+
readonly _tag: "SelectedItem";
|
|
175
184
|
readonly item: string;
|
|
176
185
|
readonly displayText: string;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
} | {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
} | {
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
} | {
|
|
213
|
-
readonly _tag: "UpdatedInputValue";
|
|
214
|
-
readonly value: string;
|
|
215
|
-
} | {
|
|
216
|
-
readonly _tag: "PressedToggleButton";
|
|
217
|
-
}>[]];
|
|
186
|
+
} | {
|
|
187
|
+
readonly _tag: "MovedPointerOverItem";
|
|
188
|
+
readonly index: number;
|
|
189
|
+
readonly screenX: number;
|
|
190
|
+
readonly screenY: number;
|
|
191
|
+
} | {
|
|
192
|
+
readonly _tag: "RequestedItemClick";
|
|
193
|
+
readonly index: number;
|
|
194
|
+
} | {
|
|
195
|
+
readonly _tag: "CompletedScrollLock";
|
|
196
|
+
} | {
|
|
197
|
+
readonly _tag: "CompletedScrollUnlock";
|
|
198
|
+
} | {
|
|
199
|
+
readonly _tag: "CompletedInertSetup";
|
|
200
|
+
} | {
|
|
201
|
+
readonly _tag: "CompletedInertTeardown";
|
|
202
|
+
} | {
|
|
203
|
+
readonly _tag: "CompletedInputFocus";
|
|
204
|
+
} | {
|
|
205
|
+
readonly _tag: "CompletedScrollIntoView";
|
|
206
|
+
} | {
|
|
207
|
+
readonly _tag: "CompletedItemClick";
|
|
208
|
+
} | {
|
|
209
|
+
readonly _tag: "AdvancedTransitionFrame";
|
|
210
|
+
} | {
|
|
211
|
+
readonly _tag: "EndedTransition";
|
|
212
|
+
} | {
|
|
213
|
+
readonly _tag: "DetectedInputMovement";
|
|
214
|
+
} | {
|
|
215
|
+
readonly _tag: "UpdatedInputValue";
|
|
216
|
+
readonly value: string;
|
|
217
|
+
} | {
|
|
218
|
+
readonly _tag: "PressedToggleButton";
|
|
219
|
+
}, never, never>;
|
|
220
|
+
}[]];
|
|
218
221
|
/** Configuration for an individual combobox item's appearance. */
|
|
219
222
|
export type ItemConfig = Readonly<{
|
|
220
223
|
className?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/ui/combobox/shared.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/ui/combobox/shared.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Array, Effect, Match as M, Option, Predicate, Schema as S, pipe, } from 'effect';
|
|
2
|
+
import * as Command from '../../command';
|
|
2
3
|
import { OptionExt } from '../../effectExtensions';
|
|
3
4
|
import { html } from '../../html';
|
|
4
5
|
import { m } from '../../message';
|
|
@@ -122,15 +123,15 @@ export const closedBaseModel = (model) => constrainedEvo(model, {
|
|
|
122
123
|
export const makeUpdate = (handlers) => {
|
|
123
124
|
const withUpdateReturn = M.withReturnType();
|
|
124
125
|
return (model, message) => {
|
|
125
|
-
const maybeNextFrame = OptionExt.when(model.isAnimated, Task.nextFrame.pipe(Effect.as(AdvancedTransitionFrame())));
|
|
126
|
-
const maybeLockScroll = OptionExt.when(model.isModal, Task.lockScroll.pipe(Effect.as(CompletedScrollLock())));
|
|
127
|
-
const maybeUnlockScroll = OptionExt.when(model.isModal, Task.unlockScroll.pipe(Effect.as(CompletedScrollUnlock())));
|
|
126
|
+
const maybeNextFrame = OptionExt.when(model.isAnimated, Task.nextFrame.pipe(Effect.as(AdvancedTransitionFrame()), Command.make('RequestFrame')));
|
|
127
|
+
const maybeLockScroll = OptionExt.when(model.isModal, Task.lockScroll.pipe(Effect.as(CompletedScrollLock()), Command.make('LockScroll')));
|
|
128
|
+
const maybeUnlockScroll = OptionExt.when(model.isModal, Task.unlockScroll.pipe(Effect.as(CompletedScrollUnlock()), Command.make('UnlockScroll')));
|
|
128
129
|
const maybeInertOthers = OptionExt.when(model.isModal, Task.inertOthers(model.id, [
|
|
129
130
|
inputWrapperSelector(model.id),
|
|
130
131
|
itemsSelector(model.id),
|
|
131
|
-
]).pipe(Effect.as(CompletedInertSetup())));
|
|
132
|
-
const maybeRestoreInert = OptionExt.when(model.isModal, Task.restoreInert(model.id).pipe(Effect.as(CompletedInertTeardown())));
|
|
133
|
-
const focusInput = Task.focus(inputSelector(model.id)).pipe(Effect.ignore, Effect.as(CompletedInputFocus()));
|
|
132
|
+
]).pipe(Effect.as(CompletedInertSetup()), Command.make('InertOthers')));
|
|
133
|
+
const maybeRestoreInert = OptionExt.when(model.isModal, Task.restoreInert(model.id).pipe(Effect.as(CompletedInertTeardown()), Command.make('RestoreInert')));
|
|
134
|
+
const focusInput = Task.focus(inputSelector(model.id)).pipe(Effect.ignore, Effect.as(CompletedInputFocus()), Command.make('FocusInput'));
|
|
134
135
|
return M.value(message).pipe(withUpdateReturn, M.tagsExhaustive({
|
|
135
136
|
Opened: ({ maybeActiveItemIndex }) => {
|
|
136
137
|
const nextModel = constrainedEvo(model, {
|
|
@@ -177,7 +178,7 @@ export const makeUpdate = (handlers) => {
|
|
|
177
178
|
nextModel,
|
|
178
179
|
activationTrigger === 'Keyboard'
|
|
179
180
|
? [
|
|
180
|
-
Task.scrollIntoView(itemSelector(model.id, index)).pipe(Effect.ignore, Effect.as(CompletedScrollIntoView())),
|
|
181
|
+
Task.scrollIntoView(itemSelector(model.id, index)).pipe(Effect.ignore, Effect.as(CompletedScrollIntoView()), Command.make('ScrollIntoView')),
|
|
181
182
|
]
|
|
182
183
|
: [],
|
|
183
184
|
];
|
|
@@ -213,7 +214,7 @@ export const makeUpdate = (handlers) => {
|
|
|
213
214
|
RequestedItemClick: ({ index }) => [
|
|
214
215
|
model,
|
|
215
216
|
[
|
|
216
|
-
Task.clickElement(itemSelector(model.id, index)).pipe(Effect.ignore, Effect.as(CompletedItemClick())),
|
|
217
|
+
Task.clickElement(itemSelector(model.id, index)).pipe(Effect.ignore, Effect.as(CompletedItemClick()), Command.make('ClickItem')),
|
|
217
218
|
],
|
|
218
219
|
],
|
|
219
220
|
UpdatedInputValue: ({ value }) => {
|
|
@@ -272,14 +273,14 @@ export const makeUpdate = (handlers) => {
|
|
|
272
273
|
transitionState: () => 'EnterAnimating',
|
|
273
274
|
}),
|
|
274
275
|
[
|
|
275
|
-
Task.waitForTransitions(itemsSelector(model.id)).pipe(Effect.as(EndedTransition())),
|
|
276
|
+
Task.waitForTransitions(itemsSelector(model.id)).pipe(Effect.as(EndedTransition()), Command.make('WaitForTransitions')),
|
|
276
277
|
],
|
|
277
278
|
]), M.when('LeaveStart', () => [
|
|
278
279
|
constrainedEvo(model, {
|
|
279
280
|
transitionState: () => 'LeaveAnimating',
|
|
280
281
|
}),
|
|
281
282
|
[
|
|
282
|
-
Effect.raceFirst(Task.detectElementMovement(inputWrapperSelector(model.id)).pipe(Effect.as(DetectedInputMovement())), Task.waitForTransitions(itemsSelector(model.id)).pipe(Effect.as(EndedTransition()))),
|
|
283
|
+
Effect.raceFirst(Task.detectElementMovement(inputWrapperSelector(model.id)).pipe(Effect.as(DetectedInputMovement())), Task.waitForTransitions(itemsSelector(model.id)).pipe(Effect.as(EndedTransition()))).pipe(Command.make('DetectMovementOrTransitionEnd')),
|
|
283
284
|
],
|
|
284
285
|
]), M.orElse(() => [model, []])),
|
|
285
286
|
EndedTransition: () => M.value(model.transitionState).pipe(withUpdateReturn, M.whenOr('EnterAnimating', 'LeaveAnimating', () => [
|