@humain/ui 2.4.2 → 2.4.3

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 (153) hide show
  1. package/dist/index194.js +6 -8
  2. package/dist/index194.js.map +1 -1
  3. package/dist/index24.js +1 -1
  4. package/dist/index24.js.map +1 -1
  5. package/dist/styles.css +1 -1
  6. package/dist/wc/AIClarificationCard.js +1 -1
  7. package/dist/wc/AIContainer.js +1 -1
  8. package/dist/wc/AIForm.js +17 -17
  9. package/dist/wc/AIInput.js +1 -1
  10. package/dist/wc/AIMermaidDiagram.js +1 -1
  11. package/dist/wc/AIMessage.js +1 -1
  12. package/dist/wc/AIScrollButton.js +4 -4
  13. package/dist/wc/AIToolCall.js +5 -5
  14. package/dist/wc/AppSidebar.constants.js +1 -1
  15. package/dist/wc/AvatarFallback.js +5 -5
  16. package/dist/wc/CheckboxIndicator.js +7 -7
  17. package/dist/wc/CollapsiblePanel.js +1 -1
  18. package/dist/wc/DialogTrigger.js +9 -9
  19. package/dist/wc/DropdownMenu.js +16 -16
  20. package/dist/wc/MenuSubmenuTrigger.js +31 -31
  21. package/dist/wc/PopoverDescription.js +30 -30
  22. package/dist/wc/PrehydrationScript.js +1 -1
  23. package/dist/wc/Select.js +18 -18
  24. package/dist/wc/SelectSeparator.js +72 -72
  25. package/dist/wc/SelectSeparator.js.map +1 -1
  26. package/dist/wc/Tabs.js +18 -18
  27. package/dist/wc/TooltipProvider.js +9 -9
  28. package/dist/wc/chart.js +1 -1
  29. package/dist/wc/chunk-75Z2AOVW.js +39 -39
  30. package/dist/wc/chunk-OSK3NFVY.js +32 -32
  31. package/dist/wc/command.js +4 -4
  32. package/dist/wc/form-field.js +1 -1
  33. package/dist/wc/form-fieldset.js +5 -5
  34. package/dist/wc/hf-accordion-card.js +4 -4
  35. package/dist/wc/hf-accordion.js +6 -6
  36. package/dist/wc/hf-ai-feedback-bar.js +5 -5
  37. package/dist/wc/hf-ai-reasoning-block.js +6 -6
  38. package/dist/wc/hf-ai-system-message.js +1 -1
  39. package/dist/wc/hf-ai-tool-run.js +1 -1
  40. package/dist/wc/hf-area-chart.js +15 -15
  41. package/dist/wc/hf-autocomplete.js +36 -36
  42. package/dist/wc/hf-bar-chart.js +4 -4
  43. package/dist/wc/hf-calendar.js +4 -4
  44. package/dist/wc/hf-carousel.js +1 -1
  45. package/dist/wc/hf-context-menu.js +8 -8
  46. package/dist/wc/hf-donut-chart.js +10 -10
  47. package/dist/wc/hf-empty-state.js +87 -88
  48. package/dist/wc/hf-empty-state.js.map +1 -1
  49. package/dist/wc/hf-history.js +4 -4
  50. package/dist/wc/hf-horizontal-bar-chart.js +7 -7
  51. package/dist/wc/hf-hover-card.js +6 -6
  52. package/dist/wc/hf-line-chart.js +4 -4
  53. package/dist/wc/hf-metric-card.js +5 -5
  54. package/dist/wc/hf-metric-item.js +8 -8
  55. package/dist/wc/hf-metric-item.js.map +1 -1
  56. package/dist/wc/hf-nav-account-menu.js +4 -4
  57. package/dist/wc/hf-notification-panel.js +2 -2
  58. package/dist/wc/hf-pie-chart.js +17 -17
  59. package/dist/wc/hf-radar-chart.js +16 -16
  60. package/dist/wc/hf-section-header.js +6 -6
  61. package/dist/wc/hf-sheet.js +1 -1
  62. package/dist/wc/hf-sparkline-chart.js +5 -5
  63. package/dist/wc/hf-steps.js +6 -6
  64. package/dist/wc/journeyDiagram-3NMN7TZE.js +10 -10
  65. package/dist/wc/pieDiagram-E7YTZNPT.js +16 -16
  66. package/dist/wc/popupStateMapping.js +53 -53
  67. package/dist/wc/popupStateMapping.js.map +1 -1
  68. package/dist/wc/selection-group.js +1 -1
  69. package/dist/wc/selection-group.js.map +1 -1
  70. package/dist/wc/{useOpenChangeComplete.js → stateAttributesMapping.js} +21 -21
  71. package/dist/wc/stateAttributesMapping.js.map +1 -0
  72. package/dist/wc/stateDiagram-D77RDMKH.js +3 -3
  73. package/dist/wc/timeline-definition-24CTP7MA.js +19 -19
  74. package/dist/wc/useCollapsiblePanel.js +3 -3
  75. package/dist/wc/usePopupHandleStore.js +4 -4
  76. package/dist/wc/useScrollLock.js +1 -1
  77. package/dist/wc/vendor/recharts.js +525 -524
  78. package/dist/wc/vendor/recharts.js.map +1 -1
  79. package/dist/wc/xychartDiagram-S5SC5T6Z.js +6 -6
  80. package/dist/wc-react/AIClarificationCard.js +1 -1
  81. package/dist/wc-react/AIContainer.js +1 -1
  82. package/dist/wc-react/AIForm.js +17 -17
  83. package/dist/wc-react/AIInput.js +1 -1
  84. package/dist/wc-react/AIMermaidDiagram.js +1 -1
  85. package/dist/wc-react/AIMessage.js +1 -1
  86. package/dist/wc-react/AIScrollButton.js +4 -4
  87. package/dist/wc-react/AIToolCall.js +5 -5
  88. package/dist/wc-react/AppSidebar.constants.js +1 -1
  89. package/dist/wc-react/AvatarFallback.js +5 -5
  90. package/dist/wc-react/CheckboxIndicator.js +7 -7
  91. package/dist/wc-react/CollapsiblePanel.js +1 -1
  92. package/dist/wc-react/DialogTrigger.js +9 -9
  93. package/dist/wc-react/DropdownMenu.js +16 -16
  94. package/dist/wc-react/FloatingPortalLite.js +3 -3
  95. package/dist/wc-react/MenuSubmenuTrigger.js +31 -31
  96. package/dist/wc-react/PopoverDescription.js +31 -31
  97. package/dist/wc-react/PrehydrationScript.js +1 -1
  98. package/dist/wc-react/Select.js +18 -18
  99. package/dist/wc-react/SelectSeparator.js +71 -70
  100. package/dist/wc-react/SelectSeparator.js.map +1 -1
  101. package/dist/wc-react/Tabs.js +18 -18
  102. package/dist/wc-react/TooltipProvider.js +9 -9
  103. package/dist/wc-react/chart.js +1 -1
  104. package/dist/wc-react/chunk-75Z2AOVW.js +39 -39
  105. package/dist/wc-react/chunk-OSK3NFVY.js +32 -32
  106. package/dist/wc-react/command.js +4 -4
  107. package/dist/wc-react/form-field.js +1 -1
  108. package/dist/wc-react/form-fieldset.js +77 -77
  109. package/dist/wc-react/hf-accordion-card.js +4 -4
  110. package/dist/wc-react/hf-accordion.js +6 -6
  111. package/dist/wc-react/hf-ai-feedback-bar.js +5 -5
  112. package/dist/wc-react/hf-ai-reasoning-block.js +6 -6
  113. package/dist/wc-react/hf-ai-system-message.js +1 -1
  114. package/dist/wc-react/hf-ai-tool-run.js +1 -1
  115. package/dist/wc-react/hf-autocomplete.js +37 -37
  116. package/dist/wc-react/hf-calendar.js +4 -4
  117. package/dist/wc-react/hf-carousel.js +1 -1
  118. package/dist/wc-react/hf-context-menu.js +8 -8
  119. package/dist/wc-react/hf-data-table.js +1 -1
  120. package/dist/wc-react/hf-empty-state.js +87 -88
  121. package/dist/wc-react/hf-empty-state.js.map +1 -1
  122. package/dist/wc-react/hf-history.js +4 -4
  123. package/dist/wc-react/hf-hover-card.js +6 -6
  124. package/dist/wc-react/hf-metric-item.js +6 -6
  125. package/dist/wc-react/hf-metric-item.js.map +1 -1
  126. package/dist/wc-react/hf-nav-account-menu.js +4 -4
  127. package/dist/wc-react/hf-notification-panel.js +2 -2
  128. package/dist/wc-react/hf-section-header.js +6 -6
  129. package/dist/wc-react/hf-sheet.js +1 -1
  130. package/dist/wc-react/hf-steps.js +5 -5
  131. package/dist/wc-react/journeyDiagram-3NMN7TZE.js +10 -10
  132. package/dist/wc-react/pieDiagram-E7YTZNPT.js +16 -16
  133. package/dist/wc-react/popupStateMapping.js +54 -54
  134. package/dist/wc-react/popupStateMapping.js.map +1 -1
  135. package/dist/wc-react/selection-group.js +1 -1
  136. package/dist/wc-react/selection-group.js.map +1 -1
  137. package/dist/wc-react/{useOpenChangeComplete.js → stateAttributesMapping.js} +19 -19
  138. package/dist/wc-react/stateAttributesMapping.js.map +1 -0
  139. package/dist/wc-react/stateDiagram-D77RDMKH.js +3 -3
  140. package/dist/wc-react/timeline-definition-24CTP7MA.js +19 -19
  141. package/dist/wc-react/useCollapsiblePanel.js +3 -3
  142. package/dist/wc-react/usePopupHandleStore.js +3 -3
  143. package/dist/wc-react/useScrollLock.js +1 -1
  144. package/dist/wc-react/vendor/recharts.js +525 -524
  145. package/dist/wc-react/vendor/recharts.js.map +1 -1
  146. package/dist/wc-react/xychartDiagram-S5SC5T6Z.js +6 -6
  147. package/package.json +1 -1
  148. package/skills/humain-ui/SKILL.md +1 -1
  149. package/skills/humain-ui-wc/SKILL.md +1 -1
  150. package/skills/humain-ui-wc.skill +0 -0
  151. package/skills/humain-ui.skill +0 -0
  152. package/dist/wc/useOpenChangeComplete.js.map +0 -1
  153. package/dist/wc-react/useOpenChangeComplete.js.map +0 -1
package/dist/index194.js CHANGED
@@ -47,12 +47,6 @@ var iconGlyphSizeClass = {
47
47
  md: "size-4",
48
48
  lg: "size-5"
49
49
  };
