@astra-kit/ui 0.0.0-stage → 0.0.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 (304) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +384 -2
  4. package/THIRD_PARTY_NOTICES.md +31 -0
  5. package/assets/fonts/geist-LICENSE.txt +93 -0
  6. package/assets/fonts/geist-latin-variable.woff2 +0 -0
  7. package/assets/fonts/ibm-plex-mono-latin-400.woff2 +0 -0
  8. package/assets/fonts/ibm-plex-mono-latin-500.woff2 +0 -0
  9. package/assets/fonts/ibmplexmono-LICENSE.txt +93 -0
  10. package/assets/fonts/inter-LICENSE.txt +93 -0
  11. package/assets/fonts/inter-latin-variable.woff2 +0 -0
  12. package/dist/adapters/unpic-image.d.ts +3 -0
  13. package/dist/adapters/unpic-image.js +98 -0
  14. package/dist/components/account-menu.d.ts +67 -0
  15. package/dist/components/account-menu.js +440 -0
  16. package/dist/components/action-button.d.ts +25 -0
  17. package/dist/components/action-button.js +264 -0
  18. package/dist/components/alert.d.ts +31 -0
  19. package/dist/components/alert.js +503 -0
  20. package/dist/components/animated-collapse.d.ts +19 -0
  21. package/dist/components/animated-collapse.js +170 -0
  22. package/dist/components/animated-count.d.ts +13 -0
  23. package/dist/components/animated-count.js +105 -0
  24. package/dist/components/animated-list-item.d.ts +25 -0
  25. package/dist/components/animated-list-item.js +134 -0
  26. package/dist/components/animated-theme-toggler.d.ts +12 -0
  27. package/dist/components/animated-theme-toggler.js +200 -0
  28. package/dist/components/avatar.d.ts +65 -0
  29. package/dist/components/avatar.js +463 -0
  30. package/dist/components/badge.d.ts +21 -0
  31. package/dist/components/badge.js +297 -0
  32. package/dist/components/button-interaction.d.ts +23 -0
  33. package/dist/components/button-interaction.js +22 -0
  34. package/dist/components/button-label.d.ts +8 -0
  35. package/dist/components/button-label.js +203 -0
  36. package/dist/components/button.d.ts +23 -0
  37. package/dist/components/button.js +145 -0
  38. package/dist/components/calendar.d.ts +47 -0
  39. package/dist/components/calendar.js +155 -0
  40. package/dist/components/card.d.ts +38 -0
  41. package/dist/components/card.js +904 -0
  42. package/dist/components/carousel.d.ts +71 -0
  43. package/dist/components/carousel.js +585 -0
  44. package/dist/components/checkbox.d.ts +15 -0
  45. package/dist/components/checkbox.js +324 -0
  46. package/dist/components/control-button.d.ts +16 -0
  47. package/dist/components/control-button.js +215 -0
  48. package/dist/components/data-table.d.ts +118 -0
  49. package/dist/components/data-table.js +895 -0
  50. package/dist/components/dialog-surface.d.ts +49 -0
  51. package/dist/components/dialog-surface.js +220 -0
  52. package/dist/components/dialog.d.ts +92 -0
  53. package/dist/components/dialog.js +320 -0
  54. package/dist/components/dropdown-menu.d.ts +57 -0
  55. package/dist/components/dropdown-menu.js +107 -0
  56. package/dist/components/field.d.ts +53 -0
  57. package/dist/components/field.js +710 -0
  58. package/dist/components/file-upload.d.ts +88 -0
  59. package/dist/components/file-upload.js +776 -0
  60. package/dist/components/filter-presets-bar.d.ts +73 -0
  61. package/dist/components/filter-presets-bar.js +510 -0
  62. package/dist/components/filter-query-bar.d.ts +21 -0
  63. package/dist/components/filter-query-bar.js +881 -0
  64. package/dist/components/filter-query-grammar.d.ts +188 -0
  65. package/dist/components/filter-query-grammar.js +875 -0
  66. package/dist/components/form.d.ts +29 -0
  67. package/dist/components/form.js +330 -0
  68. package/dist/components/highlighter.d.ts +15 -0
  69. package/dist/components/highlighter.js +152 -0
  70. package/dist/components/hover-card.d.ts +50 -0
  71. package/dist/components/hover-card.js +80 -0
  72. package/dist/components/input-group.d.ts +16 -0
  73. package/dist/components/input-group.js +277 -0
  74. package/dist/components/input.d.ts +17 -0
  75. package/dist/components/input.js +120 -0
  76. package/dist/components/label.d.ts +4 -0
  77. package/dist/components/label.js +43 -0
  78. package/dist/components/link.d.ts +9 -0
  79. package/dist/components/link.js +43 -0
  80. package/dist/components/morph-text.d.ts +14 -0
  81. package/dist/components/morph-text.js +210 -0
  82. package/dist/components/pagination.d.ts +59 -0
  83. package/dist/components/pagination.js +190 -0
  84. package/dist/components/popover.d.ts +17 -0
  85. package/dist/components/popover.js +40 -0
  86. package/dist/components/presence-swap.d.ts +22 -0
  87. package/dist/components/presence-swap.js +209 -0
  88. package/dist/components/primitives/alert-dialog.d.ts +68 -0
  89. package/dist/components/primitives/alert-dialog.js +629 -0
  90. package/dist/components/primitives/avatar.d.ts +46 -0
  91. package/dist/components/primitives/avatar.js +265 -0
  92. package/dist/components/primitives/calendar.d.ts +37 -0
  93. package/dist/components/primitives/calendar.js +1250 -0
  94. package/dist/components/primitives/carousel.d.ts +106 -0
  95. package/dist/components/primitives/carousel.js +928 -0
  96. package/dist/components/primitives/dialog.d.ts +62 -0
  97. package/dist/components/primitives/dialog.js +490 -0
  98. package/dist/components/primitives/dropdown-menu-items.d.ts +59 -0
  99. package/dist/components/primitives/dropdown-menu-items.js +265 -0
  100. package/dist/components/primitives/dropdown-menu.d.ts +64 -0
  101. package/dist/components/primitives/dropdown-menu.js +560 -0
  102. package/dist/components/primitives/hover-card.d.ts +50 -0
  103. package/dist/components/primitives/hover-card.js +507 -0
  104. package/dist/components/primitives/pagination.d.ts +65 -0
  105. package/dist/components/primitives/pagination.js +373 -0
  106. package/dist/components/primitives/popover.d.ts +22 -0
  107. package/dist/components/primitives/popover.js +213 -0
  108. package/dist/components/primitives/select.d.ts +37 -0
  109. package/dist/components/primitives/select.js +428 -0
  110. package/dist/components/primitives/tooltip.d.ts +30 -0
  111. package/dist/components/primitives/tooltip.js +277 -0
  112. package/dist/components/progress-ring.d.ts +20 -0
  113. package/dist/components/progress-ring.js +53 -0
  114. package/dist/components/radio-group.d.ts +34 -0
  115. package/dist/components/radio-group.js +392 -0
  116. package/dist/components/reaction-button.d.ts +30 -0
  117. package/dist/components/reaction-button.js +189 -0
  118. package/dist/components/rich-link-editor.d.ts +25 -0
  119. package/dist/components/rich-link-editor.js +320 -0
  120. package/dist/components/rich-markdown-content.d.ts +10 -0
  121. package/dist/components/rich-markdown-content.js +56 -0
  122. package/dist/components/rich-text-content.d.ts +19 -0
  123. package/dist/components/rich-text-content.js +26 -0
  124. package/dist/components/select.d.ts +55 -0
  125. package/dist/components/select.js +188 -0
  126. package/dist/components/separator.d.ts +3 -0
  127. package/dist/components/separator.js +48 -0
  128. package/dist/components/sheet.d.ts +19 -0
  129. package/dist/components/sheet.js +420 -0
  130. package/dist/components/sidebar-panel-context.d.ts +17 -0
  131. package/dist/components/sidebar-panel-context.js +14 -0
  132. package/dist/components/sidebar.d.ts +195 -0
  133. package/dist/components/sidebar.js +2041 -0
  134. package/dist/components/skeleton.d.ts +23 -0
  135. package/dist/components/skeleton.js +334 -0
  136. package/dist/components/split-button.d.ts +36 -0
  137. package/dist/components/split-button.js +306 -0
  138. package/dist/components/svgs/whatsappIcon.d.ts +3 -0
  139. package/dist/components/svgs/whatsappIcon.js +14 -0
  140. package/dist/components/switch.d.ts +13 -0
  141. package/dist/components/switch.js +444 -0
  142. package/dist/components/table.d.ts +10 -0
  143. package/dist/components/table.js +298 -0
  144. package/dist/components/tabs.d.ts +36 -0
  145. package/dist/components/tabs.js +636 -0
  146. package/dist/components/textarea.d.ts +16 -0
  147. package/dist/components/textarea.js +111 -0
  148. package/dist/components/themed-toaster.d.ts +7 -0
  149. package/dist/components/themed-toaster.js +86 -0
  150. package/dist/components/toaster.d.ts +12 -0
  151. package/dist/components/toaster.js +62 -0
  152. package/dist/components/tooltip.d.ts +43 -0
  153. package/dist/components/tooltip.js +65 -0
  154. package/dist/components/typing-animation.d.ts +34 -0
  155. package/dist/components/typing-animation.js +389 -0
  156. package/dist/constants/action-button.d.ts +20 -0
  157. package/dist/constants/action-button.js +17 -0
  158. package/dist/constants/alert.d.ts +16 -0
  159. package/dist/constants/alert.js +13 -0
  160. package/dist/constants/avatar.d.ts +38 -0
  161. package/dist/constants/avatar.js +32 -0
  162. package/dist/constants/badge.d.ts +6 -0
  163. package/dist/constants/badge.js +6 -0
  164. package/dist/constants/button.d.ts +16 -0
  165. package/dist/constants/button.js +16 -0
  166. package/dist/constants/calendar.d.ts +36 -0
  167. package/dist/constants/calendar.js +34 -0
  168. package/dist/constants/card.d.ts +23 -0
  169. package/dist/constants/card.js +20 -0
  170. package/dist/constants/carousel.d.ts +55 -0
  171. package/dist/constants/carousel.js +74 -0
  172. package/dist/constants/checkbox.d.ts +17 -0
  173. package/dist/constants/checkbox.js +17 -0
  174. package/dist/constants/dialog.d.ts +11 -0
  175. package/dist/constants/dialog.js +10 -0
  176. package/dist/constants/dropdown-menu.d.ts +10 -0
  177. package/dist/constants/dropdown-menu.js +37 -0
  178. package/dist/constants/field.d.ts +24 -0
  179. package/dist/constants/field.js +24 -0
  180. package/dist/constants/hover-card.d.ts +37 -0
  181. package/dist/constants/hover-card.js +85 -0
  182. package/dist/constants/morph-text.d.ts +13 -0
  183. package/dist/constants/morph-text.js +13 -0
  184. package/dist/constants/motion.d.ts +12 -0
  185. package/dist/constants/motion.js +12 -0
  186. package/dist/constants/pagination.d.ts +20 -0
  187. package/dist/constants/pagination.js +20 -0
  188. package/dist/constants/popover.d.ts +7 -0
  189. package/dist/constants/popover.js +33 -0
  190. package/dist/constants/radio-group.d.ts +10 -0
  191. package/dist/constants/radio-group.js +10 -0
  192. package/dist/constants/select.d.ts +7 -0
  193. package/dist/constants/select.js +34 -0
  194. package/dist/constants/sidebar.d.ts +9 -0
  195. package/dist/constants/sidebar.js +17 -0
  196. package/dist/constants/skeleton.d.ts +17 -0
  197. package/dist/constants/skeleton.js +17 -0
  198. package/dist/constants/split-button.d.ts +7 -0
  199. package/dist/constants/split-button.js +5 -0
  200. package/dist/constants/switch.d.ts +33 -0
  201. package/dist/constants/switch.js +41 -0
  202. package/dist/constants/tabs.d.ts +17 -0
  203. package/dist/constants/tabs.js +17 -0
  204. package/dist/constants/toast.d.ts +3 -0
  205. package/dist/constants/toast.js +3 -0
  206. package/dist/constants/tooltip.d.ts +13 -0
  207. package/dist/constants/tooltip.js +52 -0
  208. package/dist/hooks/use-horizontal-swipe.d.ts +23 -0
  209. package/dist/hooks/use-horizontal-swipe.js +80 -0
  210. package/dist/hooks/use-is-hydrated.d.ts +6 -0
  211. package/dist/hooks/use-is-hydrated.js +20 -0
  212. package/dist/hooks/use-mobile.d.ts +1 -0
  213. package/dist/hooks/use-mobile.js +19 -0
  214. package/dist/hooks/use-prefers-reduced-motion.d.ts +2 -0
  215. package/dist/hooks/use-prefers-reduced-motion.js +27 -0
  216. package/dist/hooks/use-rich-link-editor.d.ts +55 -0
  217. package/dist/hooks/use-rich-link-editor.js +515 -0
  218. package/dist/hooks/use-sidebar-persistence.d.ts +6 -0
  219. package/dist/hooks/use-sidebar-persistence.js +52 -0
  220. package/dist/hooks/use-today.d.ts +7 -0
  221. package/dist/hooks/use-today.js +50 -0
  222. package/dist/hooks/use-viewer-time-zone.d.ts +6 -0
  223. package/dist/hooks/use-viewer-time-zone.js +20 -0
  224. package/dist/hooks.d.ts +11 -0
  225. package/dist/hooks.js +11 -0
  226. package/dist/index.d.ts +71 -0
  227. package/dist/index.js +69 -0
  228. package/dist/lib/browser-clipboard.d.ts +13 -0
  229. package/dist/lib/browser-clipboard.js +48 -0
  230. package/dist/lib/column-filter-value.d.ts +12 -0
  231. package/dist/lib/column-filter-value.js +52 -0
  232. package/dist/lib/file-acceptance.d.ts +43 -0
  233. package/dist/lib/file-acceptance.js +107 -0
  234. package/dist/lib/format-file-size.d.ts +16 -0
  235. package/dist/lib/format-file-size.js +34 -0
  236. package/dist/lib/fuzzy-search.d.ts +17 -0
  237. package/dist/lib/fuzzy-search.js +183 -0
  238. package/dist/lib/horizontal-swipe.d.ts +23 -0
  239. package/dist/lib/horizontal-swipe.js +29 -0
  240. package/dist/lib/image-dimensions.d.ts +2 -0
  241. package/dist/lib/image-dimensions.js +7 -0
  242. package/dist/lib/name-initials.d.ts +7 -0
  243. package/dist/lib/name-initials.js +11 -0
  244. package/dist/lib/rich-text/link-markdown-constants.d.ts +147 -0
  245. package/dist/lib/rich-text/link-markdown-constants.js +458 -0
  246. package/dist/lib/rich-text/link-markdown-types.d.ts +53 -0
  247. package/dist/lib/rich-text/link-markdown-types.js +1 -0
  248. package/dist/lib/rich-text/link-markdown.d.ts +193 -0
  249. package/dist/lib/rich-text/link-markdown.js +592 -0
  250. package/dist/lib/rich-text/rich-markdown.d.ts +41 -0
  251. package/dist/lib/rich-text/rich-markdown.js +105 -0
  252. package/dist/lib/rich-text/rich-text-editor-dom.d.ts +26 -0
  253. package/dist/lib/rich-text/rich-text-editor-dom.js +79 -0
  254. package/dist/lib/toast-layer.d.ts +24 -0
  255. package/dist/lib/toast-layer.js +76 -0
  256. package/dist/lib/utils.d.ts +2 -0
  257. package/dist/lib/utils.js +2 -0
  258. package/dist/lib/year-month-filter.d.ts +16 -0
  259. package/dist/lib/year-month-filter.js +46 -0
  260. package/dist/motion/arc-floating-slot.d.ts +40 -0
  261. package/dist/motion/arc-floating-slot.js +177 -0
  262. package/dist/motion/arc-press.d.ts +6 -0
  263. package/dist/motion/arc-press.js +59 -0
  264. package/dist/motion/arc-swap.d.ts +22 -0
  265. package/dist/motion/arc-swap.js +49 -0
  266. package/dist/motion/arc-tokens.d.ts +53 -0
  267. package/dist/motion/arc-tokens.js +73 -0
  268. package/dist/motion/glide-indicator.d.ts +69 -0
  269. package/dist/motion/glide-indicator.js +309 -0
  270. package/dist/motion/glide-slot.d.ts +9 -0
  271. package/dist/motion/glide-slot.js +71 -0
  272. package/dist/motion/motion-slot.d.ts +12 -0
  273. package/dist/motion/motion-slot.js +376 -0
  274. package/dist/motion/overlay-warmth.d.ts +24 -0
  275. package/dist/motion/overlay-warmth.js +70 -0
  276. package/dist/motion/presence.d.ts +40 -0
  277. package/dist/motion/presence.js +101 -0
  278. package/dist/motion/surface-keyframes.d.ts +24 -0
  279. package/dist/motion/surface-keyframes.js +141 -0
  280. package/dist/motion/tokens.d.ts +81 -0
  281. package/dist/motion/tokens.js +67 -0
  282. package/dist/motion/use-attached-element.d.ts +7 -0
  283. package/dist/motion/use-attached-element.js +22 -0
  284. package/dist/motion/use-morph-width.d.ts +13 -0
  285. package/dist/motion/use-morph-width.js +59 -0
  286. package/dist/next.d.ts +14 -0
  287. package/dist/next.js +79 -0
  288. package/dist/providers/astra-ui-provider.d.ts +27 -0
  289. package/dist/providers/astra-ui-provider.js +100 -0
  290. package/dist/providers/native-provider.d.ts +4 -0
  291. package/dist/providers/native-provider.js +45 -0
  292. package/dist/sonner.d.ts +7 -0
  293. package/dist/sonner.js +8 -0
  294. package/dist/styles.css +2 -0
  295. package/dist/tanstack.d.ts +11 -0
  296. package/dist/tanstack.js +50 -0
  297. package/dist/theme.d.ts +3 -0
  298. package/dist/theme.js +1 -0
  299. package/dist/types/data-table.d.ts +27 -0
  300. package/dist/types/data-table.js +1 -0
  301. package/fonts.css +5 -0
  302. package/package.json +450 -4
  303. package/styles.css +4 -0
  304. package/theme.css +248 -0
