@flikk/ui 1.0.0-beta.30 → 1.0.0-beta.31

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 (295) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/dist/components/ai/AgentStatus/AgentStatus.d.ts +3 -0
  3. package/dist/components/ai/AgentStatus/AgentStatus.js +144 -0
  4. package/dist/components/ai/AgentStatus/AgentStatus.theme.d.ts +2 -0
  5. package/dist/components/ai/AgentStatus/AgentStatus.theme.js +37 -0
  6. package/dist/components/ai/AgentStatus/AgentStatus.types.d.ts +116 -0
  7. package/dist/components/ai/AgentStatus/index.d.ts +3 -0
  8. package/dist/components/ai/CodeBlock/CodeBlock.js +3 -3
  9. package/dist/components/ai/CodeBlock/CodeBlock.theme.js +1 -1
  10. package/dist/components/ai/PromptInput/PromptInput.js +13 -14
  11. package/dist/components/ai/PromptInput/PromptInput.theme.js +1 -1
  12. package/dist/components/ai/PromptInput/VoiceRecorder.js +3 -3
  13. package/dist/components/ai/Reasoning/Reasoning.d.ts +5 -0
  14. package/dist/components/ai/Reasoning/Reasoning.js +16 -0
  15. package/dist/components/ai/Reasoning/Reasoning.types.d.ts +20 -0
  16. package/dist/components/ai/Reasoning/index.d.ts +2 -0
  17. package/dist/components/ai/SourceCitation/SourceCitation.d.ts +4 -0
  18. package/dist/components/ai/SourceCitation/SourceCitation.js +29 -0
  19. package/dist/components/ai/SourceCitation/SourceCitation.theme.d.ts +2 -0
  20. package/dist/components/ai/SourceCitation/SourceCitation.theme.js +23 -0
  21. package/dist/components/ai/SourceCitation/SourceCitation.types.d.ts +55 -0
  22. package/dist/components/ai/SourceCitation/index.d.ts +3 -0
  23. package/dist/components/ai/StreamingResponse/ErrorDisplay.js +2 -2
  24. package/dist/components/ai/StreamingResponse/StreamingResponse.js +1 -3
  25. package/dist/components/ai/StreamingResponse/StreamingResponse.theme.js +3 -1
  26. package/dist/components/ai/TokenCounter/TokenCounter.js +2 -2
  27. package/dist/components/ai/index.d.ts +3 -0
  28. package/dist/components/ai/index.js +6 -3
  29. package/dist/components/ai/shared/StatusIndicator.d.ts +8 -0
  30. package/dist/components/ai/shared/StatusIndicator.js +34 -0
  31. package/dist/components/canvas/CanvasToolbar.js +2 -2
  32. package/dist/components/canvas/NodeControls.js +2 -2
  33. package/dist/components/canvas/NodeRenderer.js +2 -2
  34. package/dist/components/charts/ActivityRings/ActivityRings.js +2 -2
  35. package/dist/components/charts/AreaChart/AreaChart.js +21 -32
  36. package/dist/components/charts/AreaChart/AreaChart.theme.d.ts +1 -6
  37. package/dist/components/charts/AreaChart/AreaChart.theme.js +7 -19
  38. package/dist/components/charts/AreaChart/AreaChart.types.d.ts +18 -11
  39. package/dist/components/charts/AreaChart/AreaChart.types.js +10 -3
  40. package/dist/components/charts/AreaChart/index.d.ts +1 -1
  41. package/dist/components/charts/BarChart/BarChart.js +9 -28
  42. package/dist/components/charts/BarChart/BarChart.types.d.ts +20 -16
  43. package/dist/components/charts/BarChart/BarChart.types.js +11 -4
  44. package/dist/components/charts/ComboChart/BarRenderer.js +8 -5
  45. package/dist/components/charts/ComboChart/ComboChart.js +11 -24
  46. package/dist/components/charts/ComboChart/ComboChart.types.d.ts +15 -13
  47. package/dist/components/charts/ComboChart/ComboChart.types.js +14 -2
  48. package/dist/components/charts/ComboChart/LineRenderer.js +15 -10
  49. package/dist/components/charts/HorizontalBarChart/HorizontalBarChart.d.ts +16 -0
  50. package/dist/components/charts/HorizontalBarChart/HorizontalBarChart.js +237 -0
  51. package/dist/components/charts/HorizontalBarChart/HorizontalBarChart.types.d.ts +62 -0
  52. package/dist/components/charts/HorizontalBarChart/HorizontalBarChart.types.js +21 -0
  53. package/dist/components/charts/HorizontalBarChart/index.d.ts +3 -0
  54. package/dist/components/charts/LineChart/LineChart.js +9 -26
  55. package/dist/components/charts/LineChart/LineChart.types.d.ts +11 -14
  56. package/dist/components/charts/LineChart/LineChart.types.js +11 -3
  57. package/dist/components/charts/LollipopChart/LollipopChart.d.ts +3 -0
  58. package/dist/components/charts/LollipopChart/LollipopChart.js +361 -0
  59. package/dist/components/charts/LollipopChart/LollipopChart.types.d.ts +42 -0
  60. package/dist/components/charts/LollipopChart/LollipopChart.types.js +12 -0
  61. package/dist/components/charts/LollipopChart/index.d.ts +3 -0
  62. package/dist/components/charts/ScatterPlot/ScatterPlot.js +5 -4
  63. package/dist/components/charts/ScatterPlot/ScatterPlot.types.d.ts +14 -19
  64. package/dist/components/charts/ScatterPlot/ScatterPlot.types.js +9 -2
  65. package/dist/components/charts/StackedBarChart/StackedBarChart.js +150 -132
  66. package/dist/components/charts/StackedBarChart/StackedBarChart.types.d.ts +20 -18
  67. package/dist/components/charts/StackedBarChart/StackedBarChart.types.js +10 -4
  68. package/dist/components/charts/hooks/useChartAccessibility.d.ts +1 -1
  69. package/dist/components/charts/hooks/useChartAccessibility.js +3 -0
  70. package/dist/components/charts/hooks/useTooltipPosition.js +18 -6
  71. package/dist/components/charts/index.d.ts +6 -0
  72. package/dist/components/charts/index.js +6 -0
  73. package/dist/components/charts/shared/ChartAxis/CategoryYAxis.d.ts +14 -0
  74. package/dist/components/charts/shared/ChartAxis/CategoryYAxis.js +35 -0
  75. package/dist/components/charts/shared/ChartAxis/ChartAxis.types.d.ts +69 -8
  76. package/dist/components/charts/shared/ChartAxis/ValueXAxis.d.ts +14 -0
  77. package/dist/components/charts/shared/ChartAxis/ValueXAxis.js +64 -0
  78. package/dist/components/charts/shared/ChartAxis/XAxis.js +1 -1
  79. package/dist/components/charts/shared/ChartAxis/YAxis.js +2 -2
  80. package/dist/components/charts/shared/ChartAxis/index.d.ts +3 -1
  81. package/dist/components/charts/shared/ChartGrid/HorizontalGrid.d.ts +0 -2
  82. package/dist/components/charts/shared/ChartGrid/HorizontalGrid.js +1 -1
  83. package/dist/components/charts/shared/ChartGrid/VerticalGrid.d.ts +29 -0
  84. package/dist/components/charts/shared/ChartGrid/VerticalGrid.js +26 -0
  85. package/dist/components/charts/shared/ChartGrid/index.d.ts +2 -0
  86. package/dist/components/charts/shared/ChartMarker/ChartMarker.js +7 -1
  87. package/dist/components/charts/theme/chart.theme.js +18 -23
  88. package/dist/components/charts/types/chart.types.d.ts +9 -5
  89. package/dist/components/charts/types/chart.types.js +1 -7
  90. package/dist/components/charts/utils/animation-utils.js +1 -3
  91. package/dist/components/charts/utils/bar-emphasis.d.ts +32 -3
  92. package/dist/components/charts/utils/bar-emphasis.js +24 -8
  93. package/dist/components/charts/utils/index.d.ts +1 -0
  94. package/dist/components/charts/utils/series-color.d.ts +7 -0
  95. package/dist/components/charts/utils/series-color.js +20 -0
  96. package/dist/components/core/Accordion/Accordion.theme.js +2 -2
  97. package/dist/components/core/Accordion/AccordionTrigger.js +2 -2
  98. package/dist/components/core/Alert/Alert.animations.d.ts +2 -1
  99. package/dist/components/core/Alert/Alert.animations.js +21 -6
  100. package/dist/components/core/Alert/Alert.js +7 -7
  101. package/dist/components/core/Avatar/Avatar.js +50 -42
  102. package/dist/components/core/Avatar/Avatar.theme.d.ts +8 -4
  103. package/dist/components/core/Avatar/Avatar.theme.js +64 -8
  104. package/dist/components/core/Avatar/Avatar.types.d.ts +13 -2
  105. package/dist/components/core/Avatar/index.d.ts +1 -1
  106. package/dist/components/core/AvatarGroup/AvatarGroup.js +6 -8
  107. package/dist/components/core/AvatarGroup/AvatarGroup.theme.d.ts +1 -2
  108. package/dist/components/core/AvatarGroup/AvatarGroup.theme.js +2 -6
  109. package/dist/components/core/AvatarGroup/AvatarGroup.types.d.ts +0 -6
  110. package/dist/components/core/AvatarGroup/index.d.ts +1 -1
  111. package/dist/components/core/Badge/Badge.animations.js +4 -2
  112. package/dist/components/core/Badge/Badge.js +9 -4
  113. package/dist/components/core/Badge/Badge.theme.js +18 -12
  114. package/dist/components/core/Breadcrumbs/Breadcrumbs.theme.d.ts +1 -4
  115. package/dist/components/core/Breadcrumbs/Breadcrumbs.theme.js +2 -2
  116. package/dist/components/core/Button/Button.js +9 -17
  117. package/dist/components/core/Button/Button.ripple.js +2 -2
  118. package/dist/components/core/Button/Button.theme.d.ts +2 -0
  119. package/dist/components/core/Button/Button.theme.js +34 -21
  120. package/dist/components/core/Button/Button.types.d.ts +18 -1
  121. package/dist/components/core/Calendar/Calendar.js +20 -5
  122. package/dist/components/core/Calendar/Calendar.theme.js +14 -22
  123. package/dist/components/core/Calendar/Calendar.types.d.ts +0 -1
  124. package/dist/components/core/Calendar/CalendarMini/CalendarMini.js +3 -3
  125. package/dist/components/core/Card/Card.theme.js +12 -4
  126. package/dist/components/core/Card/CardBody.js +1 -1
  127. package/dist/components/core/Card/CardFooter.js +1 -1
  128. package/dist/components/core/Card/CardHeader.js +1 -1
  129. package/dist/components/core/Carousel/CarouselNext.js +2 -2
  130. package/dist/components/core/Carousel/CarouselPrevious.js +2 -2
  131. package/dist/components/core/CommandPalette/CommandPalette.js +5 -4
  132. package/dist/components/core/CommandPalette/CommandPalette.theme.js +3 -7
  133. package/dist/components/core/CommandPalette/CommandPalette.types.d.ts +2 -0
  134. package/dist/components/core/ContextMenu/ContextMenuItem.js +2 -2
  135. package/dist/components/core/ContextMenu/ContextMenuSubTrigger.js +2 -2
  136. package/dist/components/core/Drawer/Drawer.theme.js +7 -4
  137. package/dist/components/core/Drawer/DrawerHeader.js +2 -2
  138. package/dist/components/core/Dropdown/Dropdown.theme.js +3 -1
  139. package/dist/components/core/Dropdown/DropdownItem.js +2 -2
  140. package/dist/components/core/Dropdown/DropdownTrigger.js +16 -5
  141. package/dist/components/core/HeroCard/HeroCard.theme.js +5 -2
  142. package/dist/components/core/Kbd/Kbd.theme.js +4 -2
  143. package/dist/components/core/Link/Link.js +6 -4
  144. package/dist/components/core/Message/Message.js +2 -2
  145. package/dist/components/core/Message/Message.theme.js +5 -7
  146. package/dist/components/core/Message/MessageAudio.js +2 -2
  147. package/dist/components/core/Message/MessageFile.js +2 -2
  148. package/dist/components/core/Message/MessageLink.js +2 -2
  149. package/dist/components/core/Message/MessageStatusIndicator.js +5 -5
  150. package/dist/components/core/Modal/Modal.d.ts +1 -1
  151. package/dist/components/core/Modal/Modal.js +2 -2
  152. package/dist/components/core/Modal/Modal.theme.js +9 -4
  153. package/dist/components/core/Modal/ModalHeader.js +2 -2
  154. package/dist/components/core/ModalStack/ModalStackModal.js +2 -2
  155. package/dist/components/core/NavItem/NavItem.js +6 -6
  156. package/dist/components/core/OfflineIndicator/OfflineIndicator.animations.d.ts +22 -0
  157. package/dist/components/core/OfflineIndicator/OfflineIndicator.animations.js +54 -0
  158. package/dist/components/core/OfflineIndicator/OfflineIndicator.js +23 -24
  159. package/dist/components/core/OfflineIndicator/OfflineIndicator.theme.js +25 -6
  160. package/dist/components/core/OfflineIndicator/OfflineIndicator.types.d.ts +17 -0
  161. package/dist/components/core/PageHeading/PageHeading.theme.js +1 -1
  162. package/dist/components/core/PageHeading/PageHeadingBackButton.js +2 -2
  163. package/dist/components/core/Pagination/Pagination.js +3 -3
  164. package/dist/components/core/Pagination/Pagination.theme.js +3 -3
  165. package/dist/components/core/Pill/Pill.js +4 -2
  166. package/dist/components/core/Pill/Pill.theme.js +6 -4
  167. package/dist/components/core/Rating/Rating.js +4 -5
  168. package/dist/components/core/Rating/Rating.theme.js +1 -1
  169. package/dist/components/core/Segmented/Segmented.theme.js +9 -6
  170. package/dist/components/core/Sidebar/Sidebar.types.d.ts +4 -2
  171. package/dist/components/core/Sidebar/SidebarHeader.js +2 -2
  172. package/dist/components/core/Sidebar/SidebarMobileTrigger.js +2 -2
  173. package/dist/components/core/Sidebar/SidebarSearch.js +3 -3
  174. package/dist/components/core/Sidebar/SidebarToggle.js +3 -3
  175. package/dist/components/core/Sidebar/SidebarUserProfile.js +2 -2
  176. package/dist/components/core/Sortable/Sortable.js +2 -2
  177. package/dist/components/core/Tag/Tag.js +2 -2
  178. package/dist/components/core/Tag/Tag.theme.js +4 -2
  179. package/dist/components/core/Toast/Toast.js +3 -3
  180. package/dist/components/core/Toast/Toast.types.d.ts +1 -1
  181. package/dist/components/core/Toast/useToast.js +5 -5
  182. package/dist/components/core/Tooltip/Tooltip.d.ts +1 -1
  183. package/dist/components/core/Tooltip/Tooltip.js +42 -10
  184. package/dist/components/core/Tooltip/Tooltip.types.d.ts +25 -0
  185. package/dist/components/core/Tree/Tree.js +2 -2
  186. package/dist/components/core/shared/interaction.animations.d.ts +51 -0
  187. package/dist/components/core/shared/interaction.animations.js +59 -0
  188. package/dist/components/data-display/Feed/Feed.js +2 -2
  189. package/dist/components/data-display/GanttChart/GanttChart.theme.js +1 -1
  190. package/dist/components/data-display/GanttChart/GanttChartPanel.js +2 -2
  191. package/dist/components/data-display/GanttChart/GanttTableGroupRow.js +3 -3
  192. package/dist/components/data-display/GanttChart/GanttTaskContextMenu.js +2 -2
  193. package/dist/components/data-display/GanttChart/GanttToolbar.js +2 -2
  194. package/dist/components/data-display/KPI/KPI.js +2 -2
  195. package/dist/components/data-display/KPI/KPI.theme.js +4 -4
  196. package/dist/components/data-display/Metric/Metric.js +2 -2
  197. package/dist/components/data-display/Metric/Metric.theme.js +25 -8
  198. package/dist/components/data-display/Metric/Metric.types.d.ts +1 -1
  199. package/dist/components/data-display/Table/Table.theme.js +9 -9
  200. package/dist/components/data-display/Table/TableActions.js +2 -2
  201. package/dist/components/data-display/Table/TableActionsMenu.js +1 -1
  202. package/dist/components/data-display/Table/TableColumnManager.js +2 -2
  203. package/dist/components/data-display/Table/TableDeclarative.js +3 -3
  204. package/dist/components/data-display/Table/TableFilter.js +4 -4
  205. package/dist/components/data-display/Table/TableHeader.js +3 -3
  206. package/dist/components/data-display/Table/TableRow.js +2 -2
  207. package/dist/components/data-display/Table/TableSelectionHeader.js +3 -3
  208. package/dist/components/data-display/Timeline/TimelineMarker.js +2 -2
  209. package/dist/components/effects/CustomCursor/CustomCursor.js +2 -2
  210. package/dist/components/effects/CustomCursor/CustomCursor.theme.js +2 -2
  211. package/dist/components/effects/DotPattern/DotPattern.js +6 -0
  212. package/dist/components/effects/DotPattern/DotPattern.types.d.ts +4 -2
  213. package/dist/components/effects/MeshGradient/MeshGradient.utils.d.ts +1 -1
  214. package/dist/components/effects/MeshGradient/MeshGradient.utils.js +1 -1
  215. package/dist/components/forms/Checkbox/Checkbox.js +2 -1
  216. package/dist/components/forms/Checkbox/Checkbox.theme.js +2 -2
  217. package/dist/components/forms/ColorPicker/ColorPickerEyeDropper.js +2 -2
  218. package/dist/components/forms/ColorPicker/ColorPickerGradient.js +2 -2
  219. package/dist/components/forms/ColorPicker/ColorPickerHeader.js +2 -2
  220. package/dist/components/forms/ColorPicker/ColorPickerImage.js +3 -3
  221. package/dist/components/forms/ColorPicker/ColorPickerInput.js +2 -2
  222. package/dist/components/forms/ColorPicker/ColorPickerPresets.js +2 -2
  223. package/dist/components/forms/ColorPicker/ColorPickerSavedColors.js +2 -2
  224. package/dist/components/forms/Combobox/Combobox.js +3 -3
  225. package/dist/components/forms/Combobox/Combobox.theme.js +2 -2
  226. package/dist/components/forms/DatePicker/DatePicker.animations.js +16 -25
  227. package/dist/components/forms/DatePicker/DatePicker.theme.js +2 -2
  228. package/dist/components/forms/DatePicker/DatePickerBody.js +1 -1
  229. package/dist/components/forms/DatePicker/DatePickerTrigger.js +2 -2
  230. package/dist/components/forms/DateRangePicker/DateRangePicker.theme.js +3 -3
  231. package/dist/components/forms/DateRangePicker/DateRangePickerBody.js +1 -1
  232. package/dist/components/forms/DateRangePicker/DateRangePickerPresets.js +2 -2
  233. package/dist/components/forms/DateRangePicker/DateRangePickerTrigger.js +2 -2
  234. package/dist/components/forms/FileUpload/FileUpload.js +4 -4
  235. package/dist/components/forms/FileUpload/FileUpload.theme.js +5 -1
  236. package/dist/components/forms/FileUpload/FileUploadProgress.js +7 -7
  237. package/dist/components/forms/Input/Input.js +6 -7
  238. package/dist/components/forms/Input/Input.theme.js +19 -15
  239. package/dist/components/forms/InputAddress/InputAddress.js +10 -3
  240. package/dist/components/forms/InputCounter/InputCounter.js +3 -3
  241. package/dist/components/forms/InputOTP/InputOTP.d.ts +3 -12
  242. package/dist/components/forms/InputOTP/InputOTP.js +140 -151
  243. package/dist/components/forms/InputOTP/InputOTP.theme.d.ts +5 -1
  244. package/dist/components/forms/InputOTP/InputOTP.theme.js +40 -5
  245. package/dist/components/forms/InputOTP/InputOTP.types.d.ts +45 -2
  246. package/dist/components/forms/InputOTP/index.d.ts +1 -1
  247. package/dist/components/forms/InputTag/InputTag.js +5 -5
  248. package/dist/components/forms/InputTag/InputTag.theme.js +1 -2
  249. package/dist/components/forms/Mention/Mention.theme.js +3 -5
  250. package/dist/components/forms/Radio/Radio.js +3 -2
  251. package/dist/components/forms/Radio/Radio.theme.js +2 -2
  252. package/dist/components/forms/RichTextEditor/RichTextEditor.js +22 -23
  253. package/dist/components/forms/Select/Select.d.ts +5 -1
  254. package/dist/components/forms/Select/Select.js +12 -11
  255. package/dist/components/forms/Select/Select.theme.js +4 -4
  256. package/dist/components/forms/Select/Select.types.d.ts +4 -1
  257. package/dist/components/forms/SelectableCard/SelectableCard.animations.d.ts +1 -2
  258. package/dist/components/forms/SelectableCard/SelectableCard.animations.js +6 -7
  259. package/dist/components/forms/SelectableCard/SelectableCard.js +1 -1
  260. package/dist/components/forms/Signature/Signature.js +1 -1
  261. package/dist/components/forms/Slider/Slider.js +24 -11
  262. package/dist/components/forms/Slider/Slider.theme.js +9 -3
  263. package/dist/components/forms/Switch/Switch.theme.js +1 -1
  264. package/dist/components/forms/TimePicker/TimePicker.theme.js +6 -7
  265. package/dist/components/forms/TimePicker/TimePickerContent.js +1 -1
  266. package/dist/components/forms/TimePicker/TimePickerTrigger.js +3 -3
  267. package/dist/components/forms/forms.theme.js +23 -12
  268. package/dist/components/forms/index.js +1 -1
  269. package/dist/components/generative/registry.js +195 -2
  270. package/dist/components/generative/resolvers.js +16 -16
  271. package/dist/components/generative/schema.generated.js +2687 -379
  272. package/dist/components/layout/Section/Section.theme.js +1 -1
  273. package/dist/generative.schema.json +2687 -379
  274. package/dist/hooks/index.d.ts +2 -0
  275. package/dist/hooks/useElapsedTime.d.ts +28 -0
  276. package/dist/hooks/useElapsedTime.js +37 -0
  277. package/dist/hooks/useSelectPortal.d.ts +10 -2
  278. package/dist/hooks/useSelectPortal.js +6 -3
  279. package/dist/index.js +1 -1
  280. package/dist/registry.json +835 -261
  281. package/dist/shadcn-compat.css +1 -1
  282. package/dist/styles.css +1 -1
  283. package/dist/theme.css +5 -1
  284. package/dist/themes/ember.css +131 -0
  285. package/dist/themes/iris.css +94 -0
  286. package/dist/themes/jade.css +139 -0
  287. package/dist/tools.json +2705 -361
  288. package/dist/utils/colorUtils.d.ts +6 -6
  289. package/dist/utils/colorUtils.js +8 -8
  290. package/package.json +9 -6
  291. package/src/global.scss +15 -4
  292. package/src/styles/theme.css +440 -152
  293. package/tailwind.preset.cjs +52 -34
  294. package/dist/components/core/Pill/Pill.animations.d.ts +0 -32
  295. package/dist/components/core/Pill/Pill.animations.js +0 -16
