@epilot/spark-ui 0.26.1 → 0.27.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.
- package/dist/components/alert-dialog.cjs +1 -1
- package/dist/components/alert-dialog.js +1 -1
- package/dist/components/attachment.d.cts +2 -2
- package/dist/components/attachment.d.ts +2 -2
- package/dist/components/avatar.d.cts +1 -1
- package/dist/components/avatar.d.ts +1 -1
- package/dist/components/badge.cjs +10 -2
- package/dist/components/badge.cjs.map +1 -1
- package/dist/components/badge.d.cts +2 -1
- package/dist/components/badge.d.ts +2 -1
- package/dist/components/badge.js +10 -2
- package/dist/components/badge.js.map +1 -1
- package/dist/components/banner.d.cts +1 -1
- package/dist/components/banner.d.ts +1 -1
- package/dist/components/box.d.cts +1 -1
- package/dist/components/box.d.ts +1 -1
- package/dist/components/bubble.cjs +1 -1
- package/dist/components/bubble.cjs.map +1 -1
- package/dist/components/bubble.d.cts +1 -1
- package/dist/components/bubble.d.ts +1 -1
- package/dist/components/bubble.js +1 -1
- package/dist/components/bubble.js.map +1 -1
- package/dist/components/button-group.d.cts +1 -1
- package/dist/components/button-group.d.ts +1 -1
- package/dist/components/button.cjs +27 -6
- package/dist/components/button.cjs.map +1 -1
- package/dist/components/button.d.cts +8 -7
- package/dist/components/button.d.ts +8 -7
- package/dist/components/button.js +27 -6
- package/dist/components/button.js.map +1 -1
- package/dist/components/callout.d.cts +1 -1
- package/dist/components/callout.d.ts +1 -1
- package/dist/components/card.cjs +8 -4
- package/dist/components/card.cjs.map +1 -1
- package/dist/components/card.d.cts +6 -2
- package/dist/components/card.d.ts +6 -2
- package/dist/components/card.js +8 -4
- package/dist/components/card.js.map +1 -1
- package/dist/components/checkbox-group.cjs +31 -0
- package/dist/components/checkbox-group.cjs.map +1 -0
- package/dist/components/checkbox-group.d.cts +27 -0
- package/dist/components/checkbox-group.d.ts +27 -0
- package/dist/components/checkbox-group.js +28 -0
- package/dist/components/checkbox-group.js.map +1 -0
- package/dist/components/checkbox.d.cts +1 -1
- package/dist/components/checkbox.d.ts +1 -1
- package/dist/components/dialog.cjs +1 -1
- package/dist/components/dialog.js +1 -1
- package/dist/components/empty-state.d.cts +3 -3
- package/dist/components/empty-state.d.ts +3 -3
- package/dist/components/field.cjs +110 -15
- package/dist/components/field.cjs.map +1 -1
- package/dist/components/field.d.cts +16 -3
- package/dist/components/field.d.ts +16 -3
- package/dist/components/field.js +111 -17
- package/dist/components/field.js.map +1 -1
- package/dist/components/input-group.cjs +9 -9
- package/dist/components/input-group.cjs.map +1 -1
- package/dist/components/input-group.d.cts +1 -1
- package/dist/components/input-group.d.ts +1 -1
- package/dist/components/input-group.js +9 -9
- package/dist/components/input-group.js.map +1 -1
- package/dist/components/input.d.cts +1 -1
- package/dist/components/input.d.ts +1 -1
- package/dist/components/list.cjs +21 -5
- package/dist/components/list.cjs.map +1 -1
- package/dist/components/list.d.cts +13 -5
- package/dist/components/list.d.ts +13 -5
- package/dist/components/list.js +21 -5
- package/dist/components/list.js.map +1 -1
- package/dist/components/marker.cjs +1 -1
- package/dist/components/marker.cjs.map +1 -1
- package/dist/components/marker.d.cts +1 -1
- package/dist/components/marker.d.ts +1 -1
- package/dist/components/marker.js +1 -1
- package/dist/components/marker.js.map +1 -1
- package/dist/components/page-header.d.cts +1 -1
- package/dist/components/page-header.d.ts +1 -1
- package/dist/components/pill.d.cts +1 -1
- package/dist/components/pill.d.ts +1 -1
- package/dist/components/radio.cjs +6 -2
- package/dist/components/radio.cjs.map +1 -1
- package/dist/components/radio.d.cts +4 -2
- package/dist/components/radio.d.ts +4 -2
- package/dist/components/radio.js +6 -2
- package/dist/components/radio.js.map +1 -1
- package/dist/components/rating.cjs +167 -0
- package/dist/components/rating.cjs.map +1 -0
- package/dist/components/rating.d.cts +50 -0
- package/dist/components/rating.d.ts +50 -0
- package/dist/components/rating.js +162 -0
- package/dist/components/rating.js.map +1 -0
- package/dist/components/scroll-area.cjs +9 -2
- package/dist/components/scroll-area.cjs.map +1 -1
- package/dist/components/scroll-area.d.cts +1 -1
- package/dist/components/scroll-area.d.ts +1 -1
- package/dist/components/scroll-area.js +10 -3
- package/dist/components/scroll-area.js.map +1 -1
- package/dist/components/segmented-control.d.cts +1 -1
- package/dist/components/segmented-control.d.ts +1 -1
- package/dist/components/select.d.cts +1 -1
- package/dist/components/select.d.ts +1 -1
- package/dist/components/selection-item.cjs +42 -0
- package/dist/components/selection-item.cjs.map +1 -0
- package/dist/components/selection-item.d.cts +25 -0
- package/dist/components/selection-item.d.ts +25 -0
- package/dist/components/selection-item.js +39 -0
- package/dist/components/selection-item.js.map +1 -0
- package/dist/components/sheet.cjs +1 -1
- package/dist/components/sheet.js +1 -1
- package/dist/components/skeleton.cjs +1 -1
- package/dist/components/skeleton.cjs.map +1 -1
- package/dist/components/skeleton.js +1 -1
- package/dist/components/skeleton.js.map +1 -1
- package/dist/components/slider.cjs +1 -1
- package/dist/components/slider.cjs.map +1 -1
- package/dist/components/slider.js +1 -1
- package/dist/components/slider.js.map +1 -1
- package/dist/components/spinner.cjs +81 -8
- package/dist/components/spinner.cjs.map +1 -1
- package/dist/components/spinner.js +81 -8
- package/dist/components/spinner.js.map +1 -1
- package/dist/components/stepper.cjs +3 -2
- package/dist/components/stepper.cjs.map +1 -1
- package/dist/components/stepper.js +3 -2
- package/dist/components/stepper.js.map +1 -1
- package/dist/components/switch-group.cjs +32 -0
- package/dist/components/switch-group.cjs.map +1 -0
- package/dist/components/switch-group.d.cts +26 -0
- package/dist/components/switch-group.d.ts +26 -0
- package/dist/components/switch-group.js +29 -0
- package/dist/components/switch-group.js.map +1 -0
- package/dist/components/switch.d.cts +1 -1
- package/dist/components/switch.d.ts +1 -1
- package/dist/components/tabs.cjs +32 -23
- package/dist/components/tabs.cjs.map +1 -1
- package/dist/components/tabs.d.cts +5 -5
- package/dist/components/tabs.d.ts +5 -5
- package/dist/components/tabs.js +32 -23
- package/dist/components/tabs.js.map +1 -1
- package/dist/components/textarea.d.cts +1 -1
- package/dist/components/textarea.d.ts +1 -1
- package/dist/components/theme.cjs +44 -2
- package/dist/components/theme.cjs.map +1 -1
- package/dist/components/theme.d.cts +4 -2
- package/dist/components/theme.d.ts +4 -2
- package/dist/components/theme.js +44 -2
- package/dist/components/theme.js.map +1 -1
- package/dist/components/toast.cjs +1 -1
- package/dist/components/toast.js +1 -1
- package/dist/components/toggle-group.d.cts +1 -1
- package/dist/components/toggle-group.d.ts +1 -1
- package/dist/components/toggle.d.cts +2 -2
- package/dist/components/toggle.d.ts +2 -2
- package/dist/lib/accent-theme.d.cts +1 -1
- package/dist/lib/accent-theme.d.ts +1 -1
- package/dist/lib/container-chrome.cjs +4 -4
- package/dist/lib/container-chrome.cjs.map +1 -1
- package/dist/lib/container-chrome.d.cts +1 -1
- package/dist/lib/container-chrome.d.ts +1 -1
- package/dist/lib/container-chrome.js +4 -4
- package/dist/lib/container-chrome.js.map +1 -1
- package/dist/lib/input-box-variants.cjs +8 -8
- package/dist/lib/input-box-variants.cjs.map +1 -1
- package/dist/lib/input-box-variants.d.cts +1 -1
- package/dist/lib/input-box-variants.d.ts +1 -1
- package/dist/lib/input-box-variants.js +8 -8
- package/dist/lib/input-box-variants.js.map +1 -1
- package/dist/lib/selection-list.cjs +17 -0
- package/dist/lib/selection-list.cjs.map +1 -0
- package/dist/lib/selection-list.d.cts +11 -0
- package/dist/lib/selection-list.d.ts +11 -0
- package/dist/lib/selection-list.js +15 -0
- package/dist/lib/selection-list.js.map +1 -0
- package/dist/lib/theme-types.cjs.map +1 -1
- package/dist/lib/theme-types.d.cts +2 -2
- package/dist/lib/theme-types.d.ts +2 -2
- package/dist/lib/theme-types.js.map +1 -1
- package/dist/lib/toggle-group-context.d.cts +2 -1
- package/dist/lib/toggle-group-context.d.ts +2 -1
- package/dist/styles/spark-default.css +12 -1
- package/dist/styles/theme.css +98 -0
- package/dist/{theme-types-Bn5E15-P.d.ts → theme-types-CKZzOmSa.d.cts} +11 -2
- package/dist/{theme-types-Bn5E15-P.d.cts → theme-types-CKZzOmSa.d.ts} +11 -2
- package/package.json +1 -1
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const require_chunk = require("../chunk-DY84GLCh.cjs");
|
|
4
|
+
const require_components_field = require("./field.cjs");
|
|
5
|
+
let react = require("react");
|
|
6
|
+
react = require_chunk.__toESM(react);
|
|
7
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
+
let _base_ui_react_radio = require("@base-ui/react/radio");
|
|
9
|
+
let _base_ui_react_radio_group = require("@base-ui/react/radio-group");
|
|
10
|
+
let cn = require("cn");
|
|
11
|
+
//#region src/components/rating.tsx
|
|
12
|
+
const RatingContext = react.createContext(null);
|
|
13
|
+
function useRating() {
|
|
14
|
+
const context = react.useContext(RatingContext);
|
|
15
|
+
if (!context) throw new Error("RatingStars and RatingCaption need a Rating");
|
|
16
|
+
return context;
|
|
17
|
+
}
|
|
18
|
+
function Rating({ value: valueProp, defaultValue = null, onValueChange, max = 5, labels, size = "medium", readOnly = false, disabled = false, name, className, children, ...props }) {
|
|
19
|
+
const [uncontrolled, setUncontrolled] = react.useState(defaultValue);
|
|
20
|
+
const [hovered, setHovered] = react.useState(null);
|
|
21
|
+
const value = valueProp === void 0 ? uncontrolled : valueProp;
|
|
22
|
+
const setValue = react.useCallback((next) => {
|
|
23
|
+
setUncontrolled(next);
|
|
24
|
+
onValueChange?.(next);
|
|
25
|
+
}, [onValueChange]);
|
|
26
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RatingContext.Provider, {
|
|
27
|
+
value: {
|
|
28
|
+
value,
|
|
29
|
+
setValue,
|
|
30
|
+
hovered: readOnly || disabled ? null : hovered,
|
|
31
|
+
setHovered,
|
|
32
|
+
max,
|
|
33
|
+
labels,
|
|
34
|
+
size,
|
|
35
|
+
readOnly,
|
|
36
|
+
disabled,
|
|
37
|
+
name
|
|
38
|
+
},
|
|
39
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
40
|
+
"data-slot": "rating",
|
|
41
|
+
className: (0, cn.cn)("flex flex-col items-start gap-[calc(var(--spark-layout-gap)*1)]", className),
|
|
42
|
+
...props,
|
|
43
|
+
children
|
|
44
|
+
})
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
const sizeClasses = {
|
|
48
|
+
small: {
|
|
49
|
+
star: "size-4",
|
|
50
|
+
button: "size-6"
|
|
51
|
+
},
|
|
52
|
+
medium: {
|
|
53
|
+
star: "size-6",
|
|
54
|
+
button: "size-8"
|
|
55
|
+
},
|
|
56
|
+
large: {
|
|
57
|
+
star: "size-8",
|
|
58
|
+
button: "size-11"
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const compactSizeClasses = {
|
|
62
|
+
small: {
|
|
63
|
+
star: "size-3.5",
|
|
64
|
+
button: "size-6"
|
|
65
|
+
},
|
|
66
|
+
medium: {
|
|
67
|
+
star: "size-4.5",
|
|
68
|
+
button: "size-6"
|
|
69
|
+
},
|
|
70
|
+
large: {
|
|
71
|
+
star: "size-5",
|
|
72
|
+
button: "size-6"
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
function starTone(fill, disabled) {
|
|
76
|
+
if (disabled) return fill === "off" ? "fill-none stroke-gray-a6" : "fill-gray-a7 stroke-gray-a7";
|
|
77
|
+
if (fill === "on") return "fill-spark-9 stroke-spark-9";
|
|
78
|
+
if (fill === "preview") return "fill-spark-a4 stroke-spark-9";
|
|
79
|
+
return "fill-none stroke-gray-a9";
|
|
80
|
+
}
|
|
81
|
+
function captionTone(hasLabel, hovered, disabled) {
|
|
82
|
+
if (disabled) return "text-gray-a9";
|
|
83
|
+
if (!hasLabel) return "text-gray-11";
|
|
84
|
+
return hovered ? "text-spark-11" : "text-gray-12";
|
|
85
|
+
}
|
|
86
|
+
function Star({ className }) {
|
|
87
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
88
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
89
|
+
viewBox: "0 0 24 24",
|
|
90
|
+
strokeWidth: 1.5,
|
|
91
|
+
strokeLinejoin: "round",
|
|
92
|
+
"aria-hidden": "true",
|
|
93
|
+
className: (0, cn.cn)("transition-colors motion-reduce:transition-none", className),
|
|
94
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M12.60 3.17 L14.72 8.03 Q15.00 8.67 15.69 8.74 L20.97 9.26 Q22.46 9.40 21.34 10.40 L17.37 13.91 Q16.85 14.38 17.00 15.06 L18.14 20.23 Q18.47 21.70 17.17 20.94 L12.60 18.25 Q12.00 17.90 11.40 18.25 L6.83 20.94 Q5.53 21.70 5.86 20.23 L7.00 15.06 Q7.15 14.38 6.63 13.91 L2.66 10.40 Q1.54 9.40 3.03 9.26 L8.31 8.74 Q9.00 8.67 9.28 8.03 L11.40 3.17 Q12.00 1.80 12.60 3.17Z" })
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
function RatingStars({ className, onPointerLeave, onKeyDown, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedByProp, ...props }) {
|
|
98
|
+
const rating = useRating();
|
|
99
|
+
const { field, ariaDescribedBy, ariaInvalid } = require_components_field.useFieldControl({ ariaDescribedBy: ariaDescribedByProp });
|
|
100
|
+
const invalid = require_components_field.useFieldSetInvalid();
|
|
101
|
+
const { star: starSize, button: buttonSize } = (rating.max > 5 ? compactSizeClasses : sizeClasses)[rating.size];
|
|
102
|
+
const interactive = !rating.readOnly && !rating.disabled;
|
|
103
|
+
const low = Math.min(rating.value ?? 0, rating.hovered ?? rating.value ?? 0);
|
|
104
|
+
const high = Math.max(rating.value ?? 0, rating.hovered ?? 0);
|
|
105
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_radio_group.RadioGroup, {
|
|
106
|
+
"data-slot": "rating-stars",
|
|
107
|
+
"data-invalid": invalid,
|
|
108
|
+
"aria-labelledby": ariaLabelledBy ?? (field?.readOnly ? field.labelId : void 0),
|
|
109
|
+
"aria-describedby": ariaDescribedBy,
|
|
110
|
+
"aria-invalid": ariaInvalid,
|
|
111
|
+
value: rating.value,
|
|
112
|
+
onValueChange: (next) => next !== null && rating.setValue(next),
|
|
113
|
+
readOnly: rating.readOnly,
|
|
114
|
+
disabled: rating.disabled,
|
|
115
|
+
name: rating.name,
|
|
116
|
+
className: (0, cn.cn)("flex", className),
|
|
117
|
+
onPointerLeave: (event) => {
|
|
118
|
+
rating.setHovered(null);
|
|
119
|
+
onPointerLeave?.(event);
|
|
120
|
+
},
|
|
121
|
+
onKeyDown: (event) => {
|
|
122
|
+
rating.setHovered(null);
|
|
123
|
+
onKeyDown?.(event);
|
|
124
|
+
},
|
|
125
|
+
...props,
|
|
126
|
+
children: Array.from({ length: rating.max }, (_, index) => {
|
|
127
|
+
const star = index + 1;
|
|
128
|
+
const fill = star <= low ? "on" : star <= high ? "preview" : "off";
|
|
129
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_radio.Radio.Root, {
|
|
130
|
+
value: star,
|
|
131
|
+
"aria-label": rating.labels?.[index] ?? String(star),
|
|
132
|
+
"data-slot": "rating-star",
|
|
133
|
+
"data-fill": fill,
|
|
134
|
+
"aria-readonly": void 0,
|
|
135
|
+
nativeButton: true,
|
|
136
|
+
render: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {}),
|
|
137
|
+
onPointerEnter: interactive ? () => rating.setHovered(star) : void 0,
|
|
138
|
+
className: (0, cn.cn)("inline-flex min-h-[24px] min-w-[24px] shrink-0 cursor-pointer items-center justify-center rounded-sm border-0 bg-transparent p-0 touch-target-row any-pointer-coarse:min-w-11", "focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden", "data-disabled:cursor-not-allowed data-readonly:cursor-default", buttonSize),
|
|
139
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Star, { className: (0, cn.cn)(starSize, starTone(fill, rating.disabled)) })
|
|
140
|
+
}, star);
|
|
141
|
+
})
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
const captionTextSize = {
|
|
145
|
+
small: "text-[0.8125rem]",
|
|
146
|
+
medium: "text-sm",
|
|
147
|
+
large: "text-base"
|
|
148
|
+
};
|
|
149
|
+
function RatingCaption({ className, children, ...props }) {
|
|
150
|
+
const rating = useRating();
|
|
151
|
+
const shown = rating.hovered ?? rating.value;
|
|
152
|
+
const label = shown ? rating.labels?.[shown - 1] : void 0;
|
|
153
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
154
|
+
"data-slot": "rating-caption",
|
|
155
|
+
"aria-hidden": "true",
|
|
156
|
+
"aria-disabled": rating.disabled || void 0,
|
|
157
|
+
className: (0, cn.cn)("leading-5", captionTextSize[rating.size], label !== void 0 && "font-medium", captionTone(label !== void 0, !!rating.hovered, rating.disabled), className),
|
|
158
|
+
...props,
|
|
159
|
+
children: label ?? children
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
//#endregion
|
|
163
|
+
exports.Rating = Rating;
|
|
164
|
+
exports.RatingCaption = RatingCaption;
|
|
165
|
+
exports.RatingStars = RatingStars;
|
|
166
|
+
|
|
167
|
+
//# sourceMappingURL=rating.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rating.cjs","names":["React","useFieldControl","useFieldSetInvalid","RadioGroupPrimitive","RadioPrimitive"],"sources":["../../src/components/rating.tsx"],"sourcesContent":["import { Radio as RadioPrimitive } from '@base-ui/react/radio'\nimport { RadioGroup as RadioGroupPrimitive } from '@base-ui/react/radio-group'\nimport * as React from 'react'\nimport { cn } from '../utils/cn'\nimport { useFieldControl, useFieldSetInvalid } from './field'\n\ntype RatingSize = 'small' | 'medium' | 'large'\n\ntype RatingContextValue = {\n value: number | null\n setValue: (value: number) => void\n hovered: number | null\n setHovered: (value: number | null) => void\n max: number\n labels?: string[]\n size: RatingSize\n readOnly: boolean\n disabled: boolean\n name?: string\n}\n\nconst RatingContext = React.createContext<RatingContextValue | null>(null)\n\nfunction useRating() {\n const context = React.useContext(RatingContext)\n if (!context) throw new Error('RatingStars and RatingCaption need a Rating')\n return context\n}\n\ninterface RatingProps extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'defaultValue' | 'onChange'\n> {\n /** The chosen star, 1-based. `null` means nothing is chosen yet. */\n value?: number | null\n defaultValue?: number | null\n onValueChange?: (value: number) => void\n max?: number\n /** One label per star: the star's accessible name and the caption text. */\n labels?: string[]\n size?: RatingSize\n readOnly?: boolean\n disabled?: boolean\n name?: string\n}\n\nfunction Rating({\n value: valueProp,\n defaultValue = null,\n onValueChange,\n max = 5,\n labels,\n size = 'medium',\n readOnly = false,\n disabled = false,\n name,\n className,\n children,\n ...props\n}: RatingProps) {\n const [uncontrolled, setUncontrolled] = React.useState(defaultValue)\n const [hovered, setHovered] = React.useState<number | null>(null)\n const value = valueProp === undefined ? uncontrolled : valueProp\n\n const setValue = React.useCallback(\n (next: number) => {\n setUncontrolled(next)\n onValueChange?.(next)\n },\n [onValueChange],\n )\n\n return (\n <RatingContext.Provider\n value={{\n value,\n setValue,\n hovered: readOnly || disabled ? null : hovered,\n setHovered,\n max,\n labels,\n size,\n readOnly,\n disabled,\n name,\n }}\n >\n <div\n data-slot=\"rating\"\n className={cn(\n 'flex flex-col items-start gap-[calc(var(--spark-layout-gap)*1)]',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n </RatingContext.Provider>\n )\n}\n\ntype SizeClasses = { star: string; button: string }\n\nconst sizeClasses: Record<RatingSize, SizeClasses> = {\n small: { star: 'size-4', button: 'size-6' },\n medium: { star: 'size-6', button: 'size-8' },\n large: { star: 'size-8', button: 'size-11' },\n}\n\n// above five stars the row would outgrow narrow panels\nconst compactSizeClasses: Record<RatingSize, SizeClasses> = {\n small: { star: 'size-3.5', button: 'size-6' },\n medium: { star: 'size-4.5', button: 'size-6' },\n large: { star: 'size-5', button: 'size-6' },\n}\n\ntype StarFill = 'on' | 'preview' | 'off'\n\nfunction starTone(fill: StarFill, disabled: boolean) {\n if (disabled) {\n return fill === 'off'\n ? 'fill-none stroke-gray-a6'\n : 'fill-gray-a7 stroke-gray-a7'\n }\n if (fill === 'on') return 'fill-spark-9 stroke-spark-9'\n if (fill === 'preview') return 'fill-spark-a4 stroke-spark-9'\n return 'fill-none stroke-gray-a9'\n}\n\nfunction captionTone(hasLabel: boolean, hovered: boolean, disabled: boolean) {\n if (disabled) return 'text-gray-a9'\n if (!hasLabel) return 'text-gray-11'\n return hovered ? 'text-spark-11' : 'text-gray-12'\n}\n\nfunction Star({ className }: { className: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n className={cn(\n 'transition-colors motion-reduce:transition-none',\n className,\n )}\n >\n <path d=\"M12.60 3.17 L14.72 8.03 Q15.00 8.67 15.69 8.74 L20.97 9.26 Q22.46 9.40 21.34 10.40 L17.37 13.91 Q16.85 14.38 17.00 15.06 L18.14 20.23 Q18.47 21.70 17.17 20.94 L12.60 18.25 Q12.00 17.90 11.40 18.25 L6.83 20.94 Q5.53 21.70 5.86 20.23 L7.00 15.06 Q7.15 14.38 6.63 13.91 L2.66 10.40 Q1.54 9.40 3.03 9.26 L8.31 8.74 Q9.00 8.67 9.28 8.03 L11.40 3.17 Q12.00 1.80 12.60 3.17Z\" />\n </svg>\n )\n}\n\ntype RatingStarsProps = Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'defaultValue' | 'onChange'\n>\n\nfunction RatingStars({\n className,\n onPointerLeave,\n onKeyDown,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedByProp,\n ...props\n}: RatingStarsProps) {\n const rating = useRating()\n const { field, ariaDescribedBy, ariaInvalid } = useFieldControl({\n ariaDescribedBy: ariaDescribedByProp,\n })\n const invalid = useFieldSetInvalid()\n const { star: starSize, button: buttonSize } = (\n rating.max > 5 ? compactSizeClasses : sizeClasses\n )[rating.size]\n const interactive = !rating.readOnly && !rating.disabled\n const low = Math.min(rating.value ?? 0, rating.hovered ?? rating.value ?? 0)\n const high = Math.max(rating.value ?? 0, rating.hovered ?? 0)\n\n return (\n <RadioGroupPrimitive<number | null>\n data-slot=\"rating-stars\"\n data-invalid={invalid}\n // a read-only FieldLabel renders the Field's labelId and drops a caller id\n aria-labelledby={\n ariaLabelledBy ?? (field?.readOnly ? field.labelId : undefined)\n }\n aria-describedby={ariaDescribedBy}\n aria-invalid={ariaInvalid}\n value={rating.value}\n onValueChange={(next) => next !== null && rating.setValue(next)}\n readOnly={rating.readOnly}\n disabled={rating.disabled}\n name={rating.name}\n className={cn('flex', className)}\n onPointerLeave={(event) => {\n rating.setHovered(null)\n onPointerLeave?.(event)\n }}\n onKeyDown={(event) => {\n rating.setHovered(null)\n onKeyDown?.(event)\n }}\n {...props}\n >\n {Array.from({ length: rating.max }, (_, index) => {\n const star = index + 1\n const fill: StarFill =\n star <= low ? 'on' : star <= high ? 'preview' : 'off'\n return (\n <RadioPrimitive.Root\n key={star}\n value={star}\n aria-label={rating.labels?.[index] ?? String(star)}\n data-slot=\"rating-star\"\n data-fill={fill}\n // ARIA allows aria-readonly on the radiogroup, which Base UI also sets, not on a radio\n aria-readonly={undefined}\n nativeButton\n render={<button />}\n onPointerEnter={\n interactive ? () => rating.setHovered(star) : undefined\n }\n className={cn(\n // p-0 keeps the box against the UA button padding without preflight;\n // the px floor keeps axe's 24px target size when [data-scaling] shrinks rems\n 'inline-flex min-h-[24px] min-w-[24px] shrink-0 cursor-pointer items-center justify-center rounded-sm border-0 bg-transparent p-0 touch-target-row any-pointer-coarse:min-w-11',\n 'focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n 'data-disabled:cursor-not-allowed data-readonly:cursor-default',\n buttonSize,\n )}\n >\n <Star className={cn(starSize, starTone(fill, rating.disabled))} />\n </RadioPrimitive.Root>\n )\n })}\n </RadioGroupPrimitive>\n )\n}\n\nconst captionTextSize: Record<RatingSize, string> = {\n small: 'text-[0.8125rem]',\n medium: 'text-sm',\n large: 'text-base',\n}\n\nfunction RatingCaption({\n className,\n children,\n ...props\n}: React.HTMLAttributes<HTMLParagraphElement>) {\n const rating = useRating()\n const shown = rating.hovered ?? rating.value\n const label = shown ? rating.labels?.[shown - 1] : undefined\n\n return (\n <p\n data-slot=\"rating-caption\"\n // the stars already carry each label as their accessible name\n aria-hidden=\"true\"\n // axe skips contrast on inactive text, and the dim tone is the disabled cue\n aria-disabled={rating.disabled || undefined}\n className={cn(\n 'leading-5',\n captionTextSize[rating.size],\n label !== undefined && 'font-medium',\n captionTone(label !== undefined, !!rating.hovered, rating.disabled),\n className,\n )}\n {...props}\n >\n {label ?? children}\n </p>\n )\n}\n\nexport { Rating, RatingCaption, RatingStars }\nexport type { RatingProps, RatingStarsProps }\n"],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React$1 from "react";
|
|
4
|
+
|
|
5
|
+
//#region src/components/rating.d.ts
|
|
6
|
+
type RatingSize = 'small' | 'medium' | 'large';
|
|
7
|
+
interface RatingProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, 'defaultValue' | 'onChange'> {
|
|
8
|
+
/** The chosen star, 1-based. `null` means nothing is chosen yet. */
|
|
9
|
+
value?: number | null;
|
|
10
|
+
defaultValue?: number | null;
|
|
11
|
+
onValueChange?: (value: number) => void;
|
|
12
|
+
max?: number;
|
|
13
|
+
/** One label per star: the star's accessible name and the caption text. */
|
|
14
|
+
labels?: string[];
|
|
15
|
+
size?: RatingSize;
|
|
16
|
+
readOnly?: boolean;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
name?: string;
|
|
19
|
+
}
|
|
20
|
+
declare function Rating({
|
|
21
|
+
value: valueProp,
|
|
22
|
+
defaultValue,
|
|
23
|
+
onValueChange,
|
|
24
|
+
max,
|
|
25
|
+
labels,
|
|
26
|
+
size,
|
|
27
|
+
readOnly,
|
|
28
|
+
disabled,
|
|
29
|
+
name,
|
|
30
|
+
className,
|
|
31
|
+
children,
|
|
32
|
+
...props
|
|
33
|
+
}: RatingProps): import("react/jsx-runtime").JSX.Element;
|
|
34
|
+
type RatingStarsProps = Omit<React$1.HTMLAttributes<HTMLDivElement>, 'defaultValue' | 'onChange'>;
|
|
35
|
+
declare function RatingStars({
|
|
36
|
+
className,
|
|
37
|
+
onPointerLeave,
|
|
38
|
+
onKeyDown,
|
|
39
|
+
'aria-labelledby': ariaLabelledBy,
|
|
40
|
+
'aria-describedby': ariaDescribedByProp,
|
|
41
|
+
...props
|
|
42
|
+
}: RatingStarsProps): import("react/jsx-runtime").JSX.Element;
|
|
43
|
+
declare function RatingCaption({
|
|
44
|
+
className,
|
|
45
|
+
children,
|
|
46
|
+
...props
|
|
47
|
+
}: React$1.HTMLAttributes<HTMLParagraphElement>): import("react/jsx-runtime").JSX.Element;
|
|
48
|
+
//#endregion
|
|
49
|
+
export { Rating, RatingCaption, type RatingProps, RatingStars, type RatingStarsProps };
|
|
50
|
+
//# sourceMappingURL=rating.d.cts.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React$1 from "react";
|
|
4
|
+
|
|
5
|
+
//#region src/components/rating.d.ts
|
|
6
|
+
type RatingSize = 'small' | 'medium' | 'large';
|
|
7
|
+
interface RatingProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, 'defaultValue' | 'onChange'> {
|
|
8
|
+
/** The chosen star, 1-based. `null` means nothing is chosen yet. */
|
|
9
|
+
value?: number | null;
|
|
10
|
+
defaultValue?: number | null;
|
|
11
|
+
onValueChange?: (value: number) => void;
|
|
12
|
+
max?: number;
|
|
13
|
+
/** One label per star: the star's accessible name and the caption text. */
|
|
14
|
+
labels?: string[];
|
|
15
|
+
size?: RatingSize;
|
|
16
|
+
readOnly?: boolean;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
name?: string;
|
|
19
|
+
}
|
|
20
|
+
declare function Rating({
|
|
21
|
+
value: valueProp,
|
|
22
|
+
defaultValue,
|
|
23
|
+
onValueChange,
|
|
24
|
+
max,
|
|
25
|
+
labels,
|
|
26
|
+
size,
|
|
27
|
+
readOnly,
|
|
28
|
+
disabled,
|
|
29
|
+
name,
|
|
30
|
+
className,
|
|
31
|
+
children,
|
|
32
|
+
...props
|
|
33
|
+
}: RatingProps): import("react/jsx-runtime").JSX.Element;
|
|
34
|
+
type RatingStarsProps = Omit<React$1.HTMLAttributes<HTMLDivElement>, 'defaultValue' | 'onChange'>;
|
|
35
|
+
declare function RatingStars({
|
|
36
|
+
className,
|
|
37
|
+
onPointerLeave,
|
|
38
|
+
onKeyDown,
|
|
39
|
+
'aria-labelledby': ariaLabelledBy,
|
|
40
|
+
'aria-describedby': ariaDescribedByProp,
|
|
41
|
+
...props
|
|
42
|
+
}: RatingStarsProps): import("react/jsx-runtime").JSX.Element;
|
|
43
|
+
declare function RatingCaption({
|
|
44
|
+
className,
|
|
45
|
+
children,
|
|
46
|
+
...props
|
|
47
|
+
}: React$1.HTMLAttributes<HTMLParagraphElement>): import("react/jsx-runtime").JSX.Element;
|
|
48
|
+
//#endregion
|
|
49
|
+
export { Rating, RatingCaption, type RatingProps, RatingStars, type RatingStarsProps };
|
|
50
|
+
//# sourceMappingURL=rating.d.ts.map
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../utils/cn.js";
|
|
3
|
+
import { useFieldControl, useFieldSetInvalid } from "./field.js";
|
|
4
|
+
import * as React$1 from "react";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
import { Radio } from "@base-ui/react/radio";
|
|
7
|
+
import { RadioGroup } from "@base-ui/react/radio-group";
|
|
8
|
+
//#region src/components/rating.tsx
|
|
9
|
+
const RatingContext = React$1.createContext(null);
|
|
10
|
+
function useRating() {
|
|
11
|
+
const context = React$1.useContext(RatingContext);
|
|
12
|
+
if (!context) throw new Error("RatingStars and RatingCaption need a Rating");
|
|
13
|
+
return context;
|
|
14
|
+
}
|
|
15
|
+
function Rating({ value: valueProp, defaultValue = null, onValueChange, max = 5, labels, size = "medium", readOnly = false, disabled = false, name, className, children, ...props }) {
|
|
16
|
+
const [uncontrolled, setUncontrolled] = React$1.useState(defaultValue);
|
|
17
|
+
const [hovered, setHovered] = React$1.useState(null);
|
|
18
|
+
const value = valueProp === void 0 ? uncontrolled : valueProp;
|
|
19
|
+
const setValue = React$1.useCallback((next) => {
|
|
20
|
+
setUncontrolled(next);
|
|
21
|
+
onValueChange?.(next);
|
|
22
|
+
}, [onValueChange]);
|
|
23
|
+
return /* @__PURE__ */ jsx(RatingContext.Provider, {
|
|
24
|
+
value: {
|
|
25
|
+
value,
|
|
26
|
+
setValue,
|
|
27
|
+
hovered: readOnly || disabled ? null : hovered,
|
|
28
|
+
setHovered,
|
|
29
|
+
max,
|
|
30
|
+
labels,
|
|
31
|
+
size,
|
|
32
|
+
readOnly,
|
|
33
|
+
disabled,
|
|
34
|
+
name
|
|
35
|
+
},
|
|
36
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
37
|
+
"data-slot": "rating",
|
|
38
|
+
className: cn("flex flex-col items-start gap-[calc(var(--spark-layout-gap)*1)]", className),
|
|
39
|
+
...props,
|
|
40
|
+
children
|
|
41
|
+
})
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const sizeClasses = {
|
|
45
|
+
small: {
|
|
46
|
+
star: "size-4",
|
|
47
|
+
button: "size-6"
|
|
48
|
+
},
|
|
49
|
+
medium: {
|
|
50
|
+
star: "size-6",
|
|
51
|
+
button: "size-8"
|
|
52
|
+
},
|
|
53
|
+
large: {
|
|
54
|
+
star: "size-8",
|
|
55
|
+
button: "size-11"
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const compactSizeClasses = {
|
|
59
|
+
small: {
|
|
60
|
+
star: "size-3.5",
|
|
61
|
+
button: "size-6"
|
|
62
|
+
},
|
|
63
|
+
medium: {
|
|
64
|
+
star: "size-4.5",
|
|
65
|
+
button: "size-6"
|
|
66
|
+
},
|
|
67
|
+
large: {
|
|
68
|
+
star: "size-5",
|
|
69
|
+
button: "size-6"
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
function starTone(fill, disabled) {
|
|
73
|
+
if (disabled) return fill === "off" ? "fill-none stroke-gray-a6" : "fill-gray-a7 stroke-gray-a7";
|
|
74
|
+
if (fill === "on") return "fill-spark-9 stroke-spark-9";
|
|
75
|
+
if (fill === "preview") return "fill-spark-a4 stroke-spark-9";
|
|
76
|
+
return "fill-none stroke-gray-a9";
|
|
77
|
+
}
|
|
78
|
+
function captionTone(hasLabel, hovered, disabled) {
|
|
79
|
+
if (disabled) return "text-gray-a9";
|
|
80
|
+
if (!hasLabel) return "text-gray-11";
|
|
81
|
+
return hovered ? "text-spark-11" : "text-gray-12";
|
|
82
|
+
}
|
|
83
|
+
function Star({ className }) {
|
|
84
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
85
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
86
|
+
viewBox: "0 0 24 24",
|
|
87
|
+
strokeWidth: 1.5,
|
|
88
|
+
strokeLinejoin: "round",
|
|
89
|
+
"aria-hidden": "true",
|
|
90
|
+
className: cn("transition-colors motion-reduce:transition-none", className),
|
|
91
|
+
children: /* @__PURE__ */ jsx("path", { d: "M12.60 3.17 L14.72 8.03 Q15.00 8.67 15.69 8.74 L20.97 9.26 Q22.46 9.40 21.34 10.40 L17.37 13.91 Q16.85 14.38 17.00 15.06 L18.14 20.23 Q18.47 21.70 17.17 20.94 L12.60 18.25 Q12.00 17.90 11.40 18.25 L6.83 20.94 Q5.53 21.70 5.86 20.23 L7.00 15.06 Q7.15 14.38 6.63 13.91 L2.66 10.40 Q1.54 9.40 3.03 9.26 L8.31 8.74 Q9.00 8.67 9.28 8.03 L11.40 3.17 Q12.00 1.80 12.60 3.17Z" })
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
function RatingStars({ className, onPointerLeave, onKeyDown, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedByProp, ...props }) {
|
|
95
|
+
const rating = useRating();
|
|
96
|
+
const { field, ariaDescribedBy, ariaInvalid } = useFieldControl({ ariaDescribedBy: ariaDescribedByProp });
|
|
97
|
+
const invalid = useFieldSetInvalid();
|
|
98
|
+
const { star: starSize, button: buttonSize } = (rating.max > 5 ? compactSizeClasses : sizeClasses)[rating.size];
|
|
99
|
+
const interactive = !rating.readOnly && !rating.disabled;
|
|
100
|
+
const low = Math.min(rating.value ?? 0, rating.hovered ?? rating.value ?? 0);
|
|
101
|
+
const high = Math.max(rating.value ?? 0, rating.hovered ?? 0);
|
|
102
|
+
return /* @__PURE__ */ jsx(RadioGroup, {
|
|
103
|
+
"data-slot": "rating-stars",
|
|
104
|
+
"data-invalid": invalid,
|
|
105
|
+
"aria-labelledby": ariaLabelledBy ?? (field?.readOnly ? field.labelId : void 0),
|
|
106
|
+
"aria-describedby": ariaDescribedBy,
|
|
107
|
+
"aria-invalid": ariaInvalid,
|
|
108
|
+
value: rating.value,
|
|
109
|
+
onValueChange: (next) => next !== null && rating.setValue(next),
|
|
110
|
+
readOnly: rating.readOnly,
|
|
111
|
+
disabled: rating.disabled,
|
|
112
|
+
name: rating.name,
|
|
113
|
+
className: cn("flex", className),
|
|
114
|
+
onPointerLeave: (event) => {
|
|
115
|
+
rating.setHovered(null);
|
|
116
|
+
onPointerLeave?.(event);
|
|
117
|
+
},
|
|
118
|
+
onKeyDown: (event) => {
|
|
119
|
+
rating.setHovered(null);
|
|
120
|
+
onKeyDown?.(event);
|
|
121
|
+
},
|
|
122
|
+
...props,
|
|
123
|
+
children: Array.from({ length: rating.max }, (_, index) => {
|
|
124
|
+
const star = index + 1;
|
|
125
|
+
const fill = star <= low ? "on" : star <= high ? "preview" : "off";
|
|
126
|
+
return /* @__PURE__ */ jsx(Radio.Root, {
|
|
127
|
+
value: star,
|
|
128
|
+
"aria-label": rating.labels?.[index] ?? String(star),
|
|
129
|
+
"data-slot": "rating-star",
|
|
130
|
+
"data-fill": fill,
|
|
131
|
+
"aria-readonly": void 0,
|
|
132
|
+
nativeButton: true,
|
|
133
|
+
render: /* @__PURE__ */ jsx("button", {}),
|
|
134
|
+
onPointerEnter: interactive ? () => rating.setHovered(star) : void 0,
|
|
135
|
+
className: cn("inline-flex min-h-[24px] min-w-[24px] shrink-0 cursor-pointer items-center justify-center rounded-sm border-0 bg-transparent p-0 touch-target-row any-pointer-coarse:min-w-11", "focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden", "data-disabled:cursor-not-allowed data-readonly:cursor-default", buttonSize),
|
|
136
|
+
children: /* @__PURE__ */ jsx(Star, { className: cn(starSize, starTone(fill, rating.disabled)) })
|
|
137
|
+
}, star);
|
|
138
|
+
})
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
const captionTextSize = {
|
|
142
|
+
small: "text-[0.8125rem]",
|
|
143
|
+
medium: "text-sm",
|
|
144
|
+
large: "text-base"
|
|
145
|
+
};
|
|
146
|
+
function RatingCaption({ className, children, ...props }) {
|
|
147
|
+
const rating = useRating();
|
|
148
|
+
const shown = rating.hovered ?? rating.value;
|
|
149
|
+
const label = shown ? rating.labels?.[shown - 1] : void 0;
|
|
150
|
+
return /* @__PURE__ */ jsx("p", {
|
|
151
|
+
"data-slot": "rating-caption",
|
|
152
|
+
"aria-hidden": "true",
|
|
153
|
+
"aria-disabled": rating.disabled || void 0,
|
|
154
|
+
className: cn("leading-5", captionTextSize[rating.size], label !== void 0 && "font-medium", captionTone(label !== void 0, !!rating.hovered, rating.disabled), className),
|
|
155
|
+
...props,
|
|
156
|
+
children: label ?? children
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
//#endregion
|
|
160
|
+
export { Rating, RatingCaption, RatingStars };
|
|
161
|
+
|
|
162
|
+
//# sourceMappingURL=rating.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rating.js","names":["React","RadioGroupPrimitive","RadioPrimitive"],"sources":["../../src/components/rating.tsx"],"sourcesContent":["import { Radio as RadioPrimitive } from '@base-ui/react/radio'\nimport { RadioGroup as RadioGroupPrimitive } from '@base-ui/react/radio-group'\nimport * as React from 'react'\nimport { cn } from '../utils/cn'\nimport { useFieldControl, useFieldSetInvalid } from './field'\n\ntype RatingSize = 'small' | 'medium' | 'large'\n\ntype RatingContextValue = {\n value: number | null\n setValue: (value: number) => void\n hovered: number | null\n setHovered: (value: number | null) => void\n max: number\n labels?: string[]\n size: RatingSize\n readOnly: boolean\n disabled: boolean\n name?: string\n}\n\nconst RatingContext = React.createContext<RatingContextValue | null>(null)\n\nfunction useRating() {\n const context = React.useContext(RatingContext)\n if (!context) throw new Error('RatingStars and RatingCaption need a Rating')\n return context\n}\n\ninterface RatingProps extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'defaultValue' | 'onChange'\n> {\n /** The chosen star, 1-based. `null` means nothing is chosen yet. */\n value?: number | null\n defaultValue?: number | null\n onValueChange?: (value: number) => void\n max?: number\n /** One label per star: the star's accessible name and the caption text. */\n labels?: string[]\n size?: RatingSize\n readOnly?: boolean\n disabled?: boolean\n name?: string\n}\n\nfunction Rating({\n value: valueProp,\n defaultValue = null,\n onValueChange,\n max = 5,\n labels,\n size = 'medium',\n readOnly = false,\n disabled = false,\n name,\n className,\n children,\n ...props\n}: RatingProps) {\n const [uncontrolled, setUncontrolled] = React.useState(defaultValue)\n const [hovered, setHovered] = React.useState<number | null>(null)\n const value = valueProp === undefined ? uncontrolled : valueProp\n\n const setValue = React.useCallback(\n (next: number) => {\n setUncontrolled(next)\n onValueChange?.(next)\n },\n [onValueChange],\n )\n\n return (\n <RatingContext.Provider\n value={{\n value,\n setValue,\n hovered: readOnly || disabled ? null : hovered,\n setHovered,\n max,\n labels,\n size,\n readOnly,\n disabled,\n name,\n }}\n >\n <div\n data-slot=\"rating\"\n className={cn(\n 'flex flex-col items-start gap-[calc(var(--spark-layout-gap)*1)]',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n </RatingContext.Provider>\n )\n}\n\ntype SizeClasses = { star: string; button: string }\n\nconst sizeClasses: Record<RatingSize, SizeClasses> = {\n small: { star: 'size-4', button: 'size-6' },\n medium: { star: 'size-6', button: 'size-8' },\n large: { star: 'size-8', button: 'size-11' },\n}\n\n// above five stars the row would outgrow narrow panels\nconst compactSizeClasses: Record<RatingSize, SizeClasses> = {\n small: { star: 'size-3.5', button: 'size-6' },\n medium: { star: 'size-4.5', button: 'size-6' },\n large: { star: 'size-5', button: 'size-6' },\n}\n\ntype StarFill = 'on' | 'preview' | 'off'\n\nfunction starTone(fill: StarFill, disabled: boolean) {\n if (disabled) {\n return fill === 'off'\n ? 'fill-none stroke-gray-a6'\n : 'fill-gray-a7 stroke-gray-a7'\n }\n if (fill === 'on') return 'fill-spark-9 stroke-spark-9'\n if (fill === 'preview') return 'fill-spark-a4 stroke-spark-9'\n return 'fill-none stroke-gray-a9'\n}\n\nfunction captionTone(hasLabel: boolean, hovered: boolean, disabled: boolean) {\n if (disabled) return 'text-gray-a9'\n if (!hasLabel) return 'text-gray-11'\n return hovered ? 'text-spark-11' : 'text-gray-12'\n}\n\nfunction Star({ className }: { className: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n strokeWidth={1.5}\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n className={cn(\n 'transition-colors motion-reduce:transition-none',\n className,\n )}\n >\n <path d=\"M12.60 3.17 L14.72 8.03 Q15.00 8.67 15.69 8.74 L20.97 9.26 Q22.46 9.40 21.34 10.40 L17.37 13.91 Q16.85 14.38 17.00 15.06 L18.14 20.23 Q18.47 21.70 17.17 20.94 L12.60 18.25 Q12.00 17.90 11.40 18.25 L6.83 20.94 Q5.53 21.70 5.86 20.23 L7.00 15.06 Q7.15 14.38 6.63 13.91 L2.66 10.40 Q1.54 9.40 3.03 9.26 L8.31 8.74 Q9.00 8.67 9.28 8.03 L11.40 3.17 Q12.00 1.80 12.60 3.17Z\" />\n </svg>\n )\n}\n\ntype RatingStarsProps = Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'defaultValue' | 'onChange'\n>\n\nfunction RatingStars({\n className,\n onPointerLeave,\n onKeyDown,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedByProp,\n ...props\n}: RatingStarsProps) {\n const rating = useRating()\n const { field, ariaDescribedBy, ariaInvalid } = useFieldControl({\n ariaDescribedBy: ariaDescribedByProp,\n })\n const invalid = useFieldSetInvalid()\n const { star: starSize, button: buttonSize } = (\n rating.max > 5 ? compactSizeClasses : sizeClasses\n )[rating.size]\n const interactive = !rating.readOnly && !rating.disabled\n const low = Math.min(rating.value ?? 0, rating.hovered ?? rating.value ?? 0)\n const high = Math.max(rating.value ?? 0, rating.hovered ?? 0)\n\n return (\n <RadioGroupPrimitive<number | null>\n data-slot=\"rating-stars\"\n data-invalid={invalid}\n // a read-only FieldLabel renders the Field's labelId and drops a caller id\n aria-labelledby={\n ariaLabelledBy ?? (field?.readOnly ? field.labelId : undefined)\n }\n aria-describedby={ariaDescribedBy}\n aria-invalid={ariaInvalid}\n value={rating.value}\n onValueChange={(next) => next !== null && rating.setValue(next)}\n readOnly={rating.readOnly}\n disabled={rating.disabled}\n name={rating.name}\n className={cn('flex', className)}\n onPointerLeave={(event) => {\n rating.setHovered(null)\n onPointerLeave?.(event)\n }}\n onKeyDown={(event) => {\n rating.setHovered(null)\n onKeyDown?.(event)\n }}\n {...props}\n >\n {Array.from({ length: rating.max }, (_, index) => {\n const star = index + 1\n const fill: StarFill =\n star <= low ? 'on' : star <= high ? 'preview' : 'off'\n return (\n <RadioPrimitive.Root\n key={star}\n value={star}\n aria-label={rating.labels?.[index] ?? String(star)}\n data-slot=\"rating-star\"\n data-fill={fill}\n // ARIA allows aria-readonly on the radiogroup, which Base UI also sets, not on a radio\n aria-readonly={undefined}\n nativeButton\n render={<button />}\n onPointerEnter={\n interactive ? () => rating.setHovered(star) : undefined\n }\n className={cn(\n // p-0 keeps the box against the UA button padding without preflight;\n // the px floor keeps axe's 24px target size when [data-scaling] shrinks rems\n 'inline-flex min-h-[24px] min-w-[24px] shrink-0 cursor-pointer items-center justify-center rounded-sm border-0 bg-transparent p-0 touch-target-row any-pointer-coarse:min-w-11',\n 'focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n 'data-disabled:cursor-not-allowed data-readonly:cursor-default',\n buttonSize,\n )}\n >\n <Star className={cn(starSize, starTone(fill, rating.disabled))} />\n </RadioPrimitive.Root>\n )\n })}\n </RadioGroupPrimitive>\n )\n}\n\nconst captionTextSize: Record<RatingSize, string> = {\n small: 'text-[0.8125rem]',\n medium: 'text-sm',\n large: 'text-base',\n}\n\nfunction RatingCaption({\n className,\n children,\n ...props\n}: React.HTMLAttributes<HTMLParagraphElement>) {\n const rating = useRating()\n const shown = rating.hovered ?? rating.value\n const label = shown ? rating.labels?.[shown - 1] : undefined\n\n return (\n <p\n data-slot=\"rating-caption\"\n // the stars already carry each label as their accessible name\n aria-hidden=\"true\"\n // axe skips contrast on inactive text, and the dim tone is the disabled cue\n aria-disabled={rating.disabled || undefined}\n className={cn(\n 'leading-5',\n captionTextSize[rating.size],\n label !== undefined && 'font-medium',\n captionTone(label !== undefined, !!rating.hovered, rating.disabled),\n className,\n )}\n {...props}\n >\n {label ?? children}\n </p>\n )\n}\n\nexport { Rating, RatingCaption, RatingStars }\nexport type { RatingProps, RatingStarsProps }\n"],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@ let react_jsx_runtime = require("react/jsx-runtime");
|
|
|
7
7
|
let _base_ui_react_scroll_area = require("@base-ui/react/scroll-area");
|
|
8
8
|
let cn = require("cn");
|
|
9
9
|
//#region src/components/scroll-area.tsx
|
|
10
|
+
const VIEWPORT_CLASSES = "size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden motion-reduce:transition-none";
|
|
10
11
|
function ScrollArea({ className, children, ...props }) {
|
|
11
12
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_base_ui_react_scroll_area.ScrollArea.Root, {
|
|
12
13
|
"data-slot": "scroll-area",
|
|
@@ -15,7 +16,7 @@ function ScrollArea({ className, children, ...props }) {
|
|
|
15
16
|
children: [
|
|
16
17
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_scroll_area.ScrollArea.Viewport, {
|
|
17
18
|
"data-slot": "scroll-area-viewport",
|
|
18
|
-
className:
|
|
19
|
+
className: VIEWPORT_CLASSES,
|
|
19
20
|
children
|
|
20
21
|
}),
|
|
21
22
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScrollBar, {}),
|
|
@@ -37,7 +38,13 @@ function ScrollBar({ className, orientation = "vertical", ...props }) {
|
|
|
37
38
|
});
|
|
38
39
|
}
|
|
39
40
|
const ScrollAreaRoot = _base_ui_react_scroll_area.ScrollArea.Root;
|
|
40
|
-
const ScrollAreaViewport = _base_ui_react_scroll_area.ScrollArea.Viewport
|
|
41
|
+
const ScrollAreaViewport = react.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_scroll_area.ScrollArea.Viewport, {
|
|
42
|
+
ref,
|
|
43
|
+
"data-slot": "scroll-area-viewport",
|
|
44
|
+
className: (0, cn.cn)(VIEWPORT_CLASSES, className),
|
|
45
|
+
...props
|
|
46
|
+
}));
|
|
47
|
+
ScrollAreaViewport.displayName = "ScrollAreaViewport";
|
|
41
48
|
const ScrollAreaScrollbar = _base_ui_react_scroll_area.ScrollArea.Scrollbar;
|
|
42
49
|
const ScrollAreaThumb = _base_ui_react_scroll_area.ScrollArea.Thumb;
|
|
43
50
|
const ScrollAreaCorner = _base_ui_react_scroll_area.ScrollArea.Corner;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scroll-area.cjs","names":["ScrollAreaPrimitive"],"sources":["../../src/components/scroll-area.tsx"],"sourcesContent":["import { ScrollArea as ScrollAreaPrimitive } from '@base-ui/react/scroll-area'\nimport * as React from 'react'\nimport { cn } from '../utils/cn'\n\nfunction ScrollArea({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {\n return (\n <ScrollAreaPrimitive.Root\n data-slot=\"scroll-area\"\n className={cn('relative', className)}\n {...props}\n >\n <ScrollAreaPrimitive.Viewport\n data-slot=\"scroll-area-viewport\"\n className
|
|
1
|
+
{"version":3,"file":"scroll-area.cjs","names":["ScrollAreaPrimitive","React"],"sources":["../../src/components/scroll-area.tsx"],"sourcesContent":["import { ScrollArea as ScrollAreaPrimitive } from '@base-ui/react/scroll-area'\nimport * as React from 'react'\nimport { cn } from '../utils/cn'\n\nconst VIEWPORT_CLASSES =\n 'size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden motion-reduce:transition-none'\n\nfunction ScrollArea({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {\n return (\n <ScrollAreaPrimitive.Root\n data-slot=\"scroll-area\"\n className={cn('relative', className)}\n {...props}\n >\n <ScrollAreaPrimitive.Viewport\n data-slot=\"scroll-area-viewport\"\n className={VIEWPORT_CLASSES}\n >\n {children}\n </ScrollAreaPrimitive.Viewport>\n <ScrollBar />\n <ScrollAreaPrimitive.Corner />\n </ScrollAreaPrimitive.Root>\n )\n}\n\nfunction ScrollBar({\n className,\n orientation = 'vertical',\n ...props\n}: React.ComponentProps<typeof ScrollAreaPrimitive.Scrollbar>) {\n return (\n <ScrollAreaPrimitive.Scrollbar\n data-slot=\"scroll-area-scrollbar\"\n data-orientation={orientation}\n orientation={orientation}\n className={cn(\n 'flex touch-none p-px transition-colors select-none data-[orientation=horizontal]:h-2.5 data-[orientation=horizontal]:flex-col data-[orientation=horizontal]:border-t data-[orientation=horizontal]:border-t-transparent data-[orientation=vertical]:h-full data-[orientation=vertical]:w-2.5 data-[orientation=vertical]:border-l data-[orientation=vertical]:border-l-transparent',\n // radix type=\"hover\" behavior: fade in on hover/scroll, fade out 600ms later\n 'opacity-0 transition-[color,background-color,opacity] delay-[600ms] duration-150 data-hovering:opacity-100 data-hovering:delay-0 data-scrolling:opacity-100 data-scrolling:delay-0 motion-reduce:transition-none',\n className,\n )}\n {...props}\n >\n <ScrollAreaPrimitive.Thumb\n data-slot=\"scroll-area-thumb\"\n className=\"relative flex-1 rounded-full bg-gray-a8 [[data-high-contrast]_&]:bg-gray-a11\"\n />\n </ScrollAreaPrimitive.Scrollbar>\n )\n}\n\n// Radix primitives for consumers that need a custom composition (e.g. an\n// aria-labelled focusable viewport or a horizontal-only scroll area)\nconst ScrollAreaRoot = ScrollAreaPrimitive.Root\nconst ScrollAreaViewport = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Viewport>\n>(({ className, ...props }, ref) => (\n <ScrollAreaPrimitive.Viewport\n ref={ref}\n data-slot=\"scroll-area-viewport\"\n className={cn(VIEWPORT_CLASSES, className)}\n {...props}\n />\n))\nScrollAreaViewport.displayName = 'ScrollAreaViewport'\nconst ScrollAreaScrollbar = ScrollAreaPrimitive.Scrollbar\nconst ScrollAreaThumb = ScrollAreaPrimitive.Thumb\nconst ScrollAreaCorner = ScrollAreaPrimitive.Corner\n\nexport {\n ScrollArea,\n ScrollAreaCorner,\n ScrollAreaRoot,\n ScrollAreaScrollbar,\n ScrollAreaThumb,\n ScrollAreaViewport,\n ScrollBar,\n}\n"],"mappings":";;;;;;;;;AAIA,MAAM,mBACJ;AAEF,SAAS,WAAW,EAClB,WACA,UACA,GAAG,SACqD;CACxD,OACE,iBAAA,GAAA,kBAAA,MAACA,2BAAAA,WAAoB,MAArB;EACE,aAAU;EACV,YAAA,GAAA,GAAA,IAAc,YAAY,SAAS;EACnC,GAAI;YAHN;GAKE,iBAAA,GAAA,kBAAA,KAACA,2BAAAA,WAAoB,UAArB;IACE,aAAU;IACV,WAAW;IAEV;GAC2B,CAAA;GAC9B,iBAAA,GAAA,kBAAA,KAAC,WAAD,CAAY,CAAA;GACZ,iBAAA,GAAA,kBAAA,KAACA,2BAAAA,WAAoB,QAArB,CAA6B,CAAA;EACL;;AAE9B;AAEA,SAAS,UAAU,EACjB,WACA,cAAc,YACd,GAAG,SAC0D;CAC7D,OACE,iBAAA,GAAA,kBAAA,KAACA,2BAAAA,WAAoB,WAArB;EACE,aAAU;EACV,oBAAkB;EACL;EACb,YAAA,GAAA,GAAA,IACE,sXAEA,oNACA,SACF;EACA,GAAI;YAEJ,iBAAA,GAAA,kBAAA,KAACA,2BAAAA,WAAoB,OAArB;GACE,aAAU;GACV,WAAU;EACX,CAAA;CAC4B,CAAA;AAEnC;AAIA,MAAM,iBAAiBA,2BAAAA,WAAoB;AAC3C,MAAM,qBAAqBC,MAAM,YAG9B,EAAE,WAAW,GAAG,SAAS,QAC1B,iBAAA,GAAA,kBAAA,KAACD,2BAAAA,WAAoB,UAArB;CACO;CACL,aAAU;CACV,YAAA,GAAA,GAAA,IAAc,kBAAkB,SAAS;CACzC,GAAI;AACL,CAAA,CACF;AACD,mBAAmB,cAAc;AACjC,MAAM,sBAAsBA,2BAAAA,WAAoB;AAChD,MAAM,kBAAkBA,2BAAAA,WAAoB;AAC5C,MAAM,mBAAmBA,2BAAAA,WAAoB"}
|
|
@@ -15,7 +15,7 @@ declare function ScrollBar({
|
|
|
15
15
|
...props
|
|
16
16
|
}: React$1.ComponentProps<typeof ScrollArea$1.Scrollbar>): import("react/jsx-runtime").JSX.Element;
|
|
17
17
|
declare const ScrollAreaRoot: React$1.ForwardRefExoticComponent<Omit<import("@base-ui/react").ScrollAreaRootProps, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
|
|
18
|
-
declare const ScrollAreaViewport: React$1.ForwardRefExoticComponent<Omit<import("@base-ui/react").ScrollAreaViewportProps, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
|
|
18
|
+
declare const ScrollAreaViewport: React$1.ForwardRefExoticComponent<Omit<Omit<import("@base-ui/react").ScrollAreaViewportProps, "ref"> & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
|
|
19
19
|
declare const ScrollAreaScrollbar: React$1.ForwardRefExoticComponent<Omit<import("@base-ui/react").ScrollAreaScrollbarProps, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
|
|
20
20
|
declare const ScrollAreaThumb: React$1.ForwardRefExoticComponent<Omit<import("@base-ui/react").ScrollAreaThumbProps, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
|
|
21
21
|
declare const ScrollAreaCorner: React$1.ForwardRefExoticComponent<Omit<import("@base-ui/react").ScrollAreaCornerProps, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
|
|
@@ -15,7 +15,7 @@ declare function ScrollBar({
|
|
|
15
15
|
...props
|
|
16
16
|
}: React$1.ComponentProps<typeof ScrollArea$1.Scrollbar>): import("react/jsx-runtime").JSX.Element;
|
|
17
17
|
declare const ScrollAreaRoot: React$1.ForwardRefExoticComponent<Omit<import("@base-ui/react").ScrollAreaRootProps, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
|
|
18
|
-
declare const ScrollAreaViewport: React$1.ForwardRefExoticComponent<Omit<import("@base-ui/react").ScrollAreaViewportProps, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
|
|
18
|
+
declare const ScrollAreaViewport: React$1.ForwardRefExoticComponent<Omit<Omit<import("@base-ui/react").ScrollAreaViewportProps, "ref"> & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
|
|
19
19
|
declare const ScrollAreaScrollbar: React$1.ForwardRefExoticComponent<Omit<import("@base-ui/react").ScrollAreaScrollbarProps, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
|
|
20
20
|
declare const ScrollAreaThumb: React$1.ForwardRefExoticComponent<Omit<import("@base-ui/react").ScrollAreaThumbProps, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
|
|
21
21
|
declare const ScrollAreaCorner: React$1.ForwardRefExoticComponent<Omit<import("@base-ui/react").ScrollAreaCornerProps, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../utils/cn.js";
|
|
3
|
-
import "react";
|
|
3
|
+
import * as React$1 from "react";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
import { ScrollArea as ScrollArea$1 } from "@base-ui/react/scroll-area";
|
|
6
6
|
//#region src/components/scroll-area.tsx
|
|
7
|
+
const VIEWPORT_CLASSES = "size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden motion-reduce:transition-none";
|
|
7
8
|
function ScrollArea({ className, children, ...props }) {
|
|
8
9
|
return /* @__PURE__ */ jsxs(ScrollArea$1.Root, {
|
|
9
10
|
"data-slot": "scroll-area",
|
|
@@ -12,7 +13,7 @@ function ScrollArea({ className, children, ...props }) {
|
|
|
12
13
|
children: [
|
|
13
14
|
/* @__PURE__ */ jsx(ScrollArea$1.Viewport, {
|
|
14
15
|
"data-slot": "scroll-area-viewport",
|
|
15
|
-
className:
|
|
16
|
+
className: VIEWPORT_CLASSES,
|
|
16
17
|
children
|
|
17
18
|
}),
|
|
18
19
|
/* @__PURE__ */ jsx(ScrollBar, {}),
|
|
@@ -34,7 +35,13 @@ function ScrollBar({ className, orientation = "vertical", ...props }) {
|
|
|
34
35
|
});
|
|
35
36
|
}
|
|
36
37
|
const ScrollAreaRoot = ScrollArea$1.Root;
|
|
37
|
-
const ScrollAreaViewport = ScrollArea$1.Viewport
|
|
38
|
+
const ScrollAreaViewport = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(ScrollArea$1.Viewport, {
|
|
39
|
+
ref,
|
|
40
|
+
"data-slot": "scroll-area-viewport",
|
|
41
|
+
className: cn(VIEWPORT_CLASSES, className),
|
|
42
|
+
...props
|
|
43
|
+
}));
|
|
44
|
+
ScrollAreaViewport.displayName = "ScrollAreaViewport";
|
|
38
45
|
const ScrollAreaScrollbar = ScrollArea$1.Scrollbar;
|
|
39
46
|
const ScrollAreaThumb = ScrollArea$1.Thumb;
|
|
40
47
|
const ScrollAreaCorner = ScrollArea$1.Corner;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scroll-area.js","names":["ScrollAreaPrimitive"],"sources":["../../src/components/scroll-area.tsx"],"sourcesContent":["import { ScrollArea as ScrollAreaPrimitive } from '@base-ui/react/scroll-area'\nimport * as React from 'react'\nimport { cn } from '../utils/cn'\n\nfunction ScrollArea({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {\n return (\n <ScrollAreaPrimitive.Root\n data-slot=\"scroll-area\"\n className={cn('relative', className)}\n {...props}\n >\n <ScrollAreaPrimitive.Viewport\n data-slot=\"scroll-area-viewport\"\n className
|
|
1
|
+
{"version":3,"file":"scroll-area.js","names":["ScrollAreaPrimitive","React"],"sources":["../../src/components/scroll-area.tsx"],"sourcesContent":["import { ScrollArea as ScrollAreaPrimitive } from '@base-ui/react/scroll-area'\nimport * as React from 'react'\nimport { cn } from '../utils/cn'\n\nconst VIEWPORT_CLASSES =\n 'size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden motion-reduce:transition-none'\n\nfunction ScrollArea({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {\n return (\n <ScrollAreaPrimitive.Root\n data-slot=\"scroll-area\"\n className={cn('relative', className)}\n {...props}\n >\n <ScrollAreaPrimitive.Viewport\n data-slot=\"scroll-area-viewport\"\n className={VIEWPORT_CLASSES}\n >\n {children}\n </ScrollAreaPrimitive.Viewport>\n <ScrollBar />\n <ScrollAreaPrimitive.Corner />\n </ScrollAreaPrimitive.Root>\n )\n}\n\nfunction ScrollBar({\n className,\n orientation = 'vertical',\n ...props\n}: React.ComponentProps<typeof ScrollAreaPrimitive.Scrollbar>) {\n return (\n <ScrollAreaPrimitive.Scrollbar\n data-slot=\"scroll-area-scrollbar\"\n data-orientation={orientation}\n orientation={orientation}\n className={cn(\n 'flex touch-none p-px transition-colors select-none data-[orientation=horizontal]:h-2.5 data-[orientation=horizontal]:flex-col data-[orientation=horizontal]:border-t data-[orientation=horizontal]:border-t-transparent data-[orientation=vertical]:h-full data-[orientation=vertical]:w-2.5 data-[orientation=vertical]:border-l data-[orientation=vertical]:border-l-transparent',\n // radix type=\"hover\" behavior: fade in on hover/scroll, fade out 600ms later\n 'opacity-0 transition-[color,background-color,opacity] delay-[600ms] duration-150 data-hovering:opacity-100 data-hovering:delay-0 data-scrolling:opacity-100 data-scrolling:delay-0 motion-reduce:transition-none',\n className,\n )}\n {...props}\n >\n <ScrollAreaPrimitive.Thumb\n data-slot=\"scroll-area-thumb\"\n className=\"relative flex-1 rounded-full bg-gray-a8 [[data-high-contrast]_&]:bg-gray-a11\"\n />\n </ScrollAreaPrimitive.Scrollbar>\n )\n}\n\n// Radix primitives for consumers that need a custom composition (e.g. an\n// aria-labelled focusable viewport or a horizontal-only scroll area)\nconst ScrollAreaRoot = ScrollAreaPrimitive.Root\nconst ScrollAreaViewport = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Viewport>\n>(({ className, ...props }, ref) => (\n <ScrollAreaPrimitive.Viewport\n ref={ref}\n data-slot=\"scroll-area-viewport\"\n className={cn(VIEWPORT_CLASSES, className)}\n {...props}\n />\n))\nScrollAreaViewport.displayName = 'ScrollAreaViewport'\nconst ScrollAreaScrollbar = ScrollAreaPrimitive.Scrollbar\nconst ScrollAreaThumb = ScrollAreaPrimitive.Thumb\nconst ScrollAreaCorner = ScrollAreaPrimitive.Corner\n\nexport {\n ScrollArea,\n ScrollAreaCorner,\n ScrollAreaRoot,\n ScrollAreaScrollbar,\n ScrollAreaThumb,\n ScrollAreaViewport,\n ScrollBar,\n}\n"],"mappings":";;;;;;AAIA,MAAM,mBACJ;AAEF,SAAS,WAAW,EAClB,WACA,UACA,GAAG,SACqD;CACxD,OACE,qBAACA,aAAoB,MAArB;EACE,aAAU;EACV,WAAW,GAAG,YAAY,SAAS;EACnC,GAAI;YAHN;GAKE,oBAACA,aAAoB,UAArB;IACE,aAAU;IACV,WAAW;IAEV;GAC2B,CAAA;GAC9B,oBAAC,WAAD,CAAY,CAAA;GACZ,oBAACA,aAAoB,QAArB,CAA6B,CAAA;EACL;;AAE9B;AAEA,SAAS,UAAU,EACjB,WACA,cAAc,YACd,GAAG,SAC0D;CAC7D,OACE,oBAACA,aAAoB,WAArB;EACE,aAAU;EACV,oBAAkB;EACL;EACb,WAAW,GACT,sXAEA,oNACA,SACF;EACA,GAAI;YAEJ,oBAACA,aAAoB,OAArB;GACE,aAAU;GACV,WAAU;EACX,CAAA;CAC4B,CAAA;AAEnC;AAIA,MAAM,iBAAiBA,aAAoB;AAC3C,MAAM,qBAAqBC,QAAM,YAG9B,EAAE,WAAW,GAAG,SAAS,QAC1B,oBAACD,aAAoB,UAArB;CACO;CACL,aAAU;CACV,WAAW,GAAG,kBAAkB,SAAS;CACzC,GAAI;AACL,CAAA,CACF;AACD,mBAAmB,cAAc;AACjC,MAAM,sBAAsBA,aAAoB;AAChD,MAAM,kBAAkBA,aAAoB;AAC5C,MAAM,mBAAmBA,aAAoB"}
|