@lerianstudio/sindarian-ui 2.0.0-beta.2 → 2.0.0-beta.21

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 (227) hide show
  1. package/LICENSE +93 -0
  2. package/README.md +52 -1
  3. package/dist/components/breadcrumb/index.d.ts.map +1 -1
  4. package/dist/components/breadcrumb/index.js +25 -1
  5. package/dist/components/card/account-card/index.js +5 -5
  6. package/dist/components/card/basic-card/index.d.ts.map +1 -1
  7. package/dist/components/card/basic-card/index.js +2 -2
  8. package/dist/components/card/entity-card/index.js +1 -1
  9. package/dist/components/dialog/confirmation-dialog/index.d.ts.map +1 -1
  10. package/dist/components/dialog/confirmation-dialog/index.js +4 -1
  11. package/dist/components/entity-box/index.d.ts +18 -2
  12. package/dist/components/entity-box/index.d.ts.map +1 -1
  13. package/dist/components/entity-box/index.js +32 -4
  14. package/dist/components/form/date-picker-field/index.js +1 -1
  15. package/dist/components/form/date-range-field/index.js +1 -1
  16. package/dist/components/form/date-time-picker-field/index.js +1 -1
  17. package/dist/components/form/password-field/index.d.ts +5 -1
  18. package/dist/components/form/password-field/index.d.ts.map +1 -1
  19. package/dist/components/form/password-field/index.js +2 -2
  20. package/dist/components/form/select-field/index.d.ts +15 -1
  21. package/dist/components/form/select-field/index.d.ts.map +1 -1
  22. package/dist/components/form/select-field/index.js +28 -3
  23. package/dist/components/form/switch-field/index.d.ts.map +1 -1
  24. package/dist/components/form/switch-field/index.js +6 -1
  25. package/dist/components/page/index.d.ts +35 -1
  26. package/dist/components/page/index.d.ts.map +1 -1
  27. package/dist/components/page/index.js +6 -2
  28. package/dist/components/page-header/index.js +1 -1
  29. package/dist/components/table/id-table-cell.d.ts +13 -1
  30. package/dist/components/table/id-table-cell.d.ts.map +1 -1
  31. package/dist/components/table/id-table-cell.js +99 -9
  32. package/dist/components/table/index.d.ts +1 -0
  33. package/dist/components/table/index.d.ts.map +1 -1
  34. package/dist/components/table/index.js +1 -0
  35. package/dist/components/table/locked-table-actions.d.ts +24 -0
  36. package/dist/components/table/locked-table-actions.d.ts.map +1 -1
  37. package/dist/components/table/locked-table-actions.js +31 -1
  38. package/dist/components/table/name-table-cell.d.ts +57 -4
  39. package/dist/components/table/name-table-cell.d.ts.map +1 -1
  40. package/dist/components/table/name-table-cell.js +50 -2
  41. package/dist/components/ui/autocomplete/index.d.ts +24 -0
  42. package/dist/components/ui/autocomplete/index.d.ts.map +1 -1
  43. package/dist/components/ui/autocomplete/index.js +24 -0
  44. package/dist/components/ui/badge/index.d.ts +11 -7
  45. package/dist/components/ui/badge/index.d.ts.map +1 -1
  46. package/dist/components/ui/badge/index.js +20 -8
  47. package/dist/components/ui/button/index.d.ts +3 -3
  48. package/dist/components/ui/copy-field/index.d.ts +25 -1
  49. package/dist/components/ui/copy-field/index.d.ts.map +1 -1
  50. package/dist/components/ui/copy-field/index.js +16 -8
  51. package/dist/components/ui/dialog/index.d.ts +1 -1
  52. package/dist/components/ui/dialog/index.d.ts.map +1 -1
  53. package/dist/components/ui/dialog/index.js +2 -2
  54. package/dist/components/ui/file-upload/index.d.ts +159 -0
  55. package/dist/components/ui/file-upload/index.d.ts.map +1 -1
  56. package/dist/components/ui/file-upload/index.js +308 -6
  57. package/dist/components/ui/icon-button/index.d.ts +1 -1
  58. package/dist/components/ui/icon-button/styles.css +42 -0
  59. package/dist/components/ui/input/styles.css +79 -4
  60. package/dist/components/ui/lerian-wordmark/index.d.ts +6 -0
  61. package/dist/components/ui/lerian-wordmark/index.d.ts.map +1 -0
  62. package/dist/components/ui/lerian-wordmark/index.js +7 -0
  63. package/dist/components/ui/otp-input/index.js +1 -1
  64. package/dist/components/ui/radio-group/index.js +1 -1
  65. package/dist/components/ui/select/index.d.ts.map +1 -1
  66. package/dist/components/ui/select/index.js +8 -4
  67. package/dist/components/ui/select/styles.css +1 -1
  68. package/dist/components/ui/sheet/index.d.ts +42 -0
  69. package/dist/components/ui/sheet/index.d.ts.map +1 -1
  70. package/dist/components/ui/sheet/index.js +47 -14
  71. package/dist/components/ui/sidebar/index.d.ts +1 -0
  72. package/dist/components/ui/sidebar/index.d.ts.map +1 -1
  73. package/dist/components/ui/sidebar/index.js +1 -0
  74. package/dist/components/ui/sidebar/sidebar-expand-button.d.ts +1 -1
  75. package/dist/components/ui/sidebar/sidebar-expand-button.d.ts.map +1 -1
  76. package/dist/components/ui/sidebar/sidebar-expand-button.js +15 -1
  77. package/dist/components/ui/sidebar/sidebar-item.d.ts +1 -1
  78. package/dist/components/ui/sidebar/sidebar-item.d.ts.map +1 -1
  79. package/dist/components/ui/sidebar/sidebar-item.js +28 -4
  80. package/dist/components/ui/sidebar/sidebar-provider.d.ts +58 -0
  81. package/dist/components/ui/sidebar/sidebar-provider.d.ts.map +1 -1
  82. package/dist/components/ui/sidebar/sidebar-provider.js +146 -4
  83. package/dist/components/ui/sidebar/sidebar-root.d.ts +38 -1
  84. package/dist/components/ui/sidebar/sidebar-root.d.ts.map +1 -1
  85. package/dist/components/ui/sidebar/sidebar-root.js +111 -5
  86. package/dist/components/ui/sidebar/sidebar-trigger.d.ts +45 -0
  87. package/dist/components/ui/sidebar/sidebar-trigger.d.ts.map +1 -0
  88. package/dist/components/ui/sidebar/sidebar-trigger.js +57 -0
  89. package/dist/components/ui/textarea/index.js +1 -1
  90. package/dist/components/ui/toast/toaster.d.ts +5 -1
  91. package/dist/components/ui/toast/toaster.d.ts.map +1 -1
  92. package/dist/components/ui/toast/toaster.js +3 -2
  93. package/dist/enterprise/data-table/index.d.ts +77 -7
  94. package/dist/enterprise/data-table/index.d.ts.map +1 -1
  95. package/dist/enterprise/data-table/index.js +56 -11
  96. package/dist/enterprise/date-range-picker/index.js +4 -4
  97. package/dist/enterprise/number-input/index.d.ts.map +1 -1
  98. package/dist/enterprise/number-input/index.js +1 -1
  99. package/dist/esm/components/breadcrumb/index.d.ts.map +1 -1
  100. package/dist/esm/components/breadcrumb/index.js +25 -1
  101. package/dist/esm/components/card/account-card/index.js +5 -5
  102. package/dist/esm/components/card/basic-card/index.d.ts.map +1 -1
  103. package/dist/esm/components/card/basic-card/index.js +2 -2
  104. package/dist/esm/components/card/entity-card/index.js +1 -1
  105. package/dist/esm/components/dialog/confirmation-dialog/index.d.ts.map +1 -1
  106. package/dist/esm/components/dialog/confirmation-dialog/index.js +4 -1
  107. package/dist/esm/components/entity-box/index.d.ts +18 -2
  108. package/dist/esm/components/entity-box/index.d.ts.map +1 -1
  109. package/dist/esm/components/entity-box/index.js +29 -4
  110. package/dist/esm/components/form/date-picker-field/index.js +1 -1
  111. package/dist/esm/components/form/date-range-field/index.js +1 -1
  112. package/dist/esm/components/form/date-time-picker-field/index.js +1 -1
  113. package/dist/esm/components/form/password-field/index.d.ts +5 -1
  114. package/dist/esm/components/form/password-field/index.d.ts.map +1 -1
  115. package/dist/esm/components/form/password-field/index.js +2 -2
  116. package/dist/esm/components/form/select-field/index.d.ts +15 -1
  117. package/dist/esm/components/form/select-field/index.d.ts.map +1 -1
  118. package/dist/esm/components/form/select-field/index.js +29 -4
  119. package/dist/esm/components/form/switch-field/index.d.ts.map +1 -1
  120. package/dist/esm/components/form/switch-field/index.js +7 -2
  121. package/dist/esm/components/page/index.d.ts +35 -1
  122. package/dist/esm/components/page/index.d.ts.map +1 -1
  123. package/dist/esm/components/page/index.js +6 -2
  124. package/dist/esm/components/page-header/index.js +1 -1
  125. package/dist/esm/components/table/id-table-cell.d.ts +13 -1
  126. package/dist/esm/components/table/id-table-cell.d.ts.map +1 -1
  127. package/dist/esm/components/table/id-table-cell.js +100 -7
  128. package/dist/esm/components/table/index.d.ts +1 -0
  129. package/dist/esm/components/table/index.d.ts.map +1 -1
  130. package/dist/esm/components/table/index.js +1 -0
  131. package/dist/esm/components/table/locked-table-actions.d.ts +24 -0
  132. package/dist/esm/components/table/locked-table-actions.d.ts.map +1 -1
  133. package/dist/esm/components/table/locked-table-actions.js +31 -1
  134. package/dist/esm/components/table/name-table-cell.d.ts +57 -4
  135. package/dist/esm/components/table/name-table-cell.d.ts.map +1 -1
  136. package/dist/esm/components/table/name-table-cell.js +50 -2
  137. package/dist/esm/components/ui/autocomplete/index.d.ts +24 -0
  138. package/dist/esm/components/ui/autocomplete/index.d.ts.map +1 -1
  139. package/dist/esm/components/ui/autocomplete/index.js +24 -0
  140. package/dist/esm/components/ui/badge/index.d.ts +11 -7
  141. package/dist/esm/components/ui/badge/index.d.ts.map +1 -1
  142. package/dist/esm/components/ui/badge/index.js +20 -8
  143. package/dist/esm/components/ui/button/index.d.ts +3 -3
  144. package/dist/esm/components/ui/copy-field/index.d.ts +25 -1
  145. package/dist/esm/components/ui/copy-field/index.d.ts.map +1 -1
  146. package/dist/esm/components/ui/copy-field/index.js +16 -8
  147. package/dist/esm/components/ui/dialog/index.d.ts +1 -1
  148. package/dist/esm/components/ui/dialog/index.d.ts.map +1 -1
  149. package/dist/esm/components/ui/dialog/index.js +3 -3
  150. package/dist/esm/components/ui/file-upload/index.d.ts +159 -0
  151. package/dist/esm/components/ui/file-upload/index.d.ts.map +1 -1
  152. package/dist/esm/components/ui/file-upload/index.js +307 -5
  153. package/dist/esm/components/ui/icon-button/index.d.ts +1 -1
  154. package/dist/esm/components/ui/lerian-wordmark/index.d.ts +6 -0
  155. package/dist/esm/components/ui/lerian-wordmark/index.d.ts.map +1 -0
  156. package/dist/esm/components/ui/lerian-wordmark/index.js +4 -0
  157. package/dist/esm/components/ui/otp-input/index.js +1 -1
  158. package/dist/esm/components/ui/radio-group/index.js +1 -1
  159. package/dist/esm/components/ui/select/index.d.ts.map +1 -1
  160. package/dist/esm/components/ui/select/index.js +8 -4
  161. package/dist/esm/components/ui/sheet/index.d.ts +42 -0
  162. package/dist/esm/components/ui/sheet/index.d.ts.map +1 -1
  163. package/dist/esm/components/ui/sheet/index.js +48 -15
  164. package/dist/esm/components/ui/sidebar/index.d.ts +1 -0
  165. package/dist/esm/components/ui/sidebar/index.d.ts.map +1 -1
  166. package/dist/esm/components/ui/sidebar/index.js +1 -0
  167. package/dist/esm/components/ui/sidebar/sidebar-expand-button.d.ts +1 -1
  168. package/dist/esm/components/ui/sidebar/sidebar-expand-button.d.ts.map +1 -1
  169. package/dist/esm/components/ui/sidebar/sidebar-expand-button.js +15 -1
  170. package/dist/esm/components/ui/sidebar/sidebar-item.d.ts +1 -1
  171. package/dist/esm/components/ui/sidebar/sidebar-item.d.ts.map +1 -1
  172. package/dist/esm/components/ui/sidebar/sidebar-item.js +28 -4
  173. package/dist/esm/components/ui/sidebar/sidebar-provider.d.ts +58 -0
  174. package/dist/esm/components/ui/sidebar/sidebar-provider.d.ts.map +1 -1
  175. package/dist/esm/components/ui/sidebar/sidebar-provider.js +143 -1
  176. package/dist/esm/components/ui/sidebar/sidebar-root.d.ts +38 -1
  177. package/dist/esm/components/ui/sidebar/sidebar-root.d.ts.map +1 -1
  178. package/dist/esm/components/ui/sidebar/sidebar-root.js +113 -7
  179. package/dist/esm/components/ui/sidebar/sidebar-trigger.d.ts +45 -0
  180. package/dist/esm/components/ui/sidebar/sidebar-trigger.d.ts.map +1 -0
  181. package/dist/esm/components/ui/sidebar/sidebar-trigger.js +53 -0
  182. package/dist/esm/components/ui/textarea/index.js +1 -1
  183. package/dist/esm/components/ui/toast/toaster.d.ts +5 -1
  184. package/dist/esm/components/ui/toast/toaster.d.ts.map +1 -1
  185. package/dist/esm/components/ui/toast/toaster.js +3 -2
  186. package/dist/esm/enterprise/data-table/index.d.ts +77 -7
  187. package/dist/esm/enterprise/data-table/index.d.ts.map +1 -1
  188. package/dist/esm/enterprise/data-table/index.js +57 -12
  189. package/dist/esm/enterprise/date-range-picker/index.js +4 -4
  190. package/dist/esm/enterprise/number-input/index.d.ts.map +1 -1
  191. package/dist/esm/enterprise/number-input/index.js +1 -1
  192. package/dist/esm/hooks/use-toast.d.ts +18 -2
  193. package/dist/esm/hooks/use-toast.d.ts.map +1 -1
  194. package/dist/esm/hooks/use-toast.js +60 -16
  195. package/dist/esm/index.d.ts +3 -0
  196. package/dist/esm/index.d.ts.map +1 -1
  197. package/dist/esm/index.js +3 -0
  198. package/dist/esm/lib/utils.d.ts +2 -0
  199. package/dist/esm/lib/utils.d.ts.map +1 -1
  200. package/dist/esm/lib/utils.js +10 -0
  201. package/dist/esm/toast/helpers.d.ts +13 -0
  202. package/dist/esm/toast/helpers.d.ts.map +1 -1
  203. package/dist/esm/toast/helpers.js +8 -1
  204. package/dist/fonts/OFL.txt +96 -0
  205. package/dist/fonts/ibm-plex-mono-latin-400.woff2 +0 -0
  206. package/dist/fonts/ibm-plex-mono-latin-500.woff2 +0 -0
  207. package/dist/fonts/ibm-plex-serif-latin-400.woff2 +0 -0
  208. package/dist/fonts/ibm-plex-serif-latin-500.woff2 +0 -0
  209. package/dist/fonts/inter-latin.woff2 +0 -0
  210. package/dist/fonts.css +46 -0
  211. package/dist/globals.css +62 -362
  212. package/dist/hooks/use-toast.d.ts +18 -2
  213. package/dist/hooks/use-toast.d.ts.map +1 -1
  214. package/dist/hooks/use-toast.js +61 -16
  215. package/dist/index.d.ts +3 -0
  216. package/dist/index.d.ts.map +1 -1
  217. package/dist/index.js +3 -0
  218. package/dist/lib/utils.d.ts +2 -0
  219. package/dist/lib/utils.d.ts.map +1 -1
  220. package/dist/lib/utils.js +11 -0
  221. package/dist/public/wordmark.svg +1 -0
  222. package/dist/standalone.css +10 -0
  223. package/dist/toast/helpers.d.ts +13 -0
  224. package/dist/toast/helpers.d.ts.map +1 -1
  225. package/dist/toast/helpers.js +8 -1
  226. package/dist/tokens.css +367 -0
  227. package/package.json +9 -6
