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 type { BitsFocusEvent, BitsKeyboardEvent, BitsMouseEvent, WithRefProps }
7
7
  import type { DateAndTimeSegmentObj, DateOnInvalid, DateSegmentObj, DateSegmentPart, DateValidator, Granularity, HourCycle, SegmentPart, SegmentValueObj, TimeSegmentObj, EditableTimeSegmentPart } from "../../shared/date/types.js";
8
8
  import { type Formatter } from "../../internal/date-time/formatter.js";
9
9
  import { type Announcer } from "../../internal/date-time/announcer.js";
10
- export declare const DATE_FIELD_INPUT_ATTR = "data-date-field-input";
10
+ export declare const dateFieldAttrs: import("../../internal/attrs.js").BitsAttrs<readonly ["input", "label", "segment"]>;
11
11
  type SegmentConfig = {
12
12
  min: number | ((root: DateFieldRootState) => number);
13
13
  max: number | ((root: DateFieldRootState) => number);
@@ -138,6 +138,7 @@ export declare class DateFieldRootState {
138
138
  updateSegment<T extends keyof DateAndTimeSegmentObj>(part: T, cb: T extends DateSegmentPart ? Updater<DateSegmentObj[T]> : T extends EditableTimeSegmentPart ? Updater<TimeSegmentObj[T]> : Updater<DateAndTimeSegmentObj[T]>): void;
139
139
  handleSegmentClick(e: BitsMouseEvent): void;
140
140
  getBaseSegmentAttrs(part: SegmentPart, segmentId: string): {
141
+ [dateFieldAttrs.segment]: string;
141
142
  "aria-invalid": "true" | undefined;
142
143
  "aria-disabled": "true" | "false";
143
144
  "aria-readonly": "true" | "false";
@@ -176,7 +177,6 @@ export declare class DateFieldInputState {
176
177
  readonly "aria-disabled": "true" | "false";
177
178
  readonly "data-invalid": "" | undefined;
178
179
  readonly "data-disabled": "" | undefined;
179
- readonly "data-date-field-input": "";
180
180
  };
181
181
  }
182
182
  declare class DateFieldHiddenInputState {
@@ -200,7 +200,6 @@ declare class DateFieldLabelState {
200
200
  readonly id: string;
201
201
  readonly "data-invalid": "" | undefined;
202
202
  readonly "data-disabled": "" | undefined;
203
- readonly "data-date-field-label": "";
204
203
  readonly onclick: (_: BitsMouseEvent) => void;
205
204
  };
206
205
  }
@@ -415,7 +414,6 @@ declare class DateFieldTimeZoneSegmentState {
415
414
  readonly caretColor: "transparent";
416
415
  };
417
416
  readonly onkeydown: (e: BitsKeyboardEvent) => void;
418
- readonly tabindex: 0;
419
417
  } | {
420
418
  readonly "data-readonly": "" | undefined;
421
419
  readonly "aria-labelledby": string;
@@ -1,7 +1,7 @@
1
1
  import { box, onDestroyEffect, attachRef, DOMContext } from "svelte-toolbelt";
2
2
  import { onMount, untrack } from "svelte";
3
3
  import { Context, watch } from "runed";
4
- import { getAriaDisabled, getAriaHidden, getAriaInvalid, getAriaReadonly, getDataDisabled, getDataInvalid, getDataReadonly, } from "../../internal/attrs.js";
4
+ import { createBitsAttrs, getAriaDisabled, getAriaHidden, getAriaInvalid, getAriaReadonly, getDataDisabled, getDataInvalid, getDataReadonly, } from "../../internal/attrs.js";
5
5
  import { isBrowser, isNumberString } from "../../internal/is.js";
6
6
  import { kbd } from "../../internal/kbd.js";
7
7
  import { useId } from "../../internal/use-id.js";
@@ -11,8 +11,10 @@ import { areAllSegmentsFilled, createContent, getValueFromSegments, inferGranula
11
11
  import { DATE_SEGMENT_PARTS, EDITABLE_TIME_SEGMENT_PARTS, } from "../../internal/date-time/field/parts.js";
12
12
  import { getDaysInMonth, isBefore, toDate } from "../../internal/date-time/utils.js";
13
13
  import { getFirstSegment, handleSegmentNavigation, isSegmentNavigationKey, moveToNextSegment, moveToPrevSegment, } from "../../internal/date-time/field/segments.js";
14
- export const DATE_FIELD_INPUT_ATTR = "data-date-field-input";
15
- const DATE_FIELD_LABEL_ATTR = "data-date-field-label";
14
+ export const dateFieldAttrs = createBitsAttrs({
15
+ component: "date-field",
16
+ parts: ["input", "label", "segment"],
17
+ });
16
18
  const SEGMENT_CONFIGS = {
17
19
  day: {
18
20
  min: 1,
@@ -535,6 +537,7 @@ export class DateFieldRootState {
535
537
  "data-disabled": getDataDisabled(this.disabled.current),
536
538
  "data-readonly": getDataReadonly(this.readonly.current || inReadonlySegments),
537
539
  "data-segment": `${part}`,
540
+ [dateFieldAttrs.segment]: "",
538
541
  };
539
542
  if (part === "literal")
540
543
  return defaultAttrs;
@@ -585,7 +588,7 @@ export class DateFieldInputState {
585
588
  "aria-disabled": getAriaDisabled(this.root.disabled.current),
586
589
  "data-invalid": this.root.isInvalid ? "" : undefined,
587
590
  "data-disabled": getDataDisabled(this.root.disabled.current),
588
- [DATE_FIELD_INPUT_ATTR]: "",
591
+ [dateFieldAttrs.input]: "",
589
592
  ...attachRef(this.opts.ref, (v) => this.root.setFieldNode(v)),
590
593
  }));
591
594
  }
@@ -624,7 +627,7 @@ class DateFieldLabelState {
624
627
  id: this.opts.id.current,
625
628
  "data-invalid": getDataInvalid(this.root.isInvalid),
626
629
  "data-disabled": getDataDisabled(this.root.disabled.current),
627
- [DATE_FIELD_LABEL_ATTR]: "",
630
+ [dateFieldAttrs.label]: "",
628
631
  onclick: this.onclick,
629
632
  ...attachRef(this.opts.ref, (v) => this.root.setLabelNode(v)),
630
633
  }));
