bits-ui 2.2.0 → 2.3.0

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 (36) hide show
  1. package/dist/bits/index.d.ts +1 -0
  2. package/dist/bits/index.js +1 -0
  3. package/dist/bits/rating-group/components/rating-group-input.svelte +10 -0
  4. package/dist/bits/rating-group/components/rating-group-input.svelte.d.ts +18 -0
  5. package/dist/bits/rating-group/components/rating-group-item.svelte +38 -0
  6. package/dist/bits/rating-group/components/rating-group-item.svelte.d.ts +4 -0
  7. package/dist/bits/rating-group/components/rating-group.svelte +80 -0
  8. package/dist/bits/rating-group/components/rating-group.svelte.d.ts +4 -0
  9. package/dist/bits/rating-group/exports.d.ts +3 -0
  10. package/dist/bits/rating-group/exports.js +2 -0
  11. package/dist/bits/rating-group/index.d.ts +1 -0
  12. package/dist/bits/rating-group/index.js +1 -0
  13. package/dist/bits/rating-group/rating-group.svelte.d.ts +114 -0
  14. package/dist/bits/rating-group/rating-group.svelte.js +295 -0
  15. package/dist/bits/rating-group/types.d.ts +111 -0
  16. package/dist/bits/rating-group/types.js +1 -0
  17. package/dist/bits/slider/helpers.js +33 -2
  18. package/dist/bits/tooltip/components/tooltip-content-static.svelte +2 -0
  19. package/dist/bits/tooltip/components/tooltip-content.svelte +2 -0
  20. package/dist/bits/tooltip/components/tooltip-trigger.svelte +1 -1
  21. package/dist/bits/tooltip/components/tooltip.svelte +1 -1
  22. package/dist/bits/tooltip/tooltip.svelte.d.ts +16 -18
  23. package/dist/bits/tooltip/tooltip.svelte.js +3 -1
  24. package/dist/bits/utilities/floating-layer/components/floating-layer-anchor.svelte +9 -6
  25. package/dist/bits/utilities/floating-layer/components/floating-layer-content.svelte +25 -21
  26. package/dist/bits/utilities/floating-layer/components/floating-layer.svelte +2 -2
  27. package/dist/bits/utilities/floating-layer/components/floating-layer.svelte.d.ts +1 -0
  28. package/dist/bits/utilities/floating-layer/types.d.ts +18 -0
  29. package/dist/bits/utilities/floating-layer/use-floating-layer.svelte.d.ts +3 -3
  30. package/dist/bits/utilities/floating-layer/use-floating-layer.svelte.js +13 -9
  31. package/dist/bits/utilities/popper-layer/popper-layer-inner.svelte +2 -0
  32. package/dist/bits/utilities/popper-layer/types.d.ts +9 -0
  33. package/dist/index.d.ts +1 -1
  34. package/dist/index.js +1 -1
  35. package/dist/types.d.ts +1 -0
  36. package/package.json +1 -1