package/dist/globals.css CHANGED
@@ -10,11 +10,18 @@
10
10
  @import './components/ui/stepper/styles.css';
11
11
  @import './components/ui/tabs/styles.css';
12
12
  @import './components/ui/dialog/styles.css';
13
+ @import './tokens.css';
13
14
  @custom-variant dark (&:is(.dark *));
14
15
 
15
16
  @theme inline {
16
17
  --font-sans:
17
18
  var(--font-inter, 'Inter'), 'Inter', ui-sans-serif, system-ui, sans-serif;
19
+ --font-serif:
20
+ var(--font-plex-serif, ui-serif), ui-serif, Georgia, Cambria,
21
+ 'Times New Roman', Times, serif;
22
+ --font-mono:
23
+ var(--font-plex-mono, ui-monospace), ui-monospace, SFMono-Regular, Menlo,
24
+ Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
18
25
 
19
26
  --shadow-sidebar: 5px 0px 15px -3px hsl(var(--shadow-color) / 0.05);
20
27
  --shadow-data-table:
@@ -210,338 +217,7 @@
210
217
  }
211
218
  }
212
219
 
213
- @layer base {
214
- :root {
215
- color-scheme: light; /* native widgets (form controls, scrollbars) follow the theme */
216
-
217
- /* Application tokens (from Figma ring-tokens) */
218
- --body-surface: 240 5% 96%; /* base/100 = #F4F4F5 */
219
- /*
220
- --body-text and --container-text below both step one notch off base/500.
221
- base/500 clears AA on white (4.86:1) but not on --body-surface, the
222
- recessed page ground, where it read 4.43:1. That ground is exactly where
223
- the components carrying these two tokens sit: the resting tabs trigger
224
- (text-sm font-medium, and its hover fill is --card precisely because the
225
- resting ground is not white), the breadcrumb page and separator, the
226
- stepper item text and description. An axe crawl of the br-sfn cockpit
227
- flagged .text-body-text on 2026-09-06; the ratio it printed does not
228
- reproduce here, and the measured pair on this token's own ground is
229
- 4.40:1 at 8-bit precision (4.43:1 in float).
230
-
231
- 45% is the smallest step that clears it: 4.59:1 on --body-surface, up
232
- from 4.43:1, and 5.04:1 on white. Both stay eleven notches clear of
233
- --container-title (base/600), so the text-versus-title step holds.
234
-
235
- Deliberately not stepped far enough to clear --muted (#E4E4E7), which
236
- would take base/500 minus five notches and visibly darken tabs,
237
- breadcrumbs and steppers. No component in THIS kit paints either token on
238
- that fill. A consumer that does is a call-site fix on its side, not a
239
- clean bill from here: product-console's extract-table pairs bg-muted with
240
- text-body-text and reads 3.98:1 in light.
241
- */
242
- --body-text: 240 4% 45%; /* one notch off base/500: #6E6E77, AA on body-surface */
243
- --body-title: 240 5% 26%; /* base/700 = #3F3F46 */
244
- --container-surface: 0 0% 100%; /* base/white = #FFFFFF */
245
- --container-text: 240 4% 45%; /* one notch off base/500: #6E6E77, AA on body-surface */
246
- --container-title: 240 5% 34%; /* base/600 = #52525B */
247
- --container-border: 0 0% 100%; /* #FFFFFF */
248
- --link: 240 4% 16%; /* base/800 = #27272A */
249
- --link-hover: 240 4% 16%; /* #27272A with 80% opacity via /80 */
250
- --link-mute: 240 4% 16%; /* #27272A with 40% opacity via /40 */
251
- --button-primary-surface: 240 4% 16%; /* base/800 = #27272A */
252
- --button-primary-text: 0 0% 100%; /* base/white */
253
-
254
- /* Shadcn semantic tokens (aligned with Figma) */
255
- --background: 0 0% 100%; /* base/white = #FFFFFF */
256
- --foreground: 240 5% 26%; /* base/700 = #3F3F46 */
257
- --card: 0 0% 100%; /* = container-surface (white) */
258
- /* Held at base/500, the step --container-text just moved off: this token's
259
- own ground is --card (white), where base/500 clears AA at 4.86:1. It
260
- measures 3.84:1 over --muted, but no component in this kit renders it
261
- there: the data table pins its own inks rather than inheriting this one
262
- (`ui/table/index.tsx`: cells take text-foreground, heads take
263
- text-muted-foreground), so the hovered-row ground never sits under this
264
- token. */
265
- --card-foreground: 240 4% 46%; /* base/500 = #71717A */
266
- --popover: 0 0% 100%; /* base/white */
267
- --popover-foreground: 240 5% 34%; /* base/600 = #52525B */
268
- --primary: 240 4% 16%; /* base/800 = #27272A */
269
- --primary-foreground: 0 0% 100%; /* base/white */
270
- --secondary: 0 0% 100%; /* base/white */
271
- --secondary-foreground: 240 5% 34%; /* base/600 = #52525B */
272
- --muted: 240 5% 90%; /* base/200 = #E4E4E7 */
273
- --muted-foreground: 240 5% 34%; /* base/600 = #52525B */
274
- --accent: 56 99% 50%; /* #FEED02 (sunglow) */
275
- --accent-foreground: 240 10% 4%; /* base/800 for contrast on yellow */
276
- /*
277
- Shadcn — Destructive. Darkened one step to red/600. red/500 under white
278
- was 3.78:1, under AA, for both roles this token plays: the fill beneath
279
- `--destructive-foreground` (the Critical badge, every destructive
280
- button) and the plain body ink of a field/form error message on white.
281
- red/600 lifts both to 4.80:1. The hue is unchanged; only the step moved.
282
- */
283
- --destructive: 0 72% 51%; /* red/600 = #DC2626 */
284
- --destructive-foreground: 0 0% 100%; /* white */
285
- --border: 240 5% 90%; /* base/200 = #E4E4E7 */
286
- --input: 0 0% 100%; /* base/white */
287
- /* Lighter than --muted-foreground, which is also the label colour: a
288
- placeholder that matches its own label has no hierarchy left to give.
289
- Stepped off base/500 with --body-text, and for the same reason. The
290
- field paints no fill of its own (`input/styles.css`: .input-wrapper is
291
- border-only, .input-base is bg-transparent), so the hint sits on
292
- whatever ground contains the form, and on --body-surface base/500 read
293
- 4.40:1. 45% brings that to 4.59:1 and 5.04:1 on white. The retired note
294
- here claimed 4.4:1 was acceptable "on the shadcn-100 field", which named
295
- a fill the component never paints. */
296
- --input-placeholder: 240 4% 45%; /* one notch off base/500: #6E6E77, AA on body-surface */
297
- /*
298
- Focus ring. base/400 read 2.55:1 on white and 2.33:1 on --body-surface,
299
- under the 3:1 floor a focus indicator answers to (SC 1.4.11), and this is
300
- the ring every input, button and trigger in the kit paints: the wrapper
301
- border on :focus-within, and the ring itself at ring-offset-0, both of
302
- which touch the page ground directly. base/500 clears it on every light
303
- ground: 4.84:1 on white (which is also --card and --popover here) and
304
- 4.40:1 on --body-surface.
305
-
306
- It does NOT serve both themes. On the dark container surface base/500
307
- measures 2.16:1, so .dark keeps the old channel as its own declaration,
308
- where it reads 5.81:1 on --background and 4.08:1 on --card.
309
-
310
- No single value clears both themes with margin, and none is a palette
311
- step: the best one channel does is an off-scale 240 5% 57%, which clears
312
- 3:1 on all four grounds but by 0.04 on two of them. The per-theme pair
313
- sits at 4.4+ light and 4.0+ dark, each half gated in
314
- `__tests__/tokens-contract.test.ts`.
315
- */
316
- --ring: 240 4% 46%; /* base/500 = #71717A */
317
- --radius: 0.5rem;
318
-
319
- /* Accent variants */
320
- --accent-hover: 56 99% 50%; /* #FEED02 - opacity handled via /70 */
321
- --accent-mute: 56 99% 50%; /* #FEED02 - opacity handled via /50 */
322
-
323
- /* System tokens (light mode — dark overrides in .dark) */
324
- --system-error: 0 84% 60%; /* red/500 = #EF4444 */
325
- --system-error-surface: 0 86% 97%; /* red/50 = #FEF2F2 */
326
- --system-error-h1a: 0 74% 35%; /* red/800 = #991B1B */
327
- --system-error-border: 0 84% 60% / 0.5; /* #EF4444 50% */
328
- --system-error-text: 0 74% 35%; /* #991B1B */
329
- --system-success: 142 76% 36%; /* green/600 = #16A34A */
330
- --system-success-surface: 139 76% 97%; /* green/50 = #F0FDF4 */
331
- --system-success-h1a: 143 64% 24%; /* green/800 = #166534 */
332
- --system-success-border: 142 76% 36% / 0.5; /* #16A34A 50% */
333
- --system-success-text: 143 64% 24%; /* #166534 */
334
- --system-info: 221 83% 53%; /* blue/600 = #2563EB */
335
- --system-info-surface: 214 100% 97%; /* blue/50 = #EFF6FF */
336
- --system-info-h1a: 224 76% 40%; /* blue/800 = #1E40AF */
337
- --system-info-border: 221 83% 53% / 0.5; /* #2563EB 50% */
338
- --system-info-text: 224 76% 40%; /* #1E40AF */
339
- --system-alert: 48 96% 47%; /* yellow/500 = #EAB308 */
340
- --system-alert-surface: 55 92% 95%; /* yellow/50 = #FEFCE8 */
341
- --system-alert-h1a: 36 92% 29%; /* yellow/800 = #854D0E */
342
- --system-alert-border: 48 96% 47% / 0.5; /* #EAB308 50% */
343
- --system-alert-text: 36 92% 29%; /* #854D0E */
344
- --system-purple: 271 81% 56%; /* purple/600 = #9333EA */
345
- --system-purple-surface: 270 100% 98%; /* purple/50 = #FAF5FF */
346
- --system-purple-h1a: 273 67% 39%; /* purple/800 = #6B21A8 */
347
- --system-purple-border: 271 81% 56% / 0.5; /* #9333EA 50% */
348
- --system-purple-text: 273 67% 39%; /* #6B21A8 */
349
-
350
- /* Shadow color token for dark mode adaptation */
351
- --shadow-color: 0 0% 0%;
352
-
353
- /*
354
- Ledger credit semantic — deliberately DISTINCT from --destructive, not an
355
- alias: --destructive is an error/alarm, --credit is the accounting reading
356
- of a credit amount. Deeper than --destructive (red/700 vs red/500) so the
357
- two never read as the same signal. --credit-foreground mirrors --credit:
358
- the red itself carries the role as text.
359
- */
360
- --credit: 0 74% 42%; /* red/700 = #B91C1C */
361
- --credit-foreground: 0 74% 42%; /* mirrors --credit */
362
-
363
- /*
364
- Reconciliation matte fills — the recessed track behind a balance bar, one
365
- neutral step apart. Deliberately hue-neutral: the matched/unmatched signal
366
- is carried by the bar's leading edge, so a tinted wall would double-encode.
367
- */
368
- --matched-surface: 240 5% 96%; /* base/100 = #F4F4F5 */
369
- --unmatched-surface: 240 5% 90%; /* base/200 = #E4E4E7 */
370
-
371
- /*
372
- Chart series palette — 8 categorical slots drawn from the brand scales
373
- (de-york, sunglow, cod-gray) plus the system hues, ordered so no adjacent
374
- pair shares a hue neighbourhood.
375
- */
376
- --chart-1: 143 59% 36%; /* de-york-600 = #26934F */
377
- --chart-2: 0 72% 51%; /* red/600 = #DC2626 */
378
- --chart-3: 39 98% 40%; /* sunglow-600 = #CC8402 */
379
- --chart-4: 221 83% 53%; /* blue/600 = #2563EB */
380
- --chart-5: 333 71% 51%; /* pink/600 = #DB2777 */
381
- --chart-6: 193 82% 31%; /* cyan/700 = #0E7490 */
382
- --chart-7: 272 72% 47%; /* purple/700 = #7E22CE */
383
- --chart-8: 351 9% 43%; /* cod-gray-500 = #776366 */
384
- }
385
-
386
- .dark {
387
- color-scheme: dark; /* native widgets (form controls, scrollbars) follow the theme */
388
-
389
- /* Custom — Layout */
390
- --link-hover: 240 5% 96%; /* #F4F4F5 80% (opacity via /80) */
391
- --link-mute: 240 5% 96%; /* #F4F4F5 40% (opacity via /40) */
392
- --container-surface: 240 5% 26%; /* base/700 = #3F3F46 */
393
- --container-text: 240 5% 96%; /* base/100 = #F4F4F5 */
394
- --container-title: 0 0% 100%; /* base/white */
395
- --body-surface: 240 4% 16%; /* base/800 = #27272A */
396
- --body-text: 240 5% 84%; /* base/300 = #D4D4D8 */
397
- --body-title: 0 0% 100%; /* base/white */
398
- --link: 240 5% 96%; /* base/100 = #F4F4F5 */
399
- --button-primary-surface: 240 5% 96%; /* base/100 = #F4F4F5 */
400
- --button-primary-text: 240 4% 16%; /* base/800 = #27272A */
401
- --container-border: var(--border); /* shadcn/--border */
402
-
403
- /* Shadcn — Core */
404
- --background: 240 4% 16%; /* base/800 = #27272A */
405
- --foreground: 240 5% 96%; /* base/100 = #F4F4F5 */
406
- --muted: 240 5% 34%; /* base/600 = #52525B */
407
- /*
408
- Lifted off the base scale. base/400 read 4.09:1 on --container-surface
409
- (which --card aliases) and 3.01:1 on --muted, both under the 4.5 AA floor
410
- for normal text, and this is the kit's universal secondary ink: every
411
- TableHead column label (text-sm font-medium inside a text-sm Table),
412
- every empty-state line, every form label through LABEL_VOICE_CLASS, every
413
- MoneyText caption. An axe crawl of the br-sfn cockpit measured both pairs
414
- on 2026-09-06; every console on this library inherited them.
415
-
416
- 80% is the smallest round step that clears both: 6.36:1 on
417
- --container-surface and 4.68:1 on --muted. base/300 is the nearest scale
418
- step that would also clear, but it is byte-identical to this theme's
419
- --body-text, so adopting it would collapse the muted-versus-body step the
420
- two tokens exist to express. Staying on the scale is worth less than
421
- keeping that step, so the value leaves the scale instead.
422
-
423
- That step is now thin, and the trade was made with eyes open: 80% sits at
424
- L* 81 against --body-text at L* 85, so the two inks are 1.12:1 apart and
425
- barely separable side by side. Legibility won because the weight is all
426
- on one side: this token has 86 call sites and is read as prose on every
427
- surface, while --body-text has one (an uppercase sidebar group label) plus
428
- two derived theme keys. A reader who needs the step to be visible should
429
- move --body-text, which is cheap to reposition, rather than push this one
430
- back under the AA floor.
431
-
432
- Repairs a fourth pair on the way: the disabled chip in autocomplete and
433
- multiple-select paints text-muted on bg-muted-foreground, 3.01:1 before
434
- and 4.68:1 now.
435
- */
436
- --muted-foreground: 240 5% 80%; /* between base/400 and base/300: #C9C9CF, AA on container-surface and muted */
437
- --card: var(--container-surface);
438
- --card-foreground: var(--container-text);
439
- --popover: 240 4% 16%; /* base/800 = #27272A */
440
- --popover-foreground: 240 5% 96%; /* base/100 = #F4F4F5 */
441
- --border: 240 5% 34%; /* base/600 = #52525B */
442
- --input: 240 4% 16%; /* base/800 = #27272A */
443
- /* Held at base/400 rather than stepped down with the light theme: on the
444
- dark field that is already only 5.8:1, and going lighter here means
445
- darker, which would push the hint under the AA floor. */
446
- --input-placeholder: 240 5% 80%; /* between base/400 and base/300: #C9C9CF, AA on card (6.3:1); base/400 read 4.07:1 there */
447
- /* Held at base/400, which light had to leave: on this ground the two
448
- directions disagree. base/400 reads 5.81:1 on --background and 4.08:1 on
449
- --card here, while light's base/500 would read 2.16:1 on --card. */
450
- --ring: 240 5% 65%; /* base/400 = #A1A1AA */
451
- --primary: 240 5% 96%; /* base/100 = #F4F4F5 */
452
- --primary-foreground: 240 4% 16%; /* base/800 = #27272A */
453
- --secondary: 240 4% 16%; /* base/800 = #27272A */
454
- --secondary-foreground: 240 5% 96%; /* base/100 = #F4F4F5 */
455
-
456
- /* Shadcn — Accent (Brand Lerian) */
457
- --accent: 46 98% 57%; /* sunglow/400 = #FDCB28 */
458
- --accent-hover: 46 98% 57%; /* sunglow/400 = #FDCB28 - opacity via /70 */
459
- --accent-mute: 46 98% 57%; /* sunglow/400 = #FDCB28 - opacity via /50 */
460
-
461
- /*
462
- Shadcn — Destructive. Lifted to red/400 like every other red in this
463
- block (--system-error, --credit, --chart-2): the light red/500 inherited
464
- here before, which left `text-destructive` at 2.76:1 on a --card surface
465
- and `bg-destructive`/`text-destructive-foreground` at 3.78:1. The
466
- foreground inverts to red/950 — the deep end this theme already uses as
467
- --system-error-surface — so the pair reads 5.94:1.
468
- */
469
- --destructive: 0 91% 71%; /* red/400 = #F87171 */
470
- --destructive-foreground: 0 75% 15%; /* red/950 = #450A0A */
471
-
472
- /* Shadcn — System Error */
473
- --system-error: 0 91% 71%; /* red/400 = #F87171 */
474
- --system-error-surface: 0 75% 15%; /* red/950 = #450A0A */
475
- --system-error-text: 0 94% 82%; /* red/300 = #FCA5A5 */
476
- --system-error-h1a: 0 96% 89%; /* red/200 = #FECACA */
477
- --system-error-border: 0 94% 82% / 0.3; /* #FCA5A5 30% */
478
-
479
- /* Shadcn — System Success */
480
- --system-success: 142 69% 58%; /* green/400 = #4ADE80 */
481
- --system-success-surface: 145 80% 10%; /* green/950 = #052E16 */
482
- --system-success-text: 142 77% 73%; /* green/300 = #86EFAC */
483
- --system-success-h1a: 141 79% 85%; /* green/200 = #BBF7D0 */
484
- --system-success-border: 142 69% 58% / 0.3; /* #4ADE80 30% */
485
-
486
- /* Shadcn — System Info */
487
- --system-info: 213 94% 68%; /* blue/400 = #60A5FA */
488
- --system-info-surface: 226 57% 21%; /* blue/950 = #172554 */
489
- --system-info-text: 212 96% 78%; /* blue/300 = #93C5FD */
490
- --system-info-h1a: 213 97% 87%; /* blue/200 = #BFDBFE */
491
- --system-info-border: 213 94% 68% / 0.3; /* #60A5FA 30% */
492
-
493
- /* Shadcn — System Alert */
494
- --system-alert: 48 96% 53%; /* yellow/400 = #FACC15 */
495
- --system-alert-surface: 26 83% 14%; /* yellow/950 = #422006 */
496
- --system-alert-text: 48 97% 77%; /* yellow/300 = #FDE68A */
497
- --system-alert-h1a: 53 98% 77%; /* yellow/200 = #FEF08A */
498
- --system-alert-border: 48 96% 53% / 0.3; /* #FACC15 30% */
499
-
500
- /* Shadcn — System Purple */
501
- --system-purple: 270 95% 75%; /* purple/400 = #C084FC */
502
- --system-purple-surface: 266 86% 13%; /* purple/950 = #3B0764 */
503
- --system-purple-text: 269 97% 85%; /* purple/300 = #D8B4FE */
504
- --system-purple-h1a: 269 100% 92%; /* purple/200 = #E9D5FF */
505
- --system-purple-border: 270 95% 75% / 0.3; /* #C084FC 30% */
506
-
507
- /* Shadow color for dark mode */
508
- --shadow-color: 0 0% 100%;
509
-
510
- /*
511
- Ledger credit semantic — lifted for the dark canvas; foreground mirrors.
512
- Sized by the composite the mirror actually produces, not by the plain
513
- pair: components write `bg-credit/10` + `text-credit`, so the real
514
- measurement is credit-as-text over a 10% credit tint composited on
515
- --card. red/400 read only 3.34:1 there. red/300 — the channel this block
516
- already uses for --system-error-text — reaches 4.59:1, and 5.54:1 as
517
- plain text on --card.
518
-
519
- Credit stays one step further from the canvas than --destructive
520
- (red/400 here), the way light keeps credit at red/700 against a red/500
521
- destructive: on a dark ground "further from the canvas" means lighter,
522
- so the direction inverts but the separation holds and the two never read
523
- as the same signal.
524
- */
525
- --credit: 0 94% 82%; /* red/300 = #FCA5A5 */
526
- --credit-foreground: 0 94% 82%; /* mirrors --credit */
527
-
528
- /* Reconciliation matte fills — raised surfaces over base/800, one step apart. */
529
- --matched-surface: 240 5% 26%; /* base/700 = #3F3F46 */
530
- --unmatched-surface: 240 5% 34%; /* base/600 = #52525B */
531
-
532
- /* Chart series palette — same families, lifted for the dark canvas. */
533
- --chart-1: 143 53% 58%; /* de-york-400 = #5BCD86 */
534
- --chart-2: 0 91% 71%; /* red/400 = #F87171 */
535
- --chart-3: 46 98% 57%; /* sunglow-400 = #FDCB28 */
536
- --chart-4: 213 94% 68%; /* blue/400 = #60A5FA */
537
- --chart-5: 329 86% 70%; /* pink/400 = #F472B6 */
538
- --chart-6: 188 86% 53%; /* cyan/400 = #22D3EE */
539
- --chart-7: 270 95% 75%; /* purple/400 = #C084FC */
540
- --chart-8: 351 9% 69%; /* cod-gray-300 = #B7A9AB */
541
- }
542
- }
543
-
544
- /* Sonner toast overrides — solid bold backgrounds (Radix parity) */
220
+ /* Sonner toast overrides — tinted surfaces from the system token families */
545
221
  [data-sonner-toaster] {
546
222
  --width: 420px;
547
223
  pointer-events: auto !important;
@@ -559,41 +235,41 @@
559
235
  }
