bits-ui 2.3.1 → 2.4.1
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/alert-dialog/components/alert-dialog-content.svelte +1 -0
- package/dist/bits/calendar/components/calendar.svelte +4 -3
- package/dist/bits/date-field/components/date-field.svelte +4 -3
- package/dist/bits/date-picker/components/date-picker.svelte +4 -3
- package/dist/bits/date-range-field/components/date-range-field.svelte +4 -3
- package/dist/bits/date-range-picker/components/date-range-picker.svelte +4 -3
- package/dist/bits/dialog/components/dialog-content.svelte +1 -0
- package/dist/bits/index.d.ts +1 -0
- package/dist/bits/index.js +1 -0
- package/dist/bits/navigation-menu/components/navigation-menu-content-impl.svelte +1 -0
- package/dist/bits/range-calendar/components/range-calendar.svelte +4 -3
- package/dist/bits/scroll-area/scroll-area.svelte.js +1 -1
- package/dist/bits/select/select.svelte.js +1 -1
- package/dist/bits/slider/slider.svelte.d.ts +2 -1
- package/dist/bits/slider/slider.svelte.js +7 -5
- package/dist/bits/time-field/components/time-field.svelte +4 -3
- package/dist/bits/time-range-field/components/time-range-field.svelte +4 -3
- package/dist/bits/utilities/config/bits-config.d.ts +44 -0
- package/dist/bits/utilities/config/bits-config.js +92 -0
- package/dist/bits/utilities/config/components/bits-config.svelte +14 -0
- package/dist/bits/utilities/config/components/bits-config.svelte.d.ts +4 -0
- package/dist/bits/utilities/config/exports.d.ts +2 -0
- package/dist/bits/utilities/config/exports.js +2 -0
- package/dist/bits/utilities/config/index.d.ts +1 -0
- package/dist/bits/utilities/config/index.js +1 -0
- package/dist/bits/utilities/config/prop-resolvers.d.ts +13 -0
- package/dist/bits/utilities/config/prop-resolvers.js +37 -0
- package/dist/bits/utilities/config/types.d.ts +13 -0
- package/dist/bits/utilities/config/types.js +1 -0
- package/dist/bits/utilities/escape-layer/escape-layer.svelte +2 -0
- package/dist/bits/utilities/escape-layer/types.d.ts +2 -0
- package/dist/bits/utilities/escape-layer/use-escape-layer.svelte.d.ts +5 -1
- package/dist/bits/utilities/escape-layer/use-escape-layer.svelte.js +4 -1
- package/dist/bits/utilities/floating-layer/use-floating-layer.svelte.js +2 -0
- package/dist/bits/utilities/popper-layer/popper-layer-inner.svelte +1 -1
- package/dist/bits/utilities/portal/portal.svelte +21 -21
- package/dist/bits/utilities/portal/types.d.ts +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/floating-svelte/types.d.ts +12 -0
- package/dist/internal/floating-svelte/use-floating.svelte.js +18 -12
- package/dist/internal/use-data-typeahead.svelte.d.ts +1 -1
- package/dist/internal/use-data-typeahead.svelte.js +1 -1
- package/dist/internal/use-grace-area.svelte.js +5 -2
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { watch } from "runed";
|
|
2
3
|
import { box, mergeProps } from "svelte-toolbelt";
|
|
3
4
|
import { type DateValue } from "@internationalized/date";
|
|
4
5
|
import { useCalendarRoot } from "../calendar.svelte.js";
|
|
@@ -6,7 +7,7 @@
|
|
|
6
7
|
import { useId } from "../../../internal/use-id.js";
|
|
7
8
|
import { noop } from "../../../internal/noop.js";
|
|
8
9
|
import { getDefaultDate } from "../../../internal/date-time/utils.js";
|
|
9
|
-
import {
|
|
10
|
+
import { resolveLocaleProp } from "../../utilities/config/prop-resolvers.js";
|
|
10
11
|
|
|
11
12
|
let {
|
|
12
13
|
child,
|
|
@@ -24,7 +25,7 @@
|
|
|
24
25
|
isDateUnavailable = () => false,
|
|
25
26
|
fixedWeeks = false,
|
|
26
27
|
numberOfMonths = 1,
|
|
27
|
-
locale
|
|
28
|
+
locale,
|
|
28
29
|
calendarLabel = "Event",
|
|
29
30
|
disabled = false,
|
|
30
31
|
readonly = false,
|
|
@@ -84,7 +85,7 @@
|
|
|
84
85
|
isDateUnavailable: box.with(() => isDateUnavailable),
|
|
85
86
|
fixedWeeks: box.with(() => fixedWeeks),
|
|
86
87
|
numberOfMonths: box.with(() => numberOfMonths),
|
|
87
|
-
locale:
|
|
88
|
+
locale: resolveLocaleProp(() => locale),
|
|
88
89
|
calendarLabel: box.with(() => calendarLabel),
|
|
89
90
|
readonly: box.with(() => readonly),
|
|
90
91
|
disabled: box.with(() => disabled),
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { watch } from "runed";
|
|
2
3
|
import { box } from "svelte-toolbelt";
|
|
3
4
|
import type { DateValue } from "@internationalized/date";
|
|
4
5
|
import { useDateFieldRoot } from "../date-field.svelte.js";
|
|
5
6
|
import type { DateFieldRootProps } from "../types.js";
|
|
6
7
|
import { noop } from "../../../internal/noop.js";
|
|
7
8
|
import { getDefaultDate } from "../../../internal/date-time/utils.js";
|
|
8
|
-
import {
|
|
9
|
+
import { resolveLocaleProp } from "../../utilities/config/prop-resolvers.js";
|
|
9
10
|
|
|
10
11
|
let {
|
|
11
12
|
disabled = false,
|
|
12
13
|
granularity,
|
|
13
14
|
hideTimeZone = false,
|
|
14
15
|
hourCycle,
|
|
15
|
-
locale
|
|
16
|
+
locale,
|
|
16
17
|
maxValue,
|
|
17
18
|
minValue,
|
|
18
19
|
onPlaceholderChange = noop,
|
|
@@ -73,7 +74,7 @@
|
|
|
73
74
|
granularity: box.with(() => granularity),
|
|
74
75
|
hideTimeZone: box.with(() => hideTimeZone),
|
|
75
76
|
hourCycle: box.with(() => hourCycle),
|
|
76
|
-
locale:
|
|
77
|
+
locale: resolveLocaleProp(() => locale),
|
|
77
78
|
maxValue: box.with(() => maxValue),
|
|
78
79
|
minValue: box.with(() => minValue),
|
|
79
80
|
validate: box.with(() => validate),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
// Date Picker composes the DateField, Popover, and Calendar components
|
|
3
|
+
import { watch } from "runed";
|
|
3
4
|
import { box } from "svelte-toolbelt";
|
|
4
5
|
import type { DateValue } from "@internationalized/date";
|
|
5
6
|
import { useDatePickerRoot } from "../date-picker.svelte.js";
|
|
@@ -9,7 +10,7 @@
|
|
|
9
10
|
import { useDateFieldRoot } from "../../date-field/date-field.svelte.js";
|
|
10
11
|
import { FloatingLayer } from "../../utilities/floating-layer/index.js";
|
|
11
12
|
import { getDefaultDate } from "../../../internal/date-time/utils.js";
|
|
12
|
-
import {
|
|
13
|
+
import { resolveLocaleProp } from "../../utilities/config/prop-resolvers.js";
|
|
13
14
|
|
|
14
15
|
let {
|
|
15
16
|
open = $bindable(false),
|
|
@@ -28,7 +29,7 @@
|
|
|
28
29
|
granularity,
|
|
29
30
|
readonlySegments = [],
|
|
30
31
|
hourCycle,
|
|
31
|
-
locale
|
|
32
|
+
locale,
|
|
32
33
|
hideTimeZone = false,
|
|
33
34
|
required = false,
|
|
34
35
|
calendarLabel = "Event",
|
|
@@ -107,7 +108,7 @@
|
|
|
107
108
|
granularity: box.with(() => granularity),
|
|
108
109
|
readonlySegments: box.with(() => readonlySegments),
|
|
109
110
|
hourCycle: box.with(() => hourCycle),
|
|
110
|
-
locale:
|
|
111
|
+
locale: resolveLocaleProp(() => locale),
|
|
111
112
|
hideTimeZone: box.with(() => hideTimeZone),
|
|
112
113
|
required: box.with(() => required),
|
|
113
114
|
calendarLabel: box.with(() => calendarLabel),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { watch } from "runed";
|
|
2
3
|
import { box, mergeProps } from "svelte-toolbelt";
|
|
3
4
|
import type { DateValue } from "@internationalized/date";
|
|
4
5
|
import { useDateRangeFieldRoot } from "../date-range-field.svelte.js";
|
|
@@ -7,7 +8,7 @@
|
|
|
7
8
|
import { noop } from "../../../internal/noop.js";
|
|
8
9
|
import type { DateRange } from "../../../shared/index.js";
|
|
9
10
|
import { getDefaultDate } from "../../../internal/date-time/utils.js";
|
|
10
|
-
import {
|
|
11
|
+
import { resolveLocaleProp } from "../../utilities/config/prop-resolvers.js";
|
|
11
12
|
|
|
12
13
|
const uid = $props.id();
|
|
13
14
|
|
|
@@ -23,7 +24,7 @@
|
|
|
23
24
|
required = false,
|
|
24
25
|
hourCycle,
|
|
25
26
|
granularity,
|
|
26
|
-
locale
|
|
27
|
+
locale,
|
|
27
28
|
hideTimeZone = false,
|
|
28
29
|
validate = noop,
|
|
29
30
|
onInvalid = noop,
|
|
@@ -89,7 +90,7 @@
|
|
|
89
90
|
required: box.with(() => required),
|
|
90
91
|
hourCycle: box.with(() => hourCycle),
|
|
91
92
|
granularity: box.with(() => granularity),
|
|
92
|
-
locale:
|
|
93
|
+
locale: resolveLocaleProp(() => locale),
|
|
93
94
|
hideTimeZone: box.with(() => hideTimeZone),
|
|
94
95
|
validate: box.with(() => validate),
|
|
95
96
|
maxValue: box.with(() => maxValue),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { watch } from "runed";
|
|
2
3
|
import { box, mergeProps } from "svelte-toolbelt";
|
|
3
4
|
import type { DateValue } from "@internationalized/date";
|
|
4
5
|
import { useDateRangePickerRoot } from "../date-range-picker.svelte.js";
|
|
@@ -10,7 +11,7 @@
|
|
|
10
11
|
import { useId } from "../../../internal/use-id.js";
|
|
11
12
|
import type { DateRange } from "../../../shared/index.js";
|
|
12
13
|
import { getDefaultDate } from "../../../internal/date-time/utils.js";
|
|
13
|
-
import {
|
|
14
|
+
import { resolveLocaleProp } from "../../utilities/config/prop-resolvers.js";
|
|
14
15
|
|
|
15
16
|
let {
|
|
16
17
|
open = $bindable(false),
|
|
@@ -30,7 +31,7 @@
|
|
|
30
31
|
granularity,
|
|
31
32
|
readonlySegments = [],
|
|
32
33
|
hourCycle,
|
|
33
|
-
locale
|
|
34
|
+
locale,
|
|
34
35
|
hideTimeZone = false,
|
|
35
36
|
required = false,
|
|
36
37
|
calendarLabel = "Event",
|
|
@@ -136,7 +137,7 @@
|
|
|
136
137
|
granularity: box.with(() => granularity),
|
|
137
138
|
readonlySegments: box.with(() => readonlySegments),
|
|
138
139
|
hourCycle: box.with(() => hourCycle),
|
|
139
|
-
locale:
|
|
140
|
+
locale: resolveLocaleProp(() => locale),
|
|
140
141
|
hideTimeZone: box.with(() => hideTimeZone),
|
|
141
142
|
required: box.with(() => required),
|
|
142
143
|
calendarLabel: box.with(() => calendarLabel),
|
package/dist/bits/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { Accordion } from "./accordion/index.js";
|
|
|
2
2
|
export { AlertDialog } from "./alert-dialog/index.js";
|
|
3
3
|
export { AspectRatio } from "./aspect-ratio/index.js";
|
|
4
4
|
export { Avatar } from "./avatar/index.js";
|
|
5
|
+
export { BitsConfig, getBitsConfig } from "./utilities/config/index.js";
|
|
5
6
|
export { Button } from "./button/index.js";
|
|
6
7
|
export { Calendar } from "./calendar/index.js";
|
|
7
8
|
export { Checkbox } from "./checkbox/index.js";
|
package/dist/bits/index.js
CHANGED
|
@@ -2,6 +2,7 @@ export { Accordion } from "./accordion/index.js";
|
|
|
2
2
|
export { AlertDialog } from "./alert-dialog/index.js";
|
|
3
3
|
export { AspectRatio } from "./aspect-ratio/index.js";
|
|
4
4
|
export { Avatar } from "./avatar/index.js";
|
|
5
|
+
export { BitsConfig, getBitsConfig } from "./utilities/config/index.js";
|
|
5
6
|
export { Button } from "./button/index.js";
|
|
6
7
|
export { Calendar } from "./calendar/index.js";
|
|
7
8
|
export { Checkbox } from "./checkbox/index.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { watch } from "runed";
|
|
2
3
|
import { box, mergeProps } from "svelte-toolbelt";
|
|
3
4
|
import { type DateValue } from "@internationalized/date";
|
|
4
5
|
import type { RangeCalendarRootProps } from "../types.js";
|
|
@@ -6,7 +7,7 @@
|
|
|
6
7
|
import { noop } from "../../../internal/noop.js";
|
|
7
8
|
import { createId } from "../../../internal/create-id.js";
|
|
8
9
|
import { getDefaultDate } from "../../../internal/date-time/utils.js";
|
|
9
|
-
import {
|
|
10
|
+
import { resolveLocaleProp } from "../../utilities/config/prop-resolvers.js";
|
|
10
11
|
|
|
11
12
|
const uid = $props.id();
|
|
12
13
|
|
|
@@ -26,7 +27,7 @@
|
|
|
26
27
|
isDateUnavailable = () => false,
|
|
27
28
|
fixedWeeks = false,
|
|
28
29
|
numberOfMonths = 1,
|
|
29
|
-
locale
|
|
30
|
+
locale,
|
|
30
31
|
calendarLabel = "Event",
|
|
31
32
|
disabled = false,
|
|
32
33
|
readonly = false,
|
|
@@ -107,7 +108,7 @@
|
|
|
107
108
|
weekStartsOn: box.with(() => weekStartsOn),
|
|
108
109
|
weekdayFormat: box.with(() => weekdayFormat),
|
|
109
110
|
numberOfMonths: box.with(() => numberOfMonths),
|
|
110
|
-
locale:
|
|
111
|
+
locale: resolveLocaleProp(() => locale),
|
|
111
112
|
calendarLabel: box.with(() => calendarLabel),
|
|
112
113
|
fixedWeeks: box.with(() => fixedWeeks),
|
|
113
114
|
disableDaysOutsideMonth: box.with(() => disableDaysOutsideMonth),
|
|
@@ -506,7 +506,7 @@ class ScrollAreaScrollbarSharedState {
|
|
|
506
506
|
if (isScrollbarWheel)
|
|
507
507
|
this.handleWheelScroll(e, maxScrollPos);
|
|
508
508
|
};
|
|
509
|
-
const unsubListener = addEventListener(
|
|
509
|
+
const unsubListener = addEventListener(this.root.domContext.getDocument(), "wheel", handleWheel, {
|
|
510
510
|
passive: false,
|
|
511
511
|
});
|
|
512
512
|
return unsubListener;
|
|
@@ -442,7 +442,7 @@ class SelectTriggerState {
|
|
|
442
442
|
return;
|
|
443
443
|
this.root.opts.value.current = matchedItem.value;
|
|
444
444
|
},
|
|
445
|
-
enabled: !this.root.isMulti && this.root.dataTypeaheadEnabled,
|
|
445
|
+
enabled: () => !this.root.isMulti && this.root.dataTypeaheadEnabled,
|
|
446
446
|
candidateValues: () => (this.root.isMulti ? [] : this.root.candidateLabels),
|
|
447
447
|
getWindow: () => this.root.domContext.getWindow(),
|
|
448
448
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Box, type ReadableBox } from "svelte-toolbelt";
|
|
1
|
+
import { type Box, type ReadableBox, DOMContext } from "svelte-toolbelt";
|
|
2
2
|
import { Context } from "runed";
|
|
3
3
|
import type { ReadableBoxedValues, WritableBoxedValues } from "../../internal/box.svelte.js";
|
|
4
4
|
import type { BitsKeyboardEvent, OnChangeFn, WithRefProps } from "../../internal/types.js";
|
|
@@ -22,6 +22,7 @@ declare class SliderBaseRootState {
|
|
|
22
22
|
isActive: boolean;
|
|
23
23
|
direction: "rl" | "lr" | "tb" | "bt";
|
|
24
24
|
normalizedSteps: number[];
|
|
25
|
+
domContext: DOMContext;
|
|
25
26
|
constructor(opts: SliderBaseRootStateProps);
|
|
26
27
|
isThumbActive(_index: number): boolean;
|
|
27
28
|
getAllThumbs: () => HTMLElement[];
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Abdelrahman (https://github.com/abdel-17)
|
|
4
4
|
*/
|
|
5
5
|
import { untrack } from "svelte";
|
|
6
|
-
import { executeCallbacks, onMountEffect, attachRef, } from "svelte-toolbelt";
|
|
6
|
+
import { executeCallbacks, onMountEffect, attachRef, DOMContext, } from "svelte-toolbelt";
|
|
7
7
|
import { on } from "svelte/events";
|
|
8
8
|
import { Context, watch } from "runed";
|
|
9
9
|
import { getRangeStyles, getThumbStyles, getTickStyles, normalizeSteps, snapValueToCustomSteps, getAdjacentStepValue, getTickLabelStyles, getThumbLabelStyles, } from "./helpers.js";
|
|
@@ -31,8 +31,10 @@ class SliderBaseRootState {
|
|
|
31
31
|
normalizedSteps = $derived.by(() => {
|
|
32
32
|
return normalizeSteps(this.opts.step.current, this.opts.min.current, this.opts.max.current);
|
|
33
33
|
});
|
|
34
|
+
domContext;
|
|
34
35
|
constructor(opts) {
|
|
35
36
|
this.opts = opts;
|
|
37
|
+
this.domContext = new DOMContext(this.opts.ref);
|
|
36
38
|
}
|
|
37
39
|
isThumbActive(_index) {
|
|
38
40
|
return this.isActive;
|
|
@@ -101,7 +103,7 @@ class SliderSingleRootState extends SliderBaseRootState {
|
|
|
101
103
|
super(opts);
|
|
102
104
|
this.opts = opts;
|
|
103
105
|
onMountEffect(() => {
|
|
104
|
-
return executeCallbacks(on(
|
|
106
|
+
return executeCallbacks(on(this.domContext.getDocument(), "pointerdown", this.handlePointerDown), on(this.domContext.getDocument(), "pointerup", this.handlePointerUp), on(this.domContext.getDocument(), "pointermove", this.handlePointerMove), on(this.domContext.getDocument(), "pointerleave", this.handlePointerUp));
|
|
105
107
|
});
|
|
106
108
|
watch([
|
|
107
109
|
() => this.opts.step.current,
|
|
@@ -191,7 +193,7 @@ class SliderSingleRootState extends SliderBaseRootState {
|
|
|
191
193
|
const closestThumb = this.getAllThumbs()[0];
|
|
192
194
|
if (!closestThumb || !sliderNode)
|
|
193
195
|
return;
|
|
194
|
-
const target = e.target;
|
|
196
|
+
const target = e.composedPath()[0] ?? e.target;
|
|
195
197
|
if (!isElementOrSVGElement(target) || !sliderNode.contains(target))
|
|
196
198
|
return;
|
|
197
199
|
e.preventDefault();
|
|
@@ -286,7 +288,7 @@ class SliderMultiRootState extends SliderBaseRootState {
|
|
|
286
288
|
super(opts);
|
|
287
289
|
this.opts = opts;
|
|
288
290
|
onMountEffect(() => {
|
|
289
|
-
return executeCallbacks(on(
|
|
291
|
+
return executeCallbacks(on(this.domContext.getDocument(), "pointerdown", this.handlePointerDown), on(this.domContext.getDocument(), "pointerup", this.handlePointerUp), on(this.domContext.getDocument(), "pointermove", this.handlePointerMove), on(this.domContext.getDocument(), "pointerleave", this.handlePointerUp));
|
|
290
292
|
});
|
|
291
293
|
watch([
|
|
292
294
|
() => this.opts.step.current,
|
|
@@ -405,7 +407,7 @@ class SliderMultiRootState extends SliderBaseRootState {
|
|
|
405
407
|
const closestThumb = this.#getClosestThumb(e);
|
|
406
408
|
if (!closestThumb || !sliderNode)
|
|
407
409
|
return;
|
|
408
|
-
const target = e.target;
|
|
410
|
+
const target = e.composedPath()[0] ?? e.target;
|
|
409
411
|
if (!isElementOrSVGElement(target) || !sliderNode.contains(target))
|
|
410
412
|
return;
|
|
411
413
|
e.preventDefault();
|
|
@@ -5,19 +5,20 @@
|
|
|
5
5
|
</script>
|
|
6
6
|
|
|
7
7
|
<script lang="ts" generics="T extends TimeValue = Time">
|
|
8
|
+
import { watch } from "runed";
|
|
8
9
|
import { box } from "svelte-toolbelt";
|
|
9
10
|
import { useTimeFieldRoot } from "../time-field.svelte.js";
|
|
10
11
|
import type { TimeFieldRootProps } from "../types.js";
|
|
11
12
|
import { noop } from "../../../internal/noop.js";
|
|
12
13
|
import { getDefaultTime } from "../../../internal/date-time/utils.js";
|
|
13
|
-
import {
|
|
14
|
+
import { resolveLocaleProp } from "../../utilities/config/prop-resolvers.js";
|
|
14
15
|
|
|
15
16
|
let {
|
|
16
17
|
disabled = false,
|
|
17
18
|
granularity,
|
|
18
19
|
hideTimeZone = false,
|
|
19
20
|
hourCycle,
|
|
20
|
-
locale
|
|
21
|
+
locale,
|
|
21
22
|
maxValue,
|
|
22
23
|
minValue,
|
|
23
24
|
onPlaceholderChange = noop,
|
|
@@ -78,7 +79,7 @@
|
|
|
78
79
|
granularity: box.with(() => granularity),
|
|
79
80
|
hideTimeZone: box.with(() => hideTimeZone),
|
|
80
81
|
hourCycle: box.with(() => hourCycle),
|
|
81
|
-
locale:
|
|
82
|
+
locale: resolveLocaleProp(() => locale),
|
|
82
83
|
maxValue: box.with(() => maxValue),
|
|
83
84
|
minValue: box.with(() => minValue),
|
|
84
85
|
validate: box.with(() => validate),
|
|
@@ -6,13 +6,14 @@
|
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
8
|
<script lang="ts" generics="T extends TimeValue = Time">
|
|
9
|
+
import { watch } from "runed";
|
|
9
10
|
import { box, mergeProps } from "svelte-toolbelt";
|
|
10
11
|
import { useTimeRangeFieldRoot } from "../time-range-field.svelte.js";
|
|
11
12
|
import type { TimeRangeFieldRootProps } from "../types.js";
|
|
12
13
|
import { createId } from "../../../internal/create-id.js";
|
|
13
14
|
import { noop } from "../../../internal/noop.js";
|
|
14
15
|
import { getDefaultTime } from "../../../internal/date-time/utils.js";
|
|
15
|
-
import {
|
|
16
|
+
import { resolveLocaleProp } from "../../utilities/config/prop-resolvers.js";
|
|
16
17
|
|
|
17
18
|
const uid = $props.id();
|
|
18
19
|
|
|
@@ -28,7 +29,7 @@
|
|
|
28
29
|
required = false,
|
|
29
30
|
hourCycle,
|
|
30
31
|
granularity,
|
|
31
|
-
locale
|
|
32
|
+
locale,
|
|
32
33
|
hideTimeZone = false,
|
|
33
34
|
validate = noop,
|
|
34
35
|
onInvalid = noop,
|
|
@@ -94,7 +95,7 @@
|
|
|
94
95
|
required: box.with(() => required),
|
|
95
96
|
hourCycle: box.with(() => hourCycle),
|
|
96
97
|
granularity: box.with(() => granularity),
|
|
97
|
-
locale:
|
|
98
|
+
locale: resolveLocaleProp(() => locale),
|
|
98
99
|
hideTimeZone: box.with(() => hideTimeZone),
|
|
99
100
|
validate: box.with(() => validate),
|
|
100
101
|
maxValue: box.with(() => maxValue),
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Context } from "runed";
|
|
2
|
+
import type { ReadableBoxedValues } from "../../../internal/box.svelte.js";
|
|
3
|
+
import type { BitsConfigPropsWithoutChildren } from "./types.js";
|
|
4
|
+
type BitsConfigStateProps = ReadableBoxedValues<BitsConfigPropsWithoutChildren>;
|
|
5
|
+
export declare const BitsConfigContext: Context<BitsConfigState>;
|
|
6
|
+
/**
|
|
7
|
+
* Gets the current Bits UI configuration state from the context.
|
|
8
|
+
*
|
|
9
|
+
* Returns a default configuration (where all values are `undefined`) if no configuration is found.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getBitsConfig(): Required<ReadableBoxedValues<BitsConfigPropsWithoutChildren>>;
|
|
12
|
+
/**
|
|
13
|
+
* Creates and sets a new Bits UI configuration state that inherits from parent configs.
|
|
14
|
+
*
|
|
15
|
+
* @param opts - Configuration options for this level
|
|
16
|
+
* @returns The configuration state instance
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* // In a component that wants to set a default portal target
|
|
21
|
+
* const config = useBitsConfig({ defaultPortalTo: box("#some-element") });
|
|
22
|
+
*
|
|
23
|
+
* // Child components will inherit this config and can override specific values
|
|
24
|
+
* const childConfig = useBitsConfig({ someOtherProp: box("value") });
|
|
25
|
+
* // childConfig still has defaultPortalTo="#some-element" from parent
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function useBitsConfig(opts: BitsConfigStateProps): BitsConfigState;
|
|
29
|
+
/**
|
|
30
|
+
* Configuration state that inherits from parent configurations.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* Config resolution:
|
|
34
|
+
* ```
|
|
35
|
+
* Level 1: { defaultPortalTo: "#some-element", theme: "dark" }
|
|
36
|
+
* Level 2: { spacing: "large" } // inherits defaultPortalTo="#some-element", theme="dark"
|
|
37
|
+
* Level 3: { theme: "light" } // inherits defaultPortalTo="#some-element", spacing="large", overrides theme="light"
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare class BitsConfigState {
|
|
41
|
+
readonly opts: Required<BitsConfigStateProps>;
|
|
42
|
+
constructor(parent: BitsConfigState | null, opts: BitsConfigStateProps);
|
|
43
|
+
}
|
|
44
|
+
export {};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Context } from "runed";
|
|
2
|
+
import { box } from "svelte-toolbelt";
|
|
3
|
+
export const BitsConfigContext = new Context("BitsConfig");
|
|
4
|
+
/**
|
|
5
|
+
* Gets the current Bits UI configuration state from the context.
|
|
6
|
+
*
|
|
7
|
+
* Returns a default configuration (where all values are `undefined`) if no configuration is found.
|
|
8
|
+
*/
|
|
9
|
+
export function getBitsConfig() {
|
|
10
|
+
const fallback = new BitsConfigState(null, {});
|
|
11
|
+
return BitsConfigContext.getOr(fallback).opts;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Creates and sets a new Bits UI configuration state that inherits from parent configs.
|
|
15
|
+
*
|
|
16
|
+
* @param opts - Configuration options for this level
|
|
17
|
+
* @returns The configuration state instance
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* // In a component that wants to set a default portal target
|
|
22
|
+
* const config = useBitsConfig({ defaultPortalTo: box("#some-element") });
|
|
23
|
+
*
|
|
24
|
+
* // Child components will inherit this config and can override specific values
|
|
25
|
+
* const childConfig = useBitsConfig({ someOtherProp: box("value") });
|
|
26
|
+
* // childConfig still has defaultPortalTo="#some-element" from parent
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export function useBitsConfig(opts) {
|
|
30
|
+
return BitsConfigContext.set(new BitsConfigState(BitsConfigContext.getOr(null), opts));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Configuration state that inherits from parent configurations.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* Config resolution:
|
|
37
|
+
* ```
|
|
38
|
+
* Level 1: { defaultPortalTo: "#some-element", theme: "dark" }
|
|
39
|
+
* Level 2: { spacing: "large" } // inherits defaultPortalTo="#some-element", theme="dark"
|
|
40
|
+
* Level 3: { theme: "light" } // inherits defaultPortalTo="#some-element", spacing="large", overrides theme="light"
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export class BitsConfigState {
|
|
44
|
+
opts;
|
|
45
|
+
constructor(parent, opts) {
|
|
46
|
+
const resolveConfigOption = createConfigResolver(parent, opts);
|
|
47
|
+
this.opts = {
|
|
48
|
+
defaultPortalTo: resolveConfigOption((config) => config.defaultPortalTo),
|
|
49
|
+
defaultLocale: resolveConfigOption((config) => config.defaultLocale),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Returns a config resolver that resolves a given config option's value.
|
|
55
|
+
*
|
|
56
|
+
* The resolver creates reactive boxes that resolve config option values using this priority:
|
|
57
|
+
* 1. Current level's value (if defined)
|
|
58
|
+
* 2. Parent level's value (if defined and current is undefined)
|
|
59
|
+
* 3. `undefined` (if no value is found in either parent or child)
|
|
60
|
+
*
|
|
61
|
+
* @param parent - Parent configuration state (null if this is root level)
|
|
62
|
+
* @param currentOpts - Current level's configuration options
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* // Given this hierarchy:
|
|
67
|
+
* // Root: { defaultPortalTo: "#some-element" }
|
|
68
|
+
* // Child: { someOtherProp: "value" } // no defaultPortalTo specified
|
|
69
|
+
*
|
|
70
|
+
* const resolveConfigOption = createConfigResolver(parent, opts);
|
|
71
|
+
* const portalTo = resolveConfigOption(config => config.defaultPortalTo);
|
|
72
|
+
*
|
|
73
|
+
* // portalTo.current === "#some-element" (inherited from parent)
|
|
74
|
+
* // even when child didn't specify `defaultPortalTo`
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
function createConfigResolver(parent, currentOpts) {
|
|
78
|
+
return (getter) => {
|
|
79
|
+
const configOption = box.with(() => {
|
|
80
|
+
// try current opts first
|
|
81
|
+
const value = getter(currentOpts)?.current;
|
|
82
|
+
if (value !== undefined)
|
|
83
|
+
return value;
|
|
84
|
+
// if no parent, return undefined
|
|
85
|
+
if (parent === null)
|
|
86
|
+
return undefined;
|
|
87
|
+
// get value from parent (which already has its own chain resolved)
|
|
88
|
+
return getter(parent.opts)?.current;
|
|
89
|
+
});
|
|
90
|
+
return configOption;
|
|
91
|
+
};
|
|
92
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { BitsConfigProps } from "../types.js";
|
|
3
|
+
import { useBitsConfig } from "../bits-config.js";
|
|
4
|
+
import { box } from "svelte-toolbelt";
|
|
5
|
+
|
|
6
|
+
let { children, defaultPortalTo, defaultLocale }: BitsConfigProps = $props();
|
|
7
|
+
|
|
8
|
+
useBitsConfig({
|
|
9
|
+
defaultPortalTo: box.with(() => defaultPortalTo),
|
|
10
|
+
defaultLocale: box.with(() => defaultLocale),
|
|
11
|
+
});
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
{@render children?.()}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./exports.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./exports.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Getter, type ReadableBox } from "svelte-toolbelt";
|
|
2
|
+
/**
|
|
3
|
+
* Resolves a locale value using the prop, the config default, or a fallback.
|
|
4
|
+
*
|
|
5
|
+
* Default value: `"en"`
|
|
6
|
+
*/
|
|
7
|
+
export declare const resolveLocaleProp: (getProp: Getter<string | undefined>) => ReadableBox<string>;
|
|
8
|
+
/**
|
|
9
|
+
* Resolves a portal's `to` value using the prop, the config default, or a fallback.
|
|
10
|
+
*
|
|
11
|
+
* Default value: `"body"`
|
|
12
|
+
*/
|
|
13
|
+
export declare const resolvePortalToProp: (getProp: Getter<string | Element | undefined>) => ReadableBox<string | Element>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { box } from "svelte-toolbelt";
|
|
2
|
+
import { getBitsConfig } from "./bits-config.js";
|
|
3
|
+
/**
|
|
4
|
+
* Creates a generic prop resolver that follows a standard priority chain:
|
|
5
|
+
* 1. The getter's prop value (if defined)
|
|
6
|
+
* 2. The config default value (if no getter prop value is defined)
|
|
7
|
+
* 3. The fallback value (if no config value found)
|
|
8
|
+
*/
|
|
9
|
+
function createPropResolver(configOption, fallback) {
|
|
10
|
+
return (getProp) => {
|
|
11
|
+
const config = getBitsConfig();
|
|
12
|
+
return box.with(() => {
|
|
13
|
+
// 1. return the prop's value, if provided
|
|
14
|
+
const propValue = getProp();
|
|
15
|
+
if (propValue !== undefined)
|
|
16
|
+
return propValue;
|
|
17
|
+
// 2. return the resolved config option value, if available
|
|
18
|
+
const option = configOption(config).current;
|
|
19
|
+
if (option !== undefined)
|
|
20
|
+
return option;
|
|
21
|
+
// 3. return the fallback if no other value is found
|
|
22
|
+
return fallback;
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Resolves a locale value using the prop, the config default, or a fallback.
|
|
28
|
+
*
|
|
29
|
+
* Default value: `"en"`
|
|
30
|
+
*/
|
|
31
|
+
export const resolveLocaleProp = createPropResolver((config) => config.defaultLocale, "en");
|
|
32
|
+
/**
|
|
33
|
+
* Resolves a portal's `to` value using the prop, the config default, or a fallback.
|
|
34
|
+
*
|
|
35
|
+
* Default value: `"body"`
|
|
36
|
+
*/
|
|
37
|
+
export const resolvePortalToProp = createPropResolver((config) => config.defaultPortalTo, "body");
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { WithChildren } from "../../../internal/types.js";
|
|
2
|
+
import type { PortalTarget } from "../portal/types.js";
|
|
3
|
+
export type BitsConfigPropsWithoutChildren = {
|
|
4
|
+
/**
|
|
5
|
+
* The default portal `to`/target to use for the `Portal` components throughout the app.
|
|
6
|
+
*/
|
|
7
|
+
defaultPortalTo?: PortalTarget;
|
|
8
|
+
/**
|
|
9
|
+
* The default locale to use for the components that support localization.
|
|
10
|
+
*/
|
|
11
|
+
defaultLocale?: string;
|
|
12
|
+
};
|
|
13
|
+
export type BitsConfigProps = WithChildren<BitsConfigPropsWithoutChildren>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -9,12 +9,14 @@
|
|
|
9
9
|
onEscapeKeydown = noop,
|
|
10
10
|
children,
|
|
11
11
|
enabled,
|
|
12
|
+
ref,
|
|
12
13
|
}: EscapeLayerImplProps = $props();
|
|
13
14
|
|
|
14
15
|
useEscapeLayer({
|
|
15
16
|
escapeKeydownBehavior: box.with(() => escapeKeydownBehavior),
|
|
16
17
|
onEscapeKeydown: box.with(() => onEscapeKeydown),
|
|
17
18
|
enabled: box.with(() => enabled),
|
|
19
|
+
ref,
|
|
18
20
|
});
|
|
19
21
|
</script>
|
|
20
22
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Snippet } from "svelte";
|
|
2
|
+
import type { Box } from "svelte-toolbelt";
|
|
2
3
|
export type EscapeBehaviorType = "close" | "defer-otherwise-close" | "defer-otherwise-ignore" | "ignore";
|
|
3
4
|
export type EscapeLayerProps = {
|
|
4
5
|
/**
|
|
@@ -24,4 +25,5 @@ export type EscapeLayerImplProps = {
|
|
|
24
25
|
*/
|
|
25
26
|
enabled: boolean;
|
|
26
27
|
children?: Snippet;
|
|
28
|
+
ref: Box<HTMLElement | null>;
|
|
27
29
|
} & EscapeLayerProps;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import { DOMContext, type Box } from "svelte-toolbelt";
|
|
1
2
|
import type { EscapeLayerImplProps } from "./types.js";
|
|
2
3
|
import type { ReadableBoxedValues } from "../../../internal/box.svelte.js";
|
|
3
|
-
type EscapeLayerStateProps = ReadableBoxedValues<Required<Omit<EscapeLayerImplProps, "children"
|
|
4
|
+
type EscapeLayerStateProps = ReadableBoxedValues<Required<Omit<EscapeLayerImplProps, "children" | "ref">>> & {
|
|
5
|
+
ref: Box<HTMLElement | null>;
|
|
6
|
+
};
|
|
4
7
|
export declare class EscapeLayerState {
|
|
5
8
|
#private;
|
|
6
9
|
readonly opts: EscapeLayerStateProps;
|
|
10
|
+
readonly domContext: DOMContext;
|
|
7
11
|
constructor(opts: EscapeLayerStateProps);
|
|
8
12
|
}
|
|
9
13
|
export declare function useEscapeLayer(props: EscapeLayerStateProps): EscapeLayerState;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DOMContext } from "svelte-toolbelt";
|
|
1
2
|
import { watch } from "runed";
|
|
2
3
|
import { on } from "svelte/events";
|
|
3
4
|
import { kbd } from "../../../internal/kbd.js";
|
|
@@ -5,8 +6,10 @@ import { noop } from "../../../internal/noop.js";
|
|
|
5
6
|
globalThis.bitsEscapeLayers ??= new Map();
|
|
6
7
|
export class EscapeLayerState {
|
|
7
8
|
opts;
|
|
9
|
+
domContext;
|
|
8
10
|
constructor(opts) {
|
|
9
11
|
this.opts = opts;
|
|
12
|
+
this.domContext = new DOMContext(this.opts.ref);
|
|
10
13
|
let unsubEvents = noop;
|
|
11
14
|
watch(() => opts.enabled.current, (enabled) => {
|
|
12
15
|
if (enabled) {
|
|
@@ -20,7 +23,7 @@ export class EscapeLayerState {
|
|
|
20
23
|
});
|
|
21
24
|
}
|
|
22
25
|
#addEventListener = () => {
|
|
23
|
-
return on(
|
|
26
|
+
return on(this.domContext.getDocument(), "keydown", this.#onkeydown, { passive: false });
|
|
24
27
|
};
|
|
25
28
|
#onkeydown = (e) => {
|
|
26
29
|
if (e.key !== kbd.ESCAPE || !isResponsibleEscapeLayer(this))
|
|
@@ -183,6 +183,8 @@ class FloatingContentState {
|
|
|
183
183
|
return cleanup;
|
|
184
184
|
},
|
|
185
185
|
open: () => this.opts.enabled.current,
|
|
186
|
+
sideOffset: () => this.opts.sideOffset.current,
|
|
187
|
+
alignOffset: () => this.opts.alignOffset.current,
|
|
186
188
|
});
|
|
187
189
|
$effect(() => {
|
|
188
190
|
if (!this.floating.isPositioned)
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
{ref}
|
|
92
92
|
>
|
|
93
93
|
{#snippet focusScope({ props: focusScopeProps })}
|
|
94
|
-
<EscapeLayer {onEscapeKeydown} {escapeKeydownBehavior} {enabled}>
|
|
94
|
+
<EscapeLayer {onEscapeKeydown} {escapeKeydownBehavior} {enabled} {ref}>
|
|
95
95
|
<DismissibleLayer
|
|
96
96
|
{id}
|
|
97
97
|
{onInteractOutside}
|
|
@@ -5,40 +5,41 @@
|
|
|
5
5
|
import PortalConsumer from "./portal-consumer.svelte";
|
|
6
6
|
import type { PortalProps } from "./types.js";
|
|
7
7
|
import { isBrowser } from "../../../internal/is.js";
|
|
8
|
+
import { resolvePortalToProp } from "../config/prop-resolvers.js";
|
|
8
9
|
|
|
9
|
-
let { to
|
|
10
|
+
let { to: toProp, children, disabled }: PortalProps = $props();
|
|
10
11
|
|
|
12
|
+
const to = resolvePortalToProp(() => toProp);
|
|
11
13
|
const context = getAllContexts();
|
|
12
14
|
|
|
13
15
|
let target = $derived(getTarget());
|
|
14
16
|
|
|
15
17
|
function getTarget() {
|
|
16
18
|
if (!isBrowser || disabled) return null;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
19
|
+
|
|
20
|
+
let localTarget: Element | null = null;
|
|
21
|
+
|
|
22
|
+
if (typeof to.current === "string") {
|
|
23
|
+
const target = document.querySelector(to.current);
|
|
24
|
+
if (DEV && target === null) {
|
|
25
|
+
throw new Error(`Target element "${to.current}" not found.`);
|
|
24
26
|
}
|
|
25
|
-
|
|
26
|
-
localTarget = to;
|
|
27
|
+
localTarget = target;
|
|
27
28
|
} else {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
localTarget = to.current;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (DEV && !(localTarget instanceof Element)) {
|
|
33
|
+
const type = localTarget === null ? "null" : typeof localTarget;
|
|
34
|
+
throw new TypeError(
|
|
35
|
+
`Unknown portal target type: ${type}. Allowed types: string (query selector) or Element.`
|
|
36
|
+
);
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
return localTarget;
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
let instance: any;
|
|
42
|
+
let instance: ReturnType<typeof mount> | null;
|
|
42
43
|
|
|
43
44
|
function unmountInstance() {
|
|
44
45
|
if (instance) {
|
|
@@ -53,8 +54,7 @@
|
|
|
53
54
|
return;
|
|
54
55
|
}
|
|
55
56
|
instance = mount(PortalConsumer, {
|
|
56
|
-
|
|
57
|
-
target: target as any,
|
|
57
|
+
target: target,
|
|
58
58
|
props: { children },
|
|
59
59
|
context,
|
|
60
60
|
});
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { Snippet } from "svelte";
|
|
2
|
+
export type PortalTarget = Element | string;
|
|
2
3
|
export type PortalProps = {
|
|
3
4
|
/**
|
|
4
5
|
* Where to portal the content to.
|
|
5
6
|
*
|
|
6
7
|
* @default document.body
|
|
7
8
|
*/
|
|
8
|
-
to?:
|
|
9
|
+
to?: PortalTarget;
|
|
9
10
|
/**
|
|
10
11
|
* Disable portalling and render the component inline
|
|
11
12
|
*
|
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, Meter, NavigationMenu, Pagination, PinInput, Popover, Progress, RadioGroup, RangeCalendar, RatingGroup as unstable_RatingGroup, ScrollArea, Select, Separator, Slider, Switch, Tabs, TimeField, TimeRangeField, Toggle, ToggleGroup, Toolbar, Tooltip, Portal, IsUsingKeyboard, computeCommandScore, } from "./bits/index.js";
|
|
1
|
+
export { Accordion, AlertDialog, AspectRatio, Avatar, BitsConfig, Button, Calendar, Checkbox, Collapsible, Combobox, Command, ContextMenu, DateField, DatePicker, DateRangeField, DateRangePicker, Dialog, DropdownMenu, Label, LinkPreview, Menubar, Meter, NavigationMenu, Pagination, PinInput, Popover, Progress, RadioGroup, RangeCalendar, RatingGroup as unstable_RatingGroup, ScrollArea, Select, Separator, Slider, Switch, Tabs, TimeField, TimeRangeField, Toggle, ToggleGroup, Toolbar, Tooltip, Portal, IsUsingKeyboard, computeCommandScore, getBitsConfig, } 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, Meter, NavigationMenu, Pagination, PinInput, Popover, Progress, RadioGroup, RangeCalendar, RatingGroup as unstable_RatingGroup, ScrollArea, Select, Separator, Slider, Switch, Tabs, TimeField, TimeRangeField, Toggle, ToggleGroup, Toolbar, Tooltip, Portal, IsUsingKeyboard, computeCommandScore, } from "./bits/index.js";
|
|
1
|
+
export { Accordion, AlertDialog, AspectRatio, Avatar, BitsConfig, Button, Calendar, Checkbox, Collapsible, Combobox, Command, ContextMenu, DateField, DatePicker, DateRangeField, DateRangePicker, Dialog, DropdownMenu, Label, LinkPreview, Menubar, Meter, NavigationMenu, Pagination, PinInput, Popover, Progress, RadioGroup, RangeCalendar, RatingGroup as unstable_RatingGroup, ScrollArea, Select, Separator, Slider, Switch, Tabs, TimeField, TimeRangeField, Toggle, ToggleGroup, Toolbar, Tooltip, Portal, IsUsingKeyboard, computeCommandScore, getBitsConfig, } from "./bits/index.js";
|
|
2
2
|
export * from "./shared/index.js";
|
|
3
3
|
export * from "./types.js";
|
|
@@ -41,6 +41,18 @@ export type UseFloatingOptions = {
|
|
|
41
41
|
* @default undefined
|
|
42
42
|
*/
|
|
43
43
|
whileElementsMounted?: (reference: ReferenceElement, floating: FloatingElement, update: () => void) => () => void;
|
|
44
|
+
/**
|
|
45
|
+
* The offset from the reference element along the side axis.
|
|
46
|
+
* Used to detect bad coordinates during transitions.
|
|
47
|
+
* @default undefined
|
|
48
|
+
*/
|
|
49
|
+
sideOffset?: ValueOrGetValue<number | undefined>;
|
|
50
|
+
/**
|
|
51
|
+
* The offset from the reference element along the alignment axis.
|
|
52
|
+
* Used to detect bad coordinates during transitions.
|
|
53
|
+
* @default undefined
|
|
54
|
+
*/
|
|
55
|
+
alignOffset?: ValueOrGetValue<number | undefined>;
|
|
44
56
|
};
|
|
45
57
|
export type UseFloatingReturn = {
|
|
46
58
|
/**
|
|
@@ -9,6 +9,8 @@ export function useFloating(options) {
|
|
|
9
9
|
const transformOption = $derived(get(options.transform) ?? true);
|
|
10
10
|
const placementOption = $derived(get(options.placement) ?? "bottom");
|
|
11
11
|
const strategyOption = $derived(get(options.strategy) ?? "absolute");
|
|
12
|
+
const sideOffsetOption = $derived(get(options.sideOffset) ?? 0);
|
|
13
|
+
const alignOffsetOption = $derived(get(options.alignOffset) ?? 0);
|
|
12
14
|
const reference = options.reference;
|
|
13
15
|
/** State */
|
|
14
16
|
let x = $state(0);
|
|
@@ -19,21 +21,17 @@ export function useFloating(options) {
|
|
|
19
21
|
let middlewareData = $state({});
|
|
20
22
|
let isPositioned = $state(false);
|
|
21
23
|
const floatingStyles = $derived.by(() => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
top: "0",
|
|
26
|
-
};
|
|
27
|
-
if (!floating.current) {
|
|
28
|
-
return initialStyles;
|
|
29
|
-
}
|
|
30
|
-
const xVal = roundByDPR(floating.current, x);
|
|
31
|
-
const yVal = roundByDPR(floating.current, y);
|
|
24
|
+
// preserve last known position when floating ref is null (during transitions)
|
|
25
|
+
const xVal = floating.current ? roundByDPR(floating.current, x) : x;
|
|
26
|
+
const yVal = floating.current ? roundByDPR(floating.current, y) : y;
|
|
32
27
|
if (transformOption) {
|
|
33
28
|
return {
|
|
34
|
-
|
|
29
|
+
position: strategy,
|
|
30
|
+
left: "0",
|
|
31
|
+
top: "0",
|
|
35
32
|
transform: `translate(${xVal}px, ${yVal}px)`,
|
|
36
|
-
...(
|
|
33
|
+
...(floating.current &&
|
|
34
|
+
getDPR(floating.current) >= 1.5 && {
|
|
37
35
|
willChange: "transform",
|
|
38
36
|
}),
|
|
39
37
|
};
|
|
@@ -54,6 +52,14 @@ export function useFloating(options) {
|
|
|
54
52
|
placement: placementOption,
|
|
55
53
|
strategy: strategyOption,
|
|
56
54
|
}).then((position) => {
|
|
55
|
+
// ignore bad coordinates that cause jumping during close transitions
|
|
56
|
+
if (!openOption && x !== 0 && y !== 0) {
|
|
57
|
+
// if we had a good position and now getting coordinates near
|
|
58
|
+
// the expected offset bounds during close, ignore it
|
|
59
|
+
const maxExpectedOffset = Math.max(Math.abs(sideOffsetOption), Math.abs(alignOffsetOption), 15);
|
|
60
|
+
if (position.x <= maxExpectedOffset && position.y <= maxExpectedOffset)
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
57
63
|
x = position.x;
|
|
58
64
|
y = position.y;
|
|
59
65
|
strategy = position.strategy;
|
|
@@ -4,7 +4,7 @@ type UseDataTypeaheadOpts = {
|
|
|
4
4
|
onMatch: (value: string) => void;
|
|
5
5
|
getCurrentItem: () => string;
|
|
6
6
|
candidateValues: Getter<string[]>;
|
|
7
|
-
enabled: boolean
|
|
7
|
+
enabled: Getter<boolean>;
|
|
8
8
|
getWindow: () => Window & typeof globalThis;
|
|
9
9
|
};
|
|
10
10
|
export declare function useDataTypeahead(opts: UseDataTypeaheadOpts): {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { executeCallbacks, getWindow } from "svelte-toolbelt";
|
|
1
|
+
import { executeCallbacks, getDocument, getWindow } from "svelte-toolbelt";
|
|
2
2
|
import { on } from "svelte/events";
|
|
3
3
|
import { watch } from "runed";
|
|
4
4
|
import { boxAutoReset } from "./box-auto-reset.svelte.js";
|
|
@@ -60,7 +60,10 @@ export function useGraceArea(opts) {
|
|
|
60
60
|
opts.onPointerExit();
|
|
61
61
|
}
|
|
62
62
|
};
|
|
63
|
-
|
|
63
|
+
const doc = getDocument(opts.triggerNode() ?? opts.contentNode());
|
|
64
|
+
if (!doc)
|
|
65
|
+
return;
|
|
66
|
+
return on(doc, "pointermove", handleTrackPointerGrace);
|
|
64
67
|
});
|
|
65
68
|
return {
|
|
66
69
|
isPointerInTransit,
|
package/dist/types.d.ts
CHANGED
|
@@ -40,4 +40,5 @@ export type * from "./bits/toggle/types.js";
|
|
|
40
40
|
export type * from "./bits/toggle-group/types.js";
|
|
41
41
|
export type * from "./bits/toolbar/types.js";
|
|
42
42
|
export type * from "./bits/tooltip/types.js";
|
|
43
|
+
export type * from "./bits/utilities/config/types.js";
|
|
43
44
|
export type { PortalProps } from "./bits/utilities/portal/types.js";
|