@@ -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";
@@ -0,0 +1,10 @@
1
+ <script lang="ts">
2
+ import { useRatingGroupHiddenInput } from "../rating-group.svelte.js";
3
+ import HiddenInput from "../../utilities/hidden-input.svelte";
4
+
5
+ const inputState = useRatingGroupHiddenInput();
6
+ </script>
7
+
8
+ {#if inputState.shouldRender}
9
+ <HiddenInput {...inputState.props} />
10
+ {/if}
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const RatingGroupInput: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type RatingGroupInput = InstanceType<typeof RatingGroupInput>;
18
+ export default RatingGroupInput;
@@ -0,0 +1,38 @@
1
+ <script lang="ts">
2
+ import { box, mergeProps } from "svelte-toolbelt";
3
+ import type { RatingGroupItemProps } from "../types.js";
4
+ import { useRatingGroupItem } from "../rating-group.svelte.js";
5
+ import { createId } from "../../../internal/create-id.js";
6
+
7
+ const uid = $props.id();
8
+
9
+ let {
10
+ disabled = false,
11
+ index,
12
+ children,
13
+ child,
14
+ ref = $bindable(null),
15
+ id = createId(uid),
16
+ ...restProps
17
+ }: RatingGroupItemProps = $props();
18
+
19
+ const itemState = useRatingGroupItem({
20
+ disabled: box.with(() => Boolean(disabled)),
21
+ index: box.with(() => index),
22
+ id: box.with(() => id),
23
+ ref: box.with(
24
+ () => ref,
25
+ (v) => (ref = v)
26
+ ),
27
+ });
28
+
29
+ const mergedProps = $derived(mergeProps(restProps, itemState.props));
30
+ </script>
31
+
32
+ {#if child}
33
+ {@render child({ props: mergedProps, ...itemState.snippetProps })}
34
+ {:else}
35
+ <div {...mergedProps}>
36
+ {@render children?.(itemState.snippetProps)}
37
+ </div>
38
+ {/if}
@@ -0,0 +1,4 @@
1
+ import type { RatingGroupItemProps } from "../types.js";
2
+ declare const RatingGroupItem: import("svelte").Component<RatingGroupItemProps, {}, "ref">;
3
+ type RatingGroupItem = ReturnType<typeof RatingGroupItem>;
4
+ export default RatingGroupItem;
@@ -0,0 +1,80 @@
1
+ <script lang="ts">
2
+ import { box, mergeProps } from "svelte-toolbelt";
3
+ import type { RatingGroupRootProps } from "../types.js";
4
+ import { useRatingGroupRoot } from "../rating-group.svelte.js";
5
+ import RatingGroupInput from "./rating-group-input.svelte";
6
+ import { createId } from "../../../internal/create-id.js";
7
+ import { noop } from "../../../internal/noop.js";
8
+
9
+ const uid = $props.id();
10
+
11
+ let {
12
+ disabled = false,
13
+ children,
14
+ child,
15
+ value = $bindable(0),
16
+ ref = $bindable(null),
17
+ orientation = "horizontal",
18
+ name = undefined,
19
+ required = false,
20
+ min = 0,
21
+ max = 5,
22
+ allowHalf = false,
23
+ readonly = false,
24
+ id = createId(uid),
25
+ onValueChange = noop,
26
+ "aria-label": ariaLabel,
27
+ "aria-valuetext": ariaValuetextProp,
28
+ hoverPreview = true,
29
+ ...restProps
30
+ }: RatingGroupRootProps = $props();
31
+
32
+ if (value < min || value > max) {
33
+ value = Math.max(min, Math.min(max, value));
34
+ }
35
+
36
+ const ariaValuetext: NonNullable<RatingGroupRootProps["aria-valuetext"]> = $derived.by(() => {
37
+ if (ariaValuetextProp) return ariaValuetextProp;
38
+ return (value: number, max: number) => `${value} out of ${max}`;
39
+ });
40
+
41
+ const rootState = useRatingGroupRoot({
42
+ orientation: box.with(() => orientation),
43
+ disabled: box.with(() => disabled),
44
+ name: box.with(() => name),
45
+ required: box.with(() => required),
46
+ min: box.with(() => min),
47
+ max: box.with(() => max),
48
+ allowHalf: box.with(() => allowHalf),
49
+ readonly: box.with(() => readonly),
50
+ id: box.with(() => id),
51
+ value: box.with(
52
+ () => value,
53
+ (v) => {
54
+ if (v === value) return;
55
+ value = v;
56
+ onValueChange?.(v);
57
+ }
58
+ ),
59
+ ref: box.with(
60
+ () => ref,
61
+ (v) => (ref = v)
62
+ ),
63
+ ariaValuetext: box.with(() => ariaValuetext),
64
+ hoverPreview: box.with(() => hoverPreview),
65
+ });
66
+
67
+ const mergedProps = $derived(
68
+ mergeProps(restProps, rootState.props, { "aria-label": ariaLabel })
69
+ );
70
+ </script>
71
+
72
+ {#if child}
73
+ {@render child({ props: mergedProps, ...rootState.snippetProps })}
74
+ {:else}
75
+ <div {...mergedProps}>
76
+ {@render children?.(rootState.snippetProps)}
77
+ </div>
78
+ {/if}
79
+
80
+ <RatingGroupInput />
@@ -0,0 +1,4 @@
1
+ import type { RatingGroupRootProps } from "../types.js";
2
+ declare const RatingGroup: import("svelte").Component<RatingGroupRootProps, {}, "value" | "ref">;
3
+ type RatingGroup = ReturnType<typeof RatingGroup>;
4
+ export default RatingGroup;
@@ -0,0 +1,3 @@
1
+ export { default as Root } from "./components/rating-group.svelte";
2
+ export { default as Item } from "./components/rating-group-item.svelte";
3
+ export type { RatingGroupRootProps as RootProps, RatingGroupItemProps as ItemProps, } from "./types.js";
@@ -0,0 +1,2 @@
1
+ export { default as Root } from "./components/rating-group.svelte";
2
+ export { default as Item } from "./components/rating-group-item.svelte";
@@ -0,0 +1 @@
1
+ export * as RatingGroup from "./exports.js";
@@ -0,0 +1 @@
1
+ export * as RatingGroup from "./exports.js";
@@ -0,0 +1,114 @@
1
+ import { DOMContext } from "svelte-toolbelt";
2
+ import type { ReadableBoxedValues, WritableBoxedValues } from "../../internal/box.svelte.js";
3
+ import type { BitsKeyboardEvent, BitsMouseEvent, BitsPointerEvent, WithRefProps } from "../../internal/types.js";
4
+ import type { RatingGroupAriaValuetext, RatingGroupItemState as RatingGroupItemStateType } from "./types.js";
5
+ import type { Orientation } from "../../shared/index.js";
6
+ type RatingGroupRootStateProps = WithRefProps<ReadableBoxedValues<{
7
+ disabled: boolean;
8
+ required: boolean;
9
+ orientation: Orientation;
10
+ name: string | undefined;
11
+ min: number;
12
+ max: number;
13
+ allowHalf: boolean;
14
+ readonly: boolean;
15
+ hoverPreview: boolean;
16
+ ariaValuetext: NonNullable<RatingGroupAriaValuetext>;
17
+ }> & WritableBoxedValues<{
18
+ value: number;
19
+ }>>;
20
+ declare class RatingGroupRootState {
21
+ #private;
22
+ readonly opts: RatingGroupRootStateProps;
23
+ domContext: DOMContext;
24
+ readonly hasValue: boolean;
25
+ readonly valueToUse: number;
26
+ readonly isRTL: boolean;
27
+ readonly ariaValuetext: string;
28
+ readonly items: {
29
+ index: number;
30
+ state: RatingGroupItemStateType;
31
+ }[];
32
+ constructor(opts: RatingGroupRootStateProps);
33
+ isActive(itemIndex: number): boolean;
34
+ isPartial(itemIndex: number): boolean;
35
+ setHoverValue(value: number | null): void;
36
+ setValue(value: number): void;
37
+ calculateRatingFromPointer(itemIndex: number, event: {
38
+ clientX: number;
39
+ clientY: number;
40
+ currentTarget: HTMLElement;
41
+ }): number;
42
+ onpointerleave(): void;
43
+ readonly handlers: Record<string, () => void>;
44
+ onkeydown(e: BitsKeyboardEvent): void;
45
+ readonly snippetProps: {
46
+ items: {
47
+ index: number;
48
+ state: RatingGroupItemStateType;
49
+ }[];
50
+ value: number;
51
+ max: number;
52
+ };
53
+ readonly props: {
54
+ readonly id: string;
55
+ readonly role: "slider";
56
+ readonly "aria-valuenow": number;
57
+ readonly "aria-valuemin": number;
58
+ readonly "aria-valuemax": number;
59
+ readonly "aria-valuetext": string;
60
+ readonly "aria-orientation": Orientation;
61
+ readonly "aria-required": "true" | "false";
62
+ readonly "aria-disabled": "true" | undefined;
63
+ readonly "aria-label": "Rating";
64
+ readonly "data-disabled": "" | undefined;
65
+ readonly "data-readonly": "" | undefined;
66
+ readonly "data-orientation": Orientation;
67
+ readonly tabindex: 0 | -1;
68
+ readonly "data-rating-group-root": "";
69
+ readonly onkeydown: (e: BitsKeyboardEvent) => void;
70
+ readonly onpointerleave: () => void;
71
+ };
72
+ }
73
+ type RatingGroupItemStateProps = WithRefProps<ReadableBoxedValues<{
74
+ disabled: boolean;
75
+ index: number;
76
+ }>>;
77
+ declare class RatingGroupItemState {
78
+ #private;
79
+ readonly opts: RatingGroupItemStateProps;
80
+ readonly root: RatingGroupRootState;
81
+ constructor(opts: RatingGroupItemStateProps, root: RatingGroupRootState);
82
+ onclick(e: BitsMouseEvent): void;
83
+ onpointermove(e: BitsPointerEvent): void;
84
+ readonly snippetProps: {
85
+ readonly state: RatingGroupItemStateType;
86
+ };
87
+ readonly props: {
88
+ readonly id: string;
89
+ readonly role: "presentation";
90
+ readonly "data-value": number;
91
+ readonly "data-orientation": Orientation;
92
+ readonly "data-disabled": "" | undefined;
93
+ readonly "data-readonly": "" | undefined;
94
+ readonly "data-state": RatingGroupItemStateType;
95
+ readonly "data-rating-group-item": "";
96
+ readonly onclick: (e: BitsMouseEvent) => void;
97
+ readonly onpointermove: (e: BitsPointerEvent) => void;
98
+ };
99
+ }
100
+ declare class RatingGroupHiddenInputState {
101
+ readonly root: RatingGroupRootState;
102
+ readonly shouldRender: boolean;
103
+ readonly props: {
104
+ readonly name: string | undefined;
105
+ readonly value: number;
106
+ readonly required: boolean;
107
+ readonly disabled: boolean;
108
+ };
109
+ constructor(root: RatingGroupRootState);
110
+ }
111
+ export declare function useRatingGroupRoot(props: RatingGroupRootStateProps): RatingGroupRootState;
112
+ export declare function useRatingGroupItem(props: RatingGroupItemStateProps): RatingGroupItemState;
113
+ export declare function useRatingGroupHiddenInput(): RatingGroupHiddenInputState;
114
+ export {};
@@ -0,0 +1,295 @@
1
+ import { attachRef, DOMContext } from "svelte-toolbelt";
2
+ import { Context } from "runed";
3
+ import { getAriaRequired, getDataDisabled } from "../../internal/attrs.js";
4
+ import { kbd } from "../../internal/kbd.js";
5
+ const RATING_GROUP_ROOT_ATTR = "data-rating-group-root";
6
+ const RATING_GROUP_ITEM_ATTR = "data-rating-group-item";
7
+ class RatingGroupRootState {
8
+ opts;
9
+ #hoverValue = $state(null);
10
+ #keySequence = $state("");
11
+ #keySequenceTimeout = null;
12
+ domContext;
13
+ hasValue = $derived.by(() => this.opts.value.current > 0);
14
+ valueToUse = $derived.by(() => this.#hoverValue ?? this.opts.value.current);
15
+ isRTL = $derived.by(() => {
16
+ const element = this.opts.ref.current;
17
+ if (!element)
18
+ return false;
19
+ const style = getComputedStyle(element);
20
+ return style.direction === "rtl";
21
+ });
22
+ ariaValuetext = $derived.by(() => {
23
+ return typeof this.opts.ariaValuetext.current === "function"
24
+ ? this.opts.ariaValuetext.current(this.opts.value.current, this.opts.max.current)
25
+ : this.opts.ariaValuetext.current;
26
+ });
27
+ items = $derived.by(() => {
28
+ const { max, allowHalf } = this.opts;
29
+ const value = this.valueToUse;
30
+ return Array.from({ length: max.current }, (_, i) => {
31
+ const itemValue = i + 1;
32
+ const halfValue = itemValue - 0.5;
33
+ const state = value >= itemValue
34
+ ? "active"
35
+ : allowHalf.current && value >= halfValue
36
+ ? "partial"
37
+ : "inactive";
38
+ return { index: i, state };
39
+ });
40
+ });
41
+ constructor(opts) {
42
+ this.opts = opts;
43
+ this.onkeydown = this.onkeydown.bind(this);
44
+ this.onpointerleave = this.onpointerleave.bind(this);
45
+ this.domContext = new DOMContext(this.opts.ref);
46
+ }
47
+ isActive(itemIndex) {
48
+ return this.valueToUse >= itemIndex + 1;
49
+ }
50
+ isPartial(itemIndex) {
51
+ if (!this.opts.allowHalf.current)
52
+ return false;
53
+ const itemValue = itemIndex + 1;
54
+ return this.valueToUse >= itemValue - 0.5 && this.valueToUse < itemValue;
55
+ }
56
+ setHoverValue(value) {
57
+ if (this.opts.readonly.current ||
58
+ this.opts.disabled.current ||
59
+ !this.opts.hoverPreview.current)
60
+ return;
61
+ this.#hoverValue =
62
+ value === null
63
+ ? null
64
+ : Math.max(this.opts.min.current, Math.min(this.opts.max.current, value));
65
+ }
66
+ setValue(value) {
67
+ if (this.opts.readonly.current || this.opts.disabled.current)
68
+ return;
69
+ this.opts.value.current = Math.max(this.opts.min.current, Math.min(this.opts.max.current, value));
70
+ }
71
+ calculateRatingFromPointer(itemIndex, event) {
72
+ const ratingValue = itemIndex + 1;
73
+ if (!this.opts.allowHalf.current)
74
+ return ratingValue;
75
+ const rect = event.currentTarget.getBoundingClientRect();
76
+ const style = getComputedStyle(event.currentTarget);
77
+ const isHorizontal = this.opts.orientation.current === "horizontal";
78
+ const position = isHorizontal
79
+ ? (event.clientX - rect.left) / rect.width
80
+ : (event.clientY - rect.top) / rect.height;
81
+ const normalizedPosition = style.direction === "rtl" ? 1 - position : position;
82
+ return normalizedPosition < 0.5 ? ratingValue - 0.5 : ratingValue;
83
+ }
84
+ onpointerleave() {
85
+ this.setHoverValue(null);
86
+ }
87
+ handlers = {
88
+ [kbd.ARROW_UP]: () => this.#adjustValue(this.opts.allowHalf.current ? 0.5 : 1),
89
+ [kbd.ARROW_RIGHT]: () => {
90
+ const increment = this.opts.allowHalf.current ? 0.5 : 1;
91
+ // in RTL mode, right arrow should decrement
92
+ this.#adjustValue(this.isRTL ? -increment : increment);
93
+ },
94
+ [kbd.ARROW_DOWN]: () => this.#adjustValue(this.opts.allowHalf.current ? -0.5 : -1),
95
+ [kbd.ARROW_LEFT]: () => {
96
+ const increment = this.opts.allowHalf.current ? 0.5 : 1;
97
+ // in RTL mode, left arrow should increment
98
+ this.#adjustValue(this.isRTL ? increment : -increment);
99
+ },
100
+ [kbd.HOME]: () => this.setValue(this.opts.min.current),
101
+ [kbd.END]: () => this.setValue(this.opts.max.current),
102
+ [kbd.PAGE_UP]: () => this.#adjustValue(1),
103
+ [kbd.PAGE_DOWN]: () => this.#adjustValue(-1),
104
+ };
105
+ onkeydown(e) {
106
+ if (this.opts.disabled.current || this.opts.readonly.current)
107
+ return;
108
+ if (this.handlers[e.key]) {
109
+ e.preventDefault();
110
+ this.#clearKeySequence();
111
+ this.handlers[e.key]?.();
112
+ return;
113
+ }
114
+ if (this.opts.allowHalf.current && this.#handleDecimalInput(e))
115
+ return;
116
+ // handle direct number input
117
+ const num = parseInt(e.key || "");
118
+ if (!isNaN(num) && e.key) {
119
+ e.preventDefault();
120
+ if (num >= this.opts.min.current && num <= this.opts.max.current) {
121
+ this.setValue(num);
122
+ if (this.opts.allowHalf.current) {
123
+ this.#startDecimalListening(num);
124
+ }
125
+ }
126
+ return;
127
+ }
128
+ this.#clearKeySequence();
129
+ }
130
+ #adjustValue(delta) {
131
+ this.setValue(this.opts.value.current + delta);
132
+ }
133
+ #handleDecimalInput(e) {
134
+ if (!e.key)
135
+ return false;
136
+ if (e.key === ".") {
137
+ e.preventDefault();
138
+ this.#keySequence += e.key;
139
+ return true;
140
+ }
141
+ if (e.key === "5" && this.#keySequence.match(/^\d+\.$/)) {
142
+ e.preventDefault();
143
+ this.#keySequence += e.key;
144
+ const match = this.#keySequence.match(/^(\d+)\.5$/);
145
+ if (match?.[1]) {
146
+ const value = parseFloat(this.#keySequence);
147
+ if (value >= this.opts.min.current && value <= this.opts.max.current) {
148
+ this.setValue(value);
149
+ this.#clearKeySequence();
150
+ }
151
+ }
152
+ return true;
153
+ }
154
+ return false;
155
+ }
156
+ #startDecimalListening(baseValue) {
157
+ this.#keySequence = baseValue.toString();
158
+ if (this.#keySequenceTimeout) {
159
+ this.domContext.clearTimeout(this.#keySequenceTimeout);
160
+ }
161
+ this.#keySequenceTimeout = this.domContext.setTimeout(() => this.#clearKeySequence(), 1000);
162
+ }
163
+ #clearKeySequence() {
164
+ this.#keySequence = "";
165
+ if (this.#keySequenceTimeout) {
166
+ this.domContext.clearTimeout(this.#keySequenceTimeout);
167
+ this.#keySequenceTimeout = null;
168
+ }
169
+ }
170
+ snippetProps = $derived.by(() => ({
171
+ items: this.items,
172
+ value: this.opts.value.current,
173
+ max: this.opts.max.current,
174
+ }));
175
+ props = $derived.by(() => {
176
+ return {
177
+ id: this.opts.id.current,
178
+ role: "slider",
179
+ "aria-valuenow": this.opts.value.current,
180
+ "aria-valuemin": this.opts.min.current,
181
+ "aria-valuemax": this.opts.max.current,
182
+ "aria-valuetext": this.ariaValuetext,
183
+ "aria-orientation": this.opts.orientation.current,
184
+ "aria-required": getAriaRequired(this.opts.required.current),
185
+ "aria-disabled": this.opts.disabled.current ? "true" : undefined,
186
+ "aria-label": "Rating",
187
+ "data-disabled": getDataDisabled(this.opts.disabled.current),
188
+ "data-readonly": this.opts.readonly.current ? "" : undefined,
189
+ "data-orientation": this.opts.orientation.current,
190
+ tabindex: this.opts.disabled.current ? -1 : 0,
191
+ [RATING_GROUP_ROOT_ATTR]: "",
192
+ onkeydown: this.onkeydown,
193
+ onpointerleave: this.onpointerleave,
194
+ ...attachRef(this.opts.ref),
195
+ };
196
+ });
197
+ }
198
+ class RatingGroupItemState {
199
+ opts;
200
+ root;
201
+ #isDisabled = $derived.by(() => this.opts.disabled.current || this.root.opts.disabled.current);
202
+ #isActive = $derived.by(() => this.root.isActive(this.opts.index.current));
203
+ #isPartial = $derived.by(() => this.root.isPartial(this.opts.index.current));
204
+ #state = $derived.by(() => {
205
+ if (this.#isActive)
206
+ return "active";
207
+ if (this.#isPartial)
208
+ return "partial";
209
+ return "inactive";
210
+ });
211
+ constructor(opts, root) {
212
+ this.opts = opts;
213
+ this.root = root;
214
+ this.onclick = this.onclick.bind(this);
215
+ this.onpointermove = this.onpointermove.bind(this);
216
+ }
217
+ onclick(e) {
218
+ if (this.#isDisabled || this.root.opts.readonly.current)
219
+ return;
220
+ // handle clearing when clicking on first item (index 0) that's already
221
+ // active and min is 0
222
+ if (this.opts.index.current === 0 &&
223
+ this.root.opts.min.current === 0 &&
224
+ this.root.opts.value.current > 0) {
225
+ const newValue = this.root.calculateRatingFromPointer(this.opts.index.current, e);
226
+ const currentValue = this.root.opts.value.current;
227
+ // only clear if the calculated rating exactly matches current value
228
+ if (newValue === currentValue) {
229
+ this.root.setValue(0);
230
+ if (this.root.opts.ref.current) {
231
+ this.root.opts.ref.current.focus();
232
+ }
233
+ return;
234
+ }
235
+ }
236
+ const newValue = this.root.calculateRatingFromPointer(this.opts.index.current, e);
237
+ this.root.setValue(newValue);
238
+ if (this.root.opts.ref.current) {
239
+ this.root.opts.ref.current.focus();
240
+ }
241
+ }
242
+ onpointermove(e) {
243
+ if (this.#isDisabled ||
244
+ this.root.opts.readonly.current ||
245
+ !this.root.opts.hoverPreview.current)
246
+ return;
247
+ // skip hover preview for touch devices
248
+ if (e.pointerType === "touch")
249
+ return;
250
+ const hoverValue = this.root.calculateRatingFromPointer(this.opts.index.current, e);
251
+ this.root.setHoverValue(hoverValue);
252
+ }
253
+ snippetProps = $derived.by(() => {
254
+ return {
255
+ state: this.#state,
256
+ };
257
+ });
258
+ props = $derived.by(() => ({
259
+ id: this.opts.id.current,
260
+ role: "presentation",
261
+ "data-value": this.opts.index.current + 1,
262
+ "data-orientation": this.root.opts.orientation.current,
263
+ "data-disabled": getDataDisabled(this.#isDisabled),
264
+ "data-readonly": this.root.opts.readonly.current ? "" : undefined,
265
+ "data-state": this.#state,
266
+ [RATING_GROUP_ITEM_ATTR]: "",
267
+ //
268
+ onclick: this.onclick,
269
+ onpointermove: this.onpointermove,
270
+ ...attachRef(this.opts.ref),
271
+ }));
272
+ }
273
+ class RatingGroupHiddenInputState {
274
+ root;
275
+ shouldRender = $derived.by(() => this.root.opts.name.current !== undefined);
276
+ props = $derived.by(() => ({
277
+ name: this.root.opts.name.current,
278
+ value: this.root.opts.value.current,
279
+ required: this.root.opts.required.current,
280
+ disabled: this.root.opts.disabled.current,
281
+ }));
282
+ constructor(root) {
283
+ this.root = root;
284
+ }
285
+ }
286
+ const RatingGroupRootContext = new Context("RatingGroup.Root");
287
+ export function useRatingGroupRoot(props) {
288
+ return RatingGroupRootContext.set(new RatingGroupRootState(props));
289
+ }
290
+ export function useRatingGroupItem(props) {
291
+ return new RatingGroupItemState(props, RatingGroupRootContext.get());
292
+ }
293
+ export function useRatingGroupHiddenInput() {
294
+ return new RatingGroupHiddenInputState(RatingGroupRootContext.get());
295
+ }
@@ -0,0 +1,111 @@
1
+ import type { OnChangeFn, WithChild, Without } from "../../internal/types.js";
2
+ import type { Orientation } from "../../index.js";
3
+ import type { BitsPrimitiveDivAttributes } from "../../shared/attributes.js";
4
+ export type RatingGroupItemState = "active" | "partial" | "inactive";
5
+ export type RatingGroupItemData = {
6
+ index: number;
7
+ state: RatingGroupItemState;
8
+ };
9
+ export type RatingGroupRootSnippetProps = {
10
+ items: RatingGroupItemData[];
11
+ value: number;
12
+ max: number;
13
+ };
14
+ export type RatingGroupAriaValuetext = BitsPrimitiveDivAttributes["aria-valuetext"] | ((value: number, max: number) => string);
15
+ export type RatingGroupRootPropsWithoutHTML = WithChild<{
16
+ /**
17
+ * The orientation of the rating group. Used to determine
18
+ * how keyboard interactions work.
19
+ *
20
+ * @default "horizontal"
21
+ */
22
+ orientation?: Orientation;
23
+ /**
24
+ * The current rating value.
25
+ *
26
+ * @default 0
27
+ */
28
+ value?: number;
29
+ /**
30
+ * The callback to call when the rating value changes.
31
+ */
32
+ onValueChange?: OnChangeFn<number>;
33
+ /**
34
+ * The name to apply to the rating group's input element for
35
+ * form submission. If not provided, a hidden input will not
36
+ * be rendered and the rating group will not be part of a form.
37
+ *
38
+ * @default undefined
39
+ */
40
+ name?: string;
41
+ /**
42
+ * Whether the rating group is disabled.
43
+ *
44
+ * @default false
45
+ */
46
+ disabled?: boolean;
47
+ /**
48
+ * Whether the rating group is required for form submission.
49
+ * If `true`, ensure you provide a `name` prop so the hidden
50
+ * input is rendered.
51
+ *
52
+ * @default false
53
+ */
54
+ required?: boolean;
55
+ /**
56
+ * The minimum rating value.
57
+ *
58
+ * @default 0
59
+ */
60
+ min?: number;
61
+ /**
62
+ * The maximum rating value (number of items).
63
+ *
64
+ * @default 5
65
+ */
66
+ max?: number;
67
+ /**
68
+ * Whether to allow half-star ratings.
69
+ *
70
+ * @default false
71
+ */
72
+ allowHalf?: boolean;
73
+ /**
74
+ * Whether the rating group is readonly.
75
+ *
76
+ * @default false
77
+ */
78
+ readonly?: boolean;
79
+ /**
80
+ * Whether to show a preview when hovering over rating items.
81
+ * Touch events are ignored to prevent accidental previews.
82
+ *
83
+ * @default true
84
+ */
85
+ hoverPreview?: boolean;
86
+ /**
87
+ * An extended `aria-valuetext` property to use for the rating group.
88
+ * Can either be a string, or a function that receives the current value
89
+ * and max value and returns a string.
90
+ *
91
+ * @default ((value: number, max: number) => `${value} out of ${max}`)
92
+ */
93
+ "aria-valuetext"?: RatingGroupAriaValuetext;
94
+ }, RatingGroupRootSnippetProps>;
95
+ export type RatingGroupRootProps = RatingGroupRootPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, RatingGroupRootPropsWithoutHTML>;
96
+ export type RatingGroupItemSnippetProps = {
97
+ state: RatingGroupItemState;
98
+ };
99
+ export type RatingGroupItemPropsWithoutHTML = WithChild<{
100
+ /**
101
+ * The index of the rating item (0-based index).
102
+ */
103
+ index: number;
104
+ /**
105
+ * Whether the rating item is disabled.
106
+ *
107
+ * @default false
108
+ */
109
+ disabled?: boolean | null | undefined;
110
+ }, RatingGroupItemSnippetProps>;
111
+ export type RatingGroupItemProps = RatingGroupItemPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, RatingGroupItemPropsWithoutHTML>;
@@ -0,0 +1 @@
1
+ export {};
@@ -132,6 +132,29 @@ export function getThumbLabelStyles(direction, thumbPosition, labelPosition = "t
132
132
  }
133
133
  return style;
134
134
  }
135
+ /**
136
+ * Gets the number of decimal places in a number
137
+ */
138
+ function getDecimalPlaces(num) {
139
+ if (Math.floor(num) === num)
140
+ return 0;
141
+ const str = num.toString();
142
+ if (str.indexOf(".") !== -1 && str.indexOf("e-") === -1) {
143
+ return str.split(".")[1].length;
144
+ }
145
+ else if (str.indexOf("e-") !== -1) {
146
+ const parts = str.split("e-");
147
+ return parseInt(parts[1], 10);
148
+ }
149
+ return 0;
150
+ }
151
+ /**
152
+ * Rounds a number to the specified number of decimal places
153
+ */
154
+ function roundToPrecision(num, precision) {
155
+ const factor = Math.pow(10, precision);
156
+ return Math.round(num * factor) / factor;
157
+ }
135
158
  /**
136
159
  * Normalizes step to always be a sorted array of valid values within min/max range
137
160
  */
@@ -140,13 +163,21 @@ export function normalizeSteps(step, min, max) {
140
163
  // generate regular steps - match original behavior exactly
141
164
  const difference = max - min;
142
165
  let count = Math.ceil(difference / step);
143
- if (difference % step === 0) {
166
+ // Get precision from step to avoid floating point errors
167
+ const precision = getDecimalPlaces(step);
168
+ // Check if difference is divisible by step using integer arithmetic to avoid floating point errors
169
+ const factor = Math.pow(10, precision);
170
+ const intDifference = Math.round(difference * factor);
171
+ const intStep = Math.round(step * factor);
172
+ if (intDifference % intStep === 0) {
144
173
  count++;
145
174
  }
146
175
  const steps = [];
147
176
  for (let i = 0; i < count; i++) {
148
177
  const value = min + i * step;
149
- steps.push(value);
178
+ // Round to the precision of the step to avoid floating point errors
179
+ const roundedValue = roundToPrecision(value, precision);
180
+ steps.push(roundedValue);
150
181
  }
151
182
  return steps;
152
183
  }
@@ -46,6 +46,7 @@
46
46
  preventScroll={false}
47
47
  forceMount={true}
48
48
  ref={contentState.opts.ref}
49
+ tooltip={true}
49
50
  >
50
51
  {#snippet popper({ props })}
51
52
  {@const mergedProps = mergeProps(props, {
@@ -64,6 +65,7 @@
64
65
  <PopperLayer
65
66
  {...mergedProps}
66
67
  {...contentState.popperProps}
68
+ tooltip={true}
67
69
  isStatic
68
70
  present={contentState.root.opts.open.current}
69
71
  {id}
@@ -64,6 +64,7 @@
64
64
  preventScroll={false}
65
65
  forceMount={true}
66
66
  ref={contentState.opts.ref}
67
+ tooltip={true}
67
68
  >
68
69
  {#snippet popper({ props, wrapperProps })}
69
70
  {@const mergedProps = mergeProps(props, {
@@ -91,6 +92,7 @@
91
92
  preventScroll={false}
92
93
  forceMount={false}
93
94
  ref={contentState.opts.ref}
95
+ tooltip={true}
94
96
  >
95
97
  {#snippet popper({ props, wrapperProps })}
96
98
  {@const mergedProps = mergeProps(props, {
@@ -29,7 +29,7 @@
29
29
  const mergedProps = $derived(mergeProps(restProps, triggerState.props, { type }));
30
30
  </script>
31
31
 
32
- <FloatingLayerAnchor {id} ref={triggerState.opts.ref}>
32
+ <FloatingLayerAnchor {id} ref={triggerState.opts.ref} tooltip={true}>
33
33
  {#if child}
34
34
  {@render child({ props: mergedProps })}
35
35
  {:else}
@@ -32,6 +32,6 @@
32
32
  });
33
33
  </script>
34
34
 
35
- <FloatingLayer>
35
+ <FloatingLayer tooltip>
36
36
  {@render children?.()}
37
37
  </FloatingLayer>
@@ -1,7 +1,7 @@
1
1
  import { DOMContext } from "svelte-toolbelt";
2
2
  import type { ReadableBoxedValues, WritableBoxedValues } from "../../internal/box.svelte.js";
3
3
  import type { WithRefProps } from "../../internal/types.js";
4
- import type { PointerEventHandler } from "svelte/elements";
4
+ import type { FocusEventHandler, MouseEventHandler, PointerEventHandler } from "svelte/elements";
5
5
  type TooltipProviderStateProps = ReadableBoxedValues<{
6
6
  delayDuration: number;
7
7
  disableHoverableContent: boolean;
@@ -58,23 +58,21 @@ declare class TooltipTriggerState {
58
58
  constructor(opts: TooltipTriggerStateProps, root: TooltipRootState);
59
59
  handlePointerUp: () => void;
60
60
  props: {
61
- id: string;
62
- "aria-describedby": string | undefined;
63
- "data-state": string;
64
- "data-disabled": "" | undefined;
65
- "data-delay-duration": string;
66
- "data-tooltip-trigger": string;
67
- tabindex: number | undefined;
68
- disabled: boolean;
69
- onpointerup: () => void;
70
- onpointerdown: () => void;
71
- onpointermove: PointerEventHandler<HTMLElement>;
72
- onpointerleave: () => void;
73
- onfocus: (e: FocusEvent & {
74
- currentTarget: HTMLElement;
75
- }) => void;
76
- onblur: () => void;
77
- onclick: () => void;
61
+ readonly id: string;
62
+ readonly "aria-describedby": string | undefined;
63
+ readonly "data-state": string;
64
+ readonly "data-disabled": "" | undefined;
65
+ readonly "data-delay-duration": `${number}`;
66
+ readonly "data-tooltip-trigger": "";
67
+ readonly tabindex: 0 | undefined;
68
+ readonly disabled: boolean;
69
+ readonly onpointerup: PointerEventHandler<HTMLElement>;
70
+ readonly onpointerdown: PointerEventHandler<HTMLElement>;
71
+ readonly onpointermove: PointerEventHandler<HTMLElement>;
72
+ readonly onpointerleave: PointerEventHandler<HTMLElement>;
73
+ readonly onfocus: FocusEventHandler<HTMLElement>;
74
+ readonly onblur: FocusEventHandler<HTMLElement>;
75
+ readonly onclick: MouseEventHandler<HTMLElement>;
78
76
  };
79
77
  }
80
78
  type TooltipContentStateProps = WithRefProps & ReadableBoxedValues<{
@@ -194,7 +194,9 @@ class TooltipTriggerState {
194
194
  };
195
195
  props = $derived.by(() => ({
196
196
  id: this.opts.id.current,
197
- "aria-describedby": this.root.opts.open.current ? this.root.contentNode?.id : undefined,
197
+ "aria-describedby": this.root.opts.open.current
198
+ ? this.root.contentNode?.id
199
+ : undefined,
198
200
  "data-state": this.root.stateAttr,
199
201
  "data-disabled": getDataDisabled(this.#isDisabled),
200
202
  "data-delay-duration": `${this.root.delayDuration}`,
@@ -4,13 +4,16 @@
4
4
  import type { AnchorProps } from "./index.js";
5
5
  import type { Measurable } from "../../../../internal/floating-svelte/types.js";
6
6
 
7
- let { id, children, virtualEl, ref }: AnchorProps = $props();
7
+ let { id, children, virtualEl, ref, tooltip = false }: AnchorProps = $props();
8
8
 
9
- useFloatingAnchorState({
10
- id: box.with(() => id),
11
- virtualEl: box.with(() => virtualEl as unknown as Measurable | null),
12
- ref,
13
- });
9
+ useFloatingAnchorState(
10
+ {
11
+ id: box.with(() => id),
12
+ virtualEl: box.with(() => virtualEl as unknown as Measurable | null),
13
+ ref,
14
+ },
15
+ tooltip
16
+ );
14
17
  </script>
15
18
 
16
19
  {@render children?.()}
@@ -25,29 +25,33 @@
25
25
  wrapperId = useId(),
26
26
  customAnchor = null,
27
27
  enabled,
28
+ tooltip = false,
28
29
  }: ContentImplProps = $props();
29
30
 
30
- const contentState = useFloatingContentState({
31
- side: box.with(() => side),
32
- sideOffset: box.with(() => sideOffset),
33
- align: box.with(() => align),
34
- alignOffset: box.with(() => alignOffset),
35
- id: box.with(() => id),
36
- arrowPadding: box.with(() => arrowPadding),
37
- avoidCollisions: box.with(() => avoidCollisions),
38
- collisionBoundary: box.with(() => collisionBoundary),
39
- collisionPadding: box.with(() => collisionPadding),
40
- hideWhenDetached: box.with(() => hideWhenDetached),
41
- onPlaced: box.with(() => onPlaced),
42
- sticky: box.with(() => sticky),
43
- updatePositionStrategy: box.with(() => updatePositionStrategy),
44
- strategy: box.with(() => strategy),
45
- dir: box.with(() => dir),
46
- style: box.with(() => style),
47
- enabled: box.with(() => enabled),
48
- wrapperId: box.with(() => wrapperId),
49
- customAnchor: box.with(() => customAnchor),
50
- });
31
+ const contentState = useFloatingContentState(
32
+ {
33
+ side: box.with(() => side),
34
+ sideOffset: box.with(() => sideOffset),
35
+ align: box.with(() => align),
36
+ alignOffset: box.with(() => alignOffset),
37
+ id: box.with(() => id),
38
+ arrowPadding: box.with(() => arrowPadding),
39
+ avoidCollisions: box.with(() => avoidCollisions),
40
+ collisionBoundary: box.with(() => collisionBoundary),
41
+ collisionPadding: box.with(() => collisionPadding),
42
+ hideWhenDetached: box.with(() => hideWhenDetached),
43
+ onPlaced: box.with(() => onPlaced),
44
+ sticky: box.with(() => sticky),
45
+ updatePositionStrategy: box.with(() => updatePositionStrategy),
46
+ strategy: box.with(() => strategy),
47
+ dir: box.with(() => dir),
48
+ style: box.with(() => style),
49
+ enabled: box.with(() => enabled),
50
+ wrapperId: box.with(() => wrapperId),
51
+ customAnchor: box.with(() => customAnchor),
52
+ },
53
+ tooltip
54
+ );
51
55
 
52
56
  const mergedProps = $derived(
53
57
  mergeProps(contentState.wrapperProps, {
@@ -2,9 +2,9 @@
2
2
  import type { Snippet } from "svelte";
3
3
  import { useFloatingRootState } from "../use-floating-layer.svelte.js";
4
4
 
5
- let { children }: { children?: Snippet } = $props();
5
+ let { children, tooltip = false }: { children?: Snippet; tooltip?: boolean } = $props();
6
6
 
7
- useFloatingRootState();
7
+ useFloatingRootState(tooltip);
8
8
  </script>
9
9
 
10
10
  {@render children?.()}
@@ -1,6 +1,7 @@
1
1
  import type { Snippet } from "svelte";
2
2
  type $$ComponentProps = {
3
3
  children?: Snippet;
4
+ tooltip?: boolean;
4
5
  };
5
6
  declare const FloatingLayer: import("svelte").Component<$$ComponentProps, {}, "">;
6
7
  type FloatingLayer = ReturnType<typeof FloatingLayer>;
@@ -107,10 +107,28 @@ export type FloatingLayerContentImplProps = {
107
107
  */
108
108
  onPlaced?: () => void;
109
109
  enabled: boolean;
110
+ /**
111
+ * Tooltips are special in that they are commonly composed
112
+ * with other floating components, where the same trigger is
113
+ * used for both the tooltip and the popover.
114
+ *
115
+ * For situations like this, we need to use a different context
116
+ * symbol so that conflicts don't occur.
117
+ */
118
+ tooltip?: boolean;
110
119
  } & FloatingLayerContentProps;
111
120
  export type FloatingLayerAnchorProps = {
112
121
  id: string;
113
122
  children?: Snippet;
114
123
  virtualEl?: ReadableBox<Measurable | null>;
115
124
  ref: ReadableBox<HTMLElement | null>;
125
+ /**
126
+ * Tooltips are special in that they are commonly composed
127
+ * with other floating components, where the same trigger is
128
+ * used for both the tooltip and the popover.
129
+ *
130
+ * For situations like this, we need to use a different context
131
+ * symbol so that conflicts don't occur.
132
+ */
133
+ tooltip?: boolean;
116
134
  };
@@ -942,10 +942,10 @@ declare class FloatingAnchorState {
942
942
  readonly root: FloatingRootState;
943
943
  constructor(opts: FloatingAnchorStateProps, root: FloatingRootState);
944
944
  }
945
- export declare function useFloatingRootState(): FloatingRootState;
946
- export declare function useFloatingContentState(props: FloatingContentStateProps): FloatingContentState;
945
+ export declare function useFloatingRootState(tooltip?: boolean): FloatingRootState;
946
+ export declare function useFloatingContentState(props: FloatingContentStateProps, tooltip?: boolean): FloatingContentState;
947
947
  export declare function useFloatingArrowState(props: FloatingArrowStateProps): FloatingArrowState;
948
- export declare function useFloatingAnchorState(props: FloatingAnchorStateProps): FloatingAnchorState;
948
+ export declare function useFloatingAnchorState(props: FloatingAnchorStateProps, tooltip?: boolean): FloatingAnchorState;
949
949
  export declare function getSideFromPlacement(placement: Placement): "left" | "right" | "top" | "bottom";
950
950
  export declare function getAlignFromPlacement(placement: Placement): "end" | "center" | "start";
951
951
  export {};
@@ -140,9 +140,6 @@ class FloatingContentState {
140
140
  "data-align": this.placedAlign,
141
141
  style: styleToString({
142
142
  ...this.#transformedStyle,
143
- // if the FloatingContent hasn't been placed yet (not all measurements done)
144
- // we prevent animations so that users's animation don't kick in too early referring wrong sides
145
- // animation: !this.floating.isPositioned ? "none" : undefined,
146
143
  }),
147
144
  ...attachRef(this.contentRef),
148
145
  }));
@@ -233,17 +230,24 @@ class FloatingAnchorState {
233
230
  }
234
231
  const FloatingRootContext = new Context("Floating.Root");
235
232
  const FloatingContentContext = new Context("Floating.Content");
236
- export function useFloatingRootState() {
237
- return FloatingRootContext.set(new FloatingRootState());
233
+ const FloatingTooltipRootContext = new Context("Floating.Root");
234
+ export function useFloatingRootState(tooltip = false) {
235
+ return tooltip
236
+ ? FloatingTooltipRootContext.set(new FloatingRootState())
237
+ : FloatingRootContext.set(new FloatingRootState());
238
238
  }
239
- export function useFloatingContentState(props) {
240
- return FloatingContentContext.set(new FloatingContentState(props, FloatingRootContext.get()));
239
+ export function useFloatingContentState(props, tooltip = false) {
240
+ return tooltip
241
+ ? FloatingContentContext.set(new FloatingContentState(props, FloatingTooltipRootContext.get()))
242
+ : FloatingContentContext.set(new FloatingContentState(props, FloatingRootContext.get()));
241
243
  }
242
244
  export function useFloatingArrowState(props) {
243
245
  return new FloatingArrowState(props, FloatingContentContext.get());
244
246
  }
245
- export function useFloatingAnchorState(props) {
246
- return new FloatingAnchorState(props, FloatingRootContext.get());
247
+ export function useFloatingAnchorState(props, tooltip = false) {
248
+ return tooltip
249
+ ? new FloatingAnchorState(props, FloatingTooltipRootContext.get())
250
+ : new FloatingAnchorState(props, FloatingRootContext.get());
247
251
  }
248
252
  //
249
253
  // HELPERS
@@ -45,6 +45,7 @@
45
45
  isStatic = false,
46
46
  enabled,
47
47
  ref,
48
+ tooltip = false,
48
49
  ...restProps
49
50
  }: Omit<PopperLayerImplProps, "present" | "children"> & {
50
51
  enabled: boolean;
@@ -72,6 +73,7 @@
72
73
  {onPlaced}
73
74
  {customAnchor}
74
75
  {enabled}
76
+ {tooltip}
75
77
  >
76
78
  {#snippet content({ props: floatingProps, wrapperProps })}
77
79
  {#if restProps.forceMount && enabled}
@@ -22,4 +22,13 @@ export type PopperLayerImplProps = Omit<EscapeLayerImplProps & DismissibleLayerI
22
22
  }
23
23
  ]>;
24
24
  isStatic?: boolean;
25
+ /**
26
+ * Tooltips are special in that they are commonly composed
27
+ * with other floating components, where the same trigger is
28
+ * used for both the tooltip and the popover.
29
+ *
30
+ * For situations like this, we need to use a different context
31
+ * symbol so that conflicts don't occur.
32
+ */
33
+ tooltip?: boolean;
25
34
  }, "enabled">;
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, 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, 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";
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, 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, 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";
2
2
  export * from "./shared/index.js";
3
3
  export * from "./types.js";
package/dist/types.d.ts CHANGED
@@ -27,6 +27,7 @@ export type * from "./bits/popover/types.js";
27
27
  export type * from "./bits/progress/types.js";
28
28
  export type * from "./bits/radio-group/types.js";
29
29
  export type * from "./bits/range-calendar/types.js";
30
+ export type * from "./bits/rating-group/types.js";
30
31
  export type * from "./bits/scroll-area/types.js";
31
32
  export type * from "./bits/select/types.js";
32
33
  export type * from "./bits/separator/types.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bits-ui",
3
- "version": "2.2.0",
3
+ "version": "2.3.0",
4
4
  "license": "MIT",
5
5
  "repository": "github:huntabyte/bits-ui",
6
6
  "funding": "https://github.com/sponsors/huntabyte",