50
- var illustrationIconCenterClass = {
51
- cloud: "top-[58%]",
52
- box: "top-[58%]",
53
- documents: "top-[60%]",
54
- "credit-card": "top-[60%]"
55
- };
56
50
  var illustrationCircleSizeClass = {
57
51
  sm: "size-[104px]",
58
52
  md: "size-32",
@@ -191,6 +185,7 @@ function DecorativeDots({ tone }) {
191
185
  }
192
186
  function CloudShape({ accentId, shadeId, tone }) {
193
187
  return /* @__PURE__ */ jsxs("g", {
188
+ transform: "translate(10.5 14.5)",
194
189
  className: "drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]",
195
190
  children: [/* @__PURE__ */ jsx("path", {
196
191
  d: "M54 110c-21 0-38-14-38-32 0-16 14-30 33-32 8-19 27-31 49-31 27 0 50 19 55 43 17 3 30 16 30 32 0 19-18 34-40 34H55c-1 0-1-14-1-14Z",
@@ -204,6 +199,7 @@ function CloudShape({ accentId, shadeId, tone }) {
204
199
  }
205
200
  function BoxShape({ accentId, shadeId }) {
206
201
  return /* @__PURE__ */ jsxs("g", {
202
+ transform: "translate(-19.5)",
207
203
  className: "drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]",
208
204
  children: [
209
205
  /* @__PURE__ */ jsx("path", {
@@ -233,6 +229,7 @@ function BoxShape({ accentId, shadeId }) {
233
229
  }
234
230
  function DocumentsShape({ accentId, shadeId }) {
235
231
  return /* @__PURE__ */ jsxs("g", {
232
+ transform: "translate(0 -0.5)",
236
233
  className: "drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]",
237
234
  children: [
238
235
  /* @__PURE__ */ jsxs("g", {
@@ -282,6 +279,7 @@ function DocumentsShape({ accentId, shadeId }) {
282
279
  }
283
280
  function CreditCardShape({ accentId, shadeId }) {
284
281
  return /* @__PURE__ */ jsxs("g", {
282
+ transform: "translate(0 -5)",
285
283
  className: "drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]",
286
284
  children: [
287
285
  /* @__PURE__ */ jsx("rect", {
@@ -355,7 +353,7 @@ var EmptyStateIllustration = React$1.forwardRef(({ className, size = "sm", varia
355
353
  "data-slot": "empty-state-illustration-background",
356
354
  "data-testid": "empty-state-illustration-background",
357
355
  "data-centered": "true",
358
- className: cn("absolute left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full", isPrimary ? "bg-primary/20" : "bg-muted/80", illustrationCircleSizeClass[size], illustrationIconCenterClass[variant])
356
+ className: cn("absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full", isPrimary ? "bg-primary/20" : "bg-muted/80", illustrationCircleSizeClass[size])
359
357
  }),
360
358
  /* @__PURE__ */ jsx(DecorativeDots, { tone }),
361
359
  /* @__PURE__ */ jsxs("svg", {
@@ -411,7 +409,7 @@ var EmptyStateIllustration = React$1.forwardRef(({ className, size = "sm", varia
411
409
  "data-slot": "empty-state-illustration-icon",
412
410
  "data-testid": "empty-state-illustration-icon",
413
411
  "data-centered": "true",
414
- className: cn("absolute left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-xl bg-primary/10 text-primary shadow-xs backdrop-blur-md supports-backdrop-filter:backdrop-blur-md [&>svg]:shrink-0", !isPrimary && "bg-muted text-muted-foreground", illustrationIconSizeClass[size], illustrationIconCenterClass[variant]),
412
+ className: cn("absolute left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-xl bg-primary/10 text-primary shadow-xs backdrop-blur-md supports-backdrop-filter:backdrop-blur-md [&>svg]:shrink-0", !isPrimary && "bg-muted text-muted-foreground", illustrationIconSizeClass[size]),
415
413
  children: /* @__PURE__ */ jsx(EmptyStateIconGlyph, {
416
414
  icon,
417
415
  size
@@ -1 +1 @@
1
- {"version":3,"file":"index194.js","names":[],"sources":["../src/components/organisms/content/EmptyState/EmptyState.tsx"],"sourcesContent":["import { cva } from 'class-variance-authority';\nimport { Heart, Search } from 'lucide-react';\nimport * as React from 'react';\nimport { Button } from '@/components/atoms/buttons/Button';\nimport { FeaturedIcon } from '@/components/molecules/data/FeaturedIcon';\nimport {\n type FileExtension,\n FileTypeIcon,\n type SimpleFileType,\n} from '@/components/molecules/files/FileTypeIcon';\nimport { cn } from '@/lib/utils';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type EmptyStateSize = 'sm' | 'md' | 'lg';\nexport type EmptyStateMedia =\n | 'featured-icon'\n | 'illustration'\n | 'file-type-icon'\n | 'none';\nexport type EmptyStateBackgroundPatternVariant =\n | 'circles'\n | 'grid'\n | 'grid-dot'\n | 'squares'\n | 'none';\nexport type EmptyStateIllustrationVariant =\n | 'cloud'\n | 'box'\n | 'documents'\n | 'credit-card';\nexport type EmptyStateTone = 'primary' | 'gray';\n\nexport interface EmptyStateActionConfig {\n label: React.ReactNode;\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n startIcon?: React.ReactNode;\n disabled?: boolean;\n loading?: boolean;\n 'aria-label'?: string;\n}\n\n// ============================================================================\n// Shared maps\n// ============================================================================\n\nconst patternSizeClass: Record<EmptyStateSize, string> = {\n sm: 'size-[336px]',\n md: 'size-[480px]',\n lg: 'size-[768px]',\n};\n\nconst patternGridSize: Record<EmptyStateSize, string> = {\n sm: '24px 24px',\n md: '32px 32px',\n lg: '48px 48px',\n};\n\nconst illustrationSizeClass: Record<\n EmptyStateSize,\n Record<EmptyStateIllustrationVariant, string>\n> = {\n sm: {\n cloud: 'h-[118px] w-[152px]',\n box: 'h-[124px] w-[152px]',\n documents: 'h-[118px] w-[152px]',\n 'credit-card': 'h-[118px] w-[152px]',\n },\n md: {\n cloud: 'h-32 w-[172px]',\n box: 'h-[136px] w-[172px]',\n documents: 'h-32 w-[172px]',\n 'credit-card': 'h-[134px] w-[172px]',\n },\n lg: {\n cloud: 'h-40 w-[220px]',\n box: 'h-[168px] w-[220px]',\n documents: 'h-40 w-[220px]',\n 'credit-card': 'h-40 w-[220px]',\n },\n};\n\nconst illustrationIconSizeClass: Record<EmptyStateSize, string> = {\n sm: 'p-2',\n md: 'p-2.5',\n lg: 'p-2.5',\n};\n\nconst iconGlyphSizeClass: Record<EmptyStateSize, string> = {\n sm: 'size-4',\n md: 'size-4',\n lg: 'size-5',\n};\n\nconst illustrationIconCenterClass: Record<\n EmptyStateIllustrationVariant,\n string\n> = {\n cloud: 'top-[58%]',\n box: 'top-[58%]',\n documents: 'top-[60%]',\n 'credit-card': 'top-[60%]',\n};\n\nconst illustrationCircleSizeClass: Record<EmptyStateSize, string> = {\n sm: 'size-[104px]',\n md: 'size-32',\n lg: 'size-40',\n};\n\nconst fileIconWrapSizeClass: Record<EmptyStateSize, string> = {\n sm: 'size-20',\n md: 'size-24',\n lg: 'size-28',\n};\n\nconst textGapClass: Record<EmptyStateSize, string> = {\n sm: 'gap-1',\n md: 'gap-2',\n lg: 'gap-2',\n};\n\nconst mediaGapClass: Record<EmptyStateSize, string> = {\n sm: 'gap-4',\n md: 'gap-5',\n lg: 'gap-5',\n};\n\nconst contentGapClass: Record<EmptyStateSize, string> = {\n sm: 'gap-6',\n md: 'gap-8',\n lg: 'gap-8',\n};\n\nconst featuredIconSize: Record<EmptyStateSize, 'sm' | 'md' | 'lg'> = {\n sm: 'sm',\n md: 'md',\n lg: 'lg',\n};\n\nconst fileIconSize: Record<EmptyStateSize, 'sm' | 'md' | 'lg'> = {\n sm: 'md',\n md: 'md',\n lg: 'md',\n};\n\nconst headingTag = {\n 2: 'h2',\n 3: 'h3',\n 4: 'h4',\n} as const;\n\nfunction EmptyStateIconGlyph({\n icon,\n size,\n}: {\n icon: React.ReactNode;\n size: EmptyStateSize;\n}) {\n return (\n <span\n data-slot=\"empty-state-icon-glyph\"\n data-testid=\"empty-state-icon-glyph\"\n data-centered=\"true\"\n aria-hidden=\"true\"\n className={cn(\n 'inline-flex shrink-0 items-center justify-center leading-none [line-height:0] [&>svg]:block [&>svg]:size-full [&>svg]:shrink-0',\n iconGlyphSizeClass[size],\n )}\n >\n {icon}\n </span>\n );\n}\n\n// ============================================================================\n// Background Pattern\n// ============================================================================\n\nexport interface EmptyStateBackgroundPatternProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n size?: EmptyStateSize;\n variant?: EmptyStateBackgroundPatternVariant;\n}\n\nconst gridPatternStyle = (\n size: EmptyStateSize,\n dot = false,\n): React.CSSProperties => ({\n backgroundImage: dot\n ? 'radial-gradient(circle, color-mix(in oklch, var(--border) 70%, transparent) 1px, transparent 1px)'\n : [\n 'linear-gradient(to right, color-mix(in oklch, var(--border) 54%, transparent) 1px, transparent 1px)',\n 'linear-gradient(to bottom, color-mix(in oklch, var(--border) 54%, transparent) 1px, transparent 1px)',\n ].join(', '),\n backgroundSize: patternGridSize[size],\n});\n\nconst squaresBySize: Record<EmptyStateSize, number[]> = {\n sm: [96, 144, 192, 240, 288, 336],\n md: [96, 160, 224, 288, 352, 416, 480],\n lg: [96, 192, 288, 384, 480, 576, 672, 768],\n};\n\nexport const EmptyStateBackgroundPattern = React.forwardRef<\n HTMLDivElement,\n EmptyStateBackgroundPatternProps\n>(({ className, size = 'sm', variant = 'circles', style, ...props }, ref) => {\n if (variant === 'none') {\n return null;\n }\n\n return (\n <div\n ref={ref}\n data-slot=\"empty-state-background-pattern\"\n data-testid=\"empty-state-pattern\"\n data-size={size}\n data-variant={variant}\n aria-hidden=\"true\"\n className={cn(\n 'pointer-events-none absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 overflow-hidden opacity-75',\n patternSizeClass[size],\n className,\n )}\n style={style}\n {...props}\n >\n <div className=\"absolute inset-0 bg-[radial-gradient(circle_at_center,var(--background)_0%,transparent_68%)]\" />\n\n {variant === 'circles' && (\n <div className=\"absolute inset-0\">\n {Array.from({ length: 7 }, (_, index) => (\n <span\n key={index}\n className=\"absolute left-1/2 top-1/2 rounded-full border border-border/60\"\n style={{\n width: `${(index + 1) * 14}%`,\n height: `${(index + 1) * 14}%`,\n transform: 'translate(-50%, -50%)',\n }}\n />\n ))}\n </div>\n )}\n\n {(variant === 'grid' || variant === 'grid-dot') && (\n <div\n className=\"absolute inset-0 opacity-70 [mask-image:radial-gradient(circle_at_center,black_0%,black_48%,transparent_76%)]\"\n style={gridPatternStyle(size, variant === 'grid-dot')}\n />\n )}\n\n {variant === 'squares' && (\n <div className=\"absolute inset-0\">\n {squaresBySize[size].map((squareSize) => (\n <span\n key={squareSize}\n className=\"absolute left-1/2 top-1/2 rounded-xl border border-border/55\"\n style={{\n width: squareSize,\n height: squareSize,\n transform: 'translate(-50%, -50%) rotate(-12.5deg)',\n }}\n />\n ))}\n </div>\n )}\n </div>\n );\n});\n\nEmptyStateBackgroundPattern.displayName = 'EmptyStateBackgroundPattern';\n\n// ============================================================================\n// Illustration\n// ============================================================================\n\nexport interface EmptyStateIllustrationProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n size?: EmptyStateSize;\n variant?: EmptyStateIllustrationVariant;\n tone?: EmptyStateTone;\n icon?: React.ReactNode;\n}\n\nfunction DecorativeDots({ tone }: { tone: EmptyStateTone }) {\n const dotClassName =\n tone === 'primary' ? 'bg-primary/70' : 'bg-muted-foreground/10';\n\n return (\n <>\n <span\n className={cn(\n 'absolute left-[7%] top-[8%] size-2 rounded-full',\n dotClassName,\n )}\n />\n <span\n className={cn(\n 'absolute right-[6%] top-[18%] size-3 rounded-full',\n dotClassName,\n )}\n />\n <span\n className={cn(\n 'absolute bottom-[10%] left-[8%] size-3 rounded-full',\n dotClassName,\n )}\n />\n <span\n className={cn(\n 'absolute bottom-[18%] right-[13%] size-2 rounded-full',\n dotClassName,\n )}\n />\n </>\n );\n}\n\nfunction CloudShape({\n accentId,\n shadeId,\n tone,\n}: {\n accentId: string;\n shadeId: string;\n tone: EmptyStateTone;\n}) {\n return (\n <g className=\"drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]\">\n <path\n d=\"M54 110c-21 0-38-14-38-32 0-16 14-30 33-32 8-19 27-31 49-31 27 0 50 19 55 43 17 3 30 16 30 32 0 19-18 34-40 34H55c-1 0-1-14-1-14Z\"\n fill={`url(#${shadeId})`}\n />\n <path\n d=\"M68 106c-18 0-32-12-32-27 0-13 11-24 27-26 7-16 23-26 42-26 23 0 42 16 46 36 15 3 26 14 26 28 0 16-15 29-34 29H68v-14Z\"\n fill={`url(#${accentId})`}\n opacity={tone === 'primary' ? 0.78 : 0.36}\n />\n </g>\n );\n}\n\nfunction BoxShape({\n accentId,\n shadeId,\n}: {\n accentId: string;\n shadeId: string;\n}) {\n return (\n <g className=\"drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]\">\n <path d=\"M72 42 132 20l55 31-62 24-53-33Z\" fill={`url(#${accentId})`} />\n <path d=\"M72 42v72l53 34V75L72 42Z\" fill={`url(#${shadeId})`} />\n <path d=\"M125 75v73l62-35V51l-62 24Z\" fill=\"var(--card)\" />\n <path\n d=\"M132 20v33l24 14V34l-24-14Z\"\n fill=\"currentColor\"\n opacity=\"0.34\"\n />\n <path\n d=\"M72 42 132 20l55 31-62 24-53-33Z\"\n fill=\"none\"\n stroke=\"var(--border)\"\n />\n </g>\n );\n}\n\nfunction DocumentsShape({\n accentId,\n shadeId,\n}: {\n accentId: string;\n shadeId: string;\n}) {\n return (\n <g className=\"drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]\">\n <g transform=\"translate(44 48) rotate(-18)\">\n <rect\n width=\"58\"\n height=\"78\"\n rx=\"7\"\n fill={`url(#${shadeId})`}\n stroke=\"var(--border)\"\n />\n <path\n d=\"M15 21h28M15 35h21M15 49h28\"\n stroke=\"currentColor\"\n strokeOpacity=\"0.28\"\n />\n </g>\n <g transform=\"translate(83 32)\">\n <rect\n width=\"58\"\n height=\"88\"\n rx=\"7\"\n fill=\"var(--card)\"\n stroke=\"var(--border)\"\n />\n <path\n d=\"M16 26h28M16 41h22M16 56h28\"\n stroke=\"currentColor\"\n strokeOpacity=\"0.32\"\n />\n </g>\n <g transform=\"translate(121 47) rotate(18)\">\n <rect\n width=\"58\"\n height=\"78\"\n rx=\"7\"\n fill={`url(#${accentId})`}\n stroke=\"var(--border)\"\n />\n <path\n d=\"M15 21h28M15 35h21M15 49h28\"\n stroke=\"currentColor\"\n strokeOpacity=\"0.32\"\n />\n </g>\n </g>\n );\n}\n\nfunction CreditCardShape({\n accentId,\n shadeId,\n}: {\n accentId: string;\n shadeId: string;\n}) {\n return (\n <g className=\"drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]\">\n <rect\n x=\"42\"\n y=\"48\"\n width=\"136\"\n height=\"82\"\n rx=\"12\"\n fill={`url(#${shadeId})`}\n stroke=\"var(--border)\"\n />\n <rect\n x=\"42\"\n y=\"70\"\n width=\"136\"\n height=\"16\"\n fill={`url(#${accentId})`}\n opacity=\"0.72\"\n />\n <rect\n x=\"58\"\n y=\"104\"\n width=\"28\"\n height=\"8\"\n rx=\"2\"\n fill=\"currentColor\"\n opacity=\"0.28\"\n />\n <rect\n x=\"58\"\n y=\"116\"\n width=\"58\"\n height=\"5\"\n rx=\"2.5\"\n fill=\"currentColor\"\n opacity=\"0.18\"\n />\n <circle cx=\"146\" cy=\"112\" r=\"10\" fill=\"currentColor\" opacity=\"0.24\" />\n <circle cx=\"158\" cy=\"112\" r=\"10\" fill=\"currentColor\" opacity=\"0.38\" />\n </g>\n );\n}\n\nexport const EmptyStateIllustration = React.forwardRef<\n HTMLDivElement,\n EmptyStateIllustrationProps\n>(\n (\n {\n className,\n size = 'sm',\n variant = 'cloud',\n tone = 'primary',\n icon = <Heart aria-hidden=\"true\" />,\n ...props\n },\n ref,\n ) => {\n const accentId = React.useId();\n const shadeId = React.useId();\n const isPrimary = tone === 'primary';\n\n return (\n <div\n ref={ref}\n data-slot=\"empty-state-illustration\"\n data-testid=\"empty-state-illustration\"\n data-size={size}\n data-variant={variant}\n data-tone={tone}\n aria-hidden=\"true\"\n className={cn(\n 'relative shrink-0 text-primary',\n !isPrimary && 'text-muted-foreground',\n illustrationSizeClass[size][variant],\n className,\n )}\n {...props}\n >\n <div\n data-slot=\"empty-state-illustration-background\"\n data-testid=\"empty-state-illustration-background\"\n data-centered=\"true\"\n className={cn(\n 'absolute left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full',\n isPrimary ? 'bg-primary/20' : 'bg-muted/80',\n illustrationCircleSizeClass[size],\n illustrationIconCenterClass[variant],\n )}\n />\n <DecorativeDots tone={tone} />\n <svg\n viewBox=\"0 0 220 168\"\n className=\"absolute inset-0 size-full overflow-visible\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <defs>\n <linearGradient id={accentId} x1=\"25\" y1=\"12\" x2=\"190\" y2=\"148\">\n <stop\n stopColor={isPrimary ? 'var(--primary)' : 'var(--muted)'}\n stopOpacity={isPrimary ? 0.34 : 0.74}\n />\n <stop stopColor=\"var(--card)\" stopOpacity={0.95} />\n </linearGradient>\n <linearGradient id={shadeId} x1=\"54\" y1=\"18\" x2=\"165\" y2=\"140\">\n <stop stopColor=\"var(--card)\" />\n <stop\n stopColor={\n isPrimary ? 'var(--primary)' : 'var(--muted-foreground)'\n }\n stopOpacity={isPrimary ? 0.18 : 0.14}\n />\n </linearGradient>\n </defs>\n\n {variant === 'cloud' && (\n <CloudShape accentId={accentId} shadeId={shadeId} tone={tone} />\n )}\n {variant === 'box' && (\n <BoxShape accentId={accentId} shadeId={shadeId} />\n )}\n {variant === 'documents' && (\n <DocumentsShape accentId={accentId} shadeId={shadeId} />\n )}\n {variant === 'credit-card' && (\n <CreditCardShape accentId={accentId} shadeId={shadeId} />\n )}\n </svg>\n <div\n data-slot=\"empty-state-illustration-icon\"\n data-testid=\"empty-state-illustration-icon\"\n data-centered=\"true\"\n className={cn(\n 'absolute left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-xl bg-primary/10 text-primary shadow-xs backdrop-blur-md supports-backdrop-filter:backdrop-blur-md [&>svg]:shrink-0',\n !isPrimary && 'bg-muted text-muted-foreground',\n illustrationIconSizeClass[size],\n illustrationIconCenterClass[variant],\n )}\n >\n <EmptyStateIconGlyph icon={icon} size={size} />\n </div>\n </div>\n );\n },\n);\n\nEmptyStateIllustration.displayName = 'EmptyStateIllustration';\n\n// ============================================================================\n// EmptyState\n// ============================================================================\n\nconst emptyStateVariants = cva(\n 'relative isolate mx-auto flex w-full max-w-[512px] items-center justify-center overflow-visible py-8 text-center',\n {\n variants: {\n size: {\n sm: 'min-h-[212px]',\n md: 'min-h-[280px]',\n lg: 'min-h-[360px]',\n },\n },\n defaultVariants: {\n size: 'sm',\n },\n },\n);\n\nexport interface EmptyStateProps\n extends Omit<React.HTMLAttributes<HTMLElement>, 'title'> {\n title: React.ReactNode;\n description?: React.ReactNode;\n size?: EmptyStateSize;\n media?: EmptyStateMedia;\n pattern?: EmptyStateBackgroundPatternVariant | 'auto';\n icon?: React.ReactNode;\n iconLabel?: string;\n illustrationVariant?: EmptyStateIllustrationVariant;\n illustrationTone?: EmptyStateTone;\n fileExtension?: FileExtension;\n fileType?: SimpleFileType;\n primaryAction?: EmptyStateActionConfig;\n secondaryAction?: EmptyStateActionConfig;\n actions?: React.ReactNode;\n headingLevel?: 2 | 3 | 4;\n}\n\nfunction resolvePattern(\n pattern: EmptyStateProps['pattern'],\n media: EmptyStateMedia,\n): EmptyStateBackgroundPatternVariant {\n if (!pattern || pattern === 'auto') {\n if (media === 'illustration') return 'grid';\n if (media === 'none') return 'none';\n return 'circles';\n }\n return pattern;\n}\n\nfunction renderEmptyStateAction(\n action: EmptyStateActionConfig,\n intent: 'primary' | 'secondary',\n) {\n const {\n label,\n onClick,\n startIcon,\n disabled,\n loading,\n 'aria-label': ariaLabel,\n } = action;\n\n return (\n <Button\n appearance={intent === 'primary' ? 'solid' : 'outline'}\n variant={intent === 'primary' ? 'primary' : 'secondary'}\n size=\"sm\"\n shape=\"rounded\"\n onClick={onClick}\n disabled={disabled}\n loading={loading}\n startIcon={startIcon}\n aria-label={ariaLabel}\n type=\"button\"\n >\n {label}\n </Button>\n );\n}\n\nexport const EmptyState = React.forwardRef<HTMLElement, EmptyStateProps>(\n (\n {\n className,\n title,\n description,\n size = 'sm',\n media = 'featured-icon',\n pattern = 'auto',\n icon,\n iconLabel,\n illustrationVariant = 'cloud',\n illustrationTone = 'gray',\n fileExtension,\n fileType = 'document',\n primaryAction,\n secondaryAction,\n actions,\n headingLevel = 3,\n ...props\n },\n ref,\n ) => {\n const Heading = headingTag[headingLevel];\n const resolvedPattern = resolvePattern(pattern, media);\n const defaultIcon = icon ?? <Search aria-hidden=\"true\" />;\n const hasActions = actions || primaryAction || secondaryAction;\n\n return (\n <section\n ref={ref}\n data-slot=\"empty-state\"\n aria-label={typeof title === 'string' ? title : 'Empty state'}\n className={cn(emptyStateVariants({ size }), className)}\n {...props}\n >\n <div\n data-slot=\"empty-state-content\"\n className={cn(\n 'relative z-10 flex min-w-0 flex-1 flex-col items-center',\n contentGapClass[size],\n )}\n >\n <div\n data-slot=\"empty-state-body\"\n className={cn(\n 'flex w-full flex-col items-center',\n mediaGapClass[size],\n )}\n >\n {media !== 'none' && (\n <div\n data-slot=\"empty-state-media\"\n data-testid=\"empty-state-media\"\n data-media={media}\n data-centered=\"true\"\n className=\"relative flex w-full min-w-0 justify-center\"\n >\n <EmptyStateBackgroundPattern\n size={size}\n variant={resolvedPattern}\n data-centered=\"true\"\n className=\"z-0\"\n />\n\n {media === 'featured-icon' && (\n <FeaturedIcon\n data-slot=\"empty-state-featured-icon\"\n size={featuredIconSize[size]}\n shape=\"rounded\"\n intent=\"default\"\n icon={\n <EmptyStateIconGlyph icon={defaultIcon} size={size} />\n }\n aria-label={iconLabel}\n className=\"relative z-10 delight-stagger motion-reduce:animate-none\"\n />\n )}\n\n {media === 'illustration' && (\n <EmptyStateIllustration\n size={size}\n variant={illustrationVariant}\n tone={illustrationTone}\n icon={defaultIcon}\n className=\"relative z-10 delight-stagger motion-reduce:animate-none\"\n />\n )}\n\n {media === 'file-type-icon' && (\n <div\n data-slot=\"empty-state-file-icon-wrap\"\n data-testid=\"empty-state-file-icon-wrap\"\n data-centered=\"true\"\n className={cn(\n 'relative z-10 flex items-center justify-center rounded-full bg-linear-[104deg,color-mix(in_oklch,var(--card)_60%,transparent),color-mix(in_oklch,var(--muted)_55%,transparent)] delight-stagger motion-reduce:animate-none',\n fileIconWrapSizeClass[size],\n )}\n >\n <div\n data-slot=\"empty-state-file-icon-optical-center\"\n data-testid=\"empty-state-file-icon-optical-center\"\n data-centered=\"true\"\n >\n <FileTypeIcon\n extension={fileExtension}\n fileType={fileExtension ? undefined : fileType}\n size={fileIconSize[size]}\n className=\"drop-shadow-[0_1px_2px_var(--shadow-xs-1-color)]\"\n />\n </div>\n </div>\n )}\n </div>\n )}\n\n <div\n data-slot=\"empty-state-text\"\n className={cn(\n 'flex w-full max-w-[352px] flex-col items-center text-center',\n textGapClass[size],\n )}\n >\n <Heading className=\"w-full text-base font-semibold leading-6 text-foreground\">\n {title}\n </Heading>\n {description && (\n <p className=\"w-full text-sm leading-5 text-secondary-foreground\">\n {description}\n </p>\n )}\n </div>\n </div>\n\n {hasActions && (\n <div\n data-slot=\"empty-state-actions\"\n className=\"flex flex-wrap items-center justify-center gap-3\"\n >\n {actions ?? (\n <>\n {secondaryAction &&\n renderEmptyStateAction(secondaryAction, 'secondary')}\n {primaryAction &&\n renderEmptyStateAction(primaryAction, 'primary')}\n </>\n )}\n </div>\n )}\n </div>\n </section>\n );\n },\n);\n\nEmptyState.displayName = 'EmptyState';\n"],"mappings":"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"}
1
+ {"version":3,"file":"index194.js","names":[],"sources":["../src/components/organisms/content/EmptyState/EmptyState.tsx"],"sourcesContent":["import { cva } from 'class-variance-authority';\nimport { Heart, Search } from 'lucide-react';\nimport * as React from 'react';\nimport { Button } from '@/components/atoms/buttons/Button';\nimport { FeaturedIcon } from '@/components/molecules/data/FeaturedIcon';\nimport {\n type FileExtension,\n FileTypeIcon,\n type SimpleFileType,\n} from '@/components/molecules/files/FileTypeIcon';\nimport { cn } from '@/lib/utils';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type EmptyStateSize = 'sm' | 'md' | 'lg';\nexport type EmptyStateMedia =\n | 'featured-icon'\n | 'illustration'\n | 'file-type-icon'\n | 'none';\nexport type EmptyStateBackgroundPatternVariant =\n | 'circles'\n | 'grid'\n | 'grid-dot'\n | 'squares'\n | 'none';\nexport type EmptyStateIllustrationVariant =\n | 'cloud'\n | 'box'\n | 'documents'\n | 'credit-card';\nexport type EmptyStateTone = 'primary' | 'gray';\n\nexport interface EmptyStateActionConfig {\n label: React.ReactNode;\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n startIcon?: React.ReactNode;\n disabled?: boolean;\n loading?: boolean;\n 'aria-label'?: string;\n}\n\n// ============================================================================\n// Shared maps\n// ============================================================================\n\nconst patternSizeClass: Record<EmptyStateSize, string> = {\n sm: 'size-[336px]',\n md: 'size-[480px]',\n lg: 'size-[768px]',\n};\n\nconst patternGridSize: Record<EmptyStateSize, string> = {\n sm: '24px 24px',\n md: '32px 32px',\n lg: '48px 48px',\n};\n\nconst illustrationSizeClass: Record<\n EmptyStateSize,\n Record<EmptyStateIllustrationVariant, string>\n> = {\n sm: {\n cloud: 'h-[118px] w-[152px]',\n box: 'h-[124px] w-[152px]',\n documents: 'h-[118px] w-[152px]',\n 'credit-card': 'h-[118px] w-[152px]',\n },\n md: {\n cloud: 'h-32 w-[172px]',\n box: 'h-[136px] w-[172px]',\n documents: 'h-32 w-[172px]',\n 'credit-card': 'h-[134px] w-[172px]',\n },\n lg: {\n cloud: 'h-40 w-[220px]',\n box: 'h-[168px] w-[220px]',\n documents: 'h-40 w-[220px]',\n 'credit-card': 'h-40 w-[220px]',\n },\n};\n\nconst illustrationIconSizeClass: Record<EmptyStateSize, string> = {\n sm: 'p-2',\n md: 'p-2.5',\n lg: 'p-2.5',\n};\n\nconst iconGlyphSizeClass: Record<EmptyStateSize, string> = {\n sm: 'size-4',\n md: 'size-4',\n lg: 'size-5',\n};\n\nconst illustrationCircleSizeClass: Record<EmptyStateSize, string> = {\n sm: 'size-[104px]',\n md: 'size-32',\n lg: 'size-40',\n};\n\nconst fileIconWrapSizeClass: Record<EmptyStateSize, string> = {\n sm: 'size-20',\n md: 'size-24',\n lg: 'size-28',\n};\n\nconst textGapClass: Record<EmptyStateSize, string> = {\n sm: 'gap-1',\n md: 'gap-2',\n lg: 'gap-2',\n};\n\nconst mediaGapClass: Record<EmptyStateSize, string> = {\n sm: 'gap-4',\n md: 'gap-5',\n lg: 'gap-5',\n};\n\nconst contentGapClass: Record<EmptyStateSize, string> = {\n sm: 'gap-6',\n md: 'gap-8',\n lg: 'gap-8',\n};\n\nconst featuredIconSize: Record<EmptyStateSize, 'sm' | 'md' | 'lg'> = {\n sm: 'sm',\n md: 'md',\n lg: 'lg',\n};\n\nconst fileIconSize: Record<EmptyStateSize, 'sm' | 'md' | 'lg'> = {\n sm: 'md',\n md: 'md',\n lg: 'md',\n};\n\nconst headingTag = {\n 2: 'h2',\n 3: 'h3',\n 4: 'h4',\n} as const;\n\nfunction EmptyStateIconGlyph({\n icon,\n size,\n}: {\n icon: React.ReactNode;\n size: EmptyStateSize;\n}) {\n return (\n <span\n data-slot=\"empty-state-icon-glyph\"\n data-testid=\"empty-state-icon-glyph\"\n data-centered=\"true\"\n aria-hidden=\"true\"\n className={cn(\n 'inline-flex shrink-0 items-center justify-center leading-none [line-height:0] [&>svg]:block [&>svg]:size-full [&>svg]:shrink-0',\n iconGlyphSizeClass[size],\n )}\n >\n {icon}\n </span>\n );\n}\n\n// ============================================================================\n// Background Pattern\n// ============================================================================\n\nexport interface EmptyStateBackgroundPatternProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n size?: EmptyStateSize;\n variant?: EmptyStateBackgroundPatternVariant;\n}\n\nconst gridPatternStyle = (\n size: EmptyStateSize,\n dot = false,\n): React.CSSProperties => ({\n backgroundImage: dot\n ? 'radial-gradient(circle, color-mix(in oklch, var(--border) 70%, transparent) 1px, transparent 1px)'\n : [\n 'linear-gradient(to right, color-mix(in oklch, var(--border) 54%, transparent) 1px, transparent 1px)',\n 'linear-gradient(to bottom, color-mix(in oklch, var(--border) 54%, transparent) 1px, transparent 1px)',\n ].join(', '),\n backgroundSize: patternGridSize[size],\n});\n\nconst squaresBySize: Record<EmptyStateSize, number[]> = {\n sm: [96, 144, 192, 240, 288, 336],\n md: [96, 160, 224, 288, 352, 416, 480],\n lg: [96, 192, 288, 384, 480, 576, 672, 768],\n};\n\nexport const EmptyStateBackgroundPattern = React.forwardRef<\n HTMLDivElement,\n EmptyStateBackgroundPatternProps\n>(({ className, size = 'sm', variant = 'circles', style, ...props }, ref) => {\n if (variant === 'none') {\n return null;\n }\n\n return (\n <div\n ref={ref}\n data-slot=\"empty-state-background-pattern\"\n data-testid=\"empty-state-pattern\"\n data-size={size}\n data-variant={variant}\n aria-hidden=\"true\"\n className={cn(\n 'pointer-events-none absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 overflow-hidden opacity-75',\n patternSizeClass[size],\n className,\n )}\n style={style}\n {...props}\n >\n <div className=\"absolute inset-0 bg-[radial-gradient(circle_at_center,var(--background)_0%,transparent_68%)]\" />\n\n {variant === 'circles' && (\n <div className=\"absolute inset-0\">\n {Array.from({ length: 7 }, (_, index) => (\n <span\n key={index}\n className=\"absolute left-1/2 top-1/2 rounded-full border border-border/60\"\n style={{\n width: `${(index + 1) * 14}%`,\n height: `${(index + 1) * 14}%`,\n transform: 'translate(-50%, -50%)',\n }}\n />\n ))}\n </div>\n )}\n\n {(variant === 'grid' || variant === 'grid-dot') && (\n <div\n className=\"absolute inset-0 opacity-70 [mask-image:radial-gradient(circle_at_center,black_0%,black_48%,transparent_76%)]\"\n style={gridPatternStyle(size, variant === 'grid-dot')}\n />\n )}\n\n {variant === 'squares' && (\n <div className=\"absolute inset-0\">\n {squaresBySize[size].map((squareSize) => (\n <span\n key={squareSize}\n className=\"absolute left-1/2 top-1/2 rounded-xl border border-border/55\"\n style={{\n width: squareSize,\n height: squareSize,\n transform: 'translate(-50%, -50%) rotate(-12.5deg)',\n }}\n />\n ))}\n </div>\n )}\n </div>\n );\n});\n\nEmptyStateBackgroundPattern.displayName = 'EmptyStateBackgroundPattern';\n\n// ============================================================================\n// Illustration\n// ============================================================================\n\nexport interface EmptyStateIllustrationProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n size?: EmptyStateSize;\n variant?: EmptyStateIllustrationVariant;\n tone?: EmptyStateTone;\n icon?: React.ReactNode;\n}\n\nfunction DecorativeDots({ tone }: { tone: EmptyStateTone }) {\n const dotClassName =\n tone === 'primary' ? 'bg-primary/70' : 'bg-muted-foreground/10';\n\n return (\n <>\n <span\n className={cn(\n 'absolute left-[7%] top-[8%] size-2 rounded-full',\n dotClassName,\n )}\n />\n <span\n className={cn(\n 'absolute right-[6%] top-[18%] size-3 rounded-full',\n dotClassName,\n )}\n />\n <span\n className={cn(\n 'absolute bottom-[10%] left-[8%] size-3 rounded-full',\n dotClassName,\n )}\n />\n <span\n className={cn(\n 'absolute bottom-[18%] right-[13%] size-2 rounded-full',\n dotClassName,\n )}\n />\n </>\n );\n}\n\n// Keep every artwork bbox centered on the shared 220 × 168 viewBox center (110, 84).\nfunction CloudShape({\n accentId,\n shadeId,\n tone,\n}: {\n accentId: string;\n shadeId: string;\n tone: EmptyStateTone;\n}) {\n return (\n <g\n transform=\"translate(10.5 14.5)\"\n className=\"drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]\"\n >\n <path\n d=\"M54 110c-21 0-38-14-38-32 0-16 14-30 33-32 8-19 27-31 49-31 27 0 50 19 55 43 17 3 30 16 30 32 0 19-18 34-40 34H55c-1 0-1-14-1-14Z\"\n fill={`url(#${shadeId})`}\n />\n <path\n d=\"M68 106c-18 0-32-12-32-27 0-13 11-24 27-26 7-16 23-26 42-26 23 0 42 16 46 36 15 3 26 14 26 28 0 16-15 29-34 29H68v-14Z\"\n fill={`url(#${accentId})`}\n opacity={tone === 'primary' ? 0.78 : 0.36}\n />\n </g>\n );\n}\n\nfunction BoxShape({\n accentId,\n shadeId,\n}: {\n accentId: string;\n shadeId: string;\n}) {\n return (\n <g\n transform=\"translate(-19.5)\"\n className=\"drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]\"\n >\n <path d=\"M72 42 132 20l55 31-62 24-53-33Z\" fill={`url(#${accentId})`} />\n <path d=\"M72 42v72l53 34V75L72 42Z\" fill={`url(#${shadeId})`} />\n <path d=\"M125 75v73l62-35V51l-62 24Z\" fill=\"var(--card)\" />\n <path\n d=\"M132 20v33l24 14V34l-24-14Z\"\n fill=\"currentColor\"\n opacity=\"0.34\"\n />\n <path\n d=\"M72 42 132 20l55 31-62 24-53-33Z\"\n fill=\"none\"\n stroke=\"var(--border)\"\n />\n </g>\n );\n}\n\nfunction DocumentsShape({\n accentId,\n shadeId,\n}: {\n accentId: string;\n shadeId: string;\n}) {\n return (\n <g\n transform=\"translate(0 -0.5)\"\n className=\"drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]\"\n >\n <g transform=\"translate(44 48) rotate(-18)\">\n <rect\n width=\"58\"\n height=\"78\"\n rx=\"7\"\n fill={`url(#${shadeId})`}\n stroke=\"var(--border)\"\n />\n <path\n d=\"M15 21h28M15 35h21M15 49h28\"\n stroke=\"currentColor\"\n strokeOpacity=\"0.28\"\n />\n </g>\n <g transform=\"translate(83 32)\">\n <rect\n width=\"58\"\n height=\"88\"\n rx=\"7\"\n fill=\"var(--card)\"\n stroke=\"var(--border)\"\n />\n <path\n d=\"M16 26h28M16 41h22M16 56h28\"\n stroke=\"currentColor\"\n strokeOpacity=\"0.32\"\n />\n </g>\n <g transform=\"translate(121 47) rotate(18)\">\n <rect\n width=\"58\"\n height=\"78\"\n rx=\"7\"\n fill={`url(#${accentId})`}\n stroke=\"var(--border)\"\n />\n <path\n d=\"M15 21h28M15 35h21M15 49h28\"\n stroke=\"currentColor\"\n strokeOpacity=\"0.32\"\n />\n </g>\n </g>\n );\n}\n\nfunction CreditCardShape({\n accentId,\n shadeId,\n}: {\n accentId: string;\n shadeId: string;\n}) {\n return (\n <g\n transform=\"translate(0 -5)\"\n className=\"drop-shadow-[0_8px_16px_var(--shadow-soft-3-color)]\"\n >\n <rect\n x=\"42\"\n y=\"48\"\n width=\"136\"\n height=\"82\"\n rx=\"12\"\n fill={`url(#${shadeId})`}\n stroke=\"var(--border)\"\n />\n <rect\n x=\"42\"\n y=\"70\"\n width=\"136\"\n height=\"16\"\n fill={`url(#${accentId})`}\n opacity=\"0.72\"\n />\n <rect\n x=\"58\"\n y=\"104\"\n width=\"28\"\n height=\"8\"\n rx=\"2\"\n fill=\"currentColor\"\n opacity=\"0.28\"\n />\n <rect\n x=\"58\"\n y=\"116\"\n width=\"58\"\n height=\"5\"\n rx=\"2.5\"\n fill=\"currentColor\"\n opacity=\"0.18\"\n />\n <circle cx=\"146\" cy=\"112\" r=\"10\" fill=\"currentColor\" opacity=\"0.24\" />\n <circle cx=\"158\" cy=\"112\" r=\"10\" fill=\"currentColor\" opacity=\"0.38\" />\n </g>\n );\n}\n\nexport const EmptyStateIllustration = React.forwardRef<\n HTMLDivElement,\n EmptyStateIllustrationProps\n>(\n (\n {\n className,\n size = 'sm',\n variant = 'cloud',\n tone = 'primary',\n icon = <Heart aria-hidden=\"true\" />,\n ...props\n },\n ref,\n ) => {\n const accentId = React.useId();\n const shadeId = React.useId();\n const isPrimary = tone === 'primary';\n\n return (\n <div\n ref={ref}\n data-slot=\"empty-state-illustration\"\n data-testid=\"empty-state-illustration\"\n data-size={size}\n data-variant={variant}\n data-tone={tone}\n aria-hidden=\"true\"\n className={cn(\n 'relative shrink-0 text-primary',\n !isPrimary && 'text-muted-foreground',\n illustrationSizeClass[size][variant],\n className,\n )}\n {...props}\n >\n <div\n data-slot=\"empty-state-illustration-background\"\n data-testid=\"empty-state-illustration-background\"\n data-centered=\"true\"\n className={cn(\n 'absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full',\n isPrimary ? 'bg-primary/20' : 'bg-muted/80',\n illustrationCircleSizeClass[size],\n )}\n />\n <DecorativeDots tone={tone} />\n <svg\n viewBox=\"0 0 220 168\"\n className=\"absolute inset-0 size-full overflow-visible\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <defs>\n <linearGradient id={accentId} x1=\"25\" y1=\"12\" x2=\"190\" y2=\"148\">\n <stop\n stopColor={isPrimary ? 'var(--primary)' : 'var(--muted)'}\n stopOpacity={isPrimary ? 0.34 : 0.74}\n />\n <stop stopColor=\"var(--card)\" stopOpacity={0.95} />\n </linearGradient>\n <linearGradient id={shadeId} x1=\"54\" y1=\"18\" x2=\"165\" y2=\"140\">\n <stop stopColor=\"var(--card)\" />\n <stop\n stopColor={\n isPrimary ? 'var(--primary)' : 'var(--muted-foreground)'\n }\n stopOpacity={isPrimary ? 0.18 : 0.14}\n />\n </linearGradient>\n </defs>\n\n {variant === 'cloud' && (\n <CloudShape accentId={accentId} shadeId={shadeId} tone={tone} />\n )}\n {variant === 'box' && (\n <BoxShape accentId={accentId} shadeId={shadeId} />\n )}\n {variant === 'documents' && (\n <DocumentsShape accentId={accentId} shadeId={shadeId} />\n )}\n {variant === 'credit-card' && (\n <CreditCardShape accentId={accentId} shadeId={shadeId} />\n )}\n </svg>\n <div\n data-slot=\"empty-state-illustration-icon\"\n data-testid=\"empty-state-illustration-icon\"\n data-centered=\"true\"\n className={cn(\n 'absolute left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-xl bg-primary/10 text-primary shadow-xs backdrop-blur-md supports-backdrop-filter:backdrop-blur-md [&>svg]:shrink-0',\n !isPrimary && 'bg-muted text-muted-foreground',\n illustrationIconSizeClass[size],\n )}\n >\n <EmptyStateIconGlyph icon={icon} size={size} />\n </div>\n </div>\n );\n },\n);\n\nEmptyStateIllustration.displayName = 'EmptyStateIllustration';\n\n// ============================================================================\n// EmptyState\n// ============================================================================\n\nconst emptyStateVariants = cva(\n 'relative isolate mx-auto flex w-full max-w-[512px] items-center justify-center overflow-visible py-8 text-center',\n {\n variants: {\n size: {\n sm: 'min-h-[212px]',\n md: 'min-h-[280px]',\n lg: 'min-h-[360px]',\n },\n },\n defaultVariants: {\n size: 'sm',\n },\n },\n);\n\nexport interface EmptyStateProps\n extends Omit<React.HTMLAttributes<HTMLElement>, 'title'> {\n title: React.ReactNode;\n description?: React.ReactNode;\n size?: EmptyStateSize;\n media?: EmptyStateMedia;\n pattern?: EmptyStateBackgroundPatternVariant | 'auto';\n icon?: React.ReactNode;\n iconLabel?: string;\n illustrationVariant?: EmptyStateIllustrationVariant;\n illustrationTone?: EmptyStateTone;\n fileExtension?: FileExtension;\n fileType?: SimpleFileType;\n primaryAction?: EmptyStateActionConfig;\n secondaryAction?: EmptyStateActionConfig;\n actions?: React.ReactNode;\n headingLevel?: 2 | 3 | 4;\n}\n\nfunction resolvePattern(\n pattern: EmptyStateProps['pattern'],\n media: EmptyStateMedia,\n): EmptyStateBackgroundPatternVariant {\n if (!pattern || pattern === 'auto') {\n if (media === 'illustration') return 'grid';\n if (media === 'none') return 'none';\n return 'circles';\n }\n return pattern;\n}\n\nfunction renderEmptyStateAction(\n action: EmptyStateActionConfig,\n intent: 'primary' | 'secondary',\n) {\n const {\n label,\n onClick,\n startIcon,\n disabled,\n loading,\n 'aria-label': ariaLabel,\n } = action;\n\n return (\n <Button\n appearance={intent === 'primary' ? 'solid' : 'outline'}\n variant={intent === 'primary' ? 'primary' : 'secondary'}\n size=\"sm\"\n shape=\"rounded\"\n onClick={onClick}\n disabled={disabled}\n loading={loading}\n startIcon={startIcon}\n aria-label={ariaLabel}\n type=\"button\"\n >\n {label}\n </Button>\n );\n}\n\nexport const EmptyState = React.forwardRef<HTMLElement, EmptyStateProps>(\n (\n {\n className,\n title,\n description,\n size = 'sm',\n media = 'featured-icon',\n pattern = 'auto',\n icon,\n iconLabel,\n illustrationVariant = 'cloud',\n illustrationTone = 'gray',\n fileExtension,\n fileType = 'document',\n primaryAction,\n secondaryAction,\n actions,\n headingLevel = 3,\n ...props\n },\n ref,\n ) => {\n const Heading = headingTag[headingLevel];\n const resolvedPattern = resolvePattern(pattern, media);\n const defaultIcon = icon ?? <Search aria-hidden=\"true\" />;\n const hasActions = actions || primaryAction || secondaryAction;\n\n return (\n <section\n ref={ref}\n data-slot=\"empty-state\"\n aria-label={typeof title === 'string' ? title : 'Empty state'}\n className={cn(emptyStateVariants({ size }), className)}\n {...props}\n >\n <div\n data-slot=\"empty-state-content\"\n className={cn(\n 'relative z-10 flex min-w-0 flex-1 flex-col items-center',\n contentGapClass[size],\n )}\n >\n <div\n data-slot=\"empty-state-body\"\n className={cn(\n 'flex w-full flex-col items-center',\n mediaGapClass[size],\n )}\n >\n {media !== 'none' && (\n <div\n data-slot=\"empty-state-media\"\n data-testid=\"empty-state-media\"\n data-media={media}\n data-centered=\"true\"\n className=\"relative flex w-full min-w-0 justify-center\"\n >\n <EmptyStateBackgroundPattern\n size={size}\n variant={resolvedPattern}\n data-centered=\"true\"\n className=\"z-0\"\n />\n\n {media === 'featured-icon' && (\n <FeaturedIcon\n data-slot=\"empty-state-featured-icon\"\n size={featuredIconSize[size]}\n shape=\"rounded\"\n intent=\"default\"\n icon={\n <EmptyStateIconGlyph icon={defaultIcon} size={size} />\n }\n aria-label={iconLabel}\n className=\"relative z-10 delight-stagger motion-reduce:animate-none\"\n />\n )}\n\n {media === 'illustration' && (\n <EmptyStateIllustration\n size={size}\n variant={illustrationVariant}\n tone={illustrationTone}\n icon={defaultIcon}\n className=\"relative z-10 delight-stagger motion-reduce:animate-none\"\n />\n )}\n\n {media === 'file-type-icon' && (\n <div\n data-slot=\"empty-state-file-icon-wrap\"\n data-testid=\"empty-state-file-icon-wrap\"\n data-centered=\"true\"\n className={cn(\n 'relative z-10 flex items-center justify-center rounded-full bg-linear-[104deg,color-mix(in_oklch,var(--card)_60%,transparent),color-mix(in_oklch,var(--muted)_55%,transparent)] delight-stagger motion-reduce:animate-none',\n fileIconWrapSizeClass[size],\n )}\n >\n <div\n data-slot=\"empty-state-file-icon-optical-center\"\n data-testid=\"empty-state-file-icon-optical-center\"\n data-centered=\"true\"\n >\n <FileTypeIcon\n extension={fileExtension}\n fileType={fileExtension ? undefined : fileType}\n size={fileIconSize[size]}\n className=\"drop-shadow-[0_1px_2px_var(--shadow-xs-1-color)]\"\n />\n </div>\n </div>\n )}\n </div>\n )}\n\n <div\n data-slot=\"empty-state-text\"\n className={cn(\n 'flex w-full max-w-[352px] flex-col items-center text-center',\n textGapClass[size],\n )}\n >\n <Heading className=\"w-full text-base font-semibold leading-6 text-foreground\">\n {title}\n </Heading>\n {description && (\n <p className=\"w-full text-sm leading-5 text-secondary-foreground\">\n {description}\n </p>\n )}\n </div>\n </div>\n\n {hasActions && (\n <div\n data-slot=\"empty-state-actions\"\n className=\"flex flex-wrap items-center justify-center gap-3\"\n >\n {actions ?? (\n <>\n {secondaryAction &&\n renderEmptyStateAction(secondaryAction, 'secondary')}\n {primaryAction &&\n renderEmptyStateAction(primaryAction, 'primary')}\n </>\n )}\n </div>\n )}\n </div>\n </section>\n );\n },\n);\n\nEmptyState.displayName = 'EmptyState';\n"],"mappings":"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"}
package/dist/index24.js CHANGED
@@ -216,7 +216,7 @@ var FeaturedIcon = React$1.forwardRef(({ children, size = "sm", className }, ref
216
216
  className: cn("shrink-0 rounded-md border border-border bg-card/60", "flex items-center justify-center", "dark:border-border", containerSize, className),
217
217
  style: { boxShadow: "var(--shadow-inset-ring)" },
218
218
  children: /* @__PURE__ */ jsx("div", {
219
- className: cn("text-secondary-foreground", innerSize),
219
+ className: cn("text-secondary-foreground [&>svg]:block [&>svg]:size-full", innerSize),
220
220
  children
221
221
  })
222
222
  });
@@ -1 +1 @@
1
- {"version":3,"file":"index24.js","names":[],"sources":["../src/components/ui/selection-group.tsx"],"sourcesContent":["'use client';\n\nimport { cva } from 'class-variance-authority';\nimport { Minus } from 'lucide-react';\nimport * as React from 'react';\nimport { cn } from '@/lib/utils';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type SelectionColor =\n | 'primary'\n | 'secondary'\n | 'success'\n | 'warning'\n | 'info'\n | 'destructive';\n\nexport type SelectionSize = 'sm' | 'md' | 'lg';\n\nexport type SelectionVariant =\n | 'default'\n | 'card'\n | 'pill'\n | 'stacked'\n | 'icon-simple'\n | 'icon-card'\n | 'avatar'\n | 'payment'\n | 'simple'\n | 'chip';\n\nexport interface SelectionItem {\n /** Unique value for the option */\n value: string;\n /** Display label */\n label: string;\n /** Whether this option is disabled */\n disabled?: boolean;\n /** Secondary text (e.g., \"$10/month\") */\n subtext?: string;\n /** Supporting description text */\n description?: string;\n /** Leading icon component */\n icon?: React.ReactNode;\n /** Avatar element */\n avatar?: React.ReactNode;\n /** Image URL */\n image?: string;\n /** Alt text for the image (defaults to \"\" if omitted) */\n imageAlt?: string;\n /** Position of the image */\n imagePosition?: 'top' | 'left' | 'trailing';\n /** Badge element */\n badge?: React.ReactNode;\n /** Dot color for chip variant (named color or hex) */\n dotColor?: string;\n /** Price display (e.g., \"$10\") */\n price?: string;\n /** Price period (e.g., \"per month\") */\n pricePeriod?: string;\n /** Payment icon element */\n paymentIcon?: React.ReactNode;\n /** Action buttons */\n actions?: React.ReactNode;\n}\n\n// =============================================================================\n// Hooks\n// =============================================================================\n\ninterface UseSelectionStateOptions {\n /** Controlled value */\n value?: string;\n /** Default value for uncontrolled mode */\n defaultValue?: string;\n /** Callback when value changes */\n onValueChange?: (value: string) => void;\n}\n\n/**\n * Hook for managing single selection state (radio behavior).\n * Supports both controlled and uncontrolled modes.\n */\nexport function useSelectionState(\n options: UseSelectionStateOptions = {},\n): [string | undefined, (value: string) => void] {\n const { value: controlledValue, defaultValue, onValueChange } = options;\n\n const [internalValue, setInternalValue] = React.useState<string | undefined>(\n defaultValue,\n );\n\n const isControlled = controlledValue !== undefined;\n const selectedValue = isControlled ? controlledValue : internalValue;\n\n const setValue = React.useCallback(\n (newValue: string) => {\n if (!isControlled) {\n setInternalValue(newValue);\n }\n onValueChange?.(newValue);\n },\n [isControlled, onValueChange],\n );\n\n return [selectedValue, setValue];\n}\n\ninterface UseMultiSelectionStateOptions {\n /** Controlled value */\n value?: string[];\n /** Default value for uncontrolled mode */\n defaultValue?: string[];\n /** Callback when value changes */\n onValueChange?: (value: string[]) => void;\n}\n\n/**\n * Hook for managing multi selection state (checkbox behavior).\n * Supports both controlled and uncontrolled modes.\n */\nexport function useMultiSelectionState(\n options: UseMultiSelectionStateOptions = {},\n): [string[], (value: string, checked: boolean) => void] {\n const { value: controlledValue, defaultValue = [], onValueChange } = options;\n\n const [internalValue, setInternalValue] =\n React.useState<string[]>(defaultValue);\n\n const isControlled = controlledValue !== undefined;\n const selectedValues = isControlled ? controlledValue : internalValue;\n\n const setValue = React.useCallback(\n (itemValue: string, checked: boolean) => {\n const newValue = checked\n ? [...selectedValues, itemValue]\n : selectedValues.filter((v) => v !== itemValue);\n\n if (!isControlled) {\n setInternalValue(newValue);\n }\n onValueChange?.(newValue);\n },\n [isControlled, selectedValues, onValueChange],\n );\n\n return [selectedValues, setValue];\n}\n\n// =============================================================================\n// Color Mappings\n// =============================================================================\n\nexport const selectionColorClasses: Record<\n SelectionColor,\n {\n indicator: string;\n indicatorChecked: string;\n border: string;\n bg: string;\n text: string;\n }\n> = {\n primary: {\n indicator: 'border-primary',\n indicatorChecked: 'bg-primary',\n border: 'border-primary',\n bg: 'bg-primary',\n text: 'text-primary-foreground',\n },\n secondary: {\n indicator: 'border-secondary',\n indicatorChecked: 'bg-secondary-foreground',\n border: 'border-secondary',\n bg: 'bg-secondary',\n text: 'text-secondary-foreground',\n },\n success: {\n indicator: 'border-success',\n indicatorChecked: 'bg-success',\n border: 'border-success',\n bg: 'bg-success',\n text: 'text-primary-foreground',\n },\n warning: {\n indicator: 'border-warning',\n indicatorChecked: 'bg-warning',\n border: 'border-warning',\n bg: 'bg-warning',\n text: 'text-primary-foreground',\n },\n info: {\n indicator: 'border-info',\n indicatorChecked: 'bg-info',\n border: 'border-info',\n bg: 'bg-info',\n text: 'text-primary-foreground',\n },\n destructive: {\n indicator: 'border-destructive',\n indicatorChecked: 'bg-destructive',\n border: 'border-destructive',\n bg: 'bg-destructive',\n text: 'text-primary-foreground',\n },\n};\n\n// =============================================================================\n// CVA Variants\n// =============================================================================\n\n/**\n * Selection group container variants.\n * Used for the outer wrapper of a group of selection items.\n */\nexport const selectionGroupVariants = cva('flex', {\n variants: {\n orientation: {\n horizontal: 'flex-row flex-wrap',\n vertical: 'flex-col',\n },\n gap: {\n sm: 'gap-2',\n md: 'gap-3',\n lg: 'gap-4',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n gap: 'md',\n },\n});\n\n/**\n * Selection indicator variants (for both radio and checkbox).\n * Renders as a rounded indicator with border.\n */\nexport const selectionIndicatorVariants = cva(\n 'shrink-0 rounded-full border shadow-xs transition-all flex items-center justify-center',\n {\n variants: {\n size: {\n sm: 'size-4',\n md: 'size-5',\n lg: 'size-6',\n },\n },\n defaultVariants: {\n size: 'sm',\n },\n },\n);\n\n/**\n * Checkbox indicator variants (square with rounded corners).\n */\nexport const checkboxIndicatorVariants = cva(\n 'shrink-0 border shadow-xs transition-[border-color,background-color,color,box-shadow] duration-200 ease-out motion-reduce:transition-none flex items-center justify-center',\n {\n variants: {\n size: {\n sm: 'size-4 rounded-[4px]',\n md: 'size-5 rounded-[5px]',\n lg: 'size-6 rounded-[6px]',\n },\n },\n defaultVariants: {\n size: 'sm',\n },\n },\n);\n\n/**\n * Inner dot sizes for radio indicators when checked.\n */\nexport const innerDotSizes: Record<SelectionSize, string> = {\n sm: 'size-2',\n md: 'size-3',\n lg: 'size-4',\n};\n\n/**\n * Text size classes for selection labels.\n */\nexport const textSizeClasses: Record<SelectionSize, string> = {\n sm: 'text-sm',\n md: 'text-sm',\n lg: 'text-sm',\n};\n\n/**\n * Icon size classes for checkbox indicators.\n */\nexport const iconSizeClasses: Record<SelectionSize, string> = {\n sm: 'size-3',\n md: 'size-3.5',\n lg: 'size-5',\n};\n\n// =============================================================================\n// Draw-on checkmark SVG (shared delight animation)\n// =============================================================================\n\nexport const CHECKMARK_PATH = 'M4 12l5 5L20 6';\n\nexport function DrawCheck({ className }: { className?: string }) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={3}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn(className, 'delight-check-draw')}\n >\n <path d={CHECKMARK_PATH} />\n </svg>\n );\n}\n\n// =============================================================================\n// SelectionIndicator Component\n// =============================================================================\n\nexport interface SelectionIndicatorProps {\n /** Type of indicator to render */\n type: 'checkbox' | 'radio';\n /** Whether the indicator is checked */\n checked?: boolean;\n /** Whether the indicator is disabled */\n disabled?: boolean;\n /** Size of the indicator */\n size?: SelectionSize;\n /** Color of the indicator */\n color?: SelectionColor;\n /** Additional CSS classes */\n className?: string;\n /** Whether the checkbox is in indeterminate state (checkbox only) */\n indeterminate?: boolean;\n}\n\n/**\n * SelectionIndicator renders either a checkbox or radio indicator based on type.\n * For checkbox: renders a check icon when checked.\n * For radio: renders an inner dot when checked.\n */\nconst SelectionIndicator = React.forwardRef<\n HTMLSpanElement,\n SelectionIndicatorProps\n>(\n (\n {\n type,\n checked = false,\n disabled = false,\n size = 'sm',\n color = 'primary',\n className,\n indeterminate = false,\n },\n ref,\n ) => {\n const colors = selectionColorClasses[color];\n\n if (type === 'checkbox') {\n return (\n <span\n ref={ref}\n data-slot=\"selection-indicator\"\n data-type=\"checkbox\"\n data-checked={checked}\n data-indeterminate={indeterminate || undefined}\n className={cn(\n checkboxIndicatorVariants({ size }),\n checked || indeterminate\n ? cn(\n colors.indicatorChecked,\n colors.border,\n colors.text,\n 'border',\n 'delight-check-bounce',\n )\n : 'border-input bg-background',\n disabled && 'opacity-50',\n className,\n )}\n aria-hidden=\"true\"\n >\n {(checked || indeterminate) &&\n (indeterminate ? (\n <Minus\n className={cn(\n iconSizeClasses[size],\n 'animate-[scale-in_150ms_ease-out] motion-reduce:animate-none',\n )}\n strokeWidth={3}\n />\n ) : (\n <DrawCheck className={iconSizeClasses[size]} />\n ))}\n </span>\n );\n }\n\n // Radio type\n return (\n <span\n ref={ref}\n data-slot=\"selection-indicator\"\n data-type=\"radio\"\n data-checked={checked}\n className={cn(\n selectionIndicatorVariants({ size }),\n 'transition-[background-color,border-color] duration-150 motion-reduce:transition-none',\n 'border-input bg-transparent',\n disabled && 'opacity-50',\n className,\n )}\n aria-hidden=\"true\"\n >\n <span\n className={cn(\n 'rounded-full transition-transform duration-150 ease-out motion-reduce:transition-none',\n colors.indicatorChecked,\n innerDotSizes[size],\n checked ? 'scale-100' : 'scale-0',\n )}\n />\n </span>\n );\n },\n);\n\nSelectionIndicator.displayName = 'SelectionIndicator';\n\n// =============================================================================\n// FeaturedIcon Component\n// =============================================================================\n\nexport interface FeaturedIconProps {\n /** The icon content to display */\n children: React.ReactNode;\n /** Size of the featured icon container */\n size?: SelectionSize;\n /** Additional CSS classes */\n className?: string;\n}\n\n// Hoisted outside component to avoid recreation on every render\nconst featuredIconContainerSizes: Record<SelectionSize, string> = {\n sm: 'size-8',\n md: 'size-10',\n lg: 'size-12',\n};\n\nconst featuredIconInnerSizes: Record<SelectionSize, string> = {\n sm: 'size-4',\n md: 'size-5',\n lg: 'size-6',\n};\n\n/**\n * FeaturedIcon is a container for icons with border and shadow.\n * Used in icon-simple and icon-card variants.\n */\nconst FeaturedIcon = React.forwardRef<HTMLDivElement, FeaturedIconProps>(\n ({ children, size = 'sm', className }, ref) => {\n const containerSize = featuredIconContainerSizes[size];\n const innerSize = featuredIconInnerSizes[size];\n\n return (\n <div\n ref={ref}\n data-slot=\"featured-icon\"\n className={cn(\n 'shrink-0 rounded-md border border-border bg-card/60',\n 'flex items-center justify-center',\n 'dark:border-border',\n containerSize,\n className,\n )}\n style={{\n boxShadow: 'var(--shadow-inset-ring)',\n }}\n >\n <div className={cn('text-secondary-foreground', innerSize)}>\n {children}\n </div>\n </div>\n );\n },\n);\n\nFeaturedIcon.displayName = 'FeaturedIcon';\n\n// =============================================================================\n// ColorDot Component\n// =============================================================================\n\nexport type ColorDotColor =\n | 'gray'\n | 'orange'\n | 'red'\n | 'darkRed'\n | 'brand'\n | 'success'\n | 'warning'\n | 'error'\n | string; // Allow custom hex colors\n\nconst dotColorMap: Record<string, string> = {\n gray: 'bg-muted',\n orange: 'bg-warning',\n red: 'bg-destructive',\n darkRed: 'bg-destructive-hover',\n brand: 'bg-primary/10',\n success: 'bg-success/10',\n warning: 'bg-warning/10',\n error: 'bg-destructive/10',\n};\n\nconst dotSizeMap: Record<SelectionSize, string> = {\n sm: 'size-[10px]',\n md: 'size-3',\n lg: 'size-3.5',\n};\n\nexport interface ColorDotProps {\n /** Color of the dot (named color or hex) */\n color?: ColorDotColor;\n /** Size of the dot */\n size?: SelectionSize;\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * ColorDot renders a colored dot for chip variant.\n * Supports named colors (gray, orange, red, etc.) and hex colors.\n */\nconst ColorDot = React.forwardRef<HTMLSpanElement, ColorDotProps>(\n ({ color, size = 'sm', className }, ref) => {\n if (!color) return null;\n\n const colorClass = dotColorMap[color];\n const isHexColor = color.startsWith('#');\n\n return (\n <span\n ref={ref}\n data-slot=\"color-dot\"\n className={cn(\n 'shrink-0 rounded-full',\n dotSizeMap[size],\n !isHexColor && colorClass,\n className,\n )}\n style={isHexColor ? { backgroundColor: color } : undefined}\n aria-hidden=\"true\"\n />\n );\n },\n);\n\nColorDot.displayName = 'ColorDot';\n\n// =============================================================================\n// Exports\n// =============================================================================\n\nexport { ColorDot, FeaturedIcon, SelectionIndicator };\n"],"mappings":"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"}
1
+ {"version":3,"file":"index24.js","names":[],"sources":["../src/components/ui/selection-group.tsx"],"sourcesContent":["'use client';\n\nimport { cva } from 'class-variance-authority';\nimport { Minus } from 'lucide-react';\nimport * as React from 'react';\nimport { cn } from '@/lib/utils';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type SelectionColor =\n | 'primary'\n | 'secondary'\n | 'success'\n | 'warning'\n | 'info'\n | 'destructive';\n\nexport type SelectionSize = 'sm' | 'md' | 'lg';\n\nexport type SelectionVariant =\n | 'default'\n | 'card'\n | 'pill'\n | 'stacked'\n | 'icon-simple'\n | 'icon-card'\n | 'avatar'\n | 'payment'\n | 'simple'\n | 'chip';\n\nexport interface SelectionItem {\n /** Unique value for the option */\n value: string;\n /** Display label */\n label: string;\n /** Whether this option is disabled */\n disabled?: boolean;\n /** Secondary text (e.g., \"$10/month\") */\n subtext?: string;\n /** Supporting description text */\n description?: string;\n /** Leading icon component */\n icon?: React.ReactNode;\n /** Avatar element */\n avatar?: React.ReactNode;\n /** Image URL */\n image?: string;\n /** Alt text for the image (defaults to \"\" if omitted) */\n imageAlt?: string;\n /** Position of the image */\n imagePosition?: 'top' | 'left' | 'trailing';\n /** Badge element */\n badge?: React.ReactNode;\n /** Dot color for chip variant (named color or hex) */\n dotColor?: string;\n /** Price display (e.g., \"$10\") */\n price?: string;\n /** Price period (e.g., \"per month\") */\n pricePeriod?: string;\n /** Payment icon element */\n paymentIcon?: React.ReactNode;\n /** Action buttons */\n actions?: React.ReactNode;\n}\n\n// =============================================================================\n// Hooks\n// =============================================================================\n\ninterface UseSelectionStateOptions {\n /** Controlled value */\n value?: string;\n /** Default value for uncontrolled mode */\n defaultValue?: string;\n /** Callback when value changes */\n onValueChange?: (value: string) => void;\n}\n\n/**\n * Hook for managing single selection state (radio behavior).\n * Supports both controlled and uncontrolled modes.\n */\nexport function useSelectionState(\n options: UseSelectionStateOptions = {},\n): [string | undefined, (value: string) => void] {\n const { value: controlledValue, defaultValue, onValueChange } = options;\n\n const [internalValue, setInternalValue] = React.useState<string | undefined>(\n defaultValue,\n );\n\n const isControlled = controlledValue !== undefined;\n const selectedValue = isControlled ? controlledValue : internalValue;\n\n const setValue = React.useCallback(\n (newValue: string) => {\n if (!isControlled) {\n setInternalValue(newValue);\n }\n onValueChange?.(newValue);\n },\n [isControlled, onValueChange],\n );\n\n return [selectedValue, setValue];\n}\n\ninterface UseMultiSelectionStateOptions {\n /** Controlled value */\n value?: string[];\n /** Default value for uncontrolled mode */\n defaultValue?: string[];\n /** Callback when value changes */\n onValueChange?: (value: string[]) => void;\n}\n\n/**\n * Hook for managing multi selection state (checkbox behavior).\n * Supports both controlled and uncontrolled modes.\n */\nexport function useMultiSelectionState(\n options: UseMultiSelectionStateOptions = {},\n): [string[], (value: string, checked: boolean) => void] {\n const { value: controlledValue, defaultValue = [], onValueChange } = options;\n\n const [internalValue, setInternalValue] =\n React.useState<string[]>(defaultValue);\n\n const isControlled = controlledValue !== undefined;\n const selectedValues = isControlled ? controlledValue : internalValue;\n\n const setValue = React.useCallback(\n (itemValue: string, checked: boolean) => {\n const newValue = checked\n ? [...selectedValues, itemValue]\n : selectedValues.filter((v) => v !== itemValue);\n\n if (!isControlled) {\n setInternalValue(newValue);\n }\n onValueChange?.(newValue);\n },\n [isControlled, selectedValues, onValueChange],\n );\n\n return [selectedValues, setValue];\n}\n\n// =============================================================================\n// Color Mappings\n// =============================================================================\n\nexport const selectionColorClasses: Record<\n SelectionColor,\n {\n indicator: string;\n indicatorChecked: string;\n border: string;\n bg: string;\n text: string;\n }\n> = {\n primary: {\n indicator: 'border-primary',\n indicatorChecked: 'bg-primary',\n border: 'border-primary',\n bg: 'bg-primary',\n text: 'text-primary-foreground',\n },\n secondary: {\n indicator: 'border-secondary',\n indicatorChecked: 'bg-secondary-foreground',\n border: 'border-secondary',\n bg: 'bg-secondary',\n text: 'text-secondary-foreground',\n },\n success: {\n indicator: 'border-success',\n indicatorChecked: 'bg-success',\n border: 'border-success',\n bg: 'bg-success',\n text: 'text-primary-foreground',\n },\n warning: {\n indicator: 'border-warning',\n indicatorChecked: 'bg-warning',\n border: 'border-warning',\n bg: 'bg-warning',\n text: 'text-primary-foreground',\n },\n info: {\n indicator: 'border-info',\n indicatorChecked: 'bg-info',\n border: 'border-info',\n bg: 'bg-info',\n text: 'text-primary-foreground',\n },\n destructive: {\n indicator: 'border-destructive',\n indicatorChecked: 'bg-destructive',\n border: 'border-destructive',\n bg: 'bg-destructive',\n text: 'text-primary-foreground',\n },\n};\n\n// =============================================================================\n// CVA Variants\n// =============================================================================\n\n/**\n * Selection group container variants.\n * Used for the outer wrapper of a group of selection items.\n */\nexport const selectionGroupVariants = cva('flex', {\n variants: {\n orientation: {\n horizontal: 'flex-row flex-wrap',\n vertical: 'flex-col',\n },\n gap: {\n sm: 'gap-2',\n md: 'gap-3',\n lg: 'gap-4',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n gap: 'md',\n },\n});\n\n/**\n * Selection indicator variants (for both radio and checkbox).\n * Renders as a rounded indicator with border.\n */\nexport const selectionIndicatorVariants = cva(\n 'shrink-0 rounded-full border shadow-xs transition-all flex items-center justify-center',\n {\n variants: {\n size: {\n sm: 'size-4',\n md: 'size-5',\n lg: 'size-6',\n },\n },\n defaultVariants: {\n size: 'sm',\n },\n },\n);\n\n/**\n * Checkbox indicator variants (square with rounded corners).\n */\nexport const checkboxIndicatorVariants = cva(\n 'shrink-0 border shadow-xs transition-[border-color,background-color,color,box-shadow] duration-200 ease-out motion-reduce:transition-none flex items-center justify-center',\n {\n variants: {\n size: {\n sm: 'size-4 rounded-[4px]',\n md: 'size-5 rounded-[5px]',\n lg: 'size-6 rounded-[6px]',\n },\n },\n defaultVariants: {\n size: 'sm',\n },\n },\n);\n\n/**\n * Inner dot sizes for radio indicators when checked.\n */\nexport const innerDotSizes: Record<SelectionSize, string> = {\n sm: 'size-2',\n md: 'size-3',\n lg: 'size-4',\n};\n\n/**\n * Text size classes for selection labels.\n */\nexport const textSizeClasses: Record<SelectionSize, string> = {\n sm: 'text-sm',\n md: 'text-sm',\n lg: 'text-sm',\n};\n\n/**\n * Icon size classes for checkbox indicators.\n */\nexport const iconSizeClasses: Record<SelectionSize, string> = {\n sm: 'size-3',\n md: 'size-3.5',\n lg: 'size-5',\n};\n\n// =============================================================================\n// Draw-on checkmark SVG (shared delight animation)\n// =============================================================================\n\nexport const CHECKMARK_PATH = 'M4 12l5 5L20 6';\n\nexport function DrawCheck({ className }: { className?: string }) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={3}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn(className, 'delight-check-draw')}\n >\n <path d={CHECKMARK_PATH} />\n </svg>\n );\n}\n\n// =============================================================================\n// SelectionIndicator Component\n// =============================================================================\n\nexport interface SelectionIndicatorProps {\n /** Type of indicator to render */\n type: 'checkbox' | 'radio';\n /** Whether the indicator is checked */\n checked?: boolean;\n /** Whether the indicator is disabled */\n disabled?: boolean;\n /** Size of the indicator */\n size?: SelectionSize;\n /** Color of the indicator */\n color?: SelectionColor;\n /** Additional CSS classes */\n className?: string;\n /** Whether the checkbox is in indeterminate state (checkbox only) */\n indeterminate?: boolean;\n}\n\n/**\n * SelectionIndicator renders either a checkbox or radio indicator based on type.\n * For checkbox: renders a check icon when checked.\n * For radio: renders an inner dot when checked.\n */\nconst SelectionIndicator = React.forwardRef<\n HTMLSpanElement,\n SelectionIndicatorProps\n>(\n (\n {\n type,\n checked = false,\n disabled = false,\n size = 'sm',\n color = 'primary',\n className,\n indeterminate = false,\n },\n ref,\n ) => {\n const colors = selectionColorClasses[color];\n\n if (type === 'checkbox') {\n return (\n <span\n ref={ref}\n data-slot=\"selection-indicator\"\n data-type=\"checkbox\"\n data-checked={checked}\n data-indeterminate={indeterminate || undefined}\n className={cn(\n checkboxIndicatorVariants({ size }),\n checked || indeterminate\n ? cn(\n colors.indicatorChecked,\n colors.border,\n colors.text,\n 'border',\n 'delight-check-bounce',\n )\n : 'border-input bg-background',\n disabled && 'opacity-50',\n className,\n )}\n aria-hidden=\"true\"\n >\n {(checked || indeterminate) &&\n (indeterminate ? (\n <Minus\n className={cn(\n iconSizeClasses[size],\n 'animate-[scale-in_150ms_ease-out] motion-reduce:animate-none',\n )}\n strokeWidth={3}\n />\n ) : (\n <DrawCheck className={iconSizeClasses[size]} />\n ))}\n </span>\n );\n }\n\n // Radio type\n return (\n <span\n ref={ref}\n data-slot=\"selection-indicator\"\n data-type=\"radio\"\n data-checked={checked}\n className={cn(\n selectionIndicatorVariants({ size }),\n 'transition-[background-color,border-color] duration-150 motion-reduce:transition-none',\n 'border-input bg-transparent',\n disabled && 'opacity-50',\n className,\n )}\n aria-hidden=\"true\"\n >\n <span\n className={cn(\n 'rounded-full transition-transform duration-150 ease-out motion-reduce:transition-none',\n colors.indicatorChecked,\n innerDotSizes[size],\n checked ? 'scale-100' : 'scale-0',\n )}\n />\n </span>\n );\n },\n);\n\nSelectionIndicator.displayName = 'SelectionIndicator';\n\n// =============================================================================\n// FeaturedIcon Component\n// =============================================================================\n\nexport interface FeaturedIconProps {\n /** The icon content to display */\n children: React.ReactNode;\n /** Size of the featured icon container */\n size?: SelectionSize;\n /** Additional CSS classes */\n className?: string;\n}\n\n// Hoisted outside component to avoid recreation on every render\nconst featuredIconContainerSizes: Record<SelectionSize, string> = {\n sm: 'size-8',\n md: 'size-10',\n lg: 'size-12',\n};\n\nconst featuredIconInnerSizes: Record<SelectionSize, string> = {\n sm: 'size-4',\n md: 'size-5',\n lg: 'size-6',\n};\n\n/**\n * FeaturedIcon is a container for icons with border and shadow.\n * Used in icon-simple and icon-card variants.\n */\nconst FeaturedIcon = React.forwardRef<HTMLDivElement, FeaturedIconProps>(\n ({ children, size = 'sm', className }, ref) => {\n const containerSize = featuredIconContainerSizes[size];\n const innerSize = featuredIconInnerSizes[size];\n\n return (\n <div\n ref={ref}\n data-slot=\"featured-icon\"\n className={cn(\n 'shrink-0 rounded-md border border-border bg-card/60',\n 'flex items-center justify-center',\n 'dark:border-border',\n containerSize,\n className,\n )}\n style={{\n boxShadow: 'var(--shadow-inset-ring)',\n }}\n >\n <div\n className={cn(\n 'text-secondary-foreground [&>svg]:block [&>svg]:size-full',\n innerSize,\n )}\n >\n {children}\n </div>\n </div>\n );\n },\n);\n\nFeaturedIcon.displayName = 'FeaturedIcon';\n\n// =============================================================================\n// ColorDot Component\n// =============================================================================\n\nexport type ColorDotColor =\n | 'gray'\n | 'orange'\n | 'red'\n | 'darkRed'\n | 'brand'\n | 'success'\n | 'warning'\n | 'error'\n | string; // Allow custom hex colors\n\nconst dotColorMap: Record<string, string> = {\n gray: 'bg-muted',\n orange: 'bg-warning',\n red: 'bg-destructive',\n darkRed: 'bg-destructive-hover',\n brand: 'bg-primary/10',\n success: 'bg-success/10',\n warning: 'bg-warning/10',\n error: 'bg-destructive/10',\n};\n\nconst dotSizeMap: Record<SelectionSize, string> = {\n sm: 'size-[10px]',\n md: 'size-3',\n lg: 'size-3.5',\n};\n\nexport interface ColorDotProps {\n /** Color of the dot (named color or hex) */\n color?: ColorDotColor;\n /** Size of the dot */\n size?: SelectionSize;\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * ColorDot renders a colored dot for chip variant.\n * Supports named colors (gray, orange, red, etc.) and hex colors.\n */\nconst ColorDot = React.forwardRef<HTMLSpanElement, ColorDotProps>(\n ({ color, size = 'sm', className }, ref) => {\n if (!color) return null;\n\n const colorClass = dotColorMap[color];\n const isHexColor = color.startsWith('#');\n\n return (\n <span\n ref={ref}\n data-slot=\"color-dot\"\n className={cn(\n 'shrink-0 rounded-full',\n dotSizeMap[size],\n !isHexColor && colorClass,\n className,\n )}\n style={isHexColor ? { backgroundColor: color } : undefined}\n aria-hidden=\"true\"\n />\n );\n },\n);\n\nColorDot.displayName = 'ColorDot';\n\n// =============================================================================\n// Exports\n// =============================================================================\n\nexport { ColorDot, FeaturedIcon, SelectionIndicator };\n"],"mappings":";;;;;;;;;;;AAqFA,SAAgB,kBACd,UAAoC,CAAC,GACU;CAC/C,MAAM,EAAE,OAAO,iBAAiB,cAAc,kBAAkB;CAEhE,MAAM,CAAC,eAAe,oBAAoB,QAAM,SAC9C,YACF;CAEA,MAAM,eAAe,oBAAoB,KAAA;CAazC,OAAO,CAZe,eAAe,kBAAkB,eAEtC,QAAM,aACpB,aAAqB;EACpB,IAAI,CAAC,cACH,iBAAiB,QAAQ;EAE3B,gBAAgB,QAAQ;CAC1B,GACA,CAAC,cAAc,aAAa,CAGP,CAAQ;AACjC;;;;;AAeA,SAAgB,uBACd,UAAyC,CAAC,GACa;CACvD,MAAM,EAAE,OAAO,iBAAiB,eAAe,CAAC,GAAG,kBAAkB;CAErE,MAAM,CAAC,eAAe,oBACpB,QAAM,SAAmB,YAAY;CAEvC,MAAM,eAAe,oBAAoB,KAAA;CACzC,MAAM,iBAAiB,eAAe,kBAAkB;CAgBxD,OAAO,CAAC,gBAdS,QAAM,aACpB,WAAmB,YAAqB;EACvC,MAAM,WAAW,UACb,CAAC,GAAG,gBAAgB,SAAS,IAC7B,eAAe,QAAQ,MAAM,MAAM,SAAS;EAEhD,IAAI,CAAC,cACH,iBAAiB,QAAQ;EAE3B,gBAAgB,QAAQ;CAC1B,GACA;EAAC;EAAc;EAAgB;CAAa,CAGtB,CAAQ;AAClC;AAMA,IAAa,wBAST;CACF,SAAS;EACP,WAAW;EACX,kBAAkB;EAClB,QAAQ;EACR,IAAI;EACJ,MAAM;CACR;CACA,WAAW;EACT,WAAW;EACX,kBAAkB;EAClB,QAAQ;EACR,IAAI;EACJ,MAAM;CACR;CACA,SAAS;EACP,WAAW;EACX,kBAAkB;EAClB,QAAQ;EACR,IAAI;EACJ,MAAM;CACR;CACA,SAAS;EACP,WAAW;EACX,kBAAkB;EAClB,QAAQ;EACR,IAAI;EACJ,MAAM;CACR;CACA,MAAM;EACJ,WAAW;EACX,kBAAkB;EAClB,QAAQ;EACR,IAAI;EACJ,MAAM;CACR;CACA,aAAa;EACX,WAAW;EACX,kBAAkB;EAClB,QAAQ;EACR,IAAI;EACJ,MAAM;CACR;AACF;;;;;AAUA,IAAa,yBAAyB,IAAI,QAAQ;CAChD,UAAU;EACR,aAAa;GACX,YAAY;GACZ,UAAU;EACZ;EACA,KAAK;GACH,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;CACF;CACA,iBAAiB;EACf,aAAa;EACb,KAAK;CACP;AACF,CAAC;;;;;AAMD,IAAa,6BAA6B,IACxC,0FACA;CACE,UAAU,EACR,MAAM;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;CACN,EACF;CACA,iBAAiB,EACf,MAAM,KACR;AACF,CACF;;;;AAKA,IAAa,4BAA4B,IACvC,8KACA;CACE,UAAU,EACR,MAAM;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;CACN,EACF;CACA,iBAAiB,EACf,MAAM,KACR;AACF,CACF;;;;AAKA,IAAa,gBAA+C;CAC1D,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;;;;AAKA,IAAa,kBAAiD;CAC5D,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;;;;AAKA,IAAa,kBAAiD;CAC5D,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAMA,IAAa,iBAAiB;AAE9B,SAAgB,UAAU,EAAE,aAAqC;CAC/D,OACE,oBAAC,OAAD;EACE,SAAQ;EACR,MAAK;EACL,QAAO;EACP,aAAa;EACb,eAAc;EACd,gBAAe;EACf,WAAW,GAAG,WAAW,oBAAoB;EAE7C,UAAA,oBAAC,QAAD,EAAM,GAAG,eAAiB,CAAA;CACvB,CAAA;AAET;;;;;;AA4BA,IAAM,qBAAqB,QAAM,YAK7B,EACE,MACA,UAAU,OACV,WAAW,OACX,OAAO,MACP,QAAQ,WACR,WACA,gBAAgB,SAElB,QACG;CACH,MAAM,SAAS,sBAAsB;CAErC,IAAI,SAAS,YACX,OACE,oBAAC,QAAD;EACO;EACL,aAAU;EACV,aAAU;EACV,gBAAc;EACd,sBAAoB,iBAAiB,KAAA;EACrC,WAAW,GACT,0BAA0B,EAAE,KAAK,CAAC,GAClC,WAAW,gBACP,GACE,OAAO,kBACP,OAAO,QACP,OAAO,MACP,UACA,sBACF,IACA,8BACJ,YAAY,cACZ,SACF;EACA,eAAY;EAEV,WAAA,WAAW,mBACV,gBACC,oBAAC,OAAD;GACE,WAAW,GACT,gBAAgB,OAChB,8DACF;GACA,aAAa;EACd,CAAA,IAED,oBAAC,WAAD,EAAW,WAAW,gBAAgB,MAAQ,CAAA;CAE9C,CAAA;CAKV,OACE,oBAAC,QAAD;EACO;EACL,aAAU;EACV,aAAU;EACV,gBAAc;EACd,WAAW,GACT,2BAA2B,EAAE,KAAK,CAAC,GACnC,yFACA,+BACA,YAAY,cACZ,SACF;EACA,eAAY;EAEZ,UAAA,oBAAC,QAAD,EACE,WAAW,GACT,yFACA,OAAO,kBACP,cAAc,OACd,UAAU,cAAc,SAC1B,EACD,CAAA;CACG,CAAA;AAEV,CACF;AAEA,mBAAmB,cAAc;AAgBjC,IAAM,6BAA4D;CAChE,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,IAAM,yBAAwD;CAC5D,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;;;;;AAMA,IAAM,eAAe,QAAM,YACxB,EAAE,UAAU,OAAO,MAAM,aAAa,QAAQ;CAC7C,MAAM,gBAAgB,2BAA2B;CACjD,MAAM,YAAY,uBAAuB;CAEzC,OACE,oBAAC,OAAD;EACO;EACL,aAAU;EACV,WAAW,GACT,uDACA,oCACA,sBACA,eACA,SACF;EACA,OAAO,EACL,WAAW,2BACb;EAEA,UAAA,oBAAC,OAAD;GACE,WAAW,GACT,6DACA,SACF;GAEC;EACE,CAAA;CACF,CAAA;AAET,CACF;AAEA,aAAa,cAAc;AAiB3B,IAAM,cAAsC;CAC1C,MAAM;CACN,QAAQ;CACR,KAAK;CACL,SAAS;CACT,OAAO;CACP,SAAS;CACT,SAAS;CACT,OAAO;AACT;AAEA,IAAM,aAA4C;CAChD,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;;;;;AAeA,IAAM,WAAW,QAAM,YACpB,EAAE,OAAO,OAAO,MAAM,aAAa,QAAQ;CAC1C,IAAI,CAAC,OAAO,OAAO;CAEnB,MAAM,aAAa,YAAY;CAC/B,MAAM,aAAa,MAAM,WAAW,GAAG;CAEvC,OACE,oBAAC,QAAD;EACO;EACL,aAAU;EACV,WAAW,GACT,yBACA,WAAW,OACX,CAAC,cAAc,YACf,SACF;EACA,OAAO,aAAa,EAAE,iBAAiB,MAAM,IAAI,KAAA;EACjD,eAAY;CACb,CAAA;AAEL,CACF;AAEA,SAAS,cAAc"}