bits-ui 2.2.1 → 2.3.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.
Files changed (98) hide show
  1. package/dist/bits/accordion/accordion.svelte.d.ts +0 -5
  2. package/dist/bits/accordion/accordion.svelte.js +11 -14
  3. package/dist/bits/aspect-ratio/aspect-ratio.svelte.d.ts +0 -1
  4. package/dist/bits/aspect-ratio/aspect-ratio.svelte.js +6 -2
  5. package/dist/bits/avatar/avatar.svelte.d.ts +0 -3
  6. package/dist/bits/avatar/avatar.svelte.js +8 -6
  7. package/dist/bits/calendar/calendar.svelte.d.ts +2 -2
  8. package/dist/bits/calendar/calendar.svelte.js +4 -4
  9. package/dist/bits/checkbox/checkbox.svelte.d.ts +0 -3
  10. package/dist/bits/checkbox/checkbox.svelte.js +14 -14
  11. package/dist/bits/collapsible/collapsible.svelte.d.ts +0 -3
  12. package/dist/bits/collapsible/collapsible.svelte.js +8 -7
  13. package/dist/bits/command/command.svelte.d.ts +0 -12
  14. package/dist/bits/command/command.svelte.js +35 -31
  15. package/dist/bits/date-field/date-field.svelte.d.ts +2 -4
  16. package/dist/bits/date-field/date-field.svelte.js +8 -6
  17. package/dist/bits/date-picker/components/date-picker-trigger.svelte +2 -2
  18. package/dist/bits/date-range-field/date-range-field.svelte.d.ts +1 -3
  19. package/dist/bits/date-range-field/date-range-field.svelte.js +7 -5
  20. package/dist/bits/date-range-picker/components/date-range-picker-trigger.svelte +2 -2
  21. package/dist/bits/dialog/dialog.svelte.d.ts +2 -12
  22. package/dist/bits/dialog/dialog.svelte.js +16 -24
  23. package/dist/bits/index.d.ts +1 -0
  24. package/dist/bits/index.js +1 -0
  25. package/dist/bits/label/label.svelte.d.ts +0 -1
  26. package/dist/bits/label/label.svelte.js +6 -2
  27. package/dist/bits/link-preview/link-preview.svelte.d.ts +0 -2
  28. package/dist/bits/link-preview/link-preview.svelte.js +7 -5
  29. package/dist/bits/menu/components/menu-sub-content-static.svelte +1 -1
  30. package/dist/bits/menu/components/menu-sub-content.svelte +1 -1
  31. package/dist/bits/menu/menu.svelte.d.ts +2 -1
  32. package/dist/bits/menu/menu.svelte.js +39 -21
  33. package/dist/bits/menubar/menubar.svelte.d.ts +1 -7
  34. package/dist/bits/menubar/menubar.svelte.js +12 -14
  35. package/dist/bits/meter/meter.svelte.d.ts +0 -1
  36. package/dist/bits/meter/meter.svelte.js +6 -2
  37. package/dist/bits/navigation-menu/navigation-menu.svelte.d.ts +2 -11
  38. package/dist/bits/navigation-menu/navigation-menu.svelte.js +30 -25
  39. package/dist/bits/pagination/pagination.svelte.d.ts +0 -4
  40. package/dist/bits/pagination/pagination.svelte.js +9 -10
  41. package/dist/bits/pin-input/pin-input.svelte.d.ts +0 -2
  42. package/dist/bits/pin-input/pin-input.svelte.js +7 -5
  43. package/dist/bits/popover/popover.svelte.d.ts +0 -3
  44. package/dist/bits/popover/popover.svelte.js +9 -5
  45. package/dist/bits/progress/progress.svelte.d.ts +0 -1
  46. package/dist/bits/progress/progress.svelte.js +6 -2
  47. package/dist/bits/radio-group/radio-group.svelte.d.ts +7 -9
  48. package/dist/bits/radio-group/radio-group.svelte.js +9 -10
  49. package/dist/bits/range-calendar/range-calendar.svelte.d.ts +38 -38
  50. package/dist/bits/range-calendar/range-calendar.svelte.js +79 -79
  51. package/dist/bits/rating-group/components/rating-group-input.svelte +10 -0
  52. package/dist/bits/rating-group/components/rating-group-input.svelte.d.ts +18 -0
  53. package/dist/bits/rating-group/components/rating-group-item.svelte +38 -0
  54. package/dist/bits/rating-group/components/rating-group-item.svelte.d.ts +4 -0
  55. package/dist/bits/rating-group/components/rating-group.svelte +80 -0
  56. package/dist/bits/rating-group/components/rating-group.svelte.d.ts +4 -0
  57. package/dist/bits/rating-group/exports.d.ts +3 -0
  58. package/dist/bits/rating-group/exports.js +2 -0
  59. package/dist/bits/rating-group/index.d.ts +1 -0
  60. package/dist/bits/rating-group/index.js +1 -0
  61. package/dist/bits/rating-group/rating-group.svelte.d.ts +112 -0
  62. package/dist/bits/rating-group/rating-group.svelte.js +317 -0
  63. package/dist/bits/rating-group/types.d.ts +111 -0
  64. package/dist/bits/rating-group/types.js +1 -0
  65. package/dist/bits/scroll-area/scroll-area.svelte.d.ts +15 -19
  66. package/dist/bits/scroll-area/scroll-area.svelte.js +10 -10
  67. package/dist/bits/select/select.svelte.d.ts +28 -30
  68. package/dist/bits/select/select.svelte.js +36 -48
  69. package/dist/bits/separator/separator.svelte.d.ts +1 -2
  70. package/dist/bits/separator/separator.svelte.js +6 -3
  71. package/dist/bits/slider/slider.svelte.d.ts +17 -24
  72. package/dist/bits/slider/slider.svelte.js +15 -17
  73. package/dist/bits/switch/switch.svelte.d.ts +6 -8
  74. package/dist/bits/switch/switch.svelte.js +7 -5
  75. package/dist/bits/tabs/tabs.svelte.d.ts +5 -9
  76. package/dist/bits/tabs/tabs.svelte.js +11 -11
  77. package/dist/bits/time-field/time-field.svelte.d.ts +1 -3
  78. package/dist/bits/time-field/time-field.svelte.js +7 -5
  79. package/dist/bits/time-range-field/time-range-field.svelte.d.ts +1 -3
  80. package/dist/bits/time-range-field/time-range-field.svelte.js +7 -5
  81. package/dist/bits/toggle/toggle.svelte.d.ts +3 -3
  82. package/dist/bits/toggle/toggle.svelte.js +6 -3
  83. package/dist/bits/toggle-group/toggle-group.svelte.d.ts +1 -2
  84. package/dist/bits/toggle-group/toggle-group.svelte.js +8 -6
  85. package/dist/bits/toolbar/toolbar.svelte.d.ts +11 -18
  86. package/dist/bits/toolbar/toolbar.svelte.js +14 -17
  87. package/dist/bits/tooltip/tooltip.svelte.d.ts +13 -14
  88. package/dist/bits/tooltip/tooltip.svelte.js +7 -5
  89. package/dist/index.d.ts +1 -1
  90. package/dist/index.js +1 -1
  91. package/dist/internal/attrs.d.ts +14 -0
  92. package/dist/internal/attrs.js +18 -0
  93. package/dist/internal/date-time/calendar-helpers.svelte.d.ts +1 -0
  94. package/dist/internal/date-time/calendar-helpers.svelte.js +18 -1
  95. package/dist/internal/use-arrow-navigation.d.ts +2 -2
  96. package/dist/internal/use-arrow-navigation.js +1 -1
  97. package/dist/types.d.ts +1 -0
  98. package/package.json +1 -1
