bits-ui 1.0.0-next.79 → 1.0.0-next.80
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/index.d.ts +1 -0
- package/dist/bits/index.js +1 -0
- package/dist/bits/menu/menu.svelte.d.ts +2 -1
- package/dist/bits/menu/menu.svelte.js +6 -31
- package/dist/bits/range-calendar/range-calendar.svelte.js +51 -56
- package/dist/bits/utilities/is-using-keyboard/is-using-keyboard.svelte.d.ts +13 -0
- package/dist/bits/utilities/is-using-keyboard/is-using-keyboard.svelte.js +51 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/bits/index.d.ts
CHANGED
|
@@ -35,4 +35,5 @@ export { Toggle } from "./toggle/index.js";
|
|
|
35
35
|
export { ToggleGroup } from "./toggle-group/index.js";
|
|
36
36
|
export { Toolbar } from "./toolbar/index.js";
|
|
37
37
|
export { Tooltip } from "./tooltip/index.js";
|
|
38
|
+
export { IsUsingKeyboard } from "./utilities/is-using-keyboard/is-using-keyboard.svelte.js";
|
|
38
39
|
export { default as Portal } from "./utilities/portal/portal.svelte";
|
package/dist/bits/index.js
CHANGED
|
@@ -35,4 +35,5 @@ export { Toggle } from "./toggle/index.js";
|
|
|
35
35
|
export { ToggleGroup } from "./toggle-group/index.js";
|
|
36
36
|
export { Toolbar } from "./toolbar/index.js";
|
|
37
37
|
export { Tooltip } from "./tooltip/index.js";
|
|
38
|
+
export { IsUsingKeyboard } from "./utilities/is-using-keyboard/is-using-keyboard.svelte.js";
|
|
38
39
|
export { default as Portal } from "./utilities/portal/portal.svelte";
|
|
@@ -5,6 +5,7 @@ import { CustomEventDispatcher } from "../../internal/events.js";
|
|
|
5
5
|
import type { AnyFn, BitsFocusEvent, BitsKeyboardEvent, BitsMouseEvent, BitsPointerEvent, WithRefProps } from "../../internal/types.js";
|
|
6
6
|
import { useRovingFocus } from "../../internal/use-roving-focus.svelte.js";
|
|
7
7
|
import type { Direction } from "../../shared/index.js";
|
|
8
|
+
import { IsUsingKeyboard } from "../../index.js";
|
|
8
9
|
export declare const CONTEXT_MENU_TRIGGER_ATTR = "data-context-menu-trigger";
|
|
9
10
|
type MenuVariant = "context-menu" | "dropdown-menu" | "menubar";
|
|
10
11
|
export type MenuRootStateProps = ReadableBoxedValues<{
|
|
@@ -17,7 +18,7 @@ export declare const MenuOpenEvent: CustomEventDispatcher<unknown>;
|
|
|
17
18
|
declare class MenuRootState {
|
|
18
19
|
onClose: MenuRootStateProps["onClose"];
|
|
19
20
|
variant: MenuRootStateProps["variant"];
|
|
20
|
-
isUsingKeyboard:
|
|
21
|
+
isUsingKeyboard: IsUsingKeyboard;
|
|
21
22
|
dir: MenuRootStateProps["dir"];
|
|
22
23
|
constructor(props: MenuRootStateProps);
|
|
23
24
|
getAttr(name: string): string;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { afterTick, box,
|
|
1
|
+
import { afterTick, box, mergeProps, onDestroyEffect, useRefById } from "svelte-toolbelt";
|
|
2
2
|
import { Context, IsFocusWithin, watch } from "runed";
|
|
3
|
-
import { on } from "svelte/events";
|
|
4
3
|
import { FIRST_LAST_KEYS, LAST_KEYS, SELECTION_KEYS, SUB_OPEN_KEYS, getCheckedState, isMouseEvent, } from "./utils.js";
|
|
5
4
|
import { focusFirst } from "../../internal/focus.js";
|
|
6
5
|
import { CustomEventDispatcher } from "../../internal/events.js";
|
|
@@ -10,6 +9,7 @@ import { useRovingFocus } from "../../internal/use-roving-focus.svelte.js";
|
|
|
10
9
|
import { kbd } from "../../internal/kbd.js";
|
|
11
10
|
import { getAriaChecked, getAriaDisabled, getAriaExpanded, getAriaOrientation, getDataDisabled, getDataOpenClosed, } from "../../internal/attrs.js";
|
|
12
11
|
import { isPointerInGraceArea, makeHullFromElements } from "../../internal/polygon.js";
|
|
12
|
+
import { IsUsingKeyboard } from "../../index.js";
|
|
13
13
|
export const CONTEXT_MENU_TRIGGER_ATTR = "data-context-menu-trigger";
|
|
14
14
|
const MenuRootContext = new Context("Menu.Root");
|
|
15
15
|
const MenuMenuContext = new Context("Menu.Root | Menu.Sub");
|
|
@@ -23,37 +23,12 @@ export const MenuOpenEvent = new CustomEventDispatcher("bitsmenuopen", {
|
|
|
23
23
|
class MenuRootState {
|
|
24
24
|
onClose;
|
|
25
25
|
variant;
|
|
26
|
-
isUsingKeyboard =
|
|
26
|
+
isUsingKeyboard = new IsUsingKeyboard();
|
|
27
27
|
dir;
|
|
28
28
|
constructor(props) {
|
|
29
29
|
this.onClose = props.onClose;
|
|
30
30
|
this.dir = props.dir;
|
|
31
31
|
this.variant = props.variant;
|
|
32
|
-
$effect(() => {
|
|
33
|
-
const callbacksToDispose = [];
|
|
34
|
-
const handlePointer = (_) => {
|
|
35
|
-
this.isUsingKeyboard = false;
|
|
36
|
-
};
|
|
37
|
-
const handleKeydown = (_) => {
|
|
38
|
-
this.isUsingKeyboard = true;
|
|
39
|
-
const disposePointerDown = on(document, "pointerdown", handlePointer, {
|
|
40
|
-
capture: true,
|
|
41
|
-
once: true,
|
|
42
|
-
});
|
|
43
|
-
const disposePointerMove = on(document, "pointermove", handlePointer, {
|
|
44
|
-
capture: true,
|
|
45
|
-
once: true,
|
|
46
|
-
});
|
|
47
|
-
callbacksToDispose.push(disposePointerDown, disposePointerMove);
|
|
48
|
-
};
|
|
49
|
-
const disposeKeydown = on(document, "keydown", handleKeydown, {
|
|
50
|
-
capture: true,
|
|
51
|
-
});
|
|
52
|
-
callbacksToDispose.push(disposeKeydown);
|
|
53
|
-
return () => {
|
|
54
|
-
executeCallbacks(callbacksToDispose);
|
|
55
|
-
};
|
|
56
|
-
});
|
|
57
32
|
}
|
|
58
33
|
getAttr(name) {
|
|
59
34
|
return `data-${this.variant.current}-${name}`;
|
|
@@ -140,7 +115,7 @@ class MenuContentState {
|
|
|
140
115
|
return;
|
|
141
116
|
const handler = () => {
|
|
142
117
|
afterTick(() => {
|
|
143
|
-
if (!this.parentMenu.root.isUsingKeyboard)
|
|
118
|
+
if (!this.parentMenu.root.isUsingKeyboard.current)
|
|
144
119
|
return;
|
|
145
120
|
this.rovingFocusGroup.focusFirstCandidate();
|
|
146
121
|
});
|
|
@@ -211,7 +186,7 @@ class MenuContentState {
|
|
|
211
186
|
}
|
|
212
187
|
}
|
|
213
188
|
onfocus(_) {
|
|
214
|
-
if (!this.parentMenu.root.isUsingKeyboard)
|
|
189
|
+
if (!this.parentMenu.root.isUsingKeyboard.current)
|
|
215
190
|
return;
|
|
216
191
|
afterTick(() => this.rovingFocusGroup.focusFirstCandidate());
|
|
217
192
|
}
|
|
@@ -386,7 +361,7 @@ class MenuItemState {
|
|
|
386
361
|
this.#onSelect.current(selectEvent);
|
|
387
362
|
afterTick(() => {
|
|
388
363
|
if (selectEvent.defaultPrevented) {
|
|
389
|
-
this.#item.content.parentMenu.root.isUsingKeyboard = false;
|
|
364
|
+
this.#item.content.parentMenu.root.isUsingKeyboard.current = false;
|
|
390
365
|
return;
|
|
391
366
|
}
|
|
392
367
|
if (this.#closeOnSelect.current) {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { getLocalTimeZone, isSameDay, isSameMonth, isToday, } from "@internationalized/date";
|
|
2
|
-
import { untrack } from "svelte";
|
|
3
2
|
import { useRefById } from "svelte-toolbelt";
|
|
4
|
-
import { Context } from "runed";
|
|
3
|
+
import { Context, watch } from "runed";
|
|
5
4
|
import { CalendarRootContext } from "../calendar/calendar.svelte.js";
|
|
6
5
|
import { useId } from "../../internal/use-id.js";
|
|
7
6
|
import { getAriaDisabled, getAriaSelected, getDataDisabled, getDataSelected, getDataUnavailable, } from "../../internal/attrs.js";
|
|
@@ -119,65 +118,61 @@ export class RangeCalendarRootState {
|
|
|
119
118
|
* Synchronize the start and end values with the `value` in case
|
|
120
119
|
* it is updated externally.
|
|
121
120
|
*/
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
121
|
+
watch(() => this.value.current, (value) => {
|
|
122
|
+
if (value.start && value.end) {
|
|
123
|
+
this.startValue.current = value.start;
|
|
124
|
+
this.endValue.current = value.end;
|
|
125
|
+
}
|
|
126
|
+
else if (value.start) {
|
|
127
|
+
this.startValue.current = value.start;
|
|
128
|
+
this.endValue.current = undefined;
|
|
129
|
+
}
|
|
130
|
+
else if (value.start === undefined && value.end === undefined) {
|
|
131
|
+
this.startValue.current = undefined;
|
|
132
|
+
this.endValue.current = undefined;
|
|
133
|
+
}
|
|
134
134
|
});
|
|
135
135
|
/**
|
|
136
136
|
* Synchronize the placeholder value with the current start value
|
|
137
137
|
*/
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
this.placeholder.current = startValue;
|
|
144
|
-
}
|
|
145
|
-
});
|
|
138
|
+
watch(() => this.value.current, (value) => {
|
|
139
|
+
const startValue = value.start;
|
|
140
|
+
if (startValue && this.placeholder.current !== startValue) {
|
|
141
|
+
this.placeholder.current = startValue;
|
|
142
|
+
}
|
|
146
143
|
});
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}
|
|
180
|
-
});
|
|
144
|
+
watch([() => this.startValue.current, () => this.endValue.current], ([startValue, endValue]) => {
|
|
145
|
+
if (this.value.current &&
|
|
146
|
+
this.value.current.start === startValue &&
|
|
147
|
+
this.value.current.end === endValue) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (startValue && endValue) {
|
|
151
|
+
this.#updateValue((prev) => {
|
|
152
|
+
if (prev.start === startValue && prev.end === endValue) {
|
|
153
|
+
return prev;
|
|
154
|
+
}
|
|
155
|
+
if (isBefore(endValue, startValue)) {
|
|
156
|
+
const start = startValue;
|
|
157
|
+
const end = endValue;
|
|
158
|
+
this.#setStartValue(end);
|
|
159
|
+
this.#setEndValue(start);
|
|
160
|
+
return { start: endValue, end: startValue };
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
return {
|
|
164
|
+
start: startValue,
|
|
165
|
+
end: endValue,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
else if (this.value.current &&
|
|
171
|
+
this.value.current.start &&
|
|
172
|
+
this.value.current.end) {
|
|
173
|
+
this.value.current.start = undefined;
|
|
174
|
+
this.value.current.end = undefined;
|
|
175
|
+
}
|
|
181
176
|
});
|
|
182
177
|
this.shiftFocus = this.shiftFocus.bind(this);
|
|
183
178
|
this.handleCellClick = this.handleCellClick.bind(this);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type AnyFn } from "svelte-toolbelt";
|
|
2
|
+
/**
|
|
3
|
+
* Detects whether the user is currently using the keyboard
|
|
4
|
+
* or not by listening to keyboard and pointer events. Uses shared global
|
|
5
|
+
* state to avoid listener duplication.
|
|
6
|
+
*/
|
|
7
|
+
export declare class IsUsingKeyboard {
|
|
8
|
+
static _refs: number;
|
|
9
|
+
static _cleanup?: AnyFn;
|
|
10
|
+
constructor();
|
|
11
|
+
get current(): boolean;
|
|
12
|
+
set current(value: boolean);
|
|
13
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { executeCallbacks } from "svelte-toolbelt";
|
|
2
|
+
import { on } from "svelte/events";
|
|
3
|
+
// Using global state to avoid multiple listeners.
|
|
4
|
+
let isUsingKeyboard = $state(false);
|
|
5
|
+
/**
|
|
6
|
+
* Detects whether the user is currently using the keyboard
|
|
7
|
+
* or not by listening to keyboard and pointer events. Uses shared global
|
|
8
|
+
* state to avoid listener duplication.
|
|
9
|
+
*/
|
|
10
|
+
export class IsUsingKeyboard {
|
|
11
|
+
static _refs = 0; // Reference counting to avoid multiple listeners.
|
|
12
|
+
static _cleanup;
|
|
13
|
+
constructor() {
|
|
14
|
+
$effect(() => {
|
|
15
|
+
if (IsUsingKeyboard._refs === 0) {
|
|
16
|
+
IsUsingKeyboard._cleanup = $effect.root(() => {
|
|
17
|
+
const callbacksToDispose = [];
|
|
18
|
+
const handlePointer = (_) => {
|
|
19
|
+
isUsingKeyboard = false;
|
|
20
|
+
};
|
|
21
|
+
const handleKeydown = (_) => {
|
|
22
|
+
isUsingKeyboard = true;
|
|
23
|
+
};
|
|
24
|
+
callbacksToDispose.push(on(document, "pointerdown", handlePointer, {
|
|
25
|
+
capture: true,
|
|
26
|
+
}), on(document, "pointermove", handlePointer, {
|
|
27
|
+
capture: true,
|
|
28
|
+
}), on(document, "keydown", handleKeydown, {
|
|
29
|
+
capture: true,
|
|
30
|
+
}));
|
|
31
|
+
// Don't forget to spread and call twice.
|
|
32
|
+
return executeCallbacks(...callbacksToDispose);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
IsUsingKeyboard._refs++;
|
|
36
|
+
return () => {
|
|
37
|
+
IsUsingKeyboard._refs--;
|
|
38
|
+
if (IsUsingKeyboard._refs === 0) {
|
|
39
|
+
isUsingKeyboard = false;
|
|
40
|
+
IsUsingKeyboard._cleanup?.();
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
get current() {
|
|
46
|
+
return isUsingKeyboard;
|
|
47
|
+
}
|
|
48
|
+
set current(value) {
|
|
49
|
+
isUsingKeyboard = value;
|
|
50
|
+
}
|
|
51
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { Accordion, AlertDialog, AspectRatio, Avatar, Button, Calendar, Checkbox, Collapsible, Combobox, Command, ContextMenu, DateField, DatePicker, DateRangeField, DateRangePicker, Dialog, DropdownMenu, Label, LinkPreview, Menubar, NavigationMenu, Pagination, PinInput, Popover, Progress, RadioGroup, RangeCalendar, ScrollArea, Select, Separator, Slider, Switch, Tabs, Toggle, ToggleGroup, Toolbar, Tooltip, Portal, } from "./bits/index.js";
|
|
1
|
+
export { Accordion, AlertDialog, AspectRatio, Avatar, Button, Calendar, Checkbox, Collapsible, Combobox, Command, ContextMenu, DateField, DatePicker, DateRangeField, DateRangePicker, Dialog, DropdownMenu, Label, LinkPreview, Menubar, NavigationMenu, Pagination, PinInput, Popover, Progress, RadioGroup, RangeCalendar, ScrollArea, Select, Separator, Slider, Switch, Tabs, Toggle, ToggleGroup, Toolbar, Tooltip, Portal, IsUsingKeyboard, } from "./bits/index.js";
|
|
2
2
|
export * from "./shared/index.js";
|
|
3
3
|
export type * from "./shared/index.js";
|
|
4
4
|
export * from "./types.js";
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { Accordion, AlertDialog, AspectRatio, Avatar, Button, Calendar, Checkbox, Collapsible, Combobox, Command, ContextMenu, DateField, DatePicker, DateRangeField, DateRangePicker, Dialog, DropdownMenu, Label, LinkPreview, Menubar, NavigationMenu, Pagination, PinInput, Popover, Progress, RadioGroup, RangeCalendar, ScrollArea, Select, Separator, Slider, Switch, Tabs, Toggle, ToggleGroup, Toolbar, Tooltip, Portal, } from "./bits/index.js";
|
|
1
|
+
export { Accordion, AlertDialog, AspectRatio, Avatar, Button, Calendar, Checkbox, Collapsible, Combobox, Command, ContextMenu, DateField, DatePicker, DateRangeField, DateRangePicker, Dialog, DropdownMenu, Label, LinkPreview, Menubar, NavigationMenu, Pagination, PinInput, Popover, Progress, RadioGroup, RangeCalendar, ScrollArea, Select, Separator, Slider, Switch, Tabs, Toggle, ToggleGroup, Toolbar, Tooltip, Portal, IsUsingKeyboard, } from "./bits/index.js";
|
|
2
2
|
export * from "./shared/index.js";
|
|
3
3
|
export * from "./types.js";
|