@devalok/shilp-sutra 0.56.0 → 0.57.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 (253) hide show
  1. package/MIGRATION.md +107 -0
  2. package/dist/_chunks/badge-group.js +48 -34
  3. package/dist/_chunks/badge-group.js.map +1 -1
  4. package/dist/_chunks/chat.js +91 -75
  5. package/dist/_chunks/chat.js.map +1 -1
  6. package/dist/_chunks/document-preview.js +1 -1
  7. package/dist/_chunks/document-preview.js.map +1 -1
  8. package/dist/_chunks/emoji-suggestion.js +1 -1
  9. package/dist/_chunks/emoji-suggestion.js.map +1 -1
  10. package/dist/_chunks/mention-suggestion.js +2 -2
  11. package/dist/_chunks/mention-suggestion.js.map +1 -1
  12. package/dist/_chunks/oauth-button.js +1 -1
  13. package/dist/_chunks/oauth-button.js.map +1 -1
  14. package/dist/_chunks/success.js +2 -2
  15. package/dist/_chunks/success.js.map +1 -1
  16. package/dist/_chunks/tree-view.js +1 -1
  17. package/dist/_chunks/tree-view.js.map +1 -1
  18. package/dist/_chunks/use-calendar.js +4 -4
  19. package/dist/_chunks/use-calendar.js.map +1 -1
  20. package/dist/ai/blocks/text.js +1 -1
  21. package/dist/ai/blocks/text.js.map +1 -1
  22. package/dist/ai/command-bar.js +9 -9
  23. package/dist/ai/command-bar.js.map +1 -1
  24. package/dist/ai/conversation.js +2 -2
  25. package/dist/ai/conversation.js.map +1 -1
  26. package/dist/composed/activity-feed.js +1 -1
  27. package/dist/composed/activity-feed.js.map +1 -1
  28. package/dist/composed/avatar-group.d.ts +7 -2
  29. package/dist/composed/avatar-group.d.ts.map +1 -1
  30. package/dist/composed/avatar-group.js +3 -3
  31. package/dist/composed/avatar-group.js.map +1 -1
  32. package/dist/composed/command-palette.js +7 -7
  33. package/dist/composed/command-palette.js.map +1 -1
  34. package/dist/composed/content-card.js +2 -2
  35. package/dist/composed/content-card.js.map +1 -1
  36. package/dist/composed/date-picker/index.js +4 -4
  37. package/dist/composed/date-picker/index.js.map +1 -1
  38. package/dist/composed/diff.d.ts +23 -2
  39. package/dist/composed/diff.d.ts.map +1 -1
  40. package/dist/composed/diff.js +341 -260
  41. package/dist/composed/diff.js.map +1 -1
  42. package/dist/composed/emoji-picker.js +3 -3
  43. package/dist/composed/emoji-picker.js.map +1 -1
  44. package/dist/composed/error-boundary.js +2 -2
  45. package/dist/composed/error-boundary.js.map +1 -1
  46. package/dist/composed/file-preview.js +1 -1
  47. package/dist/composed/file-preview.js.map +1 -1
  48. package/dist/composed/filter-bar.js +1 -1
  49. package/dist/composed/filter-bar.js.map +1 -1
  50. package/dist/composed/inline-edit.js +1 -1
  51. package/dist/composed/inline-edit.js.map +1 -1
  52. package/dist/composed/loading-skeleton.js +3 -3
  53. package/dist/composed/loading-skeleton.js.map +1 -1
  54. package/dist/composed/master-detail.js +1 -1
  55. package/dist/composed/master-detail.js.map +1 -1
  56. package/dist/composed/member-picker.js +1 -1
  57. package/dist/composed/member-picker.js.map +1 -1
  58. package/dist/composed/multi-select-popover.js +1 -1
  59. package/dist/composed/multi-select-popover.js.map +1 -1
  60. package/dist/composed/page-skeletons.js +4 -4
  61. package/dist/composed/page-skeletons.js.map +1 -1
  62. package/dist/composed/responsive-modal.js +1 -1
  63. package/dist/composed/responsive-modal.js.map +1 -1
  64. package/dist/composed/rich-chat-input.js +17 -17
  65. package/dist/composed/rich-chat-input.js.map +1 -1
  66. package/dist/composed/rich-text-editor.js +5 -5
  67. package/dist/composed/rich-text-editor.js.map +1 -1
  68. package/dist/composed/schedule-view.js +5 -5
  69. package/dist/composed/schedule-view.js.map +1 -1
  70. package/dist/hooks/index.d.ts +1 -0
  71. package/dist/hooks/index.d.ts.map +1 -1
  72. package/dist/hooks/index.js +4 -3
  73. package/dist/hooks/use-container-size.d.ts +18 -0
  74. package/dist/hooks/use-container-size.d.ts.map +1 -0
  75. package/dist/hooks/use-container-size.js +28 -0
  76. package/dist/hooks/use-container-size.js.map +1 -0
  77. package/dist/shell/app-shell.d.ts +101 -0
  78. package/dist/shell/app-shell.d.ts.map +1 -0
  79. package/dist/shell/app-shell.js +76 -0
  80. package/dist/shell/app-shell.js.map +1 -0
  81. package/dist/shell/bottom-navbar.js +2 -2
  82. package/dist/shell/bottom-navbar.js.map +1 -1
  83. package/dist/shell/index.d.ts +1 -0
  84. package/dist/shell/index.d.ts.map +1 -1
  85. package/dist/shell/index.js +6 -5
  86. package/dist/shell/notification-center.js +4 -4
  87. package/dist/shell/notification-center.js.map +1 -1
  88. package/dist/shell/notification-preferences.js +1 -1
  89. package/dist/shell/notification-preferences.js.map +1 -1
  90. package/dist/shell/top-bar.js +7 -7
  91. package/dist/shell/top-bar.js.map +1 -1
  92. package/dist/tokens/generate-scale.d.ts +49 -0
  93. package/dist/tokens/generate-scale.d.ts.map +1 -1
  94. package/dist/tokens/primitives.css +29 -26
  95. package/dist/tokens/semantic.css +98 -39
  96. package/dist/tokens/variants.css +1 -1
  97. package/dist/ui/accordion.js +1 -1
  98. package/dist/ui/accordion.js.map +1 -1
  99. package/dist/ui/alert-dialog.js +1 -1
  100. package/dist/ui/alert-dialog.js.map +1 -1
  101. package/dist/ui/alert.d.ts.map +1 -1
  102. package/dist/ui/alert.js +7 -7
  103. package/dist/ui/alert.js.map +1 -1
  104. package/dist/ui/avatar.js +3 -3
  105. package/dist/ui/avatar.js.map +1 -1
  106. package/dist/ui/badge-indicator.js +1 -1
  107. package/dist/ui/badge-indicator.js.map +1 -1
  108. package/dist/ui/badge.d.ts +47 -33
  109. package/dist/ui/badge.d.ts.map +1 -1
  110. package/dist/ui/banner.js +1 -1
  111. package/dist/ui/banner.js.map +1 -1
  112. package/dist/ui/button.js +4 -4
  113. package/dist/ui/button.js.map +1 -1
  114. package/dist/ui/card.js +4 -4
  115. package/dist/ui/card.js.map +1 -1
  116. package/dist/ui/chat/date-separator.d.ts +8 -1
  117. package/dist/ui/chat/date-separator.d.ts.map +1 -1
  118. package/dist/ui/checkbox.js +1 -1
  119. package/dist/ui/checkbox.js.map +1 -1
  120. package/dist/ui/code.js +2 -2
  121. package/dist/ui/code.js.map +1 -1
  122. package/dist/ui/color-input.js +3 -3
  123. package/dist/ui/color-input.js.map +1 -1
  124. package/dist/ui/combobox.js +4 -4
  125. package/dist/ui/combobox.js.map +1 -1
  126. package/dist/ui/context-menu.js +4 -4
  127. package/dist/ui/context-menu.js.map +1 -1
  128. package/dist/ui/data-table-body.d.ts +3 -1
  129. package/dist/ui/data-table-body.d.ts.map +1 -1
  130. package/dist/ui/data-table-body.js +93 -92
  131. package/dist/ui/data-table-body.js.map +1 -1
  132. package/dist/ui/data-table-bulk-actions.d.ts +7 -1
  133. package/dist/ui/data-table-bulk-actions.d.ts.map +1 -1
  134. package/dist/ui/data-table-bulk-actions.js +14 -8
  135. package/dist/ui/data-table-bulk-actions.js.map +1 -1
  136. package/dist/ui/data-table-card.d.ts.map +1 -1
  137. package/dist/ui/data-table-card.js +66 -47
  138. package/dist/ui/data-table-card.js.map +1 -1
  139. package/dist/ui/data-table-context.d.ts +4 -0
  140. package/dist/ui/data-table-context.d.ts.map +1 -1
  141. package/dist/ui/data-table-context.js.map +1 -1
  142. package/dist/ui/data-table-header.d.ts.map +1 -1
  143. package/dist/ui/data-table-header.js +18 -15
  144. package/dist/ui/data-table-header.js.map +1 -1
  145. package/dist/ui/data-table-pagination.js +3 -3
  146. package/dist/ui/data-table-pagination.js.map +1 -1
  147. package/dist/ui/data-table-toolbar.d.ts +11 -1
  148. package/dist/ui/data-table-toolbar.d.ts.map +1 -1
  149. package/dist/ui/data-table-toolbar.js +7 -7
  150. package/dist/ui/data-table-toolbar.js.map +1 -1
  151. package/dist/ui/data-table.d.ts +52 -5
  152. package/dist/ui/data-table.d.ts.map +1 -1
  153. package/dist/ui/data-table.js +181 -169
  154. package/dist/ui/data-table.js.map +1 -1
  155. package/dist/ui/dialog.js +1 -1
  156. package/dist/ui/dialog.js.map +1 -1
  157. package/dist/ui/dot.js +1 -1
  158. package/dist/ui/dot.js.map +1 -1
  159. package/dist/ui/dropdown-menu.js +4 -4
  160. package/dist/ui/dropdown-menu.js.map +1 -1
  161. package/dist/ui/file-upload.js +3 -3
  162. package/dist/ui/file-upload.js.map +1 -1
  163. package/dist/ui/input-otp.js +1 -1
  164. package/dist/ui/input-otp.js.map +1 -1
  165. package/dist/ui/input.js +8 -8
  166. package/dist/ui/input.js.map +1 -1
  167. package/dist/ui/menubar.js +5 -5
  168. package/dist/ui/menubar.js.map +1 -1
  169. package/dist/ui/navigation-menu.js +1 -1
  170. package/dist/ui/navigation-menu.js.map +1 -1
  171. package/dist/ui/number-input.js +3 -3
  172. package/dist/ui/number-input.js.map +1 -1
  173. package/dist/ui/pagination.js +1 -1
  174. package/dist/ui/pagination.js.map +1 -1
  175. package/dist/ui/progress-ring.js +2 -2
  176. package/dist/ui/progress-ring.js.map +1 -1
  177. package/dist/ui/progress.d.ts.map +1 -1
  178. package/dist/ui/progress.js +16 -12
  179. package/dist/ui/progress.js.map +1 -1
  180. package/dist/ui/radio.js +1 -1
  181. package/dist/ui/radio.js.map +1 -1
  182. package/dist/ui/select.js +5 -5
  183. package/dist/ui/select.js.map +1 -1
  184. package/dist/ui/sheet.js +1 -1
  185. package/dist/ui/sheet.js.map +1 -1
  186. package/dist/ui/sidebar.js +12 -12
  187. package/dist/ui/sidebar.js.map +1 -1
  188. package/dist/ui/slider.js +1 -1
  189. package/dist/ui/slider.js.map +1 -1
  190. package/dist/ui/split-button.js +3 -3
  191. package/dist/ui/split-button.js.map +1 -1
  192. package/dist/ui/stat-card.js +1 -1
  193. package/dist/ui/stat-card.js.map +1 -1
  194. package/dist/ui/stepper.js +2 -2
  195. package/dist/ui/stepper.js.map +1 -1
  196. package/dist/ui/surface.d.ts.map +1 -1
  197. package/dist/ui/surface.js +2 -2
  198. package/dist/ui/surface.js.map +1 -1
  199. package/dist/ui/switch.js +1 -1
  200. package/dist/ui/switch.js.map +1 -1
  201. package/dist/ui/table.js +1 -1
  202. package/dist/ui/table.js.map +1 -1
  203. package/dist/ui/tabs.d.ts.map +1 -1
  204. package/dist/ui/tabs.js +1 -1
  205. package/dist/ui/tabs.js.map +1 -1
  206. package/dist/ui/textarea.js +5 -5
  207. package/dist/ui/textarea.js.map +1 -1
  208. package/dist/ui/toast.js +1 -1
  209. package/dist/ui/toast.js.map +1 -1
  210. package/dist/ui/toggle.js +3 -3
  211. package/dist/ui/toggle.js.map +1 -1
  212. package/docs/components/composed/avatar-group.md +4 -4
  213. package/docs/components/composed/diff.md +10 -2
  214. package/docs/components/composed/schedule-view.md +1 -1
  215. package/docs/components/shell/app-shell.md +132 -0
  216. package/docs/components/ui/avatar.md +1 -1
  217. package/docs/components/ui/button.md +1 -1
  218. package/docs/components/ui/chat.md +7 -1
  219. package/docs/components/ui/color-swatch.md +1 -1
  220. package/docs/components/ui/data-table-toolbar.md +6 -2
  221. package/docs/components/ui/data-table.md +41 -7
  222. package/docs/components/ui/dot.md +1 -1
  223. package/docs/components/ui/progress.md +1 -0
  224. package/docs/components/ui/surface.md +3 -3
  225. package/docs/components/ui/table.md +2 -2
  226. package/docs/recipes/install-astro.md +1 -0
  227. package/docs/recipes/install-next-app-router.md +1 -0
  228. package/docs/recipes/install-remix.md +1 -0
  229. package/docs/recipes/install-tanstack-start.md +1 -0
  230. package/docs/recipes/install-vite.md +1 -0
  231. package/llms.txt +2 -1
  232. package/make-kit/Guidelines.md +2 -2
  233. package/make-kit/components/button.md +1 -1
  234. package/make-kit/components/card.md +6 -6
  235. package/make-kit/components/surface.md +4 -4
  236. package/make-kit/foundations/color.md +4 -4
  237. package/make-kit/foundations/dark-mode.md +1 -1
  238. package/make-kit/foundations/radius.md +1 -1
  239. package/make-kit/foundations/surfaces.md +9 -9
  240. package/mcp-manifest.json +350 -32
  241. package/package.json +6 -3
  242. package/skill/SKILL.md +12 -6
  243. package/skill/references/components.md +2 -1
  244. package/skill/references/setup-astro.md +1 -0
  245. package/skill/references/setup-next-app-router.md +1 -0
  246. package/skill/references/setup-remix.md +1 -0
  247. package/skill/references/setup-tanstack-start.md +1 -0
  248. package/skill/references/setup-vite.md +1 -0
  249. package/dist/primitives/react-toast.d.ts +0 -120
  250. package/dist/ui/charts/_internal/scales.d.ts +0 -5
  251. package/dist/ui/charts/_internal/scales.d.ts.map +0 -1
  252. package/dist/ui/lib/slot.d.ts +0 -8
  253. package/dist/ui/lib/slot.d.ts.map +0 -1