@@ -7,7 +7,7 @@ import { useDOMTypeahead } from "../../internal/use-dom-typeahead.svelte.js";
7
7
  import { isElement, isElementOrSVGElement, isHTMLElement } from "../../internal/is.js";
8
8
  import { useRovingFocus } from "../../internal/use-roving-focus.svelte.js";
9
9
  import { kbd } from "../../internal/kbd.js";
10
- import { getAriaChecked, getAriaDisabled, getAriaExpanded, getAriaOrientation, getDataDisabled, getDataOpenClosed, } from "../../internal/attrs.js";
10
+ import { createBitsAttrs, getAriaChecked, getAriaDisabled, getAriaExpanded, getAriaOrientation, getDataDisabled, getDataOpenClosed, } from "../../internal/attrs.js";
11
11
  import { IsUsingKeyboard } from "../../index.js";
12
12
  import { useGraceArea } from "../../internal/use-grace-area.svelte.js";
13
13
  import { getTabbableFrom } from "../../internal/tabbable.js";
@@ -25,6 +25,24 @@ export const MenuOpenEvent = new CustomEventDispatcher("bitsmenuopen", {
25
25
  bubbles: false,
26
26
  cancelable: true,
27
27
  });
28
+ export const menuAttrs = createBitsAttrs({
29
+ component: "menu",
30
+ parts: [
31
+ "trigger",
32
+ "content",
33
+ "sub-trigger",
34
+ "item",
35
+ "group",
36
+ "group-heading",
37
+ "checkbox-group",
38
+ "checkbox-item",
39
+ "radio-group",
40
+ "radio-item",
41
+ "separator",
42
+ "sub-content",
43
+ "arrow",
44
+ ],
45
+ });
28
46
  class MenuRootState {
29
47
  opts;
30
48
  isUsingKeyboard = new IsUsingKeyboard();
@@ -33,9 +51,9 @@ class MenuRootState {
33
51
  constructor(opts) {
34
52
  this.opts = opts;
35
53
  }
36
- getAttr(name) {
37
- return `data-${this.opts.variant.current}-${name}`;
38
- }
54
+ getBitsAttr = (part) => {
55
+ return menuAttrs.getAttr(part, this.opts.variant.current);
56
+ };
39
57
  }
40
58
  class MenuMenuState {
41
59
  opts;
@@ -90,7 +108,7 @@ class MenuContentState {
90
108
  contentNode: () => this.parentMenu.contentNode,
91
109
  triggerNode: () => this.parentMenu.triggerNode,
92
110
  enabled: () => this.parentMenu.opts.open.current &&
93
- Boolean(this.parentMenu.triggerNode?.hasAttribute(this.parentMenu.root.getAttr("sub-trigger"))),
111
+ Boolean(this.parentMenu.triggerNode?.hasAttribute(this.parentMenu.root.getBitsAttr("sub-trigger"))),
94
112
  onPointerExit: () => {
95
113
  this.parentMenu.opts.open.current = false;
96
114
  },
@@ -104,7 +122,7 @@ class MenuContentState {
104
122
  }).handleTypeaheadSearch;
105
123
  this.rovingFocusGroup = useRovingFocus({
106
124
  rootNode: box.with(() => this.parentMenu.contentNode),
107
- candidateAttr: this.parentMenu.root.getAttr("item"),
125
+ candidateAttr: this.parentMenu.root.getBitsAttr("item"),
108
126
  loop: this.opts.loop,
109
127
  orientation: box.with(() => "vertical"),
110
128
  });
@@ -130,7 +148,7 @@ class MenuContentState {
130
148
  const node = this.parentMenu.contentNode;
131
149
  if (!node)
132
150
  return [];
133
- const candidates = Array.from(node.querySelectorAll(`[${this.parentMenu.root.getAttr("item")}]:not([data-disabled])`));
151
+ const candidates = Array.from(node.querySelectorAll(`[${this.parentMenu.root.getBitsAttr("item")}]:not([data-disabled])`));
134
152
  return candidates;
135
153
  }
136
154
  #isPointerMovingToSubmenu() {
@@ -193,7 +211,7 @@ class MenuContentState {
193
211
  const currentTarget = e.currentTarget;
194
212
  if (!isHTMLElement(target) || !isHTMLElement(currentTarget))
195
213
  return;
196
- const isKeydownInside = target.closest(`[${this.parentMenu.root.getAttr("content")}]`)?.id ===
214
+ const isKeydownInside = target.closest(`[${this.parentMenu.root.getBitsAttr("content")}]`)?.id ===
197
215
  this.parentMenu.contentId.current;
198
216
  const isModifierKey = e.ctrlKey || e.altKey || e.metaKey;
199
217
  const isCharacterKey = e.key.length === 1;
@@ -240,7 +258,7 @@ class MenuContentState {
240
258
  return this.#isPointerMovingToSubmenu();
241
259
  }
242
260
  onItemLeave(e) {
243
- if (e.currentTarget.hasAttribute(this.parentMenu.root.getAttr("sub-trigger")))
261
+ if (e.currentTarget.hasAttribute(this.parentMenu.root.getBitsAttr("sub-trigger")))
244
262
  return;
245
263
  if (this.#isPointerMovingToSubmenu() || this.parentMenu.root.isUsingKeyboard.current)
246
264
  return;
@@ -277,7 +295,7 @@ class MenuContentState {
277
295
  id: this.opts.id.current,
278
296
  role: "menu",
279
297
  "aria-orientation": getAriaOrientation("vertical"),
280
- [this.parentMenu.root.getAttr("content")]: "",
298
+ [this.parentMenu.root.getBitsAttr("content")]: "",
281
299
  "data-state": getDataOpenClosed(this.parentMenu.opts.open.current),
282
300
  onkeydown: this.onkeydown,
283
301
  onblur: this.onblur,
@@ -356,7 +374,7 @@ class MenuItemSharedState {
356
374
  "aria-disabled": getAriaDisabled(this.opts.disabled.current),
357
375
  "data-disabled": getDataDisabled(this.opts.disabled.current),
358
376
  "data-highlighted": this.#isFocused ? "" : undefined,
359
- [this.content.parentMenu.root.getAttr("item")]: "",
377
+ [this.content.parentMenu.root.getBitsAttr("item")]: "",
360
378
  //
361
379
  onpointermove: this.onpointermove,
362
380
  onpointerleave: this.onpointerleave,
@@ -520,7 +538,7 @@ class MenuSubTriggerState {
520
538
  "aria-controls": this.submenu.opts.open.current
521
539
  ? this.submenu.contentId.current
522
540
  : undefined,
523
- [this.submenu.root.getAttr("sub-trigger")]: "",
541
+ [this.submenu.root.getBitsAttr("sub-trigger")]: "",
524
542
  onclick: this.onclick,
525
543
  onpointermove: this.onpointermove,
526
544
  onpointerleave: this.onpointerleave,
@@ -570,7 +588,7 @@ class MenuCheckboxItemState {
570
588
  role: "menuitemcheckbox",
571
589
  "aria-checked": getAriaChecked(this.opts.checked.current, this.opts.indeterminate.current),
572
590
  "data-state": getCheckedState(this.opts.checked.current),
573
- [this.item.root.getAttr("checkbox-item")]: "",
591
+ [this.item.root.getBitsAttr("checkbox-item")]: "",
574
592
  }));
575
593
  }
576
594
  class MenuGroupState {
@@ -585,7 +603,7 @@ class MenuGroupState {
585
603
  id: this.opts.id.current,
586
604
  role: "group",
587
605
  "aria-labelledby": this.groupHeadingId,
588
- [this.root.getAttr("group")]: "",
606
+ [this.root.getBitsAttr("group")]: "",
589
607
  ...attachRef(this.opts.ref),
590
608
  }));
591
609
  }
@@ -599,7 +617,7 @@ class MenuGroupHeadingState {
599
617
  props = $derived.by(() => ({
600
618
  id: this.opts.id.current,
601
619
  role: "group",
602
- [this.group.root.getAttr("group-heading")]: "",
620
+ [this.group.root.getBitsAttr("group-heading")]: "",
603
621
  ...attachRef(this.opts.ref, (v) => (this.group.groupHeadingId = v?.id)),
604
622
  }));
605
623
  }
@@ -613,7 +631,7 @@ class MenuSeparatorState {
613
631
  props = $derived.by(() => ({
614
632
  id: this.opts.id.current,
615
633
  role: "group",
616
- [this.root.getAttr("separator")]: "",
634
+ [this.root.getBitsAttr("separator")]: "",
617
635
  ...attachRef(this.opts.ref),
618
636
  }));
619
637
  }
@@ -623,7 +641,7 @@ class MenuArrowState {
623
641
  this.root = root;
624
642
  }
625
643
  props = $derived.by(() => ({
626
- [this.root.getAttr("arrow")]: "",
644
+ [this.root.getBitsAttr("arrow")]: "",
627
645
  }));
628
646
  }
629
647
  class MenuRadioGroupState {
@@ -641,7 +659,7 @@ class MenuRadioGroupState {
641
659
  }
642
660
  props = $derived.by(() => ({
643
661
  id: this.opts.id.current,
644
- [this.root.getAttr("radio-group")]: "",
662
+ [this.root.getBitsAttr("radio-group")]: "",
645
663
  role: "group",
646
664
  "aria-labelledby": this.groupHeadingId,
647
665
  ...attachRef(this.opts.ref),
@@ -661,7 +679,7 @@ class MenuRadioItemState {
661
679
  this.group.setValue(this.opts.value.current);
662
680
  }
663
681
  props = $derived.by(() => ({
664
- [this.group.root.getAttr("radio-item")]: "",
682
+ [this.group.root.getBitsAttr("radio-item")]: "",
665
683
  ...this.item.props,
666
684
  role: "menuitemradio",
667
685
  "aria-checked": getAriaChecked(this.isChecked, false),
@@ -723,7 +741,7 @@ class DropdownMenuTriggerState {
723
741
  "aria-controls": this.#ariaControls,
724
742
  "data-disabled": getDataDisabled(this.opts.disabled.current),
725
743
  "data-state": getDataOpenClosed(this.parentMenu.opts.open.current),
726
- [this.parentMenu.root.getAttr("trigger")]: "",
744
+ [this.parentMenu.root.getBitsAttr("trigger")]: "",
727
745
  //
728
746
  onpointerdown: this.onpointerdown,
729
747
  onpointerup: this.onpointerup,
@@ -844,7 +862,7 @@ class MenuCheckboxGroupState {
844
862
  }
845
863
  props = $derived.by(() => ({
846
864
  id: this.opts.id.current,
847
- [this.root.getAttr("checkbox-group")]: "",
865
+ [this.root.getBitsAttr("checkbox-group")]: "",
848
866
  role: "group",
849
867
  "aria-labelledby": this.groupHeadingId,
850
868
  ...attachRef(this.opts.ref),
@@ -38,7 +38,6 @@ declare class MenubarRootState {
38
38
  props: {
39
39
  readonly id: string;
40
40
  readonly role: "menubar";
41
- readonly "data-menubar-root": "";
42
41
  };
43
42
  }
44
43
  type MenubarMenuStateProps = ReadableBoxedValues<{
@@ -87,7 +86,6 @@ declare class MenubarTriggerState {
87
86
  readonly "data-menu-value": string;
88
87
  readonly disabled: true | undefined;
89
88
  readonly tabindex: number;
90
- readonly "data-menubar-trigger": "";
91
89
  readonly onpointerdown: PointerEventHandler<HTMLElement>;
92
90
  readonly onpointerenter: PointerEventHandler<HTMLElement>;
93
91
  readonly onkeydown: KeyboardEventHandler<HTMLElement>;
@@ -117,11 +115,7 @@ declare class MenubarContentState {
117
115
  readonly id: string;
118
116
  readonly "aria-labelledby": string | undefined;
119
117
  readonly style: {
120
- readonly "--bits-menubar-content-transform-origin": "var(--bits-floating-transform-origin)";
121
- readonly "--bits-menubar-content-available-width": "var(--bits-floating-available-width)";
122
- readonly "--bits-menubar-content-available-height": "var(--bits-floating-available-height)";
123
- readonly "--bits-menubar-anchor-width": "var(--bits-floating-anchor-width)";
124
- readonly "--bits-menubar-anchor-height": "var(--bits-floating-anchor-height)";
118
+ [x: string]: string;
125
119
  };
126
120
  readonly onkeydown: KeyboardEventHandler<HTMLElement>;
127
121
  readonly "data-menu-content": "";
@@ -1,13 +1,16 @@
1
1
  import { afterTick, box, attachRef } from "svelte-toolbelt";
2
2
  import { Context, watch } from "runed";
3
3
  import { useRovingFocus, } from "../../internal/use-roving-focus.svelte.js";
4
- import { getAriaExpanded, getDataDisabled, getDataOpenClosed } from "../../internal/attrs.js";
4
+ import { createBitsAttrs, getAriaExpanded, getDataDisabled, getDataOpenClosed, } from "../../internal/attrs.js";
5
5
  import { kbd } from "../../internal/kbd.js";
6
6
  import { wrapArray } from "../../internal/arrays.js";
7
7
  import { FocusScopeContext, } from "../utilities/focus-scope/use-focus-scope.svelte.js";
8
8
  import { onMount } from "svelte";
9
- const MENUBAR_ROOT_ATTR = "data-menubar-root";
10
- const MENUBAR_TRIGGER_ATTR = "data-menubar-trigger";
9
+ import { getFloatingContentCSSVars } from "../../internal/floating-svelte/floating-utils.svelte";
10
+ const menubarAttrs = createBitsAttrs({
11
+ component: "menubar",
12
+ parts: ["root", "trigger", "content"],
13
+ });
11
14
  class MenubarRootState {
12
15
  opts;
13
16
  rovingFocusGroup;
@@ -18,7 +21,7 @@ class MenubarRootState {
18
21
  this.opts = opts;
19
22
  this.rovingFocusGroup = useRovingFocus({
20
23
  rootNode: this.opts.ref,
21
- candidateAttr: MENUBAR_TRIGGER_ATTR,
24
+ candidateAttr: menubarAttrs.trigger,
22
25
  loop: this.opts.loop,
23
26
  orientation: box.with(() => "horizontal"),
24
27
  });
@@ -60,7 +63,7 @@ class MenubarRootState {
60
63
  const node = this.opts.ref.current;
61
64
  if (!node)
62
65
  return [];
63
- return Array.from(node.querySelectorAll(`[${MENUBAR_TRIGGER_ATTR}]`));
66
+ return Array.from(node.querySelectorAll(menubarAttrs.selector("trigger")));
64
67
  };
65
68
  onMenuOpen = (id, triggerId) => {
66
69
  this.updateValue(id);
@@ -75,7 +78,7 @@ class MenubarRootState {
75
78
  props = $derived.by(() => ({
76
79
  id: this.opts.id.current,
77
80
  role: "menubar",
78
- [MENUBAR_ROOT_ATTR]: "",
81
+ [menubarAttrs.root]: "",
79
82
  ...attachRef(this.opts.ref),
80
83
  }));
81
84
  }
@@ -185,7 +188,7 @@ class MenubarTriggerState {
185
188
  "data-menu-value": this.menu.opts.value.current,
186
189
  disabled: this.opts.disabled.current ? true : undefined,
187
190
  tabindex: this.#tabIndex,
188
- [MENUBAR_TRIGGER_ATTR]: "",
191
+ [menubarAttrs.trigger]: "",
189
192
  onpointerdown: this.onpointerdown,
190
193
  onpointerenter: this.onpointerenter,
191
194
  onkeydown: this.onkeydown,
@@ -262,15 +265,10 @@ class MenubarContentState {
262
265
  props = $derived.by(() => ({
263
266
  id: this.opts.id.current,
264
267
  "aria-labelledby": this.menu.triggerId,
265
- style: {
266
- "--bits-menubar-content-transform-origin": "var(--bits-floating-transform-origin)",
267
- "--bits-menubar-content-available-width": "var(--bits-floating-available-width)",
268
- "--bits-menubar-content-available-height": "var(--bits-floating-available-height)",
269
- "--bits-menubar-anchor-width": "var(--bits-floating-anchor-width)",
270
- "--bits-menubar-anchor-height": "var(--bits-floating-anchor-height)",
271
- },
268
+ style: getFloatingContentCSSVars("menubar"),
272
269
  onkeydown: this.onkeydown,
273
270
  "data-menu-content": "",
271
+ [menubarAttrs.content]: "",
274
272
  ...attachRef(this.opts.ref, (v) => (this.menu.contentNode = v)),
275
273
  }));
276
274
  popperProps = {
@@ -17,7 +17,6 @@ declare class MeterRootState {
17
17
  readonly "data-value": number;
18
18
  readonly "data-max": number;
19
19
  readonly "data-min": number;
20
- readonly "data-meter-root": "";
21
20
  };
22
21
  }
23
22
  export declare function useMeterRootState(props: MeterRootStateProps): MeterRootState;
@@ -1,5 +1,9 @@
1
1
  import { attachRef } from "svelte-toolbelt";
2
- const METER_ROOT_ATTR = "data-meter-root";
2
+ import { createBitsAttrs } from "../../internal/attrs.js";
3
+ const meterAttrs = createBitsAttrs({
4
+ component: "meter",
5
+ parts: ["root"],
6
+ });
3
7
  class MeterRootState {
4
8
  opts;
5
9
  constructor(opts) {
@@ -14,7 +18,7 @@ class MeterRootState {
14
18
  "data-value": this.opts.value.current,
15
19
  "data-max": this.opts.max.current,
16
20
  "data-min": this.opts.min.current,
17
- [METER_ROOT_ATTR]: "",
21
+ [meterAttrs.root]: "",
18
22
  ...attachRef(this.opts.ref),
19
23
  }));
20
24
  }
@@ -10,6 +10,7 @@ import { type Direction, type Orientation } from "../../shared/index.js";
10
10
  import type { BitsFocusEvent, BitsKeyboardEvent, BitsMouseEvent, BitsPointerEvent } from "../../internal/types.js";
11
11
  import { useRovingFocus } from "../../internal/use-roving-focus.svelte.js";
12
12
  import type { FocusEventHandler, KeyboardEventHandler, MouseEventHandler, PointerEventHandler } from "svelte/elements";
13
+ declare const navigationMenuAttrs: import("../../internal/attrs.js").BitsAttrs<readonly ["root", "sub", "item", "list", "trigger", "content", "link", "viewport", "menu", "indicator"]>;
13
14
  type NavigationMenuProviderStateProps = ReadableBoxedValues<{
14
15
  dir: Direction;
15
16
  orientation: Orientation;
@@ -62,8 +63,6 @@ declare class NavigationMenuRootState {
62
63
  readonly id: string;
63
64
  readonly "data-orientation": "horizontal" | "vertical";
64
65
  readonly dir: Direction;
65
- readonly "data-navigation-menu-root": "";
66
- readonly "data-navigation-menu": "";
67
66
  };
68
67
  }
69
68
  type NavigationMenuSubStateProps = WithRefProps<WritableBoxedValues<{
@@ -81,8 +80,6 @@ declare class NavigationMenuSubState {
81
80
  props: {
82
81
  readonly id: string;
83
82
  readonly "data-orientation": "horizontal" | "vertical";
84
- readonly "data-navigation-menu-sub": "";
85
- readonly "data-navigation-menu": "";
86
83
  };
87
84
  }
88
85
  type NavigationMenuListStateProps = WithRefProps;
@@ -102,7 +99,6 @@ declare class NavigationMenuListState {
102
99
  props: {
103
100
  readonly id: string;
104
101
  readonly "data-orientation": "horizontal" | "vertical";
105
- readonly "data-navigation-menu-list": "";
106
102
  };
107
103
  }
108
104
  type NavigationMenuItemStateProps = WithRefProps<ReadableBoxedValues<{
@@ -132,8 +128,8 @@ export declare class NavigationMenuItemState {
132
128
  onRootContentClose: () => void;
133
129
  onContentFocusOutside: () => void;
134
130
  props: {
131
+ readonly [navigationMenuAttrs.item]: "";
135
132
  readonly id: string;
136
- readonly "data-navigation-menu-item": "";
137
133
  };
138
134
  }
139
135
  type NavigationMenuTriggerStateProps = WithRefProps & ReadableBoxedValues<{
@@ -170,7 +166,6 @@ declare class NavigationMenuTriggerState {
170
166
  readonly "data-value": string;
171
167
  readonly "aria-expanded": "true" | "false";
172
168
  readonly "aria-controls": string | undefined;
173
- readonly "data-navigation-menu-trigger": "";
174
169
  readonly onpointermove: PointerEventHandler<HTMLElement>;
175
170
  readonly onpointerleave: PointerEventHandler<HTMLElement>;
176
171
  readonly onpointerenter: (_: BitsPointerEvent<HTMLButtonElement>) => void;
@@ -219,7 +214,6 @@ declare class NavigationMenuLinkState {
219
214
  readonly onblur: (_: BitsFocusEvent) => void;
220
215
  readonly onpointerenter: PointerEventHandler<HTMLAnchorElement>;
221
216
  readonly onpointermove: PointerEventHandler<HTMLElement>;
222
- readonly "data-navigation-menu-link": "";
223
217
  };
224
218
  }
225
219
  type NavigationMenuIndicatorStateProps = WithRefProps;
@@ -260,7 +254,6 @@ declare class NavigationMenuIndicatorImplState {
260
254
  readonly transform: string;
261
255
  readonly position: "absolute";
262
256
  };
263
- readonly "data-navigation-menu-indicator": "";
264
257
  };
265
258
  }
266
259
  type NavigationMenuContentStateProps = WithRefProps;
@@ -308,7 +301,6 @@ declare class NavigationMenuContentImplState {
308
301
  readonly "data-orientation": "horizontal" | "vertical";
309
302
  readonly "data-state": "open" | "closed";
310
303
  readonly onkeydown: (e: BitsKeyboardEvent) => void;
311
- readonly "data-navigation-menu-content": "";
312
304
  };
313
305
  }
314
306
  declare class NavigationMenuViewportState {
@@ -334,7 +326,6 @@ declare class NavigationMenuViewportState {
334
326
  readonly "--bits-navigation-menu-viewport-width": string | undefined;
335
327
  readonly "--bits-navigation-menu-viewport-height": string | undefined;
336
328
  };
337
- readonly "data-navigation-menu-viewport": "";
338
329
  readonly onpointerenter: () => void;
339
330
  readonly onpointerleave: () => void;
340
331
  };
@@ -7,7 +7,7 @@ import { Context, useDebounce, watch } from "runed";
7
7
  import { untrack } from "svelte";
8
8
  import { SvelteMap } from "svelte/reactivity";
9
9
  import { useId } from "../../shared/index.js";
10
- import { getAriaExpanded, getDataDisabled, getDataOpenClosed, getDataOrientation, } from "../../internal/attrs.js";
10
+ import { createBitsAttrs, getAriaExpanded, getDataDisabled, getDataOpenClosed, getDataOrientation, } from "../../internal/attrs.js";
11
11
  import { noop } from "../../internal/noop.js";
12
12
  import { getTabbableCandidates } from "../../internal/focus.js";
13
13
  import { kbd } from "../../internal/kbd.js";
@@ -17,16 +17,21 @@ import { useArrowNavigation } from "../../internal/use-arrow-navigation.js";
17
17
  import { boxAutoReset } from "../../internal/box-auto-reset.svelte.js";
18
18
  import { useResizeObserver } from "../../internal/use-resize-observer.svelte.js";
19
19
  import { isElement } from "../../internal/is.js";
20
- const NAVIGATION_MENU_ROOT_ATTR = "data-navigation-menu-root";
21
- const NAVIGATION_MENU_ATTR = "data-navigation-menu";
22
- const NAVIGATION_MENU_SUB_ATTR = "data-navigation-menu-sub";
23
- const NAVIGATION_MENU_ITEM_ATTR = "data-navigation-menu-item";
24
- const NAVIGATION_MENU_INDICATOR_ATTR = "data-navigation-menu-indicator";
25
- const NAVIGATION_MENU_LIST_ATTR = "data-navigation-menu-list";
26
- const NAVIGATION_MENU_TRIGGER_ATTR = "data-navigation-menu-trigger";
27
- const NAVIGATION_MENU_CONTENT_ATTR = "data-navigation-menu-content";
28
- const NAVIGATION_MENU_LINK_ATTR = "data-navigation-menu-link";
29
- const NAVIGATION_MENU_VIEWPORT_ATTR = "data-navigation-menu-viewport";
20
+ const navigationMenuAttrs = createBitsAttrs({
21
+ component: "navigation-menu",
22
+ parts: [
23
+ "root",
24
+ "sub",
25
+ "item",
26
+ "list",
27
+ "trigger",
28
+ "content",
29
+ "link",
30
+ "viewport",
31
+ "menu",
32
+ "indicator",
33
+ ],
34
+ });
30
35
  class NavigationMenuProviderState {
31
36
  opts;
32
37
  indicatorTrackRef = box(null);
@@ -135,8 +140,8 @@ class NavigationMenuRootState {
135
140
  id: this.opts.id.current,
136
141
  "data-orientation": getDataOrientation(this.opts.orientation.current),
137
142
  dir: this.opts.dir.current,
138
- [NAVIGATION_MENU_ROOT_ATTR]: "",
139
- [NAVIGATION_MENU_ATTR]: "",
143
+ [navigationMenuAttrs.root]: "",
144
+ [navigationMenuAttrs.menu]: "",
140
145
  ...attachRef(this.opts.ref),
141
146
  }));
142
147
  }
@@ -173,8 +178,8 @@ class NavigationMenuSubState {
173
178
  props = $derived.by(() => ({
174
179
  id: this.opts.id.current,
175
180
  "data-orientation": getDataOrientation(this.opts.orientation.current),
176
- [NAVIGATION_MENU_SUB_ATTR]: "",
177
- [NAVIGATION_MENU_ATTR]: "",
181
+ [navigationMenuAttrs.sub]: "",
182
+ [navigationMenuAttrs.menu]: "",
178
183
  ...attachRef(this.opts.ref),
179
184
  }));
180
185
  }
@@ -191,7 +196,7 @@ class NavigationMenuListState {
191
196
  this.context = context;
192
197
  this.rovingFocusGroup = useRovingFocus({
193
198
  rootNode: opts.ref,
194
- candidateSelector: `[${NAVIGATION_MENU_TRIGGER_ATTR}]:not([data-disabled]), [${NAVIGATION_MENU_LINK_ATTR}]:not([data-disabled])`,
199
+ candidateSelector: `${navigationMenuAttrs.selector("trigger")}:not([data-disabled]), ${navigationMenuAttrs.selector("link")}:not([data-disabled])`,
195
200
  loop: box.with(() => false),
196
201
  orientation: this.context.opts.orientation,
197
202
  });
@@ -210,7 +215,7 @@ class NavigationMenuListState {
210
215
  props = $derived.by(() => ({
211
216
  id: this.opts.id.current,
212
217
  "data-orientation": getDataOrientation(this.context.opts.orientation.current),
213
- [NAVIGATION_MENU_LIST_ATTR]: "",
218
+ [navigationMenuAttrs.list]: "",
214
219
  ...attachRef(this.opts.ref),
215
220
  }));
216
221
  }
@@ -254,7 +259,7 @@ export class NavigationMenuItemState {
254
259
  onContentFocusOutside = this.#handleContentExit;
255
260
  props = $derived.by(() => ({
256
261
  id: this.opts.id.current,
257
- [NAVIGATION_MENU_ITEM_ATTR]: "",
262
+ [navigationMenuAttrs.item]: "",
258
263
  }));
259
264
  }
260
265
  class NavigationMenuTriggerState {
@@ -347,7 +352,7 @@ class NavigationMenuTriggerState {
347
352
  "data-value": this.itemContext.opts.value.current,
348
353
  "aria-expanded": getAriaExpanded(this.open),
349
354
  "aria-controls": this.itemContext.contentId,
350
- [NAVIGATION_MENU_TRIGGER_ATTR]: "",
355
+ [navigationMenuAttrs.trigger]: "",
351
356
  onpointermove: this.onpointermove,
352
357
  onpointerleave: this.onpointerleave,
353
358
  onpointerenter: this.onpointerenter,
@@ -428,7 +433,7 @@ class NavigationMenuLinkState {
428
433
  onblur: this.onblur,
429
434
  onpointerenter: this.onpointerenter,
430
435
  onpointermove: this.onpointermove,
431
- [NAVIGATION_MENU_LINK_ATTR]: "",
436
+ [navigationMenuAttrs.link]: "",
432
437
  ...attachRef(this.opts.ref),
433
438
  }));
434
439
  }
@@ -489,7 +494,7 @@ class NavigationMenuIndicatorImplState {
489
494
  transform: `translateY(${this.position?.offset}px)`,
490
495
  }),
491
496
  },
492
- [NAVIGATION_MENU_INDICATOR_ATTR]: "",
497
+ [navigationMenuAttrs.indicator]: "",
493
498
  ...attachRef(this.opts.ref),
494
499
  }));
495
500
  }
@@ -632,7 +637,7 @@ class NavigationMenuContentImplState {
632
637
  const target = e.target;
633
638
  if (!isElement(target))
634
639
  return;
635
- if (target.closest(`[${NAVIGATION_MENU_ATTR}]`) !==
640
+ if (target.closest(navigationMenuAttrs.selector("menu")) !==
636
641
  this.context.opts.rootNavigationMenuRef.current)
637
642
  return;
638
643
  const isMetaKey = e.altKey || e.ctrlKey || e.metaKey;
@@ -669,7 +674,7 @@ class NavigationMenuContentImplState {
669
674
  return;
670
675
  const newSelectedElement = useArrowNavigation(e, activeEl, undefined, {
671
676
  itemsArray: candidates,
672
- attributeName: `[${NAVIGATION_MENU_LINK_ATTR}]`,
677
+ candidateSelector: navigationMenuAttrs.selector("link"),
673
678
  loop: false,
674
679
  enableIgnoredElement: true,
675
680
  });
@@ -688,7 +693,7 @@ class NavigationMenuContentImplState {
688
693
  "data-orientation": getDataOrientation(this.context.opts.orientation.current),
689
694
  "data-state": getDataOpenClosed(this.context.opts.value.current === this.itemContext.opts.value.current),
690
695
  onkeydown: this.onkeydown,
691
- [NAVIGATION_MENU_CONTENT_ATTR]: "",
696
+ [navigationMenuAttrs.content]: "",
692
697
  ...attachRef(this.opts.ref),
693
698
  }));
694
699
  }
@@ -745,7 +750,7 @@ class NavigationMenuViewportState {
745
750
  "--bits-navigation-menu-viewport-width": this.viewportWidth,
746
751
  "--bits-navigation-menu-viewport-height": this.viewportHeight,
747
752
  },
748
- [NAVIGATION_MENU_VIEWPORT_ATTR]: "",
753
+ [navigationMenuAttrs.viewport]: "",
749
754
  onpointerenter: this.context.onContentEnter,
750
755
  onpointerleave: this.context.onContentLeave,
751
756
  ...attachRef(this.opts.ref, (v) => (this.context.viewportRef.current = v)),
@@ -38,7 +38,6 @@ declare class PaginationRootState {
38
38
  props: {
39
39
  readonly id: string;
40
40
  readonly "data-orientation": "horizontal" | "vertical";
41
- readonly "data-pagination-root": "";
42
41
  };
43
42
  }
44
43
  type PaginationPageStateProps = WithRefProps<ReadableBoxedValues<{
@@ -57,7 +56,6 @@ declare class PaginationPageState {
57
56
  readonly "aria-label": `Page ${number}`;
58
57
  readonly "data-value": `${number}`;
59
58
  readonly "data-selected": "" | undefined;
60
- readonly "data-pagination-page": "";
61
59
  readonly onclick: (e: BitsMouseEvent) => void;
62
60
  readonly onkeydown: (e: BitsKeyboardEvent) => void;
63
61
  };
@@ -76,8 +74,6 @@ declare class PaginationButtonState {
76
74
  onkeydown(e: BitsKeyboardEvent): void;
77
75
  props: {
78
76
  readonly id: string;
79
- readonly "data-pagination-prev": "" | undefined;
80
- readonly "data-pagination-next": "" | undefined;
81
77
  readonly disabled: boolean;
82
78
  readonly onclick: (e: BitsMouseEvent) => void;
83
79
  readonly onkeydown: (e: BitsKeyboardEvent) => void;
@@ -1,14 +1,14 @@
1
1
  import { attachRef } from "svelte-toolbelt";
2
2
  import { Context } from "runed";
3
- import { getDataOrientation } from "../../internal/attrs.js";
3
+ import { createBitsAttrs, getDataOrientation } from "../../internal/attrs.js";
4
4
  import { getElemDirection } from "../../internal/locale.js";
5
5
  import { kbd } from "../../internal/kbd.js";
6
6
  import { getDirectionalKeys } from "../../internal/get-directional-keys.js";
7
7
  import { useId } from "../../shared/index.js";
8
- const PAGINATION_ROOT_ATTR = "data-pagination-root";
9
- const PAGINATION_PAGE_ATTR = "data-pagination-page";
10
- const PAGINATION_PREV_ATTR = "data-pagination-prev";
11
- const PAGINATION_NEXT_ATTR = "data-pagination-next";
8
+ const paginationAttrs = createBitsAttrs({
9
+ component: "pagination",
10
+ parts: ["root", "page", "prev", "next"],
11
+ });
12
12
  class PaginationRootState {
13
13
  opts;
14
14
  totalPages = $derived.by(() => {
@@ -42,7 +42,7 @@ class PaginationRootState {
42
42
  const node = this.opts.ref.current;
43
43
  if (!node)
44
44
  return;
45
- return node.querySelector(`[data-pagination-${type}]`);
45
+ return node.querySelector(paginationAttrs.selector(type));
46
46
  }
47
47
  hasPrevPage = $derived.by(() => this.opts.page.current > 1);
48
48
  hasNextPage = $derived.by(() => this.opts.page.current < this.totalPages);
@@ -60,7 +60,7 @@ class PaginationRootState {
60
60
  props = $derived.by(() => ({
61
61
  id: this.opts.id.current,
62
62
  "data-orientation": getDataOrientation(this.opts.orientation.current),
63
- [PAGINATION_ROOT_ATTR]: "",
63
+ [paginationAttrs.root]: "",
64
64
  ...attachRef(this.opts.ref),
65
65
  }));
66
66
  }
@@ -95,7 +95,7 @@ class PaginationPageState {
95
95
  "aria-label": `Page ${this.opts.page.current.value}`,
96
96
  "data-value": `${this.opts.page.current.value}`,
97
97
  "data-selected": this.#isSelected ? "" : undefined,
98
- [PAGINATION_PAGE_ATTR]: "",
98
+ [paginationAttrs.page]: "",
99
99
  //
100
100
  onclick: this.onclick,
101
101
  onkeydown: this.onkeydown,
@@ -141,8 +141,7 @@ class PaginationButtonState {
141
141
  }
142
142
  props = $derived.by(() => ({
143
143
  id: this.opts.id.current,
144
- [PAGINATION_PREV_ATTR]: this.opts.type === "prev" ? "" : undefined,
145
- [PAGINATION_NEXT_ATTR]: this.opts.type === "next" ? "" : undefined,
144
+ [paginationAttrs[this.opts.type]]: "",
146
145
  disabled: this.#isDisabled,
147
146
  //
148
147
  onclick: this.onclick,
@@ -27,7 +27,6 @@ declare class PinInputRootState {
27
27
  onkeydown: (e: BitsKeyboardEvent) => void;
28
28
  rootProps: {
29
29
  readonly id: string;
30
- readonly "data-pin-input-root": "";
31
30
  readonly style: {
32
31
  position: string;
33
32
  cursor: string;
@@ -108,7 +107,6 @@ declare class PinInputCellState {
108
107
  constructor(opts: PinInputCellStateProps);
109
108
  props: {
110
109
  readonly id: string;
111
- readonly "data-pin-input-cell": "";
112
110
  readonly "data-active": "" | undefined;
113
111
  readonly "data-inactive": "" | undefined;
114
112
  };