foldkit 0.56.0 → 0.57.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/dist/devtools/overlay-styles.d.ts +1 -1
- package/dist/devtools/overlay-styles.d.ts.map +1 -1
- package/dist/devtools/overlay-styles.js +5 -1
- package/dist/devtools/overlay.d.ts.map +1 -1
- package/dist/devtools/overlay.js +52 -19
- package/dist/html/index.d.ts +3 -3
- package/dist/html/index.d.ts.map +1 -1
- package/dist/html/lazy.d.ts +7 -5
- package/dist/html/lazy.d.ts.map +1 -1
- package/dist/html/lazy.js +12 -8
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +2 -4
- package/dist/test/apps/disabledButton.d.ts +11 -3
- package/dist/test/apps/disabledButton.d.ts.map +1 -1
- package/dist/ui/combobox/multi.d.ts +31 -10
- package/dist/ui/combobox/multi.d.ts.map +1 -1
- package/dist/ui/combobox/public.d.ts +1 -2
- package/dist/ui/combobox/public.d.ts.map +1 -1
- package/dist/ui/combobox/public.js +1 -2
- package/dist/ui/combobox/shared.d.ts +33 -33
- package/dist/ui/combobox/shared.d.ts.map +1 -1
- package/dist/ui/combobox/shared.js +89 -112
- package/dist/ui/combobox/single.d.ts +31 -10
- package/dist/ui/combobox/single.d.ts.map +1 -1
- package/dist/ui/combobox/single.js +1 -5
- package/dist/ui/dialog/index.d.ts +10 -15
- package/dist/ui/dialog/index.d.ts.map +1 -1
- package/dist/ui/dialog/index.js +68 -73
- package/dist/ui/dialog/public.d.ts +1 -1
- package/dist/ui/dialog/public.d.ts.map +1 -1
- package/dist/ui/dialog/public.js +1 -1
- package/dist/ui/listbox/multi.d.ts +30 -9
- package/dist/ui/listbox/multi.d.ts.map +1 -1
- package/dist/ui/listbox/public.d.ts +1 -2
- package/dist/ui/listbox/public.d.ts.map +1 -1
- package/dist/ui/listbox/public.js +1 -2
- package/dist/ui/listbox/shared.d.ts +35 -36
- package/dist/ui/listbox/shared.d.ts.map +1 -1
- package/dist/ui/listbox/shared.js +106 -104
- package/dist/ui/listbox/single.d.ts +30 -9
- package/dist/ui/listbox/single.d.ts.map +1 -1
- package/dist/ui/listbox/single.js +9 -12
- package/dist/ui/menu/index.d.ts +22 -26
- package/dist/ui/menu/index.d.ts.map +1 -1
- package/dist/ui/menu/index.js +103 -91
- package/dist/ui/menu/public.d.ts +1 -2
- package/dist/ui/menu/public.d.ts.map +1 -1
- package/dist/ui/menu/public.js +1 -2
- package/dist/ui/popover/index.d.ts +21 -22
- package/dist/ui/popover/index.d.ts.map +1 -1
- package/dist/ui/popover/index.js +92 -75
- package/dist/ui/popover/public.d.ts +1 -2
- package/dist/ui/popover/public.d.ts.map +1 -1
- package/dist/ui/popover/public.js +1 -2
- package/dist/ui/transition/index.d.ts +8 -58
- package/dist/ui/transition/index.d.ts.map +1 -1
- package/dist/ui/transition/index.js +21 -111
- package/dist/ui/transition/public.d.ts +1 -1
- package/dist/ui/transition/public.d.ts.map +1 -1
- package/dist/ui/transition/public.js +1 -1
- package/dist/ui/transition/schema.d.ts +43 -0
- package/dist/ui/transition/schema.d.ts.map +1 -0
- package/dist/ui/transition/schema.js +35 -0
- package/dist/ui/transition/update.d.ts +22 -0
- package/dist/ui/transition/update.d.ts.map +1 -0
- package/dist/ui/transition/update.js +68 -0
- package/package.json +1 -1
- package/dist/ui/transition.d.ts +0 -5
- package/dist/ui/transition.d.ts.map +0 -1
- package/dist/ui/transition.js +0 -3
|
@@ -17,7 +17,11 @@ export declare const BaseModel: S.Struct<{
|
|
|
17
17
|
isAnimated: typeof S.Boolean;
|
|
18
18
|
isModal: typeof S.Boolean;
|
|
19
19
|
orientation: S.Literal<["Vertical", "Horizontal"]>;
|
|
20
|
-
|
|
20
|
+
transition: S.Struct<{
|
|
21
|
+
id: typeof S.String;
|
|
22
|
+
isShowing: typeof S.Boolean;
|
|
23
|
+
transitionState: S.Literal<["Idle", "EnterStart", "EnterAnimating", "LeaveStart", "LeaveAnimating"]>;
|
|
24
|
+
}>;
|
|
21
25
|
maybeActiveItemIndex: S.OptionFromSelf<typeof S.Number>;
|
|
22
26
|
activationTrigger: S.Literal<["Pointer", "Keyboard"]>;
|
|
23
27
|
searchQuery: typeof S.String;
|
|
@@ -96,12 +100,10 @@ export declare const CompletedClickItem: import("../../schema").CallableTaggedSt
|
|
|
96
100
|
export declare const IgnoredMouseClick: import("../../schema").CallableTaggedStruct<"IgnoredMouseClick", {}>;
|
|
97
101
|
/** Sent when a Space key-up is captured to prevent page scrolling. */
|
|
98
102
|
export declare const SuppressedSpaceScroll: import("../../schema").CallableTaggedStruct<"SuppressedSpaceScroll", {}>;
|
|
99
|
-
/**
|
|
100
|
-
export declare const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
/** Sent internally when the listbox button moves in the viewport during a leave transition, cancelling the animation. */
|
|
104
|
-
export declare const DetectedButtonMovement: import("../../schema").CallableTaggedStruct<"DetectedButtonMovement", {}>;
|
|
103
|
+
/** Wraps a Transition submodel message for delegation. */
|
|
104
|
+
export declare const GotTransitionMessage: import("../../schema").CallableTaggedStruct<"GotTransitionMessage", {
|
|
105
|
+
message: S.Union<[import("../../schema").CallableTaggedStruct<"Showed", {}>, import("../../schema").CallableTaggedStruct<"Hidden", {}>, import("../../schema").CallableTaggedStruct<"AdvancedTransitionFrame", {}>, import("../../schema").CallableTaggedStruct<"EndedTransition", {}>]>;
|
|
106
|
+
}>;
|
|
105
107
|
/** Sent when the user presses a pointer device on the listbox button. Records pointer type for click handling. */
|
|
106
108
|
export declare const PressedPointerOnButton: import("../../schema").CallableTaggedStruct<"PressedPointerOnButton", {
|
|
107
109
|
pointerType: typeof S.String;
|
|
@@ -129,9 +131,7 @@ export declare const Message: S.Union<[
|
|
|
129
131
|
typeof CompletedClickItem,
|
|
130
132
|
typeof IgnoredMouseClick,
|
|
131
133
|
typeof SuppressedSpaceScroll,
|
|
132
|
-
typeof
|
|
133
|
-
typeof EndedTransition,
|
|
134
|
-
typeof DetectedButtonMovement,
|
|
134
|
+
typeof GotTransitionMessage,
|
|
135
135
|
typeof PressedPointerOnButton
|
|
136
136
|
]>;
|
|
137
137
|
export type Opened = typeof Opened.Type;
|
|
@@ -146,9 +146,6 @@ export type Searched = typeof Searched.Type;
|
|
|
146
146
|
export type ClearedSearch = typeof ClearedSearch.Type;
|
|
147
147
|
export type IgnoredMouseClick = typeof IgnoredMouseClick.Type;
|
|
148
148
|
export type SuppressedSpaceScroll = typeof SuppressedSpaceScroll.Type;
|
|
149
|
-
export type AdvancedTransitionFrame = typeof AdvancedTransitionFrame.Type;
|
|
150
|
-
export type EndedTransition = typeof EndedTransition.Type;
|
|
151
|
-
export type DetectedButtonMovement = typeof DetectedButtonMovement.Type;
|
|
152
149
|
export type PressedPointerOnButton = typeof PressedPointerOnButton.Type;
|
|
153
150
|
export type Message = typeof Message.Type;
|
|
154
151
|
export declare const SEARCH_DEBOUNCE_MILLISECONDS = 350;
|
|
@@ -158,15 +155,9 @@ export declare const itemsSelector: (id: string) => string;
|
|
|
158
155
|
export declare const itemSelector: (id: string, index: number) => string;
|
|
159
156
|
export declare const itemId: (id: string, index: number) => string;
|
|
160
157
|
export declare const closedModel: <Model extends BaseModel>(model: Model) => Model;
|
|
161
|
-
type SelectedItemContext = Readonly<{
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
maybeUnlockScroll: Option.Option<Command.Command<Message>>;
|
|
165
|
-
maybeRestoreInert: Option.Option<Command.Command<Message>>;
|
|
166
|
-
}>;
|
|
167
|
-
/** Advances the listbox's enter/leave transition by waiting a double-rAF. */
|
|
168
|
-
export declare const RequestFrame: Command.CommandDefinition<"RequestFrame", {
|
|
169
|
-
readonly _tag: "AdvancedTransitionFrame";
|
|
158
|
+
type SelectedItemContext<Model extends BaseModel> = Readonly<{
|
|
159
|
+
closeWithFocus: (model: Model) => readonly [Model, ReadonlyArray<Command.Command<Message>>];
|
|
160
|
+
closeWithoutFocus: (model: Model) => readonly [Model, ReadonlyArray<Command.Command<Message>>];
|
|
170
161
|
}>;
|
|
171
162
|
/** Prevents page scrolling while the listbox is open in modal mode. */
|
|
172
163
|
export declare const LockScroll: Command.CommandDefinition<"LockScroll", {
|
|
@@ -205,17 +196,20 @@ export declare const DelayClearSearch: Command.CommandDefinition<"DelayClearSear
|
|
|
205
196
|
readonly _tag: "ClearedSearch";
|
|
206
197
|
readonly version: number;
|
|
207
198
|
}>;
|
|
208
|
-
/**
|
|
209
|
-
export declare const WaitForTransitions: Command.CommandDefinition<"WaitForTransitions", {
|
|
210
|
-
readonly _tag: "EndedTransition";
|
|
211
|
-
}>;
|
|
212
|
-
/** Detects whether the listbox button moved or the leave transition ended — whichever comes first. */
|
|
199
|
+
/** Detects whether the listbox button moved or the leave transition ended — whichever comes first. Both outcomes signal the Transition submodel that leave is complete. */
|
|
213
200
|
export declare const DetectMovementOrTransitionEnd: Command.CommandDefinition<"DetectMovementOrTransitionEnd", {
|
|
214
|
-
readonly _tag: "
|
|
215
|
-
|
|
216
|
-
|
|
201
|
+
readonly _tag: "GotTransitionMessage";
|
|
202
|
+
readonly message: {
|
|
203
|
+
readonly _tag: "Showed";
|
|
204
|
+
} | {
|
|
205
|
+
readonly _tag: "Hidden";
|
|
206
|
+
} | {
|
|
207
|
+
readonly _tag: "AdvancedTransitionFrame";
|
|
208
|
+
} | {
|
|
209
|
+
readonly _tag: "EndedTransition";
|
|
210
|
+
};
|
|
217
211
|
}>;
|
|
218
|
-
export declare const makeUpdate: <Model extends BaseModel>(handleSelectedItem: (model: Model, item: string, context: SelectedItemContext) => [Model, ReadonlyArray<Command.Command<Message>>]) => (model: Model, message: Message) => readonly [Model, readonly Readonly<{
|
|
212
|
+
export declare const makeUpdate: <Model extends BaseModel>(handleSelectedItem: (model: Model, item: string, context: SelectedItemContext<Model>) => [Model, ReadonlyArray<Command.Command<Message>>]) => (model: Model, message: Message) => readonly [Model, readonly Readonly<{
|
|
219
213
|
name: string;
|
|
220
214
|
effect: Effect.Effect<{
|
|
221
215
|
readonly _tag: "Opened";
|
|
@@ -269,11 +263,16 @@ export declare const makeUpdate: <Model extends BaseModel>(handleSelectedItem: (
|
|
|
269
263
|
} | {
|
|
270
264
|
readonly _tag: "SuppressedSpaceScroll";
|
|
271
265
|
} | {
|
|
272
|
-
readonly _tag: "
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
266
|
+
readonly _tag: "GotTransitionMessage";
|
|
267
|
+
readonly message: {
|
|
268
|
+
readonly _tag: "Showed";
|
|
269
|
+
} | {
|
|
270
|
+
readonly _tag: "Hidden";
|
|
271
|
+
} | {
|
|
272
|
+
readonly _tag: "AdvancedTransitionFrame";
|
|
273
|
+
} | {
|
|
274
|
+
readonly _tag: "EndedTransition";
|
|
275
|
+
};
|
|
277
276
|
} | {
|
|
278
277
|
readonly _tag: "PressedPointerOnButton";
|
|
279
278
|
readonly button: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/ui/listbox/shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,MAAM,
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/ui/listbox/shared.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Array, Effect, Match as M, Option, Predicate, Schema as S, String as Str, pipe, } from 'effect';
|
|
1
|
+
import { Array, Effect, Equal, Match as M, Option, Predicate, Schema as S, String as Str, pipe, } from 'effect';
|
|
2
2
|
import * as Command from '../../command';
|
|
3
3
|
import { OptionExt } from '../../effectExtensions';
|
|
4
4
|
import { html } from '../../html';
|
|
@@ -8,7 +8,11 @@ import * as Task from '../../task';
|
|
|
8
8
|
import { anchorHooks } from '../anchor';
|
|
9
9
|
import { groupContiguous } from '../group';
|
|
10
10
|
import { findFirstEnabledIndex, isPrintableKey, keyToIndex } from '../keyboard';
|
|
11
|
-
|
|
11
|
+
// NOTE: Transition imports are split across schema + update to avoid a circular
|
|
12
|
+
// dependency: transition → html → runtime → devtools → listbox → transition.
|
|
13
|
+
// The barrel (../transition) imports from html, which starts the cycle.
|
|
14
|
+
import { EndedTransition as TransitionEndedTransition, Hidden as TransitionHidden, Message as TransitionMessage, Model as TransitionModel, Showed as TransitionShowed, init as transitionInit, } from '../transition/schema';
|
|
15
|
+
import { update as transitionUpdate } from '../transition/update';
|
|
12
16
|
import { resolveTypeaheadMatch } from '../typeahead';
|
|
13
17
|
export { resolveTypeaheadMatch };
|
|
14
18
|
// MODEL
|
|
@@ -23,7 +27,7 @@ export const BaseModel = S.Struct({
|
|
|
23
27
|
isAnimated: S.Boolean,
|
|
24
28
|
isModal: S.Boolean,
|
|
25
29
|
orientation: Orientation,
|
|
26
|
-
|
|
30
|
+
transition: TransitionModel,
|
|
27
31
|
maybeActiveItemIndex: S.OptionFromSelf(S.Number),
|
|
28
32
|
activationTrigger: ActivationTrigger,
|
|
29
33
|
searchQuery: S.String,
|
|
@@ -38,7 +42,7 @@ export const baseInit = (config) => ({
|
|
|
38
42
|
isAnimated: config.isAnimated ?? false,
|
|
39
43
|
isModal: config.isModal ?? false,
|
|
40
44
|
orientation: config.orientation ?? 'Vertical',
|
|
41
|
-
|
|
45
|
+
transition: transitionInit({ id: `${config.id}-listbox` }),
|
|
42
46
|
maybeActiveItemIndex: Option.none(),
|
|
43
47
|
activationTrigger: 'Keyboard',
|
|
44
48
|
searchQuery: '',
|
|
@@ -101,19 +105,17 @@ export const CompletedClickItem = m('CompletedClickItem');
|
|
|
101
105
|
export const IgnoredMouseClick = m('IgnoredMouseClick');
|
|
102
106
|
/** Sent when a Space key-up is captured to prevent page scrolling. */
|
|
103
107
|
export const SuppressedSpaceScroll = m('SuppressedSpaceScroll');
|
|
104
|
-
/**
|
|
105
|
-
export const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
/** Sent internally when the listbox button moves in the viewport during a leave transition, cancelling the animation. */
|
|
109
|
-
export const DetectedButtonMovement = m('DetectedButtonMovement');
|
|
108
|
+
/** Wraps a Transition submodel message for delegation. */
|
|
109
|
+
export const GotTransitionMessage = m('GotTransitionMessage', {
|
|
110
|
+
message: TransitionMessage,
|
|
111
|
+
});
|
|
110
112
|
/** Sent when the user presses a pointer device on the listbox button. Records pointer type for click handling. */
|
|
111
113
|
export const PressedPointerOnButton = m('PressedPointerOnButton', {
|
|
112
114
|
pointerType: S.String,
|
|
113
115
|
button: S.Number,
|
|
114
116
|
});
|
|
115
117
|
/** Union of all messages the listbox component can produce. */
|
|
116
|
-
export const Message = S.Union(Opened, Closed, ClosedByTab, ActivatedItem, DeactivatedItem, SelectedItem, MovedPointerOverItem, RequestedItemClick, Searched, ClearedSearch, CompletedLockScroll, CompletedUnlockScroll, CompletedSetupInert, CompletedTeardownInert, CompletedFocusButton, CompletedFocusItems, CompletedScrollIntoView, CompletedClickItem, IgnoredMouseClick, SuppressedSpaceScroll,
|
|
118
|
+
export const Message = S.Union(Opened, Closed, ClosedByTab, ActivatedItem, DeactivatedItem, SelectedItem, MovedPointerOverItem, RequestedItemClick, Searched, ClearedSearch, CompletedLockScroll, CompletedUnlockScroll, CompletedSetupInert, CompletedTeardownInert, CompletedFocusButton, CompletedFocusItems, CompletedScrollIntoView, CompletedClickItem, IgnoredMouseClick, SuppressedSpaceScroll, GotTransitionMessage, PressedPointerOnButton);
|
|
117
119
|
// CONSTANTS
|
|
118
120
|
export const SEARCH_DEBOUNCE_MILLISECONDS = 350;
|
|
119
121
|
export const LEFT_MOUSE_BUTTON = 0;
|
|
@@ -126,15 +128,12 @@ export const itemId = (id, index) => `${id}-item-${index}`;
|
|
|
126
128
|
const constrainedEvo = makeConstrainedEvo();
|
|
127
129
|
export const closedModel = (model) => constrainedEvo(model, {
|
|
128
130
|
isOpen: () => false,
|
|
129
|
-
transitionState: () => model.isAnimated ? 'LeaveStart' : 'Idle',
|
|
130
131
|
maybeActiveItemIndex: () => Option.none(),
|
|
131
132
|
searchQuery: () => '',
|
|
132
133
|
searchVersion: () => 0,
|
|
133
134
|
maybeLastPointerPosition: () => Option.none(),
|
|
134
135
|
maybeLastButtonPointerType: () => Option.none(),
|
|
135
136
|
});
|
|
136
|
-
/** Advances the listbox's enter/leave transition by waiting a double-rAF. */
|
|
137
|
-
export const RequestFrame = Command.define('RequestFrame', AdvancedTransitionFrame);
|
|
138
137
|
/** Prevents page scrolling while the listbox is open in modal mode. */
|
|
139
138
|
export const LockScroll = Command.define('LockScroll', CompletedLockScroll);
|
|
140
139
|
/** Re-enables page scrolling after the listbox closes. */
|
|
@@ -153,14 +152,50 @@ export const ScrollIntoView = Command.define('ScrollIntoView', CompletedScrollIn
|
|
|
153
152
|
export const ClickItem = Command.define('ClickItem', CompletedClickItem);
|
|
154
153
|
/** Waits for the typeahead search debounce period before clearing the query. */
|
|
155
154
|
export const DelayClearSearch = Command.define('DelayClearSearch', ClearedSearch);
|
|
156
|
-
/**
|
|
157
|
-
export const
|
|
158
|
-
/** Detects whether the listbox button moved or the leave transition ended — whichever comes first. */
|
|
159
|
-
export const DetectMovementOrTransitionEnd = Command.define('DetectMovementOrTransitionEnd', DetectedButtonMovement, EndedTransition);
|
|
155
|
+
/** Detects whether the listbox button moved or the leave transition ended — whichever comes first. Both outcomes signal the Transition submodel that leave is complete. */
|
|
156
|
+
export const DetectMovementOrTransitionEnd = Command.define('DetectMovementOrTransitionEnd', GotTransitionMessage);
|
|
160
157
|
export const makeUpdate = (handleSelectedItem) => {
|
|
161
158
|
const withUpdateReturn = M.withReturnType();
|
|
159
|
+
const delegateToTransition = (model, transitionMessage) => {
|
|
160
|
+
const [nextTransition, transitionCommands, maybeOutMessage] = transitionUpdate(model.transition, transitionMessage);
|
|
161
|
+
const mappedCommands = transitionCommands.map(Command.mapEffect(Effect.map(message => GotTransitionMessage({ message }))));
|
|
162
|
+
const additionalCommands = Option.match(maybeOutMessage, {
|
|
163
|
+
onNone: () => [],
|
|
164
|
+
onSome: M.type().pipe(M.tagsExhaustive({
|
|
165
|
+
StartedLeaveAnimating: () => [
|
|
166
|
+
DetectMovementOrTransitionEnd(Effect.raceFirst(Task.detectElementMovement(buttonSelector(model.id)).pipe(Effect.as(GotTransitionMessage({
|
|
167
|
+
message: TransitionEndedTransition(),
|
|
168
|
+
}))), Task.waitForTransitions(itemsSelector(model.id)).pipe(Effect.as(GotTransitionMessage({
|
|
169
|
+
message: TransitionEndedTransition(),
|
|
170
|
+
}))))),
|
|
171
|
+
],
|
|
172
|
+
TransitionedOut: () => [],
|
|
173
|
+
})),
|
|
174
|
+
});
|
|
175
|
+
return [
|
|
176
|
+
constrainedEvo(model, { transition: () => nextTransition }),
|
|
177
|
+
[...mappedCommands, ...additionalCommands],
|
|
178
|
+
];
|
|
179
|
+
};
|
|
180
|
+
const openListbox = (baseModel, openCommands) => {
|
|
181
|
+
if (baseModel.isAnimated) {
|
|
182
|
+
const [nextModel, transitionCommands] = delegateToTransition(baseModel, TransitionShowed());
|
|
183
|
+
return [
|
|
184
|
+
constrainedEvo(nextModel, { isOpen: () => true }),
|
|
185
|
+
[...openCommands, ...transitionCommands],
|
|
186
|
+
];
|
|
187
|
+
}
|
|
188
|
+
return [constrainedEvo(baseModel, { isOpen: () => true }), openCommands];
|
|
189
|
+
};
|
|
190
|
+
const closeListbox = (baseModel, commands) => {
|
|
191
|
+
const closed = closedModel(baseModel);
|
|
192
|
+
if (baseModel.isAnimated) {
|
|
193
|
+
const [nextModel, transitionCommands] = delegateToTransition(closed, TransitionHidden());
|
|
194
|
+
return [nextModel, [...commands, ...transitionCommands]];
|
|
195
|
+
}
|
|
196
|
+
return [closed, commands];
|
|
197
|
+
};
|
|
162
198
|
return (model, message) => {
|
|
163
|
-
const maybeNextFrame = OptionExt.when(model.isAnimated, RequestFrame(Task.nextFrame.pipe(Effect.as(AdvancedTransitionFrame()))));
|
|
164
199
|
const maybeLockScroll = OptionExt.when(model.isModal, LockScroll(Task.lockScroll.pipe(Effect.as(CompletedLockScroll()))));
|
|
165
200
|
const maybeUnlockScroll = OptionExt.when(model.isModal, UnlockScroll(Task.unlockScroll.pipe(Effect.as(CompletedUnlockScroll()))));
|
|
166
201
|
const maybeInertOthers = OptionExt.when(model.isModal, InertOthers(Task.inertOthers(model.id, [
|
|
@@ -169,45 +204,37 @@ export const makeUpdate = (handleSelectedItem) => {
|
|
|
169
204
|
]).pipe(Effect.as(CompletedSetupInert()))));
|
|
170
205
|
const maybeRestoreInert = OptionExt.when(model.isModal, RestoreInert(Task.restoreInert(model.id).pipe(Effect.as(CompletedTeardownInert()))));
|
|
171
206
|
const focusButton = FocusButton(Task.focus(buttonSelector(model.id)).pipe(Effect.ignore, Effect.as(CompletedFocusButton())));
|
|
207
|
+
const focusItems = FocusItems(Task.focus(itemsSelector(model.id)).pipe(Effect.ignore, Effect.as(CompletedFocusItems())));
|
|
208
|
+
const openCommands = [
|
|
209
|
+
focusItems,
|
|
210
|
+
...Array.getSomes([maybeLockScroll, maybeInertOthers]),
|
|
211
|
+
];
|
|
212
|
+
const closeWithFocusCommands = [
|
|
213
|
+
focusButton,
|
|
214
|
+
...Array.getSomes([maybeUnlockScroll, maybeRestoreInert]),
|
|
215
|
+
];
|
|
216
|
+
const closeWithoutFocusCommands = Array.getSomes([
|
|
217
|
+
maybeUnlockScroll,
|
|
218
|
+
maybeRestoreInert,
|
|
219
|
+
]);
|
|
172
220
|
return M.value(message).pipe(withUpdateReturn, M.tagsExhaustive({
|
|
173
|
-
Opened: ({ maybeActiveItemIndex }) => {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
maybeNextFrame,
|
|
190
|
-
maybeLockScroll,
|
|
191
|
-
maybeInertOthers,
|
|
192
|
-
]), Array.prepend(FocusItems(Task.focus(itemsSelector(model.id)).pipe(Effect.ignore, Effect.as(CompletedFocusItems()))))),
|
|
193
|
-
];
|
|
221
|
+
Opened: ({ maybeActiveItemIndex }) => openListbox(constrainedEvo(model, {
|
|
222
|
+
maybeActiveItemIndex: () => maybeActiveItemIndex,
|
|
223
|
+
activationTrigger: () => Option.match(maybeActiveItemIndex, {
|
|
224
|
+
onNone: () => 'Pointer',
|
|
225
|
+
onSome: () => 'Keyboard',
|
|
226
|
+
}),
|
|
227
|
+
searchQuery: () => '',
|
|
228
|
+
searchVersion: () => 0,
|
|
229
|
+
maybeLastPointerPosition: () => Option.none(),
|
|
230
|
+
}), openCommands),
|
|
231
|
+
Closed: () => closeListbox(model, closeWithFocusCommands),
|
|
232
|
+
ClosedByTab: () => {
|
|
233
|
+
if (Option.exists(model.maybeLastButtonPointerType, Equal.equals('mouse'))) {
|
|
234
|
+
return [model, []];
|
|
235
|
+
}
|
|
236
|
+
return closeListbox(model, closeWithoutFocusCommands);
|
|
194
237
|
},
|
|
195
|
-
Closed: () => [
|
|
196
|
-
closedModel(model),
|
|
197
|
-
pipe(Array.getSomes([
|
|
198
|
-
maybeNextFrame,
|
|
199
|
-
maybeUnlockScroll,
|
|
200
|
-
maybeRestoreInert,
|
|
201
|
-
]), Array.prepend(focusButton)),
|
|
202
|
-
],
|
|
203
|
-
ClosedByTab: () => [
|
|
204
|
-
closedModel(model),
|
|
205
|
-
Array.getSomes([
|
|
206
|
-
maybeNextFrame,
|
|
207
|
-
maybeUnlockScroll,
|
|
208
|
-
maybeRestoreInert,
|
|
209
|
-
]),
|
|
210
|
-
],
|
|
211
238
|
ActivatedItem: ({ index, activationTrigger }) => [
|
|
212
239
|
constrainedEvo(model, {
|
|
213
240
|
maybeActiveItemIndex: () => Option.some(index),
|
|
@@ -242,10 +269,8 @@ export const makeUpdate = (handleSelectedItem) => {
|
|
|
242
269
|
]
|
|
243
270
|
: [model, []],
|
|
244
271
|
SelectedItem: ({ item }) => handleSelectedItem(model, item, {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
maybeUnlockScroll,
|
|
248
|
-
maybeRestoreInert,
|
|
272
|
+
closeWithFocus: closeModel => closeListbox(closeModel, closeWithFocusCommands),
|
|
273
|
+
closeWithoutFocus: closeModel => closeListbox(closeModel, closeWithoutFocusCommands),
|
|
249
274
|
}),
|
|
250
275
|
RequestedItemClick: ({ index }) => [
|
|
251
276
|
model,
|
|
@@ -273,29 +298,7 @@ export const makeUpdate = (handleSelectedItem) => {
|
|
|
273
298
|
}
|
|
274
299
|
return [constrainedEvo(model, { searchQuery: () => '' }), []];
|
|
275
300
|
},
|
|
276
|
-
|
|
277
|
-
constrainedEvo(model, {
|
|
278
|
-
transitionState: () => 'EnterAnimating',
|
|
279
|
-
}),
|
|
280
|
-
[
|
|
281
|
-
WaitForTransitions(Task.waitForTransitions(itemsSelector(model.id)).pipe(Effect.as(EndedTransition()))),
|
|
282
|
-
],
|
|
283
|
-
]), M.when('LeaveStart', () => [
|
|
284
|
-
constrainedEvo(model, {
|
|
285
|
-
transitionState: () => 'LeaveAnimating',
|
|
286
|
-
}),
|
|
287
|
-
[
|
|
288
|
-
DetectMovementOrTransitionEnd(Effect.raceFirst(Task.detectElementMovement(buttonSelector(model.id)).pipe(Effect.as(DetectedButtonMovement())), Task.waitForTransitions(itemsSelector(model.id)).pipe(Effect.as(EndedTransition())))),
|
|
289
|
-
],
|
|
290
|
-
]), M.orElse(() => [model, []])),
|
|
291
|
-
EndedTransition: () => M.value(model.transitionState).pipe(withUpdateReturn, M.whenOr('EnterAnimating', 'LeaveAnimating', () => [
|
|
292
|
-
constrainedEvo(model, { transitionState: () => 'Idle' }),
|
|
293
|
-
[],
|
|
294
|
-
]), M.orElse(() => [model, []])),
|
|
295
|
-
DetectedButtonMovement: () => M.value(model.transitionState).pipe(withUpdateReturn, M.when('LeaveAnimating', () => [
|
|
296
|
-
constrainedEvo(model, { transitionState: () => 'Idle' }),
|
|
297
|
-
[],
|
|
298
|
-
]), M.orElse(() => [model, []])),
|
|
301
|
+
GotTransitionMessage: ({ message: transitionMessage }) => delegateToTransition(model, transitionMessage),
|
|
299
302
|
PressedPointerOnButton: ({ pointerType, button }) => {
|
|
300
303
|
const withPointerType = constrainedEvo(model, {
|
|
301
304
|
maybeLastButtonPointerType: () => Option.some(pointerType),
|
|
@@ -304,32 +307,21 @@ export const makeUpdate = (handleSelectedItem) => {
|
|
|
304
307
|
return [withPointerType, []];
|
|
305
308
|
}
|
|
306
309
|
if (model.isOpen) {
|
|
310
|
+
const [closed, commands] = closeListbox(withPointerType, closeWithFocusCommands);
|
|
307
311
|
return [
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
maybeRestoreInert,
|
|
313
|
-
]), Array.prepend(focusButton)),
|
|
312
|
+
constrainedEvo(closed, {
|
|
313
|
+
maybeLastButtonPointerType: () => Option.some(pointerType),
|
|
314
|
+
}),
|
|
315
|
+
commands,
|
|
314
316
|
];
|
|
315
317
|
}
|
|
316
|
-
|
|
317
|
-
isOpen: () => true,
|
|
318
|
-
transitionState: () => model.isAnimated ? 'EnterStart' : 'Idle',
|
|
318
|
+
return openListbox(constrainedEvo(withPointerType, {
|
|
319
319
|
maybeActiveItemIndex: () => Option.none(),
|
|
320
320
|
activationTrigger: () => 'Pointer',
|
|
321
321
|
searchQuery: () => '',
|
|
322
322
|
searchVersion: () => 0,
|
|
323
323
|
maybeLastPointerPosition: () => Option.none(),
|
|
324
|
-
});
|
|
325
|
-
return [
|
|
326
|
-
nextModel,
|
|
327
|
-
pipe(Array.getSomes([
|
|
328
|
-
maybeNextFrame,
|
|
329
|
-
maybeLockScroll,
|
|
330
|
-
maybeInertOthers,
|
|
331
|
-
]), Array.prepend(FocusItems(Task.focus(itemsSelector(model.id)).pipe(Effect.ignore, Effect.as(CompletedFocusItems()))))),
|
|
332
|
-
];
|
|
324
|
+
}), openCommands);
|
|
333
325
|
},
|
|
334
326
|
CompletedLockScroll: () => [model, []],
|
|
335
327
|
CompletedUnlockScroll: () => [model, []],
|
|
@@ -339,14 +331,19 @@ export const makeUpdate = (handleSelectedItem) => {
|
|
|
339
331
|
CompletedFocusItems: () => [model, []],
|
|
340
332
|
CompletedScrollIntoView: () => [model, []],
|
|
341
333
|
CompletedClickItem: () => [model, []],
|
|
342
|
-
IgnoredMouseClick: () => [
|
|
334
|
+
IgnoredMouseClick: () => [
|
|
335
|
+
constrainedEvo(model, {
|
|
336
|
+
maybeLastButtonPointerType: () => Option.none(),
|
|
337
|
+
}),
|
|
338
|
+
[],
|
|
339
|
+
],
|
|
343
340
|
SuppressedSpaceScroll: () => [model, []],
|
|
344
341
|
}));
|
|
345
342
|
};
|
|
346
343
|
};
|
|
347
344
|
export const makeView = (behavior) => (config) => {
|
|
348
345
|
const { div, input, AriaActiveDescendant, AriaControls, AriaDisabled, AriaExpanded, AriaHasPopup, AriaLabelledBy, AriaMultiSelectable, AriaOrientation, AriaSelected, Attribute, Class, DataAttribute, Id, Name, OnBlur, OnClick, OnDestroy, OnInsert, OnKeyDownPreventDefault, OnKeyUpPreventDefault, OnPointerDown, OnPointerLeave, OnPointerMove, Role, Style, Tabindex, Type, Value, keyed, } = html();
|
|
349
|
-
const { model: { id, isOpen, orientation, transitionState, maybeActiveItemIndex, searchQuery, maybeLastButtonPointerType, }, toParentMessage, onSelectedItem, items, itemToConfig, isItemDisabled, isButtonDisabled, buttonContent, buttonClassName, buttonAttributes = [], itemsClassName, itemsAttributes = [], itemsScrollClassName, itemsScrollAttributes = [], backdropClassName, backdropAttributes = [], className, attributes = [], itemGroupKey, groupToHeading, groupClassName, groupAttributes = [], separatorClassName, separatorAttributes = [], anchor, name, form, isDisabled, isInvalid, } = config;
|
|
346
|
+
const { model: { id, isOpen, orientation, transition: { transitionState }, maybeActiveItemIndex, searchQuery, maybeLastButtonPointerType, }, toParentMessage, onSelectedItem, items, itemToConfig, isItemDisabled, isButtonDisabled, buttonContent, buttonClassName, buttonAttributes = [], itemsClassName, itemsAttributes = [], itemsScrollClassName, itemsScrollAttributes = [], backdropClassName, backdropAttributes = [], className, attributes = [], itemGroupKey, groupToHeading, groupClassName, groupAttributes = [], separatorClassName, separatorAttributes = [], anchor, name, form, isDisabled, isInvalid, } = config;
|
|
350
347
|
const itemToValue = config.itemToValue ?? (item => String(item));
|
|
351
348
|
const itemToSearchText = config.itemToSearchText ?? (item => itemToValue(item));
|
|
352
349
|
const dispatchSelectedItem = (value) => onSelectedItem
|
|
@@ -442,7 +439,12 @@ export const makeView = (behavior) => (config) => {
|
|
|
442
439
|
OnKeyUpPreventDefault(handleSpaceKeyUp),
|
|
443
440
|
OnClick(handleButtonClick()),
|
|
444
441
|
]),
|
|
445
|
-
...(isVisible
|
|
442
|
+
...(isVisible
|
|
443
|
+
? [
|
|
444
|
+
DataAttribute('open', ''),
|
|
445
|
+
Style({ position: 'relative', zIndex: '1' }),
|
|
446
|
+
]
|
|
447
|
+
: []),
|
|
446
448
|
...(isInvalid ? [DataAttribute('invalid', '')] : []),
|
|
447
449
|
...(buttonClassName ? [Class(buttonClassName)] : []),
|
|
448
450
|
...buttonAttributes,
|
|
@@ -9,7 +9,11 @@ export declare const Model: S.extend<S.Struct<{
|
|
|
9
9
|
isAnimated: typeof S.Boolean;
|
|
10
10
|
isModal: typeof S.Boolean;
|
|
11
11
|
orientation: S.Literal<["Vertical", "Horizontal"]>;
|
|
12
|
-
|
|
12
|
+
transition: S.Struct<{
|
|
13
|
+
id: typeof S.String;
|
|
14
|
+
isShowing: typeof S.Boolean;
|
|
15
|
+
transitionState: S.Literal<["Idle", "EnterStart", "EnterAnimating", "LeaveStart", "LeaveAnimating"]>;
|
|
16
|
+
}>;
|
|
13
17
|
maybeActiveItemIndex: S.OptionFromSelf<typeof S.Number>;
|
|
14
18
|
activationTrigger: S.Literal<["Pointer", "Keyboard"]>;
|
|
15
19
|
searchQuery: typeof S.String;
|
|
@@ -36,7 +40,11 @@ export declare const update: (model: {
|
|
|
36
40
|
readonly isAnimated: boolean;
|
|
37
41
|
readonly isModal: boolean;
|
|
38
42
|
readonly orientation: "Vertical" | "Horizontal";
|
|
39
|
-
readonly
|
|
43
|
+
readonly transition: {
|
|
44
|
+
readonly id: string;
|
|
45
|
+
readonly isShowing: boolean;
|
|
46
|
+
readonly transitionState: "Idle" | "EnterStart" | "EnterAnimating" | "LeaveStart" | "LeaveAnimating";
|
|
47
|
+
};
|
|
40
48
|
readonly maybeActiveItemIndex: Option.Option<number>;
|
|
41
49
|
readonly activationTrigger: "Pointer" | "Keyboard";
|
|
42
50
|
readonly searchQuery: string;
|
|
@@ -54,7 +62,11 @@ export declare const update: (model: {
|
|
|
54
62
|
readonly isAnimated: boolean;
|
|
55
63
|
readonly isModal: boolean;
|
|
56
64
|
readonly orientation: "Vertical" | "Horizontal";
|
|
57
|
-
readonly
|
|
65
|
+
readonly transition: {
|
|
66
|
+
readonly id: string;
|
|
67
|
+
readonly isShowing: boolean;
|
|
68
|
+
readonly transitionState: "Idle" | "EnterStart" | "EnterAnimating" | "LeaveStart" | "LeaveAnimating";
|
|
69
|
+
};
|
|
58
70
|
readonly maybeActiveItemIndex: Option.Option<number>;
|
|
59
71
|
readonly activationTrigger: "Pointer" | "Keyboard";
|
|
60
72
|
readonly searchQuery: string;
|
|
@@ -120,11 +132,16 @@ export declare const update: (model: {
|
|
|
120
132
|
} | {
|
|
121
133
|
readonly _tag: "SuppressedSpaceScroll";
|
|
122
134
|
} | {
|
|
123
|
-
readonly _tag: "
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
135
|
+
readonly _tag: "GotTransitionMessage";
|
|
136
|
+
readonly message: {
|
|
137
|
+
readonly _tag: "Showed";
|
|
138
|
+
} | {
|
|
139
|
+
readonly _tag: "Hidden";
|
|
140
|
+
} | {
|
|
141
|
+
readonly _tag: "AdvancedTransitionFrame";
|
|
142
|
+
} | {
|
|
143
|
+
readonly _tag: "EndedTransition";
|
|
144
|
+
};
|
|
128
145
|
} | {
|
|
129
146
|
readonly _tag: "PressedPointerOnButton";
|
|
130
147
|
readonly button: number;
|
|
@@ -144,7 +161,11 @@ export declare const view: <Message, Item>(config: Readonly<{
|
|
|
144
161
|
readonly isAnimated: boolean;
|
|
145
162
|
readonly isModal: boolean;
|
|
146
163
|
readonly orientation: "Vertical" | "Horizontal";
|
|
147
|
-
readonly
|
|
164
|
+
readonly transition: {
|
|
165
|
+
readonly id: string;
|
|
166
|
+
readonly isShowing: boolean;
|
|
167
|
+
readonly transitionState: "Idle" | "EnterStart" | "EnterAnimating" | "LeaveStart" | "LeaveAnimating";
|
|
168
|
+
};
|
|
148
169
|
readonly maybeActiveItemIndex: Option.Option<number>;
|
|
149
170
|
readonly activationTrigger: "Pointer" | "Keyboard";
|
|
150
171
|
readonly searchQuery: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"single.d.ts","sourceRoot":"","sources":["../../../src/ui/listbox/single.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAE,MAAM,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"single.d.ts","sourceRoot":"","sources":["../../../src/ui/listbox/single.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAEnD,OAAO,KAAK,KAAK,OAAO,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,KAAK,IAAI,EAAc,MAAM,YAAY,CAAA;AAElD,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,cAAc,EACnB,KAAK,OAAO,EACZ,YAAY,EAIb,MAAM,UAAU,CAAA;AAIjB,mJAAmJ;AACnJ,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;GAEjB,CAAA;AAED,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,6RAA6R;AAC7R,MAAM,MAAM,UAAU,GAAG,cAAc,GACrC,QAAQ,CAAC;IACP,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAC,CAAA;AAEJ,6HAA6H;AAC7H,eAAO,MAAM,IAAI,GAAI,QAAQ,UAAU,KAAG,KAGxC,CAAA;AAIF,qIAAqI;AACrI,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAMjB,CAAA;AAEF;gGACgG;AAChG,eAAO,MAAM,UAAU,GACrB,OAAO,KAAK,EACZ,MAAM,MAAM,KACX,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CACpB,CAAA;AAIvC,uEAAuE;AACvE,MAAM,MAAM,UAAU,CAAC,OAAO,EAAE,IAAI,IAAI,cAAc,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;AAE5E,2JAA2J;AAC3J,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAWf,CAAA;AAEF;mFACmF;AACnF,eAAO,MAAM,IAAI,GAAI,OAAO,EAAE,IAAI,EAChC,cAAc,IAAI,CAChB,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,EACzB,OAAO,GAAG,iBAAiB,GAAG,gBAAgB,CAC/C,KACA,CAAC,CACF,KAAK,EAAE,KAAK,EACZ,eAAe,EAAE,cAAc,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,iBAAiB,CAAC,KACrE,IAAI,CAoBR,CAAA"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Array, Option, Schema as S
|
|
1
|
+
import { Array, Option, Schema as S } from 'effect';
|
|
2
2
|
import { createLazy } from '../../html';
|
|
3
3
|
import { evo } from '../../struct';
|
|
4
|
-
import { BaseModel, SelectedItem, baseInit,
|
|
4
|
+
import { BaseModel, SelectedItem, baseInit, makeUpdate, makeView, } from './shared';
|
|
5
5
|
// MODEL
|
|
6
6
|
/** Schema for the listbox component's state, tracking open/closed status, active item, selected item, activation trigger, and typeahead search. */
|
|
7
7
|
export const Model = BaseModel.pipe(S.extend(S.Struct({ maybeSelectedItem: S.OptionFromSelf(S.String) })));
|
|
@@ -12,16 +12,13 @@ export const init = (config) => ({
|
|
|
12
12
|
});
|
|
13
13
|
// UPDATE
|
|
14
14
|
/** Processes a listbox message and returns the next model and commands. Closes the listbox on selection (single-select behavior). */
|
|
15
|
-
export const update = makeUpdate((model, item, context) =>
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
context.maybeRestoreInert,
|
|
23
|
-
]), Array.prepend(context.focusButton)),
|
|
24
|
-
]);
|
|
15
|
+
export const update = makeUpdate((model, item, context) => {
|
|
16
|
+
const [closedModelResult, commands] = context.closeWithFocus(model);
|
|
17
|
+
return [
|
|
18
|
+
evo(closedModelResult, { maybeSelectedItem: () => Option.some(item) }),
|
|
19
|
+
commands,
|
|
20
|
+
];
|
|
21
|
+
});
|
|
25
22
|
/** Programmatically selects an item in the single-select listbox, closing the listbox and returning
|
|
26
23
|
* focus commands. Use this in domain-event handlers when the listbox uses `onSelectedItem`. */
|
|
27
24
|
export const selectItem = (model, item) => update(model, SelectedItem({ item }));
|