560
236
 
561
237
  /*
562
- Type fills come from the system token families, so a toast themes with the
563
- rest of the app. All three coloured types take ONE ink, --accent-foreground:
564
- a solid system fill is bright enough to need near-black ink in BOTH themes,
565
- and that token is the only one in this sheet that is near-black in both.
566
-
567
- It replaced the per-family reasoning that stood here, which routed success
568
- and error through --primary-foreground because that token inverts (white in
569
- light, base/800 in dark). Inverting was the bug: white ink on the LIGHT
570
- fills measured 3.35:1 on --system-success and 3.78:1 on --system-error,
571
- both under AA, and no token value can fix that from the white side — the
572
- light green/600 and red/500 fills sit mid-luminance, so white caps at ~3.8
573
- while near-black reaches 5.9 and 5.3. Ratios now, ink over fill:
574
- light 5.93 / 5.25 / 11.17 and dark 11.39 / 7.23 / 13.00
575
- (success / error / warning). The dark pairs were already passing at
576
- 8.51 / 5.41 / 13.00 and only gained. `toast ink` in
577
- src/__tests__/tokens-contract.test.ts recomputes all six from these
578
- declarations, so the next token edit that drops a pair under 4.5 fails
579
- instead of shipping.
238
+ Each coloured type paints the `surface` + `text` + `border` trio of its own
239
+ family — the pairing every other tinted component in the kit already uses
240
+ (`components/ui/badge/index.tsx`, `enterprise/alert-banner/index.tsx`).
241
+ `surface` is the only slot in a system family built to sit BEHIND content: it
242
+ darkens on the dark canvas, while `base` and `h1a` are fill and ink slots
243
+ that INVERT between themes (`--system-success-h1a` is #166534 in light and
244
+ #BBF7D0 in dark). Grounding toast text on either of those forces a different
245
+ ink per theme, and the toast stops tracking the family it names.
246
+
247
+ Ink over ground, light / dark: success 6.81 / 10.62, error 7.60 / 8.51,
248
+ warning 6.62 / 11.70 — every half clear of the 4.5 floor by more than two
249
+ points. `system text tokens` in `src/__tests__/tokens-contract.test.ts`
250
+ already measures this pair for all five families, so the toast is covered by
251
+ the gate that guards the pills rather than by a rule written for it alone;
252
+ `sonner toast ink` there reads whichever pair these rules declare.
253
+
254
+ `info` stays neutral on `--card`: an informational toast is the unstyled
255
+ case, not a fourth colour.
580
256
  */