@@ -0,0 +1,22 @@
1
+ import type { Variants } from "motion/react";
2
+ import type { OfflineIndicatorPosition, OfflineIndicatorVariant } from "./OfflineIndicator.types";
3
+ /**
4
+ * Custom spring preset for offline indicator to give it a satisfying, subtle bounce.
5
+ */
6
+ export declare const indicatorSpring: {
7
+ type: "spring";
8
+ stiffness: number;
9
+ damping: number;
10
+ mass: number;
11
+ };
12
+ /**
13
+ * Generates context-aware animation variants for OfflineIndicator.
14
+ * Dynamically adjusts translation side/axis based on screen placement.
15
+ */
16
+ /**
17
+ * Fade-only variants for prefers-reduced-motion users — the status pill
18
+ * still appears/disappears (it's a role="status" signal), just without
19
+ * translation, scale, or bounce.
20
+ */
21
+ export declare const reducedMotionIndicatorVariants: Variants;
22
+ export declare const getOfflineIndicatorVariants: (position: OfflineIndicatorPosition, variant: OfflineIndicatorVariant) => Variants;
@@ -0,0 +1,54 @@
1
+ "use client";
2
+ /**
3
+ * Custom spring preset for offline indicator to give it a satisfying, subtle bounce.
4
+ */
5
+ const indicatorSpring = {
6
+ type: "spring",
7
+ stiffness: 260,
8
+ damping: 26,
9
+ mass: 1,
10
+ };
11
+ /**
12
+ * Generates context-aware animation variants for OfflineIndicator.
13
+ * Dynamically adjusts translation side/axis based on screen placement.
14
+ */
15
+ /**
16
+ * Fade-only variants for prefers-reduced-motion users — the status pill
17
+ * still appears/disappears (it's a role="status" signal), just without
18
+ * translation, scale, or bounce.
19
+ */
20
+ const reducedMotionIndicatorVariants = {
21
+ initial: { opacity: 0 },
22
+ animate: { opacity: 1, transition: { duration: 0.15 } },
23
+ exit: { opacity: 0, transition: { duration: 0.15 } },
24
+ };
25
+ const getOfflineIndicatorVariants = (position, variant) => {
26
+ const isTop = position.startsWith("top");
27
+ // Toast variants slide and scale, Banner variants just slide to maintain bleed styling
28
+ const yOffset = isTop ? -24 : 24;
29
+ const initialScale = variant === "banner" ? 1 : 0.92;
30
+ return {
31
+ initial: {
32
+ opacity: 0,
33
+ y: yOffset,
34
+ scale: initialScale,
35
+ },
36
+ animate: {
37
+ opacity: 1,
38
+ y: 0,
39
+ scale: 1,
40
+ transition: indicatorSpring,
41
+ },
42
+ exit: {
43
+ opacity: 0,
44
+ y: yOffset,
45
+ scale: initialScale,
46
+ transition: {
47
+ duration: 0.18,
48
+ ease: "easeIn",
49
+ },
50
+ },
51
+ };
52
+ };
53
+
54
+ export { getOfflineIndicatorVariants, indicatorSpring, reducedMotionIndicatorVariants };
@@ -1,13 +1,19 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from 'react/jsx-runtime';
3
3
  import React__default, { useState, useEffect, useMemo } from 'react';