@@ -163,17 +163,26 @@
163
163
  --color-surface-3: var(--neutral-3);
164
164
  --color-surface-4: var(--neutral-4);
165
165
 
166
- --color-surface-base: var(--neutral-2);
167
- --color-surface-sunken: var(--color-surface-0);
168
- --color-surface-raised: var(--neutral-1);
169
- --color-surface-overlay: var(--neutral-1);
170
- --color-surface-raised-hover: var(--neutral-3);
171
- --color-surface-raised-active: var(--neutral-4);
172
- /* App chrome (TopBar, Sidebar, BottomNavbar). Its own tier so chrome's
173
- surface is an explicit, independently-tunable decision (per the Carbon/
174
- Atlassian/Ant model), not coupled to the card surface. Starts equal to
175
- `raised` — zero visual change — but can now diverge without touching cards. */
176
- --color-surface-chrome: var(--neutral-1);
166
+ /* GROUNDS take the brand tint; OBJECTS hold neutral. In light the page, the
167
+ panel and an overlay are all pure white — an edge is what makes a card a
168
+ card. See docs/plans/2026-08-26-surface-model-rebuild.md */
169
+ --color-surface-base: var(--neutral-0);
170
+ --color-surface-panel: var(--neutral-0);
171
+ --color-surface-overlay: var(--neutral-0);
172
+ --color-surface-panel-hover: var(--neutral-2);
173
+ --color-surface-panel-active: var(--neutral-3);
174
+ --color-surface-sunken: var(--neutral-sunken);
175
+ --color-surface-sunken-hover: var(--neutral-3);
176
+
177
+ /* DEPRECATED, removed next major. `surface-raised` is renamed `surface-panel`
178
+ because in light it is not raised — it is the same white as the page.
179
+ Aliased so nothing breaks mid-migration; `pnpm lint --fix` rewrites them.
180
+ NOTE hover/focus utilities must retarget to `-panel-hover`, NOT rename: a
181
+ hover painted with a container value is invisible. That is what made every
182
+ menu item's hover a no-op in light before this rebuild. */
183
+ --color-surface-raised: var(--color-surface-panel);
184
+ --color-surface-raised-hover: var(--color-surface-panel-hover);
185
+ --color-surface-raised-active: var(--color-surface-panel-active);
177
186
  --color-surface-inverted: var(--neutral-12);
178
187
  --color-surface-inverted-fg: var(--neutral-1);
179
188
  --color-surface-disabled: var(--neutral-2);
@@ -181,11 +190,17 @@
181
190
  --color-surface-fg: var(--neutral-12);
182
191
  --color-surface-fg-muted: var(--neutral-11);
183
192
  --color-surface-fg-subtle: var(--neutral-9); /* 4.664:1 on surface-base — WCAG AA (verify, don't assume: see neutral-9) */
184
- --color-surface-border: var(--neutral-6); /* bumped for WCAG 1.4.11 (interactive/control edge) */
185
- --color-surface-border-strong: var(--neutral-7);
186
- --color-surface-border-subtle: var(--neutral-5);
187
- /* Card/panel edge — a faint hairline (NOT for interactive controls, which need the contrast-bumped token above). */
188
- --color-surface-border-card: color-mix(in oklch, var(--neutral-5) 30%, transparent);
193
+ /* OBJECT edges translucent, so an edge darkens whatever it lands on and can
194
+ never coincide with it. `surface-border` on white computes to #e8e8e8. */
195
+ --color-surface-border-subtle: oklch(0 0 0 / 0.05);
196
+ --color-surface-border: oklch(0 0 0 / 0.09);
197
+ --color-surface-border-strong: oklch(0 0 0 / 0.14);
198
+ --color-surface-border-card: var(--color-surface-border);
199
+
200
+ /* CONTROL edges — solid, so their contrast is measurable. WCAG 1.4.11 applies
201
+ to these and NOT to the decorative tiers above. */
202
+ --color-surface-border-interactive: var(--neutral-6);
203
+ --color-surface-border-interactive-strong: var(--neutral-7);
189
204
  --color-backdrop: oklch(0 0 0 / 0.4);
190
205
 
191
206
  /* Segmented control — translucent recess + raised thumb. Alpha, NOT a fixed
@@ -264,37 +279,58 @@
264
279
  /* ───────────────────────────────────────────────────────────
265
280
  CATEGORY COLORS (Sapta Varna — step subsets)
266
281
  ─────────────────────────────────────────────────────────── */
282
+ /* Foreground for solid category fills. Category step 9 LIGHTENS in dark mode,
283
+ the opposite of the intent ramps, so a fixed white fails AA there. neutral-1
284
+ inverts with the theme: near-white in light, near-black in dark.
285
+ Measured: light 4.59-4.97 on all seven, dark 5.55-6.24. Badge labels are 10px,
286
+ so AA body (4.5) is the bar, not large text. */
287
+ --color-category-fg: var(--neutral-0);
288
+
289
+ --color-category-teal-2: var(--teal-2);
267
290
  --color-category-teal-3: var(--teal-3);
291
+ --color-category-teal-4: var(--teal-4);
268
292
  --color-category-teal-7: var(--teal-7);
269
293
  --color-category-teal-9: var(--teal-9);
270
294
  --color-category-teal-11: var(--teal-11);
271
295
 
296
+ --color-category-amber-2: var(--amber-2);
272
297
  --color-category-amber-3: var(--amber-3);
298
+ --color-category-amber-4: var(--amber-4);
273
299
  --color-category-amber-7: var(--amber-7);
274
300
  --color-category-amber-9: var(--amber-9);
275
301
  --color-category-amber-11: var(--amber-11);
276
302
 
303
+ --color-category-slate-2: var(--slate-2);
277
304
  --color-category-slate-3: var(--slate-3);
305
+ --color-category-slate-4: var(--slate-4);
278
306
  --color-category-slate-7: var(--slate-7);
279
307
  --color-category-slate-9: var(--slate-9);
280
308
  --color-category-slate-11: var(--slate-11);
281
309
 
310
+ --color-category-indigo-2: var(--indigo-2);
282
311
  --color-category-indigo-3: var(--indigo-3);
312
+ --color-category-indigo-4: var(--indigo-4);
283
313
  --color-category-indigo-7: var(--indigo-7);
284
314
  --color-category-indigo-9: var(--indigo-9);
285
315
  --color-category-indigo-11: var(--indigo-11);
286
316
 
317
+ --color-category-cyan-2: var(--cyan-2);
287
318
  --color-category-cyan-3: var(--cyan-3);
319
+ --color-category-cyan-4: var(--cyan-4);
288
320
  --color-category-cyan-7: var(--cyan-7);
289
321
  --color-category-cyan-9: var(--cyan-9);
290
322
  --color-category-cyan-11: var(--cyan-11);
291
323
 
324
+ --color-category-orange-2: var(--orange-2);
292
325
  --color-category-orange-3: var(--orange-3);
326
+ --color-category-orange-4: var(--orange-4);
293
327
  --color-category-orange-7: var(--orange-7);
294
328
  --color-category-orange-9: var(--orange-9);
295
329
  --color-category-orange-11: var(--orange-11);
296
330
 
331
+ --color-category-emerald-2: var(--emerald-2);
297
332
  --color-category-emerald-3: var(--emerald-3);
333
+ --color-category-emerald-4: var(--emerald-4);
298
334
  --color-category-emerald-7: var(--emerald-7);
299
335
  --color-category-emerald-9: var(--emerald-9);
300
336
  --color-category-emerald-11: var(--emerald-11);
@@ -592,6 +628,9 @@
592
628
  --color-success-fg: var(--neutral-0);
593
629
  --color-info-fg: var(--neutral-0);
594
630
 
631
+ /* Category fills lighten in dark, so their label goes near-black, not white */
632
+ --color-category-fg: var(--neutral-1);
633
+
595
634
  /* Warning: amber-bright dark ramp */
596
635
  --color-warning-2: var(--amber-bright-2);
597
636
  --color-warning-3: var(--amber-bright-3);
@@ -603,16 +642,29 @@
603
642
  --color-warning-11: var(--amber-bright-11);
604
643
  --color-warning-fg: var(--neutral-0);
605
644
 
606
- /* Surface — dark page, lighter cards */
607
- --color-surface-base: var(--neutral-1); /* 0.11L */
608
- --color-surface-raised: var(--neutral-2); /* 0.17L */
609
- --color-surface-chrome: var(--neutral-2); /* chrome tier — matches raised for now */
610
- --color-surface-border: var(--neutral-4);
611
- --color-surface-border-strong: var(--neutral-5);
612
- --color-surface-overlay: oklch(0.13 0.0002 350);
613
- --color-surface-border-subtle: var(--neutral-3);
614
- /* Card edge in dark: a hair stronger so it still reads on the near-black base. */
615
- --color-surface-border-card: color-mix(in oklch, var(--neutral-6) 45%, transparent);
645
+ /* Surface — dark page, lighter cards. Unlike light, dark HAS room above the
646
+ page, so panel and overlay genuinely lift. */
647
+ --color-surface-base: var(--neutral-1); /* 0.147L */
648
+ --color-surface-panel: var(--neutral-2); /* 0.207L */
649
+ --color-surface-overlay: var(--neutral-2); /* same as panel + shadow */
650
+ --color-surface-panel-hover: var(--neutral-3);
651
+ --color-surface-panel-active: var(--neutral-4);
652
+ --color-surface-sunken: var(--neutral-sunken); /* coincides with the page */
653
+ --color-surface-sunken-hover: var(--neutral-2);
654
+
655
+ /* DEPRECATED — see the light block. */
656
+ --color-surface-raised: var(--color-surface-panel);
657
+ --color-surface-raised-hover: var(--color-surface-panel-hover);
658
+ --color-surface-raised-active: var(--color-surface-panel-active);
659
+
660
+ /* Object edges invert to translucent white. */
661
+ --color-surface-border-subtle: oklch(1 0 0 / 0.06);
662
+ --color-surface-border: oklch(1 0 0 / 0.10);
663
+ --color-surface-border-strong: oklch(1 0 0 / 0.16);
664
+ --color-surface-border-card: var(--color-surface-border);
665
+
666
+ --color-surface-border-interactive: var(--neutral-6);
667
+ --color-surface-border-interactive-strong: var(--neutral-7);
616
668
  --color-backdrop: oklch(0 0 0 / 0.6);
617
669
 
618
670
  /* Segmented control — inverted elevation in dark: track is a faint LIGHTER
@@ -730,20 +782,27 @@
730
782
  --color-surface-fg-muted: CanvasText;
731
783
  --color-surface-fg-subtle: GrayText;
732
784
  --color-surface-fg-disabled: GrayText;
733
- --color-surface-base: Canvas;
734
- --color-surface-sunken: Canvas;
735
- --color-surface-raised: Canvas;
736
- --color-surface-raised-hover: Canvas;
785
+ --color-surface-base: Canvas;
786
+ --color-surface-panel: Canvas;
787
+ --color-surface-overlay: Canvas;
788
+ --color-surface-panel-hover: Canvas;
789
+ --color-surface-panel-active: Canvas;
790
+ --color-surface-sunken: Canvas;
791
+ --color-surface-sunken-hover: Canvas;
792
+ --color-surface-raised: Canvas;
793
+ --color-surface-raised-hover: Canvas;
737
794
  --color-surface-raised-active: Canvas;
738
- --color-surface-chrome: Canvas;
739
- --color-surface-overlay: Canvas;
740
- --color-surface-disabled: Canvas;
741
- --color-surface-inverted: CanvasText;
742
- --color-surface-inverted-fg: Canvas;
743
- --color-surface-border: CanvasText;
744
- --color-surface-border-strong: CanvasText;
745
- --color-surface-border-subtle: GrayText;
746
- --color-surface-border-card: GrayText;
795
+ --color-surface-disabled: Canvas;
796
+ --color-surface-inverted: CanvasText;
797
+ --color-surface-inverted-fg: Canvas;
798
+ /* Forced colours flatten the object/control split — every edge must be a
799
+ system colour or it disappears entirely. */
800
+ --color-surface-border: CanvasText;
801
+ --color-surface-border-strong: CanvasText;
802
+ --color-surface-border-subtle: GrayText;
803
+ --color-surface-border-card: GrayText;
804
+ --color-surface-border-interactive: CanvasText;
805
+ --color-surface-border-interactive-strong: CanvasText;
747
806
  --color-backdrop: Canvas;
748
807
  --color-overlay: Canvas;
749
808
  --color-disabled: GrayText;
@@ -2,7 +2,7 @@
2
2
  CUSTOM VARIANTS (TW4 native)
3
3
 
4
4
  `@custom-variant <name> <selector>` registers a Tailwind 4 variant
5
- that consumers can use as a prefix, e.g. `dark:bg-surface-raised`.
5
+ that consumers can use as a prefix, e.g. `dark:bg-surface-panel`.
6
6
 
