bits-ui 1.0.0-next.17 → 1.0.0-next.19
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/bits/combobox/components/combobox-input.svelte +2 -2
- package/dist/bits/combobox/components/combobox-trigger.svelte +2 -2
- package/dist/bits/combobox/components/combobox.svelte +9 -7
- package/dist/bits/combobox/exports.d.ts +8 -8
- package/dist/bits/combobox/exports.js +8 -8
- package/dist/bits/combobox/types.d.ts +1 -1
- package/dist/bits/dialog/components/dialog-content.svelte +1 -1
- package/dist/bits/index.d.ts +0 -1
- package/dist/bits/index.js +0 -1
- package/dist/bits/menu/menu.svelte.js +2 -2
- package/dist/bits/menubar/menubar.svelte.js +1 -1
- package/dist/bits/{listbox/components/listbox-content-static.svelte → select/components/select-content-static.svelte} +6 -6
- package/dist/bits/{listbox/components/listbox-group-heading.svelte.d.ts → select/components/select-content-static.svelte.d.ts} +4 -4
- package/dist/bits/select/components/select-content.svelte +56 -35
- package/dist/bits/select/components/select-group-heading.svelte +3 -3
- package/dist/bits/select/components/select-group.svelte +4 -3
- package/dist/bits/{listbox/components/listbox-hidden-input.svelte → select/components/select-hidden-input.svelte} +4 -4
- package/dist/bits/{listbox/components/listbox-hidden-input.svelte.d.ts → select/components/select-hidden-input.svelte.d.ts} +4 -4
- package/dist/bits/select/components/select-item.svelte +14 -9
- package/dist/bits/select/components/select-scroll-down-button.svelte +20 -9
- package/dist/bits/select/components/select-scroll-down-button.svelte.d.ts +2 -2
- package/dist/bits/select/components/select-scroll-up-button.svelte +21 -10
- package/dist/bits/select/components/select-trigger.svelte +5 -7
- package/dist/bits/select/components/select-viewport.svelte +10 -0
- package/dist/bits/select/components/select.svelte +54 -56
- package/dist/bits/select/exports.d.ts +4 -7
- package/dist/bits/select/exports.js +3 -6
- package/dist/bits/select/select.svelte.d.ts +272 -258
- package/dist/bits/select/select.svelte.js +764 -831
- package/dist/bits/select/types.d.ts +128 -79
- package/dist/bits/slider/components/slider.svelte +2 -2
- package/dist/bits/slider/slider.svelte.d.ts +2 -2
- package/dist/bits/slider/slider.svelte.js +4 -4
- package/dist/bits/slider/types.d.ts +3 -2
- package/dist/bits/utilities/popper-layer/popper-layer.svelte +1 -3
- package/dist/internal/arrays.d.ts +23 -0
- package/dist/internal/arrays.js +35 -0
- package/dist/internal/date-time/calendar-helpers.svelte.js +6 -1
- package/dist/internal/use-body-scroll-lock.svelte.js +53 -42
- package/dist/internal/use-data-typeahead.svelte.d.ts +12 -0
- package/dist/internal/use-data-typeahead.svelte.js +30 -0
- package/dist/internal/use-dom-typeahead.svelte.d.ts +11 -0
- package/dist/internal/use-dom-typeahead.svelte.js +30 -0
- package/dist/types.d.ts +1 -1
- package/package.json +2 -2
- package/dist/bits/listbox/components/listbox-content-static.svelte.d.ts +0 -19
- package/dist/bits/listbox/components/listbox-content.svelte +0 -76
- package/dist/bits/listbox/components/listbox-content.svelte.d.ts +0 -19
- package/dist/bits/listbox/components/listbox-group-heading.svelte +0 -32
- package/dist/bits/listbox/components/listbox-group.svelte +0 -32
- package/dist/bits/listbox/components/listbox-group.svelte.d.ts +0 -19
- package/dist/bits/listbox/components/listbox-item.svelte +0 -43
- package/dist/bits/listbox/components/listbox-item.svelte.d.ts +0 -19
- package/dist/bits/listbox/components/listbox-scroll-down-button.svelte +0 -39
- package/dist/bits/listbox/components/listbox-scroll-down-button.svelte.d.ts +0 -19
- package/dist/bits/listbox/components/listbox-scroll-up-button.svelte +0 -39
- package/dist/bits/listbox/components/listbox-scroll-up-button.svelte.d.ts +0 -19
- package/dist/bits/listbox/components/listbox-trigger.svelte +0 -35
- package/dist/bits/listbox/components/listbox-trigger.svelte.d.ts +0 -19
- package/dist/bits/listbox/components/listbox-viewport.svelte +0 -54
- package/dist/bits/listbox/components/listbox-viewport.svelte.d.ts +0 -19
- package/dist/bits/listbox/components/listbox.svelte +0 -81
- package/dist/bits/listbox/components/listbox.svelte.d.ts +0 -18
- package/dist/bits/listbox/exports.d.ts +0 -12
- package/dist/bits/listbox/exports.js +0 -11
- package/dist/bits/listbox/index.d.ts +0 -1
- package/dist/bits/listbox/index.js +0 -1
- package/dist/bits/listbox/listbox.svelte.d.ts +0 -399
- package/dist/bits/listbox/listbox.svelte.js +0 -973
- package/dist/bits/listbox/types.d.ts +0 -177
- package/dist/bits/listbox/types.js +0 -1
- package/dist/bits/select/components/select-arrow.svelte +0 -21
- package/dist/bits/select/components/select-arrow.svelte.d.ts +0 -18
- package/dist/bits/select/components/select-content-floating.svelte +0 -73
- package/dist/bits/select/components/select-content-floating.svelte.d.ts +0 -33
- package/dist/bits/select/components/select-content-impl.svelte +0 -90
- package/dist/bits/select/components/select-content-impl.svelte.d.ts +0 -90
- package/dist/bits/select/components/select-content-item-aligned.svelte +0 -37
- package/dist/bits/select/components/select-content-item-aligned.svelte.d.ts +0 -29
- package/dist/bits/select/components/select-icon.svelte +0 -36
- package/dist/bits/select/components/select-icon.svelte.d.ts +0 -19
- package/dist/bits/select/components/select-item-text.svelte +0 -39
- package/dist/bits/select/components/select-item-text.svelte.d.ts +0 -19
- package/dist/bits/select/components/select-native.svelte +0 -36
- package/dist/bits/select/components/select-native.svelte.d.ts +0 -30
- package/dist/bits/select/components/select-provider.svelte +0 -10
- package/dist/bits/select/components/select-provider.svelte.d.ts +0 -23
- package/dist/bits/select/components/select-scroll-down-button-mounted.svelte +0 -33
- package/dist/bits/select/components/select-scroll-down-button-mounted.svelte.d.ts +0 -29
- package/dist/bits/select/components/select-scroll-up-button-mounted.svelte +0 -33
- package/dist/bits/select/components/select-scroll-up-button-mounted.svelte.d.ts +0 -29
- package/dist/bits/select/components/select-separator.svelte +0 -32
- package/dist/bits/select/components/select-separator.svelte.d.ts +0 -19
- package/dist/bits/select/components/select-value.svelte +0 -35
- package/dist/bits/select/components/select-value.svelte.d.ts +0 -19
- package/dist/internal/use-typeahead.svelte.d.ts +0 -34
- package/dist/internal/use-typeahead.svelte.js +0 -64
|
@@ -1,52 +1,50 @@
|
|
|
1
|
-
import type { HTMLSelectAttributes } from "svelte/elements";
|
|
2
1
|
import type { Expand } from "svelte-toolbelt";
|
|
3
|
-
import type {
|
|
2
|
+
import type { PortalProps } from "../utilities/portal/types.js";
|
|
3
|
+
import type { PopperLayerProps, PopperLayerStaticProps } from "../utilities/popper-layer/types.js";
|
|
4
4
|
import type { ArrowProps, ArrowPropsWithoutHTML } from "../utilities/arrow/types.js";
|
|
5
|
-
import type {
|
|
6
|
-
import type {
|
|
7
|
-
|
|
8
|
-
import type { PortalProps } from "../utilities/portal/index.js";
|
|
9
|
-
export type SelectRootPropsWithoutHTML = WithChildren<{
|
|
5
|
+
import type { BitsPrimitiveButtonAttributes, BitsPrimitiveDivAttributes } from "../../shared/attributes.js";
|
|
6
|
+
import type { OnChangeFn, WithChild, WithChildNoChildrenSnippetProps, WithChildren, Without } from "../../internal/types.js";
|
|
7
|
+
export type SelectBaseRootPropsWithoutHTML = WithChildren<{
|
|
10
8
|
/**
|
|
11
|
-
*
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* A callback that is called when the select's open state changes.
|
|
16
|
-
*/
|
|
17
|
-
onOpenChange?: OnChangeFn<boolean>;
|
|
18
|
-
/**
|
|
19
|
-
* The value of the select.
|
|
20
|
-
*/
|
|
21
|
-
value?: string;
|
|
22
|
-
/**
|
|
23
|
-
* A callback that is called when the select's value changes.
|
|
9
|
+
* Whether the combobox is disabled.
|
|
10
|
+
*
|
|
11
|
+
* @defaultValue `false`
|
|
24
12
|
*/
|
|
25
|
-
|
|
13
|
+
disabled?: boolean;
|
|
26
14
|
/**
|
|
27
|
-
*
|
|
15
|
+
* Whether the combobox is required (for form submission).
|
|
16
|
+
*
|
|
17
|
+
* @defaultValue `false`
|
|
28
18
|
*/
|
|
29
|
-
|
|
19
|
+
required?: boolean;
|
|
30
20
|
/**
|
|
31
|
-
* The name
|
|
21
|
+
* The name to apply to the hidden input element for form submission.
|
|
22
|
+
* If not provided, a hidden input will not be rendered and the combobox will not be part of a form.
|
|
32
23
|
*/
|
|
33
24
|
name?: string;
|
|
34
25
|
/**
|
|
35
|
-
*
|
|
26
|
+
* Whether the combobox popover is open.
|
|
27
|
+
*
|
|
28
|
+
* @defaultValue `false`
|
|
29
|
+
* @bindable
|
|
36
30
|
*/
|
|
37
|
-
|
|
31
|
+
open?: boolean;
|
|
38
32
|
/**
|
|
39
|
-
*
|
|
33
|
+
* A callback function called when the open state changes.
|
|
40
34
|
*/
|
|
41
|
-
|
|
35
|
+
onOpenChange?: OnChangeFn<boolean>;
|
|
42
36
|
/**
|
|
43
|
-
* Whether the
|
|
37
|
+
* Whether or not the combobox menu should loop through the items when navigating with the keyboard.
|
|
38
|
+
*
|
|
39
|
+
* @defaultValue `false`
|
|
44
40
|
*/
|
|
45
|
-
|
|
41
|
+
loop?: boolean;
|
|
46
42
|
/**
|
|
47
|
-
*
|
|
43
|
+
* How to scroll the combobox items into view when navigating with the keyboard.
|
|
44
|
+
*
|
|
45
|
+
* @defaultValue `"nearest"`
|
|
48
46
|
*/
|
|
49
|
-
|
|
47
|
+
scrollAlignment?: "nearest" | "center";
|
|
50
48
|
/**
|
|
51
49
|
* Whether or not the open state is controlled or not. If `true`, the component will not update
|
|
52
50
|
* the open state internally, instead it will call `onOpenChange` when it would have
|
|
@@ -63,7 +61,69 @@ export type SelectRootPropsWithoutHTML = WithChildren<{
|
|
|
63
61
|
* @defaultValue false
|
|
64
62
|
*/
|
|
65
63
|
controlledValue?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Optionally provide an array of `value` and `label` pairs that will be used to match
|
|
66
|
+
* and trigger selection when the trigger is focused and a key is pressed while the content
|
|
67
|
+
* is closed. It's also used to handle form autofill.
|
|
68
|
+
*
|
|
69
|
+
* By providing this value, you enable selecting a value when the trigger is focused and a key
|
|
70
|
+
* is pressed without the content being open, similar to how a native `<select>` works.
|
|
71
|
+
* For this to work, you must
|
|
72
|
+
*
|
|
73
|
+
* The label is what the user will potentially search for via typeahead, and the value is what
|
|
74
|
+
* is set as the selected value when a typeahead match is found.
|
|
75
|
+
*
|
|
76
|
+
* We can't rely on the individual `Item` components to do this because they may not ever be
|
|
77
|
+
* mounted to do the DOM if using a conditional block with a Svelte transition or certain
|
|
78
|
+
* animation libraries.
|
|
79
|
+
*
|
|
80
|
+
* IMPORTANT: This functionality is only available for single-select listboxes.
|
|
81
|
+
*/
|
|
82
|
+
items?: {
|
|
83
|
+
value: string;
|
|
84
|
+
label: string;
|
|
85
|
+
disabled?: boolean;
|
|
86
|
+
}[];
|
|
66
87
|
}>;
|
|
88
|
+
export type SelectSingleRootPropsWithoutHTML = {
|
|
89
|
+
/**
|
|
90
|
+
* The value of the selected combobox item.
|
|
91
|
+
*
|
|
92
|
+
* @bindable
|
|
93
|
+
*/
|
|
94
|
+
value?: string;
|
|
95
|
+
/**
|
|
96
|
+
* A callback function called when the value changes.
|
|
97
|
+
*/
|
|
98
|
+
onValueChange?: OnChangeFn<string>;
|
|
99
|
+
/**
|
|
100
|
+
* The type of combobox.
|
|
101
|
+
*
|
|
102
|
+
* @required
|
|
103
|
+
*/
|
|
104
|
+
type: "single";
|
|
105
|
+
};
|
|
106
|
+
export type SelectMultipleRootPropsWithoutHTML = {
|
|
107
|
+
/**
|
|
108
|
+
* The value of the selected combobox item.
|
|
109
|
+
*
|
|
110
|
+
* @bindable
|
|
111
|
+
*/
|
|
112
|
+
value?: string[];
|
|
113
|
+
/**
|
|
114
|
+
* A callback function called when the value changes.
|
|
115
|
+
*/
|
|
116
|
+
onValueChange?: OnChangeFn<string[]>;
|
|
117
|
+
/**
|
|
118
|
+
* The type of combobox.
|
|
119
|
+
*
|
|
120
|
+
* @required
|
|
121
|
+
*/
|
|
122
|
+
type: "multiple";
|
|
123
|
+
};
|
|
124
|
+
export type SelectSingleRootProps = SelectBaseRootPropsWithoutHTML & SelectSingleRootPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, SelectSingleRootPropsWithoutHTML | SelectBaseRootPropsWithoutHTML>;
|
|
125
|
+
export type SelectMultipleRootProps = SelectBaseRootPropsWithoutHTML & SelectMultipleRootPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, SelectMultipleRootPropsWithoutHTML | SelectBaseRootPropsWithoutHTML>;
|
|
126
|
+
export type SelectRootPropsWithoutHTML = SelectBaseRootPropsWithoutHTML & (SelectSingleRootPropsWithoutHTML | SelectMultipleRootPropsWithoutHTML);
|
|
67
127
|
export type SelectRootProps = SelectRootPropsWithoutHTML;
|
|
68
128
|
export type _SharedSelectContentProps = {
|
|
69
129
|
/**
|
|
@@ -73,79 +133,68 @@ export type _SharedSelectContentProps = {
|
|
|
73
133
|
*/
|
|
74
134
|
loop?: boolean;
|
|
75
135
|
};
|
|
76
|
-
export type
|
|
136
|
+
export type SelectContentSnippetProps = {
|
|
77
137
|
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* `item-aligned` - behaves similarly to a native MacOS menu by positioning content relative to the active item. <br>
|
|
81
|
-
* `floating (default)` - positions content in the same way as our other primitives, for example `Popover` or `DropdownMenu`.
|
|
138
|
+
* Whether the content is open or closed. Used alongside the `forceMount` prop to conditionally
|
|
139
|
+
* render the content using Svelte transitions.
|
|
82
140
|
*/
|
|
83
|
-
|
|
84
|
-
} & _SharedSelectContentProps>>;
|
|
85
|
-
export type SelectContentImplProps = SelectContentImplPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, SelectContentImplPropsWithoutHTML>;
|
|
86
|
-
export type SelectContentPropsWithoutHTML = SelectContentImplPropsWithoutHTML & {
|
|
87
|
-
/**
|
|
88
|
-
* Whether to force mount the content for use with certain animation libraries.
|
|
89
|
-
*/
|
|
90
|
-
forceMount?: boolean;
|
|
141
|
+
open: boolean;
|
|
91
142
|
};
|
|
143
|
+
export type SelectContentPropsWithoutHTML = Expand<WithChildNoChildrenSnippetProps<Omit<PopperLayerProps, "content" | "onOpenAutoFocus" | "trapFocus"> & _SharedSelectContentProps, SelectContentSnippetProps>>;
|
|
92
144
|
export type SelectContentProps = SelectContentPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, SelectContentPropsWithoutHTML>;
|
|
145
|
+
export type SelectContentStaticPropsWithoutHTML = Expand<WithChildNoChildrenSnippetProps<Omit<PopperLayerStaticProps, "content" | "onOpenAutoFocus" | "trapFocus"> & _SharedSelectContentProps, SelectContentSnippetProps>>;
|
|
146
|
+
export type SelectContentStaticProps = SelectContentStaticPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, SelectContentStaticPropsWithoutHTML>;
|
|
147
|
+
export type SelectTriggerPropsWithoutHTML = WithChild;
|
|
148
|
+
export type SelectTriggerProps = SelectTriggerPropsWithoutHTML & Without<BitsPrimitiveButtonAttributes, SelectTriggerPropsWithoutHTML>;
|
|
93
149
|
export type SelectItemSnippetProps = {
|
|
94
150
|
selected: boolean;
|
|
151
|
+
highlighted: boolean;
|
|
95
152
|
};
|
|
96
153
|
export type SelectItemPropsWithoutHTML = WithChild<{
|
|
97
154
|
/**
|
|
98
155
|
* The value of the item.
|
|
156
|
+
*
|
|
157
|
+
* @required
|
|
99
158
|
*/
|
|
100
159
|
value: string;
|
|
101
160
|
/**
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
* @defaultValue false
|
|
161
|
+
* The label of the item. If provided, this is the item that users will search for.
|
|
162
|
+
* If not provided, the value will be used as the label.
|
|
105
163
|
*/
|
|
106
|
-
|
|
164
|
+
label?: string;
|
|
107
165
|
/**
|
|
108
|
-
*
|
|
166
|
+
* Whether the item is disabled.
|
|
109
167
|
*
|
|
110
|
-
*
|
|
111
|
-
* component. Use this prop if the text content is not suitable for typeahead.
|
|
168
|
+
* @defaultValue `false`
|
|
112
169
|
*/
|
|
113
|
-
|
|
114
|
-
}, SelectItemSnippetProps>;
|
|
115
|
-
export type SelectItemProps = SelectItemPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, SelectItemPropsWithoutHTML>;
|
|
116
|
-
export type SelectTriggerPropsWithoutHTML = WithChild<{
|
|
170
|
+
disabled?: boolean;
|
|
117
171
|
/**
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
172
|
+
* A callback function called when the item is highlighted. This can be used as a
|
|
173
|
+
* replacement for `onfocus` since we don't actually focus the item and instead
|
|
174
|
+
* rely on the `aria-activedescendant` attribute to indicate the highlighted item.
|
|
121
175
|
*/
|
|
122
|
-
|
|
123
|
-
}>;
|
|
124
|
-
export type SelectTriggerProps = SelectTriggerPropsWithoutHTML & Without<BitsPrimitiveButtonAttributes, SelectTriggerPropsWithoutHTML>;
|
|
125
|
-
export type SelectValuePropsWithoutHTML = WithChild<{
|
|
176
|
+
onHighlight?: () => void;
|
|
126
177
|
/**
|
|
127
|
-
*
|
|
178
|
+
* A callback function called when the item is unhighlighted. This can be used as a
|
|
179
|
+
* replacement for `onblur` since we don't actually focus the item and instead
|
|
180
|
+
* rely on the `aria-activedescendant` attribute to indicate the highlighted item.
|
|
128
181
|
*/
|
|
129
|
-
|
|
130
|
-
}>;
|
|
131
|
-
export type
|
|
132
|
-
export type SelectItemTextPropsWithoutHTML = WithChild;
|
|
133
|
-
export type SelectItemTextProps = SelectItemTextPropsWithoutHTML & Without<BitsPrimitiveSpanAttributes, SelectItemTextPropsWithoutHTML>;
|
|
134
|
-
export type SelectViewportPropsWithoutHTML = WithChild;
|
|
135
|
-
export type SelectViewportProps = SelectViewportPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, SelectViewportPropsWithoutHTML>;
|
|
136
|
-
export type SelectPortalPropsWithoutHTML = PortalProps;
|
|
137
|
-
export type SelectPortalProps = SelectPortalPropsWithoutHTML;
|
|
138
|
-
export type SelectScrollUpButtonPropsWithoutHTML = WithChild;
|
|
139
|
-
export type SelectScrollUpButtonProps = SelectScrollUpButtonPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, SelectScrollUpButtonPropsWithoutHTML>;
|
|
140
|
-
export type SelectScrollDownButtonPropsWithoutHTML = WithChild;
|
|
141
|
-
export type SelectScrollDownButtonProps = SelectScrollDownButtonPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, SelectScrollDownButtonPropsWithoutHTML>;
|
|
142
|
-
export type SelectIconPropsWithoutHTML = WithChild;
|
|
143
|
-
export type SelectIconProps = SelectIconPropsWithoutHTML & Without<BitsPrimitiveSpanAttributes, SelectIconPropsWithoutHTML>;
|
|
182
|
+
onUnhighlight?: () => void;
|
|
183
|
+
}, SelectItemSnippetProps>;
|
|
184
|
+
export type SelectItemProps = SelectItemPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, SelectItemPropsWithoutHTML>;
|
|
144
185
|
export type SelectGroupPropsWithoutHTML = WithChild;
|
|
145
186
|
export type SelectGroupProps = SelectGroupPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, SelectGroupPropsWithoutHTML>;
|
|
146
187
|
export type SelectGroupHeadingPropsWithoutHTML = WithChild;
|
|
147
188
|
export type SelectGroupHeadingProps = SelectGroupHeadingPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, SelectGroupHeadingPropsWithoutHTML>;
|
|
148
189
|
export type SelectSeparatorPropsWithoutHTML = WithChild;
|
|
149
190
|
export type SelectSeparatorProps = SelectSeparatorPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, SelectSeparatorPropsWithoutHTML>;
|
|
191
|
+
export type SelectPortalPropsWithoutHTML = PortalProps;
|
|
192
|
+
export type SelectPortalProps = SelectPortalPropsWithoutHTML;
|
|
150
193
|
export type SelectArrowPropsWithoutHTML = ArrowPropsWithoutHTML;
|
|
151
194
|
export type SelectArrowProps = ArrowProps;
|
|
195
|
+
export type SelectViewportPropsWithoutHTML = WithChild;
|
|
196
|
+
export type SelectViewportProps = SelectViewportPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, SelectViewportPropsWithoutHTML>;
|
|
197
|
+
export type SelectScrollUpButtonPropsWithoutHTML = WithChild;
|
|
198
|
+
export type SelectScrollUpButtonProps = SelectScrollUpButtonPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, SelectScrollUpButtonPropsWithoutHTML>;
|
|
199
|
+
export type SelectScrollDownButtonPropsWithoutHTML = WithChild;
|
|
200
|
+
export type SelectScrollDownButtonProps = SelectScrollDownButtonPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, SelectScrollDownButtonPropsWithoutHTML>;
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
ref = $bindable(null),
|
|
13
13
|
value = $bindable([]),
|
|
14
14
|
onValueChange = noop,
|
|
15
|
-
|
|
15
|
+
onValueCommit = noop,
|
|
16
16
|
disabled = false,
|
|
17
17
|
min = 0,
|
|
18
18
|
max = 100,
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
),
|
|
44
|
-
|
|
44
|
+
onValueCommit: box.with(() => onValueCommit),
|
|
45
45
|
disabled: box.with(() => disabled),
|
|
46
46
|
min: box.with(() => min),
|
|
47
47
|
max: box.with(() => max),
|
|
@@ -13,7 +13,7 @@ type SliderRootStateProps = WithRefProps<ReadableBoxedValues<{
|
|
|
13
13
|
step: number;
|
|
14
14
|
dir: Direction;
|
|
15
15
|
autoSort: boolean;
|
|
16
|
-
|
|
16
|
+
onValueCommit: OnChangeFn<number[]>;
|
|
17
17
|
}> & WritableBoxedValues<{
|
|
18
18
|
value: number[];
|
|
19
19
|
}>>;
|
|
@@ -35,7 +35,7 @@ declare class SliderRootState {
|
|
|
35
35
|
isActive: boolean;
|
|
36
36
|
currentThumbIdx: number;
|
|
37
37
|
direction: "rl" | "lr" | "tb" | "bt";
|
|
38
|
-
|
|
38
|
+
onValueCommit: SliderRootStateProps["onValueCommit"];
|
|
39
39
|
constructor(props: SliderRootStateProps);
|
|
40
40
|
applyPosition: ({ clientXY, activeThumbIdx, start, end, }: {
|
|
41
41
|
clientXY: number;
|
|
@@ -38,7 +38,7 @@ class SliderRootState {
|
|
|
38
38
|
return this.dir.current === "rtl" ? "tb" : "bt";
|
|
39
39
|
}
|
|
40
40
|
});
|
|
41
|
-
|
|
41
|
+
onValueCommit;
|
|
42
42
|
constructor(props) {
|
|
43
43
|
this.id = props.id;
|
|
44
44
|
this.ref = props.ref;
|
|
@@ -50,7 +50,7 @@ class SliderRootState {
|
|
|
50
50
|
this.dir = props.dir;
|
|
51
51
|
this.autoSort = props.autoSort;
|
|
52
52
|
this.value = props.value;
|
|
53
|
-
this.
|
|
53
|
+
this.onValueCommit = props.onValueCommit;
|
|
54
54
|
useRefById({
|
|
55
55
|
id: this.id,
|
|
56
56
|
ref: this.ref,
|
|
@@ -187,7 +187,7 @@ class SliderRootState {
|
|
|
187
187
|
};
|
|
188
188
|
handlePointerUp = () => {
|
|
189
189
|
if (this.isActive) {
|
|
190
|
-
this.
|
|
190
|
+
this.onValueCommit.current(untrack(() => this.value.current));
|
|
191
191
|
}
|
|
192
192
|
this.isActive = false;
|
|
193
193
|
};
|
|
@@ -477,7 +477,7 @@ class SliderThumbState {
|
|
|
477
477
|
}
|
|
478
478
|
break;
|
|
479
479
|
}
|
|
480
|
-
this.#root.
|
|
480
|
+
this.#root.onValueCommit.current(this.#root.value.current);
|
|
481
481
|
};
|
|
482
482
|
props = $derived.by(() => ({
|
|
483
483
|
...this.#root.thumbsPropsArr[this.#index.current],
|
|
@@ -17,9 +17,10 @@ export type SliderRootPropsWithoutHTML = WithChild<{
|
|
|
17
17
|
onValueChange?: OnChangeFn<number[]>;
|
|
18
18
|
/**
|
|
19
19
|
* A callback function called when the user stops dragging the thumb,
|
|
20
|
-
* which is useful for knowing when the user has finished interacting with the
|
|
20
|
+
* which is useful for knowing when the user has finished interacting with the
|
|
21
|
+
* slider and _commits_ the value.
|
|
21
22
|
*/
|
|
22
|
-
|
|
23
|
+
onValueCommit?: OnChangeFn<number[]>;
|
|
23
24
|
/**
|
|
24
25
|
* Whether to automatically sort the values in the array when moving thumbs past
|
|
25
26
|
* one another.
|
|
@@ -65,3 +65,26 @@ export declare function forward<T>(array: T[], index: number, increment: number,
|
|
|
65
65
|
* @param loop loop around the array if the target index is out of bounds?
|
|
66
66
|
*/
|
|
67
67
|
export declare function backward<T>(array: T[], index: number, decrement: number, loop?: boolean): T | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* This is the "meat" of the typeahead matching logic. It takes in all the values,
|
|
70
|
+
* the search and the current match, and returns the next match (or `undefined`).
|
|
71
|
+
*
|
|
72
|
+
* We normalize the search because if a user has repeatedly pressed a character,
|
|
73
|
+
* we want the exact same behavior as if we only had that one character
|
|
74
|
+
* (ie. cycle through options starting with that character)
|
|
75
|
+
*
|
|
76
|
+
* We also reorder the values by wrapping the array around the current match.
|
|
77
|
+
* This is so we always look forward from the current match, and picking the first
|
|
78
|
+
* match will always be the correct one.
|
|
79
|
+
*
|
|
80
|
+
* Finally, if the normalized search is exactly one character, we exclude the
|
|
81
|
+
* current match from the values because otherwise it would be the first to match always
|
|
82
|
+
* and focus would never move. This is as opposed to the regular case, where we
|
|
83
|
+
* don't want focus to move if the current match still matches.
|
|
84
|
+
*/
|
|
85
|
+
export declare function getNextMatch(values: string[], search: string, currentMatch?: string): string | undefined;
|
|
86
|
+
/**
|
|
87
|
+
* Wraps an array around itself at a given start index
|
|
88
|
+
* Example: `wrapArray(['a', 'b', 'c', 'd'], 2) === ['c', 'd', 'a', 'b']`
|
|
89
|
+
*/
|
|
90
|
+
export declare function wrapArray<T>(array: T[], startIndex: number): T[];
|
package/dist/internal/arrays.js
CHANGED
|
@@ -168,3 +168,38 @@ export function backward(array, index, decrement, loop = true) {
|
|
|
168
168
|
}
|
|
169
169
|
return array[targetIndex];
|
|
170
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* This is the "meat" of the typeahead matching logic. It takes in all the values,
|
|
173
|
+
* the search and the current match, and returns the next match (or `undefined`).
|
|
174
|
+
*
|
|
175
|
+
* We normalize the search because if a user has repeatedly pressed a character,
|
|
176
|
+
* we want the exact same behavior as if we only had that one character
|
|
177
|
+
* (ie. cycle through options starting with that character)
|
|
178
|
+
*
|
|
179
|
+
* We also reorder the values by wrapping the array around the current match.
|
|
180
|
+
* This is so we always look forward from the current match, and picking the first
|
|
181
|
+
* match will always be the correct one.
|
|
182
|
+
*
|
|
183
|
+
* Finally, if the normalized search is exactly one character, we exclude the
|
|
184
|
+
* current match from the values because otherwise it would be the first to match always
|
|
185
|
+
* and focus would never move. This is as opposed to the regular case, where we
|
|
186
|
+
* don't want focus to move if the current match still matches.
|
|
187
|
+
*/
|
|
188
|
+
export function getNextMatch(values, search, currentMatch) {
|
|
189
|
+
const isRepeated = search.length > 1 && Array.from(search).every((char) => char === search[0]);
|
|
190
|
+
const normalizedSearch = isRepeated ? search[0] : search;
|
|
191
|
+
const currentMatchIndex = currentMatch ? values.indexOf(currentMatch) : -1;
|
|
192
|
+
let wrappedValues = wrapArray(values, Math.max(currentMatchIndex, 0));
|
|
193
|
+
const excludeCurrentMatch = normalizedSearch.length === 1;
|
|
194
|
+
if (excludeCurrentMatch)
|
|
195
|
+
wrappedValues = wrappedValues.filter((v) => v !== currentMatch);
|
|
196
|
+
const nextMatch = wrappedValues.find((value) => value?.toLowerCase().startsWith(normalizedSearch.toLowerCase()));
|
|
197
|
+
return nextMatch !== currentMatch ? nextMatch : undefined;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Wraps an array around itself at a given start index
|
|
201
|
+
* Example: `wrapArray(['a', 'b', 'c', 'd'], 2) === ['c', 'd', 'a', 'b']`
|
|
202
|
+
*/
|
|
203
|
+
export function wrapArray(array, startIndex) {
|
|
204
|
+
return array.map((_, index) => array[(startIndex + index) % array.length]);
|
|
205
|
+
}
|
|
@@ -62,7 +62,12 @@ function createMonth(props) {
|
|
|
62
62
|
if (!startFrom) {
|
|
63
63
|
startFrom = dateObj.add({ months: 1 }).set({ day: 1 });
|
|
64
64
|
}
|
|
65
|
-
|
|
65
|
+
let length = extraDays;
|
|
66
|
+
if (nextMonthDays.length === 0) {
|
|
67
|
+
length = extraDays - 1;
|
|
68
|
+
nextMonthDays.push(startFrom);
|
|
69
|
+
}
|
|
70
|
+
const extraDaysArray = Array.from({ length }, (_, i) => {
|
|
66
71
|
const incr = i + 1;
|
|
67
72
|
return startFrom.add({ days: incr });
|
|
68
73
|
});
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { SvelteMap } from "svelte/reactivity";
|
|
2
2
|
import { afterTick, box } from "svelte-toolbelt";
|
|
3
|
+
import { Previous, watch } from "runed";
|
|
4
|
+
import { untrack } from "svelte";
|
|
3
5
|
import { isBrowser, isIOS } from "./is.js";
|
|
4
6
|
import { addEventListener } from "./events.js";
|
|
5
7
|
import { useId } from "./use-id.js";
|
|
6
8
|
import { createSharedHook } from "./create-shared-hook.svelte.js";
|
|
7
|
-
import { watch } from "./box.svelte.js";
|
|
8
9
|
const useBodyLockStackCount = createSharedHook(() => {
|
|
9
10
|
const map = new SvelteMap();
|
|
10
11
|
const locked = $derived.by(() => {
|
|
@@ -15,6 +16,7 @@ const useBodyLockStackCount = createSharedHook(() => {
|
|
|
15
16
|
}
|
|
16
17
|
return false;
|
|
17
18
|
});
|
|
19
|
+
const prevLocked = new Previous(() => locked);
|
|
18
20
|
let initialBodyStyle = $state({});
|
|
19
21
|
let stopTouchMoveListener = null;
|
|
20
22
|
function resetBodyStyle() {
|
|
@@ -27,43 +29,43 @@ const useBodyLockStackCount = createSharedHook(() => {
|
|
|
27
29
|
document.body.style.overflow = initialBodyStyle.overflow ?? "";
|
|
28
30
|
isIOS && stopTouchMoveListener?.();
|
|
29
31
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
$effect(() => {
|
|
33
|
+
const curr = locked;
|
|
34
|
+
return untrack(() => {
|
|
35
|
+
if (!curr) {
|
|
36
|
+
return;
|
|
34
37
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
document.body.style.overflow = "hidden";
|
|
38
|
+
const bodyStyle = getComputedStyle(document.body);
|
|
39
|
+
initialBodyStyle.overflow = bodyStyle.overflow;
|
|
40
|
+
initialBodyStyle.paddingRight = bodyStyle.paddingRight;
|
|
41
|
+
initialBodyStyle.marginRight = bodyStyle.marginRight;
|
|
42
|
+
initialBodyStyle.pointerEvents = bodyStyle.pointerEvents;
|
|
43
|
+
// TODO: account for RTL direction, etc.
|
|
44
|
+
const verticalScrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
45
|
+
const paddingRight = Number.parseInt(initialBodyStyle.paddingRight ?? "0", 10);
|
|
46
|
+
const config = {
|
|
47
|
+
padding: paddingRight + verticalScrollbarWidth,
|
|
48
|
+
margin: Number.parseInt(initialBodyStyle.marginRight ?? "0", 10),
|
|
49
|
+
};
|
|
50
|
+
if (verticalScrollbarWidth > 0) {
|
|
51
|
+
document.body.style.paddingRight = `${config.padding}px`;
|
|
52
|
+
document.body.style.marginRight = `${config.margin}px`;
|
|
53
|
+
document.body.style.setProperty("--scrollbar-width", `${verticalScrollbarWidth}px`);
|
|
54
|
+
document.body.style.overflow = "hidden";
|
|
55
|
+
}
|
|
56
|
+
if (isIOS) {
|
|
57
|
+
stopTouchMoveListener = addEventListener(document, "touchmove", (e) => {
|
|
58
|
+
if (e.target !== document.documentElement)
|
|
59
|
+
return;
|
|
60
|
+
if (e.touches.length > 1)
|
|
61
|
+
return;
|
|
62
|
+
e.preventDefault();
|
|
63
|
+
}, { passive: false });
|
|
64
|
+
}
|
|
65
|
+
afterTick(() => {
|
|
66
|
+
document.body.style.pointerEvents = "none";
|
|
67
|
+
document.body.style.overflow = "hidden";
|
|
68
|
+
});
|
|
67
69
|
});
|
|
68
70
|
});
|
|
69
71
|
$effect(() => {
|
|
@@ -71,16 +73,25 @@ const useBodyLockStackCount = createSharedHook(() => {
|
|
|
71
73
|
stopTouchMoveListener?.();
|
|
72
74
|
};
|
|
73
75
|
});
|
|
74
|
-
return
|
|
76
|
+
return {
|
|
77
|
+
get map() {
|
|
78
|
+
return map;
|
|
79
|
+
},
|
|
80
|
+
resetBodyStyle,
|
|
81
|
+
};
|
|
75
82
|
});
|
|
76
83
|
export function useBodyScrollLock(initialState) {
|
|
77
84
|
const id = useId();
|
|
78
|
-
const
|
|
79
|
-
map.set(id, initialState ?? false);
|
|
80
|
-
const locked = box.with(() => map.get(id) ?? false, (v) => map.set(id, v));
|
|
85
|
+
const countState = useBodyLockStackCount();
|
|
86
|
+
countState.map.set(id, initialState ?? false);
|
|
87
|
+
const locked = box.with(() => countState.map.get(id) ?? false, (v) => countState.map.set(id, v));
|
|
81
88
|
$effect(() => {
|
|
82
89
|
return () => {
|
|
83
|
-
map.delete(id);
|
|
90
|
+
countState.map.delete(id);
|
|
91
|
+
const length = Array.from(countState.map.values()).length;
|
|
92
|
+
if (length === 0) {
|
|
93
|
+
countState.resetBodyStyle();
|
|
94
|
+
}
|
|
84
95
|
};
|
|
85
96
|
});
|
|
86
97
|
return locked;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type DataTypeahead = ReturnType<typeof useDataTypeahead>;
|
|
2
|
+
type UseDataTypeaheadOpts = {
|
|
3
|
+
onMatch: (value: string) => void;
|
|
4
|
+
getCurrentItem: () => string;
|
|
5
|
+
enabled: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare function useDataTypeahead(opts: UseDataTypeaheadOpts): {
|
|
8
|
+
search: import("svelte-toolbelt").WritableBox<string>;
|
|
9
|
+
handleTypeaheadSearch: (key: string, candidateValues: string[]) => string | undefined;
|
|
10
|
+
resetTypeahead: () => void;
|
|
11
|
+
};
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getNextMatch } from "./arrays.js";
|
|
2
|
+
import { boxAutoReset } from "./box-auto-reset.svelte.js";
|
|
3
|
+
export function useDataTypeahead(opts) {
|
|
4
|
+
// Reset `search` 1 second after it was last updated
|
|
5
|
+
const search = boxAutoReset("", 1000);
|
|
6
|
+
function handleTypeaheadSearch(key, candidateValues) {
|
|
7
|
+
if (!opts.enabled)
|
|
8
|
+
return;
|
|
9
|
+
if (!candidateValues.length)
|
|
10
|
+
return;
|
|
11
|
+
search.current = search.current + key;
|
|
12
|
+
const currentItem = opts.getCurrentItem();
|
|
13
|
+
const currentMatch = candidateValues.find((item) => item === currentItem) ?? "";
|
|
14
|
+
const values = candidateValues.map((item) => item ?? "");
|
|
15
|
+
const nextMatch = getNextMatch(values, search.current, currentMatch);
|
|
16
|
+
const newItem = candidateValues.find((item) => item === nextMatch);
|
|
17
|
+
if (newItem) {
|
|
18
|
+
opts.onMatch(newItem);
|
|
19
|
+
}
|
|
20
|
+
return newItem;
|
|
21
|
+
}
|
|
22
|
+
function resetTypeahead() {
|
|
23
|
+
search.current = "";
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
search,
|
|
27
|
+
handleTypeaheadSearch,
|
|
28
|
+
resetTypeahead,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type DOMTypeahead = ReturnType<typeof useDOMTypeahead>;
|
|
2
|
+
type UseDOMTypeaheadOpts = {
|
|
3
|
+
onMatch?: (item: HTMLElement) => void;
|
|
4
|
+
getCurrentItem?: () => HTMLElement | null;
|
|
5
|
+
};
|
|
6
|
+
export declare function useDOMTypeahead(opts?: UseDOMTypeaheadOpts): {
|
|
7
|
+
search: import("svelte-toolbelt").WritableBox<string>;
|
|
8
|
+
handleTypeaheadSearch: (key: string, candidates: HTMLElement[]) => HTMLElement | undefined;
|
|
9
|
+
resetTypeahead: () => void;
|
|
10
|
+
};
|
|
11
|
+
export {};
|