@@ -1173,7 +1176,6 @@ class DateFieldTimeZoneSegmentState {
1173
1176
  caretColor: "transparent",
1174
1177
  },
1175
1178
  onkeydown: this.onkeydown,
1176
- tabindex: 0,
1177
1179
  ...this.root.getBaseSegmentAttrs("timeZoneName", this.opts.id.current),
1178
1180
  "data-readonly": getDataReadonly(true),
1179
1181
  ...attachRef(this.opts.ref),
@@ -2,7 +2,7 @@
2
2
  import { mergeProps } from "svelte-toolbelt";
3
3
  import type { DatePickerTriggerProps } from "../types.js";
4
4
  import PopoverTrigger from "../../popover/components/popover-trigger.svelte";
5
- import { DATE_FIELD_INPUT_ATTR } from "../../date-field/date-field.svelte.js";
5
+ import { dateFieldAttrs } from "../../date-field/date-field.svelte.js";
6
6
  import {
7
7
  handleSegmentNavigation,
8
8
  isSegmentNavigationKey,
@@ -14,7 +14,7 @@
14
14
  if (isSegmentNavigationKey(e.key)) {
15
15
  const currNode = e.currentTarget as HTMLElement;
16
16
  const dateFieldInputNode = currNode.closest(
17
- `[${DATE_FIELD_INPUT_ATTR}]`
17
+ dateFieldAttrs.selector("input")
18
18
  ) as HTMLElement;
19
19
  if (!dateFieldInputNode) return;
20
20
  handleSegmentNavigation(e, dateFieldInputNode);
@@ -8,7 +8,7 @@ import type { DateOnInvalid, DateRange, DateRangeValidator, SegmentPart } from "
8
8
  import type { WithRefProps } from "../../internal/types.js";
9
9
  import type { Granularity } from "../../shared/date/types.js";
10
10
  import { type Formatter } from "../../internal/date-time/formatter.js";
11
- export declare const DATE_RANGE_FIELD_ROOT_ATTR = "data-date-range-field-root";
11
+ export declare const dateRangeFieldAttrs: import("../../internal/attrs.js").BitsAttrs<readonly ["root", "label"]>;
12
12
  type DateRangeFieldRootStateProps = WithRefProps<WritableBoxedValues<{
13
13
  value: DateRange;
14
14
  placeholder: DateValue;
@@ -58,7 +58,6 @@ export declare class DateRangeFieldRootState {
58
58
  props: {
59
59
  readonly id: string;
60
60
  readonly role: "group";
61
- readonly "data-date-range-field-root": "";
62
61
  readonly "data-invalid": "" | undefined;
63
62
  };
64
63
  }
@@ -72,7 +71,6 @@ declare class DateRangeFieldLabelState {
72
71
  readonly id: string;
73
72
  readonly "data-invalid": "" | undefined;
74
73
  readonly "data-disabled": "" | undefined;
75
- readonly "data-date-range-field-label": "";
76
74
  readonly onclick: () => void;
77
75
  };
78
76
  }
@@ -2,13 +2,15 @@ import { box, onDestroyEffect, attachRef, DOMContext } from "svelte-toolbelt";
2
2
  import { Context, watch } from "runed";
3
3
  import { DateFieldInputState, useDateFieldRoot } from "../date-field/date-field.svelte.js";
4
4
  import { useId } from "../../internal/use-id.js";
5
- import { getDataDisabled, getDataInvalid } from "../../internal/attrs.js";
5
+ import { createBitsAttrs, getDataDisabled, getDataInvalid } from "../../internal/attrs.js";
6
6
  import { createFormatter } from "../../internal/date-time/formatter.js";
7
7
  import { removeDescriptionElement } from "../../internal/date-time/field/helpers.js";
8
8
  import { isBefore } from "../../internal/date-time/utils.js";
9
9
  import { getFirstSegment } from "../../internal/date-time/field/segments.js";
10
- export const DATE_RANGE_FIELD_ROOT_ATTR = "data-date-range-field-root";
11
- const DATE_RANGE_FIELD_LABEL_ATTR = "data-date-range-field-label";
10
+ export const dateRangeFieldAttrs = createBitsAttrs({
11
+ component: "date-range-field",
12
+ parts: ["root", "label"],
13
+ });
12
14
  export class DateRangeFieldRootState {
13
15
  opts;
14
16
  startFieldState = undefined;
@@ -130,7 +132,7 @@ export class DateRangeFieldRootState {
130
132
  props = $derived.by(() => ({
131
133
  id: this.opts.id.current,
132
134
  role: "group",
133
- [DATE_RANGE_FIELD_ROOT_ATTR]: "",
135
+ [dateRangeFieldAttrs.root]: "",
134
136
  "data-invalid": getDataInvalid(this.isInvalid),
135
137
  ...attachRef(this.opts.ref, (v) => (this.fieldNode = v)),
136
138
  }));
@@ -155,7 +157,7 @@ class DateRangeFieldLabelState {
155
157
  // TODO: invalid state for field
156
158
  "data-invalid": getDataInvalid(this.root.isInvalid),
157
159
  "data-disabled": getDataDisabled(this.root.opts.disabled.current),
158
- [DATE_RANGE_FIELD_LABEL_ATTR]: "",
160
+ [dateRangeFieldAttrs.label]: "",
159
161
  onclick: this.#onclick,
160
162
  ...attachRef(this.opts.ref, (v) => (this.root.labelNode = v)),
161
163
  }));
@@ -2,7 +2,7 @@
2
2
  import { mergeProps } from "svelte-toolbelt";
3
3
  import type { DateRangePickerTriggerProps } from "../types.js";
4
4
  import PopoverTrigger from "../../popover/components/popover-trigger.svelte";
5
- import { DATE_RANGE_FIELD_ROOT_ATTR } from "../../date-range-field/date-range-field.svelte.js";
5
+ import { dateRangeFieldAttrs } from "../../date-range-field/date-range-field.svelte.js";
6
6
  import {
7
7
  handleSegmentNavigation,
8
8
  isSegmentNavigationKey,
@@ -14,7 +14,7 @@
14
14
  if (isSegmentNavigationKey(e.key)) {
15
15
  const currNode = e.currentTarget as HTMLElement;
16
16
  const dateFieldInputNode = currNode.closest(
17
- `[${DATE_RANGE_FIELD_ROOT_ATTR}]`
17
+ dateRangeFieldAttrs.selector("root")
18
18
  ) as HTMLElement;
19
19
  if (!dateFieldInputNode) return;
20
20
  handleSegmentNavigation(e, dateFieldInputNode);
@@ -1,6 +1,7 @@
1
1
  import type { ReadableBoxedValues, WritableBoxedValues } from "../../internal/box.svelte.js";
2
2
  import type { BitsKeyboardEvent, BitsMouseEvent, WithRefProps } from "../../internal/types.js";
3
3
  type DialogVariant = "alert-dialog" | "dialog";
4
+ declare const dialogAttrs: import("../../internal/attrs.js").BitsAttrs<readonly ["content", "trigger", "overlay", "title", "description", "close", "cancel", "action"]>;
4
5
  type DialogRootStateProps = WritableBoxedValues<{
5
6
  open: boolean;
6
7
  }> & ReadableBoxedValues<{
@@ -16,19 +17,10 @@ declare class DialogRootState {
16
17
  triggerId: string | undefined;
17
18
  descriptionId: string | undefined;
18
19
  cancelNode: HTMLElement | null;
19
- attrs: {
20
- readonly content: "data-dialog-content" | "data-alert-dialog-content";
21
- readonly trigger: "data-dialog-trigger" | "data-alert-dialog-trigger";
22
- readonly overlay: "data-dialog-overlay" | "data-alert-dialog-overlay";
23
- readonly title: "data-dialog-title" | "data-alert-dialog-title";
24
- readonly description: "data-dialog-description" | "data-alert-dialog-description";
25
- readonly close: "data-dialog-close" | "data-alert-dialog-close";
26
- readonly cancel: "data-dialog-cancel" | "data-alert-dialog-cancel";
27
- readonly action: "data-dialog-action" | "data-alert-dialog-action";
28
- };
29
20
  constructor(opts: DialogRootStateProps);
30
21
  handleOpen(): void;
31
22
  handleClose(): void;
23
+ getBitsAttr: typeof dialogAttrs.getAttr;
32
24
  sharedProps: {
33
25
  readonly "data-state": "open" | "closed";
34
26
  };
@@ -58,7 +50,6 @@ type DialogCloseStateProps = WithRefProps & ReadableBoxedValues<{
58
50
  disabled: boolean;
59
51
  }>;
60
52
  declare class DialogCloseState {
61
- #private;
62
53
  readonly opts: DialogCloseStateProps;
63
54
  readonly root: DialogRootState;
64
55
  constructor(opts: DialogCloseStateProps, root: DialogRootState);
@@ -75,7 +66,6 @@ declare class DialogCloseState {
75
66
  }
76
67
  type DialogActionStateProps = WithRefProps;
77
68
  declare class DialogActionState {
78
- #private;
79
69
  readonly opts: DialogActionStateProps;
80
70
  readonly root: DialogRootState;
81
71
  constructor(opts: DialogActionStateProps, root: DialogRootState);
@@ -1,20 +1,12 @@
1
1
  import { attachRef } from "svelte-toolbelt";
2
2
  import { Context } from "runed";
3
- import { getAriaExpanded, getDataOpenClosed } from "../../internal/attrs.js";
3
+ import { createBitsAttrs, getAriaExpanded, getDataOpenClosed } from "../../internal/attrs.js";
4
4
  import { kbd } from "../../internal/kbd.js";
5
5
  import { untrack } from "svelte";
6
- function createAttrs(variant) {
7
- return {
8
- content: `data-${variant}-content`,
9
- trigger: `data-${variant}-trigger`,
10
- overlay: `data-${variant}-overlay`,
11
- title: `data-${variant}-title`,
12
- description: `data-${variant}-description`,
13
- close: `data-${variant}-close`,
14
- cancel: `data-${variant}-cancel`,
15
- action: `data-${variant}-action`,
16
- };
17
- }
6
+ const dialogAttrs = createBitsAttrs({
7
+ component: "dialog",
8
+ parts: ["content", "trigger", "overlay", "title", "description", "close", "cancel", "action"],
9
+ });
18
10
  class DialogRootState {
19
11
  opts;
20
12
  triggerNode = $state(null);
@@ -25,7 +17,6 @@ class DialogRootState {
25
17
  triggerId = $state(undefined);
26
18
  descriptionId = $state(undefined);
27
19
  cancelNode = $state(null);
28
- attrs = $derived.by(() => createAttrs(this.opts.variant.current));
29
20
  constructor(opts) {
30
21
  this.opts = opts;
31
22
  this.handleOpen = this.handleOpen.bind(this);
@@ -41,6 +32,9 @@ class DialogRootState {
41
32
  return;
42
33
  this.opts.open.current = false;
43
34
  }
35
+ getBitsAttr = (part) => {
36
+ return dialogAttrs.getAttr(part, this.opts.variant.current);
37
+ };
44
38
  sharedProps = $derived.by(() => ({
45
39
  "data-state": getDataOpenClosed(this.opts.open.current),
46
40
  }));
@@ -74,7 +68,7 @@ class DialogTriggerState {
74
68
  "aria-haspopup": "dialog",
75
69
  "aria-expanded": getAriaExpanded(this.root.opts.open.current),
76
70
  "aria-controls": this.root.contentId,
77
- [this.root.attrs.trigger]: "",
71
+ [this.root.getBitsAttr("trigger")]: "",
78
72
  onkeydown: this.onkeydown,
79
73
  onclick: this.onclick,
80
74
  disabled: this.opts.disabled.current ? true : undefined,
@@ -88,7 +82,6 @@ class DialogTriggerState {
88
82
  class DialogCloseState {
89
83
  opts;
90
84
  root;
91
- #attr = $derived.by(() => this.root.attrs[this.opts.variant.current]);
92
85
  constructor(opts, root) {
93
86
  this.opts = opts;
94
87
  this.root = root;
@@ -112,7 +105,7 @@ class DialogCloseState {
112
105
  }
113
106
  props = $derived.by(() => ({
114
107
  id: this.opts.id.current,
115
- [this.#attr]: "",
108
+ [this.root.getBitsAttr(this.opts.variant.current)]: "",
116
109
  onclick: this.onclick,
117
110
  onkeydown: this.onkeydown,
118
111
  disabled: this.opts.disabled.current ? true : undefined,
@@ -124,14 +117,13 @@ class DialogCloseState {
124
117
  class DialogActionState {
125
118
  opts;
126
119
  root;
127
- #attr = $derived.by(() => this.root.attrs.action);
128
120
  constructor(opts, root) {
129
121
  this.opts = opts;
130
122
  this.root = root;
131
123
  }
132
124
  props = $derived.by(() => ({
133
125
  id: this.opts.id.current,
134
- [this.#attr]: "",
126
+ [this.root.getBitsAttr("action")]: "",
135
127
  ...this.root.sharedProps,
136
128
  ...attachRef(this.opts.ref),
137
129
  }));
@@ -147,7 +139,7 @@ class DialogTitleState {
147
139
  id: this.opts.id.current,
148
140
  role: "heading",
149
141
  "aria-level": this.opts.level.current,
150
- [this.root.attrs.title]: "",
142
+ [this.root.getBitsAttr("title")]: "",
151
143
  ...this.root.sharedProps,
152
144
  ...attachRef(this.opts.ref, (v) => (this.root.titleId = v?.id)),
153
145
  }));
@@ -161,7 +153,7 @@ class DialogDescriptionState {
161
153
  }
162
154
  props = $derived.by(() => ({
163
155
  id: this.opts.id.current,
164
- [this.root.attrs.description]: "",
156
+ [this.root.getBitsAttr("description")]: "",
165
157
  ...this.root.sharedProps,
166
158
  ...attachRef(this.opts.ref, (v) => {
167
159
  this.root.descriptionNode = v;
@@ -183,7 +175,7 @@ class DialogContentState {
183
175
  "aria-modal": "true",
184
176
  "aria-describedby": this.root.descriptionId,
185
177
  "aria-labelledby": this.root.titleId,
186
- [this.root.attrs.content]: "",
178
+ [this.root.getBitsAttr("content")]: "",
187
179
  style: {
188
180
  pointerEvents: "auto",
189
181
  outline: this.root.opts.variant.current === "alert-dialog" ? "none" : undefined,
@@ -206,7 +198,7 @@ class DialogOverlayState {
206
198
  snippetProps = $derived.by(() => ({ open: this.root.opts.open.current }));
207
199
  props = $derived.by(() => ({
208
200
  id: this.opts.id.current,
209
- [this.root.attrs.overlay]: "",
201
+ [this.root.getBitsAttr("overlay")]: "",
210
202
  style: {
211
203
  pointerEvents: "auto",
212
204
  },
@@ -240,7 +232,7 @@ class AlertDialogCancelState {
240
232
  }
241
233
  props = $derived.by(() => ({
242
234
  id: this.opts.id.current,
243
- [this.root.attrs.cancel]: "",
235
+ [this.root.getBitsAttr("cancel")]: "",
244
236
  onclick: this.onclick,
245
237
  onkeydown: this.onkeydown,
246
238
  tabindex: 0,
@@ -26,6 +26,7 @@ export { Popover } from "./popover/index.js";
26
26
  export { Progress } from "./progress/index.js";
27
27
  export { RadioGroup } from "./radio-group/index.js";
28
28
  export { RangeCalendar } from "./range-calendar/index.js";
29
+ export { RatingGroup } from "./rating-group/index.js";
29
30
  export { ScrollArea } from "./scroll-area/index.js";
30
31
  export { Select } from "./select/index.js";
31
32
  export { Separator } from "./separator/index.js";
@@ -26,6 +26,7 @@ export { Popover } from "./popover/index.js";
26
26
  export { Progress } from "./progress/index.js";
27
27
  export { RadioGroup } from "./radio-group/index.js";
28
28
  export { RangeCalendar } from "./range-calendar/index.js";
29
+ export { RatingGroup } from "./rating-group/index.js";
29
30
  export { ScrollArea } from "./scroll-area/index.js";
30
31
  export { Select } from "./select/index.js";
31
32
  export { Separator } from "./separator/index.js";
@@ -6,7 +6,6 @@ declare class LabelRootState {
6
6
  onmousedown(e: BitsMouseEvent): void;
7
7
  props: {
8
8
  readonly id: string;
9
- readonly "data-label-root": "";
10
9
  readonly onmousedown: (e: BitsMouseEvent) => void;
11
10
  };
12
11
  }
@@ -1,5 +1,9 @@
1
1
  import { attachRef } from "svelte-toolbelt";
2
- const ROOT_ATTR = "data-label-root";
2
+ import { createBitsAttrs } from "../../internal/attrs.js";
3
+ const labelAttrs = createBitsAttrs({
4
+ component: "label",
5
+ parts: ["root"],
6
+ });
3
7
  class LabelRootState {
4
8
  opts;
5
9
  constructor(opts) {
@@ -12,7 +16,7 @@ class LabelRootState {
12
16
  }
13
17
  props = $derived.by(() => ({
14
18
  id: this.opts.id.current,
15
- [ROOT_ATTR]: "",
19
+ [labelAttrs.root]: "",
16
20
  onmousedown: this.onmousedown,
17
21
  ...attachRef(this.opts.ref),
18
22
  }));
@@ -40,7 +40,6 @@ declare class LinkPreviewTriggerState {
40
40
  readonly "data-state": "open" | "closed";
41
41
  readonly "aria-controls": string | undefined;
42
42
  readonly role: "button";
43
- readonly "data-link-preview-trigger": "";
44
43
  readonly onpointerenter: (e: BitsPointerEvent) => void;
45
44
  readonly onfocus: (e: BitsFocusEvent) => void;
46
45
  readonly onblur: (_: BitsFocusEvent) => void;
@@ -69,7 +68,6 @@ declare class LinkPreviewContentState {
69
68
  readonly id: string;
70
69
  readonly tabindex: -1;
71
70
  readonly "data-state": "open" | "closed";
72
- readonly "data-link-preview-content": "";
73
71
  readonly onpointerdown: (e: BitsPointerEvent) => void;
74
72
  readonly onpointerenter: (e: BitsPointerEvent) => void;
75
73
  readonly onfocusout: (e: BitsFocusEvent) => void;
@@ -1,12 +1,14 @@
1
1
  import { afterSleep, onDestroyEffect, attachRef, DOMContext } from "svelte-toolbelt";
2
2
  import { Context, watch } from "runed";
3
3
  import { on } from "svelte/events";
4
- import { getAriaExpanded, getDataOpenClosed } from "../../internal/attrs.js";
4
+ import { createBitsAttrs, getAriaExpanded, getDataOpenClosed } from "../../internal/attrs.js";
5
5
  import { isElement, isFocusVisible, isTouch } from "../../internal/is.js";
6
6
  import { getTabbableCandidates } from "../../internal/focus.js";
7
7
  import { useGraceArea } from "../../internal/use-grace-area.svelte.js";
8
- const LINK_PREVIEW_CONTENT_ATTR = "data-link-preview-content";
9
- const LINK_PREVIEW_TRIGGER_ATTR = "data-link-preview-trigger";
8
+ const linkPreviewAttrs = createBitsAttrs({
9
+ component: "link-preview",
10
+ parts: ["content", "trigger"],
11
+ });
10
12
  class LinkPreviewRootState {
11
13
  opts;
12
14
  hasSelection = $state(false);
@@ -126,7 +128,7 @@ class LinkPreviewTriggerState {
126
128
  "data-state": getDataOpenClosed(this.root.opts.open.current),
127
129
  "aria-controls": this.root.contentNode?.id,
128
130
  role: "button",
129
- [LINK_PREVIEW_TRIGGER_ATTR]: "",
131
+ [linkPreviewAttrs.trigger]: "",
130
132
  onpointerenter: this.onpointerenter,
131
133
  onfocus: this.onfocus,
132
134
  onblur: this.onblur,
@@ -197,7 +199,7 @@ class LinkPreviewContentState {
197
199
  id: this.opts.id.current,
198
200
  tabindex: -1,
199
201
  "data-state": getDataOpenClosed(this.root.opts.open.current),
200
- [LINK_PREVIEW_CONTENT_ATTR]: "",
202
+ [linkPreviewAttrs.content]: "",
201
203
  onpointerdown: this.onpointerdown,
202
204
  onpointerenter: this.onpointerenter,
203
205
  onfocusout: this.onfocusout,
@@ -54,7 +54,7 @@
54
54
  }
55
55
  }
56
56
 
57
- const dataAttr = $derived(subContentState.parentMenu.root.getAttr("sub-content"));
57
+ const dataAttr = $derived(subContentState.parentMenu.root.getBitsAttr("sub-content"));
58
58
 
59
59
  const mergedProps = $derived(
60
60
  mergeProps(restProps, subContentState.props, {
@@ -55,7 +55,7 @@
55
55
  }
56
56
  }
57
57
 
58
- const dataAttr = $derived(subContentState.parentMenu.root.getAttr("sub-content"));
58
+ const dataAttr = $derived(subContentState.parentMenu.root.getBitsAttr("sub-content"));
59
59
 
60
60
  const mergedProps = $derived(
61
61
  mergeProps(restProps, subContentState.props, {
@@ -17,13 +17,14 @@ export type MenuRootStateProps = ReadableBoxedValues<{
17
17
  onClose: AnyFn;
18
18
  };
19
19
  export declare const MenuOpenEvent: CustomEventDispatcher<unknown>;
20
+ export declare const menuAttrs: import("../../internal/attrs.js").BitsAttrs<readonly ["trigger", "content", "sub-trigger", "item", "group", "group-heading", "checkbox-group", "checkbox-item", "radio-group", "radio-item", "separator", "sub-content", "arrow"]>;
20
21
  declare class MenuRootState {
21
22
  readonly opts: MenuRootStateProps;
22
23
  isUsingKeyboard: IsUsingKeyboard;
23
24
  ignoreCloseAutoFocus: boolean;
24
25
  isPointerInTransit: boolean;
25
26
  constructor(opts: MenuRootStateProps);
26
- getAttr(name: string): string;
27
+ getBitsAttr: typeof menuAttrs.getAttr;
27
28
  }
28
29
  type MenuMenuStateProps = WritableBoxedValues<{
29
30
  open: boolean;