bits-ui 1.4.0 → 1.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.
@@ -4,6 +4,7 @@
4
4
  import type { AccordionRootProps } from "../types.js";
5
5
  import { useId } from "../../../internal/use-id.js";
6
6
  import { noop } from "../../../internal/noop.js";
7
+ import { watch } from "runed";
7
8
 
8
9
  let {
9
10
  disabled = false,
@@ -19,7 +20,20 @@
19
20
  ...restProps
20
21
  }: AccordionRootProps = $props();
21
22
 
22
- value === undefined && (value = type === "single" ? "" : []);
23
+ function handleDefaultValue() {
24
+ if (value !== undefined) return;
25
+ value = type === "single" ? "" : [];
26
+ }
27
+
28
+ // SSR
29
+ handleDefaultValue();
30
+
31
+ watch.pre(
32
+ () => value,
33
+ () => {
34
+ handleDefaultValue();
35
+ }
36
+ );
23
37
 
24
38
  const rootState = useAccordionRoot({
25
39
  type,
@@ -6,6 +6,7 @@
6
6
  import { useId } from "../../../internal/use-id.js";
7
7
  import { noop } from "../../../internal/noop.js";
8
8
  import { getDefaultDate } from "../../../internal/date-time/utils.js";
9
+ import { watch } from "runed";
9
10
 
10
11
  let {
11
12
  child,
@@ -40,16 +41,36 @@
40
41
  defaultValue: value,
41
42
  });
42
43
 
43
- if (placeholder === undefined) {
44
+ function handleDefaultPlaceholder() {
45
+ if (placeholder !== undefined) return;
44
46
  placeholder = defaultPlaceholder;
45
47
  }
46
48
 
47
- if (value === undefined) {
48
- const defaultValue = type === "single" ? undefined : [];
49
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
50
- value = defaultValue as any;
49
+ // SSR
50
+ handleDefaultPlaceholder();
51
+
52
+ watch.pre(
53
+ () => placeholder,
54
+ () => {
55
+ handleDefaultPlaceholder();
56
+ }
57
+ );
58
+
59
+ function handleDefaultValue() {
60
+ if (value !== undefined) return;
61
+ value = type === "single" ? undefined : [];
51
62
  }
52
63
 
64
+ // SSR
65
+ handleDefaultValue();
66
+
67
+ watch.pre(
68
+ () => value,
69
+ () => {
70
+ handleDefaultValue();
71
+ }
72
+ );
73
+
53
74
  const rootState = useCalendarRoot({
54
75
  id: box.with(() => id),
55
76
  ref: box.with(
@@ -5,6 +5,7 @@
5
5
  import FloatingLayer from "../../utilities/floating-layer/components/floating-layer.svelte";
6
6
  import { useSelectRoot } from "../../select/select.svelte.js";
7
7
  import ListboxHiddenInput from "../../select/components/select-hidden-input.svelte";
8
+ import { watch } from "runed";
8
9
 
9
10
  let {
10
11
  value = $bindable(),
@@ -27,6 +28,14 @@
27
28
  value = defaultValue;
28
29
  }
29
30
 
31
+ watch.pre(
32
+ () => value,
33
+ () => {
34
+ if (value !== undefined) return;
35
+ value = type === "single" ? "" : [];
36
+ }
37
+ );
38
+
30
39
  const rootState = useSelectRoot({
31
40
  type,
32
41
  value: box.with(
@@ -36,8 +36,10 @@
36
36
  value: box.with(
37
37
  () => value,
38
38
  (v) => {
39
- value = v;
40
- onValueChange(v);
39
+ if (value !== v) {
40
+ value = v;
41
+ onValueChange(v);
42
+ }
41
43
  }
42
44
  ),
43
45
  vimBindings: box.with(() => vimBindings),
@@ -5,6 +5,7 @@
5
5
  import type { DateFieldRootProps } from "../types.js";
6
6
  import { noop } from "../../../internal/noop.js";
7
7
  import { getDefaultDate } from "../../../internal/date-time/utils.js";
8
+ import { watch } from "runed";
8
9
 
9
10
  let {
10
11
  disabled = false,
@@ -27,7 +28,9 @@
27
28
  children,
28
29
  }: DateFieldRootProps = $props();
29
30
 
30
- if (placeholder === undefined) {
31
+ function handleDefaultPlaceholder() {
32
+ if (placeholder !== undefined) return;
33
+
31
34
  const defaultPlaceholder = getDefaultDate({
32
35
  granularity,
33
36
  defaultValue: value,
@@ -36,6 +39,21 @@
36
39
  placeholder = defaultPlaceholder;
37
40
  }
38
41
 
42
+ // SSR
43
+ handleDefaultPlaceholder();
44
+
45
+ /**
46
+ * Covers an edge case where when a spread props object is reassigned,
47
+ * the props are reset to their default values, which would make placeholder
48
+ * undefined which causes errors to be thrown.
49
+ */
50
+ watch.pre(
51
+ () => placeholder,
52
+ () => {
53
+ handleDefaultPlaceholder();
54
+ }
55
+ );
56
+
39
57
  useDateFieldRoot({
40
58
  value: box.with(
41
59
  () => value,
@@ -9,6 +9,7 @@
9
9
  import { useDateFieldRoot } from "../../date-field/date-field.svelte.js";
10
10
  import { FloatingLayer } from "../../utilities/floating-layer/index.js";
11
11
  import { getDefaultDate } from "../../../internal/date-time/utils.js";
12
+ import { watch } from "runed";
12
13
 
13
14
  let {
14
15
  open = $bindable(false),
@@ -50,10 +51,26 @@
50
51
  defaultValue: value,
51
52
  });
52
53
 
53
- if (placeholder === undefined) {
54
+ function handleDefaultPlaceholder() {
55
+ if (placeholder !== undefined) return;
54
56
  placeholder = defaultPlaceholder;
55
57
  }
56
58
 
59
+ // SSR
60
+ handleDefaultPlaceholder();
61
+
62
+ /**
63
+ * Covers an edge case where when a spread props object is reassigned,
64
+ * the props are reset to their default values, which would make placeholder
65
+ * undefined which causes errors to be thrown.
66
+ */
67
+ watch.pre(
68
+ () => placeholder,
69
+ () => {
70
+ handleDefaultPlaceholder();
71
+ }
72
+ );
73
+
57
74
  function onDateSelect() {
58
75
  if (closeOnDateSelect) {
59
76
  open = false;
@@ -7,6 +7,7 @@
7
7
  import { noop } from "../../../internal/noop.js";
8
8
  import type { DateRange } from "../../../shared/index.js";
9
9
  import { getDefaultDate } from "../../../internal/date-time/utils.js";
10
+ import { watch } from "runed";
10
11
 
11
12
  let {
12
13
  id = useId(),
@@ -38,21 +39,43 @@
38
39
  let startValue = $state<DateValue | undefined>(value?.start);
39
40
  let endValue = $state<DateValue | undefined>(value?.end);
40
41
 
41
- if (placeholder === undefined) {
42
- const defaultPlaceholder = getDefaultDate({
43
- granularity,
44
- defaultValue: value?.start,
45
- });
46
-
42
+ function handleDefaultPlaceholder() {
43
+ if (placeholder !== undefined) return;
44
+ const defaultPlaceholder = getDefaultDate({ granularity, defaultValue: value?.start });
47
45
  placeholder = defaultPlaceholder;
48
46
  }
49
47
 
50
- if (value === undefined) {
51
- const defaultValue = { start: undefined, end: undefined };
48
+ // SSR
49
+ handleDefaultPlaceholder();
50
+
51
+ watch.pre(
52
+ () => placeholder,
53
+ () => {
54
+ handleDefaultPlaceholder();
55
+ }
56
+ );
52
57
 
58
+ function handleDefaultValue() {
59
+ if (value !== undefined) return;
60
+ const defaultValue = { start: undefined, end: undefined };
53
61
  value = defaultValue;
54
62
  }
55
63
 
64
+ // SSR
65
+ handleDefaultValue();
66
+
67
+ /**
68
+ * Covers an edge case where when a spread props object is reassigned,
69
+ * the props are reset to their default values, which would make value
70
+ * undefined which causes errors to be thrown.
71
+ */
72
+ watch.pre(
73
+ () => value,
74
+ () => {
75
+ handleDefaultValue();
76
+ }
77
+ );
78
+
56
79
  const rootState = useDateRangeFieldRoot({
57
80
  id: box.with(() => id),
58
81
  ref: box.with(
@@ -10,6 +10,7 @@
10
10
  import { useId } from "../../../internal/use-id.js";
11
11
  import type { DateRange } from "../../../shared/index.js";
12
12
  import { getDefaultDate } from "../../../internal/date-time/utils.js";
13
+ import { watch } from "runed";
13
14
 
14
15
  let {
15
16
  open = $bindable(false),
@@ -54,18 +55,51 @@
54
55
  let startValue = $state<DateValue | undefined>(value?.start);
55
56
  let endValue = $state<DateValue | undefined>(value?.end);
56
57
 
57
- if (value === undefined) {
58
+ function handleDefaultValue() {
59
+ if (value !== undefined) return;
58
60
  value = { start: undefined, end: undefined };
59
61
  }
62
+
63
+ // SSR
64
+ handleDefaultValue();
65
+
66
+ /**
67
+ * Covers an edge case where when a spread props object is reassigned,
68
+ * the props are reset to their default values, which would make value
69
+ * undefined which causes errors to be thrown.
70
+ */
71
+ watch.pre(
72
+ () => value,
73
+ () => {
74
+ handleDefaultValue();
75
+ }
76
+ );
77
+
60
78
  const defaultPlaceholder = getDefaultDate({
61
79
  granularity,
62
80
  defaultValue: value?.start,
63
81
  });
64
82
 
65
- if (placeholder === undefined) {
83
+ function handleDefaultPlaceholder() {
84
+ if (placeholder !== undefined) return;
66
85
  placeholder = defaultPlaceholder;
67
86
  }
68
87
 
88
+ // SSR
89
+ handleDefaultPlaceholder();
90
+
91
+ /**
92
+ * Covers an edge case where when a spread props object is reassigned,
93
+ * the props are reset to their default values, which would make placeholder
94
+ * undefined which causes errors to be thrown.
95
+ */
96
+ watch.pre(
97
+ () => placeholder,
98
+ () => {
99
+ handleDefaultPlaceholder();
100
+ }
101
+ );
102
+
69
103
  function onRangeSelect() {
70
104
  if (closeOnRangeSelect) {
71
105
  open = false;
@@ -6,6 +6,7 @@
6
6
  import { noop } from "../../../internal/noop.js";
7
7
  import { useId } from "../../../internal/use-id.js";
8
8
  import { getDefaultDate } from "../../../internal/date-time/utils.js";
9
+ import { watch } from "runed";
9
10
 
10
11
  let {
11
12
  children,
@@ -43,15 +44,36 @@
43
44
  defaultValue: value?.start,
44
45
  });
45
46
 
46
- if (placeholder === undefined) {
47
+ function handleDefaultPlaceholder() {
48
+ if (placeholder !== undefined) return;
47
49
  placeholder = defaultPlaceholder;
48
50
  }
49
51
 
50
- if (value === undefined) {
51
- const defaultValue = { start: undefined, end: undefined };
52
- value = defaultValue;
52
+ // SSR
53
+ handleDefaultPlaceholder();
54
+
55
+ watch.pre(
56
+ () => placeholder,
57
+ () => {
58
+ handleDefaultPlaceholder();
59
+ }
60
+ );
61
+
62
+ function handleDefaultValue() {
63
+ if (value !== undefined) return;
64
+ value = { start: undefined, end: undefined };
53
65
  }
54
66
 
67
+ // SSR
68
+ handleDefaultValue();
69
+
70
+ watch.pre(
71
+ () => value,
72
+ () => {
73
+ handleDefaultValue();
74
+ }
75
+ );
76
+
55
77
  const rootState = useRangeCalendarRoot({
56
78
  id: box.with(() => id),
57
79
  ref: box.with(
@@ -5,6 +5,7 @@
5
5
  import { useSelectRoot } from "../select.svelte.js";
6
6
  import type { SelectRootProps } from "../types.js";
7
7
  import SelectHiddenInput from "./select-hidden-input.svelte";
8
+ import { watch } from "runed";
8
9
 
9
10
  let {
10
11
  value = $bindable(),
@@ -22,12 +23,21 @@
22
23
  children,
23
24
  }: SelectRootProps = $props();
24
25
 
25
- if (value === undefined) {
26
- const defaultValue = type === "single" ? "" : [];
27
-
28
- value = defaultValue;
26
+ function handleDefaultValue() {
27
+ if (value !== undefined) return;
28
+ value = type === "single" ? "" : [];
29
29
  }
30
30
 
31
+ // SSR
32
+ handleDefaultValue();
33
+
34
+ watch.pre(
35
+ () => value,
36
+ () => {
37
+ handleDefaultValue();
38
+ }
39
+ );
40
+
31
41
  const rootState = useSelectRoot({
32
42
  type,
33
43
  value: box.with(
@@ -62,8 +62,7 @@ class SelectBaseRootState {
62
62
  const node = this.contentNode;
63
63
  if (!node)
64
64
  return [];
65
- const nodes = Array.from(node.querySelectorAll(`[${this.bitsAttrs.item}]:not([data-disabled])`));
66
- return nodes;
65
+ return Array.from(node.querySelectorAll(`[${this.bitsAttrs.item}]:not([data-disabled])`));
67
66
  }
68
67
  setHighlightedToFirstCandidate() {
69
68
  this.setHighlightedNode(null);
@@ -817,7 +816,10 @@ class SelectItemState {
817
816
  : undefined,
818
817
  "data-value": this.opts.value.current,
819
818
  "data-disabled": getDataDisabled(this.opts.disabled.current),
820
- "data-highlighted": this.root.highlightedValue === this.opts.value.current ? "" : undefined,
819
+ "data-highlighted": this.root.highlightedValue === this.opts.value.current &&
820
+ !this.opts.disabled.current
821
+ ? ""
822
+ : undefined,
821
823
  "data-selected": this.root.includesItem(this.opts.value.current) ? "" : undefined,
822
824
  "data-label": this.opts.label.current,
823
825
  [this.root.bitsAttrs.item]: "",
@@ -4,6 +4,7 @@
4
4
  import { useSliderRoot } from "../slider.svelte.js";
5
5
  import { useId } from "../../../internal/use-id.js";
6
6
  import { noop } from "../../../internal/noop.js";
7
+ import { watch } from "runed";
7
8
 
8
9
  let {
9
10
  children,
@@ -24,10 +25,21 @@
24
25
  ...restProps
25
26
  }: SliderRootProps = $props();
26
27
 
27
- if (value === undefined) {
28
+ function handleDefaultValue() {
29
+ if (value !== undefined) return;
28
30
  value = type === "single" ? 0 : [];
29
31
  }
30
32
 
33
+ // SSR
34
+ handleDefaultValue();
35
+
36
+ watch.pre(
37
+ () => value,
38
+ () => {
39
+ handleDefaultValue();
40
+ }
41
+ );
42
+
31
43
  const rootState = useSliderRoot({
32
44
  id: box.with(() => id),
33
45
  ref: box.with(
@@ -5,6 +5,7 @@
5
5
  import { useToggleGroupRoot } from "../toggle-group.svelte.js";
6
6
  import { useId } from "../../../internal/use-id.js";
7
7
  import { noop } from "../../../internal/noop.js";
8
+ import { watch } from "runed";
8
9
 
9
10
  let {
10
11
  id = useId(),
@@ -21,12 +22,21 @@
21
22
  ...restProps
22
23
  }: ToggleGroupRootProps = $props();
23
24
 
24
- if (value === undefined) {
25
- const defaultValue = type === "single" ? "" : [];
26
-
27
- value = defaultValue;
25
+ function handleDefaultValue() {
26
+ if (value !== undefined) return;
27
+ value = type === "single" ? "" : [];
28
28
  }
29
29
 
30
+ // SSR
31
+ handleDefaultValue();
32
+
33
+ watch.pre(
34
+ () => value,
35
+ () => {
36
+ handleDefaultValue();
37
+ }
38
+ );
39
+
30
40
  const rootState = useToggleGroupRoot({
31
41
  id: box.with(() => id),
32
42
  value: box.with(
@@ -5,6 +5,7 @@
5
5
  import { useToolbarGroup } from "../toolbar.svelte.js";
6
6
  import { useId } from "../../../internal/use-id.js";
7
7
  import { noop } from "../../../internal/noop.js";
8
+ import { watch } from "runed";
8
9
 
9
10
  let {
10
11
  id = useId(),
@@ -18,11 +19,21 @@
18
19
  ...restProps
19
20
  }: ToolbarGroupProps = $props();
20
21
 
21
- if (value === undefined) {
22
- const defaultValue = type === "single" ? "" : [];
23
- value = defaultValue;
22
+ function handleDefaultValue() {
23
+ if (value !== undefined) return;
24
+ value = type === "single" ? "" : [];
24
25
  }
25
26
 
27
+ // SSR
28
+ handleDefaultValue();
29
+
30
+ watch.pre(
31
+ () => value,
32
+ () => {
33
+ handleDefaultValue();
34
+ }
35
+ );
36
+
26
37
  const groupState = useToolbarGroup({
27
38
  id: box.with(() => id),
28
39
  disabled: box.with(() => disabled),
@@ -10,13 +10,12 @@ export function useDOMTypeahead(opts) {
10
10
  return;
11
11
  search.current = search.current + key;
12
12
  const currentItem = getCurrentItem();
13
- const currentMatch = candidates.find((item) => item === currentItem)?.textContent ?? "";
14
- const values = candidates.map((item) => item.textContent ?? "");
13
+ const currentMatch = candidates.find((item) => item === currentItem)?.textContent?.trim() ?? "";
14
+ const values = candidates.map((item) => item.textContent?.trim() ?? "");
15
15
  const nextMatch = getNextMatch(values, search.current, currentMatch);
16
- const newItem = candidates.find((item) => item.textContent === nextMatch);
17
- if (newItem) {
16
+ const newItem = candidates.find((item) => item.textContent?.trim() === nextMatch);
17
+ if (newItem)
18
18
  onMatch(newItem);
19
- }
20
19
  return newItem;
21
20
  }
22
21
  function resetTypeahead() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bits-ui",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "license": "MIT",
5
5
  "repository": "github:huntabyte/bits-ui",
6
6
  "funding": "https://github.com/sponsors/huntabyte",