7
7
  Our dark variant matches TW3's classic `darkMode: 'class'` behavior
8
8
  plus one extra: the `.dark` element itself also receives `dark:*`
@@ -24,7 +24,7 @@ var h = c.forwardRef(({ className: e, children: n, chevronPosition: r = "right",
24
24
  className: "flex",
25
25
  children: /* @__PURE__ */ u(i, {
26
26
  ref: c,
27
- className: o("group flex flex-1 items-center justify-between py-ds-05 text-left text-body-md font-medium hover:bg-surface-raised rounded-control data-[state=open]:bg-surface-raised focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9", e),
27
+ className: o("group flex flex-1 items-center justify-between py-ds-05 text-left text-body-md font-medium hover:bg-surface-panel-hover rounded-control data-[state=open]:bg-surface-panel-hover focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9", e),
28
28
  ...a,
29
29
  children: [
30
30
  r === "left" && f,
@@ -1 +1 @@
1
- {"version":3,"file":"accordion.js","names":[],"sources":["../../src/ui/accordion.tsx"],"sourcesContent":["'use client'\n\nimport * as AccordionPrimitive from '@primitives/react-accordion'\nimport { IconChevronDown } from '@tabler/icons-react'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { Icon } from './icon'\nimport { tweens } from './lib/motion'\nimport { cn } from './lib/utils'\n\n/**\n * Accordion compound component — vertically stacked, collapsible content sections.\n *\n * **Parts (in composition order):**\n * - `Accordion` — root; controls single vs. multiple open panels (this root)\n * - `AccordionItem` — individual collapsible section (requires `value` prop)\n * - `AccordionTrigger` — the clickable header row (chevron icon auto-renders and rotates)\n * - `AccordionContent` — the collapsible body revealed when the item is open\n *\n * **`type` prop (required on root):**\n * - `\"single\"` — only one panel open at a time; supports `collapsible` prop to re-close the active item\n * - `\"multiple\"` — multiple panels open simultaneously (value is `string[]`); `collapsible` is NOT valid here\n *\n * @compound\n * @example\n * // Single-open FAQ accordion:\n * <Accordion type=\"single\" defaultValue=\"item-1\" collapsible>\n * <AccordionItem value=\"item-1\">\n * <AccordionTrigger>What is Shilp Sutra?</AccordionTrigger>\n * <AccordionContent>\n * A React design system built for Next.js App Router, with full accessibility baked in.\n * </AccordionContent>\n * </AccordionItem>\n * <AccordionItem value=\"item-2\">\n * <AccordionTrigger>Is dark mode supported?</AccordionTrigger>\n * <AccordionContent>\n * Yes — add the <code>.dark</code> class to the root element to activate it.\n * </AccordionContent>\n * </AccordionItem>\n * </Accordion>\n *\n * @example\n * // Multiple-open controlled accordion:\n * const [open, setOpen] = useState<string[]>(['billing'])\n * <Accordion type=\"multiple\" value={open} onValueChange={setOpen}>\n * <AccordionItem value=\"billing\">\n * <AccordionTrigger>Billing</AccordionTrigger>\n * <AccordionContent>Your billing details here.</AccordionContent>\n * </AccordionItem>\n * <AccordionItem value=\"security\">\n * <AccordionTrigger>Security</AccordionTrigger>\n * <AccordionContent>Security settings here.</AccordionContent>\n * </AccordionItem>\n * </Accordion>\n */\nconst Accordion = AccordionPrimitive.Root\n\nconst AccordionItem = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item\n ref={ref}\n className={cn('border-b border-surface-border', className)}\n {...props}\n />\n))\nAccordionItem.displayName = 'AccordionItem'\n\ninterface AccordionTriggerExtendedProps extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger> {\n chevronPosition?: 'left' | 'right'\n}\n\nconst AccordionTrigger = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Trigger>,\n AccordionTriggerExtendedProps\n>(({ className, children, chevronPosition = 'right', ...props }, ref) => {\n const chevron = (\n <Icon icon={IconChevronDown} size=\"sm\" className=\"shrink-0 text-surface-fg-muted transition-transform duration-moderate-02 ease-productive-standard group-data-[state=open]:rotate-180\" />\n )\n\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n 'group flex flex-1 items-center justify-between py-ds-05 text-left text-body-md font-medium hover:bg-surface-raised rounded-control data-[state=open]:bg-surface-raised focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9',\n className,\n )}\n {...props}\n >\n {chevronPosition === 'left' && chevron}\n {children}\n {chevronPosition === 'right' && chevron}\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n )\n})\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName\n\nconst AccordionContent = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"w-full overflow-hidden text-body-md data-[state=open]:animate-accordion-down data-[state=closed]:animate-accordion-up\"\n {...props}\n >\n <motion.div\n initial={false}\n animate={{ opacity: 1 }}\n transition={tweens.fade}\n >\n <div className={cn('pb-ds-05 pt-ds-02', className)}>{children}</div>\n </motion.div>\n </AccordionPrimitive.Content>\n))\nAccordionContent.displayName = AccordionPrimitive.Content.displayName\n\nexport type AccordionItemProps = React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\nexport type AccordionTriggerProps = AccordionTriggerExtendedProps\nexport type AccordionContentProps = React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n\nexport { Accordion, AccordionContent,AccordionItem, AccordionTrigger }\n"],"mappings":";;;;;;;;;;AAwDA,IAAM,IAAY,GAEZ,IAAgB,EAAM,YAGzB,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,GAAD;CACO;CACL,WAAW,EAAG,kCAAkC,CAAS;CACzD,GAAI;AACL,CAAA,CACF;AACD,EAAc,cAAc;AAM5B,IAAM,IAAmB,EAAM,YAG5B,EAAE,cAAW,aAAU,qBAAkB,SAAS,GAAG,KAAS,MAAQ;CACvE,IAAM,IACJ,kBAAC,GAAD;EAAM,MAAM;EAAiB,MAAK;EAAK,WAAU;CAAwI,CAAA;CAG3L,OACE,kBAAC,GAAD;EAA2B,WAAU;YACnC,kBAAC,GAAD;GACO;GACL,WAAW,EACT,wPACA,CACF;GACA,GAAI;aANN;IAQG,MAAoB,UAAU;IAC9B;IACA,MAAoB,WAAW;GACN;;CACH,CAAA;AAE/B,CAAC;AACD,EAAiB,cAAA,EAAyC;AAE1D,IAAM,IAAmB,EAAM,YAG5B,EAAE,cAAW,aAAU,GAAG,KAAS,MACpC,kBAAC,GAAD;CACO;CACL,WAAU;CACV,GAAI;WAEJ,kBAAC,EAAO,KAAR;EACE,SAAS;EACT,SAAS,EAAE,SAAS,EAAE;EACtB,YAAY,EAAO;YAEnB,kBAAC,OAAD;GAAK,WAAW,EAAG,qBAAqB,CAAS;GAAI;EAAc,CAAA;CACzD,CAAA;AACc,CAAA,CAC7B;AACD,EAAiB,cAAA,EAAyC"}
1
+ {"version":3,"file":"accordion.js","names":[],"sources":["../../src/ui/accordion.tsx"],"sourcesContent":["'use client'\n\nimport * as AccordionPrimitive from '@primitives/react-accordion'\nimport { IconChevronDown } from '@tabler/icons-react'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { Icon } from './icon'\nimport { tweens } from './lib/motion'\nimport { cn } from './lib/utils'\n\n/**\n * Accordion compound component — vertically stacked, collapsible content sections.\n *\n * **Parts (in composition order):**\n * - `Accordion` — root; controls single vs. multiple open panels (this root)\n * - `AccordionItem` — individual collapsible section (requires `value` prop)\n * - `AccordionTrigger` — the clickable header row (chevron icon auto-renders and rotates)\n * - `AccordionContent` — the collapsible body revealed when the item is open\n *\n * **`type` prop (required on root):**\n * - `\"single\"` — only one panel open at a time; supports `collapsible` prop to re-close the active item\n * - `\"multiple\"` — multiple panels open simultaneously (value is `string[]`); `collapsible` is NOT valid here\n *\n * @compound\n * @example\n * // Single-open FAQ accordion:\n * <Accordion type=\"single\" defaultValue=\"item-1\" collapsible>\n * <AccordionItem value=\"item-1\">\n * <AccordionTrigger>What is Shilp Sutra?</AccordionTrigger>\n * <AccordionContent>\n * A React design system built for Next.js App Router, with full accessibility baked in.\n * </AccordionContent>\n * </AccordionItem>\n * <AccordionItem value=\"item-2\">\n * <AccordionTrigger>Is dark mode supported?</AccordionTrigger>\n * <AccordionContent>\n * Yes — add the <code>.dark</code> class to the root element to activate it.\n * </AccordionContent>\n * </AccordionItem>\n * </Accordion>\n *\n * @example\n * // Multiple-open controlled accordion:\n * const [open, setOpen] = useState<string[]>(['billing'])\n * <Accordion type=\"multiple\" value={open} onValueChange={setOpen}>\n * <AccordionItem value=\"billing\">\n * <AccordionTrigger>Billing</AccordionTrigger>\n * <AccordionContent>Your billing details here.</AccordionContent>\n * </AccordionItem>\n * <AccordionItem value=\"security\">\n * <AccordionTrigger>Security</AccordionTrigger>\n * <AccordionContent>Security settings here.</AccordionContent>\n * </AccordionItem>\n * </Accordion>\n */\nconst Accordion = AccordionPrimitive.Root\n\nconst AccordionItem = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item\n ref={ref}\n className={cn('border-b border-surface-border', className)}\n {...props}\n />\n))\nAccordionItem.displayName = 'AccordionItem'\n\ninterface AccordionTriggerExtendedProps extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger> {\n chevronPosition?: 'left' | 'right'\n}\n\nconst AccordionTrigger = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Trigger>,\n AccordionTriggerExtendedProps\n>(({ className, children, chevronPosition = 'right', ...props }, ref) => {\n const chevron = (\n <Icon icon={IconChevronDown} size=\"sm\" className=\"shrink-0 text-surface-fg-muted transition-transform duration-moderate-02 ease-productive-standard group-data-[state=open]:rotate-180\" />\n )\n\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n 'group flex flex-1 items-center justify-between py-ds-05 text-left text-body-md font-medium hover:bg-surface-panel-hover rounded-control data-[state=open]:bg-surface-panel-hover focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9',\n className,\n )}\n {...props}\n >\n {chevronPosition === 'left' && chevron}\n {children}\n {chevronPosition === 'right' && chevron}\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n )\n})\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName\n\nconst AccordionContent = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"w-full overflow-hidden text-body-md data-[state=open]:animate-accordion-down data-[state=closed]:animate-accordion-up\"\n {...props}\n >\n <motion.div\n initial={false}\n animate={{ opacity: 1 }}\n transition={tweens.fade}\n >\n <div className={cn('pb-ds-05 pt-ds-02', className)}>{children}</div>\n </motion.div>\n </AccordionPrimitive.Content>\n))\nAccordionContent.displayName = AccordionPrimitive.Content.displayName\n\nexport type AccordionItemProps = React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\nexport type AccordionTriggerProps = AccordionTriggerExtendedProps\nexport type AccordionContentProps = React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n\nexport { Accordion, AccordionContent,AccordionItem, AccordionTrigger }\n"],"mappings":";;;;;;;;;;AAwDA,IAAM,IAAY,GAEZ,IAAgB,EAAM,YAGzB,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,GAAD;CACO;CACL,WAAW,EAAG,kCAAkC,CAAS;CACzD,GAAI;AACL,CAAA,CACF;AACD,EAAc,cAAc;AAM5B,IAAM,IAAmB,EAAM,YAG5B,EAAE,cAAW,aAAU,qBAAkB,SAAS,GAAG,KAAS,MAAQ;CACvE,IAAM,IACJ,kBAAC,GAAD;EAAM,MAAM;EAAiB,MAAK;EAAK,WAAU;CAAwI,CAAA;CAG3L,OACE,kBAAC,GAAD;EAA2B,WAAU;YACnC,kBAAC,GAAD;GACO;GACL,WAAW,EACT,kQACA,CACF;GACA,GAAI;aANN;IAQG,MAAoB,UAAU;IAC9B;IACA,MAAoB,WAAW;GACN;;CACH,CAAA;AAE/B,CAAC;AACD,EAAiB,cAAA,EAAyC;AAE1D,IAAM,IAAmB,EAAM,YAG5B,EAAE,cAAW,aAAU,GAAG,KAAS,MACpC,kBAAC,GAAD;CACO;CACL,WAAU;CACV,GAAI;WAEJ,kBAAC,EAAO,KAAR;EACE,SAAS;EACT,SAAS,EAAE,SAAS,EAAE;EACtB,YAAY,EAAO;YAEnB,kBAAC,OAAD;GAAK,WAAW,EAAG,qBAAqB,CAAS;GAAI;EAAc,CAAA;CACzD,CAAA;AACc,CAAA,CAC7B;AACD,EAAiB,cAAA,EAAyC"}
@@ -107,7 +107,7 @@ var k = p.forwardRef(({ className: e, ...t }, i) => /* @__PURE__ */ m(r, {
107
107
  k.displayName = r.displayName;
108
108
  var A = p.forwardRef(({ className: e, ...t }, r) => /* @__PURE__ */ m(i, {
109
109
  ref: r,
110
- className: n("inline-flex h-ds-md items-center justify-center rounded-control px-ds-05 text-body-md font-semibold transition-colors bg-transparent text-surface-fg-muted border border-surface-border-strong hover:bg-surface-raised hover:text-surface-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-action-disabled", e),
110
+ className: n("inline-flex h-ds-md items-center justify-center rounded-control px-ds-05 text-body-md font-semibold transition-colors bg-transparent text-surface-fg-muted border border-surface-border-strong hover:bg-surface-panel-hover hover:text-surface-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-action-disabled", e),
111
111
  ...t
112
112
  }));
113
113
  A.displayName = i.displayName;
@@ -1 +1 @@
1
- {"version":3,"file":"alert-dialog.js","names":[],"sources":["../../src/ui/alert-dialog.tsx"],"sourcesContent":["'use client'\n\nimport * as AlertDialogPrimitive from '@primitives/react-alert-dialog'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { useIsMobile } from '../hooks/use-mobile'\nimport { springs, tweens } from './lib/motion'\nimport { cn } from './lib/utils'\n\n// ── Internal context to thread `open` state to animated children ──\n\ntype AlertDialogContextValue = { open: boolean }\nconst AlertDialogContext = React.createContext<AlertDialogContextValue>({ open: false })\nconst useAlertDialogOpen = () => React.useContext(AlertDialogContext)\n\nconst AlertDialog: React.FC<React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Root>> = ({\n open: openProp,\n defaultOpen,\n onOpenChange,\n ...props\n}) => {\n const [internalOpen, setInternalOpen] = React.useState(defaultOpen ?? false)\n const isControlled = openProp !== undefined\n const open = isControlled ? openProp : internalOpen\n\n const handleOpenChange = React.useCallback(\n (nextOpen: boolean) => {\n if (!isControlled) setInternalOpen(nextOpen)\n onOpenChange?.(nextOpen)\n },\n [isControlled, onOpenChange],\n )\n\n const contextValue = React.useMemo(() => ({ open }), [open])\n\n return (\n <AlertDialogContext.Provider value={contextValue}>\n <AlertDialogPrimitive.Root open={open} onOpenChange={handleOpenChange} {...props} />\n </AlertDialogContext.Provider>\n )\n}\nAlertDialog.displayName = 'AlertDialog'\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n ref={ref}\n forceMount\n className={cn(\n 'fixed inset-0 z-modal bg-overlay',\n className,\n )}\n {...props}\n />\n))\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName\n\ninterface AlertDialogContentProps extends React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content> {\n /** When true (default), AlertDialog fills the screen on mobile (<768px). Set false to always use centered modal. */\n responsive?: boolean\n}\n\nconst AlertDialogContent = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Content>,\n AlertDialogContentProps\n>(({ className, children, responsive, ...props }, ref) => {\n const { open } = useAlertDialogOpen()\n const isMobileRaw = useIsMobile()\n const isMobile = responsive !== false && isMobileRaw\n\n return (\n <AnimatePresence>\n {open && (\n <AlertDialogPortal forceMount>\n <AlertDialogOverlay asChild>\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={tweens.fade}\n />\n </AlertDialogOverlay>\n <AlertDialogPrimitive.Content\n ref={ref}\n forceMount\n asChild\n {...props}\n >\n <motion.div\n initial={isMobile ? { y: '100%' } : { opacity: 0, scale: 0.95, x: '-50%', y: '-50%' }}\n animate={isMobile ? { y: 0 } : { opacity: 1, scale: 1, x: '-50%', y: '-50%' }}\n exit={isMobile ? { y: '100%' } : { opacity: 0, scale: 0.95, x: '-50%', y: '-50%' }}\n transition={isMobile\n ? springs.smooth\n : { ...springs.smooth, opacity: tweens.fade }\n }\n className={cn(\n 'fixed z-modal grid w-full gap-ds-05 bg-surface-overlay p-ds-06',\n responsive !== false\n ? 'inset-0 md:inset-auto md:left-[50%] md:top-[50%] md:max-w-lg md:rounded-overlay-lg md:shadow-overlay'\n : 'left-[50%] top-[50%] max-w-lg rounded-overlay-lg shadow-overlay',\n className,\n )}\n >\n {children}\n </motion.div>\n </AlertDialogPrimitive.Content>\n </AlertDialogPortal>\n )}\n </AnimatePresence>\n )\n})\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName\n\nconst AlertDialogHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col space-y-ds-02b text-center sm:text-left',\n className,\n )}\n {...props}\n />\n ),\n)\nAlertDialogHeader.displayName = 'AlertDialogHeader'\n\nconst AlertDialogFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-ds-03',\n className,\n )}\n {...props}\n />\n ),\n)\nAlertDialogFooter.displayName = 'AlertDialogFooter'\n\nconst AlertDialogTitle = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n className={cn(\n 'text-heading-xs font-semibold',\n className,\n )}\n {...props}\n />\n))\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName\n\nconst AlertDialogDescription = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n className={cn('text-body-md text-surface-fg-muted', className)}\n {...props}\n />\n))\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName\n\nconst AlertDialogAction = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n className={cn(\n 'inline-flex h-ds-md items-center justify-center rounded-control px-ds-05 text-body-md font-semibold transition-colors bg-accent-9 text-accent-fg hover:bg-accent-10 active:bg-accent-10 shadow-raised focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-action-disabled',\n className,\n )}\n {...props}\n />\n))\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName\n\nconst AlertDialogCancel = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n className={cn(\n 'inline-flex h-ds-md items-center justify-center rounded-control px-ds-05 text-body-md font-semibold transition-colors bg-transparent text-surface-fg-muted border border-surface-border-strong hover:bg-surface-raised hover:text-surface-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-action-disabled',\n className,\n )}\n {...props}\n />\n))\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName\n\nexport type { AlertDialogContentProps }\nexport type AlertDialogActionProps = React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\nexport type AlertDialogCancelProps = React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n\nexport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogOverlay,\n AlertDialogPortal,\n AlertDialogTitle,\n AlertDialogTrigger,\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"alert-dialog.js","names":[],"sources":["../../src/ui/alert-dialog.tsx"],"sourcesContent":["'use client'\n\nimport * as AlertDialogPrimitive from '@primitives/react-alert-dialog'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { useIsMobile } from '../hooks/use-mobile'\nimport { springs, tweens } from './lib/motion'\nimport { cn } from './lib/utils'\n\n// ── Internal context to thread `open` state to animated children ──\n\ntype AlertDialogContextValue = { open: boolean }\nconst AlertDialogContext = React.createContext<AlertDialogContextValue>({ open: false })\nconst useAlertDialogOpen = () => React.useContext(AlertDialogContext)\n\nconst AlertDialog: React.FC<React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Root>> = ({\n open: openProp,\n defaultOpen,\n onOpenChange,\n ...props\n}) => {\n const [internalOpen, setInternalOpen] = React.useState(defaultOpen ?? false)\n const isControlled = openProp !== undefined\n const open = isControlled ? openProp : internalOpen\n\n const handleOpenChange = React.useCallback(\n (nextOpen: boolean) => {\n if (!isControlled) setInternalOpen(nextOpen)\n onOpenChange?.(nextOpen)\n },\n [isControlled, onOpenChange],\n )\n\n const contextValue = React.useMemo(() => ({ open }), [open])\n\n return (\n <AlertDialogContext.Provider value={contextValue}>\n <AlertDialogPrimitive.Root open={open} onOpenChange={handleOpenChange} {...props} />\n </AlertDialogContext.Provider>\n )\n}\nAlertDialog.displayName = 'AlertDialog'\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n ref={ref}\n forceMount\n className={cn(\n 'fixed inset-0 z-modal bg-overlay',\n className,\n )}\n {...props}\n />\n))\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName\n\ninterface AlertDialogContentProps extends React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content> {\n /** When true (default), AlertDialog fills the screen on mobile (<768px). Set false to always use centered modal. */\n responsive?: boolean\n}\n\nconst AlertDialogContent = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Content>,\n AlertDialogContentProps\n>(({ className, children, responsive, ...props }, ref) => {\n const { open } = useAlertDialogOpen()\n const isMobileRaw = useIsMobile()\n const isMobile = responsive !== false && isMobileRaw\n\n return (\n <AnimatePresence>\n {open && (\n <AlertDialogPortal forceMount>\n <AlertDialogOverlay asChild>\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={tweens.fade}\n />\n </AlertDialogOverlay>\n <AlertDialogPrimitive.Content\n ref={ref}\n forceMount\n asChild\n {...props}\n >\n <motion.div\n initial={isMobile ? { y: '100%' } : { opacity: 0, scale: 0.95, x: '-50%', y: '-50%' }}\n animate={isMobile ? { y: 0 } : { opacity: 1, scale: 1, x: '-50%', y: '-50%' }}\n exit={isMobile ? { y: '100%' } : { opacity: 0, scale: 0.95, x: '-50%', y: '-50%' }}\n transition={isMobile\n ? springs.smooth\n : { ...springs.smooth, opacity: tweens.fade }\n }\n className={cn(\n 'fixed z-modal grid w-full gap-ds-05 bg-surface-overlay p-ds-06',\n responsive !== false\n ? 'inset-0 md:inset-auto md:left-[50%] md:top-[50%] md:max-w-lg md:rounded-overlay-lg md:shadow-overlay'\n : 'left-[50%] top-[50%] max-w-lg rounded-overlay-lg shadow-overlay',\n className,\n )}\n >\n {children}\n </motion.div>\n </AlertDialogPrimitive.Content>\n </AlertDialogPortal>\n )}\n </AnimatePresence>\n )\n})\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName\n\nconst AlertDialogHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col space-y-ds-02b text-center sm:text-left',\n className,\n )}\n {...props}\n />\n ),\n)\nAlertDialogHeader.displayName = 'AlertDialogHeader'\n\nconst AlertDialogFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-ds-03',\n className,\n )}\n {...props}\n />\n ),\n)\nAlertDialogFooter.displayName = 'AlertDialogFooter'\n\nconst AlertDialogTitle = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n className={cn(\n 'text-heading-xs font-semibold',\n className,\n )}\n {...props}\n />\n))\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName\n\nconst AlertDialogDescription = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n className={cn('text-body-md text-surface-fg-muted', className)}\n {...props}\n />\n))\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName\n\nconst AlertDialogAction = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n className={cn(\n 'inline-flex h-ds-md items-center justify-center rounded-control px-ds-05 text-body-md font-semibold transition-colors bg-accent-9 text-accent-fg hover:bg-accent-10 active:bg-accent-10 shadow-raised focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-action-disabled',\n className,\n )}\n {...props}\n />\n))\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName\n\nconst AlertDialogCancel = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n className={cn(\n 'inline-flex h-ds-md items-center justify-center rounded-control px-ds-05 text-body-md font-semibold transition-colors bg-transparent text-surface-fg-muted border border-surface-border-strong hover:bg-surface-panel-hover hover:text-surface-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-action-disabled',\n className,\n )}\n {...props}\n />\n))\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName\n\nexport type { AlertDialogContentProps }\nexport type AlertDialogActionProps = React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\nexport type AlertDialogCancelProps = React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n\nexport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogOverlay,\n AlertDialogPortal,\n AlertDialogTitle,\n AlertDialogTrigger,\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"alert.d.ts","sourceRoot":"","sources":["../../src/ui/alert.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,QAAA,MAAM,aAAa;;;;8EA4ClB,CAAA;AAUD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,WAAW,UACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,EACzD,YAAY,CAAC,OAAO,aAAa,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,QAAA,MAAM,KAAK,mFA0DV,CAAA;AAGD,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAA"}
1
+ {"version":3,"file":"alert.d.ts","sourceRoot":"","sources":["../../src/ui/alert.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,QAAA,MAAM,aAAa;;;;8EA4ClB,CAAA;AAUD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,WAAW,UACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,EACzD,YAAY,CAAC,OAAO,aAAa,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,QAAA,MAAM,KAAK,mFAkEV,CAAA;AAGD,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAA"}
package/dist/ui/alert.js CHANGED
@@ -32,27 +32,27 @@ var h = m("relative flex rounded-surface border", {
32
32
  {
33
33
  variant: "subtle",
34
34
  color: "info",
35
- className: "bg-info-3 border-info-7 text-info-11"
35
+ className: "bg-info-2 border-info-4 text-info-11"
36
36
  },
37
37
  {
38
38
  variant: "subtle",
39
39
  color: "success",
40
- className: "bg-success-3 border-success-7 text-success-11"
40
+ className: "bg-success-2 border-success-4 text-success-11"
41
41
  },
42
42
  {
43
43
  variant: "subtle",
44
44
  color: "warning",
45
- className: "bg-warning-3 border-warning-7 text-warning-11"
45
+ className: "bg-warning-2 border-warning-4 text-warning-11"
46
46
  },
47
47
  {
48
48
  variant: "subtle",
49
49
  color: "error",
50
- className: "bg-error-3 border-error-7 text-error-11"
50
+ className: "bg-error-2 border-error-4 text-error-11"
51
51
  },
52
52
  {
53
53
  variant: "subtle",
54
54
  color: "neutral",
55
- className: "bg-surface-raised border-surface-border-strong text-surface-fg [&>svg]:text-surface-fg-muted"
55
+ className: "bg-surface-panel border-surface-border-strong text-surface-fg [&>svg]:text-surface-fg-muted"
56
56
  },
57
57
  {
58
58
  variant: "solid",
@@ -77,7 +77,7 @@ var h = m("relative flex rounded-surface border", {
77
77
  {
78
78
  variant: "solid",
79
79
  color: "neutral",
80
- className: "bg-surface-raised-hover text-surface-fg border-transparent [&>svg]:text-surface-fg-muted"
80
+ className: "bg-surface-panel-hover text-surface-fg border-transparent [&>svg]:text-surface-fg-muted"
81
81
  },
82
82
  {
83
83
  variant: "outline",
@@ -163,7 +163,7 @@ var h = m("relative flex rounded-surface border", {
163
163
  _ && /* @__PURE__ */ a("button", {
164
164
  type: "button",
165
165
  onClick: w,
166
- className: "shrink-0 min-h-ds-xs min-w-ds-xs flex items-center justify-center rounded-control-inner text-surface-fg-subtle transition-colors duration-fast-01 ease-productive-standard hover:text-surface-fg-muted hover:bg-surface-raised-hover active:scale-95 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9",
166
+ className: n("shrink-0 min-h-ds-xs min-w-ds-xs flex items-center justify-center rounded-control-inner transition-colors duration-fast-01 ease-productive-standard active:scale-95 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9", c === "solid" ? "text-current opacity-80 hover:opacity-100" : "text-surface-fg-subtle hover:text-surface-fg-muted hover:bg-surface-panel-hover"),
167
167
  "aria-label": "Dismiss",
168
168
  children: /* @__PURE__ */ a(r, {
169
169
  icon: d,
@@ -1 +1 @@
1
- {"version":3,"file":"alert.js","names":[],"sources":["../../src/ui/alert.tsx"],"sourcesContent":["'use client'\n\nimport { IconAlertCircle, IconAlertTriangle,IconCircleCheck, IconInfoCircle, IconX } from '@tabler/icons-react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { Icon } from './icon'\nimport { motionProps,springs } from './lib/motion'\nimport { cn } from './lib/utils'\n\nconst alertVariants = cva(\n 'relative flex rounded-surface border',\n {\n variants: {\n variant: {\n subtle: '',\n solid: '',\n outline: '',\n },\n color: {\n info: '',\n success: '',\n warning: '',\n error: '',\n neutral: '',\n },\n size: {\n sm: 'gap-ds-03 p-ds-03',\n md: 'gap-ds-04 p-ds-05',\n lg: 'gap-ds-05 p-ds-07',\n },\n },\n compoundVariants: [\n // subtle (surface bg) — default, matches previous behavior\n { variant: 'subtle', color: 'info', className: 'bg-info-3 border-info-7 text-info-11' },\n { variant: 'subtle', color: 'success', className: 'bg-success-3 border-success-7 text-success-11' },\n { variant: 'subtle', color: 'warning', className: 'bg-warning-3 border-warning-7 text-warning-11' },\n { variant: 'subtle', color: 'error', className: 'bg-error-3 border-error-7 text-error-11' },\n { variant: 'subtle', color: 'neutral', className: 'bg-surface-raised border-surface-border-strong text-surface-fg [&>svg]:text-surface-fg-muted' },\n // solid (solid bg, contrasting text) — canonical name\n { variant: 'solid', color: 'info', className: 'bg-info-9 text-info-fg border-transparent [&>svg]:text-info-fg' },\n { variant: 'solid', color: 'success', className: 'bg-success-9 text-success-fg border-transparent [&>svg]:text-success-fg' },\n { variant: 'solid', color: 'warning', className: 'bg-warning-9 text-warning-fg border-transparent [&>svg]:text-warning-fg' },\n { variant: 'solid', color: 'error', className: 'bg-error-9 text-error-fg border-transparent [&>svg]:text-error-fg' },\n { variant: 'solid', color: 'neutral', className: 'bg-surface-raised-hover text-surface-fg border-transparent [&>svg]:text-surface-fg-muted' },\n // outline (transparent bg, colored border)\n { variant: 'outline', color: 'info', className: 'bg-transparent border-info-7 text-info-11' },\n { variant: 'outline', color: 'success', className: 'bg-transparent border-success-7 text-success-11' },\n { variant: 'outline', color: 'warning', className: 'bg-transparent border-warning-7 text-warning-11' },\n { variant: 'outline', color: 'error', className: 'bg-transparent border-error-7 text-error-11' },\n { variant: 'outline', color: 'neutral', className: 'bg-transparent border-surface-border-strong text-surface-fg [&>svg]:text-surface-fg-muted' },\n ],\n defaultVariants: { variant: 'subtle', color: 'info', size: 'md' },\n },\n)\n\nconst ALERT_ICONS: Record<string, React.ForwardRefExoticComponent<any>> = {\n info: IconInfoCircle,\n success: IconCircleCheck,\n warning: IconAlertTriangle,\n error: IconAlertCircle,\n neutral: IconInfoCircle,\n}\n\n/**\n * Props for Alert — an inline message block with a colored icon, optional title, optional body,\n * and an optional dismiss button. Renders with `role=\"alert\"` for screen reader announcements.\n *\n * **Variants:** `subtle` (default, tinted surface) | `solid` (solid colored bg) | `outline` (transparent bg, colored border)\n *\n * **Colors:** `info` (default, blue tones) | `success` | `warning` | `error` | `neutral`\n * The matching icon (info circle, checkmark, triangle, alert circle) is auto-selected by color.\n *\n * **Alert vs Banner:** Alert is inline (inside page content). Banner is a full-width notification\n * strip rendered at the top of a page/section (see `<Banner>`).\n *\n * **Dismissible:** Provide `onDismiss` to show an × button. Absence of the prop = non-dismissible.\n *\n * @example\n * // Informational tip inside a settings form:\n * <Alert title=\"Tip\" color=\"info\">\n * Changes take effect after you save and reload the page.\n * </Alert>\n *\n * @example\n * // Error feedback after a failed API call (dismissible):\n * <Alert color=\"error\" title=\"Save failed\" onDismiss={() => setError(null)}>\n * Your changes could not be saved. Please try again.\n * </Alert>\n *\n * @example\n * // Success confirmation after publishing:\n * <Alert color=\"success\" title=\"Published!\">\n * Your post is now live and visible to all subscribers.\n * </Alert>\n *\n * @example\n * // Neutral inline note (no colored intent):\n * <Alert color=\"neutral\">This field is auto-populated from your profile.</Alert>\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface AlertProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n VariantProps<typeof alertVariants> {\n title?: string\n /**\n * Called after the exit animation completes, not immediately on click.\n * The dismiss button sets internal visibility to false, triggering the exit\n * animation; `onDismiss` fires via `AnimatePresence.onExitComplete`.\n */\n onDismiss?: () => void\n}\n\nconst Alert = React.forwardRef<HTMLDivElement, AlertProps>(\n ({ className, variant = 'subtle', color = 'info', size = 'md', title, onDismiss, children, ...props }, ref) => {\n const AlertIcon = ALERT_ICONS[color ?? 'info']\n const [isVisible, setIsVisible] = React.useState(true)\n\n const handleDismiss = React.useCallback(() => {\n setIsVisible(false)\n }, [])\n\n const iconSize = size === 'sm' ? 'sm' : size === 'lg' ? 'lg' : 'md'\n const dismissIconSize = size === 'sm' ? 'xs' : 'sm'\n const textClass = size === 'sm' ? 'text-body-xs' : size === 'lg' ? 'text-body-md' : 'text-body-md'\n const titleClass = size === 'sm' ? 'text-body-sm' : size === 'lg' ? 'text-heading-xs' : 'text-body-md'\n\n return (\n <AnimatePresence onExitComplete={onDismiss}>\n {isVisible && (\n <motion.div\n ref={ref}\n initial={{ opacity: 1, y: 0 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={springs.snappy}\n className={cn(alertVariants({ variant, color, size }), className)}\n role=\"alert\"\n {...motionProps(props)}\n >\n <Icon icon={AlertIcon} size={iconSize} className=\"mt-ds-01 shrink-0\" />\n <div className=\"flex-1 min-w-0\">\n {title && <p className={cn(titleClass, 'font-semibold mb-ds-01')}>{title}</p>}\n {/* Body: on solid variants the CVA sets text-accent-fg (white) on\n saturated step-9 backgrounds. Muting the body to surface-fg (grey)\n there drops contrast below WCAG AA. Only mute on subtle/outline\n variants where the root color is a readable step-11. */}\n <div\n className={cn(\n textClass,\n variant !== 'solid' && 'text-surface-fg-muted',\n )}\n >\n {children}\n </div>\n </div>\n {onDismiss && (\n <button\n type=\"button\"\n onClick={handleDismiss}\n className=\"shrink-0 min-h-ds-xs min-w-ds-xs flex items-center justify-center rounded-control-inner text-surface-fg-subtle transition-colors duration-fast-01 ease-productive-standard hover:text-surface-fg-muted hover:bg-surface-raised-hover active:scale-95 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9\"\n aria-label=\"Dismiss\"\n >\n <Icon icon={IconX} size={dismissIconSize} />\n </button>\n )}\n </motion.div>\n )}\n </AnimatePresence>\n )\n },\n)\nAlert.displayName = 'Alert'\n\nexport { Alert, alertVariants }\n"],"mappings":"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"}
1
+ {"version":3,"file":"alert.js","names":[],"sources":["../../src/ui/alert.tsx"],"sourcesContent":["'use client'\n\nimport { IconAlertCircle, IconAlertTriangle,IconCircleCheck, IconInfoCircle, IconX } from '@tabler/icons-react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { Icon } from './icon'\nimport { motionProps,springs } from './lib/motion'\nimport { cn } from './lib/utils'\n\nconst alertVariants = cva(\n 'relative flex rounded-surface border',\n {\n variants: {\n variant: {\n subtle: '',\n solid: '',\n outline: '',\n },\n color: {\n info: '',\n success: '',\n warning: '',\n error: '',\n neutral: '',\n },\n size: {\n sm: 'gap-ds-03 p-ds-03',\n md: 'gap-ds-04 p-ds-05',\n lg: 'gap-ds-05 p-ds-07',\n },\n },\n compoundVariants: [\n // subtle (surface bg) — default, matches previous behavior\n { variant: 'subtle', color: 'info', className: 'bg-info-2 border-info-4 text-info-11' },\n { variant: 'subtle', color: 'success', className: 'bg-success-2 border-success-4 text-success-11' },\n { variant: 'subtle', color: 'warning', className: 'bg-warning-2 border-warning-4 text-warning-11' },\n { variant: 'subtle', color: 'error', className: 'bg-error-2 border-error-4 text-error-11' },\n { variant: 'subtle', color: 'neutral', className: 'bg-surface-panel border-surface-border-strong text-surface-fg [&>svg]:text-surface-fg-muted' },\n // solid (solid bg, contrasting text) — canonical name\n { variant: 'solid', color: 'info', className: 'bg-info-9 text-info-fg border-transparent [&>svg]:text-info-fg' },\n { variant: 'solid', color: 'success', className: 'bg-success-9 text-success-fg border-transparent [&>svg]:text-success-fg' },\n { variant: 'solid', color: 'warning', className: 'bg-warning-9 text-warning-fg border-transparent [&>svg]:text-warning-fg' },\n { variant: 'solid', color: 'error', className: 'bg-error-9 text-error-fg border-transparent [&>svg]:text-error-fg' },\n { variant: 'solid', color: 'neutral', className: 'bg-surface-panel-hover text-surface-fg border-transparent [&>svg]:text-surface-fg-muted' },\n // outline (transparent bg, colored border)\n { variant: 'outline', color: 'info', className: 'bg-transparent border-info-7 text-info-11' },\n { variant: 'outline', color: 'success', className: 'bg-transparent border-success-7 text-success-11' },\n { variant: 'outline', color: 'warning', className: 'bg-transparent border-warning-7 text-warning-11' },\n { variant: 'outline', color: 'error', className: 'bg-transparent border-error-7 text-error-11' },\n { variant: 'outline', color: 'neutral', className: 'bg-transparent border-surface-border-strong text-surface-fg [&>svg]:text-surface-fg-muted' },\n ],\n defaultVariants: { variant: 'subtle', color: 'info', size: 'md' },\n },\n)\n\nconst ALERT_ICONS: Record<string, React.ForwardRefExoticComponent<any>> = {\n info: IconInfoCircle,\n success: IconCircleCheck,\n warning: IconAlertTriangle,\n error: IconAlertCircle,\n neutral: IconInfoCircle,\n}\n\n/**\n * Props for Alert — an inline message block with a colored icon, optional title, optional body,\n * and an optional dismiss button. Renders with `role=\"alert\"` for screen reader announcements.\n *\n * **Variants:** `subtle` (default, tinted surface) | `solid` (solid colored bg) | `outline` (transparent bg, colored border)\n *\n * **Colors:** `info` (default, blue tones) | `success` | `warning` | `error` | `neutral`\n * The matching icon (info circle, checkmark, triangle, alert circle) is auto-selected by color.\n *\n * **Alert vs Banner:** Alert is inline (inside page content). Banner is a full-width notification\n * strip rendered at the top of a page/section (see `<Banner>`).\n *\n * **Dismissible:** Provide `onDismiss` to show an × button. Absence of the prop = non-dismissible.\n *\n * @example\n * // Informational tip inside a settings form:\n * <Alert title=\"Tip\" color=\"info\">\n * Changes take effect after you save and reload the page.\n * </Alert>\n *\n * @example\n * // Error feedback after a failed API call (dismissible):\n * <Alert color=\"error\" title=\"Save failed\" onDismiss={() => setError(null)}>\n * Your changes could not be saved. Please try again.\n * </Alert>\n *\n * @example\n * // Success confirmation after publishing:\n * <Alert color=\"success\" title=\"Published!\">\n * Your post is now live and visible to all subscribers.\n * </Alert>\n *\n * @example\n * // Neutral inline note (no colored intent):\n * <Alert color=\"neutral\">This field is auto-populated from your profile.</Alert>\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface AlertProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n VariantProps<typeof alertVariants> {\n title?: string\n /**\n * Called after the exit animation completes, not immediately on click.\n * The dismiss button sets internal visibility to false, triggering the exit\n * animation; `onDismiss` fires via `AnimatePresence.onExitComplete`.\n */\n onDismiss?: () => void\n}\n\nconst Alert = React.forwardRef<HTMLDivElement, AlertProps>(\n ({ className, variant = 'subtle', color = 'info', size = 'md', title, onDismiss, children, ...props }, ref) => {\n const AlertIcon = ALERT_ICONS[color ?? 'info']\n const [isVisible, setIsVisible] = React.useState(true)\n\n const handleDismiss = React.useCallback(() => {\n setIsVisible(false)\n }, [])\n\n const iconSize = size === 'sm' ? 'sm' : size === 'lg' ? 'lg' : 'md'\n const dismissIconSize = size === 'sm' ? 'xs' : 'sm'\n const textClass = size === 'sm' ? 'text-body-xs' : size === 'lg' ? 'text-body-md' : 'text-body-md'\n const titleClass = size === 'sm' ? 'text-body-sm' : size === 'lg' ? 'text-heading-xs' : 'text-body-md'\n\n return (\n <AnimatePresence onExitComplete={onDismiss}>\n {isVisible && (\n <motion.div\n ref={ref}\n initial={{ opacity: 1, y: 0 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={springs.snappy}\n className={cn(alertVariants({ variant, color, size }), className)}\n role=\"alert\"\n {...motionProps(props)}\n >\n <Icon icon={AlertIcon} size={iconSize} className=\"mt-ds-01 shrink-0\" />\n <div className=\"flex-1 min-w-0\">\n {title && <p className={cn(titleClass, 'font-semibold mb-ds-01')}>{title}</p>}\n {/* Body: on solid variants the CVA sets text-accent-fg (white) on\n saturated step-9 backgrounds. Muting the body to surface-fg (grey)\n there drops contrast below WCAG AA. Only mute on subtle/outline\n variants where the root color is a readable step-11. */}\n <div\n className={cn(\n textClass,\n variant !== 'solid' && 'text-surface-fg-muted',\n )}\n >\n {children}\n </div>\n </div>\n {onDismiss && (\n <button\n type=\"button\"\n onClick={handleDismiss}\n className={cn(\n 'shrink-0 min-h-ds-xs min-w-ds-xs flex items-center justify-center rounded-control-inner transition-colors duration-fast-01 ease-productive-standard active:scale-95 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9',\n // On solid the fill is a saturated step 9, where a mid grey\n // measures as low as 1.01:1. Inherit the alert's own foreground,\n // exactly as the title and body already do.\n variant === 'solid'\n ? 'text-current opacity-80 hover:opacity-100'\n : 'text-surface-fg-subtle hover:text-surface-fg-muted hover:bg-surface-panel-hover',\n )}\n aria-label=\"Dismiss\"\n >\n <Icon icon={IconX} size={dismissIconSize} />\n </button>\n )}\n </motion.div>\n )}\n </AnimatePresence>\n )\n },\n)\nAlert.displayName = 'Alert'\n\nexport { Alert, alertVariants }\n"],"mappings":";;;;;;;;;;AAWA,IAAM,IAAgB,EACpB,wCACA;CACE,UAAU;EACR,SAAS;GACP,QAAQ;GACR,OAAO;GACP,SAAS;EACX;EACA,OAAO;GACL,MAAM;GACN,SAAS;GACT,SAAS;GACT,OAAO;GACP,SAAS;EACX;EACA,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;CACF;CACA,kBAAkB;EAEhB;GAAE,SAAS;GAAU,OAAO;GAAQ,WAAW;EAAuC;EACtF;GAAE,SAAS;GAAU,OAAO;GAAW,WAAW;EAAgD;EAClG;GAAE,SAAS;GAAU,OAAO;GAAW,WAAW;EAAgD;EAClG;GAAE,SAAS;GAAU,OAAO;GAAS,WAAW;EAA0C;EAC1F;GAAE,SAAS;GAAU,OAAO;GAAW,WAAW;EAA8F;EAEhJ;GAAE,SAAS;GAAS,OAAO;GAAQ,WAAW;EAAiE;EAC/G;GAAE,SAAS;GAAS,OAAO;GAAW,WAAW;EAA0E;EAC3H;GAAE,SAAS;GAAS,OAAO;GAAW,WAAW;EAA0E;EAC3H;GAAE,SAAS;GAAS,OAAO;GAAS,WAAW;EAAoE;EACnH;GAAE,SAAS;GAAS,OAAO;GAAW,WAAW;EAA0F;EAE3I;GAAE,SAAS;GAAW,OAAO;GAAQ,WAAW;EAA4C;EAC5F;GAAE,SAAS;GAAW,OAAO;GAAW,WAAW;EAAkD;EACrG;GAAE,SAAS;GAAW,OAAO;GAAW,WAAW;EAAkD;EACrG;GAAE,SAAS;GAAW,OAAO;GAAS,WAAW;EAA8C;EAC/F;GAAE,SAAS;GAAW,OAAO;GAAW,WAAW;EAA4F;CACjJ;CACA,iBAAiB;EAAE,SAAS;EAAU,OAAO;EAAQ,MAAM;CAAK;AAClE,CACF,GAEM,IAAoE;CACxE,MAAS;CACT,SAAS;CACT,SAAS;CACT,OAAS;CACT,SAAS;AACX,GAmDM,IAAQ,EAAM,YACjB,EAAE,cAAW,aAAU,UAAU,WAAQ,QAAQ,UAAO,MAAM,UAAO,cAAW,aAAU,GAAG,KAAS,MAAQ;CAC7G,IAAM,IAAY,EAAY,KAAS,SACjC,CAAC,GAAW,KAAgB,EAAM,SAAS,EAAI,GAE/C,IAAgB,EAAM,kBAAkB;EAC5C,EAAa,EAAK;CACpB,GAAG,CAAC,CAAC,GAEC,IAAW,MAAS,OAAO,OAAO,MAAS,OAAO,OAAO,MACzD,IAAkB,MAAS,OAAO,OAAO,MACzC,IAAY,MAAS,OAAO,iBAAiC,gBAC7D,IAAa,MAAS,OAAO,iBAAiB,MAAS,OAAO,oBAAoB;CAExF,OACE,kBAAC,GAAD;EAAiB,gBAAgB;YAC9B,KACC,kBAAC,EAAO,KAAR;GACO;GACL,SAAS;IAAE,SAAS;IAAG,GAAG;GAAE;GAC5B,SAAS;IAAE,SAAS;IAAG,GAAG;GAAE;GAC5B,MAAM;IAAE,SAAS;IAAG,GAAG;GAAG;GAC1B,YAAY,EAAQ;GACpB,WAAW,EAAG,EAAc;IAAE;IAAS;IAAO;GAAK,CAAC,GAAG,CAAS;GAChE,MAAK;GACL,GAAI,EAAY,CAAK;aARvB;IAUE,kBAAC,GAAD;KAAM,MAAM;KAAW,MAAM;KAAU,WAAU;IAAqB,CAAA;IACtE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACG,KAAS,kBAAC,KAAD;MAAG,WAAW,EAAG,GAAY,wBAAwB;gBAAI;KAAS,CAAA,GAK5E,kBAAC,OAAD;MACE,WAAW,EACT,GACA,MAAY,WAAW,uBACzB;MAEC;KACE,CAAA,CACF;;IACJ,KACC,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAW,EACT,qPAIA,MAAY,UACR,8CACA,iFACN;KACA,cAAW;eAEX,kBAAC,GAAD;MAAM,MAAM;MAAO,MAAM;KAAkB,CAAA;IACrC,CAAA;GAEA;;CAEC,CAAA;AAErB,CACF;AACA,EAAM,cAAc"}
package/dist/ui/avatar.js CHANGED
@@ -98,7 +98,7 @@ function S(e) {
98
98
  return x[Math.abs(t) % x.length];
99
99
  }
100
100
  var C = s.forwardRef(({ className: n, size: r, shape: s, status: d, ring: b, badge: x, loading: S, children: C, ...w }, T) => {
101
- let E = s ?? "circle", D = b && b !== "none" ? t("ring-2 ring-offset-2 ring-offset-surface-raised", v[b], y[E]) : void 0;
101
+ let E = s ?? "circle", D = b && b !== "none" ? t("ring-2 ring-offset-2 ring-offset-surface-panel", v[b], y[E]) : void 0;
102
102
  if (S) return /* @__PURE__ */ c("span", {
103
103
  ref: T,
104
104
  className: t("relative inline-flex shrink-0", D),
@@ -139,14 +139,14 @@ var C = s.forwardRef(({ className: n, size: r, shape: s, status: d, ring: b, bad
139
139
  })
140
140
  }),
141
141
  O && (x === "dot" ? /* @__PURE__ */ c("span", {
142
- className: "absolute -right-0.5 -top-0.5 h-ds-03 w-ds-03 rounded-pill bg-error-9 ring-2 ring-surface-raised",
142
+ className: "absolute -right-0.5 -top-0.5 h-ds-03 w-ds-03 rounded-pill bg-error-9 ring-2 ring-surface-panel",
143
143
  "data-slot": "avatar-badge-dot",
144
144
  "aria-hidden": "true"
145
145
  }) : typeof x == "number" ? /* @__PURE__ */ c(u.span, {
146
146
  initial: { scale: 0 },
147
147
  animate: { scale: 1 },
148
148
  transition: e.smooth,
149
- className: "absolute -right-1 -top-1 flex min-w-ds-05 items-center justify-center rounded-pill bg-error-9 px-1 text-[10px] font-bold leading-[16px] text-error-fg ring-2 ring-surface-raised",
149
+ className: "absolute -right-1 -top-1 flex min-w-ds-05 items-center justify-center rounded-pill bg-error-9 px-1 text-[10px] font-bold leading-[16px] text-error-fg ring-2 ring-surface-panel",
150
150
  "data-slot": "avatar-badge",
151
151
  role: "status",
152
152
  "aria-label": `${x > 99 ? "99+" : x} notifications`,
@@ -1 +1 @@
1
- {"version":3,"file":"avatar.js","names":[],"sources":["../../src/ui/avatar.tsx"],"sourcesContent":["'use client'\n\nimport * as AvatarPrimitive from \"@primitives/react-avatar\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { motion } from \"framer-motion\"\nimport * as React from \"react\"\n\nimport { Dot, type DotColor, type DotSize } from \"./dot\"\nimport { springs } from \"./lib/motion\"\nimport { cn } from \"./lib/utils\"\nimport { Skeleton } from \"./skeleton\"\n\n// ── Contexts so AvatarFallback can inherit shape & size from Avatar ──\ntype AvatarShape = 'circle' | 'square' | 'rounded'\ntype AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'\nconst AvatarShapeContext = React.createContext<AvatarShape>('circle')\nconst AvatarSizeContext = React.createContext<AvatarSize>('md')\n\nexport const avatarVariants = cva(\n 'relative flex shrink-0 overflow-hidden',\n {\n variants: {\n size: {\n xs: 'h-ds-xs w-ds-xs',\n sm: 'h-ds-sm w-ds-sm',\n md: 'h-ds-md w-ds-md',\n lg: 'h-ds-lg w-ds-lg',\n xl: 'h-ds-xl w-ds-xl',\n },\n shape: {\n circle: 'rounded-pill',\n square: 'rounded-none',\n rounded: 'rounded-control',\n },\n },\n defaultVariants: { size: 'md', shape: 'circle' },\n }\n)\n\nexport type AvatarStatus = 'online' | 'offline' | 'busy' | 'away'\n\nexport type AvatarRing = 'none' | 'lead' | 'admin' | 'client'\n\n// Presence status → shared Dot intent colour.\nconst statusDotColor: Record<AvatarStatus, DotColor> = {\n online: 'success',\n offline: 'neutral',\n busy: 'error',\n away: 'warning',\n}\n\nconst statusLabelMap: Record<AvatarStatus, string> = {\n online: 'Online',\n offline: 'Offline',\n busy: 'Busy',\n away: 'Away',\n}\n\n/** Avatar size → Dot size (the status dot scales with the avatar). */\nconst statusDotSize: Record<AvatarSize, DotSize> = {\n xs: 'xs',\n sm: 'sm',\n md: 'md',\n lg: 'lg',\n xl: 'lg',\n}\n\n// ── Role ring ───────────────────────────────────────────────────────────────\n\nconst ringColorMap: Record<Exclude<AvatarRing, 'none'>, string> = {\n lead: 'ring-accent-7',\n admin: 'ring-warning-7',\n client: 'ring-info-7',\n}\n\nconst ringShapeMap: Record<string, string> = {\n circle: 'rounded-pill',\n square: 'rounded-none',\n rounded: 'rounded-control',\n}\n\n// ── Fallback font sizes that scale with avatar size ─────────────────────────\nconst fallbackTextSizeMap: Record<AvatarSize, string> = {\n xs: 'text-body-xs',\n sm: 'text-body-xs',\n md: 'text-body-sm',\n lg: 'text-body-md',\n xl: 'text-heading-xs',\n}\n\n// ── Deterministic fallback colors ───────────────────────────────────────────\n\nconst FALLBACK_COLORS = [\n { bg: 'bg-accent-3', text: 'text-accent-11' },\n { bg: 'bg-success-3', text: 'text-success-11' },\n { bg: 'bg-warning-3', text: 'text-warning-11' },\n { bg: 'bg-error-3', text: 'text-error-11' },\n { bg: 'bg-info-3', text: 'text-info-11' },\n { bg: 'bg-category-teal-3', text: 'text-category-teal-11' },\n { bg: 'bg-category-indigo-3', text: 'text-category-indigo-11' },\n { bg: 'bg-category-cyan-3', text: 'text-category-cyan-11' },\n] as const\n\n/**\n * Simple string hash that produces a deterministic index into FALLBACK_COLORS.\n * Uses djb2 for a reasonable distribution with short strings.\n */\nfunction getFallbackColor(seed: string): (typeof FALLBACK_COLORS)[number] {\n let hash = 5381\n for (let i = 0; i < seed.length; i++) {\n hash = ((hash << 5) + hash + seed.charCodeAt(i)) | 0\n }\n const index = Math.abs(hash) % FALLBACK_COLORS.length\n return FALLBACK_COLORS[index]\n}\n\n/**\n * Props for Avatar — a user/entity image container with size, shape, and presence-status variants.\n *\n * **Sizes:** `xs` | `sm` | `md` (default) | `lg` | `xl` — the status dot scales with the avatar size.\n *\n * **Shapes:** `circle` (default, round) | `square` (sharp corners) | `rounded` (rounded corners, for bots/apps)\n *\n * **Status dot:** `status=\"online\"` (green) | `\"offline\"` (muted) | `\"busy\"` (red) | `\"away\"` (amber).\n * The dot renders with `role=\"img\"` and an accessible `aria-label` — it is not purely decorative.\n *\n * **Role ring:** `ring=\"lead\"` (accent) | `\"admin\"` (warning) | `\"client\"` (info) — a colored ring\n * around the avatar indicating the user's role.\n *\n * **Badge:** `badge={5}` (number) | `badge=\"dot\"` (notification dot) | `badge={<Icon />}` (custom).\n * Numbers > 99 display as \"99+\". Badge is hidden when `0` or `undefined`.\n *\n * **Loading:** `loading={true}` shows a pulse skeleton placeholder.\n *\n * **Children:** Use `<AvatarImage>` for the photo and `<AvatarFallback>` for initials when the image fails.\n *\n * @example\n * // User avatar with photo and fallback initials:\n * <Avatar size=\"md\">\n * <AvatarImage src={user.avatarUrl} alt={user.name} />\n * <AvatarFallback>JD</AvatarFallback>\n * </Avatar>\n *\n * @example\n * // Online presence indicator in a team roster:\n * <Avatar size=\"lg\" status=\"online\">\n * <AvatarImage src={user.photoUrl} alt={user.name} />\n * <AvatarFallback>{user.initials}</AvatarFallback>\n * </Avatar>\n *\n * @example\n * // Square shape for a bot/integration logo:\n * <Avatar shape=\"square\" size=\"xl\">\n * <AvatarImage src=\"/logos/github.png\" alt=\"GitHub\" />\n * </Avatar>\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface AvatarProps\n extends Omit<React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>, 'children'>,\n VariantProps<typeof avatarVariants> {\n /** Optional status indicator displayed as a dot at the bottom-right corner */\n status?: AvatarStatus\n /** Role ring color indicator */\n ring?: AvatarRing\n /** Badge overlay: number, 'dot', or custom ReactNode */\n badge?: number | 'dot' | React.ReactNode\n /** Show loading skeleton instead of content */\n loading?: boolean\n children?: React.ReactNode\n}\n\nconst Avatar = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Root>,\n AvatarProps\n>(({ className, size, shape, status, ring, badge, loading, children, ...props }, ref) => {\n const resolvedShape = shape ?? 'circle'\n\n // Build ring classes for the outer wrapper\n const ringClasses = ring && ring !== 'none'\n ? cn('ring-2 ring-offset-2 ring-offset-surface-raised', ringColorMap[ring], ringShapeMap[resolvedShape])\n : undefined\n\n // Loading skeleton — early return\n if (loading) {\n return (\n <span ref={ref} className={cn('relative inline-flex shrink-0', ringClasses)}>\n <Skeleton\n className={cn(avatarVariants({ size, shape }))}\n data-slot=\"avatar-skeleton\"\n />\n </span>\n )\n }\n\n // Determine whether to render badge\n const showBadge = badge !== undefined && badge !== 0\n\n return (\n <AvatarShapeContext.Provider value={resolvedShape}>\n <AvatarSizeContext.Provider value={size ?? 'md'}>\n <span className={cn('relative inline-flex shrink-0', ringClasses)}>\n <AvatarPrimitive.Root\n ref={ref}\n className={cn(avatarVariants({ size, shape }), className)}\n {...props}\n >\n {children}\n </AvatarPrimitive.Root>\n {status && (\n <span\n className=\"absolute bottom-0 right-0\"\n role=\"img\"\n aria-label={statusLabelMap[status]}\n >\n {/* Shared Dot primitive: colour + contrast ring; wrapper owns position + a11y. */}\n <Dot color={statusDotColor[status]} size={statusDotSize[size ?? 'md']} withBorder aria-hidden />\n </span>\n )}\n {showBadge && (\n badge === 'dot' ? (\n <span\n className=\"absolute -right-0.5 -top-0.5 h-ds-03 w-ds-03 rounded-pill bg-error-9 ring-2 ring-surface-raised\"\n data-slot=\"avatar-badge-dot\"\n aria-hidden=\"true\"\n />\n ) : typeof badge === 'number' ? (\n <motion.span\n initial={{ scale: 0 }}\n animate={{ scale: 1 }}\n transition={springs.smooth}\n className=\"absolute -right-1 -top-1 flex min-w-ds-05 items-center justify-center rounded-pill bg-error-9 px-1 text-[10px] font-bold leading-[16px] text-error-fg ring-2 ring-surface-raised\"\n data-slot=\"avatar-badge\"\n role=\"status\"\n aria-label={`${badge > 99 ? '99+' : badge} notifications`}\n >\n {badge > 99 ? '99+' : badge}\n </motion.span>\n ) : (\n <span className=\"absolute -right-1 -top-1\" data-slot=\"avatar-badge-custom\">\n {badge}\n </span>\n )\n )}\n </span>\n </AvatarSizeContext.Provider>\n </AvatarShapeContext.Provider>\n )\n})\nAvatar.displayName = AvatarPrimitive.Root.displayName\n\nconst AvatarImage = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Image>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>\n>(({ className, ...props }, ref) => (\n <motion.span\n initial={{ scale: 0.96 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={springs.smooth}\n className=\"absolute inset-0 h-full w-full\"\n >\n <AvatarPrimitive.Image\n ref={ref}\n className={cn(\"aspect-square h-full w-full\", className)}\n {...props}\n />\n </motion.span>\n))\nAvatarImage.displayName = AvatarPrimitive.Image.displayName\n\nexport interface AvatarFallbackProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback> {\n /**\n * Seed string for deterministic color selection.\n * Falls back to the text content of `children` if not provided.\n */\n colorSeed?: string\n}\n\nconst AvatarFallback = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Fallback>,\n AvatarFallbackProps\n>(({ className, colorSeed, children, ...props }, ref) => {\n // Derive seed: explicit colorSeed > children text content > empty string\n const childrenText = typeof children === 'string' ? children : ''\n const seed = colorSeed ?? childrenText\n const color = getFallbackColor(seed)\n\n // Inherit shape and size from parent Avatar via context\n const shape = React.useContext(AvatarShapeContext)\n const size = React.useContext(AvatarSizeContext)\n const shapeClass = shape === 'square' ? 'rounded-none' : shape === 'rounded' ? 'rounded-control' : 'rounded-pill'\n\n // Letter-spacing based on character count\n const tracking = childrenText.length === 1 ? 'tracking-wide' : 'tracking-normal'\n\n return (\n <AvatarPrimitive.Fallback\n ref={ref}\n data-slot=\"avatar-fallback\"\n className={cn(\n 'flex h-full w-full items-center justify-center font-semibold',\n shapeClass,\n fallbackTextSizeMap[size],\n color.bg,\n color.text,\n tracking,\n className,\n )}\n {...props}\n >\n {children}\n </AvatarPrimitive.Fallback>\n )\n})\nAvatarFallback.displayName = AvatarPrimitive.Fallback.displayName\n\nexport { Avatar, AvatarFallback,AvatarImage }\n"],"mappings":"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"}
1
+ {"version":3,"file":"avatar.js","names":[],"sources":["../../src/ui/avatar.tsx"],"sourcesContent":["'use client'\n\nimport * as AvatarPrimitive from \"@primitives/react-avatar\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { motion } from \"framer-motion\"\nimport * as React from \"react\"\n\nimport { Dot, type DotColor, type DotSize } from \"./dot\"\nimport { springs } from \"./lib/motion\"\nimport { cn } from \"./lib/utils\"\nimport { Skeleton } from \"./skeleton\"\n\n// ── Contexts so AvatarFallback can inherit shape & size from Avatar ──\ntype AvatarShape = 'circle' | 'square' | 'rounded'\ntype AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'\nconst AvatarShapeContext = React.createContext<AvatarShape>('circle')\nconst AvatarSizeContext = React.createContext<AvatarSize>('md')\n\nexport const avatarVariants = cva(\n 'relative flex shrink-0 overflow-hidden',\n {\n variants: {\n size: {\n xs: 'h-ds-xs w-ds-xs',\n sm: 'h-ds-sm w-ds-sm',\n md: 'h-ds-md w-ds-md',\n lg: 'h-ds-lg w-ds-lg',\n xl: 'h-ds-xl w-ds-xl',\n },\n shape: {\n circle: 'rounded-pill',\n square: 'rounded-none',\n rounded: 'rounded-control',\n },\n },\n defaultVariants: { size: 'md', shape: 'circle' },\n }\n)\n\nexport type AvatarStatus = 'online' | 'offline' | 'busy' | 'away'\n\nexport type AvatarRing = 'none' | 'lead' | 'admin' | 'client'\n\n// Presence status → shared Dot intent colour.\nconst statusDotColor: Record<AvatarStatus, DotColor> = {\n online: 'success',\n offline: 'neutral',\n busy: 'error',\n away: 'warning',\n}\n\nconst statusLabelMap: Record<AvatarStatus, string> = {\n online: 'Online',\n offline: 'Offline',\n busy: 'Busy',\n away: 'Away',\n}\n\n/** Avatar size → Dot size (the status dot scales with the avatar). */\nconst statusDotSize: Record<AvatarSize, DotSize> = {\n xs: 'xs',\n sm: 'sm',\n md: 'md',\n lg: 'lg',\n xl: 'lg',\n}\n\n// ── Role ring ───────────────────────────────────────────────────────────────\n\nconst ringColorMap: Record<Exclude<AvatarRing, 'none'>, string> = {\n lead: 'ring-accent-7',\n admin: 'ring-warning-7',\n client: 'ring-info-7',\n}\n\nconst ringShapeMap: Record<string, string> = {\n circle: 'rounded-pill',\n square: 'rounded-none',\n rounded: 'rounded-control',\n}\n\n// ── Fallback font sizes that scale with avatar size ─────────────────────────\nconst fallbackTextSizeMap: Record<AvatarSize, string> = {\n xs: 'text-body-xs',\n sm: 'text-body-xs',\n md: 'text-body-sm',\n lg: 'text-body-md',\n xl: 'text-heading-xs',\n}\n\n// ── Deterministic fallback colors ───────────────────────────────────────────\n\nconst FALLBACK_COLORS = [\n { bg: 'bg-accent-3', text: 'text-accent-11' },\n { bg: 'bg-success-3', text: 'text-success-11' },\n { bg: 'bg-warning-3', text: 'text-warning-11' },\n { bg: 'bg-error-3', text: 'text-error-11' },\n { bg: 'bg-info-3', text: 'text-info-11' },\n { bg: 'bg-category-teal-3', text: 'text-category-teal-11' },\n { bg: 'bg-category-indigo-3', text: 'text-category-indigo-11' },\n { bg: 'bg-category-cyan-3', text: 'text-category-cyan-11' },\n] as const\n\n/**\n * Simple string hash that produces a deterministic index into FALLBACK_COLORS.\n * Uses djb2 for a reasonable distribution with short strings.\n */\nfunction getFallbackColor(seed: string): (typeof FALLBACK_COLORS)[number] {\n let hash = 5381\n for (let i = 0; i < seed.length; i++) {\n hash = ((hash << 5) + hash + seed.charCodeAt(i)) | 0\n }\n const index = Math.abs(hash) % FALLBACK_COLORS.length\n return FALLBACK_COLORS[index]\n}\n\n/**\n * Props for Avatar — a user/entity image container with size, shape, and presence-status variants.\n *\n * **Sizes:** `xs` | `sm` | `md` (default) | `lg` | `xl` — the status dot scales with the avatar size.\n *\n * **Shapes:** `circle` (default, round) | `square` (sharp corners) | `rounded` (rounded corners, for bots/apps)\n *\n * **Status dot:** `status=\"online\"` (green) | `\"offline\"` (muted) | `\"busy\"` (red) | `\"away\"` (amber).\n * The dot renders with `role=\"img\"` and an accessible `aria-label` — it is not purely decorative.\n *\n * **Role ring:** `ring=\"lead\"` (accent) | `\"admin\"` (warning) | `\"client\"` (info) — a colored ring\n * around the avatar indicating the user's role.\n *\n * **Badge:** `badge={5}` (number) | `badge=\"dot\"` (notification dot) | `badge={<Icon />}` (custom).\n * Numbers > 99 display as \"99+\". Badge is hidden when `0` or `undefined`.\n *\n * **Loading:** `loading={true}` shows a pulse skeleton placeholder.\n *\n * **Children:** Use `<AvatarImage>` for the photo and `<AvatarFallback>` for initials when the image fails.\n *\n * @example\n * // User avatar with photo and fallback initials:\n * <Avatar size=\"md\">\n * <AvatarImage src={user.avatarUrl} alt={user.name} />\n * <AvatarFallback>JD</AvatarFallback>\n * </Avatar>\n *\n * @example\n * // Online presence indicator in a team roster:\n * <Avatar size=\"lg\" status=\"online\">\n * <AvatarImage src={user.photoUrl} alt={user.name} />\n * <AvatarFallback>{user.initials}</AvatarFallback>\n * </Avatar>\n *\n * @example\n * // Square shape for a bot/integration logo:\n * <Avatar shape=\"square\" size=\"xl\">\n * <AvatarImage src=\"/logos/github.png\" alt=\"GitHub\" />\n * </Avatar>\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface AvatarProps\n extends Omit<React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>, 'children'>,\n VariantProps<typeof avatarVariants> {\n /** Optional status indicator displayed as a dot at the bottom-right corner */\n status?: AvatarStatus\n /** Role ring color indicator */\n ring?: AvatarRing\n /** Badge overlay: number, 'dot', or custom ReactNode */\n badge?: number | 'dot' | React.ReactNode\n /** Show loading skeleton instead of content */\n loading?: boolean\n children?: React.ReactNode\n}\n\nconst Avatar = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Root>,\n AvatarProps\n>(({ className, size, shape, status, ring, badge, loading, children, ...props }, ref) => {\n const resolvedShape = shape ?? 'circle'\n\n // Build ring classes for the outer wrapper\n const ringClasses = ring && ring !== 'none'\n ? cn('ring-2 ring-offset-2 ring-offset-surface-panel', ringColorMap[ring], ringShapeMap[resolvedShape])\n : undefined\n\n // Loading skeleton — early return\n if (loading) {\n return (\n <span ref={ref} className={cn('relative inline-flex shrink-0', ringClasses)}>\n <Skeleton\n className={cn(avatarVariants({ size, shape }))}\n data-slot=\"avatar-skeleton\"\n />\n </span>\n )\n }\n\n // Determine whether to render badge\n const showBadge = badge !== undefined && badge !== 0\n\n return (\n <AvatarShapeContext.Provider value={resolvedShape}>\n <AvatarSizeContext.Provider value={size ?? 'md'}>\n <span className={cn('relative inline-flex shrink-0', ringClasses)}>\n <AvatarPrimitive.Root\n ref={ref}\n className={cn(avatarVariants({ size, shape }), className)}\n {...props}\n >\n {children}\n </AvatarPrimitive.Root>\n {status && (\n <span\n className=\"absolute bottom-0 right-0\"\n role=\"img\"\n aria-label={statusLabelMap[status]}\n >\n {/* Shared Dot primitive: colour + contrast ring; wrapper owns position + a11y. */}\n <Dot color={statusDotColor[status]} size={statusDotSize[size ?? 'md']} withBorder aria-hidden />\n </span>\n )}\n {showBadge && (\n badge === 'dot' ? (\n <span\n className=\"absolute -right-0.5 -top-0.5 h-ds-03 w-ds-03 rounded-pill bg-error-9 ring-2 ring-surface-panel\"\n data-slot=\"avatar-badge-dot\"\n aria-hidden=\"true\"\n />\n ) : typeof badge === 'number' ? (\n <motion.span\n initial={{ scale: 0 }}\n animate={{ scale: 1 }}\n transition={springs.smooth}\n className=\"absolute -right-1 -top-1 flex min-w-ds-05 items-center justify-center rounded-pill bg-error-9 px-1 text-[10px] font-bold leading-[16px] text-error-fg ring-2 ring-surface-panel\"\n data-slot=\"avatar-badge\"\n role=\"status\"\n aria-label={`${badge > 99 ? '99+' : badge} notifications`}\n >\n {badge > 99 ? '99+' : badge}\n </motion.span>\n ) : (\n <span className=\"absolute -right-1 -top-1\" data-slot=\"avatar-badge-custom\">\n {badge}\n </span>\n )\n )}\n </span>\n </AvatarSizeContext.Provider>\n </AvatarShapeContext.Provider>\n )\n})\nAvatar.displayName = AvatarPrimitive.Root.displayName\n\nconst AvatarImage = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Image>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>\n>(({ className, ...props }, ref) => (\n <motion.span\n initial={{ scale: 0.96 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={springs.smooth}\n className=\"absolute inset-0 h-full w-full\"\n >\n <AvatarPrimitive.Image\n ref={ref}\n className={cn(\"aspect-square h-full w-full\", className)}\n {...props}\n />\n </motion.span>\n))\nAvatarImage.displayName = AvatarPrimitive.Image.displayName\n\nexport interface AvatarFallbackProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback> {\n /**\n * Seed string for deterministic color selection.\n * Falls back to the text content of `children` if not provided.\n */\n colorSeed?: string\n}\n\nconst AvatarFallback = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Fallback>,\n AvatarFallbackProps\n>(({ className, colorSeed, children, ...props }, ref) => {\n // Derive seed: explicit colorSeed > children text content > empty string\n const childrenText = typeof children === 'string' ? children : ''\n const seed = colorSeed ?? childrenText\n const color = getFallbackColor(seed)\n\n // Inherit shape and size from parent Avatar via context\n const shape = React.useContext(AvatarShapeContext)\n const size = React.useContext(AvatarSizeContext)\n const shapeClass = shape === 'square' ? 'rounded-none' : shape === 'rounded' ? 'rounded-control' : 'rounded-pill'\n\n // Letter-spacing based on character count\n const tracking = childrenText.length === 1 ? 'tracking-wide' : 'tracking-normal'\n\n return (\n <AvatarPrimitive.Fallback\n ref={ref}\n data-slot=\"avatar-fallback\"\n className={cn(\n 'flex h-full w-full items-center justify-center font-semibold',\n shapeClass,\n fallbackTextSizeMap[size],\n color.bg,\n color.text,\n tracking,\n className,\n )}\n {...props}\n >\n {children}\n </AvatarPrimitive.Fallback>\n )\n})\nAvatarFallback.displayName = AvatarPrimitive.Fallback.displayName\n\nexport { Avatar, AvatarFallback,AvatarImage }\n"],"mappings":"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"}
@@ -36,7 +36,7 @@ var c = {
36
36
  opacity: 0
37
37
  },
38
38
  transition: e.smooth,
39
- className: t("absolute flex items-center justify-center rounded-pill font-sans font-semibold ring-2 ring-surface-raised", l[f], c[h], d ? "h-2.5 w-2.5" : "min-w-[18px] h-[18px] px-1 text-[11px] leading-none"),
39
+ className: t("absolute flex items-center justify-center rounded-pill font-sans font-semibold ring-2 ring-surface-panel", l[f], c[h], d ? "h-2.5 w-2.5" : "min-w-[18px] h-[18px] px-1 text-[11px] leading-none"),
40
40
  children: !d && S
41
41
  }, "indicator") })]
42
42
  });
@@ -1 +1 @@
1
- {"version":3,"file":"badge-indicator.js","names":[],"sources":["../../src/ui/badge-indicator.tsx"],"sourcesContent":["'use client'\n\nimport { AnimatePresence, motion, useReducedMotion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { springs } from './lib/motion'\nimport { cn } from './lib/utils'\n\nconst PLACEMENT_CLASSES = {\n 'top-right': '-top-1 -right-1',\n 'top-left': '-top-1 -left-1',\n 'bottom-right': '-bottom-1 -right-1',\n 'bottom-left': '-bottom-1 -left-1',\n} as const\n\nconst COLOR_CLASSES = {\n error: 'bg-error-9 text-error-fg',\n success: 'bg-success-9 text-success-fg',\n warning: 'bg-warning-9 text-warning-fg',\n accent: 'bg-accent-9 text-accent-fg',\n info: 'bg-info-9 text-info-fg',\n} as const\n\nexport interface BadgeIndicatorProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'color'> {\n count?: number\n max?: number\n dot?: boolean\n color?: keyof typeof COLOR_CLASSES\n invisible?: boolean\n showZero?: boolean\n placement?: keyof typeof PLACEMENT_CLASSES\n children: React.ReactNode\n}\n\nexport const BadgeIndicator = React.forwardRef<HTMLSpanElement, BadgeIndicatorProps>(\n function BadgeIndicator(\n {\n count,\n max = 99,\n dot = false,\n color = 'error',\n invisible = false,\n showZero = false,\n placement = 'top-right',\n className,\n children,\n ...rest\n },\n ref,\n ) {\n const prefersReduced = useReducedMotion()\n const show = !invisible && (dot || (count !== undefined && (count > 0 || showZero)))\n const displayCount = count !== undefined && count > max ? `${max}+` : count\n\n return (\n <span ref={ref} className={cn('relative inline-flex', className)} {...rest}>\n {children}\n <AnimatePresence>\n {show && (\n <motion.span\n key=\"indicator\"\n initial={prefersReduced ? { opacity: 0 } : { scale: 0, opacity: 0 }}\n animate={prefersReduced ? { opacity: 1 } : { scale: 1, opacity: 1 }}\n exit={prefersReduced ? { opacity: 0 } : { scale: 0, opacity: 0 }}\n transition={springs.smooth}\n className={cn(\n 'absolute flex items-center justify-center rounded-pill font-sans font-semibold ring-2 ring-surface-raised',\n COLOR_CLASSES[color],\n PLACEMENT_CLASSES[placement],\n dot\n ? 'h-2.5 w-2.5'\n : 'min-w-[18px] h-[18px] px-1 text-[11px] leading-none',\n )}\n >\n {!dot && displayCount}\n </motion.span>\n )}\n </AnimatePresence>\n </span>\n )\n})\n\nBadgeIndicator.displayName = 'BadgeIndicator'\n"],"mappings":";;;;;;;AAQA,IAAM,IAAoB;CACxB,aAAa;CACb,YAAY;CACZ,gBAAgB;CAChB,eAAe;AACjB,GAEM,IAAgB;CACpB,OAAO;CACP,SAAS;CACT,SAAS;CACT,QAAQ;CACR,MAAM;AACR,GAaa,IAAiB,EAAM,WAClC,SACE,EACE,UACA,SAAM,IACN,SAAM,IACN,WAAQ,SACR,eAAY,IACZ,cAAW,IACX,eAAY,aACZ,cACA,aACA,GAAG,KAEL,GACA;CACA,IAAM,IAAiB,EAAiB,GAClC,IAAO,CAAC,MAAc,KAAQ,MAAU,KAAA,MAAc,IAAQ,KAAK,KACnE,IAAe,MAAU,KAAA,KAAa,IAAQ,IAAM,GAAG,EAAI,KAAK;CAEtE,OACE,kBAAC,QAAD;EAAW;EAAK,WAAW,EAAG,wBAAwB,CAAS;EAAG,GAAI;YAAtE,CACG,GACH,kBAAC,GAAD,EAAA,UACG,KACC,kBAAC,EAAO,MAAR;GAEE,SAAS,IAAiB,EAAE,SAAS,EAAE,IAAI;IAAE,OAAO;IAAG,SAAS;GAAE;GAClE,SAAS,IAAiB,EAAE,SAAS,EAAE,IAAI;IAAE,OAAO;IAAG,SAAS;GAAE;GAClE,MAAM,IAAiB,EAAE,SAAS,EAAE,IAAI;IAAE,OAAO;IAAG,SAAS;GAAE;GAC/D,YAAY,EAAQ;GACpB,WAAW,EACT,6GACA,EAAc,IACd,EAAkB,IAClB,IACI,gBACA,qDACN;aAEC,CAAC,KAAO;EACE,GAfP,WAeO,EAEA,CAAA,CACb;;AAEV,CAAC;AAED,EAAe,cAAc"}
1
+ {"version":3,"file":"badge-indicator.js","names":[],"sources":["../../src/ui/badge-indicator.tsx"],"sourcesContent":["'use client'\n\nimport { AnimatePresence, motion, useReducedMotion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { springs } from './lib/motion'\nimport { cn } from './lib/utils'\n\nconst PLACEMENT_CLASSES = {\n 'top-right': '-top-1 -right-1',\n 'top-left': '-top-1 -left-1',\n 'bottom-right': '-bottom-1 -right-1',\n 'bottom-left': '-bottom-1 -left-1',\n} as const\n\nconst COLOR_CLASSES = {\n error: 'bg-error-9 text-error-fg',\n success: 'bg-success-9 text-success-fg',\n warning: 'bg-warning-9 text-warning-fg',\n accent: 'bg-accent-9 text-accent-fg',\n info: 'bg-info-9 text-info-fg',\n} as const\n\nexport interface BadgeIndicatorProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'color'> {\n count?: number\n max?: number\n dot?: boolean\n color?: keyof typeof COLOR_CLASSES\n invisible?: boolean\n showZero?: boolean\n placement?: keyof typeof PLACEMENT_CLASSES\n children: React.ReactNode\n}\n\nexport const BadgeIndicator = React.forwardRef<HTMLSpanElement, BadgeIndicatorProps>(\n function BadgeIndicator(\n {\n count,\n max = 99,\n dot = false,\n color = 'error',\n invisible = false,\n showZero = false,\n placement = 'top-right',\n className,\n children,\n ...rest\n },\n ref,\n ) {\n const prefersReduced = useReducedMotion()\n const show = !invisible && (dot || (count !== undefined && (count > 0 || showZero)))\n const displayCount = count !== undefined && count > max ? `${max}+` : count\n\n return (\n <span ref={ref} className={cn('relative inline-flex', className)} {...rest}>\n {children}\n <AnimatePresence>\n {show && (\n <motion.span\n key=\"indicator\"\n initial={prefersReduced ? { opacity: 0 } : { scale: 0, opacity: 0 }}\n animate={prefersReduced ? { opacity: 1 } : { scale: 1, opacity: 1 }}\n exit={prefersReduced ? { opacity: 0 } : { scale: 0, opacity: 0 }}\n transition={springs.smooth}\n className={cn(\n 'absolute flex items-center justify-center rounded-pill font-sans font-semibold ring-2 ring-surface-panel',\n COLOR_CLASSES[color],\n PLACEMENT_CLASSES[placement],\n dot\n ? 'h-2.5 w-2.5'\n : 'min-w-[18px] h-[18px] px-1 text-[11px] leading-none',\n )}\n >\n {!dot && displayCount}\n </motion.span>\n )}\n </AnimatePresence>\n </span>\n )\n})\n\nBadgeIndicator.displayName = 'BadgeIndicator'\n"],"mappings":";;;;;;;AAQA,IAAM,IAAoB;CACxB,aAAa;CACb,YAAY;CACZ,gBAAgB;CAChB,eAAe;AACjB,GAEM,IAAgB;CACpB,OAAO;CACP,SAAS;CACT,SAAS;CACT,QAAQ;CACR,MAAM;AACR,GAaa,IAAiB,EAAM,WAClC,SACE,EACE,UACA,SAAM,IACN,SAAM,IACN,WAAQ,SACR,eAAY,IACZ,cAAW,IACX,eAAY,aACZ,cACA,aACA,GAAG,KAEL,GACA;CACA,IAAM,IAAiB,EAAiB,GAClC,IAAO,CAAC,MAAc,KAAQ,MAAU,KAAA,MAAc,IAAQ,KAAK,KACnE,IAAe,MAAU,KAAA,KAAa,IAAQ,IAAM,GAAG,EAAI,KAAK;CAEtE,OACE,kBAAC,QAAD;EAAW;EAAK,WAAW,EAAG,wBAAwB,CAAS;EAAG,GAAI;YAAtE,CACG,GACH,kBAAC,GAAD,EAAA,UACG,KACC,kBAAC,EAAO,MAAR;GAEE,SAAS,IAAiB,EAAE,SAAS,EAAE,IAAI;IAAE,OAAO;IAAG,SAAS;GAAE;GAClE,SAAS,IAAiB,EAAE,SAAS,EAAE,IAAI;IAAE,OAAO;IAAG,SAAS;GAAE;GAClE,MAAM,IAAiB,EAAE,SAAS,EAAE,IAAI;IAAE,OAAO;IAAG,SAAS;GAAE;GAC/D,YAAY,EAAQ;GACpB,WAAW,EACT,4GACA,EAAc,IACd,EAAkB,IAClB,IACI,gBACA,qDACN;aAEC,CAAC,KAAO;EACE,GAfP,WAeO,EAEA,CAAA,CACb;;AAEV,CAAC;AAED,EAAe,cAAc"}