4
- import { SignalSlashIcon, CheckCircleIcon } from '@heroicons/react/24/solid';
5
- import { AnimatePresence, motion } from 'motion/react';
4
+ import { WifiSlash, CheckCircle } from '@phosphor-icons/react';
5
+ import { useReducedMotion, AnimatePresence, motion } from 'motion/react';
6
6
  import { cn } from '../../../utils/cn.js';
7
7
  import { useNetworkStatus } from '../../../hooks/useNetworkStatus.js';
8
8
  import { getDefaultQueue } from '../../../utils/actionQueue.js';
9
+ import { Link } from '../Link/Link.js';
10
+ import { reducedMotionIndicatorVariants, getOfflineIndicatorVariants } from './OfflineIndicator.animations.js';
9
11
  import { offlineIndicatorTheme } from './OfflineIndicator.theme.js';
10
12
 
13
+ const isOfflineIndicatorAction = (action) => typeof action === "object" &&
14
+ action !== null &&
15
+ "label" in action &&
16
+ "onClick" in action;
11
17
  /**
12
18
  * OfflineIndicator - Visual indicator for offline status
13
19
  *
@@ -21,9 +27,10 @@ import { offlineIndicatorTheme } from './OfflineIndicator.theme.js';
21
27
  * // Custom position and variant
22
28
  * <OfflineIndicator position="bottom-right" variant="badge" />
23
29
  */