581
257
  [data-sonner-toast][data-type='success'] {
582
- --normal-bg: hsl(var(--system-success));
583
- --normal-text: hsl(var(--accent-foreground));
584
- --normal-border: transparent;
258
+ --normal-bg: hsl(var(--system-success-surface));
259
+ --normal-text: hsl(var(--system-success-text));
260
+ --normal-border: hsl(var(--system-success-border));
585
261
  }
586
262
 
587
263
  [data-sonner-toast][data-type='error'] {
588
- --normal-bg: hsl(var(--system-error));
589
- --normal-text: hsl(var(--accent-foreground));
590
- --normal-border: transparent;
264
+ --normal-bg: hsl(var(--system-error-surface));
265
+ --normal-text: hsl(var(--system-error-text));
266
+ --normal-border: hsl(var(--system-error-border));
591
267
  }
592
268
 
593
269
  [data-sonner-toast][data-type='warning'] {
594
- --normal-bg: hsl(var(--system-alert));
595
- --normal-text: hsl(var(--accent-foreground));
596
- --normal-border: transparent;
270
+ --normal-bg: hsl(var(--system-alert-surface));
271
+ --normal-text: hsl(var(--system-alert-text));
272
+ --normal-border: hsl(var(--system-alert-border));
597
273
  }
