vorma 0.86.0-pre.2 → 0.86.0-pre.3
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/core/_index.d.ts +1 -0
- package/.dist/core/_index.d.ts.map +1 -1
- package/.dist/core/_index.js +6 -0
- package/.dist/core/_index.js.map +1 -1
- package/.dist/core/vorma_client_wasm_bg.wasm +0 -0
- package/.dist/ui/solid/solid.js +29 -39
- package/.dist/ui/solid/solid.js.map +1 -1
- package/core/client_wasm/vorma_client_wasm_bg.wasm +0 -0
- package/core/create_client_core.ts +9 -1
- package/package.json +1 -16
- package/ui/solid/solid.tsx +29 -10
- package/.dist/kit/lab/design/components/remix/remix.d.ts +0 -2309
- package/.dist/kit/lab/design/components/remix/remix.d.ts.map +0 -1
- package/.dist/kit/lab/design/components/remix/remix.js +0 -7022
- package/.dist/kit/lab/design/components/remix/remix.js.map +0 -1
- package/.dist/kit/lab/design/core/core.d.ts +0 -527
- package/.dist/kit/lab/design/core/core.d.ts.map +0 -1
- package/.dist/kit/lab/design/core/core.js +0 -668
- package/.dist/kit/lab/design/core/core.js.map +0 -1
- package/.dist/kit/matcher/matcher.d.ts +0 -78
- package/.dist/kit/matcher/matcher.d.ts.map +0 -1
- package/.dist/kit/matcher/matcher.js +0 -517
- package/.dist/kit/matcher/matcher.js.map +0 -1
- package/.dist/ui/remix/remix.d.ts +0 -73
- package/.dist/ui/remix/remix.d.ts.map +0 -1
- package/.dist/ui/remix/remix.js +0 -409
- package/.dist/ui/remix/remix.js.map +0 -1
- package/kit/lab/design/components/remix/accordion.ts +0 -474
- package/kit/lab/design/components/remix/alert-dialog.ts +0 -512
- package/kit/lab/design/components/remix/alert.ts +0 -213
- package/kit/lab/design/components/remix/aspect-ratio.ts +0 -111
- package/kit/lab/design/components/remix/badge.ts +0 -59
- package/kit/lab/design/components/remix/box.ts +0 -49
- package/kit/lab/design/components/remix/button.ts +0 -314
- package/kit/lab/design/components/remix/callout.ts +0 -127
- package/kit/lab/design/components/remix/checkable-state.ts +0 -187
- package/kit/lab/design/components/remix/checkbox-group.ts +0 -443
- package/kit/lab/design/components/remix/checkbox.ts +0 -215
- package/kit/lab/design/components/remix/chip.ts +0 -165
- package/kit/lab/design/components/remix/code-block.ts +0 -181
- package/kit/lab/design/components/remix/collapsible.ts +0 -325
- package/kit/lab/design/components/remix/component-state.ts +0 -55
- package/kit/lab/design/components/remix/component-style.ts +0 -364
- package/kit/lab/design/components/remix/composite-navigation.ts +0 -71
- package/kit/lab/design/components/remix/conditions.ts +0 -25
- package/kit/lab/design/components/remix/controllable-state.ts +0 -58
- package/kit/lab/design/components/remix/description-list.ts +0 -275
- package/kit/lab/design/components/remix/dialog.ts +0 -653
- package/kit/lab/design/components/remix/empty-state.ts +0 -146
- package/kit/lab/design/components/remix/field.ts +0 -418
- package/kit/lab/design/components/remix/fieldset.ts +0 -153
- package/kit/lab/design/components/remix/form-mirror.ts +0 -94
- package/kit/lab/design/components/remix/form-reset.ts +0 -85
- package/kit/lab/design/components/remix/form.ts +0 -109
- package/kit/lab/design/components/remix/grid.ts +0 -187
- package/kit/lab/design/components/remix/group-label.ts +0 -47
- package/kit/lab/design/components/remix/icon.ts +0 -176
- package/kit/lab/design/components/remix/input.ts +0 -163
- package/kit/lab/design/components/remix/kbd.ts +0 -58
- package/kit/lab/design/components/remix/list.ts +0 -120
- package/kit/lab/design/components/remix/listbox.ts +0 -1116
- package/kit/lab/design/components/remix/menu.ts +0 -1477
- package/kit/lab/design/components/remix/ordered-collection.ts +0 -95
- package/kit/lab/design/components/remix/popover-scroll-lock.ts +0 -89
- package/kit/lab/design/components/remix/popover.ts +0 -576
- package/kit/lab/design/components/remix/popup-behavior.ts +0 -96
- package/kit/lab/design/components/remix/progress.ts +0 -185
- package/kit/lab/design/components/remix/radio-group.ts +0 -420
- package/kit/lab/design/components/remix/recipe.ts +0 -70
- package/kit/lab/design/components/remix/remix.ts +0 -683
- package/kit/lab/design/components/remix/responsive.ts +0 -106
- package/kit/lab/design/components/remix/root.ts +0 -137
- package/kit/lab/design/components/remix/select.ts +0 -1546
- package/kit/lab/design/components/remix/separator.ts +0 -108
- package/kit/lab/design/components/remix/slider.ts +0 -308
- package/kit/lab/design/components/remix/spinner.ts +0 -114
- package/kit/lab/design/components/remix/stack.ts +0 -205
- package/kit/lab/design/components/remix/stat.ts +0 -127
- package/kit/lab/design/components/remix/surface.ts +0 -71
- package/kit/lab/design/components/remix/switch.ts +0 -219
- package/kit/lab/design/components/remix/table.ts +0 -395
- package/kit/lab/design/components/remix/tabs.ts +0 -404
- package/kit/lab/design/components/remix/text.ts +0 -169
- package/kit/lab/design/components/remix/textarea.ts +0 -164
- package/kit/lab/design/components/remix/toast.ts +0 -299
- package/kit/lab/design/components/remix/tooltip.ts +0 -330
- package/kit/lab/design/components/remix/typeahead.ts +0 -81
- package/kit/lab/design/components/remix/types.ts +0 -19
- package/kit/lab/design/components/remix/visually-hidden.ts +0 -100
- package/kit/lab/design/core/color.ts +0 -46
- package/kit/lab/design/core/core.ts +0 -111
- package/kit/lab/design/core/create_primitive.ts +0 -455
- package/kit/lab/design/core/create_system.ts +0 -303
- package/kit/lab/design/core/css.ts +0 -127
- package/kit/lab/design/core/define_system.ts +0 -508
- package/kit/lab/design/core/math.ts +0 -12
- package/kit/lab/design/core/object.ts +0 -31
- package/kit/lab/design/core/recipe/create_recipe.ts +0 -185
- package/kit/lab/design/core/recipe/recipe.ts +0 -26
- package/kit/lab/design/core/recipe/style.ts +0 -62
- package/kit/lab/design/core/recipe/types.ts +0 -160
- package/kit/lab/design/core/resolve_token.ts +0 -118
- package/kit/lab/design/core/types.ts +0 -636
- package/ui/remix/remix.tsx +0 -901
|
@@ -1,1546 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Fragment,
|
|
3
|
-
createElement,
|
|
4
|
-
on,
|
|
5
|
-
ref,
|
|
6
|
-
type Handle,
|
|
7
|
-
type Props,
|
|
8
|
-
type RemixNode,
|
|
9
|
-
} from "remix/ui";
|
|
10
|
-
import {
|
|
11
|
-
createRecipe,
|
|
12
|
-
type AnyGeneratedSystemMetadata,
|
|
13
|
-
type RecipeVariantPropsFor,
|
|
14
|
-
type RecipeVariantValue,
|
|
15
|
-
type RecipeWithVariantGroups,
|
|
16
|
-
} from "../../core/core.ts";
|
|
17
|
-
import { checkableStateFromValue, type CheckableStateName } from "./checkable-state.ts";
|
|
18
|
-
import {
|
|
19
|
-
ariaBoolean,
|
|
20
|
-
ariaTrue,
|
|
21
|
-
componentDataAttribute,
|
|
22
|
-
componentStateAttribute,
|
|
23
|
-
dataFlag,
|
|
24
|
-
openStateFromBoolean,
|
|
25
|
-
} from "./component-state.ts";
|
|
26
|
-
import {
|
|
27
|
-
createComponentAnatomyAttrs,
|
|
28
|
-
createComponentSlotProps,
|
|
29
|
-
createComponentStyleTargets,
|
|
30
|
-
} from "./component-style.ts";
|
|
31
|
-
import {
|
|
32
|
-
get_collection_navigation_item,
|
|
33
|
-
get_first_collection_item,
|
|
34
|
-
get_last_collection_item,
|
|
35
|
-
} from "./composite-navigation.ts";
|
|
36
|
-
import { create_controllable_state } from "./controllable-state.ts";
|
|
37
|
-
import { createNativeSelectFormMirror } from "./form-mirror.ts";
|
|
38
|
-
import {
|
|
39
|
-
create_group_label_ref_mix,
|
|
40
|
-
create_group_label_relationship,
|
|
41
|
-
type GroupLabelRelationship,
|
|
42
|
-
} from "./group-label.ts";
|
|
43
|
-
import {
|
|
44
|
-
create_ordered_collection,
|
|
45
|
-
type OrderedCollectionItem,
|
|
46
|
-
} from "./ordered-collection.ts";
|
|
47
|
-
import { popoverScrollLockGuard } from "./popover-scroll-lock.ts";
|
|
48
|
-
import {
|
|
49
|
-
createPopupRefMix,
|
|
50
|
-
createPopupRelationship,
|
|
51
|
-
type PopupRelationship,
|
|
52
|
-
} from "./popup-behavior.ts";
|
|
53
|
-
import {
|
|
54
|
-
mergeRecipeConditionSelectors,
|
|
55
|
-
type RecipeConditionSelectorMap,
|
|
56
|
-
} from "./recipe.ts";
|
|
57
|
-
import { type BreakpointForStyleSystem, type ResponsiveProps } from "./responsive.ts";
|
|
58
|
-
import { create_typeahead } from "./typeahead.ts";
|
|
59
|
-
import type { ComponentStyle, ComponentStyleSystem, RemixComponent } from "./types.ts";
|
|
60
|
-
|
|
61
|
-
const select_slot = {
|
|
62
|
-
group: "group",
|
|
63
|
-
groupLabel: "groupLabel",
|
|
64
|
-
icon: "icon",
|
|
65
|
-
list: "list",
|
|
66
|
-
option: "option",
|
|
67
|
-
optionIndicator: "optionIndicator",
|
|
68
|
-
optionText: "optionText",
|
|
69
|
-
popup: "popup",
|
|
70
|
-
separator: "separator",
|
|
71
|
-
trigger: "trigger",
|
|
72
|
-
value: "value",
|
|
73
|
-
} as const;
|
|
74
|
-
|
|
75
|
-
export type SelectRecipeSlot = (typeof select_slot)[keyof typeof select_slot];
|
|
76
|
-
|
|
77
|
-
export type SelectRecipeCondition =
|
|
78
|
-
| "active"
|
|
79
|
-
| "disabled"
|
|
80
|
-
| "focusVisible"
|
|
81
|
-
| "highlighted"
|
|
82
|
-
| "hover"
|
|
83
|
-
| "open"
|
|
84
|
-
| "placeholder"
|
|
85
|
-
| "reducedMotion"
|
|
86
|
-
| "selected";
|
|
87
|
-
|
|
88
|
-
export type SelectRecipeInput<
|
|
89
|
-
TVariant extends string = string,
|
|
90
|
-
TSize extends string = string,
|
|
91
|
-
TPopupLayout extends string = string,
|
|
92
|
-
> = RecipeWithVariantGroups<
|
|
93
|
-
SelectRecipeSlot,
|
|
94
|
-
string,
|
|
95
|
-
ComponentStyle,
|
|
96
|
-
{
|
|
97
|
-
popupLayout: TPopupLayout;
|
|
98
|
-
size: TSize;
|
|
99
|
-
variant: TVariant;
|
|
100
|
-
}
|
|
101
|
-
>;
|
|
102
|
-
|
|
103
|
-
export type SelectRecipeVariant<TRecipe extends SelectRecipeInput> = RecipeVariantValue<
|
|
104
|
-
TRecipe,
|
|
105
|
-
"variant"
|
|
106
|
-
>;
|
|
107
|
-
export type SelectRecipeSize<TRecipe extends SelectRecipeInput> = RecipeVariantValue<
|
|
108
|
-
TRecipe,
|
|
109
|
-
"size"
|
|
110
|
-
>;
|
|
111
|
-
export type SelectRecipePopupLayout<TRecipe extends SelectRecipeInput> =
|
|
112
|
-
RecipeVariantValue<TRecipe, "popupLayout">;
|
|
113
|
-
export type SelectRecipeSelection<TRecipe extends SelectRecipeInput> =
|
|
114
|
-
RecipeVariantPropsFor<TRecipe, "popupLayout" | "size" | "variant">;
|
|
115
|
-
|
|
116
|
-
export type SelectStyleSystem<
|
|
117
|
-
TMode extends string = string,
|
|
118
|
-
TRecipe extends SelectRecipeInput = SelectRecipeInput,
|
|
119
|
-
TMetadata extends AnyGeneratedSystemMetadata = AnyGeneratedSystemMetadata,
|
|
120
|
-
> = ComponentStyleSystem<TMode, { recipe: { select: TRecipe } }, TMetadata>;
|
|
121
|
-
|
|
122
|
-
export const selectOpenChangeReason = {
|
|
123
|
-
escape: "escape",
|
|
124
|
-
interactOutside: "interactOutside",
|
|
125
|
-
option: "option",
|
|
126
|
-
tab: "tab",
|
|
127
|
-
trigger: "trigger",
|
|
128
|
-
} as const;
|
|
129
|
-
|
|
130
|
-
export const selectValueChangeReason = {
|
|
131
|
-
keyboard: "keyboard",
|
|
132
|
-
pointer: "pointer",
|
|
133
|
-
} as const;
|
|
134
|
-
|
|
135
|
-
export const selectHighlightChangeReason = {
|
|
136
|
-
keyboard: "keyboard",
|
|
137
|
-
open: "open",
|
|
138
|
-
pointer: "pointer",
|
|
139
|
-
typeahead: "typeahead",
|
|
140
|
-
} as const;
|
|
141
|
-
|
|
142
|
-
export type SelectOpenChangeReason =
|
|
143
|
-
(typeof selectOpenChangeReason)[keyof typeof selectOpenChangeReason];
|
|
144
|
-
|
|
145
|
-
export type SelectValueChangeReason =
|
|
146
|
-
(typeof selectValueChangeReason)[keyof typeof selectValueChangeReason];
|
|
147
|
-
|
|
148
|
-
export type SelectHighlightChangeReason =
|
|
149
|
-
(typeof selectHighlightChangeReason)[keyof typeof selectHighlightChangeReason];
|
|
150
|
-
|
|
151
|
-
export type SelectOpenChangeDetails = {
|
|
152
|
-
event?: Event;
|
|
153
|
-
reason: SelectOpenChangeReason;
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
export type SelectValueChangeDetails = {
|
|
157
|
-
event?: Event;
|
|
158
|
-
reason: SelectValueChangeReason;
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
export type SelectHighlightChangeDetails = {
|
|
162
|
-
event?: Event;
|
|
163
|
-
reason: SelectHighlightChangeReason;
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
export type SelectValueChangeHandler<TValue extends string = string> = (
|
|
167
|
-
value: TValue | null,
|
|
168
|
-
details?: SelectValueChangeDetails,
|
|
169
|
-
) => void;
|
|
170
|
-
|
|
171
|
-
export type SelectOpenChangeHandler = (
|
|
172
|
-
open: boolean,
|
|
173
|
-
details?: SelectOpenChangeDetails,
|
|
174
|
-
) => void;
|
|
175
|
-
|
|
176
|
-
export type SelectHighlightChangeHandler<TValue extends string = string> = (
|
|
177
|
-
value: TValue | null,
|
|
178
|
-
details?: SelectHighlightChangeDetails,
|
|
179
|
-
) => void;
|
|
180
|
-
|
|
181
|
-
export type SelectProps<TValue extends string = string> = {
|
|
182
|
-
autoComplete?: string;
|
|
183
|
-
children?: RemixNode;
|
|
184
|
-
defaultOpen?: boolean;
|
|
185
|
-
defaultHighlightedValue?: TValue | null;
|
|
186
|
-
defaultValue?: TValue | null;
|
|
187
|
-
disabled?: boolean;
|
|
188
|
-
form?: string;
|
|
189
|
-
highlightedValue?: TValue | null;
|
|
190
|
-
invalid?: boolean;
|
|
191
|
-
loopFocus?: boolean;
|
|
192
|
-
name?: string;
|
|
193
|
-
onHighlightChange?: SelectHighlightChangeHandler<TValue>;
|
|
194
|
-
onOpenChange?: SelectOpenChangeHandler;
|
|
195
|
-
onOpenChangeComplete?: SelectOpenChangeHandler;
|
|
196
|
-
onValueChange?: SelectValueChangeHandler<TValue>;
|
|
197
|
-
open?: boolean;
|
|
198
|
-
placeholder?: string;
|
|
199
|
-
readOnly?: boolean;
|
|
200
|
-
required?: boolean;
|
|
201
|
-
typeahead?: boolean;
|
|
202
|
-
value?: TValue | null;
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
export type SelectTriggerStyleProps<
|
|
206
|
-
TVariant extends string = string,
|
|
207
|
-
TSize extends string = string,
|
|
208
|
-
> = {
|
|
209
|
-
size?: TSize;
|
|
210
|
-
variant?: TVariant;
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
export type SelectTriggerProps<
|
|
214
|
-
TVariant extends string = string,
|
|
215
|
-
TSize extends string = string,
|
|
216
|
-
TBreakpoint extends string = string,
|
|
217
|
-
> = Omit<Props<"button">, "style"> &
|
|
218
|
-
SelectTriggerStyleProps<TVariant, TSize> &
|
|
219
|
-
ResponsiveProps<SelectTriggerStyleProps<TVariant, TSize>, TBreakpoint> & {
|
|
220
|
-
style?: never;
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
export type SelectPopupStyleProps<TLayout extends string = string> = {
|
|
224
|
-
layout?: TLayout;
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
export type SelectPopupProps<
|
|
228
|
-
TLayout extends string = string,
|
|
229
|
-
TBreakpoint extends string = string,
|
|
230
|
-
> = Omit<Props<"div">, "style"> &
|
|
231
|
-
SelectPopupStyleProps<TLayout> &
|
|
232
|
-
ResponsiveProps<SelectPopupStyleProps<TLayout>, TBreakpoint> & {
|
|
233
|
-
style?: never;
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
export type SelectListProps<
|
|
237
|
-
TLayout extends string = string,
|
|
238
|
-
TBreakpoint extends string = string,
|
|
239
|
-
> = SelectPopupProps<TLayout, TBreakpoint>;
|
|
240
|
-
|
|
241
|
-
export type SelectValueProps = Omit<Props<"span">, "style"> & {
|
|
242
|
-
placeholder?: RemixNode;
|
|
243
|
-
style?: never;
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
export type SelectIconProps = Omit<Props<"span">, "style"> & {
|
|
247
|
-
style?: never;
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
export type SelectGroupProps = Omit<Props<"div">, "style"> & {
|
|
251
|
-
style?: never;
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
export type SelectGroupLabelProps = Omit<Props<"div">, "style"> & {
|
|
255
|
-
style?: never;
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
export type SelectSeparatorProps = Omit<Props<"div">, "style"> & {
|
|
259
|
-
style?: never;
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
export type SelectOptionProps<TValue extends string = string> = Omit<
|
|
263
|
-
Props<"div">,
|
|
264
|
-
"style"
|
|
265
|
-
> & {
|
|
266
|
-
disabled?: boolean;
|
|
267
|
-
style?: never;
|
|
268
|
-
textValue?: string;
|
|
269
|
-
value: TValue;
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
export type SelectOptionTextProps = Omit<Props<"span">, "style"> & {
|
|
273
|
-
style?: never;
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
export type SelectOptionIndicatorProps = Omit<Props<"span">, "style"> & {
|
|
277
|
-
style?: never;
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
export type SelectComponents<
|
|
281
|
-
TVariant extends string = string,
|
|
282
|
-
TSize extends string = string,
|
|
283
|
-
TPopupLayout extends string = string,
|
|
284
|
-
> = {
|
|
285
|
-
Group: RemixComponent<SelectGroupProps, SelectGroupRuntimeContext>;
|
|
286
|
-
GroupLabel: RemixComponent<SelectGroupLabelProps>;
|
|
287
|
-
Icon: RemixComponent<SelectIconProps>;
|
|
288
|
-
List: RemixComponent<SelectListProps<TPopupLayout>>;
|
|
289
|
-
Option: RemixComponent<SelectOptionProps>;
|
|
290
|
-
OptionIndicator: RemixComponent<SelectOptionIndicatorProps>;
|
|
291
|
-
OptionText: RemixComponent<SelectOptionTextProps>;
|
|
292
|
-
Popup: RemixComponent<SelectPopupProps<TPopupLayout>>;
|
|
293
|
-
Root: RemixComponent<SelectProps, SelectRuntimeContext>;
|
|
294
|
-
Separator: RemixComponent<SelectSeparatorProps>;
|
|
295
|
-
Trigger: RemixComponent<SelectTriggerProps<TVariant, TSize>>;
|
|
296
|
-
Value: RemixComponent<SelectValueProps>;
|
|
297
|
-
};
|
|
298
|
-
|
|
299
|
-
export type SelectOptions = {
|
|
300
|
-
conditions?: Partial<
|
|
301
|
-
Readonly<Record<SelectRecipeSlot, RecipeConditionSelectorMap<string>>>
|
|
302
|
-
>;
|
|
303
|
-
};
|
|
304
|
-
|
|
305
|
-
type SelectRuntimeContext = {
|
|
306
|
-
close: (details: SelectOpenChangeDetails) => void;
|
|
307
|
-
get_disabled: () => boolean;
|
|
308
|
-
get_highlighted_id: () => string | undefined;
|
|
309
|
-
get_highlighted_value: () => string | null;
|
|
310
|
-
get_invalid: () => boolean;
|
|
311
|
-
get_list_id: () => string;
|
|
312
|
-
get_open: () => boolean;
|
|
313
|
-
get_placeholder: () => string | undefined;
|
|
314
|
-
get_popup_relationship: () => PopupRelationship;
|
|
315
|
-
get_popup_id: () => string;
|
|
316
|
-
get_read_only: () => boolean;
|
|
317
|
-
get_required: () => boolean;
|
|
318
|
-
get_selected_text: () => string | undefined;
|
|
319
|
-
get_trigger_id: () => string;
|
|
320
|
-
get_value: () => string | null;
|
|
321
|
-
handle_keydown: (event: KeyboardEvent) => void;
|
|
322
|
-
highlight_by_offset: (offset: number, details: SelectHighlightChangeDetails) => void;
|
|
323
|
-
highlight_first: () => void;
|
|
324
|
-
highlight_last: () => void;
|
|
325
|
-
highlight_value: (
|
|
326
|
-
value: string | null,
|
|
327
|
-
details: SelectHighlightChangeDetails,
|
|
328
|
-
) => void;
|
|
329
|
-
open: (details: SelectOpenChangeDetails, highlight?: SelectOpenHighlight) => void;
|
|
330
|
-
register_option: (option: RegisteredSelectOption) => void;
|
|
331
|
-
register_trigger: (node: HTMLElement | null) => void;
|
|
332
|
-
search: (text: string, event: KeyboardEvent) => void;
|
|
333
|
-
select_value: (value: string | null, details: SelectValueChangeDetails) => void;
|
|
334
|
-
sync_popup: () => void;
|
|
335
|
-
toggle: (details: SelectOpenChangeDetails) => void;
|
|
336
|
-
unregister_option: (id: string) => void;
|
|
337
|
-
};
|
|
338
|
-
|
|
339
|
-
type RegisteredSelectOption = OrderedCollectionItem<string>;
|
|
340
|
-
|
|
341
|
-
type SelectOpenHighlight = "first" | "last" | "selected";
|
|
342
|
-
|
|
343
|
-
type SelectGroupRuntimeContext = GroupLabelRelationship;
|
|
344
|
-
|
|
345
|
-
const trigger_conditions = {
|
|
346
|
-
active: "&:active",
|
|
347
|
-
disabled: "&:disabled, &[aria-disabled='true']",
|
|
348
|
-
focusVisible: "&:focus-visible",
|
|
349
|
-
hover: "&:hover",
|
|
350
|
-
open: "&[aria-expanded='true']",
|
|
351
|
-
placeholder: `&[${componentDataAttribute.placeholder}]`,
|
|
352
|
-
reducedMotion: "@media (prefers-reduced-motion: reduce)",
|
|
353
|
-
} as const satisfies RecipeConditionSelectorMap<SelectRecipeCondition>;
|
|
354
|
-
|
|
355
|
-
const option_conditions = {
|
|
356
|
-
disabled: `&[aria-disabled='true'], &[${componentDataAttribute.disabled}]`,
|
|
357
|
-
highlighted: `&[${componentDataAttribute.highlighted}]`,
|
|
358
|
-
reducedMotion: "@media (prefers-reduced-motion: reduce)",
|
|
359
|
-
selected: `&[aria-selected='true'], &[${componentDataAttribute.selected}]`,
|
|
360
|
-
} as const satisfies RecipeConditionSelectorMap<SelectRecipeCondition>;
|
|
361
|
-
|
|
362
|
-
const open_conditions = {
|
|
363
|
-
open: `&:popover-open, &[${componentDataAttribute.open}]`,
|
|
364
|
-
reducedMotion: "@media (prefers-reduced-motion: reduce)",
|
|
365
|
-
} as const satisfies RecipeConditionSelectorMap<SelectRecipeCondition>;
|
|
366
|
-
|
|
367
|
-
const value_conditions = {
|
|
368
|
-
placeholder: `&[${componentDataAttribute.placeholder}]`,
|
|
369
|
-
reducedMotion: "@media (prefers-reduced-motion: reduce)",
|
|
370
|
-
} as const satisfies RecipeConditionSelectorMap<SelectRecipeCondition>;
|
|
371
|
-
|
|
372
|
-
const select_scope = "select";
|
|
373
|
-
const select_option_value_attribute = "data-vorma-select-value";
|
|
374
|
-
const select_page_jump_size = 10;
|
|
375
|
-
const select_typeahead_reset_ms = 700;
|
|
376
|
-
|
|
377
|
-
function infer_text_value(children: RemixNode): string {
|
|
378
|
-
if (typeof children === "string" || typeof children === "number") {
|
|
379
|
-
return String(children);
|
|
380
|
-
}
|
|
381
|
-
return "";
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
function is_select_keyboard_selection(event: KeyboardEvent): boolean {
|
|
385
|
-
return event.key === "Enter" || event.key === " " || event.key === "Spacebar";
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
function is_printable_key_event(event: KeyboardEvent): boolean {
|
|
389
|
-
return event.key.length === 1 && !event.altKey && !event.ctrlKey && !event.metaKey;
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
function coerce_select_value(value: string | null | undefined): string | null {
|
|
393
|
-
return value ?? null;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
function select_option_state(selected: boolean): CheckableStateName {
|
|
397
|
-
return checkableStateFromValue(selected, false);
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
export function createSelect<
|
|
401
|
-
TMode extends string,
|
|
402
|
-
TRecipe extends SelectRecipeInput,
|
|
403
|
-
TMetadata extends AnyGeneratedSystemMetadata,
|
|
404
|
-
>(
|
|
405
|
-
style_system: SelectStyleSystem<TMode, TRecipe, TMetadata>,
|
|
406
|
-
options: SelectOptions = {},
|
|
407
|
-
): SelectComponents<
|
|
408
|
-
SelectRecipeVariant<TRecipe>,
|
|
409
|
-
SelectRecipeSize<TRecipe>,
|
|
410
|
-
SelectRecipePopupLayout<TRecipe>
|
|
411
|
-
> {
|
|
412
|
-
type TVariant = SelectRecipeVariant<TRecipe>;
|
|
413
|
-
type TSize = SelectRecipeSize<TRecipe>;
|
|
414
|
-
type TPopupLayout = SelectRecipePopupLayout<TRecipe>;
|
|
415
|
-
type TBreakpoint = BreakpointForStyleSystem<typeof style_system>;
|
|
416
|
-
|
|
417
|
-
const select_recipe = createRecipe(style_system.token.recipe.select);
|
|
418
|
-
|
|
419
|
-
function Root(
|
|
420
|
-
handle: Handle<SelectProps, SelectRuntimeContext>,
|
|
421
|
-
): (props: SelectProps) => RemixNode {
|
|
422
|
-
let local_open = handle.props.defaultOpen ?? false;
|
|
423
|
-
let local_value = handle.props.defaultValue ?? null;
|
|
424
|
-
let local_highlighted_value = handle.props.defaultHighlightedValue ?? null;
|
|
425
|
-
let last_completed_open = handle.props.open ?? local_open;
|
|
426
|
-
let last_open_details: SelectOpenChangeDetails = {
|
|
427
|
-
reason: selectOpenChangeReason.trigger,
|
|
428
|
-
};
|
|
429
|
-
const popup_relationship = createPopupRelationship();
|
|
430
|
-
const option_collection = create_ordered_collection<RegisteredSelectOption>();
|
|
431
|
-
const option_typeahead = create_typeahead<RegisteredSelectOption>({
|
|
432
|
-
timeoutMs: select_typeahead_reset_ms,
|
|
433
|
-
});
|
|
434
|
-
const open_state = create_controllable_state<boolean, SelectOpenChangeDetails>({
|
|
435
|
-
getControlled: () => {
|
|
436
|
-
return handle.props.open;
|
|
437
|
-
},
|
|
438
|
-
getLocal: () => {
|
|
439
|
-
return local_open;
|
|
440
|
-
},
|
|
441
|
-
getOnChange: () => {
|
|
442
|
-
return handle.props.onOpenChange;
|
|
443
|
-
},
|
|
444
|
-
setLocal: (value) => {
|
|
445
|
-
local_open = value;
|
|
446
|
-
},
|
|
447
|
-
});
|
|
448
|
-
const value_state = create_controllable_state<
|
|
449
|
-
string | null,
|
|
450
|
-
SelectValueChangeDetails
|
|
451
|
-
>({
|
|
452
|
-
getControlled: () => {
|
|
453
|
-
if (handle.props.value === undefined) {
|
|
454
|
-
return undefined;
|
|
455
|
-
}
|
|
456
|
-
return coerce_select_value(handle.props.value);
|
|
457
|
-
},
|
|
458
|
-
getLocal: () => {
|
|
459
|
-
return local_value;
|
|
460
|
-
},
|
|
461
|
-
getOnChange: () => {
|
|
462
|
-
return handle.props.onValueChange;
|
|
463
|
-
},
|
|
464
|
-
setLocal: (value) => {
|
|
465
|
-
local_value = value;
|
|
466
|
-
},
|
|
467
|
-
});
|
|
468
|
-
const highlighted_state = create_controllable_state<
|
|
469
|
-
string | null,
|
|
470
|
-
SelectHighlightChangeDetails
|
|
471
|
-
>({
|
|
472
|
-
getControlled: () => {
|
|
473
|
-
if (handle.props.highlightedValue === undefined) {
|
|
474
|
-
return undefined;
|
|
475
|
-
}
|
|
476
|
-
return coerce_select_value(handle.props.highlightedValue);
|
|
477
|
-
},
|
|
478
|
-
getLocal: () => {
|
|
479
|
-
return local_highlighted_value;
|
|
480
|
-
},
|
|
481
|
-
getOnChange: () => {
|
|
482
|
-
return handle.props.onHighlightChange;
|
|
483
|
-
},
|
|
484
|
-
setLocal: (value) => {
|
|
485
|
-
local_highlighted_value = value;
|
|
486
|
-
},
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
function get_open(): boolean {
|
|
490
|
-
return open_state.get();
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
function get_value(): string | null {
|
|
494
|
-
return value_state.get();
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
function get_highlighted_value(): string | null {
|
|
498
|
-
return highlighted_state.get();
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
function get_options(): RegisteredSelectOption[] {
|
|
502
|
-
return option_collection.getItems();
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
function get_enabled_options(): RegisteredSelectOption[] {
|
|
506
|
-
return option_collection.getEnabledItems();
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
function find_option(value: string | null): RegisteredSelectOption | undefined {
|
|
510
|
-
if (value === null) {
|
|
511
|
-
return undefined;
|
|
512
|
-
}
|
|
513
|
-
return option_collection.findByValue(value);
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
function scroll_highlighted_option_into_view(): void {
|
|
517
|
-
const highlighted_option = find_option(get_highlighted_value());
|
|
518
|
-
if (
|
|
519
|
-
highlighted_option &&
|
|
520
|
-
typeof highlighted_option.node.scrollIntoView === "function"
|
|
521
|
-
) {
|
|
522
|
-
highlighted_option.node.scrollIntoView({ block: "nearest" });
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
function schedule_highlight_scroll(): void {
|
|
527
|
-
handle.queueTask((signal) => {
|
|
528
|
-
if (signal.aborted) {
|
|
529
|
-
return;
|
|
530
|
-
}
|
|
531
|
-
scroll_highlighted_option_into_view();
|
|
532
|
-
});
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
function request_open(open: boolean, details: SelectOpenChangeDetails): void {
|
|
536
|
-
if (open && handle.props.disabled) {
|
|
537
|
-
return;
|
|
538
|
-
}
|
|
539
|
-
const changed = open_state.set(open, details);
|
|
540
|
-
if (!changed) {
|
|
541
|
-
return;
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
last_open_details = details;
|
|
545
|
-
void handle.update();
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
function set_highlighted_value(
|
|
549
|
-
value: string | null,
|
|
550
|
-
details: SelectHighlightChangeDetails,
|
|
551
|
-
): void {
|
|
552
|
-
const changed = highlighted_state.set(value, details);
|
|
553
|
-
if (!changed) {
|
|
554
|
-
return;
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
schedule_highlight_scroll();
|
|
558
|
-
void handle.update();
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
function highlight_option(
|
|
562
|
-
option: RegisteredSelectOption | undefined,
|
|
563
|
-
details: SelectHighlightChangeDetails,
|
|
564
|
-
): void {
|
|
565
|
-
set_highlighted_value(option?.value ?? null, details);
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
function move_highlight(
|
|
569
|
-
offset: number,
|
|
570
|
-
details: SelectHighlightChangeDetails,
|
|
571
|
-
clamp = false,
|
|
572
|
-
): void {
|
|
573
|
-
const enabled_options = get_enabled_options();
|
|
574
|
-
if (enabled_options.length === 0) {
|
|
575
|
-
highlight_option(undefined, details);
|
|
576
|
-
return;
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
const next_option = get_collection_navigation_item({
|
|
580
|
-
clamp,
|
|
581
|
-
currentValue: get_highlighted_value(),
|
|
582
|
-
fallbackValue: get_value(),
|
|
583
|
-
items: enabled_options,
|
|
584
|
-
loop: handle.props.loopFocus,
|
|
585
|
-
offset,
|
|
586
|
-
});
|
|
587
|
-
if (next_option === undefined) {
|
|
588
|
-
return;
|
|
589
|
-
}
|
|
590
|
-
highlight_option(next_option, details);
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
function select_value(
|
|
594
|
-
value: string | null,
|
|
595
|
-
details: SelectValueChangeDetails,
|
|
596
|
-
): void {
|
|
597
|
-
if (handle.props.disabled || handle.props.readOnly) {
|
|
598
|
-
return;
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
const option = find_option(value);
|
|
602
|
-
if (option?.disabled) {
|
|
603
|
-
return;
|
|
604
|
-
}
|
|
605
|
-
value_state.set(value, details);
|
|
606
|
-
if (handle.props.highlightedValue === undefined) {
|
|
607
|
-
local_highlighted_value = value;
|
|
608
|
-
}
|
|
609
|
-
request_open(false, {
|
|
610
|
-
event: details.event,
|
|
611
|
-
reason:
|
|
612
|
-
details.event instanceof KeyboardEvent && details.event.key === "Tab"
|
|
613
|
-
? selectOpenChangeReason.tab
|
|
614
|
-
: selectOpenChangeReason.option,
|
|
615
|
-
});
|
|
616
|
-
void handle.update();
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
function search(text: string, event: KeyboardEvent): void {
|
|
620
|
-
if (handle.props.typeahead === false) {
|
|
621
|
-
return;
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
const match = option_typeahead.search({
|
|
625
|
-
currentValue: get_highlighted_value(),
|
|
626
|
-
items: get_enabled_options(),
|
|
627
|
-
key: text,
|
|
628
|
-
});
|
|
629
|
-
|
|
630
|
-
highlight_option(match, {
|
|
631
|
-
event,
|
|
632
|
-
reason: selectHighlightChangeReason.typeahead,
|
|
633
|
-
});
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
function apply_open_highlight(
|
|
637
|
-
highlight: SelectOpenHighlight | undefined,
|
|
638
|
-
details: SelectOpenChangeDetails,
|
|
639
|
-
): void {
|
|
640
|
-
if (highlight === "first") {
|
|
641
|
-
highlight_option(get_first_collection_item(get_enabled_options()), {
|
|
642
|
-
event: details.event,
|
|
643
|
-
reason: selectHighlightChangeReason.open,
|
|
644
|
-
});
|
|
645
|
-
return;
|
|
646
|
-
}
|
|
647
|
-
if (highlight === "last") {
|
|
648
|
-
highlight_option(get_last_collection_item(get_enabled_options()), {
|
|
649
|
-
event: details.event,
|
|
650
|
-
reason: selectHighlightChangeReason.open,
|
|
651
|
-
});
|
|
652
|
-
return;
|
|
653
|
-
}
|
|
654
|
-
if (highlight === "selected" && get_highlighted_value() === null) {
|
|
655
|
-
highlight_option(find_option(get_value()), {
|
|
656
|
-
event: details.event,
|
|
657
|
-
reason: selectHighlightChangeReason.open,
|
|
658
|
-
});
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
function create_hidden_select(props: SelectProps): RemixNode {
|
|
663
|
-
return createNativeSelectFormMirror({
|
|
664
|
-
autoComplete: props.autoComplete,
|
|
665
|
-
disabled: props.disabled,
|
|
666
|
-
form: props.form,
|
|
667
|
-
name: props.name,
|
|
668
|
-
options: get_options().map((option) => {
|
|
669
|
-
return {
|
|
670
|
-
disabled: option.disabled,
|
|
671
|
-
text: option.text,
|
|
672
|
-
value: option.value,
|
|
673
|
-
};
|
|
674
|
-
}),
|
|
675
|
-
placeholder: props.placeholder,
|
|
676
|
-
required: props.required,
|
|
677
|
-
value: get_value(),
|
|
678
|
-
});
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
function open_from_keyboard(
|
|
682
|
-
event: KeyboardEvent,
|
|
683
|
-
highlight?: SelectOpenHighlight,
|
|
684
|
-
): void {
|
|
685
|
-
request_open(true, {
|
|
686
|
-
event,
|
|
687
|
-
reason: selectOpenChangeReason.trigger,
|
|
688
|
-
});
|
|
689
|
-
apply_open_highlight(highlight, {
|
|
690
|
-
event,
|
|
691
|
-
reason: selectOpenChangeReason.trigger,
|
|
692
|
-
});
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
function handle_keyboard(event: KeyboardEvent): void {
|
|
696
|
-
if (handle.props.disabled) {
|
|
697
|
-
return;
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
const keyboard_highlight_details: SelectHighlightChangeDetails = {
|
|
701
|
-
event,
|
|
702
|
-
reason: selectHighlightChangeReason.keyboard,
|
|
703
|
-
};
|
|
704
|
-
|
|
705
|
-
if (event.altKey && event.key === "ArrowDown") {
|
|
706
|
-
event.preventDefault();
|
|
707
|
-
open_from_keyboard(event, "selected");
|
|
708
|
-
return;
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
if (event.altKey && event.key === "ArrowUp" && get_open()) {
|
|
712
|
-
event.preventDefault();
|
|
713
|
-
select_value(get_highlighted_value(), {
|
|
714
|
-
event,
|
|
715
|
-
reason: selectValueChangeReason.keyboard,
|
|
716
|
-
});
|
|
717
|
-
return;
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
if (event.key === "ArrowDown") {
|
|
721
|
-
event.preventDefault();
|
|
722
|
-
if (get_open()) {
|
|
723
|
-
move_highlight(1, keyboard_highlight_details);
|
|
724
|
-
return;
|
|
725
|
-
}
|
|
726
|
-
open_from_keyboard(event, "selected");
|
|
727
|
-
return;
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
if (event.key === "ArrowUp") {
|
|
731
|
-
event.preventDefault();
|
|
732
|
-
if (get_open()) {
|
|
733
|
-
move_highlight(-1, keyboard_highlight_details);
|
|
734
|
-
return;
|
|
735
|
-
}
|
|
736
|
-
open_from_keyboard(event, "last");
|
|
737
|
-
return;
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
if (event.key === "Home") {
|
|
741
|
-
event.preventDefault();
|
|
742
|
-
if (!get_open()) {
|
|
743
|
-
open_from_keyboard(event, "first");
|
|
744
|
-
return;
|
|
745
|
-
}
|
|
746
|
-
highlight_option(
|
|
747
|
-
get_first_collection_item(get_enabled_options()),
|
|
748
|
-
keyboard_highlight_details,
|
|
749
|
-
);
|
|
750
|
-
return;
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
if (event.key === "End") {
|
|
754
|
-
event.preventDefault();
|
|
755
|
-
const enabled_options = get_enabled_options();
|
|
756
|
-
if (!get_open()) {
|
|
757
|
-
open_from_keyboard(event, "last");
|
|
758
|
-
return;
|
|
759
|
-
}
|
|
760
|
-
highlight_option(
|
|
761
|
-
get_last_collection_item(enabled_options),
|
|
762
|
-
keyboard_highlight_details,
|
|
763
|
-
);
|
|
764
|
-
return;
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
if (event.key === "PageDown" && get_open()) {
|
|
768
|
-
event.preventDefault();
|
|
769
|
-
move_highlight(select_page_jump_size, keyboard_highlight_details, true);
|
|
770
|
-
return;
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
if (event.key === "PageUp" && get_open()) {
|
|
774
|
-
event.preventDefault();
|
|
775
|
-
move_highlight(-select_page_jump_size, keyboard_highlight_details, true);
|
|
776
|
-
return;
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
if (is_select_keyboard_selection(event)) {
|
|
780
|
-
event.preventDefault();
|
|
781
|
-
if (!get_open()) {
|
|
782
|
-
open_from_keyboard(event, "selected");
|
|
783
|
-
return;
|
|
784
|
-
}
|
|
785
|
-
select_value(get_highlighted_value(), {
|
|
786
|
-
event,
|
|
787
|
-
reason: selectValueChangeReason.keyboard,
|
|
788
|
-
});
|
|
789
|
-
return;
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
if (event.key === "Escape" && get_open()) {
|
|
793
|
-
event.preventDefault();
|
|
794
|
-
request_open(false, {
|
|
795
|
-
event,
|
|
796
|
-
reason: selectOpenChangeReason.escape,
|
|
797
|
-
});
|
|
798
|
-
return;
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
if (event.key === "Tab" && get_open()) {
|
|
802
|
-
const highlighted_value = get_highlighted_value();
|
|
803
|
-
if (highlighted_value === null) {
|
|
804
|
-
request_open(false, {
|
|
805
|
-
event,
|
|
806
|
-
reason: selectOpenChangeReason.tab,
|
|
807
|
-
});
|
|
808
|
-
return;
|
|
809
|
-
}
|
|
810
|
-
select_value(highlighted_value, {
|
|
811
|
-
event,
|
|
812
|
-
reason: selectValueChangeReason.keyboard,
|
|
813
|
-
});
|
|
814
|
-
return;
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
if (is_printable_key_event(event)) {
|
|
818
|
-
event.preventDefault();
|
|
819
|
-
if (!get_open()) {
|
|
820
|
-
request_open(true, {
|
|
821
|
-
event,
|
|
822
|
-
reason: selectOpenChangeReason.trigger,
|
|
823
|
-
});
|
|
824
|
-
}
|
|
825
|
-
search(event.key, event);
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
const context: SelectRuntimeContext = {
|
|
830
|
-
close: (details) => {
|
|
831
|
-
request_open(false, details);
|
|
832
|
-
},
|
|
833
|
-
get_disabled: () => {
|
|
834
|
-
return handle.props.disabled === true;
|
|
835
|
-
},
|
|
836
|
-
get_highlighted_id: () => {
|
|
837
|
-
return find_option(get_highlighted_value())?.id;
|
|
838
|
-
},
|
|
839
|
-
get_highlighted_value,
|
|
840
|
-
get_invalid: () => {
|
|
841
|
-
return handle.props.invalid === true;
|
|
842
|
-
},
|
|
843
|
-
get_list_id: () => {
|
|
844
|
-
return `${handle.id}-list`;
|
|
845
|
-
},
|
|
846
|
-
get_open,
|
|
847
|
-
get_placeholder: () => {
|
|
848
|
-
return handle.props.placeholder;
|
|
849
|
-
},
|
|
850
|
-
get_popup_relationship: () => {
|
|
851
|
-
return popup_relationship;
|
|
852
|
-
},
|
|
853
|
-
get_popup_id: () => {
|
|
854
|
-
return `${handle.id}-popup`;
|
|
855
|
-
},
|
|
856
|
-
get_read_only: () => {
|
|
857
|
-
return handle.props.readOnly === true;
|
|
858
|
-
},
|
|
859
|
-
get_required: () => {
|
|
860
|
-
return handle.props.required === true;
|
|
861
|
-
},
|
|
862
|
-
get_selected_text: () => {
|
|
863
|
-
return find_option(get_value())?.text;
|
|
864
|
-
},
|
|
865
|
-
get_trigger_id: () => {
|
|
866
|
-
return `${handle.id}-trigger`;
|
|
867
|
-
},
|
|
868
|
-
get_value,
|
|
869
|
-
handle_keydown: handle_keyboard,
|
|
870
|
-
highlight_by_offset: (offset, details) => {
|
|
871
|
-
move_highlight(offset, details);
|
|
872
|
-
},
|
|
873
|
-
highlight_first: () => {
|
|
874
|
-
highlight_option(get_first_collection_item(get_enabled_options()), {
|
|
875
|
-
reason: selectHighlightChangeReason.keyboard,
|
|
876
|
-
});
|
|
877
|
-
},
|
|
878
|
-
highlight_last: () => {
|
|
879
|
-
highlight_option(get_last_collection_item(get_enabled_options()), {
|
|
880
|
-
reason: selectHighlightChangeReason.keyboard,
|
|
881
|
-
});
|
|
882
|
-
},
|
|
883
|
-
highlight_value: (value, details) => {
|
|
884
|
-
highlight_option(find_option(value), details);
|
|
885
|
-
},
|
|
886
|
-
open: (details, highlight = "selected") => {
|
|
887
|
-
if (handle.props.disabled) {
|
|
888
|
-
return;
|
|
889
|
-
}
|
|
890
|
-
apply_open_highlight(highlight, details);
|
|
891
|
-
request_open(true, details);
|
|
892
|
-
},
|
|
893
|
-
register_option: (option) => {
|
|
894
|
-
const changed = option_collection.register(option);
|
|
895
|
-
if (changed) {
|
|
896
|
-
void handle.update();
|
|
897
|
-
}
|
|
898
|
-
},
|
|
899
|
-
register_trigger: (node) => {
|
|
900
|
-
popup_relationship.registerTrigger(node);
|
|
901
|
-
},
|
|
902
|
-
search,
|
|
903
|
-
select_value,
|
|
904
|
-
sync_popup: () => {
|
|
905
|
-
popup_relationship.syncPopup(get_open());
|
|
906
|
-
schedule_highlight_scroll();
|
|
907
|
-
},
|
|
908
|
-
toggle: (details) => {
|
|
909
|
-
if (get_open()) {
|
|
910
|
-
request_open(false, details);
|
|
911
|
-
return;
|
|
912
|
-
}
|
|
913
|
-
context.open(details);
|
|
914
|
-
},
|
|
915
|
-
unregister_option: (id) => {
|
|
916
|
-
const option = option_collection.unregister(id);
|
|
917
|
-
void handle.update();
|
|
918
|
-
if (option?.value === get_highlighted_value()) {
|
|
919
|
-
set_highlighted_value(null, {
|
|
920
|
-
reason: selectHighlightChangeReason.open,
|
|
921
|
-
});
|
|
922
|
-
}
|
|
923
|
-
},
|
|
924
|
-
};
|
|
925
|
-
handle.context.set(context);
|
|
926
|
-
|
|
927
|
-
return (props: SelectProps): RemixNode => {
|
|
928
|
-
const current_open = get_open();
|
|
929
|
-
if (current_open !== last_completed_open) {
|
|
930
|
-
const completed_open = current_open;
|
|
931
|
-
const completed_details = last_open_details;
|
|
932
|
-
last_completed_open = current_open;
|
|
933
|
-
handle.queueTask((signal) => {
|
|
934
|
-
if (signal.aborted) {
|
|
935
|
-
return;
|
|
936
|
-
}
|
|
937
|
-
props.onOpenChangeComplete?.(completed_open, completed_details);
|
|
938
|
-
});
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
return createElement(
|
|
942
|
-
Fragment,
|
|
943
|
-
{},
|
|
944
|
-
props.children,
|
|
945
|
-
create_hidden_select(props),
|
|
946
|
-
);
|
|
947
|
-
};
|
|
948
|
-
}
|
|
949
|
-
|
|
950
|
-
function create_resolve_slot<TProps extends object>(
|
|
951
|
-
slot: SelectRecipeSlot,
|
|
952
|
-
selection: (props: Partial<TProps>) => SelectRecipeSelection<TRecipe>,
|
|
953
|
-
): (
|
|
954
|
-
props: Partial<TProps>,
|
|
955
|
-
) => ReturnType<typeof select_recipe.resolve>["slots"][typeof slot] {
|
|
956
|
-
return (props) => {
|
|
957
|
-
return select_recipe.resolve(selection(props)).slots[slot];
|
|
958
|
-
};
|
|
959
|
-
}
|
|
960
|
-
|
|
961
|
-
function Trigger(
|
|
962
|
-
handle: Handle<SelectTriggerProps<TVariant, TSize, TBreakpoint>>,
|
|
963
|
-
): (props: SelectTriggerProps<TVariant, TSize, TBreakpoint>) => RemixNode {
|
|
964
|
-
const context = handle.context.get(Root);
|
|
965
|
-
const resolve_slot = create_resolve_slot<
|
|
966
|
-
SelectTriggerStyleProps<TVariant, TSize>
|
|
967
|
-
>(select_slot.trigger, (props) => {
|
|
968
|
-
return {
|
|
969
|
-
size: props.size,
|
|
970
|
-
variant: props.variant,
|
|
971
|
-
} satisfies SelectRecipeSelection<TRecipe>;
|
|
972
|
-
});
|
|
973
|
-
|
|
974
|
-
return (props: SelectTriggerProps<TVariant, TSize, TBreakpoint>): RemixNode => {
|
|
975
|
-
const {
|
|
976
|
-
at,
|
|
977
|
-
children,
|
|
978
|
-
mix,
|
|
979
|
-
size,
|
|
980
|
-
type = "button",
|
|
981
|
-
variant,
|
|
982
|
-
...trigger_props
|
|
983
|
-
} = props;
|
|
984
|
-
const is_open = context.get_open();
|
|
985
|
-
const has_value = context.get_value() !== null;
|
|
986
|
-
const highlighted_id = context.get_highlighted_id();
|
|
987
|
-
const parts = createComponentStyleTargets({
|
|
988
|
-
at,
|
|
989
|
-
hostElements: {
|
|
990
|
-
[select_slot.trigger]: "button",
|
|
991
|
-
},
|
|
992
|
-
targets: {
|
|
993
|
-
[select_slot.trigger]: {
|
|
994
|
-
host: select_slot.trigger,
|
|
995
|
-
conditions: mergeRecipeConditionSelectors(
|
|
996
|
-
trigger_conditions,
|
|
997
|
-
options.conditions?.[select_slot.trigger],
|
|
998
|
-
),
|
|
999
|
-
resolveSlot: resolve_slot,
|
|
1000
|
-
},
|
|
1001
|
-
},
|
|
1002
|
-
props: { size, variant },
|
|
1003
|
-
styleSystem: style_system,
|
|
1004
|
-
});
|
|
1005
|
-
const trigger_click_mix = on<HTMLButtonElement, "click">("click", (event) => {
|
|
1006
|
-
context.toggle({
|
|
1007
|
-
event,
|
|
1008
|
-
reason: selectOpenChangeReason.trigger,
|
|
1009
|
-
});
|
|
1010
|
-
});
|
|
1011
|
-
const trigger_keydown_mix = on<HTMLButtonElement, "keydown">(
|
|
1012
|
-
"keydown",
|
|
1013
|
-
(event) => {
|
|
1014
|
-
context.handle_keydown(event);
|
|
1015
|
-
},
|
|
1016
|
-
);
|
|
1017
|
-
const trigger_ref_mix = ref<HTMLButtonElement>((node, signal) => {
|
|
1018
|
-
context.register_trigger(node);
|
|
1019
|
-
signal.addEventListener("abort", () => {
|
|
1020
|
-
context.register_trigger(null);
|
|
1021
|
-
});
|
|
1022
|
-
});
|
|
1023
|
-
|
|
1024
|
-
return createElement(
|
|
1025
|
-
"button",
|
|
1026
|
-
createComponentSlotProps({
|
|
1027
|
-
attrs: createComponentAnatomyAttrs(select_scope, select_slot.trigger),
|
|
1028
|
-
mix: [
|
|
1029
|
-
trigger_ref_mix,
|
|
1030
|
-
trigger_click_mix,
|
|
1031
|
-
trigger_keydown_mix,
|
|
1032
|
-
parts.hosts[select_slot.trigger].mix,
|
|
1033
|
-
],
|
|
1034
|
-
props: {
|
|
1035
|
-
...trigger_props,
|
|
1036
|
-
"aria-activedescendant": is_open ? highlighted_id : undefined,
|
|
1037
|
-
"aria-controls": context.get_list_id(),
|
|
1038
|
-
"aria-disabled": ariaTrue(context.get_disabled()),
|
|
1039
|
-
"aria-expanded": ariaBoolean(is_open),
|
|
1040
|
-
"aria-haspopup": "listbox",
|
|
1041
|
-
"aria-invalid": ariaTrue(context.get_invalid()),
|
|
1042
|
-
"aria-readonly": ariaTrue(context.get_read_only()),
|
|
1043
|
-
"aria-required": ariaTrue(context.get_required()),
|
|
1044
|
-
[componentDataAttribute.disabled]: dataFlag(
|
|
1045
|
-
context.get_disabled(),
|
|
1046
|
-
),
|
|
1047
|
-
[componentDataAttribute.invalid]: dataFlag(context.get_invalid()),
|
|
1048
|
-
[componentDataAttribute.open]: dataFlag(is_open),
|
|
1049
|
-
[componentDataAttribute.placeholder]: dataFlag(!has_value),
|
|
1050
|
-
[componentDataAttribute.readOnly]: dataFlag(
|
|
1051
|
-
context.get_read_only(),
|
|
1052
|
-
),
|
|
1053
|
-
[componentDataAttribute.required]: dataFlag(
|
|
1054
|
-
context.get_required(),
|
|
1055
|
-
),
|
|
1056
|
-
[componentStateAttribute]: openStateFromBoolean(is_open),
|
|
1057
|
-
disabled: context.get_disabled(),
|
|
1058
|
-
id: context.get_trigger_id(),
|
|
1059
|
-
mix,
|
|
1060
|
-
role: "combobox",
|
|
1061
|
-
type,
|
|
1062
|
-
},
|
|
1063
|
-
}),
|
|
1064
|
-
children,
|
|
1065
|
-
);
|
|
1066
|
-
};
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
function Popup(
|
|
1070
|
-
handle: Handle<SelectPopupProps<TPopupLayout, TBreakpoint>>,
|
|
1071
|
-
): (props: SelectPopupProps<TPopupLayout, TBreakpoint>) => RemixNode {
|
|
1072
|
-
const context = handle.context.get(Root);
|
|
1073
|
-
const resolve_slot = create_resolve_slot<SelectPopupStyleProps<TPopupLayout>>(
|
|
1074
|
-
select_slot.popup,
|
|
1075
|
-
(props) => {
|
|
1076
|
-
return {
|
|
1077
|
-
popupLayout: props.layout,
|
|
1078
|
-
} satisfies SelectRecipeSelection<TRecipe>;
|
|
1079
|
-
},
|
|
1080
|
-
);
|
|
1081
|
-
|
|
1082
|
-
return (props: SelectPopupProps<TPopupLayout, TBreakpoint>): RemixNode => {
|
|
1083
|
-
const { at, children, layout, mix, ...popup_props } = props;
|
|
1084
|
-
const is_open = context.get_open();
|
|
1085
|
-
const parts = createComponentStyleTargets({
|
|
1086
|
-
at,
|
|
1087
|
-
targets: {
|
|
1088
|
-
[select_slot.popup]: {
|
|
1089
|
-
host: select_slot.popup,
|
|
1090
|
-
conditions: mergeRecipeConditionSelectors(
|
|
1091
|
-
open_conditions,
|
|
1092
|
-
options.conditions?.[select_slot.popup],
|
|
1093
|
-
),
|
|
1094
|
-
resolveSlot: resolve_slot,
|
|
1095
|
-
},
|
|
1096
|
-
},
|
|
1097
|
-
props: { layout },
|
|
1098
|
-
styleSystem: style_system,
|
|
1099
|
-
});
|
|
1100
|
-
const popup_ref_mix = createPopupRefMix({
|
|
1101
|
-
getOpen: context.get_open,
|
|
1102
|
-
onInteractOutside: (event) => {
|
|
1103
|
-
context.close({
|
|
1104
|
-
event,
|
|
1105
|
-
reason: selectOpenChangeReason.interactOutside,
|
|
1106
|
-
});
|
|
1107
|
-
},
|
|
1108
|
-
relationship: context.get_popup_relationship(),
|
|
1109
|
-
});
|
|
1110
|
-
|
|
1111
|
-
handle.queueTask((signal) => {
|
|
1112
|
-
if (signal.aborted) {
|
|
1113
|
-
return;
|
|
1114
|
-
}
|
|
1115
|
-
context.sync_popup();
|
|
1116
|
-
});
|
|
1117
|
-
|
|
1118
|
-
return createElement(
|
|
1119
|
-
"div",
|
|
1120
|
-
createComponentSlotProps({
|
|
1121
|
-
attrs: createComponentAnatomyAttrs(select_scope, select_slot.popup),
|
|
1122
|
-
mix: [
|
|
1123
|
-
popoverScrollLockGuard(),
|
|
1124
|
-
popup_ref_mix,
|
|
1125
|
-
parts.hosts[select_slot.popup].mix,
|
|
1126
|
-
],
|
|
1127
|
-
props: {
|
|
1128
|
-
...popup_props,
|
|
1129
|
-
"aria-labelledby": context.get_trigger_id(),
|
|
1130
|
-
[componentDataAttribute.open]: dataFlag(is_open),
|
|
1131
|
-
hidden: !is_open,
|
|
1132
|
-
id: context.get_popup_id(),
|
|
1133
|
-
mix,
|
|
1134
|
-
popover: "manual",
|
|
1135
|
-
},
|
|
1136
|
-
}),
|
|
1137
|
-
children,
|
|
1138
|
-
);
|
|
1139
|
-
};
|
|
1140
|
-
}
|
|
1141
|
-
|
|
1142
|
-
function List(
|
|
1143
|
-
handle: Handle<SelectListProps<TPopupLayout, TBreakpoint>>,
|
|
1144
|
-
): (props: SelectListProps<TPopupLayout, TBreakpoint>) => RemixNode {
|
|
1145
|
-
const context = handle.context.get(Root);
|
|
1146
|
-
const resolve_slot = create_resolve_slot<SelectPopupStyleProps<TPopupLayout>>(
|
|
1147
|
-
select_slot.list,
|
|
1148
|
-
(props) => {
|
|
1149
|
-
return {
|
|
1150
|
-
popupLayout: props.layout,
|
|
1151
|
-
} satisfies SelectRecipeSelection<TRecipe>;
|
|
1152
|
-
},
|
|
1153
|
-
);
|
|
1154
|
-
|
|
1155
|
-
return (props: SelectPopupProps<TPopupLayout, TBreakpoint>): RemixNode => {
|
|
1156
|
-
const { at, children, layout, mix, ...list_props } = props;
|
|
1157
|
-
const parts = createComponentStyleTargets({
|
|
1158
|
-
at,
|
|
1159
|
-
targets: {
|
|
1160
|
-
[select_slot.list]: {
|
|
1161
|
-
host: select_slot.list,
|
|
1162
|
-
conditions: mergeRecipeConditionSelectors(
|
|
1163
|
-
open_conditions,
|
|
1164
|
-
options.conditions?.[select_slot.list],
|
|
1165
|
-
),
|
|
1166
|
-
resolveSlot: resolve_slot,
|
|
1167
|
-
},
|
|
1168
|
-
},
|
|
1169
|
-
props: { layout },
|
|
1170
|
-
styleSystem: style_system,
|
|
1171
|
-
});
|
|
1172
|
-
const list_keydown_mix = on<HTMLElement, "keydown">("keydown", (event) => {
|
|
1173
|
-
context.handle_keydown(event);
|
|
1174
|
-
});
|
|
1175
|
-
|
|
1176
|
-
return createElement(
|
|
1177
|
-
"div",
|
|
1178
|
-
createComponentSlotProps({
|
|
1179
|
-
attrs: createComponentAnatomyAttrs(select_scope, select_slot.list),
|
|
1180
|
-
mix: [list_keydown_mix, parts.hosts[select_slot.list].mix],
|
|
1181
|
-
props: {
|
|
1182
|
-
...list_props,
|
|
1183
|
-
"aria-labelledby": context.get_trigger_id(),
|
|
1184
|
-
id: context.get_list_id(),
|
|
1185
|
-
mix,
|
|
1186
|
-
role: "listbox",
|
|
1187
|
-
},
|
|
1188
|
-
}),
|
|
1189
|
-
children,
|
|
1190
|
-
);
|
|
1191
|
-
};
|
|
1192
|
-
}
|
|
1193
|
-
|
|
1194
|
-
function Value(
|
|
1195
|
-
handle: Handle<SelectValueProps>,
|
|
1196
|
-
): (props: SelectValueProps) => RemixNode {
|
|
1197
|
-
const context = handle.context.get(Root);
|
|
1198
|
-
|
|
1199
|
-
return (props: SelectValueProps): RemixNode => {
|
|
1200
|
-
const { children, mix, placeholder, ...value_props } = props;
|
|
1201
|
-
const selected_text = context.get_selected_text();
|
|
1202
|
-
const placeholder_text = placeholder ?? context.get_placeholder();
|
|
1203
|
-
const is_placeholder = selected_text === undefined;
|
|
1204
|
-
const parts = createComponentStyleTargets({
|
|
1205
|
-
targets: {
|
|
1206
|
-
[select_slot.value]: {
|
|
1207
|
-
host: select_slot.value,
|
|
1208
|
-
conditions: mergeRecipeConditionSelectors(
|
|
1209
|
-
value_conditions,
|
|
1210
|
-
options.conditions?.[select_slot.value],
|
|
1211
|
-
),
|
|
1212
|
-
resolveSlot: () => {
|
|
1213
|
-
return select_recipe.resolve().slots.value;
|
|
1214
|
-
},
|
|
1215
|
-
},
|
|
1216
|
-
},
|
|
1217
|
-
props: {},
|
|
1218
|
-
styleSystem: style_system,
|
|
1219
|
-
});
|
|
1220
|
-
|
|
1221
|
-
return createElement(
|
|
1222
|
-
"span",
|
|
1223
|
-
createComponentSlotProps({
|
|
1224
|
-
attrs: createComponentAnatomyAttrs(select_scope, select_slot.value),
|
|
1225
|
-
mix: parts.hosts[select_slot.value].mix,
|
|
1226
|
-
props: {
|
|
1227
|
-
...value_props,
|
|
1228
|
-
[componentDataAttribute.placeholder]: dataFlag(is_placeholder),
|
|
1229
|
-
mix,
|
|
1230
|
-
},
|
|
1231
|
-
}),
|
|
1232
|
-
children ?? selected_text ?? placeholder_text,
|
|
1233
|
-
);
|
|
1234
|
-
};
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
function create_static_span_component<TProps extends { mix?: unknown }>(
|
|
1238
|
-
slot: SelectRecipeSlot,
|
|
1239
|
-
): RemixComponent<TProps> {
|
|
1240
|
-
return () => {
|
|
1241
|
-
return (props: TProps): RemixNode => {
|
|
1242
|
-
const { children, mix, ...rest_props } = props as TProps & {
|
|
1243
|
-
children?: RemixNode;
|
|
1244
|
-
mix?: unknown;
|
|
1245
|
-
};
|
|
1246
|
-
const parts = createComponentStyleTargets({
|
|
1247
|
-
targets: {
|
|
1248
|
-
[slot]: {
|
|
1249
|
-
host: slot,
|
|
1250
|
-
resolveSlot: () => {
|
|
1251
|
-
return select_recipe.resolve().slots[slot];
|
|
1252
|
-
},
|
|
1253
|
-
},
|
|
1254
|
-
},
|
|
1255
|
-
props: {},
|
|
1256
|
-
styleSystem: style_system,
|
|
1257
|
-
});
|
|
1258
|
-
|
|
1259
|
-
return createElement(
|
|
1260
|
-
"span",
|
|
1261
|
-
createComponentSlotProps({
|
|
1262
|
-
attrs: createComponentAnatomyAttrs(select_scope, slot),
|
|
1263
|
-
mix: parts.hosts[slot].mix,
|
|
1264
|
-
props: {
|
|
1265
|
-
...rest_props,
|
|
1266
|
-
mix,
|
|
1267
|
-
},
|
|
1268
|
-
}),
|
|
1269
|
-
children,
|
|
1270
|
-
);
|
|
1271
|
-
};
|
|
1272
|
-
};
|
|
1273
|
-
}
|
|
1274
|
-
|
|
1275
|
-
function create_static_div_component<TProps extends { mix?: unknown }>(
|
|
1276
|
-
slot: SelectRecipeSlot,
|
|
1277
|
-
role?: string,
|
|
1278
|
-
): RemixComponent<TProps> {
|
|
1279
|
-
return () => {
|
|
1280
|
-
return (props: TProps): RemixNode => {
|
|
1281
|
-
const { children, mix, ...rest_props } = props as TProps & {
|
|
1282
|
-
children?: RemixNode;
|
|
1283
|
-
mix?: unknown;
|
|
1284
|
-
};
|
|
1285
|
-
const parts = createComponentStyleTargets({
|
|
1286
|
-
targets: {
|
|
1287
|
-
[slot]: {
|
|
1288
|
-
host: slot,
|
|
1289
|
-
resolveSlot: () => {
|
|
1290
|
-
return select_recipe.resolve().slots[slot];
|
|
1291
|
-
},
|
|
1292
|
-
},
|
|
1293
|
-
},
|
|
1294
|
-
props: {},
|
|
1295
|
-
styleSystem: style_system,
|
|
1296
|
-
});
|
|
1297
|
-
|
|
1298
|
-
return createElement(
|
|
1299
|
-
"div",
|
|
1300
|
-
createComponentSlotProps({
|
|
1301
|
-
attrs: createComponentAnatomyAttrs(select_scope, slot),
|
|
1302
|
-
mix: parts.hosts[slot].mix,
|
|
1303
|
-
props: {
|
|
1304
|
-
...rest_props,
|
|
1305
|
-
mix,
|
|
1306
|
-
role,
|
|
1307
|
-
},
|
|
1308
|
-
}),
|
|
1309
|
-
children,
|
|
1310
|
-
);
|
|
1311
|
-
};
|
|
1312
|
-
};
|
|
1313
|
-
}
|
|
1314
|
-
|
|
1315
|
-
function Group(
|
|
1316
|
-
handle: Handle<SelectGroupProps, SelectGroupRuntimeContext>,
|
|
1317
|
-
): (props: SelectGroupProps) => RemixNode {
|
|
1318
|
-
const group_context = create_group_label_relationship({
|
|
1319
|
-
label_id: `${handle.id}-label`,
|
|
1320
|
-
on_change: () => {
|
|
1321
|
-
void handle.update();
|
|
1322
|
-
},
|
|
1323
|
-
});
|
|
1324
|
-
handle.context.set(group_context);
|
|
1325
|
-
|
|
1326
|
-
return (props: SelectGroupProps): RemixNode => {
|
|
1327
|
-
const { children, mix, ...group_props } = props;
|
|
1328
|
-
const parts = createComponentStyleTargets({
|
|
1329
|
-
targets: {
|
|
1330
|
-
[select_slot.group]: {
|
|
1331
|
-
host: select_slot.group,
|
|
1332
|
-
resolveSlot: () => {
|
|
1333
|
-
return select_recipe.resolve().slots.group;
|
|
1334
|
-
},
|
|
1335
|
-
},
|
|
1336
|
-
},
|
|
1337
|
-
props: {},
|
|
1338
|
-
styleSystem: style_system,
|
|
1339
|
-
});
|
|
1340
|
-
|
|
1341
|
-
return createElement(
|
|
1342
|
-
"div",
|
|
1343
|
-
createComponentSlotProps({
|
|
1344
|
-
attrs: createComponentAnatomyAttrs(select_scope, select_slot.group),
|
|
1345
|
-
mix: parts.hosts[select_slot.group].mix,
|
|
1346
|
-
props: {
|
|
1347
|
-
...group_props,
|
|
1348
|
-
"aria-labelledby": group_context.get_labelled_by(),
|
|
1349
|
-
mix,
|
|
1350
|
-
role: "group",
|
|
1351
|
-
},
|
|
1352
|
-
}),
|
|
1353
|
-
children,
|
|
1354
|
-
);
|
|
1355
|
-
};
|
|
1356
|
-
}
|
|
1357
|
-
|
|
1358
|
-
function GroupLabel(
|
|
1359
|
-
handle: Handle<SelectGroupLabelProps>,
|
|
1360
|
-
): (props: SelectGroupLabelProps) => RemixNode {
|
|
1361
|
-
const group_context = handle.context.get(Group);
|
|
1362
|
-
|
|
1363
|
-
return (props: SelectGroupLabelProps): RemixNode => {
|
|
1364
|
-
const { children, mix, ...group_label_props } = props;
|
|
1365
|
-
const parts = createComponentStyleTargets({
|
|
1366
|
-
targets: {
|
|
1367
|
-
[select_slot.groupLabel]: {
|
|
1368
|
-
host: select_slot.groupLabel,
|
|
1369
|
-
resolveSlot: () => {
|
|
1370
|
-
return select_recipe.resolve().slots.groupLabel;
|
|
1371
|
-
},
|
|
1372
|
-
},
|
|
1373
|
-
},
|
|
1374
|
-
props: {},
|
|
1375
|
-
styleSystem: style_system,
|
|
1376
|
-
});
|
|
1377
|
-
const group_label_ref_mix = create_group_label_ref_mix(group_context);
|
|
1378
|
-
|
|
1379
|
-
return createElement(
|
|
1380
|
-
"div",
|
|
1381
|
-
createComponentSlotProps({
|
|
1382
|
-
attrs: createComponentAnatomyAttrs(
|
|
1383
|
-
select_scope,
|
|
1384
|
-
select_slot.groupLabel,
|
|
1385
|
-
),
|
|
1386
|
-
mix: [group_label_ref_mix, parts.hosts[select_slot.groupLabel].mix],
|
|
1387
|
-
props: {
|
|
1388
|
-
...group_label_props,
|
|
1389
|
-
id: group_context.get_label_id(),
|
|
1390
|
-
mix,
|
|
1391
|
-
},
|
|
1392
|
-
}),
|
|
1393
|
-
children,
|
|
1394
|
-
);
|
|
1395
|
-
};
|
|
1396
|
-
}
|
|
1397
|
-
|
|
1398
|
-
function Option(
|
|
1399
|
-
handle: Handle<SelectOptionProps>,
|
|
1400
|
-
): (props: SelectOptionProps) => RemixNode {
|
|
1401
|
-
const context = handle.context.get(Root);
|
|
1402
|
-
let option_node: HTMLElement | null = null;
|
|
1403
|
-
let option_id: string | null = null;
|
|
1404
|
-
|
|
1405
|
-
return (props: SelectOptionProps): RemixNode => {
|
|
1406
|
-
const {
|
|
1407
|
-
children,
|
|
1408
|
-
disabled = false,
|
|
1409
|
-
mix,
|
|
1410
|
-
textValue,
|
|
1411
|
-
value,
|
|
1412
|
-
...option_props
|
|
1413
|
-
} = props;
|
|
1414
|
-
const selected = context.get_value() === value;
|
|
1415
|
-
const highlighted = context.get_highlighted_value() === value;
|
|
1416
|
-
const option_text = textValue ?? infer_text_value(children);
|
|
1417
|
-
const current_option_id = `${handle.id}-option`;
|
|
1418
|
-
option_id = current_option_id;
|
|
1419
|
-
const parts = createComponentStyleTargets({
|
|
1420
|
-
targets: {
|
|
1421
|
-
[select_slot.option]: {
|
|
1422
|
-
host: select_slot.option,
|
|
1423
|
-
conditions: mergeRecipeConditionSelectors(
|
|
1424
|
-
option_conditions,
|
|
1425
|
-
options.conditions?.[select_slot.option],
|
|
1426
|
-
),
|
|
1427
|
-
resolveSlot: () => {
|
|
1428
|
-
return select_recipe.resolve().slots.option;
|
|
1429
|
-
},
|
|
1430
|
-
},
|
|
1431
|
-
},
|
|
1432
|
-
props: {},
|
|
1433
|
-
styleSystem: style_system,
|
|
1434
|
-
});
|
|
1435
|
-
const option_click_mix = on<HTMLElement, "click">("click", (event) => {
|
|
1436
|
-
if (disabled) {
|
|
1437
|
-
return;
|
|
1438
|
-
}
|
|
1439
|
-
context.select_value(value, {
|
|
1440
|
-
event,
|
|
1441
|
-
reason: selectValueChangeReason.pointer,
|
|
1442
|
-
});
|
|
1443
|
-
});
|
|
1444
|
-
const option_pointer_down_mix = on<HTMLElement, "pointerdown">(
|
|
1445
|
-
"pointerdown",
|
|
1446
|
-
(event) => {
|
|
1447
|
-
if (disabled) {
|
|
1448
|
-
return;
|
|
1449
|
-
}
|
|
1450
|
-
event.preventDefault();
|
|
1451
|
-
},
|
|
1452
|
-
);
|
|
1453
|
-
const option_pointer_move_mix = on<HTMLElement, "pointermove">(
|
|
1454
|
-
"pointermove",
|
|
1455
|
-
(event) => {
|
|
1456
|
-
if (disabled) {
|
|
1457
|
-
return;
|
|
1458
|
-
}
|
|
1459
|
-
context.highlight_value(value, {
|
|
1460
|
-
event,
|
|
1461
|
-
reason: selectHighlightChangeReason.pointer,
|
|
1462
|
-
});
|
|
1463
|
-
},
|
|
1464
|
-
);
|
|
1465
|
-
function register_option(node: HTMLElement): void {
|
|
1466
|
-
context.register_option({
|
|
1467
|
-
disabled,
|
|
1468
|
-
id: current_option_id,
|
|
1469
|
-
node,
|
|
1470
|
-
text: option_text || node.textContent || "",
|
|
1471
|
-
value,
|
|
1472
|
-
});
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1475
|
-
if (option_node) {
|
|
1476
|
-
handle.queueTask((signal) => {
|
|
1477
|
-
if (signal.aborted || !option_node) {
|
|
1478
|
-
return;
|
|
1479
|
-
}
|
|
1480
|
-
register_option(option_node);
|
|
1481
|
-
});
|
|
1482
|
-
}
|
|
1483
|
-
|
|
1484
|
-
const option_ref_mix = ref<HTMLElement>((node, signal) => {
|
|
1485
|
-
option_node = node;
|
|
1486
|
-
register_option(node);
|
|
1487
|
-
signal.addEventListener("abort", () => {
|
|
1488
|
-
if (option_id) {
|
|
1489
|
-
context.unregister_option(option_id);
|
|
1490
|
-
}
|
|
1491
|
-
option_node = null;
|
|
1492
|
-
});
|
|
1493
|
-
});
|
|
1494
|
-
|
|
1495
|
-
return createElement(
|
|
1496
|
-
"div",
|
|
1497
|
-
createComponentSlotProps({
|
|
1498
|
-
attrs: createComponentAnatomyAttrs(select_scope, select_slot.option),
|
|
1499
|
-
mix: [
|
|
1500
|
-
option_ref_mix,
|
|
1501
|
-
option_pointer_down_mix,
|
|
1502
|
-
option_click_mix,
|
|
1503
|
-
option_pointer_move_mix,
|
|
1504
|
-
parts.hosts[select_slot.option].mix,
|
|
1505
|
-
],
|
|
1506
|
-
props: {
|
|
1507
|
-
...option_props,
|
|
1508
|
-
"aria-disabled": ariaTrue(disabled),
|
|
1509
|
-
"aria-selected": ariaBoolean(selected),
|
|
1510
|
-
[componentDataAttribute.disabled]: dataFlag(disabled),
|
|
1511
|
-
[componentDataAttribute.highlighted]: dataFlag(highlighted),
|
|
1512
|
-
[componentDataAttribute.selected]: dataFlag(selected),
|
|
1513
|
-
[componentStateAttribute]: select_option_state(selected),
|
|
1514
|
-
[select_option_value_attribute]: value,
|
|
1515
|
-
id: current_option_id,
|
|
1516
|
-
mix,
|
|
1517
|
-
role: "option",
|
|
1518
|
-
},
|
|
1519
|
-
}),
|
|
1520
|
-
children ?? option_text,
|
|
1521
|
-
);
|
|
1522
|
-
};
|
|
1523
|
-
}
|
|
1524
|
-
|
|
1525
|
-
return {
|
|
1526
|
-
Group,
|
|
1527
|
-
GroupLabel,
|
|
1528
|
-
Icon: create_static_span_component<SelectIconProps>(select_slot.icon),
|
|
1529
|
-
List,
|
|
1530
|
-
Option,
|
|
1531
|
-
OptionIndicator: create_static_span_component<SelectOptionIndicatorProps>(
|
|
1532
|
-
select_slot.optionIndicator,
|
|
1533
|
-
),
|
|
1534
|
-
OptionText: create_static_span_component<SelectOptionTextProps>(
|
|
1535
|
-
select_slot.optionText,
|
|
1536
|
-
),
|
|
1537
|
-
Popup,
|
|
1538
|
-
Root,
|
|
1539
|
-
Separator: create_static_div_component<SelectSeparatorProps>(
|
|
1540
|
-
select_slot.separator,
|
|
1541
|
-
"separator",
|
|
1542
|
-
),
|
|
1543
|
-
Trigger,
|
|
1544
|
-
Value,
|
|
1545
|
-
};
|
|
1546
|
-
}
|