24
- const OfflineIndicator = React__default.forwardRef(({ position = "top", showQueueCount = false, queue, variant = "toast", autoHideOnline = true, autoHideDelay = 5000, offlineMessage = "You're offline", onlineMessage = "Back online", className, }, ref) => {
25
- var _a, _b;
30
+ const OfflineIndicator = React__default.forwardRef(({ position = "top", showQueueCount = false, queue, variant = "toast", autoHideOnline = true, autoHideDelay = 5000, offlineMessage = "You're offline", onlineMessage = "Back online", action, className, }, ref) => {
31
+ var _a, _b, _c;
26
32
  const theme = offlineIndicatorTheme;
33
+ const shouldReduceMotion = useReducedMotion();
27
34
  const { isOnline, wasOffline } = useNetworkStatus();
28
35
  const [isVisible, setIsVisible] = useState(false);
29
36
  const [queueSize, setQueueSize] = useState(0);
@@ -73,29 +80,21 @@ const OfflineIndicator = React__default.forwardRef(({ position = "top", showQueu
73
80
  autoHideOnline,
74
81
  autoHideDelay,
75
82
  ]);
76
- // Animation variants
77
- const animationVariants = useMemo(() => ({
78
- initial: {
79
- opacity: 0,
80
- y: position.startsWith("top") ? -20 : 20,
81
- scale: 0.95,
82
- },
83
- animate: {
84
- opacity: 1,
85
- y: 0,
86
- scale: 1,
87
- },
88
- exit: {
89
- opacity: 0,
90
- y: position.startsWith("top") ? -20 : 20,
91
- scale: 0.95,
92
- },
93
- }), [position]);
83
+ // Animation variants — fade-only under prefers-reduced-motion (§12)
84
+ const animationVariants = useMemo(() => shouldReduceMotion
85
+ ? reducedMotionIndicatorVariants
86
+ : getOfflineIndicatorVariants(position, variant), [shouldReduceMotion, position, variant]);
94
87
  const isOffline = !isOnline;
95
- const Icon = isOffline ? SignalSlashIcon : CheckCircleIcon;
88
+ const Icon = isOffline ? WifiSlash : CheckCircle;
96
89
  const message = isOffline ? offlineMessage : onlineMessage;
97
90
  const stateStyle = isOffline ? theme.offline : theme.online;
98
- return (jsx(AnimatePresence, { children: isVisible && (jsxs(motion.div, { ref: ref, initial: "initial", animate: "animate", exit: "exit", variants: animationVariants, transition: { duration: 0.2, ease: "easeOut" }, className: cn(theme.base, (_a = theme.positions) === null || _a === void 0 ? void 0 : _a[position], (_b = theme.variants) === null || _b === void 0 ? void 0 : _b[variant], stateStyle, className), role: "status", "aria-live": "polite", children: [jsx(Icon, { className: theme.icon, "aria-hidden": "true" }), jsxs("span", { className: theme.message, children: [message, showQueueCount && queueSize > 0 && isOffline && (jsxs("span", { className: theme.queueCount, children: ["(", queueSize, " action", queueSize !== 1 ? "s" : "", " queued)"] }))] })] })) }));
91
+ // No `layout` on the root motion.div: its FLIP transform would fight the
92
+ // y/scale enter/exit variants on the same element (the documented
93
+ // concurrent layout+transform trap). Content-size changes animate via the
94
+ // children's layout="position" instead.
95
+ return (jsx(AnimatePresence, { children: isVisible && (jsxs(motion.div, { ref: ref, initial: "initial", animate: "animate", exit: "exit", variants: animationVariants, className: cn(theme.base, variant === "banner"
96
+ ? (_a = theme.bannerPositions) === null || _a === void 0 ? void 0 : _a[position]
97
+ : (_b = theme.positions) === null || _b === void 0 ? void 0 : _b[position], (_c = theme.variants) === null || _c === void 0 ? void 0 : _c[variant], stateStyle, className), role: "status", "aria-live": "polite", children: [jsx("div", { className: "relative size-3.5 flex-shrink-0", children: jsx(AnimatePresence, { mode: "popLayout", children: jsx(motion.div, { initial: shouldReduceMotion ? { opacity: 0 } : { opacity: 0, scale: 0.5, rotate: -45 }, animate: shouldReduceMotion ? { opacity: 1 } : { opacity: 1, scale: 1, rotate: 0 }, exit: shouldReduceMotion ? { opacity: 0 } : { opacity: 0, scale: 0.5, rotate: 45 }, transition: { duration: 0.25 }, className: "absolute inset-0 flex items-center justify-center", children: jsx(Icon, { className: "size-full", "aria-hidden": "true" }) }, isOffline ? "offline" : "online") }) }), jsxs(motion.span, { layout: shouldReduceMotion ? false : "position", className: theme.message, children: [message, jsx(AnimatePresence, { mode: "popLayout", children: showQueueCount && queueSize > 0 && isOffline && (jsxs(motion.span, { initial: shouldReduceMotion ? { opacity: 0 } : { opacity: 0, scale: 0.8 }, animate: shouldReduceMotion ? { opacity: 1 } : { opacity: 1, scale: 1 }, exit: shouldReduceMotion ? { opacity: 0 } : { opacity: 0, scale: 0.8 }, transition: { duration: 0.18 }, className: theme.queueCount, children: ["(", queueSize, " action", queueSize !== 1 ? "s" : "", " queued)"] })) })] }), jsx(AnimatePresence, { children: action != null && isOffline && (jsx(motion.div, { layout: shouldReduceMotion ? false : "position", initial: shouldReduceMotion ? { opacity: 0 } : { opacity: 0, scale: 0.9 }, animate: shouldReduceMotion ? { opacity: 1 } : { opacity: 1, scale: 1 }, exit: shouldReduceMotion ? { opacity: 0 } : { opacity: 0, scale: 0.9 }, transition: { duration: 0.2 }, className: "inline-flex items-center flex-shrink-0", children: isOfflineIndicatorAction(action) ? (jsx(Link, { size: "sm", onClick: action.onClick, className: theme.action, children: action.label })) : (action) })) })] })) }));
99
98
  });
100
99
  OfflineIndicator.displayName = "OfflineIndicator";
101
100
 
@@ -1,5 +1,5 @@
1
1
  const offlineIndicatorTheme = {
2
- base: "fixed z-50 flex items-center gap-2 transition-all duration-300 select-none ",
2
+ base: "fixed z-50 flex items-center gap-1.5 transition-colors duration-300 select-none",
3
3
  positions: {
4
4
  top: "top-4 left-1/2 -translate-x-1/2",
5
5
  bottom: "bottom-4 left-1/2 -translate-x-1/2",
@@ -8,14 +8,33 @@ const offlineIndicatorTheme = {
8
8
  "bottom-left": "bottom-4 left-4",
9
9
  "bottom-right": "bottom-4 right-4",
10
10
  },
11
+ // Banner is an edge-to-edge bar, so it collapses every position to the
12
+ // flush viewport edge — only the top/bottom half of `position` matters.
13
+ bannerPositions: {
14
+ top: "top-0",
15
+ bottom: "bottom-0",
16
+ "top-left": "top-0",
17
+ "top-right": "top-0",
18
+ "bottom-left": "bottom-0",
19
+ "bottom-right": "bottom-0",
20
+ },
11
21
  variants: {
12
- banner: "w-full left-0 right-0 px-4 py-1 justify-center rounded-none shadow-real-lg",
13
- toast: "px-3 py-2 rounded-[var(--radius-base)] shadow-real-lg",
22
+ // translate-x-0 cancels the centered positions' -translate-x-1/2 (cn's
23
+ // tailwind-merge lets the variant win) — without it the full-width bar
24
+ // is dragged left by half its own width and clips off-screen.
25
+ banner: "w-full left-0 right-0 translate-x-0 px-4 py-1 justify-center rounded-none shadow-real-lg",
26
+ toast: "px-3 py-2 rounded-[var(--toast-radius)] shadow-real-xl",
14
27
  },
15
- offline: "bg-[var(--color-neutral-900)]/90 backdrop-blur-sm text-[var(--color-neutral-100)]",
28
+ // Filled-neutral pill: the bare neutral token flips light/dark on its own
29
+ // (dark near-black pill in light mode, light pill in dark mode) and
30
+ // -contrast auto-derives — no hand-picked rungs or dark: inversions (§3).
31
+ offline: "bg-[var(--color-mono)]/90 backdrop-blur-sm text-[var(--color-mono-contrast)]",
16
32
  online: "bg-[var(--color-success)]/90 backdrop-blur-sm text-[var(--color-success-contrast)]",
17
- icon: "size-4 flex-shrink-0",
18
- message: "text-xs font-medium",
33
+ // text-inherit keeps the link legible on the inverse pill in BOTH modes
34
+ // (near-black in light, near-white in dark) — a fixed Link color can't.
35
+ action: "text-xs font-semibold text-inherit",
36
+ icon: "size-3.5 flex-shrink-0",
37
+ message: "text-xs font-medium -tracking-[0.025em]",
19
38
  queueCount: "text-xs opacity-80 ml-1",
20
39
  };
21
40
 
@@ -1,4 +1,12 @@
1
+ import type { ReactNode } from "react";
1
2
  import type { ActionQueue } from "../../../utils/actionQueue";
3
+ /**
4
+ * Declarative action rendered after the offline message (e.g. a retry link)
5
+ */
6
+ export interface OfflineIndicatorAction {
7
+ label: string;
8
+ onClick: () => void;
9
+ }
2
10
  /**
3
11
  * Position options for OfflineIndicator
4
12
  */
@@ -27,6 +35,11 @@ export interface OfflineIndicatorProps {
27
35
  offlineMessage?: string;
28
36
  /** Custom online message (shown briefly when reconnecting) */
29
37
  onlineMessage?: string;
38
+ /**
39
+ * Action shown next to the message while offline — pass `{ label, onClick }`
40
+ * for a link-styled button (mirrors Toast's `action`), or any ReactNode.
41
+ */
42
+ action?: OfflineIndicatorAction | ReactNode;
30
43
  /** Additional class names */
31
44
  className?: string;
32
45
  }
@@ -38,6 +51,8 @@ export interface OfflineIndicatorTheme {
38
51
  base?: string;
39
52
  /** Position-specific styles */
40
53
  positions?: Record<OfflineIndicatorPosition, string>;
54
+ /** Position overrides for the full-bleed banner variant (flush to the viewport edge, no inset) */
55
+ bannerPositions?: Record<OfflineIndicatorPosition, string>;
41
56
  /** Variant-specific styles */
42
57
  variants?: {
43
58
  banner?: string;
@@ -48,6 +63,8 @@ export interface OfflineIndicatorTheme {
48
63
  offline?: string;
49
64
  /** Online (reconnected) state styles */
50
65
  online?: string;
66
+ /** Action link styles */
67
+ action?: string;
51
68
  /** Icon styles */
52
69
  icon?: string;
53
70
  /** Message text styles */
@@ -1,7 +1,7 @@
1
1
  const pageHeadingTheme = {
2
2
  baseStyle: "flex flex-col pb-6 mb-6",
3
3
  headerStyle: "flex flex-col items-start sm:flex-row sm:items-center gap-4",
4
- titleStyle: "text-xl font-bold text-[var(--color-text-primary)]",
4
+ titleStyle: "text-[length:var(--page-heading-title-size)] leading-[1.4] font-bold text-[var(--color-text-primary)]",
5
5
  subtitleStyle: "text-sm text-[var(--color-text-secondary)] mt-1",
6
6
  actionsStyle: "sm:ml-auto flex items-center gap-2 shrink-0",
7
7
  iconStyle: "flex items-center justify-center shrink-0 text-[var(--color-text-muted)]",
@@ -2,11 +2,11 @@
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import React__default from 'react';
4
4
  import { cn } from '../../../utils/cn.js';
5
- import { ArrowLeftIcon } from '@heroicons/react/20/solid';
5
+ import { ArrowLeft } from '@phosphor-icons/react';
6
6
  import { Link } from '../Link/Link.js';
7
7
 
8
8
  const PageHeadingBackButton = React__default.forwardRef(({ label = "Back", onClick, className, ...props }, ref) => {
9
- return (jsxs(Link, { ref: ref, color: "neutral", size: "sm", onClick: onClick, className: cn("mb-2 w-fit", className), ...props, children: [jsx(ArrowLeftIcon, { className: "size-4" }), typeof label === 'string'
9
+ return (jsxs(Link, { ref: ref, color: "mono", size: "sm", onClick: onClick, className: cn("mb-2 w-fit", className), ...props, children: [jsx(ArrowLeft, { className: "size-4" }), typeof label === 'string'
10
10
  ? jsx("span", { children: label })
11
11
  : label] }));
12
12
  });
@@ -3,7 +3,7 @@ import { jsx, jsxs } from 'react/jsx-runtime';
3
3
  import React__default, { useMemo, useCallback } from 'react';
4
4
  import { paginationTheme } from './Pagination.theme.js';
5
5
  import { cn } from '../../../utils/cn.js';
6
- import { ChevronDoubleLeftIcon, ChevronLeftIcon, ChevronRightIcon, ChevronDoubleRightIcon } from '@heroicons/react/24/outline';
6
+ import { CaretDoubleLeft, CaretLeft, CaretRight, CaretDoubleRight } from '@phosphor-icons/react';
7
7
 
8
8
  /**
9
9
  * Internal PaginationItem component for page numbers and ellipsis
@@ -83,14 +83,14 @@ const Pagination = React__default.forwardRef(({ currentPage, totalPages, onPageC
83
83
  // on page 1, or "(totalPages + 1)" on the last page).
84
84
  const previousPageLabelNumber = Math.max(currentPage - 1, 1);
85
85
  const nextPageLabelNumber = Math.min(currentPage + 1, totalPages);
86
- return (jsxs("nav", { ref: ref, role: "navigation", "aria-label": "Pagination Navigation", className: cn(theme.baseStyle, className), ...props, children: [showFirstLast && (jsxs(PaginationItem, { size: size, isDisabled: isFirstPage, onClick: () => handlePageChange(1), "aria-label": "Go to first page", children: [jsx(ChevronDoubleLeftIcon, { className: "w-4 h-4" }), jsx("span", { className: "sr-only", children: "First" })] })), showPrevNext && (jsxs(PaginationItem, { size: size, isDisabled: isFirstPage, onClick: () => handlePageChange(currentPage - 1), "aria-label": `Go to previous page (${previousPageLabelNumber})`, children: [jsx(ChevronLeftIcon, { className: "w-4 h-4" }), jsx("span", { className: "sr-only", children: "Previous" })] })), paginationRange.map((pageNumber, index) => {
86
+ return (jsxs("nav", { ref: ref, role: "navigation", "aria-label": "Pagination Navigation", className: cn(theme.baseStyle, className), ...props, children: [showFirstLast && (jsxs(PaginationItem, { size: size, isDisabled: isFirstPage, onClick: () => handlePageChange(1), "aria-label": "Go to first page", children: [jsx(CaretDoubleLeft, { className: "w-4 h-4" }), jsx("span", { className: "sr-only", children: "First" })] })), showPrevNext && (jsxs(PaginationItem, { size: size, isDisabled: isFirstPage, onClick: () => handlePageChange(currentPage - 1), "aria-label": `Go to previous page (${previousPageLabelNumber})`, children: [jsx(CaretLeft, { className: "w-4 h-4" }), jsx("span", { className: "sr-only", children: "Previous" })] })), paginationRange.map((pageNumber, index) => {
87
87
  if (pageNumber === "...") {
88
88
  return (jsx("span", { role: "separator", "aria-hidden": "true", children: "\u2026" }, `ellipsis-${index}`));
89
89
  }
90
90
  const page = pageNumber;
91
91
  const isActive = page === currentPage;
92
92
  return (jsxs(PaginationItem, { size: size, variant: "page", isActive: isActive, onClick: () => handlePageChange(page), "aria-label": isActive ? `Page ${page}, current page` : `Go to page ${page}`, children: [page, isActive && jsx("span", { className: "sr-only", children: "(current)" })] }, page));
93
- }), showPrevNext && (jsxs(PaginationItem, { size: size, isDisabled: isLastPage, onClick: () => handlePageChange(currentPage + 1), "aria-label": `Go to next page (${nextPageLabelNumber})`, children: [jsx(ChevronRightIcon, { className: "w-4 h-4" }), jsx("span", { className: "sr-only", children: "Next" })] })), showFirstLast && (jsxs(PaginationItem, { size: size, isDisabled: isLastPage, onClick: () => handlePageChange(totalPages), "aria-label": "Go to last page", children: [jsx(ChevronDoubleRightIcon, { className: "w-4 h-4" }), jsx("span", { className: "sr-only", children: "Last" })] }))] }));
93
+ }), showPrevNext && (jsxs(PaginationItem, { size: size, isDisabled: isLastPage, onClick: () => handlePageChange(currentPage + 1), "aria-label": `Go to next page (${nextPageLabelNumber})`, children: [jsx(CaretRight, { className: "w-4 h-4" }), jsx("span", { className: "sr-only", children: "Next" })] })), showFirstLast && (jsxs(PaginationItem, { size: size, isDisabled: isLastPage, onClick: () => handlePageChange(totalPages), "aria-label": "Go to last page", children: [jsx(CaretDoubleRight, { className: "w-4 h-4" }), jsx("span", { className: "sr-only", children: "Last" })] }))] }));
94
94
  });
95
95
  Pagination.displayName = "Pagination";
96
96
 
@@ -9,7 +9,7 @@ const paginationTheme = {
9
9
  // Dark mode: neutral-800 background, lighter text, neutral-600 borders
10
10
  itemStyle: "inline-flex items-center justify-center font-medium rounded-[var(--form-radius)] transition-all duration-200 ease-in-out " +
11
11
  // Focus styles
12
- "focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)] focus-visible:ring-offset-2 dark:focus-visible:ring-offset-[var(--color-neutral-900)] " +
12
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)] focus-visible:ring-offset-2 dark:focus-visible:ring-offset-[var(--color-mono-900)] " +
13
13
  // Base state - light
14
14
  "cursor-pointer bg-white border border-transparent text-[var(--color-text-muted)] " +
15
15
  // Base state - dark
@@ -21,7 +21,7 @@ const paginationTheme = {
21
21
  // Active state - light
22
22
  "data-[active=true]:bg-white data-[active=true]:border-[var(--color-border)] data-[active=true]:text-[var(--color-text-primary)] " +
23
23
  // Active state - dark (uses primary color accent)
24
- "dark:data-[active=true]:bg-[var(--color-neutral-800)] dark:data-[active=true]:border-none dark:data-[active=true]:text-[var(--color-text-primary)] " +
24
+ "dark:data-[active=true]:bg-[var(--color-mono-800)] dark:data-[active=true]:border-none dark:data-[active=true]:text-[var(--color-text-primary)] " +
25
25
  // Disabled state
26
26
  "data-[disabled=true]:opacity-50 data-[disabled=true]:cursor-not-allowed data-[disabled=true]:pointer-events-none",
27
27
  // Unified item sizes
@@ -30,7 +30,7 @@ const paginationTheme = {
30
30
  md: "size-10 min-w-[2.5rem] text-sm",
31
31
  },
32
32
  // Ellipsis styles
33
- ellipsisStyle: "inline-flex items-center justify-center font-medium text-[var(--color-text-muted)] dark:text-[var(--color-neutral-500)] cursor-default pointer-events-none",
33
+ ellipsisStyle: "inline-flex items-center justify-center font-medium text-[var(--color-text-muted)] cursor-default pointer-events-none",
34
34
  };
35
35
 
36
36
  export { paginationTheme };
@@ -3,9 +3,11 @@ import { jsx, jsxs } from 'react/jsx-runtime';
3
3
  import React__default, { useState, useEffect, useCallback } from 'react';
4
4
  import { useReducedMotion, motion } from 'motion/react';
5
5
  import { pillTheme } from './Pill.theme.js';
6
- import { pillTapVariant } from './Pill.animations.js';
6
+ import { createPressVariants } from '../shared/interaction.animations.js';
7
7
  import { cn } from '../../../utils/cn.js';
8
8
 
9
+ // Shared press physics + subtle hover lift (module-level constant)
10
+ const PILL_PRESS_VARIANTS = createPressVariants(0.97, 1.02);
9
11
  /**
10
12
  * Pill component - Simplified selectable chip for filters and tags
11
13
  *
@@ -120,7 +122,7 @@ const Pill = React__default.forwardRef((props, ref) => {
120
122
  // Accessibility
121
123
  role: isSelectable && !readOnly ? "button" : undefined, tabIndex: isInteractive ? 0 : undefined, "aria-pressed": isSelectable && !readOnly ? isSelected : undefined, "aria-readonly": readOnly || undefined,
122
124
  // Animation
123
- whileTap: isInteractive && !shouldReduceMotion ? pillTapVariant : undefined, ...restProps, children: [renderStartIcon(), children] }));
125
+ variants: PILL_PRESS_VARIANTS, animate: "rest", whileHover: isInteractive && !shouldReduceMotion ? "hover" : undefined, whileTap: isInteractive && !shouldReduceMotion ? "press" : undefined, ...restProps, children: [renderStartIcon(), children] }));
124
126
  });
125
127
  Pill.displayName = "Pill";
126
128
 
@@ -9,7 +9,7 @@ const pillTheme = {
9
9
  * Base pill style - structure and default colors (no hover)
10
10
  */
11
11
  baseStyle: "inline-flex items-center justify-center font-medium rounded-full select-none whitespace-nowrap " +
12
- "ring-1 bg-[var(--color-surface)] transition-all duration-300 " +
12
+ "ring-1 bg-[var(--color-surface)] transition-[color,background-color,box-shadow] duration-150 ease-out " +
13
13
  "text-[var(--color-text-primary)] ring-[var(--color-border)] " +
14
14
  "focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)]",
15
15
  /**
@@ -26,10 +26,12 @@ const pillTheme = {
26
26
  /**
27
27
  * Size variants
28
28
  */
29
+ // Paddings tokenised (--pill-px-*/--pill-py-*) so a theme can grow the chip
30
+ // tier alongside its controls — defaults are px-2.5/px-3 + py-0.5/py-1.
29
31
  sizes: {
30
- sm: "text-xs px-2.5 py-0.5 gap-0.5",
31
- md: "text-sm px-2.5 py-0.5 gap-1",
32
- lg: "text-sm px-3 py-1 gap-1.5",
32
+ sm: "text-xs px-[var(--pill-px-sm)] py-[var(--pill-py-sm)] gap-0.5",
33
+ md: "text-sm px-[var(--pill-px-md)] py-[var(--pill-py-md)] gap-1",
34
+ lg: "text-sm px-[var(--pill-px-lg)] py-[var(--pill-py-lg)] gap-1.5",
33
35
  },
34
36
  /**
35
37
  * Icon sizes for iconStart and CheckIcon
@@ -1,8 +1,7 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from 'react/jsx-runtime';
3
3
  import React__default, { useState, useMemo, useCallback } from 'react';
4
- import { StarIcon } from '@heroicons/react/24/solid';
5
- import { StarIcon as StarIcon$1 } from '@heroicons/react/24/outline';
4
+ import { Star } from '@phosphor-icons/react';
6
5
  import { cn } from '../../../utils/cn.js';
7
6
  import { ratingTheme } from './Rating.theme.js';
8
7
 
@@ -147,14 +146,14 @@ const Rating = React__default.memo(React__default.forwardRef(({ value: controlle
147
146
  // Determine which icon to render based on fill state
148
147
  const renderStarIcon = () => {
149
148
  if (fillState === "full") {
150
- return iconFilled ? (jsx("span", { className: cn(starSizeClass, filledColorClass), "aria-hidden": "true", children: iconFilled })) : (jsx(StarIcon, { className: cn(starSizeClass, filledColorClass), "aria-hidden": "true" }));
149
+ return iconFilled ? (jsx("span", { className: cn(starSizeClass, filledColorClass), "aria-hidden": "true", children: iconFilled })) : (jsx(Star, { className: cn(starSizeClass, filledColorClass), "aria-hidden": "true" }));
151
150
  }
152
151
  if (fillState === "half") {
153
152
  // Half star: clip a filled star to the left half, overlay on empty star
154
- return (jsxs("span", { className: cn("relative inline-flex", starSizeClass), "aria-hidden": "true", children: [iconEmpty ? (jsx("span", { className: cn("absolute inset-0", emptyColorClass), children: iconEmpty })) : (jsx(StarIcon$1, { className: cn("absolute inset-0", starSizeClass, emptyColorClass) })), jsx("span", { className: "absolute inset-0 overflow-hidden", style: { width: "50%" }, children: iconFilled ? (jsx("span", { className: cn(filledColorClass), children: iconFilled })) : (jsx(StarIcon, { className: cn(starSizeClass, filledColorClass) })) })] }));
153
+ return (jsxs("span", { className: cn("relative inline-flex", starSizeClass), "aria-hidden": "true", children: [iconEmpty ? (jsx("span", { className: cn("absolute inset-0", emptyColorClass), children: iconEmpty })) : (jsx(Star, { className: cn("absolute inset-0", starSizeClass, emptyColorClass) })), jsx("span", { className: "absolute inset-0 overflow-hidden", style: { width: "50%" }, children: iconFilled ? (jsx("span", { className: cn(filledColorClass), children: iconFilled })) : (jsx(Star, { className: cn(starSizeClass, filledColorClass) })) })] }));
155
154
  }
156
155
  // Empty star
157
- return iconEmpty ? (jsx("span", { className: cn(starSizeClass, emptyColorClass), "aria-hidden": "true", children: iconEmpty })) : (jsx(StarIcon$1, { className: cn(starSizeClass, emptyColorClass), "aria-hidden": "true" }));
156
+ return iconEmpty ? (jsx("span", { className: cn(starSizeClass, emptyColorClass), "aria-hidden": "true", children: iconEmpty })) : (jsx(Star, { className: cn(starSizeClass, emptyColorClass), "aria-hidden": "true" }));
158
157
  };
159
158
  if (!isInteractive) {
160
159
  // Read-only or disabled: render as a non-interactive span
@@ -27,7 +27,7 @@ const ratingTheme = {
27
27
  danger: "text-[var(--color-danger)]",
28
28
  },
29
29
  // Empty star color
30
- emptyColor: "text-[var(--color-neutral-300)]",
30
+ emptyColor: "text-[var(--color-mono-300)]",
31
31
  // State styles
32
32
  states: {
33
33
  disabled: "opacity-50 cursor-not-allowed pointer-events-none",
@@ -3,7 +3,7 @@
3
3
  */
4
4
  const segmentedTheme = {
5
5
  // Base styles for the segmented container
6
- baseStyle: "relative flex rounded-[var(--segmented-radius)] bg-neutral-100 dark:bg-neutral-900 border border-[var(--color-border)] p-[var(--segmented-padding)] shadow-inner-real-md",
6
+ baseStyle: "relative flex w-fit rounded-[var(--segmented-radius)] bg-[var(--color-surface-sunken)] border border-[var(--color-border)] p-[var(--segmented-padding)] shadow-inner-real-md",
7
7
  // Size variants using CSS variables
8
8
  sizes: {
9
9
  sm: "min-h-[var(--segmented-min-h-sm)]",
@@ -15,7 +15,7 @@ const segmentedTheme = {
15
15
  // Disabled style
16
16
  disabledStyle: "opacity-50 cursor-not-allowed pointer-events-none",
17
17
  // Sliding background style with CSS variables
18
- slidingBackgroundStyle: "absolute top-[0px] left-[0px] rounded-[var(--segmented-inner-radius)] transition-transform duration-200 ease-out pointer-events-none z-0 bg-[var(--color-surface)] shadow-real-md dark:bg-neutral-800",
18
+ slidingBackgroundStyle: "absolute top-[0px] left-[0px] rounded-[var(--segmented-inner-radius)] transition-transform duration-200 ease-out pointer-events-none z-0 bg-[var(--color-surface)] shadow-real-md",
19
19
  };
20
20
  /**
21
21
  * Default theme for the SegmentedItem component
@@ -23,11 +23,14 @@ const segmentedTheme = {
23
23
  const segmentedItemTheme = {
24
24
  // Base styles for the segmented item
25
25
  baseStyle: "relative flex min-w-fit flex-1 items-center justify-center whitespace-nowrap transition-all duration-200 rounded-[var(--segmented-inner-radius)] font-medium cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary-500)] focus-visible:ring-offset-1",
26
- // Size variants using CSS variables
26
+ // Size variants using CSS variables. Type reads --segmented-text-size-*
27
+ // (which aliases the shared --form-text-size-* ramp) so lg steps up with its
28
+ // box — it was pinned at text-sm across all three sizes while Button/Input,
29
+ // whose height tokens Segmented literally aliases, both stepped up at lg.
27
30
  sizes: {
28
- sm: "text-sm px-[var(--segmented-px-sm)]",
29
- md: "text-sm px-[var(--segmented-px-md)]",
30
- lg: "text-sm px-[var(--segmented-px-lg)]",
31
+ sm: "text-[length:var(--segmented-text-size-sm)]/[var(--segmented-line-height-sm)] px-[var(--segmented-px-sm)]",
32
+ md: "text-[length:var(--segmented-text-size-md)]/[var(--segmented-line-height-md)] px-[var(--segmented-px-md)]",
33
+ lg: "text-[length:var(--segmented-text-size-lg)]/[var(--segmented-line-height-lg)] px-[var(--segmented-px-lg)]",
31
34
  },
32
35
  // Selected state
33
36
  selectedStyle: "text-[var(--color-text-primary)] z-10",
@@ -133,11 +133,13 @@ export interface SidebarNavGroupProps extends React.HTMLAttributes<HTMLDivElemen
133
133
  }
134
134
  export interface SidebarToggleProps extends React.HTMLAttributes<HTMLButtonElement> {
135
135
  /**
136
- * Custom icon for expanded state
136
+ * Icon shown while the sidebar is COLLAPSED — clicking it expands.
137
+ * Falls back to the default chevron.
137
138
  */
138
139
  expandIcon?: ReactNode;
139
140
  /**
140
- * Custom icon for collapsed state
141
+ * Icon shown while the sidebar is EXPANDED — clicking it collapses.
142
+ * Falls back to the default chevron.
141
143
  */
142
144
  collapseIcon?: ReactNode;
143
145
  }
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from 'react/jsx-runtime';
3
3
  import React__default from 'react';
4
- import { XMarkIcon } from '@heroicons/react/24/outline';
4
+ import { X } from '@phosphor-icons/react';
5
5
  import { cn } from '../../../utils/cn.js';
6
6
  import { useSidebarContext, useSidebarCollapsed } from './SidebarContext.js';
7
7
  import { SidebarToggle } from './SidebarToggle.js';
@@ -22,7 +22,7 @@ const SidebarHeader = React__default.forwardRef(({ logo, showToggle = true, cust
22
22
  // fills the interior exactly. Left-pinned in both states (no
23
23
  // `justify-*` toggle) so nothing jumps mid-animation. Same value
24
24
  // for collapsed + expanded → no padding transition needed.
25
- "px-3", className), ...props, children: [jsx("div", { className: "flex items-center min-w-0 flex-1", children: logo }), isMobile && isMobileOpen && (jsx(Button, { variant: "ghost", size: "sm", className: "size-7 p-0 text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)]", onClick: () => sidebarContext === null || sidebarContext === void 0 ? void 0 : sidebarContext.setMobileOpen(false), "aria-label": "Close navigation", children: jsx(XMarkIcon, { className: "size-4" }) })), !isMobile && showToggle && (customToggle || jsx(SidebarToggle, {}))] }));
25
+ "px-3", className), ...props, children: [jsx("div", { className: "flex items-center min-w-0 flex-1", children: logo }), isMobile && isMobileOpen && (jsx(Button, { variant: "ghost", size: "sm", className: "size-7 p-0 text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)]", onClick: () => sidebarContext === null || sidebarContext === void 0 ? void 0 : sidebarContext.setMobileOpen(false), "aria-label": "Close navigation", children: jsx(X, { className: "size-4" }) })), !isMobile && showToggle && (customToggle || jsx(SidebarToggle, {}))] }));
26
26
  });
27
27
  SidebarHeader.displayName = "SidebarHeader";
28
28
 
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx } from 'react/jsx-runtime';
3
3
  import React__default from 'react';
4
- import { Bars3Icon } from '@heroicons/react/24/outline';
4
+ import { List } from '@phosphor-icons/react';
5
5
  import { cn } from '../../../utils/cn.js';
6
6
  import { useSidebarContext } from './SidebarContext.js';
7
7
  import { Button } from '../Button/Button.js';
@@ -23,7 +23,7 @@ const SidebarMobileTrigger = React__default.forwardRef(({ icon, className, onCli
23
23
  onClick === null || onClick === void 0 ? void 0 : onClick(e);
24
24
  };
25
25
  const { onAnimationStart, onAnimationEnd, onDrag, onDragStart, onDragEnd, color: _color, ...buttonProps } = props;
26
- return (jsx(Button, { ref: ref, variant: "soft", size: "sm", className: cn("size-9 p-0", className), onClick: handleClick, "aria-label": "Open navigation menu", ...buttonProps, children: icon || jsx(Bars3Icon, { className: "size-5" }) }));
26
+ return (jsx(Button, { ref: ref, variant: "soft", size: "sm", className: cn("size-9 p-0", className), onClick: handleClick, "aria-label": "Open navigation menu", ...buttonProps, children: icon || jsx(List, { className: "size-5" }) }));
27
27
  });
28
28
  SidebarMobileTrigger.displayName = "SidebarMobileTrigger";
29
29
 
@@ -2,7 +2,7 @@
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import React__default, { useState, useRef, useEffect } from 'react';
4
4
  import { motion, AnimatePresence } from 'motion/react';
5
- import { MagnifyingGlassIcon } from '@heroicons/react/24/outline';
5
+ import { MagnifyingGlass } from '@phosphor-icons/react';
6
6
  import { cn } from '../../../utils/cn.js';
7
7
  import { Tooltip } from '../Tooltip/Tooltip.js';
8
8
  import '../Tooltip/Tooltip.animations.js';
@@ -106,7 +106,7 @@ const SidebarSearch = React__default.forwardRef(({ value: controlledValue, defau
106
106
  // width) and the input fading in/out via AnimatePresence. Adding
107
107
  // a justify-* toggle here would snap the icon by 4px on frame 0
108
108
  // of every transition.
109
- "transition-[background-color,box-shadow] duration-200 ease-[cubic-bezier(0.4,0,0.2,1)]", "overflow-hidden", isCollapsedView ? shellCollapsed : shellExpanded, inputGroupClassName), children: [jsx("span", { className: cn("flex items-center justify-center flex-shrink-0 pl-2", "text-[var(--color-text-muted)] transition-colors duration-200"), "aria-hidden": !isCollapsedView || undefined, children: iconStart !== null && iconStart !== void 0 ? iconStart : jsx(MagnifyingGlassIcon, { className: "size-5" }) }), jsx(AnimatePresence, { initial: false, children: !isCollapsedView && (jsx(motion.div, { initial: { opacity: 0, x: -4 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: -4 }, transition: {
109
+ "transition-[background-color,box-shadow] duration-200 ease-[cubic-bezier(0.4,0,0.2,1)]", "overflow-hidden", isCollapsedView ? shellCollapsed : shellExpanded, inputGroupClassName), children: [jsx("span", { className: cn("flex items-center justify-center flex-shrink-0 pl-2", "text-[var(--color-text-muted)] transition-colors duration-200"), "aria-hidden": !isCollapsedView || undefined, children: iconStart !== null && iconStart !== void 0 ? iconStart : jsx(MagnifyingGlass, { className: "size-5" }) }), jsx(AnimatePresence, { initial: false, children: !isCollapsedView && (jsx(motion.div, { initial: { opacity: 0, x: -4 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: -4 }, transition: {
110
110
  opacity: { duration: 0.15, ease: [0.4, 0, 0.2, 1] },
111
111
  x: { duration: 0.2, ease: [0.4, 0, 0.2, 1] },
112
112
  }, className: "flex-1 min-w-0 flex items-center overflow-hidden", children: jsx("input", { ref: setInputRef, type: "search", value: value, onChange: handleChange, placeholder: placeholder, "aria-label": collapsedLabel, className: cn(
@@ -114,7 +114,7 @@ const SidebarSearch = React__default.forwardRef(({ value: controlledValue, defau
114
114
  // Input pl-3 (12) → text starts at field-x = 28 + 12 = 40,
115
115
  // giving a 12px icon→text gap (matches <Input iconStart>'s
116
116
  // pl-3 + pl-10 = 12px convention).
117
- "w-full bg-transparent border-0 outline-none text-sm py-2 pl-3 pr-3", "text-[var(--color-text-primary)] placeholder:text-[var(--color-text-placeholder)]", "dark:placeholder:text-[var(--color-neutral-500)]") }) }, "search-input")) })] }));
117
+ "w-full bg-transparent border-0 outline-none text-sm py-2 pl-3 pr-3", "text-[var(--color-text-primary)] placeholder:text-[var(--color-text-placeholder)]") }) }, "search-input")) })] }));
118
118
  return (
119
119
  // Outer horizontal padding mirrors Sidebar.Content (px-3 collapsed,
120
120
  // px-2.5 expanded) so the search row sits on the exact same horizontal
@@ -1,14 +1,14 @@
1
1
  "use client";
2
2
  import { jsx } from 'react/jsx-runtime';
3
3
  import React__default from 'react';
4
- import { ChevronLeftIcon } from '@heroicons/react/24/outline';
4
+ import { CaretLeft } from '@phosphor-icons/react';
5
5
  import { motion } from 'motion/react';
6
6
  import { cn } from '../../../utils/cn.js';
7
7
  import { useSidebarContext } from './SidebarContext.js';
8
8
  import { Button } from '../Button/Button.js';
9
9
 
10
10
  const SidebarToggle = React__default.forwardRef(({ expandIcon, collapseIcon, className, onClick, ...props }, ref) => {
11
- var _a;
11
+ var _a, _b;
12
12
  const sidebarContext = useSidebarContext();
13
13
  if (!sidebarContext) {
14
14
  if (process.env.NODE_ENV !== "production") {
@@ -26,7 +26,7 @@ const SidebarToggle = React__default.forwardRef(({ expandIcon, collapseIcon, cla
26
26
  const positionClasses = side === "left"
27
27
  ? "absolute right-0 translate-x-1/2 top-4 z-50"
28
28
  : "absolute left-0 -translate-x-1/2 top-4 z-50";
29
- return (jsx(Button, { ref: ref, iconOnly: true, variant: "ghost", className: cn("size-6 p-0 rounded-full border border-[var(--color-border)] bg-[var(--color-background)]/50 backdrop-blur-sm text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)] hover:shadow-md hover:bg-[var(--color-surface-hover)] opacity-100 transition-all duration-400", positionClasses, className), onClick: handleClick, "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar", title: collapsed ? "Expand sidebar" : "Collapse sidebar", ...buttonProps, children: jsx(motion.div, { initial: false, animate: { rotate: collapsed ? 180 : 0 }, transition: { duration: 0.2, ease: [0.4, 0, 0.2, 1] }, className: "flex items-center justify-center", children: jsx(ChevronLeftIcon, { className: "size-3", strokeWidth: 2.5 }) }) }));
29
+ return (jsx(Button, { ref: ref, iconOnly: true, variant: "ghost", className: cn("size-6 p-0 rounded-full border border-[var(--color-border)] bg-[var(--color-background)]/50 backdrop-blur-sm text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)] hover:shadow-md hover:bg-[var(--color-surface-hover)] opacity-100 transition-all duration-400", positionClasses, className), onClick: handleClick, "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar", title: collapsed ? "Expand sidebar" : "Collapse sidebar", ...buttonProps, children: (_b = (collapsed ? expandIcon : collapseIcon)) !== null && _b !== void 0 ? _b : (jsx(motion.div, { initial: false, animate: { rotate: collapsed ? 180 : 0 }, transition: { duration: 0.2, ease: [0.4, 0, 0.2, 1] }, className: "flex items-center justify-center", children: jsx(CaretLeft, { className: "size-3", weight: "bold" }) })) }));
30
30
  });
31
31
  SidebarToggle.displayName = "SidebarToggle";
32
32
 
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from 'react/jsx-runtime';
3
3
  import React__default from 'react';
4
- import { ChevronUpDownIcon } from '@heroicons/react/20/solid';
4
+ import { CaretUpDown } from '@phosphor-icons/react';
5
5
  import { cn } from '../../../utils/cn.js';
6
6
  import { motion, AnimatePresence } from 'motion/react';
7
7
  import { useSidebarCollapsed } from './SidebarContext.js';
@@ -37,7 +37,7 @@ const SidebarUserProfile = React__default.forwardRef(({ name, email, avatar, sta
37
37
  className: "flex-shrink-0", children: avatarElement }), jsx(AnimatePresence, { initial: false, children: !isCollapsedView && (jsxs(motion.div, { className: "flex flex-row items-center gap-2 flex-1 min-w-0 overflow-hidden whitespace-nowrap", initial: { opacity: 0, x: -4 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: -4 }, transition: {
38
38
  opacity: { duration: 0.15, ease: [0.4, 0, 0.2, 1] },
39
39
  x: { duration: 0.2, ease: [0.4, 0, 0.2, 1] }
40
- }, children: [children !== null && children !== void 0 ? children : (jsxs("div", { className: "flex-1 min-w-0", children: [jsx("div", { className: "text-sm font-medium text-[var(--color-text-primary)] truncate", children: name }), email && (jsx("div", { className: "text-xs text-[var(--color-text-secondary)]/80 truncate", children: email }))] })), dropdownContent && (jsx(ChevronUpDownIcon, { className: "size-4 flex-shrink-0 text-[var(--color-text-muted)]" }))] }, "profile-text")) })] }));
40
+ }, children: [children !== null && children !== void 0 ? children : (jsxs("div", { className: "flex-1 min-w-0", children: [jsx("div", { className: "text-sm font-medium text-[var(--color-text-primary)] truncate", children: name }), email && (jsx("div", { className: "text-xs text-[var(--color-text-secondary)]/80 truncate", children: email }))] })), dropdownContent && (jsx(CaretUpDown, { className: "size-4 flex-shrink-0 text-[var(--color-text-muted)]" }))] }, "profile-text")) })] }));
41
41
  // When dropdownContent is provided, the profile acts as a menu trigger.
42
42
  if (dropdownContent) {
43
43
  return (jsxs(Dropdown, { placement: "right-end", offset: 8, children: [jsx(Dropdown.Trigger, { children: content }), jsx(Dropdown.Menu, { "aria-label": `${name} menu`, children: dropdownContent })] }));