@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.
Files changed (185) hide show
  1. package/dist/components/alert-dialog.cjs +1 -1
  2. package/dist/components/alert-dialog.js +1 -1
  3. package/dist/components/attachment.d.cts +2 -2
  4. package/dist/components/attachment.d.ts +2 -2
  5. package/dist/components/avatar.d.cts +1 -1
  6. package/dist/components/avatar.d.ts +1 -1
  7. package/dist/components/badge.cjs +10 -2
  8. package/dist/components/badge.cjs.map +1 -1
  9. package/dist/components/badge.d.cts +2 -1
  10. package/dist/components/badge.d.ts +2 -1
  11. package/dist/components/badge.js +10 -2
  12. package/dist/components/badge.js.map +1 -1
  13. package/dist/components/banner.d.cts +1 -1
  14. package/dist/components/banner.d.ts +1 -1
  15. package/dist/components/box.d.cts +1 -1
  16. package/dist/components/box.d.ts +1 -1
  17. package/dist/components/bubble.cjs +1 -1
  18. package/dist/components/bubble.cjs.map +1 -1
  19. package/dist/components/bubble.d.cts +1 -1
  20. package/dist/components/bubble.d.ts +1 -1
  21. package/dist/components/bubble.js +1 -1
  22. package/dist/components/bubble.js.map +1 -1
  23. package/dist/components/button-group.d.cts +1 -1
  24. package/dist/components/button-group.d.ts +1 -1
  25. package/dist/components/button.cjs +27 -6
  26. package/dist/components/button.cjs.map +1 -1
  27. package/dist/components/button.d.cts +8 -7
  28. package/dist/components/button.d.ts +8 -7
  29. package/dist/components/button.js +27 -6
  30. package/dist/components/button.js.map +1 -1
  31. package/dist/components/callout.d.cts +1 -1
  32. package/dist/components/callout.d.ts +1 -1
  33. package/dist/components/card.cjs +8 -4
  34. package/dist/components/card.cjs.map +1 -1
  35. package/dist/components/card.d.cts +6 -2
  36. package/dist/components/card.d.ts +6 -2
  37. package/dist/components/card.js +8 -4
  38. package/dist/components/card.js.map +1 -1
  39. package/dist/components/checkbox-group.cjs +31 -0
  40. package/dist/components/checkbox-group.cjs.map +1 -0
  41. package/dist/components/checkbox-group.d.cts +27 -0
  42. package/dist/components/checkbox-group.d.ts +27 -0
  43. package/dist/components/checkbox-group.js +28 -0
  44. package/dist/components/checkbox-group.js.map +1 -0
  45. package/dist/components/checkbox.d.cts +1 -1
  46. package/dist/components/checkbox.d.ts +1 -1
  47. package/dist/components/dialog.cjs +1 -1
  48. package/dist/components/dialog.js +1 -1
  49. package/dist/components/empty-state.d.cts +3 -3
  50. package/dist/components/empty-state.d.ts +3 -3
  51. package/dist/components/field.cjs +110 -15
  52. package/dist/components/field.cjs.map +1 -1
  53. package/dist/components/field.d.cts +16 -3
  54. package/dist/components/field.d.ts +16 -3
  55. package/dist/components/field.js +111 -17
  56. package/dist/components/field.js.map +1 -1
  57. package/dist/components/input-group.cjs +9 -9
  58. package/dist/components/input-group.cjs.map +1 -1
  59. package/dist/components/input-group.d.cts +1 -1
  60. package/dist/components/input-group.d.ts +1 -1
  61. package/dist/components/input-group.js +9 -9
  62. package/dist/components/input-group.js.map +1 -1
  63. package/dist/components/input.d.cts +1 -1
  64. package/dist/components/input.d.ts +1 -1
  65. package/dist/components/list.cjs +21 -5
  66. package/dist/components/list.cjs.map +1 -1
  67. package/dist/components/list.d.cts +13 -5
  68. package/dist/components/list.d.ts +13 -5
  69. package/dist/components/list.js +21 -5
  70. package/dist/components/list.js.map +1 -1
  71. package/dist/components/marker.cjs +1 -1
  72. package/dist/components/marker.cjs.map +1 -1
  73. package/dist/components/marker.d.cts +1 -1
  74. package/dist/components/marker.d.ts +1 -1
  75. package/dist/components/marker.js +1 -1
  76. package/dist/components/marker.js.map +1 -1
  77. package/dist/components/page-header.d.cts +1 -1
  78. package/dist/components/page-header.d.ts +1 -1
  79. package/dist/components/pill.d.cts +1 -1
  80. package/dist/components/pill.d.ts +1 -1
  81. package/dist/components/radio.cjs +6 -2
  82. package/dist/components/radio.cjs.map +1 -1
  83. package/dist/components/radio.d.cts +4 -2
  84. package/dist/components/radio.d.ts +4 -2
  85. package/dist/components/radio.js +6 -2
  86. package/dist/components/radio.js.map +1 -1
  87. package/dist/components/rating.cjs +167 -0
  88. package/dist/components/rating.cjs.map +1 -0
  89. package/dist/components/rating.d.cts +50 -0
  90. package/dist/components/rating.d.ts +50 -0
  91. package/dist/components/rating.js +162 -0
  92. package/dist/components/rating.js.map +1 -0
  93. package/dist/components/scroll-area.cjs +9 -2
  94. package/dist/components/scroll-area.cjs.map +1 -1
  95. package/dist/components/scroll-area.d.cts +1 -1
  96. package/dist/components/scroll-area.d.ts +1 -1
  97. package/dist/components/scroll-area.js +10 -3
  98. package/dist/components/scroll-area.js.map +1 -1
  99. package/dist/components/segmented-control.d.cts +1 -1
  100. package/dist/components/segmented-control.d.ts +1 -1
  101. package/dist/components/select.d.cts +1 -1
  102. package/dist/components/select.d.ts +1 -1
  103. package/dist/components/selection-item.cjs +42 -0
  104. package/dist/components/selection-item.cjs.map +1 -0
  105. package/dist/components/selection-item.d.cts +25 -0
  106. package/dist/components/selection-item.d.ts +25 -0
  107. package/dist/components/selection-item.js +39 -0
  108. package/dist/components/selection-item.js.map +1 -0
  109. package/dist/components/sheet.cjs +1 -1
  110. package/dist/components/sheet.js +1 -1
  111. package/dist/components/skeleton.cjs +1 -1
  112. package/dist/components/skeleton.cjs.map +1 -1
  113. package/dist/components/skeleton.js +1 -1
  114. package/dist/components/skeleton.js.map +1 -1
  115. package/dist/components/slider.cjs +1 -1
  116. package/dist/components/slider.cjs.map +1 -1
  117. package/dist/components/slider.js +1 -1
  118. package/dist/components/slider.js.map +1 -1
  119. package/dist/components/spinner.cjs +81 -8
  120. package/dist/components/spinner.cjs.map +1 -1
  121. package/dist/components/spinner.js +81 -8
  122. package/dist/components/spinner.js.map +1 -1
  123. package/dist/components/stepper.cjs +3 -2
  124. package/dist/components/stepper.cjs.map +1 -1
  125. package/dist/components/stepper.js +3 -2
  126. package/dist/components/stepper.js.map +1 -1
  127. package/dist/components/switch-group.cjs +32 -0
  128. package/dist/components/switch-group.cjs.map +1 -0
  129. package/dist/components/switch-group.d.cts +26 -0
  130. package/dist/components/switch-group.d.ts +26 -0
  131. package/dist/components/switch-group.js +29 -0
  132. package/dist/components/switch-group.js.map +1 -0
  133. package/dist/components/switch.d.cts +1 -1
  134. package/dist/components/switch.d.ts +1 -1
  135. package/dist/components/tabs.cjs +32 -23
  136. package/dist/components/tabs.cjs.map +1 -1
  137. package/dist/components/tabs.d.cts +5 -5
  138. package/dist/components/tabs.d.ts +5 -5
  139. package/dist/components/tabs.js +32 -23
  140. package/dist/components/tabs.js.map +1 -1
  141. package/dist/components/textarea.d.cts +1 -1
  142. package/dist/components/textarea.d.ts +1 -1
  143. package/dist/components/theme.cjs +44 -2
  144. package/dist/components/theme.cjs.map +1 -1
  145. package/dist/components/theme.d.cts +4 -2
  146. package/dist/components/theme.d.ts +4 -2
  147. package/dist/components/theme.js +44 -2
  148. package/dist/components/theme.js.map +1 -1
  149. package/dist/components/toast.cjs +1 -1
  150. package/dist/components/toast.js +1 -1
  151. package/dist/components/toggle-group.d.cts +1 -1
  152. package/dist/components/toggle-group.d.ts +1 -1
  153. package/dist/components/toggle.d.cts +2 -2
  154. package/dist/components/toggle.d.ts +2 -2
  155. package/dist/lib/accent-theme.d.cts +1 -1
  156. package/dist/lib/accent-theme.d.ts +1 -1
  157. package/dist/lib/container-chrome.cjs +4 -4
  158. package/dist/lib/container-chrome.cjs.map +1 -1
  159. package/dist/lib/container-chrome.d.cts +1 -1
  160. package/dist/lib/container-chrome.d.ts +1 -1
  161. package/dist/lib/container-chrome.js +4 -4
  162. package/dist/lib/container-chrome.js.map +1 -1
  163. package/dist/lib/input-box-variants.cjs +8 -8
  164. package/dist/lib/input-box-variants.cjs.map +1 -1
  165. package/dist/lib/input-box-variants.d.cts +1 -1
  166. package/dist/lib/input-box-variants.d.ts +1 -1
  167. package/dist/lib/input-box-variants.js +8 -8
  168. package/dist/lib/input-box-variants.js.map +1 -1
  169. package/dist/lib/selection-list.cjs +17 -0
  170. package/dist/lib/selection-list.cjs.map +1 -0
  171. package/dist/lib/selection-list.d.cts +11 -0
  172. package/dist/lib/selection-list.d.ts +11 -0
  173. package/dist/lib/selection-list.js +15 -0
  174. package/dist/lib/selection-list.js.map +1 -0
  175. package/dist/lib/theme-types.cjs.map +1 -1
  176. package/dist/lib/theme-types.d.cts +2 -2
  177. package/dist/lib/theme-types.d.ts +2 -2
  178. package/dist/lib/theme-types.js.map +1 -1
  179. package/dist/lib/toggle-group-context.d.cts +2 -1
  180. package/dist/lib/toggle-group-context.d.ts +2 -1
  181. package/dist/styles/spark-default.css +12 -1
  182. package/dist/styles/theme.css +98 -0
  183. package/dist/{theme-types-Bn5E15-P.d.ts → theme-types-CKZzOmSa.d.cts} +11 -2
  184. package/dist/{theme-types-Bn5E15-P.d.cts → theme-types-CKZzOmSa.d.ts} +11 -2
  185. 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: "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",
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=\"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 >\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 = ScrollAreaPrimitive.Viewport\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,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,WAAU;IAET;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,qBAAqBA,2BAAAA,WAAoB;AAC/C,MAAM,sBAAsBA,2BAAAA,WAAoB;AAChD,MAAM,kBAAkBA,2BAAAA,WAAoB;AAC5C,MAAM,mBAAmBA,2BAAAA,WAAoB"}
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: "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",
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=\"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 >\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 = ScrollAreaPrimitive.Viewport\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,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,WAAU;IAET;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,qBAAqBA,aAAoB;AAC/C,MAAM,sBAAsBA,aAAoB;AAChD,MAAM,kBAAkBA,aAAoB;AAC5C,MAAM,mBAAmBA,aAAoB"}
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"}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { f as SparkStyle } from "../theme-types-Bn5E15-P.cjs";
3
+ import { g as SparkStyle } from "../theme-types-CKZzOmSa.cjs";
4
4
  import * as React$1 from "react";
5
5
  import { Tabs } from "@base-ui/react/tabs";
6
6
 
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { f as SparkStyle } from "../theme-types-Bn5E15-P.js";
3
+ import { g as SparkStyle } from "../theme-types-CKZzOmSa.js";
4
4
  import * as React$1 from "react";
5
5
  import { Tabs } from "@base-ui/react/tabs";
6
6