598
274
 
599
275
  [data-sonner-toast][data-type='info'] {
@@ -602,8 +278,32 @@
602
278
  --normal-border: hsl(var(--border));
603
279
  }
604
280
 
605
- [data-sonner-toast] [data-title] {
606
- font-weight: 600;
281
+ /*
282
+ The title outranks the description, and both rules have to WIN the cascade
283
+ for that to mean anything. Sonner ships
284
+ `[data-sonner-toast][data-styled='true'] [data-title]` at font-weight 500 and
285
+ its description twin at 400 — both (0,3,0), both injected at runtime.
286
+ The title rule here was a plain `[data-sonner-toast] [data-title]` (0,2,0):
287
+ it declared 600 and rendered at 500, losing outright, while the description
288
+ carried `!important` and rendered at 600. The hierarchy came out inverted on
289
+ every toast in the kit, the long line heavier than the label naming it.
290
+
291
+ Both now take the compound selector plus !important — the shape the
292
+ close-button rules below already use against this same stylesheet, and for
293
+ the same reason: source order cannot settle a tie with a sheet that is
294
+ injected at runtime.
295
+
296
+ The description returns to 400. It is the running text of a toast, and 14px
297
+ semibold across a full sentence reads as emphasis with nothing left to
298
+ emphasise; the family ink already carries the severity. Its `color` override
299
+ keeps !important on its own merits — sonner hardcodes #3f3f3f there, plus a
300
+ dark-theme rule of its own on top.
301
+
302
+ `toast text weights` in src/__tests__/tokens-contract.test.ts holds the order
303
+ and the two properties that let it apply.
304
+ */
305
+ [data-sonner-toast][data-styled='true'] [data-title] {
306
+ font-weight: 600 !important;
607
307
  font-size: 0.875rem;
608
308
  line-height: 1.25rem;
609
309
  }
@@ -611,7 +311,7 @@
611
311
  [data-sonner-toast] [data-description],
612
312
  [data-sonner-toast][data-styled='true'] [data-description] {
613
313
  font-size: 0.875rem;
614
- font-weight: 600 !important;
314
+ font-weight: 400 !important;
615
315
  line-height: 1.25rem;
616
316
  color: var(--normal-text) !important;
617
317
  }
@@ -1,4 +1,10 @@
1
1
  import type { ToastActionElement } from '../components/ui/toast';
2
+ /**
3
+ * Lifetime of every non-destructive toast, and the `<Toaster />` fallback for
4
+ * anything raised without one. The two must not drift apart, so the Toaster
5
+ * imports this rather than repeating the literal.
6
+ */
7
+ export declare const DEFAULT_DURATION = 10000;
2
8
  type ToastVariant = 'default' | 'success' | 'warning' | 'destructive';
3
9
  type ToasterToast = {
4
10
  id: string | number;
@@ -6,9 +12,19 @@ type ToasterToast = {
6
12
  description?: React.ReactNode;
7
13
  variant?: ToastVariant;
8
14
  action?: ToastActionElement;
15
+ /**
16
+ * Auto-dismiss delay in ms, which must be greater than 0: sonner resolves it
17
+ * as `toast.duration || toasterDuration || default`, so `0` reads as unset
18
+ * and the toast silently takes the `<Toaster />` default instead of closing
19
+ * at once. Omit it to take the variant's own lifetime: `destructive` stays
20
+ * until dismissed, every other variant closes after 10s.
21
+ */
22
+ duration?: number;
23
+ };
24
+ type Toast = Omit<ToasterToast, 'id'> & {
25
+ id?: ToasterToast['id'];
9
26
  };
10
- type Toast = Omit<ToasterToast, 'id'>;
11
- declare function toast({ title, description, variant, ...rest }: Toast): {
27
+ declare function toast({ title, description, variant, duration, id, ...rest }: Toast): {
12
28
  id: string | number;
13
29
  dismiss: () => string | number;
14
30
  update: (props: Partial<ToasterToast>) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"use-toast.d.ts","sourceRoot":"","sources":["../../src/hooks/use-toast.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAI/D,KAAK,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAA;AAErE,KAAK,YAAY,GAAG;IAClB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC7B,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,MAAM,CAAC,EAAE,kBAAkB,CAAA;CAC5B,CAAA;AAED,KAAK,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;AAErC,iBAAS,KAAK,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK;;;oBA+B1C,OAAO,CAAC,YAAY,CAAC;EAQxC;AAED;;;;;;;GAOG;AACH,iBAAS,QAAQ;;wBAGO,MAAM,GAAG,MAAM;YAOrB,YAAY,EAAE;EAE/B;AAED,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAA;AAC1B,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,CAAA"}
1
+ {"version":3,"file":"use-toast.d.ts","sourceRoot":"","sources":["../../src/hooks/use-toast.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAE/D;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,QAAQ,CAAA;AAerC,KAAK,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAA;AAErE,KAAK,YAAY,GAAG;IAClB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC7B,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,KAAK,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,YAAY,CAAC,IAAI,CAAC,CAAA;CAAE,CAAA;AAiCnE,iBAAS,KAAK,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK;;;oBAsCxD,OAAO,CAAC,YAAY,CAAC;EASxC;AAED;;;;;;;GAOG;AACH,iBAAS,QAAQ;;wBAGO,MAAM,GAAG,MAAM;YAOrB,YAAY,EAAE;EAE/B;AAED,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAA;AAC1B,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,CAAA"}
@@ -1,43 +1,88 @@
1
1
  'use client';
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.DEFAULT_DURATION = void 0;
4
5
  exports.useToast = useToast;
5
6
  exports.toast = toast;
6
7
  const sonner_1 = require("sonner");
7
- const DEFAULT_DURATION = 10000;
8
- function toast({ title, description, variant, ...rest }) {
8
+ /**
9
+ * Lifetime of every non-destructive toast, and the `<Toaster />` fallback for
10
+ * anything raised without one. The two must not drift apart, so the Toaster
11
+ * imports this rather than repeating the literal.
12
+ */
13
+ exports.DEFAULT_DURATION = 10000;
14
+ /**
15
+ * A destructive toast reports something the operator has to read -- a refused
16
+ * money operation, a failed copy of a show-once secret, a language switch that
17
+ * did not take. It stays up until dismissed instead of auto-closing.
18
+ *
19
+ * `Infinity` is how sonner disables the auto-close timer (it short-circuits the
20
+ * timer effect rather than calling `setTimeout(fn, Infinity)`, which would fire
21
+ * immediately). `<Toaster />` already passes `closeButton`, and sonner gates the
22
+ * close button on that flag alone, never on the duration -- so a persistent
23
+ * toast still renders its dismiss affordance.
24
+ */
25
+ const PERSIST_UNTIL_DISMISSED = Infinity;
26
+ const isPlainText = (value) => value === undefined || typeof value === 'string';
27
+ /**
28
+ * Two identical errors share one toast instead of stacking: same variant, same
29
+ * text -- same id, and sonner updates the one already on screen.
30
+ *
31
+ * Unbounded stacking is worse for a persistent toast than for a transient one.
32
+ * `<Toaster />` shows three at a time and renders the rest `opacity: 0;
33
+ * pointer-events: none`, so a fourth error nobody can read is also a fourth
34
+ * error nobody can close -- and without an auto-dismiss, nothing ahead of it
35
+ * clears on its own.
36
+ *
37
+ * Only plain-text toasts collapse. A `ReactNode` has no stable key and
38
+ * `String(node)` would fold unrelated errors onto one id.
39
+ *
40
+ * ponytail: the ceiling is still three. Distinct persistent errors past the
41
+ * third queue behind the front three until one is dismissed; lifting that means
42
+ * raising `visibleToasts`, not more work here.
43
+ */
44
+ function collapseKey(title, description) {
45
+ if (!isPlainText(title) || !isPlainText(description)) {
46
+ return undefined;
47
+ }
48
+ return `destructive:${JSON.stringify([title ?? null, description ?? null])}`;
49
+ }
50
+ function toast({ title, description, variant, duration, id, ...rest }) {
9
51
  const message = title ?? '';
52
+ const toastId = variant === 'destructive' && id === undefined
53
+ ? collapseKey(title, description)
54
+ : id;
10
55
  const options = {
11
56
  description,
12
- ...rest
57
+ ...rest,
58
+ ...(toastId !== undefined && { id: toastId }),
59
+ duration: duration ??
60
+ (variant === 'destructive' ? PERSIST_UNTIL_DISMISSED : exports.DEFAULT_DURATION)
13
61
  };
14
- let id;
62
+ let raisedId;
15
63
  switch (variant) {
16
64
  case 'success':
17
- options.duration = DEFAULT_DURATION;
18
- id = sonner_1.toast.success(message, options);
65
+ raisedId = sonner_1.toast.success(message, options);
19
66
  break;
20
67
  case 'warning':
21
- options.duration = DEFAULT_DURATION;
22
- id = sonner_1.toast.warning(message, options);
68
+ raisedId = sonner_1.toast.warning(message, options);
23
69
  break;
24
70
  case 'destructive':
25
- options.duration = DEFAULT_DURATION;
26
- id = sonner_1.toast.error(message, options);
71
+ raisedId = sonner_1.toast.error(message, options);
27
72
  break;
28
73
  default:
29
- options.duration = DEFAULT_DURATION;
30
- id = (0, sonner_1.toast)(message, options);
74
+ raisedId = (0, sonner_1.toast)(message, options);
31
75
  break;
32
76
  }
33
77
  return {
34
- id,
35
- dismiss: () => sonner_1.toast.dismiss(id),
78
+ id: raisedId,
79
+ dismiss: () => sonner_1.toast.dismiss(raisedId),
36
80
  update: (props) => {
37
81
  (0, sonner_1.toast)(props.title ?? message, {
38
- id,
82
+ ...rest,
83
+ id: raisedId,
39
84
  description: props.description ?? description,
40
- ...rest
85
+ duration: props.duration ?? options.duration
41
86
  });
42
87
  }
43
88
  };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './components/ui/alert';
2
2
  export * from './components/ui/autocomplete';
3
+ export * from './hooks/use-click-away';
3
4
  export * from './components/ui/autosize-textarea';
4
5
  export * from './components/ui/avatar';
5
6
  export * from './components/ui/badge';
@@ -17,6 +18,7 @@ export * from './components/ui/dropdown-menu';
17
18
  export * from './components/ui/input';
18
19
  export * from './components/ui/otp-input';
19
20
  export * from './components/ui/label';
21
+ export * from './components/ui/lerian-wordmark';
20
22
  export * from './components/ui/loading-button';
21
23
  export * from './components/ui/multiple-select';
22
24
  export * from './components/ui/paper';
@@ -39,6 +41,7 @@ export * from './components/ui/toast';
39
41
  export * from './components/ui/toast/toaster';
40
42
  export * from './hooks/use-toast';
41
43
  export * from './components/ui/time-picker';
44
+ export * from './hooks/use-time';
42
45
  export * from './components/ui/tooltip';
43
46
  export * from './components/ui/form';
44
47
  export { Breadcrumb as ApplicationBreadcrumb } from './components/breadcrumb';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAGA,cAAc,uBAAuB,CAAA;AACrC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,mCAAmC,CAAA;AACjD,cAAc,wBAAwB,CAAA;AACtC,cAAc,uBAAuB,CAAA;AACrC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,wBAAwB,CAAA;AACtC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,yBAAyB,CAAA;AACvC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,wBAAwB,CAAA;AACtC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,uBAAuB,CAAA;AACrC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,uBAAuB,CAAA;AACrC,cAAc,mCAAmC,CAAA;AACjD,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,yBAAyB,CAAA;AACvC,cAAc,wBAAwB,CAAA;AACtC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,yBAAyB,CAAA;AACvC,cAAc,qBAAqB,CAAA;AACnC,cAAc,wBAAwB,CAAA;AACtC,cAAc,uBAAuB,CAAA;AACrC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,mBAAmB,CAAA;AACjC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,yBAAyB,CAAA;AACvC,cAAc,sBAAsB,CAAA;AAGpC,OAAO,EAAE,UAAU,IAAI,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAC7E,cAAc,8CAA8C,CAAA;AAC5D,cAAc,mBAAmB,CAAA;AACjC,cAAc,qBAAqB,CAAA;AACnC,cAAc,yBAAyB,CAAA;AACvC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,0BAA0B,CAAA;AACxC,cAAc,yBAAyB,CAAA;AACvC,cAAc,oBAAoB,CAAA;AAGlC,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA;AACvB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AAGxB,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,8BAA8B,CAAA;AAG5C,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAChC,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAGA,cAAc,uBAAuB,CAAA;AACrC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,wBAAwB,CAAA;AACtC,cAAc,mCAAmC,CAAA;AACjD,cAAc,wBAAwB,CAAA;AACtC,cAAc,uBAAuB,CAAA;AACrC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,wBAAwB,CAAA;AACtC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,yBAAyB,CAAA;AACvC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,wBAAwB,CAAA;AACtC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,uBAAuB,CAAA;AACrC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,uBAAuB,CAAA;AACrC,cAAc,mCAAmC,CAAA;AACjD,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,yBAAyB,CAAA;AACvC,cAAc,wBAAwB,CAAA;AACtC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,yBAAyB,CAAA;AACvC,cAAc,qBAAqB,CAAA;AACnC,cAAc,wBAAwB,CAAA;AACtC,cAAc,uBAAuB,CAAA;AACrC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,mBAAmB,CAAA;AACjC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,kBAAkB,CAAA;AAChC,cAAc,yBAAyB,CAAA;AACvC,cAAc,sBAAsB,CAAA;AAGpC,OAAO,EAAE,UAAU,IAAI,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAC7E,cAAc,8CAA8C,CAAA;AAC5D,cAAc,mBAAmB,CAAA;AACjC,cAAc,qBAAqB,CAAA;AACnC,cAAc,yBAAyB,CAAA;AACvC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,0BAA0B,CAAA;AACxC,cAAc,yBAAyB,CAAA;AACvC,cAAc,oBAAoB,CAAA;AAGlC,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA;AACvB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AAGxB,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,8BAA8B,CAAA;AAG5C,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAChC,cAAc,kBAAkB,CAAA"}