@astra-kit/ui 0.0.0-stage → 1.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 +21 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +330 -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 +58 -0
  55. package/dist/components/dropdown-menu.js +135 -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 +17 -0
  177. package/dist/constants/dropdown-menu.js +48 -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,23 @@
1
+ import type { ReactNode } from "react";
2
+ export type SkeletonProps = {
3
+ /** Accessible name of the loading status; defaults to "Cargando contenido". */
4
+ label?: string;
5
+ /** Number of text lines, clamped to 1-6; defaults to 3. */
6
+ lines?: number;
7
+ /** Adds a round avatar block before the lines. */
8
+ avatar?: boolean;
9
+ /** Content to reveal once loading finishes; with children the placeholder crossfades into them. */
10
+ children?: ReactNode;
11
+ /** Keeps the placeholder visible while true (the default). Only used together with `children`. */
12
+ loading?: boolean;
13
+ /** Classes for the outer element: the placeholder, or the reveal frame when there are children. */
14
+ className?: string;
15
+ };
16
+ /**
17
+ * Reserves space while content loads. Without children it draws Arc's placeholder, three text lines by default; with
18
+ * children it shows that placeholder while `loading` and then crossfades into them.
19
+ * @param props - Placeholder shape, accessible label, loading state and classes.
20
+ * @returns The placeholder, or the reveal frame when there are children.
21
+ */
22
+ declare function Skeleton({ label, lines, avatar, children, loading, className, }: SkeletonProps): import("react").JSX.Element;
23
+ export { Skeleton };
@@ -0,0 +1,334 @@
1
+ "use client";
2
+ import { c as _c } from "react/compiler-runtime";
3
+ /**
4
+ * Arc's Skeleton (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md): placeholders that reserve space while
5
+ * content loads, with a calm, finite pulse that ripples down the blocks and rests after about 20 seconds. It draws
6
+ * Arc's placeholder of text lines and an optional avatar, and with children its reveal, which crossfades into the
7
+ * content while the height springs to its new size. Like Arc, it only draws lines and an avatar: other shapes are
8
+ * built by the consumer.
9
+ */
10
+ import { useEffect, useLayoutEffect, useRef } from "react";
11
+ import { AnimatePresence, animate, motion, useIsPresent } from "motion/react";
12
+ import { SKELETON_DEFAULT_LABEL, SKELETON_DEFAULT_LINES, SKELETON_LINE_LIMITS, SKELETON_MORPH_WINDOW_MS, SKELETON_REVEAL_OFFSET_PX } from "../constants/skeleton.js";
13
+ import { usePrefersReducedMotion } from "../hooks/use-prefers-reduced-motion.js";
14
+ import { cn } from "../lib/utils.js";
15
+ import { ARC_DURATION, ARC_EASE, ARC_SPRING_SMOOTH } from "../motion/arc-tokens.js";
16
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
17
+ /**
18
+ * Arc's block: a soft fill mixed from the strong border, and a 1.8s pulse that starts a beat later for each
19
+ * `--index` and stops after 11 rounds. Reduced motion shows a still block.
20
+ */
21
+ const blockClassName = "block rounded-(--radius-control) bg-[color-mix(in_oklab,var(--border-strong)_38%,var(--surface))] animate-pulse [animation-delay:calc(var(--index,0)*90ms)] [animation-duration:1.8s] [animation-fill-mode:both] [animation-iteration-count:11] [animation-timing-function:var(--ease-in-out)] motion-reduce:animate-none";
22
+ /**
23
+ * Follows the content height. After `busy` flips, the frame springs from its old height to its new one, owning its
24
+ * inline height and overflow only while it moves and restoring the consumer's values afterwards, so a fixed height
25
+ * from `className` or `style` keeps applying at rest. It clips only while moving, so focus rings stay visible at rest.
26
+ * @param contentRef - The measured content; its parent is the frame that springs.
27
+ * @param busy - Whether the placeholder is showing; a change opens the window in which resizes spring.
28
+ * @param reduceMotion - Whether every resize should jump.
29
+ */
30
+ function useMorphHeight(contentRef, busy, reduceMotion) {
31
+ const changedAt = useRef(0);
32
+ useLayoutEffect(() => {
33
+ changedAt.current = performance.now();
34
+ }, [busy]);
35
+ useEffect(() => {
36
+ const content = contentRef.current;
37
+ const frame = content?.parentElement;
38
+ if (!content || !frame || typeof ResizeObserver === "undefined") return;
39
+ let lastFrameHeight;
40
+ let controls;
41
+ let restingStyle;
42
+ const readFrameHeight = () => frame.getBoundingClientRect().height;
43
+ const settle = () => {
44
+ if (restingStyle) Object.assign(frame.style, restingStyle);
45
+ restingStyle = undefined;
46
+ };
47
+ const observer = new ResizeObserver(() => {
48
+ controls?.stop();
49
+ const fromHeight = restingStyle ? readFrameHeight() : lastFrameHeight;
50
+ if (restingStyle) frame.style.height = restingStyle.height;
51
+ const nextHeight = readFrameHeight();
52
+ lastFrameHeight = nextHeight;
53
+ const isOutsideWindow = performance.now() - changedAt.current > SKELETON_MORPH_WINDOW_MS;
54
+ if (reduceMotion || fromHeight === undefined || fromHeight === nextHeight || isOutsideWindow) return settle();
55
+ restingStyle ??= {
56
+ height: frame.style.height,
57
+ overflow: frame.style.overflow
58
+ };
59
+ frame.style.overflow = "hidden";
60
+ frame.style.height = `${fromHeight}px`;
61
+ controls = animate(fromHeight, nextHeight, {
62
+ ...ARC_SPRING_SMOOTH,
63
+ onUpdate: (animatedHeight) => {
64
+ frame.style.height = `${animatedHeight}px`;
65
+ },
66
+ onComplete: settle
67
+ });
68
+ });
69
+ observer.observe(content);
70
+ return () => {
71
+ observer.disconnect();
72
+ controls?.stop();
73
+ settle();
74
+ };
75
+ }, [contentRef, reduceMotion]);
76
+ }
77
+ /** Arc's composed placeholder: an optional avatar and a column of lines, announced once as a busy status. */
78
+ function SkeletonPlaceholder(t0) {
79
+ const $ = _c(14);
80
+ const { lines, avatar, label, className } = t0;
81
+ const lineCount = Math.min(Math.max(Math.floor(lines), SKELETON_LINE_LIMITS.min), SKELETON_LINE_LIMITS.max);
82
+ const firstLineIndex = avatar ? 1 : 0;
83
+ let t1;
84
+ if ($[0] !== className) {
85
+ t1 = cn("flex w-full min-w-0 items-start gap-(--space-4)", className);
86
+ $[0] = className;
87
+ $[1] = t1;
88
+ } else {
89
+ t1 = $[1];
90
+ }
91
+ let t2;
92
+ if ($[2] !== avatar) {
93
+ t2 = avatar ? /* @__PURE__ */ _jsx("span", {
94
+ "data-slot": "skeleton",
95
+ "aria-hidden": "true",
96
+ className: cn(blockClassName, "size-(--control-height-md) flex-none rounded-(--radius-pill)")
97
+ }) : null;
98
+ $[2] = avatar;
99
+ $[3] = t2;
100
+ } else {
101
+ t2 = $[3];
102
+ }
103
+ let t3;
104
+ if ($[4] !== firstLineIndex || $[5] !== lineCount) {
105
+ let t4;
106
+ if ($[7] !== firstLineIndex) {
107
+ t4 = (_, lineIndex) => /* @__PURE__ */ _jsx("span", {
108
+ "data-slot": "skeleton",
109
+ className: cn(blockClassName, "h-(--space-3) w-full first:h-(--space-4) first:w-[48%] last:not-first:w-[72%]"),
110
+ style: { "--index": lineIndex + firstLineIndex }
111
+ }, lineIndex);
112
+ $[7] = firstLineIndex;
113
+ $[8] = t4;
114
+ } else {
115
+ t4 = $[8];
116
+ }
117
+ t3 = /* @__PURE__ */ _jsx("span", {
118
+ "aria-hidden": "true",
119
+ className: "grid flex-1 gap-(--space-3) pt-(--space-1)",
120
+ children: Array.from({ length: lineCount }, t4)
121
+ });
122
+ $[4] = firstLineIndex;
123
+ $[5] = lineCount;
124
+ $[6] = t3;
125
+ } else {
126
+ t3 = $[6];
127
+ }
128
+ let t4;
129
+ if ($[9] !== label || $[10] !== t1 || $[11] !== t2 || $[12] !== t3) {
130
+ t4 = /* @__PURE__ */ _jsxs("div", {
131
+ "data-slot": "skeleton-placeholder",
132
+ role: "status",
133
+ "aria-label": label,
134
+ "aria-busy": "true",
135
+ className: t1,
136
+ children: [t2, t3]
137
+ });
138
+ $[9] = label;
139
+ $[10] = t1;
140
+ $[11] = t2;
141
+ $[12] = t3;
142
+ $[13] = t4;
143
+ } else {
144
+ t4 = $[13];
145
+ }
146
+ return t4;
147
+ }
148
+ /**
149
+ * One side of the reveal. While it fades out it turns inert and hidden from assistive technology, so stale content
150
+ * under the new branch cannot be clicked, focused or announced.
151
+ */
152
+ function SkeletonBranch(t0) {
153
+ const $ = _c(8);
154
+ let props;
155
+ let ref;
156
+ if ($[0] !== t0) {
157
+ ({ref, ...props} = t0);
158
+ $[0] = t0;
159
+ $[1] = props;
160
+ $[2] = ref;
161
+ } else {
162
+ props = $[1];
163
+ ref = $[2];
164
+ }
165
+ const isPresent = useIsPresent();
166
+ const t1 = isPresent ? undefined : true;
167
+ const t2 = !isPresent || undefined;
168
+ let t3;
169
+ if ($[3] !== props || $[4] !== ref || $[5] !== t1 || $[6] !== t2) {
170
+ t3 = /* @__PURE__ */ _jsx(motion.div, {
171
+ ref,
172
+ ...props,
173
+ "aria-hidden": t1,
174
+ inert: t2
175
+ });
176
+ $[3] = props;
177
+ $[4] = ref;
178
+ $[5] = t1;
179
+ $[6] = t2;
180
+ $[7] = t3;
181
+ } else {
182
+ t3 = $[7];
183
+ }
184
+ return t3;
185
+ }
186
+ /** Arc's reveal: the placeholder crossfades into the content while the frame springs to the new height. */
187
+ function SkeletonReveal(t0) {
188
+ const $ = _c(12);
189
+ const { loading, placeholder, children, className } = t0;
190
+ const reduceMotion = usePrefersReducedMotion();
191
+ const contentRef = useRef(null);
192
+ useMorphHeight(contentRef, loading, reduceMotion);
193
+ const t1 = reduceMotion ? ARC_DURATION.instant : ARC_DURATION.fast;
194
+ let t2;
195
+ if ($[0] !== t1) {
196
+ t2 = { duration: t1 };
197
+ $[0] = t1;
198
+ $[1] = t2;
199
+ } else {
200
+ t2 = $[1];
201
+ }
202
+ const exitTransition = t2;
203
+ let t3;
204
+ if ($[2] !== children || $[3] !== exitTransition || $[4] !== loading || $[5] !== placeholder || $[6] !== reduceMotion) {
205
+ t3 = /* @__PURE__ */ _jsx("div", {
206
+ ref: contentRef,
207
+ className: "relative flow-root",
208
+ children: /* @__PURE__ */ _jsx(AnimatePresence, {
209
+ mode: "popLayout",
210
+ initial: false,
211
+ children: loading ? /* @__PURE__ */ _jsx(SkeletonBranch, {
212
+ initial: { opacity: 0 },
213
+ animate: { opacity: 1 },
214
+ exit: {
215
+ opacity: 0,
216
+ transition: exitTransition
217
+ },
218
+ transition: {
219
+ duration: reduceMotion ? ARC_DURATION.instant : ARC_DURATION.fast,
220
+ ease: [...ARC_EASE.standard]
221
+ },
222
+ children: placeholder
223
+ }, "placeholder") : /* @__PURE__ */ _jsx(SkeletonBranch, {
224
+ initial: reduceMotion ? { opacity: 0 } : {
225
+ opacity: 0,
226
+ y: SKELETON_REVEAL_OFFSET_PX
227
+ },
228
+ animate: {
229
+ opacity: 1,
230
+ y: 0
231
+ },
232
+ exit: {
233
+ opacity: 0,
234
+ transition: exitTransition
235
+ },
236
+ transition: {
237
+ duration: reduceMotion ? ARC_DURATION.instant : ARC_DURATION.standard,
238
+ ease: [...ARC_EASE.enter]
239
+ },
240
+ children
241
+ }, "content")
242
+ })
243
+ });
244
+ $[2] = children;
245
+ $[3] = exitTransition;
246
+ $[4] = loading;
247
+ $[5] = placeholder;
248
+ $[6] = reduceMotion;
249
+ $[7] = t3;
250
+ } else {
251
+ t3 = $[7];
252
+ }
253
+ let t4;
254
+ if ($[8] !== className || $[9] !== loading || $[10] !== t3) {
255
+ t4 = /* @__PURE__ */ _jsx("div", {
256
+ "data-slot": "skeleton-reveal",
257
+ "aria-busy": loading,
258
+ className,
259
+ children: t3
260
+ });
261
+ $[8] = className;
262
+ $[9] = loading;
263
+ $[10] = t3;
264
+ $[11] = t4;
265
+ } else {
266
+ t4 = $[11];
267
+ }
268
+ return t4;
269
+ }
270
+ /**
271
+ * Reserves space while content loads. Without children it draws Arc's placeholder, three text lines by default; with
272
+ * children it shows that placeholder while `loading` and then crossfades into them.
273
+ * @param props - Placeholder shape, accessible label, loading state and classes.
274
+ * @returns The placeholder, or the reveal frame when there are children.
275
+ */
276
+ function Skeleton(t0) {
277
+ const $ = _c(14);
278
+ const { label: t1, lines: t2, avatar: t3, children, loading: t4, className } = t0;
279
+ const label = t1 === undefined ? SKELETON_DEFAULT_LABEL : t1;
280
+ const lines = t2 === undefined ? SKELETON_DEFAULT_LINES : t2;
281
+ const avatar = t3 === undefined ? false : t3;
282
+ const loading = t4 === undefined ? true : t4;
283
+ if (children === undefined) {
284
+ let t5;
285
+ if ($[0] !== avatar || $[1] !== className || $[2] !== label || $[3] !== lines) {
286
+ t5 = /* @__PURE__ */ _jsx(SkeletonPlaceholder, {
287
+ lines,
288
+ avatar,
289
+ label,
290
+ className
291
+ });
292
+ $[0] = avatar;
293
+ $[1] = className;
294
+ $[2] = label;
295
+ $[3] = lines;
296
+ $[4] = t5;
297
+ } else {
298
+ t5 = $[4];
299
+ }
300
+ return t5;
301
+ }
302
+ let t5;
303
+ if ($[5] !== avatar || $[6] !== label || $[7] !== lines) {
304
+ t5 = /* @__PURE__ */ _jsx(SkeletonPlaceholder, {
305
+ lines,
306
+ avatar,
307
+ label
308
+ });
309
+ $[5] = avatar;
310
+ $[6] = label;
311
+ $[7] = lines;
312
+ $[8] = t5;
313
+ } else {
314
+ t5 = $[8];
315
+ }
316
+ let t6;
317
+ if ($[9] !== children || $[10] !== className || $[11] !== loading || $[12] !== t5) {
318
+ t6 = /* @__PURE__ */ _jsx(SkeletonReveal, {
319
+ loading,
320
+ placeholder: t5,
321
+ className,
322
+ children
323
+ });
324
+ $[9] = children;
325
+ $[10] = className;
326
+ $[11] = loading;
327
+ $[12] = t5;
328
+ $[13] = t6;
329
+ } else {
330
+ t6 = $[13];
331
+ }
332
+ return t6;
333
+ }
334
+ export { Skeleton };
@@ -0,0 +1,36 @@
1
+ import type { ReactNode } from "react";
2
+ import type { SplitButtonVariant } from "../constants/split-button.js";
3
+ export type { SplitButtonVariant } from "../constants/split-button.js";
4
+ /** One entry of the menu half. */
5
+ export type SplitButtonAction = {
6
+ label: string;
7
+ onSelect?: () => void;
8
+ disabled?: boolean;
9
+ /** Marks an action that deletes or discards, drawn in the danger color. */
10
+ destructive?: boolean;
11
+ icon?: ReactNode;
12
+ };
13
+ export type SplitButtonProps = {
14
+ /** Label of the main action and its accessible name; changing it morphs the letters in place. */
15
+ label: string;
16
+ /** Actions of the menu half, in order. */
17
+ actions: SplitButtonAction[];
18
+ /** Runs the main action. */
19
+ onClick?: () => void;
20
+ disabled?: boolean;
21
+ /** Icon before the label; swapping it for another element (such as Copy for Check) crossfades it. */
22
+ icon?: ReactNode;
23
+ /** `primary` for the main action of a surface, `secondary` for a quieter, smaller one. */
24
+ variant?: SplitButtonVariant;
25
+ /** Accessible name of the menu half; defaults to "Más acciones de {label}". */
26
+ menuLabel?: string;
27
+ className?: string;
28
+ };
29
+ /**
30
+ * A main action joined to a menu of related actions, such as Copy page with Copy as Markdown and Open in a new tab.
31
+ * The main half announces label changes politely; the menu half opens a `DropdownMenu` aligned to its end.
32
+ * @param props - Main action, its icon, the menu actions, the variant and accessible names.
33
+ * @returns The joined pair of buttons and their menu.
34
+ */
35
+ declare function SplitButton({ label, actions, onClick, disabled, icon, variant, menuLabel, className, }: SplitButtonProps): import("react").JSX.Element;
36
+ export { SplitButton };
@@ -0,0 +1,306 @@
1
+ "use client";
2
+ import { c as _c } from "react/compiler-runtime";
3
+ /**
4
+ * Arc's SplitButton (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md) built from @astra-kit/ui's `Button` and
5
+ * `DropdownMenu`: a main action whose icon and label morph in place, joined to a menu of related actions. The menu
6
+ * half never scales on press, so the menu opens from a still anchor.
7
+ */
8
+ import { isValidElement, useRef } from "react";
9
+ import { AnimatePresence, motion } from "motion/react";
10
+ import { ChevronDown } from "lucide-react";
11
+ import { SPLIT_BUTTON_SIZE_BY_VARIANT } from "../constants/split-button.js";
12
+ import { usePrefersReducedMotion } from "../hooks/use-prefers-reduced-motion.js";
13
+ import { cn } from "../lib/utils.js";
14
+ 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_REST as restState } from "../motion/arc-swap.js";
15
+ import { useMorphWidth } from "../motion/use-morph-width.js";
16
+ import { Button } from "./button.js";
17
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "./primitives/dropdown-menu.js";
18
+ import { MorphText } from "./morph-text.js";
19
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
20
+ /**
21
+ * Names an icon element, so swapping Copy for Check morphs while a re-render of the same icon stays still.
22
+ * @param icon - Icon node.
23
+ * @returns Element name, the text of a text node, or an empty string.
24
+ */
25
+ function getIconKey(icon) {
26
+ if (!isValidElement(icon)) return icon == null || typeof icon === "boolean" ? "" : String(icon);
27
+ const elementType = icon.type;
28
+ return typeof elementType === "string" ? elementType : elementType?.displayName ?? elementType?.name ?? "icon";
29
+ }
30
+ /**
31
+ * Visible content of the main action: the icon and the morphing label, inside a slot whose width follows on a
32
+ * spring when either changes.
33
+ * @param props - Label, icon and whether the user prefers reduced motion.
34
+ * @returns Content hidden from assistive tech; the button names itself through `aria-label`.
35
+ */
36
+ function SplitButtonMainContent(t0) {
37
+ const $ = _c(17);
38
+ const { label, icon, reduceMotion } = t0;
39
+ const contentRef = useRef(null);
40
+ let t1;
41
+ if ($[0] !== icon) {
42
+ t1 = getIconKey(icon);
43
+ $[0] = icon;
44
+ $[1] = t1;
45
+ } else {
46
+ t1 = $[1];
47
+ }
48
+ const iconKey = t1;
49
+ const width = useMorphWidth(contentRef, `${iconKey}|${label}`, reduceMotion);
50
+ let t2;
51
+ if ($[2] !== width) {
52
+ t2 = { width };
53
+ $[2] = width;
54
+ $[3] = t2;
55
+ } else {
56
+ t2 = $[3];
57
+ }
58
+ let t3;
59
+ if ($[4] !== icon || $[5] !== iconKey || $[6] !== reduceMotion) {
60
+ t3 = icon ? /* @__PURE__ */ _jsx("span", {
61
+ className: "inline-grid flex-none place-items-center",
62
+ children: /* @__PURE__ */ _jsx(AnimatePresence, {
63
+ initial: false,
64
+ children: /* @__PURE__ */ _jsx(motion.span, {
65
+ className: "col-start-1 row-start-1 inline-flex items-center justify-center",
66
+ initial: reduceMotion ? reducedEnter : iconEnter,
67
+ animate: restState,
68
+ exit: reduceMotion ? reducedExit : iconExit,
69
+ transition: reduceMotion ? reducedTransition : iconTransition,
70
+ children: icon
71
+ }, iconKey)
72
+ })
73
+ }) : null;
74
+ $[4] = icon;
75
+ $[5] = iconKey;
76
+ $[6] = reduceMotion;
77
+ $[7] = t3;
78
+ } else {
79
+ t3 = $[7];
80
+ }
81
+ let t4;
82
+ if ($[8] !== label || $[9] !== reduceMotion) {
83
+ t4 = /* @__PURE__ */ _jsx(MorphText, {
84
+ text: label,
85
+ reduceMotion
86
+ });
87
+ $[8] = label;
88
+ $[9] = reduceMotion;
89
+ $[10] = t4;
90
+ } else {
91
+ t4 = $[10];
92
+ }
93
+ let t5;
94
+ if ($[11] !== t3 || $[12] !== t4) {
95
+ t5 = /* @__PURE__ */ _jsxs("span", {
96
+ ref: contentRef,
97
+ className: "inline-flex flex-none items-center gap-2 whitespace-nowrap",
98
+ children: [t3, t4]
99
+ });
100
+ $[11] = t3;
101
+ $[12] = t4;
102
+ $[13] = t5;
103
+ } else {
104
+ t5 = $[13];
105
+ }
106
+ let t6;
107
+ if ($[14] !== t2 || $[15] !== t5) {
108
+ t6 = /* @__PURE__ */ _jsx(motion.span, {
109
+ "data-slot": "split-button-label",
110
+ className: "inline-flex min-w-0 items-center data-morphing:[clip-path:inset(-50%_calc(var(--spacing)*-2))]",
111
+ style: t2,
112
+ "aria-hidden": "true",
113
+ children: t5
114
+ });
115
+ $[14] = t2;
116
+ $[15] = t5;
117
+ $[16] = t6;
118
+ } else {
119
+ t6 = $[16];
120
+ }
121
+ return t6;
122
+ }
123
+ /**
124
+ * A main action joined to a menu of related actions, such as Copy page with Copy as Markdown and Open in a new tab.
125
+ * The main half announces label changes politely; the menu half opens a `DropdownMenu` aligned to its end.
126
+ * @param props - Main action, its icon, the menu actions, the variant and accessible names.
127
+ * @returns The joined pair of buttons and their menu.
128
+ */
129
+ function SplitButton(t0) {
130
+ const $ = _c(39);
131
+ const { label, actions, onClick, disabled, icon, variant: t1, menuLabel, className } = t0;
132
+ const variant = t1 === undefined ? "primary" : t1;
133
+ const reduceMotion = usePrefersReducedMotion();
134
+ const size = SPLIT_BUTTON_SIZE_BY_VARIANT[variant];
135
+ let t2;
136
+ if ($[0] !== className) {
137
+ t2 = cn("inline-flex items-stretch", className);
138
+ $[0] = className;
139
+ $[1] = t2;
140
+ } else {
141
+ t2 = $[1];
142
+ }
143
+ let t3;
144
+ if ($[2] !== icon || $[3] !== label || $[4] !== reduceMotion) {
145
+ t3 = /* @__PURE__ */ _jsx(SplitButtonMainContent, {
146
+ label,
147
+ icon,
148
+ reduceMotion
149
+ });
150
+ $[2] = icon;
151
+ $[3] = label;
152
+ $[4] = reduceMotion;
153
+ $[5] = t3;
154
+ } else {
155
+ t3 = $[5];
156
+ }
157
+ let t4;
158
+ if ($[6] !== disabled || $[7] !== label || $[8] !== onClick || $[9] !== size || $[10] !== t3 || $[11] !== variant) {
159
+ t4 = /* @__PURE__ */ _jsx(Button, {
160
+ variant,
161
+ size,
162
+ "aria-label": label,
163
+ className: "rounded-r-none border-r-0",
164
+ disabled,
165
+ onClick,
166
+ children: t3
167
+ });
168
+ $[6] = disabled;
169
+ $[7] = label;
170
+ $[8] = onClick;
171
+ $[9] = size;
172
+ $[10] = t3;
173
+ $[11] = variant;
174
+ $[12] = t4;
175
+ } else {
176
+ t4 = $[12];
177
+ }
178
+ const t5 = menuLabel ?? `Más acciones de ${label}`;
179
+ const t6 = variant === "primary" ? "border-l-[color-mix(in_oklab,var(--background)_18%,var(--foreground))]" : "w-(--control-height-sm) border-l-border";
180
+ let t7;
181
+ if ($[13] !== t6) {
182
+ t7 = cn("w-(--control-height-md) rounded-l-none px-0 [&_svg]:transition-transform [&_svg]:duration-(--duration-fast) data-[state=open]:[&_svg]:rotate-180 motion-reduce:[&_svg]:transition-none", t6);
183
+ $[13] = t6;
184
+ $[14] = t7;
185
+ } else {
186
+ t7 = $[14];
187
+ }
188
+ let t8;
189
+ if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
190
+ t8 = /* @__PURE__ */ _jsx(ChevronDown, {
191
+ strokeWidth: 1.75,
192
+ "aria-hidden": "true"
193
+ });
194
+ $[15] = t8;
195
+ } else {
196
+ t8 = $[15];
197
+ }
198
+ let t9;
199
+ if ($[16] !== size || $[17] !== t5 || $[18] !== t7 || $[19] !== variant) {
200
+ t9 = /* @__PURE__ */ _jsx(Button, {
201
+ variant,
202
+ size,
203
+ "aria-label": t5,
204
+ className: t7,
205
+ children: t8
206
+ });
207
+ $[16] = size;
208
+ $[17] = t5;
209
+ $[18] = t7;
210
+ $[19] = variant;
211
+ $[20] = t9;
212
+ } else {
213
+ t9 = $[20];
214
+ }
215
+ let t10;
216
+ if ($[21] !== disabled || $[22] !== t9) {
217
+ t10 = /* @__PURE__ */ _jsx(DropdownMenuTrigger, {
218
+ asChild: true,
219
+ disabled,
220
+ children: t9
221
+ });
222
+ $[21] = disabled;
223
+ $[22] = t9;
224
+ $[23] = t10;
225
+ } else {
226
+ t10 = $[23];
227
+ }
228
+ let t11;
229
+ if ($[24] !== label) {
230
+ t11 = /* @__PURE__ */ _jsx("span", {
231
+ className: "sr-only",
232
+ "aria-live": "polite",
233
+ children: label
234
+ });
235
+ $[24] = label;
236
+ $[25] = t11;
237
+ } else {
238
+ t11 = $[25];
239
+ }
240
+ let t12;
241
+ if ($[26] !== t10 || $[27] !== t11 || $[28] !== t2 || $[29] !== t4 || $[30] !== variant) {
242
+ t12 = /* @__PURE__ */ _jsxs("div", {
243
+ role: "group",
244
+ "data-slot": "split-button",
245
+ "data-variant": variant,
246
+ className: t2,
247
+ children: [
248
+ t4,
249
+ t10,
250
+ t11
251
+ ]
252
+ });
253
+ $[26] = t10;
254
+ $[27] = t11;
255
+ $[28] = t2;
256
+ $[29] = t4;
257
+ $[30] = variant;
258
+ $[31] = t12;
259
+ } else {
260
+ t12 = $[31];
261
+ }
262
+ let t13;
263
+ if ($[32] !== actions) {
264
+ t13 = actions.map(_temp);
265
+ $[32] = actions;
266
+ $[33] = t13;
267
+ } else {
268
+ t13 = $[33];
269
+ }
270
+ let t14;
271
+ if ($[34] !== t13) {
272
+ t14 = /* @__PURE__ */ _jsx(DropdownMenuContent, {
273
+ align: "end",
274
+ sideOffset: 4,
275
+ collisionPadding: 12,
276
+ loop: true,
277
+ children: t13
278
+ });
279
+ $[34] = t13;
280
+ $[35] = t14;
281
+ } else {
282
+ t14 = $[35];
283
+ }
284
+ let t15;
285
+ if ($[36] !== t12 || $[37] !== t14) {
286
+ t15 = /* @__PURE__ */ _jsxs(DropdownMenu, { children: [t12, t14] });
287
+ $[36] = t12;
288
+ $[37] = t14;
289
+ $[38] = t15;
290
+ } else {
291
+ t15 = $[38];
292
+ }
293
+ return t15;
294
+ }
295
+ function _temp(action) {
296
+ return /* @__PURE__ */ _jsxs(DropdownMenuItem, {
297
+ variant: action.destructive ? "destructive" : "default",
298
+ disabled: action.disabled,
299
+ onSelect: action.onSelect,
300
+ children: [action.icon ? /* @__PURE__ */ _jsx("span", {
301
+ "aria-hidden": "true",
302
+ children: action.icon
303
+ }) : null, action.label]
304
+ }, action.label);
305
+ }
306
+ export { SplitButton };
@@ -0,0 +1,3 @@
1
+ import type { SVGProps } from "react";
2
+ declare const WhatsappIcon: (props: SVGProps<SVGSVGElement>) => import("react").JSX.Element;
3
+ export { WhatsappIcon };