@@ -0,0 +1,297 @@
1
+ "use client";
2
+ import { c as _c } from "react/compiler-runtime";
3
+ /**
4
+ * Arc's Badge (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md): a small pill for status, category or
5
+ * metadata on Arc's tones and tokens. A new text label rises in while the pill springs to its new width, and a new
6
+ * icon crossfades in place. The API is Arc's: `tone`, `size`, `icon` and `children`.
7
+ */
8
+ import { isValidElement, useRef } from "react";
9
+ import { cva } from "class-variance-authority";
10
+ import { AnimatePresence, motion, useIsPresent } from "motion/react";
11
+ import { BADGE_LABEL_OFFSET_EM } from "../constants/badge.js";
12
+ import { usePrefersReducedMotion } from "../hooks/use-prefers-reduced-motion.js";
13
+ import { cn } from "../lib/utils.js";
14
+ import { ARC_BLUR, ARC_DURATION, ARC_EASE } from "../motion/arc-tokens.js";
15
+ import { ARC_ICON_ENTER, ARC_ICON_EXIT, ARC_ICON_TRANSITION, ARC_REDUCED_EXIT, ARC_REDUCED_TRANSITION, ARC_SWAP_EXIT_TRANSITION, ARC_SWAP_REST } from "../motion/arc-swap.js";
16
+ import { useMorphWidth } from "../motion/use-morph-width.js";
17
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
18
+ /**
19
+ * Arc's badge recipe. Each tone sets the pill's colour roles as custom properties, so hover can mix the tone into the
20
+ * border and fill. Hover answers on fine pointers only.
21
+ */
22
+ const badgeRecipe = cva("group/badge inline-flex w-fit shrink-0 items-center justify-center overflow-clip rounded-(--radius-pill) border border-(--badge-border) bg-(--badge-background) leading-none font-medium tracking-[-.01em] whitespace-nowrap text-(--badge-foreground) transition-[border-color,background-color,color] duration-(--duration-standard) ease-(--ease-standard) motion-reduce:duration-(--duration-instant) hover-fine:border-[color-mix(in_oklab,var(--badge-color)_32%,var(--border))] hover-fine:bg-[color-mix(in_oklab,var(--badge-color)_10%,var(--surface))] aria-invalid:border-danger [&>svg]:pointer-events-none [&>svg]:size-3! [&>svg]:text-(--badge-color)", { variants: {
23
+ tone: {
24
+ neutral: "[--badge-background:var(--surface-muted)] [--badge-border:var(--border)] [--badge-color:var(--text-secondary)] [--badge-foreground:var(--text-secondary)]",
25
+ success: "[--badge-background:color-mix(in_oklab,var(--success)_10%,var(--surface))] [--badge-border:color-mix(in_oklab,var(--success)_25%,var(--border))] [--badge-color:var(--success)] [--badge-foreground:var(--success)]",
26
+ info: "[--badge-background:var(--accent-subtle)] [--badge-border:color-mix(in_oklab,var(--accent)_24%,var(--border))] [--badge-color:var(--accent)] [--badge-foreground:var(--accent-strong)]",
27
+ warning: "[--badge-background:color-mix(in_oklab,var(--warning)_11%,var(--surface))] [--badge-border:color-mix(in_oklab,var(--warning)_27%,var(--border))] [--badge-color:var(--warning)] [--badge-foreground:var(--warning)]",
28
+ danger: "[--badge-background:color-mix(in_oklab,var(--danger)_10%,var(--surface))] [--badge-border:color-mix(in_oklab,var(--danger)_26%,var(--border))] [--badge-color:var(--danger)] [--badge-foreground:var(--danger)]"
29
+ },
30
+ size: {
31
+ sm: "min-h-[22px] gap-1 px-2 text-[11px]",
32
+ md: "min-h-[26px] gap-[5px] px-2.5 text-xs"
33
+ }
34
+ } });
35
+ /** A new label rises out of a soft blur; the old one lifts away faster. */
36
+ const labelEnter = {
37
+ opacity: 0,
38
+ y: `${BADGE_LABEL_OFFSET_EM.enter}em`,
39
+ filter: `blur(${ARC_BLUR.soft}px)`
40
+ };
41
+ const labelExit = {
42
+ opacity: 0,
43
+ y: `${BADGE_LABEL_OFFSET_EM.exit}em`,
44
+ filter: `blur(${ARC_BLUR.subtle}px)`,
45
+ transition: ARC_SWAP_EXIT_TRANSITION
46
+ };
47
+ const labelTransition = {
48
+ duration: ARC_DURATION.standard,
49
+ ease: [...ARC_EASE.enter]
50
+ };
51
+ const reducedEnter = { opacity: 0 };
52
+ /** Outgoing copies are hidden from assistive technology while they fade, so only the current one is read. */
53
+ function BadgeSwap(props) {
54
+ const $ = _c(3);
55
+ const isPresent = useIsPresent();
56
+ const t0 = isPresent ? props["aria-hidden"] : true;
57
+ let t1;
58
+ if ($[0] !== props || $[1] !== t0) {
59
+ t1 = /* @__PURE__ */ _jsx(motion.span, {
60
+ ...props,
61
+ "aria-hidden": t0
62
+ });
63
+ $[0] = props;
64
+ $[1] = t0;
65
+ $[2] = t1;
66
+ } else {
67
+ t1 = $[2];
68
+ }
69
+ return t1;
70
+ }
71
+ /** Keys an icon by its component, so a new icon crossfades in while re-rendering the same icon stays still. */
72
+ function getIconKey(icon) {
73
+ if (!isValidElement(icon)) return "icon";
74
+ const iconType = icon.type;
75
+ return typeof iconType === "string" ? iconType : iconType.displayName ?? iconType.name ?? "icon";
76
+ }
77
+ /** Arc's swapping content: the icon and text change in place while the pill springs to the new width. */
78
+ function BadgeContent(t0) {
79
+ const $ = _c(19);
80
+ const { icon, label, reduceMotion } = t0;
81
+ const contentRef = useRef(null);
82
+ let t1;
83
+ if ($[0] !== icon) {
84
+ t1 = icon ? getIconKey(icon) : "";
85
+ $[0] = icon;
86
+ $[1] = t1;
87
+ } else {
88
+ t1 = $[1];
89
+ }
90
+ const iconKey = t1;
91
+ const width = useMorphWidth(contentRef, `${iconKey}\n${label}`, reduceMotion);
92
+ let t2;
93
+ if ($[2] !== width) {
94
+ t2 = { width };
95
+ $[2] = width;
96
+ $[3] = t2;
97
+ } else {
98
+ t2 = $[3];
99
+ }
100
+ let t3;
101
+ if ($[4] !== icon || $[5] !== iconKey || $[6] !== reduceMotion) {
102
+ t3 = icon ? /* @__PURE__ */ _jsx(BadgeIcon, {
103
+ icon,
104
+ iconKey,
105
+ reduceMotion
106
+ }) : null;
107
+ $[4] = icon;
108
+ $[5] = iconKey;
109
+ $[6] = reduceMotion;
110
+ $[7] = t3;
111
+ } else {
112
+ t3 = $[7];
113
+ }
114
+ const t4 = reduceMotion ? reducedEnter : labelEnter;
115
+ const t5 = reduceMotion ? ARC_REDUCED_EXIT : labelExit;
116
+ const t6 = reduceMotion ? ARC_REDUCED_TRANSITION : labelTransition;
117
+ let t7;
118
+ if ($[8] !== label || $[9] !== t4 || $[10] !== t5 || $[11] !== t6) {
119
+ t7 = /* @__PURE__ */ _jsx("span", {
120
+ className: "relative inline-flex items-center",
121
+ children: /* @__PURE__ */ _jsx(AnimatePresence, {
122
+ mode: "popLayout",
123
+ initial: false,
124
+ children: /* @__PURE__ */ _jsx(BadgeSwap, {
125
+ className: "block",
126
+ initial: t4,
127
+ animate: ARC_SWAP_REST,
128
+ exit: t5,
129
+ transition: t6,
130
+ children: label
131
+ }, label)
132
+ })
133
+ });
134
+ $[8] = label;
135
+ $[9] = t4;
136
+ $[10] = t5;
137
+ $[11] = t6;
138
+ $[12] = t7;
139
+ } else {
140
+ t7 = $[12];
141
+ }
142
+ let t8;
143
+ if ($[13] !== t3 || $[14] !== t7) {
144
+ t8 = /* @__PURE__ */ _jsxs("span", {
145
+ ref: contentRef,
146
+ className: "relative inline-flex w-max items-center gap-[inherit]",
147
+ children: [t3, t7]
148
+ });
149
+ $[13] = t3;
150
+ $[14] = t7;
151
+ $[15] = t8;
152
+ } else {
153
+ t8 = $[15];
154
+ }
155
+ let t9;
156
+ if ($[16] !== t2 || $[17] !== t8) {
157
+ t9 = /* @__PURE__ */ _jsx(motion.span, {
158
+ "data-slot": "badge-content",
159
+ className: "block gap-[inherit] data-morphing:overflow-clip",
160
+ style: t2,
161
+ children: t8
162
+ });
163
+ $[16] = t2;
164
+ $[17] = t8;
165
+ $[18] = t9;
166
+ } else {
167
+ t9 = $[18];
168
+ }
169
+ return t9;
170
+ }
171
+ /** The leading icon, tinted with the tone; a different icon component crossfades in. */
172
+ function BadgeIcon(t0) {
173
+ const $ = _c(6);
174
+ const { icon, iconKey, reduceMotion } = t0;
175
+ const t1 = reduceMotion ? reducedEnter : ARC_ICON_ENTER;
176
+ const t2 = reduceMotion ? ARC_REDUCED_EXIT : ARC_ICON_EXIT;
177
+ const t3 = reduceMotion ? ARC_REDUCED_TRANSITION : ARC_ICON_TRANSITION;
178
+ let t4;
179
+ if ($[0] !== icon || $[1] !== iconKey || $[2] !== t1 || $[3] !== t2 || $[4] !== t3) {
180
+ t4 = /* @__PURE__ */ _jsx("span", {
181
+ "data-slot": "badge-icon",
182
+ "aria-hidden": "true",
183
+ className: "relative inline-flex flex-none items-center justify-center leading-none text-(--badge-color) [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-3",
184
+ children: /* @__PURE__ */ _jsx(AnimatePresence, {
185
+ mode: "popLayout",
186
+ initial: false,
187
+ children: /* @__PURE__ */ _jsx(BadgeSwap, {
188
+ className: "relative inline-flex items-center",
189
+ initial: t1,
190
+ animate: ARC_SWAP_REST,
191
+ exit: t2,
192
+ transition: t3,
193
+ children: icon
194
+ }, iconKey)
195
+ })
196
+ });
197
+ $[0] = icon;
198
+ $[1] = iconKey;
199
+ $[2] = t1;
200
+ $[3] = t2;
201
+ $[4] = t3;
202
+ $[5] = t4;
203
+ } else {
204
+ t4 = $[5];
205
+ }
206
+ return t4;
207
+ }
208
+ /**
209
+ * A small label for status, category or metadata. String or number children swap in place with Arc's motion and the
210
+ * pill springs to the new width; other children render as they are.
211
+ * @param props - Tone, size, optional icon and native span attributes.
212
+ * @returns The badge.
213
+ */
214
+ function Badge(t0) {
215
+ const $ = _c(22);
216
+ let children;
217
+ let className;
218
+ let icon;
219
+ let props;
220
+ let t1;
221
+ let t2;
222
+ if ($[0] !== t0) {
223
+ ({className, tone: t1, size: t2, icon, children, ...props} = t0);
224
+ $[0] = t0;
225
+ $[1] = children;
226
+ $[2] = className;
227
+ $[3] = icon;
228
+ $[4] = props;
229
+ $[5] = t1;
230
+ $[6] = t2;
231
+ } else {
232
+ children = $[1];
233
+ className = $[2];
234
+ icon = $[3];
235
+ props = $[4];
236
+ t1 = $[5];
237
+ t2 = $[6];
238
+ }
239
+ const tone = t1 === undefined ? "neutral" : t1;
240
+ const size = t2 === undefined ? "md" : t2;
241
+ const reduceMotion = usePrefersReducedMotion();
242
+ const label = typeof children === "string" || typeof children === "number" ? String(children) : null;
243
+ let t3;
244
+ if ($[7] !== children || $[8] !== icon || $[9] !== label || $[10] !== reduceMotion) {
245
+ t3 = label === null ? /* @__PURE__ */ _jsxs(_Fragment, { children: [icon ? /* @__PURE__ */ _jsx(BadgeIcon, {
246
+ icon,
247
+ iconKey: getIconKey(icon),
248
+ reduceMotion
249
+ }) : null, children] }) : /* @__PURE__ */ _jsx(BadgeContent, {
250
+ icon,
251
+ label,
252
+ reduceMotion
253
+ });
254
+ $[7] = children;
255
+ $[8] = icon;
256
+ $[9] = label;
257
+ $[10] = reduceMotion;
258
+ $[11] = t3;
259
+ } else {
260
+ t3 = $[11];
261
+ }
262
+ const content = t3;
263
+ let t4;
264
+ if ($[12] !== className || $[13] !== size || $[14] !== tone) {
265
+ t4 = cn(badgeRecipe({
266
+ tone,
267
+ size
268
+ }), className);
269
+ $[12] = className;
270
+ $[13] = size;
271
+ $[14] = tone;
272
+ $[15] = t4;
273
+ } else {
274
+ t4 = $[15];
275
+ }
276
+ let t5;
277
+ if ($[16] !== content || $[17] !== props || $[18] !== size || $[19] !== t4 || $[20] !== tone) {
278
+ t5 = /* @__PURE__ */ _jsx("span", {
279
+ "data-slot": "badge",
280
+ "data-tone": tone,
281
+ "data-size": size,
282
+ className: t4,
283
+ ...props,
284
+ children: content
285
+ });
286
+ $[16] = content;
287
+ $[17] = props;
288
+ $[18] = size;
289
+ $[19] = t4;
290
+ $[20] = tone;
291
+ $[21] = t5;
292
+ } else {
293
+ t5 = $[21];
294
+ }
295
+ return t5;
296
+ }
297
+ export { Badge };
@@ -0,0 +1,23 @@
1
+ /** Interaction states shared by `Button` and the internal `ControlButton`. */
2
+ import type { MouseEvent } from "react";
3
+ /** Swallows activation while loading, keeping the button focusable instead of disabling it. */
4
+ declare function preventActivation(event: MouseEvent<HTMLElement>): void;
5
+ /**
6
+ * While loading, these handlers are dropped: Radix triggers open their layer from pointer and key handlers they
7
+ * inject through `asChild`, so swallowing only the click would leave a busy trigger able to open it. Keyboard focus
8
+ * stays, since nothing here touches focusability.
9
+ */
10
+ export declare const LOADING_INERT_HANDLERS: {
11
+ readonly onClick: typeof preventActivation;
12
+ readonly onPointerDown: undefined;
13
+ readonly onKeyDown: undefined;
14
+ };
15
+ /**
16
+ * Applied while a parent `AnimatePresence` removes the button, so a stale control can be neither clicked, focused
17
+ * nor announced during the exit animation.
18
+ */
19
+ export declare const LEAVING_ATTRIBUTES: {
20
+ readonly inert: true;
21
+ readonly "aria-hidden": true;
22
+ };
23
+ export {};
@@ -0,0 +1,22 @@
1
+ /** Swallows activation while loading, keeping the button focusable instead of disabling it. */
2
+ function preventActivation(event) {
3
+ event.preventDefault();
4
+ }
5
+ /**
6
+ * While loading, these handlers are dropped: Radix triggers open their layer from pointer and key handlers they
7
+ * inject through `asChild`, so swallowing only the click would leave a busy trigger able to open it. Keyboard focus
8
+ * stays, since nothing here touches focusability.
9
+ */
10
+ export const LOADING_INERT_HANDLERS = {
11
+ onClick: preventActivation,
12
+ onPointerDown: undefined,
13
+ onKeyDown: undefined
14
+ };
15
+ /**
16
+ * Applied while a parent `AnimatePresence` removes the button, so a stale control can be neither clicked, focused
17
+ * nor announced during the exit animation.
18
+ */
19
+ export const LEAVING_ATTRIBUTES = {
20
+ inert: true,
21
+ "aria-hidden": true
22
+ };
@@ -0,0 +1,8 @@
1
+ import type { ReactNode } from "react";
2
+ export type ButtonLabelProps = {
3
+ children: ReactNode;
4
+ loading: boolean;
5
+ reduceMotion: boolean;
6
+ };
7
+ /** Button content: a spinner while loading and a label whose width springs when it changes. */
8
+ export declare function ButtonLabel({ children, loading, reduceMotion }: ButtonLabelProps): import("react").JSX.Element;
@@ -0,0 +1,203 @@
1
+ "use client";
2
+ import { c as _c } from "react/compiler-runtime";
3
+ /**
4
+ * Label morph and loading spinner adapted from Arc (https://uiarc.dev), Copyright (c) 2026 Elia Kuratli,
5
+ * MIT License. The full license text ships in THIRD_PARTY_NOTICES.md. Internal to Button.
6
+ */
7
+ import { isValidElement, useRef } from "react";
8
+ import { AnimatePresence, motion, useIsPresent } from "motion/react";
9
+ import { cn } from "../lib/utils.js";
10
+ import { ARC_BLUR, ARC_DURATION, ARC_EASE } from "../motion/arc-tokens.js";
11
+ import { ARC_ICON_ENTER as iconEnter, ARC_ICON_EXIT as iconExit, ARC_ICON_TRANSITION as iconTransition, ARC_REDUCED_ENTER as reducedEnter, ARC_REDUCED_EXIT as reducedExit, ARC_REDUCED_TRANSITION as reducedTransition, ARC_SWAP_EXIT_TRANSITION as exitTransition, ARC_SWAP_REST as restState } from "../motion/arc-swap.js";
12
+ import { useMorphWidth } from "../motion/use-morph-width.js";
13
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
14
+ /** Text rises out of a soft blur; the outgoing label lifts away a little faster. */
15
+ const textEnter = {
16
+ opacity: 0,
17
+ y: 4,
18
+ filter: `blur(${ARC_BLUR.soft}px)`
19
+ };
20
+ const textExit = {
21
+ opacity: 0,
22
+ y: -3,
23
+ filter: `blur(${ARC_BLUR.soft}px)`,
24
+ transition: exitTransition
25
+ };
26
+ const textTransition = {
27
+ duration: ARC_DURATION.standard,
28
+ ease: [...ARC_EASE.enter]
29
+ };
30
+ /** Matches markup tags inside a label key so icon-only labels can be detected. */
31
+ const LABEL_KEY_TAG_PATTERN = /<[^>]*>/g;
32
+ /** Detects visible text left in a label key. */
33
+ const VISIBLE_TEXT_PATTERN = /\S/;
34
+ /** Builds a key from text and element names, so a new label crossfades while prop-only updates stay in place. */
35
+ function getLabelKey(node) {
36
+ if (node == null || typeof node === "boolean") return "";
37
+ if (typeof node === "string" || typeof node === "number" || typeof node === "bigint") return String(node);
38
+ if (Array.isArray(node)) return node.map(getLabelKey).join("");
39
+ if (!isValidElement(node)) return "";
40
+ const elementType = node.type;
41
+ const elementName = typeof elementType === "string" ? elementType : elementType?.displayName ?? elementType?.name ?? "";
42
+ return `<${elementName}>${getLabelKey(node.props.children)}`;
43
+ }
44
+ /** One generation of the label; the outgoing one is hidden from assistive tech while it leaves. */
45
+ function LabelPhase(t0) {
46
+ const $ = _c(7);
47
+ const { children, isIcon, reduceMotion, ref } = t0;
48
+ const isPresent = useIsPresent();
49
+ const t1 = isPresent ? undefined : true;
50
+ const t2 = reduceMotion ? reducedEnter : isIcon ? iconEnter : textEnter;
51
+ const t3 = reduceMotion ? reducedExit : isIcon ? iconExit : textExit;
52
+ const t4 = reduceMotion ? reducedTransition : isIcon ? iconTransition : textTransition;
53
+ let t5;
54
+ if ($[0] !== children || $[1] !== ref || $[2] !== t1 || $[3] !== t2 || $[4] !== t3 || $[5] !== t4) {
55
+ t5 = /* @__PURE__ */ _jsx(motion.span, {
56
+ ref,
57
+ className: "inline-flex items-center justify-center gap-[inherit] whitespace-nowrap",
58
+ "aria-hidden": t1,
59
+ initial: t2,
60
+ animate: restState,
61
+ exit: t3,
62
+ transition: t4,
63
+ children
64
+ });
65
+ $[0] = children;
66
+ $[1] = ref;
67
+ $[2] = t1;
68
+ $[3] = t2;
69
+ $[4] = t3;
70
+ $[5] = t4;
71
+ $[6] = t5;
72
+ } else {
73
+ t5 = $[6];
74
+ }
75
+ return t5;
76
+ }
77
+ /** Button content: a spinner while loading and a label whose width springs when it changes. */
78
+ export function ButtonLabel(t0) {
79
+ const $ = _c(25);
80
+ const { children, loading, reduceMotion } = t0;
81
+ const contentRef = useRef(null);
82
+ let t1;
83
+ if ($[0] !== children) {
84
+ t1 = getLabelKey(children);
85
+ $[0] = children;
86
+ $[1] = t1;
87
+ } else {
88
+ t1 = $[1];
89
+ }
90
+ const labelKey = t1;
91
+ const width = useMorphWidth(contentRef, labelKey, reduceMotion);
92
+ let t2;
93
+ if ($[2] !== loading || $[3] !== reduceMotion) {
94
+ t2 = loading ? /* @__PURE__ */ _jsx(motion.span, {
95
+ className: "absolute top-1/2 left-1/2 -m-2 grid size-4",
96
+ "aria-hidden": "true",
97
+ initial: reduceMotion ? { opacity: 0 } : {
98
+ opacity: 0,
99
+ scale: .6
100
+ },
101
+ animate: {
102
+ opacity: 1,
103
+ scale: 1
104
+ },
105
+ exit: reduceMotion ? reducedExit : {
106
+ ...iconExit,
107
+ scale: .8
108
+ },
109
+ transition: reduceMotion ? reducedTransition : iconTransition,
110
+ children: /* @__PURE__ */ _jsx("span", { className: "animate-spin rounded-full border-[1.5px] border-current border-r-transparent motion-reduce:animate-none" })
111
+ }, "loader") : null;
112
+ $[2] = loading;
113
+ $[3] = reduceMotion;
114
+ $[4] = t2;
115
+ } else {
116
+ t2 = $[4];
117
+ }
118
+ let t3;
119
+ if ($[5] !== t2) {
120
+ t3 = /* @__PURE__ */ _jsx(AnimatePresence, {
121
+ initial: false,
122
+ children: t2
123
+ });
124
+ $[5] = t2;
125
+ $[6] = t3;
126
+ } else {
127
+ t3 = $[6];
128
+ }
129
+ const t4 = loading && "opacity-0";
130
+ let t5;
131
+ if ($[7] !== t4) {
132
+ t5 = cn("inline-flex min-w-0 items-center justify-center gap-[inherit] transition-opacity duration-150 data-morphing:[clip-path:inset(-50%_calc(var(--spacing)*-3))]", t4);
133
+ $[7] = t4;
134
+ $[8] = t5;
135
+ } else {
136
+ t5 = $[8];
137
+ }
138
+ let t6;
139
+ if ($[9] !== width) {
140
+ t6 = { width };
141
+ $[9] = width;
142
+ $[10] = t6;
143
+ } else {
144
+ t6 = $[10];
145
+ }
146
+ let t7;
147
+ if ($[11] !== labelKey) {
148
+ t7 = VISIBLE_TEXT_PATTERN.test(labelKey.replace(LABEL_KEY_TAG_PATTERN, ""));
149
+ $[11] = labelKey;
150
+ $[12] = t7;
151
+ } else {
152
+ t7 = $[12];
153
+ }
154
+ const t8 = !t7;
155
+ let t9;
156
+ if ($[13] !== children || $[14] !== labelKey || $[15] !== reduceMotion || $[16] !== t8) {
157
+ t9 = /* @__PURE__ */ _jsx("span", {
158
+ ref: contentRef,
159
+ className: "inline-flex flex-none items-center gap-[inherit]",
160
+ children: /* @__PURE__ */ _jsx(AnimatePresence, {
161
+ mode: "popLayout",
162
+ initial: false,
163
+ children: /* @__PURE__ */ _jsx(LabelPhase, {
164
+ isIcon: t8,
165
+ reduceMotion,
166
+ children
167
+ }, labelKey)
168
+ })
169
+ });
170
+ $[13] = children;
171
+ $[14] = labelKey;
172
+ $[15] = reduceMotion;
173
+ $[16] = t8;
174
+ $[17] = t9;
175
+ } else {
176
+ t9 = $[17];
177
+ }
178
+ let t10;
179
+ if ($[18] !== t5 || $[19] !== t6 || $[20] !== t9) {
180
+ t10 = /* @__PURE__ */ _jsx(motion.span, {
181
+ "data-slot": "button-label",
182
+ className: t5,
183
+ style: t6,
184
+ children: t9
185
+ });
186
+ $[18] = t5;
187
+ $[19] = t6;
188
+ $[20] = t9;
189
+ $[21] = t10;
190
+ } else {
191
+ t10 = $[21];
192
+ }
193
+ let t11;
194
+ if ($[22] !== t10 || $[23] !== t3) {
195
+ t11 = /* @__PURE__ */ _jsxs(_Fragment, { children: [t3, t10] });
196
+ $[22] = t10;
197
+ $[23] = t3;
198
+ $[24] = t11;
199
+ } else {
200
+ t11 = $[24];
201
+ }
202
+ return t11;
203
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Arc's Button (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md): its variants, sizes, tokens and motion,
3
+ * with width-aware press feedback, a label that springs to its new width and a loading spinner. It renders a native
4
+ * button; style links as links instead. Composite components that need icon sizes use the internal `ControlButton`.
5
+ */
6
+ import type { ComponentProps } from "react";
7
+ /** Visual weight, as in Arc: one primary action per surface. */
8
+ export type ButtonVariant = "primary" | "secondary" | "ghost" | "danger";
9
+ /** Height and padding, from Arc's control heights. */
10
+ export type ButtonSize = "sm" | "md" | "lg";
11
+ export type ButtonProps = ComponentProps<"button"> & {
12
+ variant?: ButtonVariant;
13
+ size?: ButtonSize;
14
+ /** Shows a spinner, sets `aria-busy` and swallows clicks while keeping keyboard focus. */
15
+ loading?: boolean;
16
+ };
17
+ /**
18
+ * A single action on a page, form or dialog. Defaults to `type="button"`, so it only submits a form when asked to.
19
+ * @param props - Variant, size, loading state and native button attributes, including `ref`.
20
+ * @returns The native button.
21
+ */
22
+ declare function Button({ className, variant, size, loading, type, children, ref, ...props }: ButtonProps): import("react").JSX.Element;
23
+ export { Button };