@humain/ui 2.2.4 → 2.2.5

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 (87) hide show
  1. package/dist/index11.js +4 -4
  2. package/dist/index11.js.map +1 -1
  3. package/dist/index110.js +4 -4
  4. package/dist/index110.js.map +1 -1
  5. package/dist/index134.js +4 -4
  6. package/dist/index134.js.map +1 -1
  7. package/dist/index135.js +2 -2
  8. package/dist/index135.js.map +1 -1
  9. package/dist/index151.js +3 -3
  10. package/dist/index151.js.map +1 -1
  11. package/dist/index152.js +1 -1
  12. package/dist/index152.js.map +1 -1
  13. package/dist/index155.js +1 -1
  14. package/dist/index155.js.map +1 -1
  15. package/dist/index188.js +4 -4
  16. package/dist/index188.js.map +1 -1
  17. package/dist/index201.js +1 -1
  18. package/dist/index201.js.map +1 -1
  19. package/dist/index228.js +1 -1
  20. package/dist/index228.js.map +1 -1
  21. package/dist/index24.js +1 -1
  22. package/dist/index24.js.map +1 -1
  23. package/dist/index25.js +4 -4
  24. package/dist/index25.js.map +1 -1
  25. package/dist/index39.js +2 -2
  26. package/dist/index39.js.map +1 -1
  27. package/dist/index5.js +8 -8
  28. package/dist/index5.js.map +1 -1
  29. package/dist/styles.css +1 -1
  30. package/dist/wc/AIScrollButton.js +8 -8
  31. package/dist/wc/AIScrollButton.js.map +1 -1
  32. package/dist/wc/Badge.js +9 -9
  33. package/dist/wc/Badge.js.map +1 -1
  34. package/dist/wc/Checkbox.js +22 -22
  35. package/dist/wc/Checkbox.js.map +1 -1
  36. package/dist/wc/Pagination.js +4 -4
  37. package/dist/wc/Pagination.js.map +1 -1
  38. package/dist/wc/Switch.js +23 -23
  39. package/dist/wc/Switch.js.map +1 -1
  40. package/dist/wc/Tabs.js +110 -110
  41. package/dist/wc/Tabs.js.map +1 -1
  42. package/dist/wc/Tooltip.js +28 -28
  43. package/dist/wc/Tooltip.js.map +1 -1
  44. package/dist/wc/button.js +33 -33
  45. package/dist/wc/button.js.map +1 -1
  46. package/dist/wc/hf-alert.js +10 -10
  47. package/dist/wc/hf-alert.js.map +1 -1
  48. package/dist/wc/hf-nav-account-menu.js +8 -8
  49. package/dist/wc/hf-nav-account-menu.js.map +1 -1
  50. package/dist/wc/hf-steps.js +8 -8
  51. package/dist/wc/hf-steps.js.map +1 -1
  52. package/dist/wc/markdown-renderer.js +4 -4
  53. package/dist/wc/markdown-renderer.js.map +1 -1
  54. package/dist/wc/selection-group.js +6 -6
  55. package/dist/wc/selection-group.js.map +1 -1
  56. package/dist/wc-react/AIScrollButton.js +18 -18
  57. package/dist/wc-react/AIScrollButton.js.map +1 -1
  58. package/dist/wc-react/Badge.js +16 -16
  59. package/dist/wc-react/Badge.js.map +1 -1
  60. package/dist/wc-react/Checkbox.js +14 -14
  61. package/dist/wc-react/Checkbox.js.map +1 -1
  62. package/dist/wc-react/Pagination.js +130 -130
  63. package/dist/wc-react/Pagination.js.map +1 -1
  64. package/dist/wc-react/Switch.js +2 -2
  65. package/dist/wc-react/Switch.js.map +1 -1
  66. package/dist/wc-react/Tabs.js +38 -38
  67. package/dist/wc-react/Tabs.js.map +1 -1
  68. package/dist/wc-react/Tooltip.js +22 -22
  69. package/dist/wc-react/Tooltip.js.map +1 -1
  70. package/dist/wc-react/button.js +8 -8
  71. package/dist/wc-react/button.js.map +1 -1
  72. package/dist/wc-react/hf-alert.js +28 -28
  73. package/dist/wc-react/hf-alert.js.map +1 -1
  74. package/dist/wc-react/hf-nav-account-menu.js +7 -7
  75. package/dist/wc-react/hf-nav-account-menu.js.map +1 -1
  76. package/dist/wc-react/hf-steps.js +16 -16
  77. package/dist/wc-react/hf-steps.js.map +1 -1
  78. package/dist/wc-react/markdown-renderer.js +4 -4
  79. package/dist/wc-react/markdown-renderer.js.map +1 -1
  80. package/dist/wc-react/selection-group.js +1 -1
  81. package/dist/wc-react/selection-group.js.map +1 -1
  82. package/package.json +1 -1
  83. package/skills/humain-ui/SKILL.md +1 -1
  84. package/skills/humain-ui-wc/SKILL.md +1 -1
  85. package/skills/humain-ui-wc.skill +0 -0
  86. package/skills/humain-ui.skill +0 -0
  87. package/src/tokens.css +10 -2
@@ -1 +1 @@
1
- {"version":3,"file":"index135.js","names":[],"sources":["../src/components/ui/tabs.tsx"],"sourcesContent":["'use client';\n\nimport { Tabs as TabsPrimitive } from '@base-ui/react/tabs';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport * as React from 'react';\n\nimport { cn } from '@/lib/utils';\n\n// ============================================\n// TabsList Variants\n// ============================================\n\nconst tabsListVariants = cva(\n 'group/tabs-list inline-flex w-fit items-center justify-center group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col',\n {\n variants: {\n variant: {\n // Primary variants\n boxed:\n 'bg-muted rounded-lg p-[3px] overflow-clip group-data-[orientation=vertical]/tabs:gap-1',\n pill: 'bg-muted rounded-full p-[3px] overflow-clip group-data-[orientation=vertical]/tabs:gap-1',\n bordered:\n 'gap-3 bg-transparent relative pb-0 w-full rounded-none overflow-x-auto after:absolute after:bottom-0 after:inset-x-0 after:h-px after:bg-border after:z-0 group-data-[orientation=vertical]/tabs:overflow-x-visible group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:inset-x-auto group-data-[orientation=vertical]/tabs:after:left-0 group-data-[orientation=vertical]/tabs:after:w-px group-data-[orientation=vertical]/tabs:after:h-auto group-data-[orientation=vertical]/tabs:w-fit',\n lifted:\n 'gap-0 bg-transparent relative w-full rounded-none overflow-x-auto after:absolute after:bottom-0 after:inset-x-0 after:h-px after:bg-border after:z-0 group-data-[orientation=vertical]/tabs:overflow-x-visible',\n },\n size: {\n sm: '',\n md: '',\n lg: '',\n },\n align: {\n start: '',\n center: '',\n end: '',\n stretch: '',\n },\n borderPosition: {\n bottom: '',\n top: '',\n },\n },\n compoundVariants: [\n // Size applies container height for boxed/pill variants\n {\n variant: 'boxed',\n size: 'sm',\n className: 'group-data-[orientation=horizontal]/tabs:h-[38px]',\n },\n {\n variant: 'boxed',\n size: 'md',\n className: 'group-data-[orientation=horizontal]/tabs:h-[42px]',\n },\n {\n variant: 'boxed',\n size: 'lg',\n className: 'group-data-[orientation=horizontal]/tabs:h-[46px]',\n },\n {\n variant: 'pill',\n size: 'sm',\n className: 'group-data-[orientation=horizontal]/tabs:h-[38px]',\n },\n {\n variant: 'pill',\n size: 'md',\n className: 'group-data-[orientation=horizontal]/tabs:h-[42px]',\n },\n {\n variant: 'pill',\n size: 'lg',\n className: 'group-data-[orientation=horizontal]/tabs:h-[46px]',\n },\n // Alignment for bordered variant\n { variant: 'bordered', align: 'start', className: 'justify-start' },\n { variant: 'bordered', align: 'center', className: 'justify-center' },\n { variant: 'bordered', align: 'end', className: 'justify-end' },\n { variant: 'bordered', align: 'stretch', className: 'justify-start' },\n // Alignment for lifted variant\n { variant: 'lifted', align: 'start', className: 'justify-start' },\n { variant: 'lifted', align: 'center', className: 'justify-center' },\n { variant: 'lifted', align: 'end', className: 'justify-end' },\n { variant: 'lifted', align: 'stretch', className: 'justify-start' },\n // Border position top for bordered/lifted\n {\n variant: 'bordered',\n borderPosition: 'top',\n className: 'after:bottom-auto after:top-0',\n },\n {\n variant: 'lifted',\n borderPosition: 'top',\n className: 'after:bottom-auto after:top-0',\n },\n ],\n defaultVariants: {\n variant: 'boxed',\n size: 'md',\n align: 'start',\n borderPosition: 'bottom',\n },\n },\n);\n\ntype TabsListVariantProps = VariantProps<typeof tabsListVariants>;\n\ninterface TabsListProps extends TabsPrimitive.List.Props, TabsListVariantProps {\n /** Enable gradient styling on active tab */\n gradient?: boolean;\n}\n\n// ============================================\n// TabsTrigger Variants\n// ============================================\n\nconst tabsTriggerVariants = cva([\n // Base\n 'relative inline-flex items-center justify-center whitespace-nowrap',\n 'gap-1.5 border border-transparent font-medium',\n 'transition-[color,background-color,border-color,box-shadow,opacity] duration-200 ease-smooth motion-reduce:transition-none',\n 'group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start',\n 'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring focus-visible:ring-[3px] focus-visible:outline-1',\n 'disabled:pointer-events-none disabled:text-muted-foreground disabled:opacity-70',\n '[&_svg]:pointer-events-none [&_svg]:shrink-0',\n 'text-foreground',\n\n // Size: sm\n 'group-data-[size=sm]/tabs-list:h-9 group-data-[size=sm]/tabs-list:px-2 group-data-[size=sm]/tabs-list:py-1 group-data-[size=sm]/tabs-list:text-sm',\n \"group-data-[size=sm]/tabs-list:[&_svg:not([class*='size-'])]:size-4\",\n // Size: md\n 'group-data-[size=md]/tabs-list:h-10 group-data-[size=md]/tabs-list:px-2.5 group-data-[size=md]/tabs-list:py-[5px] group-data-[size=md]/tabs-list:text-sm',\n \"group-data-[size=md]/tabs-list:[&_svg:not([class*='size-'])]:size-4\",\n // Size: lg\n 'group-data-[size=lg]/tabs-list:h-11 group-data-[size=lg]/tabs-list:px-3 group-data-[size=lg]/tabs-list:py-2 group-data-[size=lg]/tabs-list:text-base',\n \"group-data-[size=lg]/tabs-list:[&_svg:not([class*='size-'])]:size-5\",\n\n // Boxed variant\n 'group-data-[variant=boxed]/tabs-list:rounded-[10px] group-data-[variant=boxed]/tabs-list:flex-1 group-data-[variant=boxed]/tabs-list:h-[calc(100%-1px)]',\n 'group-data-[variant=boxed]/tabs-list:data-active:bg-secondary group-data-[variant=boxed]/tabs-list:data-active:shadow-sm group-data-[variant=boxed]/tabs-list:data-active:text-foreground',\n 'group-data-[variant=boxed]/tabs-list:hover:bg-primary-foreground dark:group-data-[variant=boxed]/tabs-list:hover:bg-input/30',\n 'group-data-[orientation=vertical]/tabs:group-data-[variant=boxed]/tabs-list:flex-initial group-data-[orientation=vertical]/tabs:group-data-[variant=boxed]/tabs-list:justify-center',\n\n // Pill variant\n 'group-data-[variant=pill]/tabs-list:rounded-full group-data-[variant=pill]/tabs-list:flex-1 group-data-[variant=pill]/tabs-list:h-[calc(100%-1px)]',\n 'group-data-[variant=pill]/tabs-list:data-active:bg-background group-data-[variant=pill]/tabs-list:data-active:shadow-sm group-data-[variant=pill]/tabs-list:data-active:text-foreground',\n 'group-data-[variant=pill]/tabs-list:hover:bg-primary-foreground dark:group-data-[variant=pill]/tabs-list:hover:bg-input/30',\n 'dark:group-data-[variant=pill]/tabs-list:data-active:bg-accent dark:group-data-[variant=pill]/tabs-list:data-active:text-accent-foreground dark:group-data-[variant=pill]/tabs-list:data-active:border-input',\n 'group-data-[orientation=vertical]/tabs:group-data-[variant=pill]/tabs-list:flex-initial group-data-[orientation=vertical]/tabs:group-data-[variant=pill]/tabs-list:justify-center',\n\n // Bordered variant\n 'group-data-[variant=bordered]/tabs-list:bg-transparent group-data-[variant=bordered]/tabs-list:rounded-none',\n 'group-data-[variant=bordered]/tabs-list:pb-2.5 group-data-[variant=bordered]/tabs-list:flex-initial',\n 'group-data-[variant=bordered]/tabs-list:data-active:bg-background group-data-[variant=bordered]/tabs-list:data-active:text-primary group-data-[variant=bordered]/tabs-list:data-active:shadow-none',\n 'group-data-[variant=bordered]/tabs-list:group-data-[align=stretch]/tabs-list:flex-1',\n 'group-data-[variant=bordered]/tabs-list:after:bg-primary/90 group-data-[variant=bordered]/tabs-list:after:absolute group-data-[variant=bordered]/tabs-list:after:bottom-0 group-data-[variant=bordered]/tabs-list:after:inset-x-0 group-data-[variant=bordered]/tabs-list:after:h-0.5 group-data-[variant=bordered]/tabs-list:after:z-10 group-data-[variant=bordered]/tabs-list:after:opacity-0 group-data-[variant=bordered]/tabs-list:after:transition-opacity group-data-[variant=bordered]/tabs-list:after:duration-200 group-data-[variant=bordered]/tabs-list:after:ease-out',\n 'group-data-[variant=bordered]/tabs-list:data-active:after:opacity-100',\n 'group-data-[variant=bordered]/tabs-list:hover:after:opacity-100 group-data-[variant=bordered]/tabs-list:hover:after:bg-primary/20',\n 'group-data-[variant=bordered]/tabs-list:data-active:hover:after:bg-primary/90',\n 'group-data-[variant=bordered]/tabs-list:group-data-[border-position=top]/tabs-list:after:bottom-auto group-data-[variant=bordered]/tabs-list:group-data-[border-position=top]/tabs-list:after:top-0',\n 'group-data-[variant=bordered]/tabs-list:group-data-[border-position=top]/tabs-list:pb-0 group-data-[variant=bordered]/tabs-list:group-data-[border-position=top]/tabs-list:pt-2.5',\n 'group-data-[orientation=vertical]/tabs:group-data-[variant=bordered]/tabs-list:after:inset-x-auto group-data-[orientation=vertical]/tabs:group-data-[variant=bordered]/tabs-list:after:inset-y-0 group-data-[orientation=vertical]/tabs:group-data-[variant=bordered]/tabs-list:after:left-0 group-data-[orientation=vertical]/tabs:group-data-[variant=bordered]/tabs-list:after:w-0.5 group-data-[orientation=vertical]/tabs:group-data-[variant=bordered]/tabs-list:after:h-auto',\n 'group-data-[orientation=vertical]/tabs:group-data-[variant=bordered]/tabs-list:pb-0 group-data-[orientation=vertical]/tabs:group-data-[variant=bordered]/tabs-list:pl-2.5',\n\n // Lifted variant — browser-tab style with curved corner connectors\n 'group-data-[variant=lifted]/tabs-list:flex-initial',\n 'group-data-[variant=lifted]/tabs-list:rounded-t-md',\n 'group-data-[variant=lifted]/tabs-list:border-b group-data-[variant=lifted]/tabs-list:border-b-border',\n 'group-data-[variant=lifted]/tabs-list:text-foreground',\n 'group-data-[variant=lifted]/tabs-list:data-active:bg-background',\n 'group-data-[variant=lifted]/tabs-list:data-active:text-primary',\n 'group-data-[variant=lifted]/tabs-list:data-active:border group-data-[variant=lifted]/tabs-list:data-active:border-border',\n 'group-data-[variant=lifted]/tabs-list:data-active:border-b-0 group-data-[variant=lifted]/tabs-list:data-active:border-b-background',\n 'group-data-[variant=lifted]/tabs-list:data-active:rounded-t-[10px]',\n 'group-data-[variant=lifted]/tabs-list:data-active:mb-[-1px] group-data-[variant=lifted]/tabs-list:data-active:z-10',\n 'group-data-[variant=lifted]/tabs-list:data-active:before:absolute group-data-[variant=lifted]/tabs-list:data-active:before:bottom-0 group-data-[variant=lifted]/tabs-list:data-active:before:left-[-10px] group-data-[variant=lifted]/tabs-list:data-active:before:size-[10px] group-data-[variant=lifted]/tabs-list:data-active:before:rounded-br-[10px] group-data-[variant=lifted]/tabs-list:data-active:before:border-b group-data-[variant=lifted]/tabs-list:data-active:before:border-r group-data-[variant=lifted]/tabs-list:data-active:before:border-border group-data-[variant=lifted]/tabs-list:data-active:before:bg-background group-data-[variant=lifted]/tabs-list:data-active:before:shadow-[2px_2px_0_0_var(--background)]',\n 'group-data-[variant=lifted]/tabs-list:data-active:after:absolute group-data-[variant=lifted]/tabs-list:data-active:after:bottom-0 group-data-[variant=lifted]/tabs-list:data-active:after:right-[-10px] group-data-[variant=lifted]/tabs-list:data-active:after:size-[10px] group-data-[variant=lifted]/tabs-list:data-active:after:rounded-bl-[10px] group-data-[variant=lifted]/tabs-list:data-active:after:border-b group-data-[variant=lifted]/tabs-list:data-active:after:border-l group-data-[variant=lifted]/tabs-list:data-active:after:border-border group-data-[variant=lifted]/tabs-list:data-active:after:bg-background group-data-[variant=lifted]/tabs-list:data-active:after:shadow-[-2px_2px_0_0_var(--background)]',\n 'group-data-[variant=lifted]/tabs-list:group-data-[align=stretch]/tabs-list:flex-1',\n\n // Gradient support (uses brand tokens)\n 'group-data-[variant=boxed]/tabs-list:group-data-[gradient]/tabs-list:data-active:bg-[linear-gradient(100deg,var(--air-100)/0.1,var(--primary)/0.1)] group-data-[variant=boxed]/tabs-list:group-data-[gradient]/tabs-list:data-active:text-primary',\n 'group-data-[variant=pill]/tabs-list:group-data-[gradient]/tabs-list:data-active:bg-[linear-gradient(98deg,var(--air-100),var(--primary))] group-data-[variant=pill]/tabs-list:group-data-[gradient]/tabs-list:data-active:text-primary-foreground',\n\n // Hide pseudo-element underline when TabsIndicator is used\n 'group-has-[[data-slot=tabs-indicator]]/tabs-list:after:hidden',\n]);\n\n// ============================================\n// Components\n// ============================================\n\nconst Tabs = React.forwardRef<HTMLDivElement, TabsPrimitive.Root.Props>(\n ({ className, orientation = 'horizontal', ...props }, ref) => (\n <TabsPrimitive.Root\n ref={ref}\n data-slot=\"tabs\"\n data-orientation={orientation}\n className={cn(\n 'gap-2 group/tabs flex data-[orientation=horizontal]:flex-col',\n className,\n )}\n {...props}\n />\n ),\n);\n\nconst TabsList = React.forwardRef<HTMLDivElement, TabsListProps>(\n (\n {\n className,\n variant = 'boxed',\n size = 'md',\n align = 'start',\n borderPosition = 'bottom',\n gradient,\n ...props\n },\n ref,\n ) => {\n return (\n <TabsPrimitive.List\n ref={ref}\n data-slot=\"tabs-list\"\n data-variant={variant}\n data-align={align}\n data-size={size}\n data-border-position={borderPosition}\n {...(gradient ? { 'data-gradient': '' } : {})}\n className={cn(\n tabsListVariants({ variant, size, align, borderPosition }),\n className,\n )}\n {...props}\n />\n );\n },\n);\n\nconst TabsTrigger = React.forwardRef<\n HTMLButtonElement,\n TabsPrimitive.Tab.Props\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Tab\n ref={ref}\n data-slot=\"tabs-trigger\"\n className={cn(tabsTriggerVariants(), className)}\n {...props}\n />\n));\n\nconst TabsContent = React.forwardRef<HTMLDivElement, TabsPrimitive.Panel.Props>(\n ({ className, ...props }, ref) => (\n <TabsPrimitive.Panel\n ref={ref}\n data-slot=\"tabs-content\"\n className={cn(\n 'flex-1 focus-visible:outline-none delight-fade-in',\n className,\n )}\n {...props}\n />\n ),\n);\n\n/**\n * Animated indicator that slides to the active tab position.\n * Use with `variant=\"bordered\"` on TabsList.\n *\n * @example\n * ```tsx\n * <TabsList variant=\"bordered\">\n * <TabsTrigger value=\"tab1\">Tab 1</TabsTrigger>\n * <TabsTrigger value=\"tab2\">Tab 2</TabsTrigger>\n * <TabsIndicator />\n * </TabsList>\n * ```\n */\nconst TabsIndicator = React.forwardRef<\n HTMLSpanElement,\n TabsPrimitive.Indicator.Props\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Indicator\n ref={ref}\n data-slot=\"tabs-indicator\"\n className={cn(\n 'absolute bottom-0 left-0 h-0.5 z-10 bg-primary/90',\n 'w-[var(--active-tab-width)]',\n // Width must be layout-animated (Base UI constraint); transform is GPU-composited\n 'transition-[transform,width] duration-300 ease-smooth motion-reduce:transition-none',\n className,\n )}\n style={{\n transform: 'translateX(var(--active-tab-left, 0px))',\n }}\n {...props}\n />\n));\n\nTabs.displayName = 'Tabs';\nTabsList.displayName = 'TabsList';\nTabsTrigger.displayName = 'TabsTrigger';\nTabsContent.displayName = 'TabsContent';\nTabsIndicator.displayName = 'TabsIndicator';\n\nexport {\n Tabs,\n TabsContent,\n TabsIndicator,\n TabsList,\n TabsTrigger,\n tabsListVariants,\n tabsTriggerVariants,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index135.js","names":[],"sources":["../src/components/ui/tabs.tsx"],"sourcesContent":["'use client';\n\nimport { Tabs as TabsPrimitive } from '@base-ui/react/tabs';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport * as React from 'react';\n\nimport { cn } from '@/lib/utils';\n\n// ============================================\n// TabsList Variants\n// ============================================\n\nconst tabsListVariants = cva(\n 'group/tabs-list inline-flex w-fit items-center justify-center group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col',\n {\n variants: {\n variant: {\n // Primary variants\n boxed:\n 'bg-muted rounded-lg p-[3px] overflow-clip group-data-[orientation=vertical]/tabs:gap-1',\n pill: 'bg-muted rounded-full p-[3px] overflow-clip group-data-[orientation=vertical]/tabs:gap-1',\n bordered:\n 'gap-3 bg-transparent relative pb-0 w-full rounded-none overflow-x-auto after:absolute after:bottom-0 after:inset-x-0 after:h-px after:bg-border after:z-0 group-data-[orientation=vertical]/tabs:overflow-x-visible group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:inset-x-auto group-data-[orientation=vertical]/tabs:after:left-0 group-data-[orientation=vertical]/tabs:after:w-px group-data-[orientation=vertical]/tabs:after:h-auto group-data-[orientation=vertical]/tabs:w-fit',\n lifted:\n 'gap-0 bg-transparent relative w-full rounded-none overflow-x-auto after:absolute after:bottom-0 after:inset-x-0 after:h-px after:bg-border after:z-0 group-data-[orientation=vertical]/tabs:overflow-x-visible',\n },\n size: {\n sm: '',\n md: '',\n lg: '',\n },\n align: {\n start: '',\n center: '',\n end: '',\n stretch: '',\n },\n borderPosition: {\n bottom: '',\n top: '',\n },\n },\n compoundVariants: [\n // Size applies container height for boxed/pill variants\n {\n variant: 'boxed',\n size: 'sm',\n className: 'group-data-[orientation=horizontal]/tabs:h-[38px]',\n },\n {\n variant: 'boxed',\n size: 'md',\n className: 'group-data-[orientation=horizontal]/tabs:h-[42px]',\n },\n {\n variant: 'boxed',\n size: 'lg',\n className: 'group-data-[orientation=horizontal]/tabs:h-[46px]',\n },\n {\n variant: 'pill',\n size: 'sm',\n className: 'group-data-[orientation=horizontal]/tabs:h-[38px]',\n },\n {\n variant: 'pill',\n size: 'md',\n className: 'group-data-[orientation=horizontal]/tabs:h-[42px]',\n },\n {\n variant: 'pill',\n size: 'lg',\n className: 'group-data-[orientation=horizontal]/tabs:h-[46px]',\n },\n // Alignment for bordered variant\n { variant: 'bordered', align: 'start', className: 'justify-start' },\n { variant: 'bordered', align: 'center', className: 'justify-center' },\n { variant: 'bordered', align: 'end', className: 'justify-end' },\n { variant: 'bordered', align: 'stretch', className: 'justify-start' },\n // Alignment for lifted variant\n { variant: 'lifted', align: 'start', className: 'justify-start' },\n { variant: 'lifted', align: 'center', className: 'justify-center' },\n { variant: 'lifted', align: 'end', className: 'justify-end' },\n { variant: 'lifted', align: 'stretch', className: 'justify-start' },\n // Border position top for bordered/lifted\n {\n variant: 'bordered',\n borderPosition: 'top',\n className: 'after:bottom-auto after:top-0',\n },\n {\n variant: 'lifted',\n borderPosition: 'top',\n className: 'after:bottom-auto after:top-0',\n },\n ],\n defaultVariants: {\n variant: 'boxed',\n size: 'md',\n align: 'start',\n borderPosition: 'bottom',\n },\n },\n);\n\ntype TabsListVariantProps = VariantProps<typeof tabsListVariants>;\n\ninterface TabsListProps extends TabsPrimitive.List.Props, TabsListVariantProps {\n /** Enable gradient styling on active tab */\n gradient?: boolean;\n}\n\n// ============================================\n// TabsTrigger Variants\n// ============================================\n\nconst tabsTriggerVariants = cva([\n // Base\n 'relative inline-flex items-center justify-center whitespace-nowrap',\n 'gap-1.5 border border-transparent font-medium',\n 'transition-[color,background-color,border-color,box-shadow,opacity] duration-200 ease-smooth motion-reduce:transition-none',\n 'group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start',\n 'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring focus-visible:ring-[3px] focus-visible:outline-1',\n 'disabled:pointer-events-none disabled:text-muted-foreground disabled:opacity-70',\n '[&_svg]:pointer-events-none [&_svg]:shrink-0',\n 'text-foreground',\n\n // Size: sm\n 'group-data-[size=sm]/tabs-list:h-9 group-data-[size=sm]/tabs-list:px-2 group-data-[size=sm]/tabs-list:py-1 group-data-[size=sm]/tabs-list:text-sm',\n \"group-data-[size=sm]/tabs-list:[&_svg:not([class*='size-'])]:size-4\",\n // Size: md\n 'group-data-[size=md]/tabs-list:h-10 group-data-[size=md]/tabs-list:px-2.5 group-data-[size=md]/tabs-list:py-[5px] group-data-[size=md]/tabs-list:text-sm',\n \"group-data-[size=md]/tabs-list:[&_svg:not([class*='size-'])]:size-4\",\n // Size: lg\n 'group-data-[size=lg]/tabs-list:h-11 group-data-[size=lg]/tabs-list:px-3 group-data-[size=lg]/tabs-list:py-2 group-data-[size=lg]/tabs-list:text-base',\n \"group-data-[size=lg]/tabs-list:[&_svg:not([class*='size-'])]:size-5\",\n\n // Boxed variant\n 'group-data-[variant=boxed]/tabs-list:rounded-[10px] group-data-[variant=boxed]/tabs-list:flex-1 group-data-[variant=boxed]/tabs-list:h-[calc(100%-1px)]',\n 'group-data-[variant=boxed]/tabs-list:data-active:bg-secondary group-data-[variant=boxed]/tabs-list:data-active:shadow-sm group-data-[variant=boxed]/tabs-list:data-active:text-foreground',\n 'group-data-[variant=boxed]/tabs-list:hover:bg-accent',\n 'group-data-[orientation=vertical]/tabs:group-data-[variant=boxed]/tabs-list:flex-initial group-data-[orientation=vertical]/tabs:group-data-[variant=boxed]/tabs-list:justify-center',\n\n // Pill variant\n 'group-data-[variant=pill]/tabs-list:rounded-full group-data-[variant=pill]/tabs-list:flex-1 group-data-[variant=pill]/tabs-list:h-[calc(100%-1px)]',\n 'group-data-[variant=pill]/tabs-list:data-active:bg-background group-data-[variant=pill]/tabs-list:data-active:shadow-sm group-data-[variant=pill]/tabs-list:data-active:text-foreground',\n 'group-data-[variant=pill]/tabs-list:hover:bg-accent',\n 'dark:group-data-[variant=pill]/tabs-list:data-active:bg-accent dark:group-data-[variant=pill]/tabs-list:data-active:text-accent-foreground dark:group-data-[variant=pill]/tabs-list:data-active:border-input',\n 'group-data-[orientation=vertical]/tabs:group-data-[variant=pill]/tabs-list:flex-initial group-data-[orientation=vertical]/tabs:group-data-[variant=pill]/tabs-list:justify-center',\n\n // Bordered variant\n 'group-data-[variant=bordered]/tabs-list:bg-transparent group-data-[variant=bordered]/tabs-list:rounded-none',\n 'group-data-[variant=bordered]/tabs-list:pb-2.5 group-data-[variant=bordered]/tabs-list:flex-initial',\n 'group-data-[variant=bordered]/tabs-list:data-active:bg-background group-data-[variant=bordered]/tabs-list:data-active:text-primary group-data-[variant=bordered]/tabs-list:data-active:shadow-none',\n 'group-data-[variant=bordered]/tabs-list:group-data-[align=stretch]/tabs-list:flex-1',\n 'group-data-[variant=bordered]/tabs-list:after:bg-primary/90 group-data-[variant=bordered]/tabs-list:after:absolute group-data-[variant=bordered]/tabs-list:after:bottom-0 group-data-[variant=bordered]/tabs-list:after:inset-x-0 group-data-[variant=bordered]/tabs-list:after:h-0.5 group-data-[variant=bordered]/tabs-list:after:z-10 group-data-[variant=bordered]/tabs-list:after:opacity-0 group-data-[variant=bordered]/tabs-list:after:transition-opacity group-data-[variant=bordered]/tabs-list:after:duration-200 group-data-[variant=bordered]/tabs-list:after:ease-out',\n 'group-data-[variant=bordered]/tabs-list:data-active:after:opacity-100',\n 'group-data-[variant=bordered]/tabs-list:hover:after:opacity-100 group-data-[variant=bordered]/tabs-list:hover:after:bg-primary/20',\n 'group-data-[variant=bordered]/tabs-list:data-active:hover:after:bg-primary/90',\n 'group-data-[variant=bordered]/tabs-list:group-data-[border-position=top]/tabs-list:after:bottom-auto group-data-[variant=bordered]/tabs-list:group-data-[border-position=top]/tabs-list:after:top-0',\n 'group-data-[variant=bordered]/tabs-list:group-data-[border-position=top]/tabs-list:pb-0 group-data-[variant=bordered]/tabs-list:group-data-[border-position=top]/tabs-list:pt-2.5',\n 'group-data-[orientation=vertical]/tabs:group-data-[variant=bordered]/tabs-list:after:inset-x-auto group-data-[orientation=vertical]/tabs:group-data-[variant=bordered]/tabs-list:after:inset-y-0 group-data-[orientation=vertical]/tabs:group-data-[variant=bordered]/tabs-list:after:left-0 group-data-[orientation=vertical]/tabs:group-data-[variant=bordered]/tabs-list:after:w-0.5 group-data-[orientation=vertical]/tabs:group-data-[variant=bordered]/tabs-list:after:h-auto',\n 'group-data-[orientation=vertical]/tabs:group-data-[variant=bordered]/tabs-list:pb-0 group-data-[orientation=vertical]/tabs:group-data-[variant=bordered]/tabs-list:pl-2.5',\n\n // Lifted variant — browser-tab style with curved corner connectors\n 'group-data-[variant=lifted]/tabs-list:flex-initial',\n 'group-data-[variant=lifted]/tabs-list:rounded-t-md',\n 'group-data-[variant=lifted]/tabs-list:border-b group-data-[variant=lifted]/tabs-list:border-b-border',\n 'group-data-[variant=lifted]/tabs-list:text-foreground',\n 'group-data-[variant=lifted]/tabs-list:data-active:bg-background',\n 'group-data-[variant=lifted]/tabs-list:data-active:text-primary',\n 'group-data-[variant=lifted]/tabs-list:data-active:border group-data-[variant=lifted]/tabs-list:data-active:border-border',\n 'group-data-[variant=lifted]/tabs-list:data-active:border-b-0 group-data-[variant=lifted]/tabs-list:data-active:border-b-background',\n 'group-data-[variant=lifted]/tabs-list:data-active:rounded-t-[10px]',\n 'group-data-[variant=lifted]/tabs-list:data-active:mb-[-1px] group-data-[variant=lifted]/tabs-list:data-active:z-10',\n 'group-data-[variant=lifted]/tabs-list:data-active:before:absolute group-data-[variant=lifted]/tabs-list:data-active:before:bottom-0 group-data-[variant=lifted]/tabs-list:data-active:before:left-[-10px] group-data-[variant=lifted]/tabs-list:data-active:before:size-[10px] group-data-[variant=lifted]/tabs-list:data-active:before:rounded-br-[10px] group-data-[variant=lifted]/tabs-list:data-active:before:border-b group-data-[variant=lifted]/tabs-list:data-active:before:border-r group-data-[variant=lifted]/tabs-list:data-active:before:border-border group-data-[variant=lifted]/tabs-list:data-active:before:bg-background group-data-[variant=lifted]/tabs-list:data-active:before:shadow-[2px_2px_0_0_var(--background)]',\n 'group-data-[variant=lifted]/tabs-list:data-active:after:absolute group-data-[variant=lifted]/tabs-list:data-active:after:bottom-0 group-data-[variant=lifted]/tabs-list:data-active:after:right-[-10px] group-data-[variant=lifted]/tabs-list:data-active:after:size-[10px] group-data-[variant=lifted]/tabs-list:data-active:after:rounded-bl-[10px] group-data-[variant=lifted]/tabs-list:data-active:after:border-b group-data-[variant=lifted]/tabs-list:data-active:after:border-l group-data-[variant=lifted]/tabs-list:data-active:after:border-border group-data-[variant=lifted]/tabs-list:data-active:after:bg-background group-data-[variant=lifted]/tabs-list:data-active:after:shadow-[-2px_2px_0_0_var(--background)]',\n 'group-data-[variant=lifted]/tabs-list:group-data-[align=stretch]/tabs-list:flex-1',\n\n // Gradient support (uses brand tokens)\n 'group-data-[variant=boxed]/tabs-list:group-data-[gradient]/tabs-list:data-active:bg-[linear-gradient(100deg,var(--air-100)/0.1,var(--primary)/0.1)] group-data-[variant=boxed]/tabs-list:group-data-[gradient]/tabs-list:data-active:text-primary',\n 'group-data-[variant=pill]/tabs-list:group-data-[gradient]/tabs-list:data-active:bg-[linear-gradient(98deg,var(--air-100),var(--primary))] group-data-[variant=pill]/tabs-list:group-data-[gradient]/tabs-list:data-active:text-primary-foreground',\n\n // Hide pseudo-element underline when TabsIndicator is used\n 'group-has-[[data-slot=tabs-indicator]]/tabs-list:after:hidden',\n]);\n\n// ============================================\n// Components\n// ============================================\n\nconst Tabs = React.forwardRef<HTMLDivElement, TabsPrimitive.Root.Props>(\n ({ className, orientation = 'horizontal', ...props }, ref) => (\n <TabsPrimitive.Root\n ref={ref}\n data-slot=\"tabs\"\n data-orientation={orientation}\n className={cn(\n 'gap-2 group/tabs flex data-[orientation=horizontal]:flex-col',\n className,\n )}\n {...props}\n />\n ),\n);\n\nconst TabsList = React.forwardRef<HTMLDivElement, TabsListProps>(\n (\n {\n className,\n variant = 'boxed',\n size = 'md',\n align = 'start',\n borderPosition = 'bottom',\n gradient,\n ...props\n },\n ref,\n ) => {\n return (\n <TabsPrimitive.List\n ref={ref}\n data-slot=\"tabs-list\"\n data-variant={variant}\n data-align={align}\n data-size={size}\n data-border-position={borderPosition}\n {...(gradient ? { 'data-gradient': '' } : {})}\n className={cn(\n tabsListVariants({ variant, size, align, borderPosition }),\n className,\n )}\n {...props}\n />\n );\n },\n);\n\nconst TabsTrigger = React.forwardRef<\n HTMLButtonElement,\n TabsPrimitive.Tab.Props\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Tab\n ref={ref}\n data-slot=\"tabs-trigger\"\n className={cn(tabsTriggerVariants(), className)}\n {...props}\n />\n));\n\nconst TabsContent = React.forwardRef<HTMLDivElement, TabsPrimitive.Panel.Props>(\n ({ className, ...props }, ref) => (\n <TabsPrimitive.Panel\n ref={ref}\n data-slot=\"tabs-content\"\n className={cn(\n 'flex-1 focus-visible:outline-none delight-fade-in',\n className,\n )}\n {...props}\n />\n ),\n);\n\n/**\n * Animated indicator that slides to the active tab position.\n * Use with `variant=\"bordered\"` on TabsList.\n *\n * @example\n * ```tsx\n * <TabsList variant=\"bordered\">\n * <TabsTrigger value=\"tab1\">Tab 1</TabsTrigger>\n * <TabsTrigger value=\"tab2\">Tab 2</TabsTrigger>\n * <TabsIndicator />\n * </TabsList>\n * ```\n */\nconst TabsIndicator = React.forwardRef<\n HTMLSpanElement,\n TabsPrimitive.Indicator.Props\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Indicator\n ref={ref}\n data-slot=\"tabs-indicator\"\n className={cn(\n 'absolute bottom-0 left-0 h-0.5 z-10 bg-primary/90',\n 'w-[var(--active-tab-width)]',\n // Width must be layout-animated (Base UI constraint); transform is GPU-composited\n 'transition-[transform,width] duration-300 ease-smooth motion-reduce:transition-none',\n className,\n )}\n style={{\n transform: 'translateX(var(--active-tab-left, 0px))',\n }}\n {...props}\n />\n));\n\nTabs.displayName = 'Tabs';\nTabsList.displayName = 'TabsList';\nTabsTrigger.displayName = 'TabsTrigger';\nTabsContent.displayName = 'TabsContent';\nTabsIndicator.displayName = 'TabsIndicator';\n\nexport {\n Tabs,\n TabsContent,\n TabsIndicator,\n TabsList,\n TabsTrigger,\n tabsListVariants,\n tabsTriggerVariants,\n};\n"],"mappings":"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"}
package/dist/index151.js CHANGED
@@ -68,7 +68,7 @@ function renderRenderOnlyComponent(language, content) {
68
68
  }
69
69
  function renderInteractiveError({ language, inverted, message }) {
70
70
  return /* @__PURE__ */ jsxs("div", {
71
- className: cn("my-4 p-4 rounded-lg", inverted ? "border border-primary-foreground/30 bg-primary-foreground/10 text-primary-foreground text-sm" : "border border-destructive bg-destructive/20 text-destructive text-sm"),
71
+ className: cn("my-4 p-4 rounded-lg", inverted ? "border border-primary-foreground/30 bg-background/10 text-primary-foreground text-sm" : "border border-destructive bg-destructive/20 text-destructive text-sm"),
72
72
  role: "alert",
73
73
  "data-slot": "ai-interactive-error",
74
74
  children: [
@@ -98,7 +98,7 @@ function renderCodeBlock({ code, language, inverted }) {
98
98
  });
99
99
  if (!inverted) return block;
100
100
  return /* @__PURE__ */ jsx("div", {
101
- className: "my-4 [&_[data-slot=ai-code-block]]:bg-primary-foreground/10 [&_[data-slot=ai-code-block]]:border-primary-foreground/20 [&_[data-slot=ai-code-block-header]]:bg-primary-foreground/5 [&_[data-slot=ai-code-block-header]]:border-primary-foreground/20 [&_[data-slot=ai-code-block-header]_span]:!text-primary-foreground/60 [&_[data-slot=ai-code-block-header]_button]:!text-primary-foreground/60",
101
+ className: "my-4 [&_[data-slot=ai-code-block]]:bg-background/10 [&_[data-slot=ai-code-block]]:border-primary-foreground/20 [&_[data-slot=ai-code-block-header]]:bg-background/5 [&_[data-slot=ai-code-block-header]]:border-primary-foreground/20 [&_[data-slot=ai-code-block-header]_span]:!text-primary-foreground/60 [&_[data-slot=ai-code-block-header]_button]:!text-primary-foreground/60",
102
102
  style: INVERTED_SUGAR_HIGH_STYLE,
103
103
  children: block
104
104
  });
@@ -107,7 +107,7 @@ function createCodeComponent(variant = "default") {
107
107
  const inv = variant === "inverted";
108
108
  return function UnifiedCodeBlock({ className, children }) {
109
109
  if (!className?.includes("language-")) return /* @__PURE__ */ jsx("code", {
110
- className: cn("px-1.5 py-0.5 rounded text-sm font-mono transition-colors", "break-words [overflow-wrap:anywhere]", inv ? "bg-primary-foreground/15 text-primary-foreground" : "bg-accent text-foreground", className),
110
+ className: cn("px-1.5 py-0.5 rounded text-sm font-mono transition-colors", "break-words [overflow-wrap:anywhere]", inv ? "bg-background/15 text-primary-foreground" : "bg-accent text-foreground", className),
111
111
  children
112
112
  });
113
113
  const match = /language-(\w+)/.exec(className || "");
@@ -1 +1 @@
1
- {"version":3,"file":"index151.js","names":[],"sources":["../src/components/organisms/ai/_shared/code-handler.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { INVERTED_SUGAR_HIGH_STYLE } from '@/lib/syntax-highlight';\nimport { cn } from '@/lib/utils';\nimport { validateInteractiveSchema } from './schema-validation';\nimport type { MarkdownVariant } from './types';\n\n// =============================================================================\n// Lazy-loaded renderers\n// =============================================================================\n\nconst LazyAIMermaidDiagram = React.lazy(\n () => import('@/components/organisms/ai/AIMermaidDiagram'),\n);\nconst LazyAIAsciiDiagram = React.lazy(\n () => import('@/components/organisms/ai/AIAsciiDiagram'),\n);\nconst LazyAIChart = React.lazy(\n () => import('@/components/organisms/ai/AIChart'),\n);\nconst LazyAITable = React.lazy(\n () => import('@/components/organisms/ai/AITable'),\n);\nconst LazyAIForm = React.lazy(() => import('@/components/organisms/ai/AIForm'));\nconst LazyAISelect = React.lazy(\n () => import('@/components/organisms/ai/AISelect'),\n);\nconst LazyAICodeBlock = React.lazy(() =>\n import('@/components/organisms/ai/AICodeBlock').then((module) => ({\n default: module.AICodeBlock,\n })),\n);\n\n// =============================================================================\n// Loading skeleton for lazy components\n// =============================================================================\n\nfunction LazyLoadingSkeleton() {\n return (\n <div className=\"my-4 flex items-center justify-center p-8 rounded-xl border border-border bg-muted animate-pulse\">\n <div className=\"h-4 w-32 bg-accent rounded\" />\n </div>\n );\n}\n\n// =============================================================================\n// Interactive languages (fire onInteraction events)\n// =============================================================================\n\nconst INTERACTIVE_LANGUAGES = ['chart', 'select', 'table', 'form'] as const;\ntype InteractiveLanguage = (typeof INTERACTIVE_LANGUAGES)[number];\n\nfunction isInteractiveLanguage(\n language: string,\n): language is InteractiveLanguage {\n return INTERACTIVE_LANGUAGES.includes(language as InteractiveLanguage);\n}\n\n// =============================================================================\n// Render-only languages (visual output, no interaction events)\n// =============================================================================\n\nconst RENDER_ONLY_LANGUAGES = ['mermaid', 'ascii'] as const;\ntype RenderOnlyLanguage = (typeof RENDER_ONLY_LANGUAGES)[number];\n\nfunction isRenderOnlyLanguage(\n language: string,\n): language is RenderOnlyLanguage {\n return RENDER_ONLY_LANGUAGES.includes(language as RenderOnlyLanguage);\n}\n\n// =============================================================================\n// Component lookup maps\n// =============================================================================\n\ntype InteractiveComponentProps = {\n schema: unknown;\n};\n\ntype CodeRendererEntry = {\n Component: React.LazyExoticComponent<React.ComponentType<{ code: string }>>;\n prop: 'code';\n};\n\ntype ContentRendererEntry = {\n Component: React.LazyExoticComponent<\n React.ComponentType<{ content: string }>\n >;\n prop: 'content';\n};\n\ntype RenderOnlyComponentEntry = CodeRendererEntry | ContentRendererEntry;\n\nconst INTERACTIVE_COMPONENTS: Record<\n InteractiveLanguage,\n React.LazyExoticComponent<React.ComponentType<InteractiveComponentProps>>\n> = {\n chart: LazyAIChart as React.LazyExoticComponent<\n React.ComponentType<InteractiveComponentProps>\n >,\n select: LazyAISelect as React.LazyExoticComponent<\n React.ComponentType<InteractiveComponentProps>\n >,\n table: LazyAITable as React.LazyExoticComponent<\n React.ComponentType<InteractiveComponentProps>\n >,\n form: LazyAIForm as React.LazyExoticComponent<\n React.ComponentType<InteractiveComponentProps>\n >,\n};\n\nconst RENDER_ONLY_COMPONENTS: Record<\n RenderOnlyLanguage,\n RenderOnlyComponentEntry\n> = {\n mermaid: {\n Component: LazyAIMermaidDiagram as React.LazyExoticComponent<\n React.ComponentType<{ code: string }>\n >,\n prop: 'code',\n },\n ascii: {\n Component: LazyAIAsciiDiagram as React.LazyExoticComponent<\n React.ComponentType<{ content: string }>\n >,\n prop: 'content',\n },\n};\n\nconst LOADING_FALLBACK = <LazyLoadingSkeleton />;\n\n// =============================================================================\n// Render helpers\n// =============================================================================\n\nfunction renderInteractiveComponent(\n language: InteractiveLanguage,\n schema: unknown,\n): React.ReactElement {\n const Component = INTERACTIVE_COMPONENTS[language];\n return (\n <React.Suspense fallback={LOADING_FALLBACK}>\n <Component schema={schema} />\n </React.Suspense>\n );\n}\n\nfunction renderRenderOnlyComponent(\n language: RenderOnlyLanguage,\n content: string,\n): React.ReactElement {\n const { Component, prop } = RENDER_ONLY_COMPONENTS[language];\n if (prop === 'code') {\n return (\n <React.Suspense fallback={LOADING_FALLBACK}>\n <Component code={content} />\n </React.Suspense>\n );\n }\n\n return (\n <React.Suspense fallback={LOADING_FALLBACK}>\n <Component content={content} />\n </React.Suspense>\n );\n}\n\nfunction renderInteractiveError({\n language,\n inverted,\n message,\n}: {\n language: InteractiveLanguage;\n inverted: boolean;\n message: string;\n}): React.ReactElement {\n return (\n <div\n className={cn(\n 'my-4 p-4 rounded-lg',\n inverted\n ? 'border border-primary-foreground/30 bg-primary-foreground/10 text-primary-foreground text-sm'\n : 'border border-destructive bg-destructive/20 text-destructive text-sm',\n )}\n role=\"alert\"\n data-slot=\"ai-interactive-error\"\n >\n <span className=\"font-semibold\">Invalid {language} schema:</span>{' '}\n {message}\n </div>\n );\n}\n\nfunction renderCodeBlock({\n code,\n language,\n inverted,\n}: {\n code: string;\n language: string;\n inverted: boolean;\n}): React.ReactElement {\n const block = (\n <React.Suspense fallback={LOADING_FALLBACK}>\n <LazyAICodeBlock\n code={code}\n language={language}\n showHeader={true}\n showCopyButton={true}\n className={inverted ? undefined : 'my-4'}\n />\n </React.Suspense>\n );\n\n if (!inverted) {\n return block;\n }\n\n return (\n <div\n className=\"my-4 [&_[data-slot=ai-code-block]]:bg-primary-foreground/10 [&_[data-slot=ai-code-block]]:border-primary-foreground/20 [&_[data-slot=ai-code-block-header]]:bg-primary-foreground/5 [&_[data-slot=ai-code-block-header]]:border-primary-foreground/20 [&_[data-slot=ai-code-block-header]_span]:!text-primary-foreground/60 [&_[data-slot=ai-code-block-header]_button]:!text-primary-foreground/60\"\n style={INVERTED_SUGAR_HIGH_STYLE}\n >\n {block}\n </div>\n );\n}\n\n// =============================================================================\n// Unified code component for react-markdown\n// =============================================================================\n\nfunction createCodeComponent(variant: MarkdownVariant = 'default'): React.FC<{\n className?: string;\n children?: React.ReactNode;\n}> {\n const inv = variant === 'inverted';\n\n return function UnifiedCodeBlock({ className, children }) {\n const isInline = !className?.includes('language-');\n\n if (isInline) {\n return (\n <code\n className={cn(\n 'px-1.5 py-0.5 rounded text-sm font-mono transition-colors',\n 'break-words [overflow-wrap:anywhere]',\n inv\n ? 'bg-primary-foreground/15 text-primary-foreground'\n : 'bg-accent text-foreground',\n className,\n )}\n >\n {children}\n </code>\n );\n }\n\n const match = /language-(\\w+)/.exec(className || '');\n const language = match ? match[1] : 'plaintext';\n const content = String(children).replace(/\\n$/, '');\n\n if (isRenderOnlyLanguage(language)) {\n return renderRenderOnlyComponent(language, content);\n }\n\n if (isInteractiveLanguage(language)) {\n try {\n const schema = JSON.parse(content);\n const validation = validateInteractiveSchema(language, schema);\n\n if (!validation.valid) {\n return renderInteractiveError({\n language,\n inverted: inv,\n message:\n 'The configuration does not match the expected schema shape.',\n });\n }\n\n return renderInteractiveComponent(language, validation.schema);\n } catch {\n return renderInteractiveError({\n language,\n inverted: inv,\n message:\n 'Unable to parse the configuration. Please check the JSON syntax.',\n });\n }\n }\n\n return renderCodeBlock({ code: content, language, inverted: inv });\n };\n}\n\nexport { createCodeComponent, LazyLoadingSkeleton };\n"],"mappings":"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"}
1
+ {"version":3,"file":"index151.js","names":[],"sources":["../src/components/organisms/ai/_shared/code-handler.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { INVERTED_SUGAR_HIGH_STYLE } from '@/lib/syntax-highlight';\nimport { cn } from '@/lib/utils';\nimport { validateInteractiveSchema } from './schema-validation';\nimport type { MarkdownVariant } from './types';\n\n// =============================================================================\n// Lazy-loaded renderers\n// =============================================================================\n\nconst LazyAIMermaidDiagram = React.lazy(\n () => import('@/components/organisms/ai/AIMermaidDiagram'),\n);\nconst LazyAIAsciiDiagram = React.lazy(\n () => import('@/components/organisms/ai/AIAsciiDiagram'),\n);\nconst LazyAIChart = React.lazy(\n () => import('@/components/organisms/ai/AIChart'),\n);\nconst LazyAITable = React.lazy(\n () => import('@/components/organisms/ai/AITable'),\n);\nconst LazyAIForm = React.lazy(() => import('@/components/organisms/ai/AIForm'));\nconst LazyAISelect = React.lazy(\n () => import('@/components/organisms/ai/AISelect'),\n);\nconst LazyAICodeBlock = React.lazy(() =>\n import('@/components/organisms/ai/AICodeBlock').then((module) => ({\n default: module.AICodeBlock,\n })),\n);\n\n// =============================================================================\n// Loading skeleton for lazy components\n// =============================================================================\n\nfunction LazyLoadingSkeleton() {\n return (\n <div className=\"my-4 flex items-center justify-center p-8 rounded-xl border border-border bg-muted animate-pulse\">\n <div className=\"h-4 w-32 bg-accent rounded\" />\n </div>\n );\n}\n\n// =============================================================================\n// Interactive languages (fire onInteraction events)\n// =============================================================================\n\nconst INTERACTIVE_LANGUAGES = ['chart', 'select', 'table', 'form'] as const;\ntype InteractiveLanguage = (typeof INTERACTIVE_LANGUAGES)[number];\n\nfunction isInteractiveLanguage(\n language: string,\n): language is InteractiveLanguage {\n return INTERACTIVE_LANGUAGES.includes(language as InteractiveLanguage);\n}\n\n// =============================================================================\n// Render-only languages (visual output, no interaction events)\n// =============================================================================\n\nconst RENDER_ONLY_LANGUAGES = ['mermaid', 'ascii'] as const;\ntype RenderOnlyLanguage = (typeof RENDER_ONLY_LANGUAGES)[number];\n\nfunction isRenderOnlyLanguage(\n language: string,\n): language is RenderOnlyLanguage {\n return RENDER_ONLY_LANGUAGES.includes(language as RenderOnlyLanguage);\n}\n\n// =============================================================================\n// Component lookup maps\n// =============================================================================\n\ntype InteractiveComponentProps = {\n schema: unknown;\n};\n\ntype CodeRendererEntry = {\n Component: React.LazyExoticComponent<React.ComponentType<{ code: string }>>;\n prop: 'code';\n};\n\ntype ContentRendererEntry = {\n Component: React.LazyExoticComponent<\n React.ComponentType<{ content: string }>\n >;\n prop: 'content';\n};\n\ntype RenderOnlyComponentEntry = CodeRendererEntry | ContentRendererEntry;\n\nconst INTERACTIVE_COMPONENTS: Record<\n InteractiveLanguage,\n React.LazyExoticComponent<React.ComponentType<InteractiveComponentProps>>\n> = {\n chart: LazyAIChart as React.LazyExoticComponent<\n React.ComponentType<InteractiveComponentProps>\n >,\n select: LazyAISelect as React.LazyExoticComponent<\n React.ComponentType<InteractiveComponentProps>\n >,\n table: LazyAITable as React.LazyExoticComponent<\n React.ComponentType<InteractiveComponentProps>\n >,\n form: LazyAIForm as React.LazyExoticComponent<\n React.ComponentType<InteractiveComponentProps>\n >,\n};\n\nconst RENDER_ONLY_COMPONENTS: Record<\n RenderOnlyLanguage,\n RenderOnlyComponentEntry\n> = {\n mermaid: {\n Component: LazyAIMermaidDiagram as React.LazyExoticComponent<\n React.ComponentType<{ code: string }>\n >,\n prop: 'code',\n },\n ascii: {\n Component: LazyAIAsciiDiagram as React.LazyExoticComponent<\n React.ComponentType<{ content: string }>\n >,\n prop: 'content',\n },\n};\n\nconst LOADING_FALLBACK = <LazyLoadingSkeleton />;\n\n// =============================================================================\n// Render helpers\n// =============================================================================\n\nfunction renderInteractiveComponent(\n language: InteractiveLanguage,\n schema: unknown,\n): React.ReactElement {\n const Component = INTERACTIVE_COMPONENTS[language];\n return (\n <React.Suspense fallback={LOADING_FALLBACK}>\n <Component schema={schema} />\n </React.Suspense>\n );\n}\n\nfunction renderRenderOnlyComponent(\n language: RenderOnlyLanguage,\n content: string,\n): React.ReactElement {\n const { Component, prop } = RENDER_ONLY_COMPONENTS[language];\n if (prop === 'code') {\n return (\n <React.Suspense fallback={LOADING_FALLBACK}>\n <Component code={content} />\n </React.Suspense>\n );\n }\n\n return (\n <React.Suspense fallback={LOADING_FALLBACK}>\n <Component content={content} />\n </React.Suspense>\n );\n}\n\nfunction renderInteractiveError({\n language,\n inverted,\n message,\n}: {\n language: InteractiveLanguage;\n inverted: boolean;\n message: string;\n}): React.ReactElement {\n return (\n <div\n className={cn(\n 'my-4 p-4 rounded-lg',\n inverted\n ? 'border border-primary-foreground/30 bg-background/10 text-primary-foreground text-sm'\n : 'border border-destructive bg-destructive/20 text-destructive text-sm',\n )}\n role=\"alert\"\n data-slot=\"ai-interactive-error\"\n >\n <span className=\"font-semibold\">Invalid {language} schema:</span>{' '}\n {message}\n </div>\n );\n}\n\nfunction renderCodeBlock({\n code,\n language,\n inverted,\n}: {\n code: string;\n language: string;\n inverted: boolean;\n}): React.ReactElement {\n const block = (\n <React.Suspense fallback={LOADING_FALLBACK}>\n <LazyAICodeBlock\n code={code}\n language={language}\n showHeader={true}\n showCopyButton={true}\n className={inverted ? undefined : 'my-4'}\n />\n </React.Suspense>\n );\n\n if (!inverted) {\n return block;\n }\n\n return (\n <div\n className=\"my-4 [&_[data-slot=ai-code-block]]:bg-background/10 [&_[data-slot=ai-code-block]]:border-primary-foreground/20 [&_[data-slot=ai-code-block-header]]:bg-background/5 [&_[data-slot=ai-code-block-header]]:border-primary-foreground/20 [&_[data-slot=ai-code-block-header]_span]:!text-primary-foreground/60 [&_[data-slot=ai-code-block-header]_button]:!text-primary-foreground/60\"\n style={INVERTED_SUGAR_HIGH_STYLE}\n >\n {block}\n </div>\n );\n}\n\n// =============================================================================\n// Unified code component for react-markdown\n// =============================================================================\n\nfunction createCodeComponent(variant: MarkdownVariant = 'default'): React.FC<{\n className?: string;\n children?: React.ReactNode;\n}> {\n const inv = variant === 'inverted';\n\n return function UnifiedCodeBlock({ className, children }) {\n const isInline = !className?.includes('language-');\n\n if (isInline) {\n return (\n <code\n className={cn(\n 'px-1.5 py-0.5 rounded text-sm font-mono transition-colors',\n 'break-words [overflow-wrap:anywhere]',\n inv\n ? 'bg-background/15 text-primary-foreground'\n : 'bg-accent text-foreground',\n className,\n )}\n >\n {children}\n </code>\n );\n }\n\n const match = /language-(\\w+)/.exec(className || '');\n const language = match ? match[1] : 'plaintext';\n const content = String(children).replace(/\\n$/, '');\n\n if (isRenderOnlyLanguage(language)) {\n return renderRenderOnlyComponent(language, content);\n }\n\n if (isInteractiveLanguage(language)) {\n try {\n const schema = JSON.parse(content);\n const validation = validateInteractiveSchema(language, schema);\n\n if (!validation.valid) {\n return renderInteractiveError({\n language,\n inverted: inv,\n message:\n 'The configuration does not match the expected schema shape.',\n });\n }\n\n return renderInteractiveComponent(language, validation.schema);\n } catch {\n return renderInteractiveError({\n language,\n inverted: inv,\n message:\n 'Unable to parse the configuration. Please check the JSON syntax.',\n });\n }\n }\n\n return renderCodeBlock({ code: content, language, inverted: inv });\n };\n}\n\nexport { createCodeComponent, LazyLoadingSkeleton };\n"],"mappings":"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"}
package/dist/index152.js CHANGED
@@ -38,7 +38,7 @@ var variantColors = {
38
38
  },
39
39
  bgMuted: {
40
40
  default: "bg-muted",
41
- inverted: "bg-primary-foreground/20"
41
+ inverted: "bg-background/20"
42
42
  }
43
43
  };
44
44
  function vc(variant, token) {
@@ -1 +1 @@
1
- {"version":3,"file":"index152.js","names":[],"sources":["../src/components/organisms/ai/_shared/markdown-renderer.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport ReactMarkdown, { type Components } from 'react-markdown';\nimport rehypeKatex from 'rehype-katex';\nimport remarkGfm from 'remark-gfm';\nimport remarkMath from 'remark-math';\nimport type { PluggableList } from 'unified';\nimport { cn } from '@/lib/utils';\nimport { createCodeComponent } from './code-handler';\n\nconst remarkPlugins: PluggableList = [remarkGfm, remarkMath];\nconst rehypePlugins: PluggableList = [[rehypeKatex, { output: 'mathml' }]];\nconst markdownOverflowWrapClasses =\n 'min-w-0 max-w-full break-words [overflow-wrap:anywhere]';\n\n// =============================================================================\n// Variant-aware color mapping\n// =============================================================================\n\nimport type { MarkdownVariant } from './types';\n\nexport type { MarkdownVariant } from './types';\n\nconst variantColors = {\n heading: { default: 'text-foreground', inverted: 'text-primary-foreground' },\n body: {\n default: 'text-secondary-foreground',\n inverted: 'text-primary-foreground/90',\n },\n link: { default: 'text-primary', inverted: 'text-primary-foreground' },\n muted: {\n default: 'text-muted-foreground',\n inverted: 'text-primary-foreground/70',\n },\n faint: {\n default: 'text-text-quaternary',\n inverted: 'text-primary-foreground/50',\n },\n border: {\n default: 'border-border',\n inverted: 'border-primary-foreground/25',\n },\n bgMuted: { default: 'bg-muted', inverted: 'bg-primary-foreground/20' },\n} as const;\n\ntype ColorToken = keyof typeof variantColors;\n\nfunction vc(variant: MarkdownVariant, token: ColorToken): string {\n return variantColors[token][variant];\n}\n\n// =============================================================================\n// Create variant-aware component overrides for react-markdown\n// =============================================================================\n\nfunction createMarkdownComponents(\n variant: MarkdownVariant,\n): Partial<Components> {\n return {\n h1: ({ className, children, ...props }) => (\n <h1\n className={cn(\n 'text-display-xs font-bold mt-6 mb-4',\n markdownOverflowWrapClasses,\n vc(variant, 'heading'),\n className,\n )}\n {...props}\n >\n {children}\n </h1>\n ),\n h2: ({ className, children, ...props }) => (\n <h2\n className={cn(\n 'text-xl font-semibold mt-5 mb-3',\n markdownOverflowWrapClasses,\n vc(variant, 'heading'),\n className,\n )}\n {...props}\n >\n {children}\n </h2>\n ),\n h3: ({ className, children, ...props }) => (\n <h3\n className={cn(\n 'text-lg font-semibold mt-4 mb-2',\n markdownOverflowWrapClasses,\n vc(variant, 'heading'),\n className,\n )}\n {...props}\n >\n {children}\n </h3>\n ),\n h4: ({ className, children, ...props }) => (\n <h4\n className={cn(\n 'text-base font-semibold mt-3 mb-2',\n markdownOverflowWrapClasses,\n vc(variant, 'heading'),\n className,\n )}\n {...props}\n >\n {children}\n </h4>\n ),\n p: ({ className, children, ...props }) => (\n <p\n className={cn(\n 'text-base leading-relaxed mb-4',\n markdownOverflowWrapClasses,\n vc(variant, 'body'),\n className,\n )}\n {...props}\n >\n {children}\n </p>\n ),\n ul: ({ className, children, ...props }) => (\n <ul\n className={cn(\n 'list-disc list-inside mb-4 space-y-1',\n markdownOverflowWrapClasses,\n vc(variant, 'body'),\n className,\n )}\n {...props}\n >\n {children}\n </ul>\n ),\n ol: ({ className, children, ...props }) => (\n <ol\n className={cn(\n 'list-decimal list-inside mb-4 space-y-1',\n markdownOverflowWrapClasses,\n vc(variant, 'body'),\n className,\n )}\n {...props}\n >\n {children}\n </ol>\n ),\n li: ({ className, children, ...props }) => (\n <li\n className={cn(\n 'leading-relaxed',\n markdownOverflowWrapClasses,\n className,\n )}\n {...props}\n >\n {children}\n </li>\n ),\n a: ({ className, children, href, ...props }) => (\n <a\n href={href}\n className={cn(\n 'underline underline-offset-2 transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring rounded-sm',\n markdownOverflowWrapClasses,\n vc(variant, 'link'),\n variant === 'default' && 'hover:text-primary',\n variant === 'inverted' && 'hover:text-primary-foreground',\n className,\n )}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n {...props}\n >\n {children}\n </a>\n ),\n blockquote: ({ className, children, ...props }) => (\n <blockquote\n className={cn(\n 'border-s-4 ps-4 py-2 my-4 italic',\n markdownOverflowWrapClasses,\n vc(variant, 'muted'),\n vc(variant, 'border'),\n className,\n )}\n {...props}\n >\n {children}\n </blockquote>\n ),\n code: createCodeComponent(variant),\n pre: ({ children }) => <>{children}</>,\n hr: ({ className, ...props }) => (\n <hr className={cn('my-6', vc(variant, 'border'), className)} {...props} />\n ),\n table: ({ className, children, ...props }) => (\n <section\n className=\"not-prose overflow-x-auto my-4 [overflow-wrap:normal] [&_a]:break-normal [&_a]:[overflow-wrap:normal] [&_code]:break-normal [&_code]:[overflow-wrap:normal] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring\"\n aria-label=\"Data table\"\n // biome-ignore lint/a11y/noNoninteractiveTabindex: Focusable scroll region satisfies axe scrollable-region-focusable.\n tabIndex={0}\n >\n <table\n className={cn(\n 'min-w-full border-collapse border [overflow-wrap:normal]',\n vc(variant, 'border'),\n variant === 'inverted' && '!bg-transparent',\n className,\n )}\n {...props}\n >\n {children}\n </table>\n </section>\n ),\n thead: ({ className, children, ...props }) => (\n <thead\n className={cn(\n variant === 'default' ? vc(variant, 'bgMuted') : '!bg-transparent',\n className,\n )}\n {...props}\n >\n {children}\n </thead>\n ),\n tbody: ({ className, children, ...props }) => (\n <tbody\n className={cn(\n variant === 'default'\n ? 'divide-y divide-border'\n : 'divide-y divide-primary-foreground/20',\n className,\n )}\n {...props}\n >\n {children}\n </tbody>\n ),\n tr: ({ children, ...props }) => <tr {...props}>{children}</tr>,\n th: ({ className, children, ...props }) => (\n <th\n className={cn(\n 'px-4 py-2 text-start text-sm font-semibold border',\n '[overflow-wrap:normal]',\n vc(variant, 'body'),\n vc(variant, 'border'),\n variant === 'inverted' && '!bg-transparent',\n className,\n )}\n {...props}\n >\n {children}\n </th>\n ),\n td: ({ className, children, ...props }) => (\n <td\n className={cn(\n 'px-4 py-2 text-sm border',\n '[overflow-wrap:normal]',\n vc(variant, 'body'),\n vc(variant, 'border'),\n variant === 'inverted' && '!bg-transparent',\n className,\n )}\n {...props}\n >\n {children}\n </td>\n ),\n strong: ({ className, children, ...props }) => (\n <strong\n className={cn(\n 'font-semibold',\n markdownOverflowWrapClasses,\n vc(variant, 'heading'),\n className,\n )}\n {...props}\n >\n {children}\n </strong>\n ),\n em: ({ className, children, ...props }) => (\n <em className={cn(markdownOverflowWrapClasses, className)} {...props}>\n {children}\n </em>\n ),\n del: ({ className, children, ...props }) => (\n <del\n className={cn(\n 'line-through',\n markdownOverflowWrapClasses,\n vc(variant, 'faint'),\n className,\n )}\n {...props}\n >\n {children}\n </del>\n ),\n img: ({ className, alt, src, ...props }) => (\n <img\n src={src}\n alt={alt}\n className={cn('max-w-full h-auto rounded-lg my-4', className)}\n loading=\"lazy\"\n {...props}\n />\n ),\n };\n}\n\n// =============================================================================\n// Component cache (at most 2 entries: 'default' and 'inverted')\n// =============================================================================\n\nconst componentCache = new Map<MarkdownVariant, Partial<Components>>();\n\nfunction getComponents(variant: MarkdownVariant): Partial<Components> {\n let cached = componentCache.get(variant);\n if (!cached) {\n cached = createMarkdownComponents(variant);\n componentCache.set(variant, cached);\n }\n return cached;\n}\n\n// =============================================================================\n// MarkdownRenderer\n// =============================================================================\n\nexport interface MarkdownRendererProps {\n /** Markdown content to render */\n children: string;\n /** Additional class name */\n className?: string;\n /** Color variant — 'inverted' for white text on colored backgrounds */\n variant?: MarkdownVariant;\n}\n\nconst MarkdownRenderer = React.memo(function MarkdownRenderer({\n children,\n className,\n variant = 'default',\n}: MarkdownRendererProps) {\n const components = getComponents(variant);\n\n return (\n <div\n data-slot=\"ai-markdown\"\n className={cn(\n 'prose prose-gray max-w-none',\n markdownOverflowWrapClasses,\n className,\n )}\n >\n <ReactMarkdown\n remarkPlugins={remarkPlugins}\n rehypePlugins={rehypePlugins}\n components={components}\n >\n {children}\n </ReactMarkdown>\n </div>\n );\n});\n\nMarkdownRenderer.displayName = 'MarkdownRenderer';\n\nexport { MarkdownRenderer };\n"],"mappings":"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"}
1
+ {"version":3,"file":"index152.js","names":[],"sources":["../src/components/organisms/ai/_shared/markdown-renderer.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport ReactMarkdown, { type Components } from 'react-markdown';\nimport rehypeKatex from 'rehype-katex';\nimport remarkGfm from 'remark-gfm';\nimport remarkMath from 'remark-math';\nimport type { PluggableList } from 'unified';\nimport { cn } from '@/lib/utils';\nimport { createCodeComponent } from './code-handler';\n\nconst remarkPlugins: PluggableList = [remarkGfm, remarkMath];\nconst rehypePlugins: PluggableList = [[rehypeKatex, { output: 'mathml' }]];\nconst markdownOverflowWrapClasses =\n 'min-w-0 max-w-full break-words [overflow-wrap:anywhere]';\n\n// =============================================================================\n// Variant-aware color mapping\n// =============================================================================\n\nimport type { MarkdownVariant } from './types';\n\nexport type { MarkdownVariant } from './types';\n\nconst variantColors = {\n heading: { default: 'text-foreground', inverted: 'text-primary-foreground' },\n body: {\n default: 'text-secondary-foreground',\n inverted: 'text-primary-foreground/90',\n },\n link: { default: 'text-primary', inverted: 'text-primary-foreground' },\n muted: {\n default: 'text-muted-foreground',\n inverted: 'text-primary-foreground/70',\n },\n faint: {\n default: 'text-text-quaternary',\n inverted: 'text-primary-foreground/50',\n },\n border: {\n default: 'border-border',\n inverted: 'border-primary-foreground/25',\n },\n bgMuted: { default: 'bg-muted', inverted: 'bg-background/20' },\n} as const;\n\ntype ColorToken = keyof typeof variantColors;\n\nfunction vc(variant: MarkdownVariant, token: ColorToken): string {\n return variantColors[token][variant];\n}\n\n// =============================================================================\n// Create variant-aware component overrides for react-markdown\n// =============================================================================\n\nfunction createMarkdownComponents(\n variant: MarkdownVariant,\n): Partial<Components> {\n return {\n h1: ({ className, children, ...props }) => (\n <h1\n className={cn(\n 'text-display-xs font-bold mt-6 mb-4',\n markdownOverflowWrapClasses,\n vc(variant, 'heading'),\n className,\n )}\n {...props}\n >\n {children}\n </h1>\n ),\n h2: ({ className, children, ...props }) => (\n <h2\n className={cn(\n 'text-xl font-semibold mt-5 mb-3',\n markdownOverflowWrapClasses,\n vc(variant, 'heading'),\n className,\n )}\n {...props}\n >\n {children}\n </h2>\n ),\n h3: ({ className, children, ...props }) => (\n <h3\n className={cn(\n 'text-lg font-semibold mt-4 mb-2',\n markdownOverflowWrapClasses,\n vc(variant, 'heading'),\n className,\n )}\n {...props}\n >\n {children}\n </h3>\n ),\n h4: ({ className, children, ...props }) => (\n <h4\n className={cn(\n 'text-base font-semibold mt-3 mb-2',\n markdownOverflowWrapClasses,\n vc(variant, 'heading'),\n className,\n )}\n {...props}\n >\n {children}\n </h4>\n ),\n p: ({ className, children, ...props }) => (\n <p\n className={cn(\n 'text-base leading-relaxed mb-4',\n markdownOverflowWrapClasses,\n vc(variant, 'body'),\n className,\n )}\n {...props}\n >\n {children}\n </p>\n ),\n ul: ({ className, children, ...props }) => (\n <ul\n className={cn(\n 'list-disc list-inside mb-4 space-y-1',\n markdownOverflowWrapClasses,\n vc(variant, 'body'),\n className,\n )}\n {...props}\n >\n {children}\n </ul>\n ),\n ol: ({ className, children, ...props }) => (\n <ol\n className={cn(\n 'list-decimal list-inside mb-4 space-y-1',\n markdownOverflowWrapClasses,\n vc(variant, 'body'),\n className,\n )}\n {...props}\n >\n {children}\n </ol>\n ),\n li: ({ className, children, ...props }) => (\n <li\n className={cn(\n 'leading-relaxed',\n markdownOverflowWrapClasses,\n className,\n )}\n {...props}\n >\n {children}\n </li>\n ),\n a: ({ className, children, href, ...props }) => (\n <a\n href={href}\n className={cn(\n 'underline underline-offset-2 transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring rounded-sm',\n markdownOverflowWrapClasses,\n vc(variant, 'link'),\n variant === 'default' && 'hover:text-primary',\n variant === 'inverted' && 'hover:text-primary-foreground',\n className,\n )}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n {...props}\n >\n {children}\n </a>\n ),\n blockquote: ({ className, children, ...props }) => (\n <blockquote\n className={cn(\n 'border-s-4 ps-4 py-2 my-4 italic',\n markdownOverflowWrapClasses,\n vc(variant, 'muted'),\n vc(variant, 'border'),\n className,\n )}\n {...props}\n >\n {children}\n </blockquote>\n ),\n code: createCodeComponent(variant),\n pre: ({ children }) => <>{children}</>,\n hr: ({ className, ...props }) => (\n <hr className={cn('my-6', vc(variant, 'border'), className)} {...props} />\n ),\n table: ({ className, children, ...props }) => (\n <section\n className=\"not-prose overflow-x-auto my-4 [overflow-wrap:normal] [&_a]:break-normal [&_a]:[overflow-wrap:normal] [&_code]:break-normal [&_code]:[overflow-wrap:normal] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring\"\n aria-label=\"Data table\"\n // biome-ignore lint/a11y/noNoninteractiveTabindex: Focusable scroll region satisfies axe scrollable-region-focusable.\n tabIndex={0}\n >\n <table\n className={cn(\n 'min-w-full border-collapse border [overflow-wrap:normal]',\n vc(variant, 'border'),\n variant === 'inverted' && '!bg-transparent',\n className,\n )}\n {...props}\n >\n {children}\n </table>\n </section>\n ),\n thead: ({ className, children, ...props }) => (\n <thead\n className={cn(\n variant === 'default' ? vc(variant, 'bgMuted') : '!bg-transparent',\n className,\n )}\n {...props}\n >\n {children}\n </thead>\n ),\n tbody: ({ className, children, ...props }) => (\n <tbody\n className={cn(\n variant === 'default'\n ? 'divide-y divide-border'\n : 'divide-y divide-primary-foreground/20',\n className,\n )}\n {...props}\n >\n {children}\n </tbody>\n ),\n tr: ({ children, ...props }) => <tr {...props}>{children}</tr>,\n th: ({ className, children, ...props }) => (\n <th\n className={cn(\n 'px-4 py-2 text-start text-sm font-semibold border',\n '[overflow-wrap:normal]',\n vc(variant, 'body'),\n vc(variant, 'border'),\n variant === 'inverted' && '!bg-transparent',\n className,\n )}\n {...props}\n >\n {children}\n </th>\n ),\n td: ({ className, children, ...props }) => (\n <td\n className={cn(\n 'px-4 py-2 text-sm border',\n '[overflow-wrap:normal]',\n vc(variant, 'body'),\n vc(variant, 'border'),\n variant === 'inverted' && '!bg-transparent',\n className,\n )}\n {...props}\n >\n {children}\n </td>\n ),\n strong: ({ className, children, ...props }) => (\n <strong\n className={cn(\n 'font-semibold',\n markdownOverflowWrapClasses,\n vc(variant, 'heading'),\n className,\n )}\n {...props}\n >\n {children}\n </strong>\n ),\n em: ({ className, children, ...props }) => (\n <em className={cn(markdownOverflowWrapClasses, className)} {...props}>\n {children}\n </em>\n ),\n del: ({ className, children, ...props }) => (\n <del\n className={cn(\n 'line-through',\n markdownOverflowWrapClasses,\n vc(variant, 'faint'),\n className,\n )}\n {...props}\n >\n {children}\n </del>\n ),\n img: ({ className, alt, src, ...props }) => (\n <img\n src={src}\n alt={alt}\n className={cn('max-w-full h-auto rounded-lg my-4', className)}\n loading=\"lazy\"\n {...props}\n />\n ),\n };\n}\n\n// =============================================================================\n// Component cache (at most 2 entries: 'default' and 'inverted')\n// =============================================================================\n\nconst componentCache = new Map<MarkdownVariant, Partial<Components>>();\n\nfunction getComponents(variant: MarkdownVariant): Partial<Components> {\n let cached = componentCache.get(variant);\n if (!cached) {\n cached = createMarkdownComponents(variant);\n componentCache.set(variant, cached);\n }\n return cached;\n}\n\n// =============================================================================\n// MarkdownRenderer\n// =============================================================================\n\nexport interface MarkdownRendererProps {\n /** Markdown content to render */\n children: string;\n /** Additional class name */\n className?: string;\n /** Color variant — 'inverted' for white text on colored backgrounds */\n variant?: MarkdownVariant;\n}\n\nconst MarkdownRenderer = React.memo(function MarkdownRenderer({\n children,\n className,\n variant = 'default',\n}: MarkdownRendererProps) {\n const components = getComponents(variant);\n\n return (\n <div\n data-slot=\"ai-markdown\"\n className={cn(\n 'prose prose-gray max-w-none',\n markdownOverflowWrapClasses,\n className,\n )}\n >\n <ReactMarkdown\n remarkPlugins={remarkPlugins}\n rehypePlugins={rehypePlugins}\n components={components}\n >\n {children}\n </ReactMarkdown>\n </div>\n );\n});\n\nMarkdownRenderer.displayName = 'MarkdownRenderer';\n\nexport { MarkdownRenderer };\n"],"mappings":"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"}
package/dist/index155.js CHANGED
@@ -170,7 +170,7 @@ function AIScrollButton({ scrollRef, containerRef, threshold = 50, onClick, visi
170
170
  stiffness: 500,
171
171
  damping: 30
172
172
  },
173
- className: "absolute -top-1 -end-1 flex items-center justify-center min-w-[18px] h-[18px] px-1 rounded-full bg-destructive text-primary-foreground text-xs font-medium motion-reduce:transition-none",
173
+ className: "absolute -top-1 -end-1 flex items-center justify-center min-w-[18px] h-[18px] px-1 rounded-full bg-destructive text-destructive-foreground text-xs font-medium motion-reduce:transition-none",
174
174
  "aria-label": `${unreadCount > 99 ? "99+" : unreadCount} new messages`,
175
175
  children: unreadCount > 99 ? "99+" : unreadCount
176
176
  })]
@@ -1 +1 @@
1
- {"version":3,"file":"index155.js","names":[],"sources":["../src/components/organisms/ai/AIScrollButton/AIScrollButton.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\nimport { ArrowDown } from 'lucide-react';\nimport { AnimatePresence, motion } from 'motion/react';\nimport * as React from 'react';\nimport { Button } from '@/components/atoms/buttons/Button';\nimport { cn } from '@/lib/utils';\n\n// =============================================================================\n// Variants\n// =============================================================================\n\nconst scrollButtonVariants = cva(\n 'fixed flex items-center justify-center shadow-lg transition-all',\n {\n variants: {\n variant: {\n default: 'bg-background hover:bg-muted border border-border',\n primary: 'bg-primary/10 hover:bg-primary/90 text-primary-foreground',\n ghost:\n 'bg-card/80 hover:bg-background supports-backdrop-filter:backdrop-blur-sm border border-border',\n },\n size: {\n sm: 'size-8 rounded-full',\n md: 'size-10 rounded-full',\n lg: 'size-12 rounded-xl',\n },\n position: {\n 'bottom-center':\n 'bottom-4 start-1/2 -translate-x-1/2 rtl:translate-x-1/2',\n 'bottom-right': 'bottom-4 end-4',\n 'bottom-left': 'bottom-4 start-4',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'md',\n position: 'bottom-center',\n },\n },\n);\n\n// =============================================================================\n// useScrollToBottom Hook\n// =============================================================================\n\nexport interface UseScrollToBottomOptions {\n /** Threshold in pixels from bottom to consider \"at bottom\" */\n threshold?: number;\n /** Scroll behavior */\n behavior?: ScrollBehavior;\n /** Enable auto-scroll mode: tracks whether auto-scroll should fire on content changes */\n autoScroll?: boolean;\n}\n\nexport interface UseScrollToBottomReturn {\n /** Whether the user is at the bottom of the container */\n isAtBottom: boolean;\n /** Scroll to bottom function */\n scrollToBottom: (behavior?: ScrollBehavior) => void;\n /** Ref to attach to the scrollable container */\n containerRef: React.RefObject<HTMLDivElement | null>;\n /** Ref to attach to the scroll anchor element */\n anchorRef: React.RefObject<HTMLDivElement | null>;\n /** Whether auto-scroll should fire (only meaningful when autoScroll option is true) */\n shouldAutoScroll: boolean;\n /** Call when user scrolls manually to disable auto-scroll (re-enables when user scrolls back to bottom) */\n handleUserScroll: () => void;\n /** Trigger an auto-scroll if shouldAutoScroll is true (uses requestAnimationFrame) */\n triggerAutoScroll: () => void;\n}\n\nexport function useScrollToBottom({\n threshold = 50,\n behavior = 'smooth',\n autoScroll: autoScrollEnabled = false,\n}: UseScrollToBottomOptions = {}): UseScrollToBottomReturn {\n const containerRef = React.useRef<HTMLDivElement>(null);\n const anchorRef = React.useRef<HTMLDivElement>(null);\n const [isAtBottom, setIsAtBottom] = React.useState(true);\n const [shouldAutoScroll, setShouldAutoScroll] = React.useState(true);\n\n const scrollToBottom = React.useCallback(\n (overrideBehavior?: ScrollBehavior) => {\n const scrollBehavior = overrideBehavior ?? behavior;\n if (anchorRef.current) {\n anchorRef.current.scrollIntoView({ behavior: scrollBehavior });\n } else if (containerRef.current) {\n containerRef.current.scrollTop = containerRef.current.scrollHeight;\n }\n },\n [behavior],\n );\n\n const checkIsAtBottom = React.useCallback(() => {\n const container = containerRef.current;\n if (!container) return true;\n const { scrollTop, scrollHeight, clientHeight } = container;\n const distanceFromBottom = scrollHeight - scrollTop - clientHeight;\n return distanceFromBottom <= threshold;\n }, [threshold]);\n\n React.useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const handleScroll = () => {\n const atBottom = checkIsAtBottom();\n setIsAtBottom((prev) => (prev === atBottom ? prev : atBottom));\n if (autoScrollEnabled && atBottom) {\n setShouldAutoScroll((prev) => prev || true);\n }\n };\n\n handleScroll();\n\n container.addEventListener('scroll', handleScroll, { passive: true });\n return () => container.removeEventListener('scroll', handleScroll);\n }, [checkIsAtBottom, autoScrollEnabled]);\n\n React.useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n const OwnerResizeObserver =\n container.ownerDocument.defaultView?.ResizeObserver;\n if (!OwnerResizeObserver) return;\n\n const resizeObserver = new OwnerResizeObserver(() => {\n const atBottom = checkIsAtBottom();\n setIsAtBottom((prev) => (prev === atBottom ? prev : atBottom));\n });\n\n resizeObserver.observe(container);\n return () => resizeObserver.disconnect();\n }, [checkIsAtBottom]);\n\n const handleUserScroll = React.useCallback(() => {\n if (!checkIsAtBottom()) {\n setShouldAutoScroll(false);\n }\n }, [checkIsAtBottom]);\n\n const triggerAutoScroll = React.useCallback(() => {\n if (autoScrollEnabled && shouldAutoScroll) {\n const ownerWindow =\n anchorRef.current?.ownerDocument.defaultView ??\n containerRef.current?.ownerDocument.defaultView;\n ownerWindow?.requestAnimationFrame(() => {\n scrollToBottom('smooth');\n });\n }\n }, [autoScrollEnabled, shouldAutoScroll, scrollToBottom]);\n\n return {\n isAtBottom,\n scrollToBottom,\n containerRef,\n anchorRef,\n shouldAutoScroll,\n handleUserScroll,\n triggerAutoScroll,\n };\n}\n\n// =============================================================================\n// Main AIScrollButton Component\n// =============================================================================\n\nexport interface AIScrollButtonProps\n extends VariantProps<typeof scrollButtonVariants> {\n /** Target scroll element ref */\n scrollRef?: React.RefObject<HTMLElement | null>;\n /** Scrollable container ref */\n containerRef?: React.RefObject<HTMLElement | null>;\n /** Threshold in pixels from bottom to show button */\n threshold?: number;\n /** Click handler (defaults to scrolling to bottom) */\n onClick?: () => void;\n /** Whether to show the button (controlled) */\n visible?: boolean;\n /** Label for accessibility */\n label?: string;\n /** Show unread count badge */\n unreadCount?: number;\n /** Additional class name */\n className?: string;\n}\n\nfunction getIconSize(size: AIScrollButtonProps['size']): string {\n switch (size) {\n case 'sm':\n return 'size-4';\n case 'lg':\n return 'size-6';\n default:\n return 'size-5';\n }\n}\n\nfunction AIScrollButton({\n scrollRef,\n containerRef,\n threshold = 50,\n onClick,\n visible: controlledVisible,\n variant,\n size,\n position,\n label = 'Scroll to bottom',\n unreadCount,\n className,\n}: AIScrollButtonProps) {\n const [internalVisible, setInternalVisible] = React.useState(false);\n\n // Track scroll position if containerRef is provided and no controlled visibility\n React.useEffect(() => {\n if (controlledVisible !== undefined) return;\n\n const container = containerRef?.current;\n if (!container) return;\n\n const handleScroll = () => {\n const { scrollTop, scrollHeight, clientHeight } = container;\n const distanceFromBottom = scrollHeight - scrollTop - clientHeight;\n setInternalVisible(distanceFromBottom > threshold);\n };\n\n handleScroll();\n container.addEventListener('scroll', handleScroll, { passive: true });\n return () => container.removeEventListener('scroll', handleScroll);\n }, [containerRef, threshold, controlledVisible]);\n\n const isVisible = controlledVisible ?? internalVisible;\n\n const handleClick = () => {\n if (onClick) {\n onClick();\n } else if (scrollRef?.current) {\n scrollRef.current.scrollIntoView({ behavior: 'smooth' });\n } else if (containerRef?.current) {\n containerRef.current.scrollTop = containerRef.current.scrollHeight;\n }\n };\n\n const iconSize = getIconSize(size);\n\n return (\n <AnimatePresence>\n {isVisible && (\n <motion.div\n data-slot=\"ai-scroll-button\"\n initial={{ opacity: 0, y: 20, scale: 0.9 }}\n animate={{ opacity: 1, y: 0, scale: 1 }}\n exit={{ opacity: 0, y: 20, scale: 0.9 }}\n transition={{ duration: 0.2, ease: [0.4, 0, 0.2, 1] }}\n className={cn(\n scrollButtonVariants({ variant, size, position }),\n 'motion-reduce:transition-none',\n className,\n )}\n >\n <Button\n appearance=\"ghost\"\n variant=\"secondary\"\n size=\"icon\"\n onClick={handleClick}\n className=\"size-full rounded-full\"\n aria-label={label}\n >\n <ArrowDown\n className={cn(\n iconSize,\n variant === 'primary'\n ? 'text-primary-foreground'\n : 'text-muted-foreground',\n )}\n />\n </Button>\n\n {/* Unread count badge */}\n {unreadCount !== undefined && unreadCount > 0 && (\n <motion.div\n initial={{ scale: 0 }}\n animate={{ scale: 1 }}\n transition={{ type: 'spring', stiffness: 500, damping: 30 }}\n className=\"absolute -top-1 -end-1 flex items-center justify-center min-w-[18px] h-[18px] px-1 rounded-full bg-destructive text-primary-foreground text-xs font-medium motion-reduce:transition-none\"\n aria-label={`${unreadCount > 99 ? '99+' : unreadCount} new messages`}\n >\n {unreadCount > 99 ? '99+' : unreadCount}\n </motion.div>\n )}\n </motion.div>\n )}\n </AnimatePresence>\n );\n}\n\nAIScrollButton.displayName = 'AIScrollButton';\n\n// =============================================================================\n// Scroll Anchor Component\n// =============================================================================\n\nexport interface AIScrollAnchorProps {\n /** Ref to expose for scrolling */\n ref?: React.Ref<HTMLDivElement>;\n /** Additional class name */\n className?: string;\n}\n\nconst AIScrollAnchor = React.forwardRef<HTMLDivElement, AIScrollAnchorProps>(\n ({ className }, ref) => {\n return (\n <div ref={ref} className={cn('h-px w-full', className)} aria-hidden />\n );\n },\n);\n\nAIScrollAnchor.displayName = 'AIScrollAnchor';\n\nexport { AIScrollAnchor, AIScrollButton, scrollButtonVariants };\n"],"mappings":"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"}
1
+ {"version":3,"file":"index155.js","names":[],"sources":["../src/components/organisms/ai/AIScrollButton/AIScrollButton.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\nimport { ArrowDown } from 'lucide-react';\nimport { AnimatePresence, motion } from 'motion/react';\nimport * as React from 'react';\nimport { Button } from '@/components/atoms/buttons/Button';\nimport { cn } from '@/lib/utils';\n\n// =============================================================================\n// Variants\n// =============================================================================\n\nconst scrollButtonVariants = cva(\n 'fixed flex items-center justify-center shadow-lg transition-all',\n {\n variants: {\n variant: {\n default: 'bg-background hover:bg-muted border border-border',\n primary: 'bg-primary/10 hover:bg-primary/90 text-primary-foreground',\n ghost:\n 'bg-card/80 hover:bg-background supports-backdrop-filter:backdrop-blur-sm border border-border',\n },\n size: {\n sm: 'size-8 rounded-full',\n md: 'size-10 rounded-full',\n lg: 'size-12 rounded-xl',\n },\n position: {\n 'bottom-center':\n 'bottom-4 start-1/2 -translate-x-1/2 rtl:translate-x-1/2',\n 'bottom-right': 'bottom-4 end-4',\n 'bottom-left': 'bottom-4 start-4',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'md',\n position: 'bottom-center',\n },\n },\n);\n\n// =============================================================================\n// useScrollToBottom Hook\n// =============================================================================\n\nexport interface UseScrollToBottomOptions {\n /** Threshold in pixels from bottom to consider \"at bottom\" */\n threshold?: number;\n /** Scroll behavior */\n behavior?: ScrollBehavior;\n /** Enable auto-scroll mode: tracks whether auto-scroll should fire on content changes */\n autoScroll?: boolean;\n}\n\nexport interface UseScrollToBottomReturn {\n /** Whether the user is at the bottom of the container */\n isAtBottom: boolean;\n /** Scroll to bottom function */\n scrollToBottom: (behavior?: ScrollBehavior) => void;\n /** Ref to attach to the scrollable container */\n containerRef: React.RefObject<HTMLDivElement | null>;\n /** Ref to attach to the scroll anchor element */\n anchorRef: React.RefObject<HTMLDivElement | null>;\n /** Whether auto-scroll should fire (only meaningful when autoScroll option is true) */\n shouldAutoScroll: boolean;\n /** Call when user scrolls manually to disable auto-scroll (re-enables when user scrolls back to bottom) */\n handleUserScroll: () => void;\n /** Trigger an auto-scroll if shouldAutoScroll is true (uses requestAnimationFrame) */\n triggerAutoScroll: () => void;\n}\n\nexport function useScrollToBottom({\n threshold = 50,\n behavior = 'smooth',\n autoScroll: autoScrollEnabled = false,\n}: UseScrollToBottomOptions = {}): UseScrollToBottomReturn {\n const containerRef = React.useRef<HTMLDivElement>(null);\n const anchorRef = React.useRef<HTMLDivElement>(null);\n const [isAtBottom, setIsAtBottom] = React.useState(true);\n const [shouldAutoScroll, setShouldAutoScroll] = React.useState(true);\n\n const scrollToBottom = React.useCallback(\n (overrideBehavior?: ScrollBehavior) => {\n const scrollBehavior = overrideBehavior ?? behavior;\n if (anchorRef.current) {\n anchorRef.current.scrollIntoView({ behavior: scrollBehavior });\n } else if (containerRef.current) {\n containerRef.current.scrollTop = containerRef.current.scrollHeight;\n }\n },\n [behavior],\n );\n\n const checkIsAtBottom = React.useCallback(() => {\n const container = containerRef.current;\n if (!container) return true;\n const { scrollTop, scrollHeight, clientHeight } = container;\n const distanceFromBottom = scrollHeight - scrollTop - clientHeight;\n return distanceFromBottom <= threshold;\n }, [threshold]);\n\n React.useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const handleScroll = () => {\n const atBottom = checkIsAtBottom();\n setIsAtBottom((prev) => (prev === atBottom ? prev : atBottom));\n if (autoScrollEnabled && atBottom) {\n setShouldAutoScroll((prev) => prev || true);\n }\n };\n\n handleScroll();\n\n container.addEventListener('scroll', handleScroll, { passive: true });\n return () => container.removeEventListener('scroll', handleScroll);\n }, [checkIsAtBottom, autoScrollEnabled]);\n\n React.useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n const OwnerResizeObserver =\n container.ownerDocument.defaultView?.ResizeObserver;\n if (!OwnerResizeObserver) return;\n\n const resizeObserver = new OwnerResizeObserver(() => {\n const atBottom = checkIsAtBottom();\n setIsAtBottom((prev) => (prev === atBottom ? prev : atBottom));\n });\n\n resizeObserver.observe(container);\n return () => resizeObserver.disconnect();\n }, [checkIsAtBottom]);\n\n const handleUserScroll = React.useCallback(() => {\n if (!checkIsAtBottom()) {\n setShouldAutoScroll(false);\n }\n }, [checkIsAtBottom]);\n\n const triggerAutoScroll = React.useCallback(() => {\n if (autoScrollEnabled && shouldAutoScroll) {\n const ownerWindow =\n anchorRef.current?.ownerDocument.defaultView ??\n containerRef.current?.ownerDocument.defaultView;\n ownerWindow?.requestAnimationFrame(() => {\n scrollToBottom('smooth');\n });\n }\n }, [autoScrollEnabled, shouldAutoScroll, scrollToBottom]);\n\n return {\n isAtBottom,\n scrollToBottom,\n containerRef,\n anchorRef,\n shouldAutoScroll,\n handleUserScroll,\n triggerAutoScroll,\n };\n}\n\n// =============================================================================\n// Main AIScrollButton Component\n// =============================================================================\n\nexport interface AIScrollButtonProps\n extends VariantProps<typeof scrollButtonVariants> {\n /** Target scroll element ref */\n scrollRef?: React.RefObject<HTMLElement | null>;\n /** Scrollable container ref */\n containerRef?: React.RefObject<HTMLElement | null>;\n /** Threshold in pixels from bottom to show button */\n threshold?: number;\n /** Click handler (defaults to scrolling to bottom) */\n onClick?: () => void;\n /** Whether to show the button (controlled) */\n visible?: boolean;\n /** Label for accessibility */\n label?: string;\n /** Show unread count badge */\n unreadCount?: number;\n /** Additional class name */\n className?: string;\n}\n\nfunction getIconSize(size: AIScrollButtonProps['size']): string {\n switch (size) {\n case 'sm':\n return 'size-4';\n case 'lg':\n return 'size-6';\n default:\n return 'size-5';\n }\n}\n\nfunction AIScrollButton({\n scrollRef,\n containerRef,\n threshold = 50,\n onClick,\n visible: controlledVisible,\n variant,\n size,\n position,\n label = 'Scroll to bottom',\n unreadCount,\n className,\n}: AIScrollButtonProps) {\n const [internalVisible, setInternalVisible] = React.useState(false);\n\n // Track scroll position if containerRef is provided and no controlled visibility\n React.useEffect(() => {\n if (controlledVisible !== undefined) return;\n\n const container = containerRef?.current;\n if (!container) return;\n\n const handleScroll = () => {\n const { scrollTop, scrollHeight, clientHeight } = container;\n const distanceFromBottom = scrollHeight - scrollTop - clientHeight;\n setInternalVisible(distanceFromBottom > threshold);\n };\n\n handleScroll();\n container.addEventListener('scroll', handleScroll, { passive: true });\n return () => container.removeEventListener('scroll', handleScroll);\n }, [containerRef, threshold, controlledVisible]);\n\n const isVisible = controlledVisible ?? internalVisible;\n\n const handleClick = () => {\n if (onClick) {\n onClick();\n } else if (scrollRef?.current) {\n scrollRef.current.scrollIntoView({ behavior: 'smooth' });\n } else if (containerRef?.current) {\n containerRef.current.scrollTop = containerRef.current.scrollHeight;\n }\n };\n\n const iconSize = getIconSize(size);\n\n return (\n <AnimatePresence>\n {isVisible && (\n <motion.div\n data-slot=\"ai-scroll-button\"\n initial={{ opacity: 0, y: 20, scale: 0.9 }}\n animate={{ opacity: 1, y: 0, scale: 1 }}\n exit={{ opacity: 0, y: 20, scale: 0.9 }}\n transition={{ duration: 0.2, ease: [0.4, 0, 0.2, 1] }}\n className={cn(\n scrollButtonVariants({ variant, size, position }),\n 'motion-reduce:transition-none',\n className,\n )}\n >\n <Button\n appearance=\"ghost\"\n variant=\"secondary\"\n size=\"icon\"\n onClick={handleClick}\n className=\"size-full rounded-full\"\n aria-label={label}\n >\n <ArrowDown\n className={cn(\n iconSize,\n variant === 'primary'\n ? 'text-primary-foreground'\n : 'text-muted-foreground',\n )}\n />\n </Button>\n\n {/* Unread count badge */}\n {unreadCount !== undefined && unreadCount > 0 && (\n <motion.div\n initial={{ scale: 0 }}\n animate={{ scale: 1 }}\n transition={{ type: 'spring', stiffness: 500, damping: 30 }}\n className=\"absolute -top-1 -end-1 flex items-center justify-center min-w-[18px] h-[18px] px-1 rounded-full bg-destructive text-destructive-foreground text-xs font-medium motion-reduce:transition-none\"\n aria-label={`${unreadCount > 99 ? '99+' : unreadCount} new messages`}\n >\n {unreadCount > 99 ? '99+' : unreadCount}\n </motion.div>\n )}\n </motion.div>\n )}\n </AnimatePresence>\n );\n}\n\nAIScrollButton.displayName = 'AIScrollButton';\n\n// =============================================================================\n// Scroll Anchor Component\n// =============================================================================\n\nexport interface AIScrollAnchorProps {\n /** Ref to expose for scrolling */\n ref?: React.Ref<HTMLDivElement>;\n /** Additional class name */\n className?: string;\n}\n\nconst AIScrollAnchor = React.forwardRef<HTMLDivElement, AIScrollAnchorProps>(\n ({ className }, ref) => {\n return (\n <div ref={ref} className={cn('h-px w-full', className)} aria-hidden />\n );\n },\n);\n\nAIScrollAnchor.displayName = 'AIScrollAnchor';\n\nexport { AIScrollAnchor, AIScrollButton, scrollButtonVariants };\n"],"mappings":"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"}
package/dist/index188.js CHANGED
@@ -10,10 +10,10 @@ var tooltipVariants = cva("data-open:animate-in data-open:fade-in-0 data-open:zo
10
10
  variant: {
11
11
  primary: "bg-foreground text-background",
12
12
  secondary: "bg-secondary text-secondary-foreground border border-border shadow-sm",
13
- info: "bg-info text-primary-foreground",
14
- success: "bg-success text-primary-foreground",
15
- warning: "bg-warning text-primary-foreground",
16
- destructive: "bg-destructive text-primary-foreground"
13
+ info: "bg-info text-info-foreground",
14
+ success: "bg-success text-success-foreground",
15
+ warning: "bg-warning text-warning-foreground",
16
+ destructive: "bg-destructive text-destructive-foreground"
17
17
  },
18
18
  shape: {
19
19
  default: "rounded-md",
@@ -1 +1 @@
1
- {"version":3,"file":"index188.js","names":[],"sources":["../src/components/organisms/overlays/Tooltip/Tooltip.tsx"],"sourcesContent":["'use client';\n\nimport { Tooltip as TooltipPrimitive } from '@base-ui/react/tooltip';\nimport { cva } from 'class-variance-authority';\nimport * as React from 'react';\nimport { cn, extractText } from '@/lib/utils';\n\nconst tooltipVariants = cva(\n 'data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 motion-reduce:animate-none z-50 w-fit max-w-xs origin-(--transform-origin) px-3 py-1.5 text-xs shadow-[var(--shadow-tooltip)]',\n {\n variants: {\n variant: {\n primary: 'bg-foreground text-background',\n secondary:\n 'bg-secondary text-secondary-foreground border border-border shadow-sm',\n info: 'bg-info text-primary-foreground',\n success: 'bg-success text-primary-foreground',\n warning: 'bg-warning text-primary-foreground',\n destructive: 'bg-destructive text-primary-foreground',\n },\n shape: {\n default: 'rounded-md',\n rounded: 'rounded-full',\n },\n },\n defaultVariants: {\n variant: 'primary',\n shape: 'default',\n },\n },\n);\n\nconst arrowVariants = cva(\n 'size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] z-50 data-[side=bottom]:top-1 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5',\n {\n variants: {\n variant: {\n primary: 'bg-foreground fill-foreground',\n secondary: 'bg-secondary fill-secondary',\n info: 'bg-info fill-info',\n success: 'bg-success fill-success',\n warning: 'bg-warning fill-warning',\n destructive: 'bg-destructive fill-destructive',\n },\n },\n defaultVariants: {\n variant: 'primary',\n },\n },\n);\n\ntype TooltipVariant =\n | 'primary'\n | 'secondary'\n | 'info'\n | 'success'\n | 'warning'\n | 'destructive';\ntype TooltipShape = 'default' | 'rounded';\ntype TooltipPosition = 'top' | 'bottom' | 'left' | 'right' | 'none';\n\n// =============================================================================\n// Base Tooltip Sub-components\n// =============================================================================\n\nfunction TooltipProvider({\n delay = 0,\n ...props\n}: TooltipPrimitive.Provider.Props) {\n return (\n <TooltipPrimitive.Provider\n data-slot=\"tooltip-provider\"\n delay={delay}\n {...props}\n />\n );\n}\n\nfunction TooltipRoot(props: TooltipPrimitive.Root.Props) {\n return <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />;\n}\n\nconst TooltipTrigger = React.forwardRef<\n HTMLButtonElement,\n TooltipPrimitive.Trigger.Props\n>(function TooltipTrigger(props, ref) {\n return (\n <TooltipPrimitive.Trigger\n ref={ref}\n data-slot=\"tooltip-trigger\"\n {...props}\n />\n );\n});\n\ninterface TooltipPopupProps\n extends TooltipPrimitive.Popup.Props,\n Pick<\n TooltipPrimitive.Positioner.Props,\n 'align' | 'alignOffset' | 'side' | 'sideOffset'\n > {\n variant?: TooltipVariant;\n shape?: TooltipShape;\n /** Optional Base UI portal container for the tooltip popup. */\n container?: TooltipPrimitive.Portal.Props['container'];\n /** When true or position is 'none', hides the arrow */\n hideArrow?: boolean;\n}\n\nfunction TooltipPopup({\n className,\n side = 'top',\n sideOffset = 4,\n align = 'center',\n alignOffset = 0,\n variant = 'primary',\n shape = 'default',\n hideArrow = false,\n container,\n children,\n ...props\n}: TooltipPopupProps) {\n return (\n <TooltipPrimitive.Portal container={container}>\n <TooltipPrimitive.Positioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n className=\"isolate z-50\"\n >\n <TooltipPrimitive.Popup\n data-slot=\"tooltip-popup\"\n className={cn(tooltipVariants({ variant, shape }), className)}\n {...props}\n >\n {children}\n {!hideArrow && (\n <TooltipPrimitive.Arrow className={arrowVariants({ variant })} />\n )}\n </TooltipPrimitive.Popup>\n </TooltipPrimitive.Positioner>\n </TooltipPrimitive.Portal>\n );\n}\n\n// =============================================================================\n// Rich Content Sub-components\n// =============================================================================\n\nfunction TooltipIcon({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <span\n data-slot=\"tooltip-icon\"\n className={cn('shrink-0 [&>svg]:size-4', className)}\n >\n {children}\n </span>\n );\n}\nTooltipIcon.displayName = 'Tooltip.Icon';\n\nfunction TooltipAvatar({\n src,\n alt,\n children,\n className,\n}: {\n src?: string;\n alt: string;\n children?: React.ReactNode;\n className?: string;\n}) {\n if (children) {\n return (\n <span data-slot=\"tooltip-avatar\" className={cn('shrink-0', className)}>\n {children}\n </span>\n );\n }\n return (\n <img\n data-slot=\"tooltip-avatar\"\n src={src}\n alt={alt}\n className={cn('size-4 shrink-0 rounded-full object-cover', className)}\n />\n );\n}\nTooltipAvatar.displayName = 'Tooltip.Avatar';\n\nfunction TooltipContent({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <div\n data-slot=\"tooltip-content\"\n className={cn('flex flex-col gap-0.5', className)}\n >\n {children}\n </div>\n );\n}\nTooltipContent.displayName = 'Tooltip.Content';\n\nfunction TooltipTitle({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <span\n data-slot=\"tooltip-title\"\n className={cn('text-xs font-semibold leading-4', className)}\n >\n {children}\n </span>\n );\n}\nTooltipTitle.displayName = 'Tooltip.Title';\n\ninterface TooltipSubtitleProps {\n children: React.ReactNode;\n className?: string;\n /** Variant affects subtitle opacity */\n variant?: TooltipVariant;\n}\n\nfunction TooltipSubtitle({\n children,\n className,\n variant = 'primary',\n}: TooltipSubtitleProps) {\n const subtitleClass =\n variant === 'secondary'\n ? 'text-muted-foreground'\n : 'text-inherit opacity-70';\n\n return (\n <span\n data-slot=\"tooltip-subtitle\"\n className={cn('text-xs font-medium leading-4', subtitleClass, className)}\n >\n {children}\n </span>\n );\n}\nTooltipSubtitle.displayName = 'Tooltip.Subtitle';\n\nfunction TooltipBadge({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <span data-slot=\"tooltip-badge\" className={cn('shrink-0', className)}>\n {children}\n </span>\n );\n}\nTooltipBadge.displayName = 'Tooltip.Badge';\n\ninterface TooltipImageProps {\n src: string;\n alt: string;\n layout?: 'vertical' | 'horizontal';\n className?: string;\n}\n\nfunction TooltipImage({\n src,\n alt,\n layout = 'vertical',\n className,\n}: TooltipImageProps) {\n return (\n <img\n data-slot=\"tooltip-image\"\n src={src}\n alt={alt}\n className={cn(\n 'rounded-md object-cover',\n layout === 'vertical' ? 'w-full h-20' : 'w-20 h-14 shrink-0',\n className,\n )}\n />\n );\n}\nTooltipImage.displayName = 'Tooltip.Image';\n\n// =============================================================================\n// High-level Tooltip Wrapper Component\n// =============================================================================\n\ninterface TooltipProps {\n /** The element that triggers the tooltip (required) */\n trigger: React.ReactElement;\n /** The main tooltip text */\n content: React.ReactNode;\n /** Style variant */\n variant?: TooltipVariant;\n /** Shape variant */\n shape?: TooltipShape;\n /** Arrow position - 'none' hides the arrow */\n position?: TooltipPosition;\n /** Alignment of tooltip relative to trigger */\n align?: 'start' | 'center' | 'end';\n /** Delay in ms before showing tooltip */\n delayDuration?: number;\n /** Distance from trigger */\n sideOffset?: number;\n /** Optional icon before content */\n icon?: React.ReactNode;\n /** Optional avatar - string for src or ReactNode for custom */\n avatar?: string | React.ReactNode;\n /** Optional supporting text */\n subtitle?: React.ReactNode;\n /** Optional badge element */\n badge?: React.ReactNode;\n /** Optional image */\n image?: string;\n /** Image layout - auto-detected or override */\n imageLayout?: 'vertical' | 'horizontal';\n /** Optional Base UI portal container. Takes precedence over the trigger owner document. */\n container?: TooltipPrimitive.Portal.Props['container'];\n /** Override content with custom children */\n children?: React.ReactNode;\n}\n\ninterface TooltipRenderedContentProps {\n children?: React.ReactNode;\n content: React.ReactNode;\n variant: TooltipVariant;\n icon?: React.ReactNode;\n avatar?: string | React.ReactNode;\n subtitle?: React.ReactNode;\n badge?: React.ReactNode;\n image?: string;\n imageLayout: 'vertical' | 'horizontal';\n hasRichContent: React.ReactNode;\n contentAlt: string;\n}\n\nfunction TooltipRenderedContent({\n children,\n content,\n variant,\n icon,\n avatar,\n subtitle,\n badge,\n image,\n imageLayout,\n hasRichContent,\n contentAlt,\n}: TooltipRenderedContentProps) {\n if (children) return children;\n\n const subtitleElement = subtitle && (\n <TooltipSubtitle variant={variant}>{subtitle}</TooltipSubtitle>\n );\n\n if (image) {\n return (\n <div\n className={cn(\n 'flex gap-1.5 delight-tooltip-stagger',\n imageLayout === 'vertical' ? 'flex-col' : 'flex-row items-center',\n )}\n >\n <TooltipImage\n src={image}\n alt={contentAlt}\n layout={imageLayout}\n className=\"delight-tooltip-image\"\n />\n <TooltipContent>\n <TooltipTitle>{content}</TooltipTitle>\n {subtitleElement}\n </TooltipContent>\n </div>\n );\n }\n\n if (!hasRichContent) return content;\n\n return (\n <div className=\"flex items-center gap-1.5 delight-tooltip-stagger\">\n {avatar &&\n (typeof avatar === 'string' ? (\n <TooltipAvatar src={avatar} alt={contentAlt} />\n ) : (\n <TooltipAvatar alt={contentAlt}>{avatar}</TooltipAvatar>\n ))}\n {icon && <TooltipIcon>{icon}</TooltipIcon>}\n <TooltipContent>\n <TooltipTitle>{content}</TooltipTitle>\n {subtitleElement}\n </TooltipContent>\n {badge && <TooltipBadge>{badge}</TooltipBadge>}\n </div>\n );\n}\n\nconst Tooltip = ({\n trigger,\n content,\n variant = 'primary',\n shape = 'default',\n position = 'top',\n align = 'center',\n delayDuration,\n sideOffset = 6,\n icon,\n avatar,\n subtitle,\n badge,\n image,\n imageLayout,\n container,\n children,\n}: TooltipProps) => {\n const [triggerElement, setTriggerElement] =\n React.useState<HTMLElement | null>(null);\n const [triggerPortalContainer, setTriggerPortalContainer] =\n React.useState<HTMLElement | null>(null);\n const setTriggerRef = React.useCallback((element: HTMLElement | null) => {\n setTriggerElement((currentElement) =>\n currentElement === element ? currentElement : element,\n );\n }, []);\n\n React.useEffect(() => {\n const nextContainer = triggerElement?.ownerDocument.body ?? null;\n setTriggerPortalContainer((currentContainer) =>\n currentContainer === nextContainer ? currentContainer : nextContainer,\n );\n }, [triggerElement]);\n\n // Determine if we have rich content\n const hasRichContent = icon || avatar || subtitle || badge || image;\n\n const resolvedImageLayout = imageLayout ?? 'vertical';\n const contentAlt = extractText(content);\n const portalContainer =\n container === undefined ? triggerPortalContainer : container;\n\n return (\n <TooltipProvider delay={delayDuration}>\n <TooltipRoot>\n <TooltipTrigger ref={setTriggerRef} render={trigger} />\n <TooltipPopup\n container={portalContainer}\n side={position === 'none' ? 'top' : position}\n align={align}\n sideOffset={sideOffset}\n variant={variant}\n shape={shape}\n hideArrow={position === 'none'}\n className={cn(hasRichContent && 'p-2')}\n >\n <TooltipRenderedContent\n content={content}\n variant={variant}\n icon={icon}\n avatar={avatar}\n subtitle={subtitle}\n badge={badge}\n image={image}\n imageLayout={resolvedImageLayout}\n hasRichContent={hasRichContent}\n contentAlt={contentAlt}\n >\n {children}\n </TooltipRenderedContent>\n </TooltipPopup>\n </TooltipRoot>\n </TooltipProvider>\n );\n};\n\nTooltip.displayName = 'Tooltip';\nTooltipProvider.displayName = 'Tooltip.Provider';\nTooltipRoot.displayName = 'Tooltip.Root';\nTooltipTrigger.displayName = 'Tooltip.Trigger';\nTooltipPopup.displayName = 'Tooltip.Popup';\n\n/**\n * Tooltip component with dot notation for compound parts.\n *\n * @example\n * ```tsx\n * // Simple usage (recommended for most cases)\n * <Tooltip trigger={<Button>Hover me</Button>} content=\"Tooltip text\" />\n *\n * // With variants\n * <Tooltip trigger={<Button>Save</Button>} content=\"Saved!\" variant=\"success\" shape=\"rounded\" />\n *\n * // With rich content\n * <Tooltip trigger={<Button>Info</Button>} content=\"Title\" icon={<InfoIcon />} subtitle=\"Description\" />\n *\n * // Advanced usage with dot notation\n * <Tooltip.Root>\n * <Tooltip.Trigger render={<Button>Hover me</Button>} />\n * <Tooltip.Popup variant=\"info\">\n * <Tooltip.Icon><InfoIcon /></Tooltip.Icon>\n * <Tooltip.Content>\n * <Tooltip.Title>Title</Tooltip.Title>\n * <Tooltip.Subtitle>Description</Tooltip.Subtitle>\n * </Tooltip.Content>\n * </Tooltip.Popup>\n * </Tooltip.Root>\n * ```\n */\nconst TooltipCompound = Object.assign(Tooltip, {\n Root: TooltipRoot,\n Provider: TooltipProvider,\n Trigger: TooltipTrigger,\n Popup: TooltipPopup,\n Icon: TooltipIcon,\n Avatar: TooltipAvatar,\n Content: TooltipContent,\n Title: TooltipTitle,\n Subtitle: TooltipSubtitle,\n Badge: TooltipBadge,\n Image: TooltipImage,\n});\n\nexport type { TooltipPosition, TooltipProps, TooltipShape, TooltipVariant };\nexport {\n arrowVariants,\n TooltipAvatar,\n TooltipBadge,\n TooltipCompound as Tooltip,\n TooltipContent,\n TooltipIcon,\n TooltipImage,\n TooltipPopup,\n TooltipProvider,\n TooltipRoot,\n TooltipSubtitle,\n TooltipTitle,\n TooltipTrigger,\n tooltipVariants,\n};\n"],"mappings":";;;;;;;AAOA,IAAM,kBAAkB,IACtB,kaACA;CACE,UAAU;EACR,SAAS;GACP,SAAS;GACT,WACE;GACF,MAAM;GACN,SAAS;GACT,SAAS;GACT,aAAa;EACf;EACA,OAAO;GACL,SAAS;GACT,SAAS;EACX;CACF;CACA,iBAAiB;EACf,SAAS;EACT,OAAO;CACT;AACF,CACF;AAEA,IAAM,gBAAgB,IACpB,2SACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,WAAW;EACX,MAAM;EACN,SAAS;EACT,SAAS;EACT,aAAa;CACf,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CACF;AAgBA,SAAS,gBAAgB,EACvB,QAAQ,GACR,GAAG,SAC+B;CAClC,OACE,oBAAC,QAAiB,UAAlB;EACE,aAAU;EACH;EACP,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,YAAY,OAAoC;CACvD,OAAO,oBAAC,QAAiB,MAAlB;EAAuB,aAAU;EAAU,GAAI;CAAQ,CAAA;AAChE;AAEA,IAAM,iBAAiB,QAAM,WAG3B,SAAS,eAAe,OAAO,KAAK;CACpC,OACE,oBAAC,QAAiB,SAAlB;EACO;EACL,aAAU;EACV,GAAI;CACL,CAAA;AAEL,CAAC;AAgBD,SAAS,aAAa,EACpB,WACA,OAAO,OACP,aAAa,GACb,QAAQ,UACR,cAAc,GACd,UAAU,WACV,QAAQ,WACR,YAAY,OACZ,WACA,UACA,GAAG,SACiB;CACpB,OACE,oBAAC,QAAiB,QAAlB;EAAoC;YAClC,oBAAC,QAAiB,YAAlB;GACS;GACM;GACP;GACM;GACZ,WAAU;aAEV,qBAAC,QAAiB,OAAlB;IACE,aAAU;IACV,WAAW,GAAG,gBAAgB;KAAE;KAAS;IAAM,CAAC,GAAG,SAAS;IAC5D,GAAI;cAHN,CAKG,UACA,CAAC,aACA,oBAAC,QAAiB,OAAlB,EAAwB,WAAW,cAAc,EAAE,QAAQ,CAAC,EAAI,CAAA,CAE5C;;EACG,CAAA;CACN,CAAA;AAE7B;AAMA,SAAS,YAAY,EACnB,UACA,aAIC;CACD,OACE,oBAAC,QAAD;EACE,aAAU;EACV,WAAW,GAAG,2BAA2B,SAAS;EAEjD;CACG,CAAA;AAEV;AACA,YAAY,cAAc;AAE1B,SAAS,cAAc,EACrB,KACA,KACA,UACA,aAMC;CACD,IAAI,UACF,OACE,oBAAC,QAAD;EAAM,aAAU;EAAiB,WAAW,GAAG,YAAY,SAAS;EACjE;CACG,CAAA;CAGV,OACE,oBAAC,OAAD;EACE,aAAU;EACL;EACA;EACL,WAAW,GAAG,6CAA6C,SAAS;CACrE,CAAA;AAEL;AACA,cAAc,cAAc;AAE5B,SAAS,eAAe,EACtB,UACA,aAIC;CACD,OACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,yBAAyB,SAAS;EAE/C;CACE,CAAA;AAET;AACA,eAAe,cAAc;AAE7B,SAAS,aAAa,EACpB,UACA,aAIC;CACD,OACE,oBAAC,QAAD;EACE,aAAU;EACV,WAAW,GAAG,mCAAmC,SAAS;EAEzD;CACG,CAAA;AAEV;AACA,aAAa,cAAc;AAS3B,SAAS,gBAAgB,EACvB,UACA,WACA,UAAU,aACa;CAMvB,OACE,oBAAC,QAAD;EACE,aAAU;EACV,WAAW,GAAG,iCAPhB,YAAY,cACR,0BACA,2BAK4D,SAAS;EAEtE;CACG,CAAA;AAEV;AACA,gBAAgB,cAAc;AAE9B,SAAS,aAAa,EACpB,UACA,aAIC;CACD,OACE,oBAAC,QAAD;EAAM,aAAU;EAAgB,WAAW,GAAG,YAAY,SAAS;EAChE;CACG,CAAA;AAEV;AACA,aAAa,cAAc;AAS3B,SAAS,aAAa,EACpB,KACA,KACA,SAAS,YACT,aACoB;CACpB,OACE,oBAAC,OAAD;EACE,aAAU;EACL;EACA;EACL,WAAW,GACT,2BACA,WAAW,aAAa,gBAAgB,sBACxC,SACF;CACD,CAAA;AAEL;AACA,aAAa,cAAc;AAuD3B,SAAS,uBAAuB,EAC9B,UACA,SACA,SACA,MACA,QACA,UACA,OACA,OACA,aACA,gBACA,cAC8B;CAC9B,IAAI,UAAU,OAAO;CAErB,MAAM,kBAAkB,YACtB,oBAAC,iBAAD;EAA0B;YAAU;CAA0B,CAAA;CAGhE,IAAI,OACF,OACE,qBAAC,OAAD;EACE,WAAW,GACT,wCACA,gBAAgB,aAAa,aAAa,uBAC5C;YAJF,CAME,oBAAC,cAAD;GACE,KAAK;GACL,KAAK;GACL,QAAQ;GACR,WAAU;EACX,CAAA,GACD,qBAAC,gBAAD,EAAA,UAAA,CACE,oBAAC,cAAD,EAAA,UAAe,QAAsB,CAAA,GACpC,eACa,EAAA,CAAA,CACb;;CAIT,IAAI,CAAC,gBAAgB,OAAO;CAE5B,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf;GACG,WACE,OAAO,WAAW,WACjB,oBAAC,eAAD;IAAe,KAAK;IAAQ,KAAK;GAAa,CAAA,IAE9C,oBAAC,eAAD;IAAe,KAAK;cAAa;GAAsB,CAAA;GAE1D,QAAQ,oBAAC,aAAD,EAAA,UAAc,KAAkB,CAAA;GACzC,qBAAC,gBAAD,EAAA,UAAA,CACE,oBAAC,cAAD,EAAA,UAAe,QAAsB,CAAA,GACpC,eACa,EAAA,CAAA;GACf,SAAS,oBAAC,cAAD,EAAA,UAAe,MAAoB,CAAA;EAC1C;;AAET;AAEA,IAAM,aAAW,EACf,SACA,SACA,UAAU,WACV,QAAQ,WACR,WAAW,OACX,QAAQ,UACR,eACA,aAAa,GACb,MACA,QACA,UACA,OACA,OACA,aACA,WACA,eACkB;CAClB,MAAM,CAAC,gBAAgB,qBACrB,QAAM,SAA6B,IAAI;CACzC,MAAM,CAAC,wBAAwB,6BAC7B,QAAM,SAA6B,IAAI;CACzC,MAAM,gBAAgB,QAAM,aAAa,YAAgC;EACvE,mBAAmB,mBACjB,mBAAmB,UAAU,iBAAiB,OAChD;CACF,GAAG,CAAC,CAAC;CAEL,QAAM,gBAAgB;EACpB,MAAM,gBAAgB,gBAAgB,cAAc,QAAQ;EAC5D,2BAA2B,qBACzB,qBAAqB,gBAAgB,mBAAmB,aAC1D;CACF,GAAG,CAAC,cAAc,CAAC;CAGnB,MAAM,iBAAiB,QAAQ,UAAU,YAAY,SAAS;CAE9D,MAAM,sBAAsB,eAAe;CAC3C,MAAM,aAAa,YAAY,OAAO;CAItC,OACE,oBAAC,iBAAD;EAAiB,OAAO;YACtB,qBAAC,aAAD,EAAA,UAAA,CACE,oBAAC,gBAAD;GAAgB,KAAK;GAAe,QAAQ;EAAU,CAAA,GACtD,oBAAC,cAAD;GACE,WAPN,cAAc,KAAA,IAAY,yBAAyB;GAQ7C,MAAM,aAAa,SAAS,QAAQ;GAC7B;GACK;GACH;GACF;GACP,WAAW,aAAa;GACxB,WAAW,GAAG,kBAAkB,KAAK;aAErC,oBAAC,wBAAD;IACW;IACA;IACH;IACE;IACE;IACH;IACA;IACP,aAAa;IACG;IACJ;IAEX;GACqB,CAAA;EACZ,CAAA,CACH,EAAA,CAAA;CACE,CAAA;AAErB;AAEA,UAAQ,cAAc;AACtB,gBAAgB,cAAc;AAC9B,YAAY,cAAc;AAC1B,eAAe,cAAc;AAC7B,aAAa,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6B3B,IAAM,kBAAkB,OAAO,OAAO,WAAS;CAC7C,MAAM;CACN,UAAU;CACV,SAAS;CACT,OAAO;CACP,MAAM;CACN,QAAQ;CACR,SAAS;CACT,OAAO;CACP,UAAU;CACV,OAAO;CACP,OAAO;AACT,CAAC"}
1
+ {"version":3,"file":"index188.js","names":[],"sources":["../src/components/organisms/overlays/Tooltip/Tooltip.tsx"],"sourcesContent":["'use client';\n\nimport { Tooltip as TooltipPrimitive } from '@base-ui/react/tooltip';\nimport { cva } from 'class-variance-authority';\nimport * as React from 'react';\nimport { cn, extractText } from '@/lib/utils';\n\nconst tooltipVariants = cva(\n 'data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 motion-reduce:animate-none z-50 w-fit max-w-xs origin-(--transform-origin) px-3 py-1.5 text-xs shadow-[var(--shadow-tooltip)]',\n {\n variants: {\n variant: {\n primary: 'bg-foreground text-background',\n secondary:\n 'bg-secondary text-secondary-foreground border border-border shadow-sm',\n info: 'bg-info text-info-foreground',\n success: 'bg-success text-success-foreground',\n warning: 'bg-warning text-warning-foreground',\n destructive: 'bg-destructive text-destructive-foreground',\n },\n shape: {\n default: 'rounded-md',\n rounded: 'rounded-full',\n },\n },\n defaultVariants: {\n variant: 'primary',\n shape: 'default',\n },\n },\n);\n\nconst arrowVariants = cva(\n 'size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] z-50 data-[side=bottom]:top-1 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5',\n {\n variants: {\n variant: {\n primary: 'bg-foreground fill-foreground',\n secondary: 'bg-secondary fill-secondary',\n info: 'bg-info fill-info',\n success: 'bg-success fill-success',\n warning: 'bg-warning fill-warning',\n destructive: 'bg-destructive fill-destructive',\n },\n },\n defaultVariants: {\n variant: 'primary',\n },\n },\n);\n\ntype TooltipVariant =\n | 'primary'\n | 'secondary'\n | 'info'\n | 'success'\n | 'warning'\n | 'destructive';\ntype TooltipShape = 'default' | 'rounded';\ntype TooltipPosition = 'top' | 'bottom' | 'left' | 'right' | 'none';\n\n// =============================================================================\n// Base Tooltip Sub-components\n// =============================================================================\n\nfunction TooltipProvider({\n delay = 0,\n ...props\n}: TooltipPrimitive.Provider.Props) {\n return (\n <TooltipPrimitive.Provider\n data-slot=\"tooltip-provider\"\n delay={delay}\n {...props}\n />\n );\n}\n\nfunction TooltipRoot(props: TooltipPrimitive.Root.Props) {\n return <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />;\n}\n\nconst TooltipTrigger = React.forwardRef<\n HTMLButtonElement,\n TooltipPrimitive.Trigger.Props\n>(function TooltipTrigger(props, ref) {\n return (\n <TooltipPrimitive.Trigger\n ref={ref}\n data-slot=\"tooltip-trigger\"\n {...props}\n />\n );\n});\n\ninterface TooltipPopupProps\n extends TooltipPrimitive.Popup.Props,\n Pick<\n TooltipPrimitive.Positioner.Props,\n 'align' | 'alignOffset' | 'side' | 'sideOffset'\n > {\n variant?: TooltipVariant;\n shape?: TooltipShape;\n /** Optional Base UI portal container for the tooltip popup. */\n container?: TooltipPrimitive.Portal.Props['container'];\n /** When true or position is 'none', hides the arrow */\n hideArrow?: boolean;\n}\n\nfunction TooltipPopup({\n className,\n side = 'top',\n sideOffset = 4,\n align = 'center',\n alignOffset = 0,\n variant = 'primary',\n shape = 'default',\n hideArrow = false,\n container,\n children,\n ...props\n}: TooltipPopupProps) {\n return (\n <TooltipPrimitive.Portal container={container}>\n <TooltipPrimitive.Positioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n className=\"isolate z-50\"\n >\n <TooltipPrimitive.Popup\n data-slot=\"tooltip-popup\"\n className={cn(tooltipVariants({ variant, shape }), className)}\n {...props}\n >\n {children}\n {!hideArrow && (\n <TooltipPrimitive.Arrow className={arrowVariants({ variant })} />\n )}\n </TooltipPrimitive.Popup>\n </TooltipPrimitive.Positioner>\n </TooltipPrimitive.Portal>\n );\n}\n\n// =============================================================================\n// Rich Content Sub-components\n// =============================================================================\n\nfunction TooltipIcon({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <span\n data-slot=\"tooltip-icon\"\n className={cn('shrink-0 [&>svg]:size-4', className)}\n >\n {children}\n </span>\n );\n}\nTooltipIcon.displayName = 'Tooltip.Icon';\n\nfunction TooltipAvatar({\n src,\n alt,\n children,\n className,\n}: {\n src?: string;\n alt: string;\n children?: React.ReactNode;\n className?: string;\n}) {\n if (children) {\n return (\n <span data-slot=\"tooltip-avatar\" className={cn('shrink-0', className)}>\n {children}\n </span>\n );\n }\n return (\n <img\n data-slot=\"tooltip-avatar\"\n src={src}\n alt={alt}\n className={cn('size-4 shrink-0 rounded-full object-cover', className)}\n />\n );\n}\nTooltipAvatar.displayName = 'Tooltip.Avatar';\n\nfunction TooltipContent({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <div\n data-slot=\"tooltip-content\"\n className={cn('flex flex-col gap-0.5', className)}\n >\n {children}\n </div>\n );\n}\nTooltipContent.displayName = 'Tooltip.Content';\n\nfunction TooltipTitle({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <span\n data-slot=\"tooltip-title\"\n className={cn('text-xs font-semibold leading-4', className)}\n >\n {children}\n </span>\n );\n}\nTooltipTitle.displayName = 'Tooltip.Title';\n\ninterface TooltipSubtitleProps {\n children: React.ReactNode;\n className?: string;\n /** Variant affects subtitle opacity */\n variant?: TooltipVariant;\n}\n\nfunction TooltipSubtitle({\n children,\n className,\n variant = 'primary',\n}: TooltipSubtitleProps) {\n const subtitleClass =\n variant === 'secondary'\n ? 'text-muted-foreground'\n : 'text-inherit opacity-70';\n\n return (\n <span\n data-slot=\"tooltip-subtitle\"\n className={cn('text-xs font-medium leading-4', subtitleClass, className)}\n >\n {children}\n </span>\n );\n}\nTooltipSubtitle.displayName = 'Tooltip.Subtitle';\n\nfunction TooltipBadge({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <span data-slot=\"tooltip-badge\" className={cn('shrink-0', className)}>\n {children}\n </span>\n );\n}\nTooltipBadge.displayName = 'Tooltip.Badge';\n\ninterface TooltipImageProps {\n src: string;\n alt: string;\n layout?: 'vertical' | 'horizontal';\n className?: string;\n}\n\nfunction TooltipImage({\n src,\n alt,\n layout = 'vertical',\n className,\n}: TooltipImageProps) {\n return (\n <img\n data-slot=\"tooltip-image\"\n src={src}\n alt={alt}\n className={cn(\n 'rounded-md object-cover',\n layout === 'vertical' ? 'w-full h-20' : 'w-20 h-14 shrink-0',\n className,\n )}\n />\n );\n}\nTooltipImage.displayName = 'Tooltip.Image';\n\n// =============================================================================\n// High-level Tooltip Wrapper Component\n// =============================================================================\n\ninterface TooltipProps {\n /** The element that triggers the tooltip (required) */\n trigger: React.ReactElement;\n /** The main tooltip text */\n content: React.ReactNode;\n /** Style variant */\n variant?: TooltipVariant;\n /** Shape variant */\n shape?: TooltipShape;\n /** Arrow position - 'none' hides the arrow */\n position?: TooltipPosition;\n /** Alignment of tooltip relative to trigger */\n align?: 'start' | 'center' | 'end';\n /** Delay in ms before showing tooltip */\n delayDuration?: number;\n /** Distance from trigger */\n sideOffset?: number;\n /** Optional icon before content */\n icon?: React.ReactNode;\n /** Optional avatar - string for src or ReactNode for custom */\n avatar?: string | React.ReactNode;\n /** Optional supporting text */\n subtitle?: React.ReactNode;\n /** Optional badge element */\n badge?: React.ReactNode;\n /** Optional image */\n image?: string;\n /** Image layout - auto-detected or override */\n imageLayout?: 'vertical' | 'horizontal';\n /** Optional Base UI portal container. Takes precedence over the trigger owner document. */\n container?: TooltipPrimitive.Portal.Props['container'];\n /** Override content with custom children */\n children?: React.ReactNode;\n}\n\ninterface TooltipRenderedContentProps {\n children?: React.ReactNode;\n content: React.ReactNode;\n variant: TooltipVariant;\n icon?: React.ReactNode;\n avatar?: string | React.ReactNode;\n subtitle?: React.ReactNode;\n badge?: React.ReactNode;\n image?: string;\n imageLayout: 'vertical' | 'horizontal';\n hasRichContent: React.ReactNode;\n contentAlt: string;\n}\n\nfunction TooltipRenderedContent({\n children,\n content,\n variant,\n icon,\n avatar,\n subtitle,\n badge,\n image,\n imageLayout,\n hasRichContent,\n contentAlt,\n}: TooltipRenderedContentProps) {\n if (children) return children;\n\n const subtitleElement = subtitle && (\n <TooltipSubtitle variant={variant}>{subtitle}</TooltipSubtitle>\n );\n\n if (image) {\n return (\n <div\n className={cn(\n 'flex gap-1.5 delight-tooltip-stagger',\n imageLayout === 'vertical' ? 'flex-col' : 'flex-row items-center',\n )}\n >\n <TooltipImage\n src={image}\n alt={contentAlt}\n layout={imageLayout}\n className=\"delight-tooltip-image\"\n />\n <TooltipContent>\n <TooltipTitle>{content}</TooltipTitle>\n {subtitleElement}\n </TooltipContent>\n </div>\n );\n }\n\n if (!hasRichContent) return content;\n\n return (\n <div className=\"flex items-center gap-1.5 delight-tooltip-stagger\">\n {avatar &&\n (typeof avatar === 'string' ? (\n <TooltipAvatar src={avatar} alt={contentAlt} />\n ) : (\n <TooltipAvatar alt={contentAlt}>{avatar}</TooltipAvatar>\n ))}\n {icon && <TooltipIcon>{icon}</TooltipIcon>}\n <TooltipContent>\n <TooltipTitle>{content}</TooltipTitle>\n {subtitleElement}\n </TooltipContent>\n {badge && <TooltipBadge>{badge}</TooltipBadge>}\n </div>\n );\n}\n\nconst Tooltip = ({\n trigger,\n content,\n variant = 'primary',\n shape = 'default',\n position = 'top',\n align = 'center',\n delayDuration,\n sideOffset = 6,\n icon,\n avatar,\n subtitle,\n badge,\n image,\n imageLayout,\n container,\n children,\n}: TooltipProps) => {\n const [triggerElement, setTriggerElement] =\n React.useState<HTMLElement | null>(null);\n const [triggerPortalContainer, setTriggerPortalContainer] =\n React.useState<HTMLElement | null>(null);\n const setTriggerRef = React.useCallback((element: HTMLElement | null) => {\n setTriggerElement((currentElement) =>\n currentElement === element ? currentElement : element,\n );\n }, []);\n\n React.useEffect(() => {\n const nextContainer = triggerElement?.ownerDocument.body ?? null;\n setTriggerPortalContainer((currentContainer) =>\n currentContainer === nextContainer ? currentContainer : nextContainer,\n );\n }, [triggerElement]);\n\n // Determine if we have rich content\n const hasRichContent = icon || avatar || subtitle || badge || image;\n\n const resolvedImageLayout = imageLayout ?? 'vertical';\n const contentAlt = extractText(content);\n const portalContainer =\n container === undefined ? triggerPortalContainer : container;\n\n return (\n <TooltipProvider delay={delayDuration}>\n <TooltipRoot>\n <TooltipTrigger ref={setTriggerRef} render={trigger} />\n <TooltipPopup\n container={portalContainer}\n side={position === 'none' ? 'top' : position}\n align={align}\n sideOffset={sideOffset}\n variant={variant}\n shape={shape}\n hideArrow={position === 'none'}\n className={cn(hasRichContent && 'p-2')}\n >\n <TooltipRenderedContent\n content={content}\n variant={variant}\n icon={icon}\n avatar={avatar}\n subtitle={subtitle}\n badge={badge}\n image={image}\n imageLayout={resolvedImageLayout}\n hasRichContent={hasRichContent}\n contentAlt={contentAlt}\n >\n {children}\n </TooltipRenderedContent>\n </TooltipPopup>\n </TooltipRoot>\n </TooltipProvider>\n );\n};\n\nTooltip.displayName = 'Tooltip';\nTooltipProvider.displayName = 'Tooltip.Provider';\nTooltipRoot.displayName = 'Tooltip.Root';\nTooltipTrigger.displayName = 'Tooltip.Trigger';\nTooltipPopup.displayName = 'Tooltip.Popup';\n\n/**\n * Tooltip component with dot notation for compound parts.\n *\n * @example\n * ```tsx\n * // Simple usage (recommended for most cases)\n * <Tooltip trigger={<Button>Hover me</Button>} content=\"Tooltip text\" />\n *\n * // With variants\n * <Tooltip trigger={<Button>Save</Button>} content=\"Saved!\" variant=\"success\" shape=\"rounded\" />\n *\n * // With rich content\n * <Tooltip trigger={<Button>Info</Button>} content=\"Title\" icon={<InfoIcon />} subtitle=\"Description\" />\n *\n * // Advanced usage with dot notation\n * <Tooltip.Root>\n * <Tooltip.Trigger render={<Button>Hover me</Button>} />\n * <Tooltip.Popup variant=\"info\">\n * <Tooltip.Icon><InfoIcon /></Tooltip.Icon>\n * <Tooltip.Content>\n * <Tooltip.Title>Title</Tooltip.Title>\n * <Tooltip.Subtitle>Description</Tooltip.Subtitle>\n * </Tooltip.Content>\n * </Tooltip.Popup>\n * </Tooltip.Root>\n * ```\n */\nconst TooltipCompound = Object.assign(Tooltip, {\n Root: TooltipRoot,\n Provider: TooltipProvider,\n Trigger: TooltipTrigger,\n Popup: TooltipPopup,\n Icon: TooltipIcon,\n Avatar: TooltipAvatar,\n Content: TooltipContent,\n Title: TooltipTitle,\n Subtitle: TooltipSubtitle,\n Badge: TooltipBadge,\n Image: TooltipImage,\n});\n\nexport type { TooltipPosition, TooltipProps, TooltipShape, TooltipVariant };\nexport {\n arrowVariants,\n TooltipAvatar,\n TooltipBadge,\n TooltipCompound as Tooltip,\n TooltipContent,\n TooltipIcon,\n TooltipImage,\n TooltipPopup,\n TooltipProvider,\n TooltipRoot,\n TooltipSubtitle,\n TooltipTitle,\n TooltipTrigger,\n tooltipVariants,\n};\n"],"mappings":"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"}
package/dist/index201.js CHANGED
@@ -13,7 +13,7 @@ var stepIndicatorVariants = cva("flex items-center justify-center shrink-0 size-
13
13
  },
14
14
  status: {
15
15
  complete: "bg-primary text-primary-foreground shadow-sm",
16
- active: "bg-primary-foreground border-2 border-primary text-primary shadow-sm",
16
+ active: "bg-background border-2 border-primary text-primary shadow-sm",
17
17
  incomplete: "bg-accent text-muted-foreground"
18
18
  }
19
19
  },
@@ -1 +1 @@
1
- {"version":3,"file":"index201.js","names":[],"sources":["../src/components/organisms/content/Steps/Steps.tsx"],"sourcesContent":["import { cva } from 'class-variance-authority';\nimport { Check } from 'lucide-react';\nimport * as React from 'react';\nimport { createSafeContext } from '@/lib/create-safe-context';\nimport { cn, extractText } from '@/lib/utils';\n\n/* -----------------------------------------------------------------------------\n * Types\n * -------------------------------------------------------------------------- */\n\nexport type StepStatus = 'complete' | 'active' | 'incomplete';\n\nexport interface StepData {\n label: string;\n subtext?: string;\n}\n\nexport interface StepsProps {\n /** Steps data for flat API */\n steps?: StepData[];\n /** Current step index (0-based) for flat API */\n currentStep?: number;\n /** Orientation of the steps */\n orientation?: 'horizontal' | 'vertical';\n /** Shape of step indicators */\n shape?: 'rounded' | 'round';\n /** Type of bullet content */\n bulletType?: 'text' | 'icon';\n /** Callback when a step is clicked */\n onStepClick?: (index: number) => void;\n /** Children for compound API */\n children?: React.ReactNode;\n /** Additional className */\n className?: string;\n}\n\nexport interface StepsItemProps {\n /** Override auto-calculated status */\n status?: StepStatus;\n /** Click handler for this step */\n onClick?: () => void;\n /** Step label content */\n children: React.ReactNode;\n /** Additional className */\n className?: string;\n}\n\nexport interface StepsSubtextProps {\n children: React.ReactNode;\n className?: string;\n}\n\n/* -----------------------------------------------------------------------------\n * Variants\n * -------------------------------------------------------------------------- */\n\nconst stepIndicatorVariants = cva(\n 'flex items-center justify-center shrink-0 size-[38px] font-medium text-lg transition-all duration-200 ease-out motion-reduce:transition-none',\n {\n variants: {\n shape: {\n rounded: 'rounded-lg',\n round: 'rounded-full',\n },\n status: {\n complete: 'bg-primary text-primary-foreground shadow-sm',\n active:\n 'bg-primary-foreground border-2 border-primary text-primary shadow-sm',\n incomplete: 'bg-accent text-muted-foreground',\n },\n },\n defaultVariants: {\n shape: 'rounded',\n status: 'incomplete',\n },\n },\n);\n\nconst stepConnectorVariants = cva(\n 'shrink-0 transition-colors duration-200 ease-out motion-reduce:transition-none',\n {\n variants: {\n orientation: {\n // Horizontal: fluid width fills available space; mt-[18px] centers 2px line with 38px indicator\n horizontal: 'h-0.5 flex-1 min-w-4 mx-2 mt-[18px]',\n // Vertical: fixed size, centered under 38px indicator\n vertical: 'w-0.5 h-[30px] my-1 ml-[18px]',\n },\n status: {\n complete: 'bg-primary',\n incomplete: 'bg-border',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n status: 'incomplete',\n },\n },\n);\n\nconst stepLabelVariants = cva('text-base leading-6', {\n variants: {\n status: {\n complete: 'text-card-foreground',\n active: 'text-card-foreground',\n incomplete: 'text-muted-foreground',\n },\n },\n defaultVariants: {\n status: 'incomplete',\n },\n});\n\nconst stepSubtextVariants = cva('text-sm leading-5 text-muted-foreground');\n\n/* -----------------------------------------------------------------------------\n * Context\n * -------------------------------------------------------------------------- */\n\ninterface StepsContextValue {\n orientation: 'horizontal' | 'vertical';\n shape: 'rounded' | 'round';\n bulletType: 'text' | 'icon';\n onStepClick?: (index: number) => void;\n getStepStatus: (index: number) => StepStatus;\n}\n\nconst [StepsContext, useStepsContext] =\n createSafeContext<StepsContextValue>('Steps');\n\n/** Per-item index context — injected by Steps parent via Children.map or flat API */\nconst StepIndexContext = React.createContext<number>(0);\n\n/* -----------------------------------------------------------------------------\n * Sub-components\n * -------------------------------------------------------------------------- */\n\ninterface StepIndicatorProps {\n index: number;\n status: StepStatus;\n shape: 'rounded' | 'round';\n bulletType: 'text' | 'icon';\n}\n\nfunction StepIndicatorContent({\n index,\n status,\n shape,\n bulletType,\n}: StepIndicatorProps) {\n if (bulletType === 'icon') {\n if (status === 'complete') {\n return <Check className=\"size-[22px] delight-check-draw\" />;\n }\n if (status === 'active') {\n return (\n <div\n className={cn(\n 'size-5 bg-primary',\n shape === 'rounded' ? 'rounded-sm' : 'rounded-full',\n )}\n />\n );\n }\n\n return <div className=\"size-1.5 rounded-full bg-current\" />;\n }\n\n return index + 1;\n}\n\nfunction StepIndicator({\n index,\n status,\n shape,\n bulletType,\n}: StepIndicatorProps) {\n return (\n <div\n data-slot=\"steps-indicator\"\n aria-hidden=\"true\"\n className={cn(\n stepIndicatorVariants({ shape, status }),\n status === 'complete' && 'delight-check-bounce',\n status === 'active' && 'delight-pulse-once',\n )}\n >\n <StepIndicatorContent\n index={index}\n status={status}\n shape={shape}\n bulletType={bulletType}\n />\n </div>\n );\n}\n\nStepIndicator.displayName = 'StepIndicator';\n\ninterface StepConnectorProps {\n orientation: 'horizontal' | 'vertical';\n isComplete: boolean;\n}\n\nfunction StepConnector({ orientation, isComplete }: StepConnectorProps) {\n return (\n <div\n data-slot=\"steps-connector\"\n aria-hidden=\"true\"\n className={cn(\n stepConnectorVariants({\n orientation,\n status: isComplete ? 'complete' : 'incomplete',\n }),\n isComplete && 'delight-connector-fill',\n )}\n />\n );\n}\n\nStepConnector.displayName = 'StepConnector';\n\nfunction StepsSubtext({ children, className }: StepsSubtextProps) {\n return (\n <span\n data-slot=\"steps-subtext\"\n className={cn(stepSubtextVariants(), className)}\n >\n {children}\n </span>\n );\n}\n\nStepsSubtext.displayName = 'Steps.Subtext';\n\nfunction StepsItem({\n status: statusOverride,\n onClick,\n children,\n className,\n}: StepsItemProps) {\n const ctx = useStepsContext();\n const index = React.useContext(StepIndexContext);\n const status = statusOverride ?? ctx.getStepStatus(index);\n const isFirst = index === 0;\n const handleClick =\n onClick ?? (ctx.onStepClick ? () => ctx.onStepClick?.(index) : undefined);\n\n // Extract subtext from children\n let label: React.ReactNode = null;\n let subtext: React.ReactNode = null;\n\n React.Children.forEach(children, (child) => {\n if (React.isValidElement(child) && child.type === StepsSubtext) {\n subtext = child;\n } else if (child != null && child !== false) {\n label = child;\n }\n });\n\n // Connector colored based on previous step's completion (source step, not destination)\n const prevStepStatus = !isFirst ? ctx.getStepStatus(index - 1) : undefined;\n const connector = !isFirst && (\n <StepConnector\n orientation={ctx.orientation}\n isComplete={prevStepStatus === 'complete'}\n />\n );\n\n const isHorizontal = ctx.orientation === 'horizontal';\n\n // Build indicator element\n const indicator = (\n <StepIndicator\n index={index}\n status={status}\n shape={ctx.shape}\n bulletType={ctx.bulletType}\n />\n );\n\n // Build label element\n // In horizontal mode, w-0 ensures the label doesn't affect the indicator column width.\n // The text overflows visually (centered under the 38px indicator) but the layout\n // width stays fixed, keeping all connectors equally spaced (matching Figma spec).\n const labelElement = (\n <div\n data-slot=\"steps-label\"\n className={cn(\n 'flex flex-col',\n isHorizontal\n ? 'items-center gap-0.5 text-center w-0 whitespace-nowrap'\n : 'items-start gap-0.5 ml-2.5',\n )}\n >\n <span className={stepLabelVariants({ status })}>{label}</span>\n {subtext}\n </div>\n );\n\n // Layout differs by orientation:\n // - Horizontal: connector + (indicator column), items-start so indicators align at top\n // - Vertical: connector above, indicator + label in row\n const content = isHorizontal ? (\n <div className=\"flex w-full items-start\">\n {connector}\n <div className=\"flex flex-col items-center\">\n {indicator}\n {labelElement}\n </div>\n </div>\n ) : (\n <div className=\"flex flex-col items-start\">\n {connector}\n <div className=\"flex items-center\">\n {indicator}\n {labelElement}\n </div>\n </div>\n );\n\n const labelText = React.useMemo(() => extractText(label), [label]);\n const statusSuffix =\n status === 'complete'\n ? ', completed'\n : status === 'active'\n ? ', current'\n : '';\n\n return (\n <li\n data-slot=\"steps-item\"\n aria-current={status === 'active' ? 'step' : undefined}\n aria-label={\n !handleClick && labelText\n ? `Step ${index + 1}: ${labelText}${statusSuffix}`\n : undefined\n }\n className={cn(\n isHorizontal && !isFirst && 'flex-1',\n !handleClick && className,\n )}\n >\n {handleClick ? (\n <button\n type=\"button\"\n onClick={handleClick}\n aria-label={`Step ${index + 1}: ${labelText || ''}${statusSuffix}`}\n className={cn(\n 'cursor-pointer',\n isHorizontal && 'w-full',\n className,\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background rounded-sm',\n )}\n >\n {content}\n </button>\n ) : (\n content\n )}\n </li>\n );\n}\n\nStepsItem.displayName = 'Steps.Item';\n\n/* -----------------------------------------------------------------------------\n * Main Component\n * -------------------------------------------------------------------------- */\n\n/**\n * Steps displays a multi-step progress indicator for wizards and workflows.\n * Supports horizontal/vertical orientation, numbered or icon bullets, and clickable steps.\n *\n * @llms Wizard/workflow progress with horizontal/vertical layout, numbered or icon steps\n * @example\n * ```tsx\n * <Steps\n * steps={[{ label: 'Details' }, { label: 'Payment' }, { label: 'Confirm' }]}\n * currentStep={1}\n * orientation=\"horizontal\"\n * />\n * ```\n */\nfunction Steps({\n steps,\n currentStep = 0,\n orientation = 'horizontal',\n shape = 'rounded',\n bulletType = 'text',\n onStepClick,\n children,\n className,\n}: StepsProps) {\n const getStepStatus = React.useCallback(\n (index: number): StepStatus => {\n if (index < currentStep) return 'complete';\n if (index === currentStep) return 'active';\n return 'incomplete';\n },\n [currentStep],\n );\n\n const contextValue = React.useMemo<StepsContextValue>(\n () => ({\n orientation,\n shape,\n bulletType,\n onStepClick,\n getStepStatus,\n }),\n [orientation, shape, bulletType, onStepClick, getStepStatus],\n );\n\n // Determine if using flat API or compound API\n const useCompoundAPI = !steps && React.Children.count(children) > 0;\n\n const renderFlatAPI = () => {\n if (!steps || steps.length === 0) return null;\n\n return steps.map((step, index) => (\n <StepIndexContext.Provider key={`${index}-${step.label}`} value={index}>\n <StepsItem>\n {step.label}\n {step.subtext && <StepsSubtext>{step.subtext}</StepsSubtext>}\n </StepsItem>\n </StepIndexContext.Provider>\n ));\n };\n\n const renderCompoundAPI = () => {\n return React.Children.map(children, (child, index) => (\n <StepIndexContext.Provider value={index}>\n {child}\n </StepIndexContext.Provider>\n ));\n };\n\n return (\n <StepsContext.Provider value={contextValue}>\n <nav\n aria-label=\"Progress steps\"\n data-slot=\"steps\"\n // biome-ignore lint/a11y/noNoninteractiveTabindex: Focusable scroll region satisfies axe scrollable-region-focusable.\n tabIndex={0}\n className={cn(\n 'overflow-x-auto focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring',\n className,\n )}\n >\n <ol\n data-slot=\"steps-list\"\n className={cn(\n 'flex',\n orientation === 'horizontal'\n ? 'flex-row items-start px-4'\n : 'flex-col items-start',\n )}\n >\n {useCompoundAPI ? renderCompoundAPI() : renderFlatAPI()}\n </ol>\n </nav>\n </StepsContext.Provider>\n );\n}\n\nSteps.displayName = 'Steps';\n\n/* -----------------------------------------------------------------------------\n * Compound Export\n * -------------------------------------------------------------------------- */\n\n/**\n * @llms Wizard/workflow progress with horizontal/vertical layout, numbered or icon steps\n */\nexport const StepsCompound = Object.assign(Steps, {\n Item: StepsItem,\n Subtext: StepsSubtext,\n});\n\nexport {\n StepsCompound as Steps,\n StepsItem,\n StepsSubtext,\n stepConnectorVariants,\n stepIndicatorVariants,\n stepLabelVariants,\n stepSubtextVariants,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index201.js","names":[],"sources":["../src/components/organisms/content/Steps/Steps.tsx"],"sourcesContent":["import { cva } from 'class-variance-authority';\nimport { Check } from 'lucide-react';\nimport * as React from 'react';\nimport { createSafeContext } from '@/lib/create-safe-context';\nimport { cn, extractText } from '@/lib/utils';\n\n/* -----------------------------------------------------------------------------\n * Types\n * -------------------------------------------------------------------------- */\n\nexport type StepStatus = 'complete' | 'active' | 'incomplete';\n\nexport interface StepData {\n label: string;\n subtext?: string;\n}\n\nexport interface StepsProps {\n /** Steps data for flat API */\n steps?: StepData[];\n /** Current step index (0-based) for flat API */\n currentStep?: number;\n /** Orientation of the steps */\n orientation?: 'horizontal' | 'vertical';\n /** Shape of step indicators */\n shape?: 'rounded' | 'round';\n /** Type of bullet content */\n bulletType?: 'text' | 'icon';\n /** Callback when a step is clicked */\n onStepClick?: (index: number) => void;\n /** Children for compound API */\n children?: React.ReactNode;\n /** Additional className */\n className?: string;\n}\n\nexport interface StepsItemProps {\n /** Override auto-calculated status */\n status?: StepStatus;\n /** Click handler for this step */\n onClick?: () => void;\n /** Step label content */\n children: React.ReactNode;\n /** Additional className */\n className?: string;\n}\n\nexport interface StepsSubtextProps {\n children: React.ReactNode;\n className?: string;\n}\n\n/* -----------------------------------------------------------------------------\n * Variants\n * -------------------------------------------------------------------------- */\n\nconst stepIndicatorVariants = cva(\n 'flex items-center justify-center shrink-0 size-[38px] font-medium text-lg transition-all duration-200 ease-out motion-reduce:transition-none',\n {\n variants: {\n shape: {\n rounded: 'rounded-lg',\n round: 'rounded-full',\n },\n status: {\n complete: 'bg-primary text-primary-foreground shadow-sm',\n active: 'bg-background border-2 border-primary text-primary shadow-sm',\n incomplete: 'bg-accent text-muted-foreground',\n },\n },\n defaultVariants: {\n shape: 'rounded',\n status: 'incomplete',\n },\n },\n);\n\nconst stepConnectorVariants = cva(\n 'shrink-0 transition-colors duration-200 ease-out motion-reduce:transition-none',\n {\n variants: {\n orientation: {\n // Horizontal: fluid width fills available space; mt-[18px] centers 2px line with 38px indicator\n horizontal: 'h-0.5 flex-1 min-w-4 mx-2 mt-[18px]',\n // Vertical: fixed size, centered under 38px indicator\n vertical: 'w-0.5 h-[30px] my-1 ml-[18px]',\n },\n status: {\n complete: 'bg-primary',\n incomplete: 'bg-border',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n status: 'incomplete',\n },\n },\n);\n\nconst stepLabelVariants = cva('text-base leading-6', {\n variants: {\n status: {\n complete: 'text-card-foreground',\n active: 'text-card-foreground',\n incomplete: 'text-muted-foreground',\n },\n },\n defaultVariants: {\n status: 'incomplete',\n },\n});\n\nconst stepSubtextVariants = cva('text-sm leading-5 text-muted-foreground');\n\n/* -----------------------------------------------------------------------------\n * Context\n * -------------------------------------------------------------------------- */\n\ninterface StepsContextValue {\n orientation: 'horizontal' | 'vertical';\n shape: 'rounded' | 'round';\n bulletType: 'text' | 'icon';\n onStepClick?: (index: number) => void;\n getStepStatus: (index: number) => StepStatus;\n}\n\nconst [StepsContext, useStepsContext] =\n createSafeContext<StepsContextValue>('Steps');\n\n/** Per-item index context — injected by Steps parent via Children.map or flat API */\nconst StepIndexContext = React.createContext<number>(0);\n\n/* -----------------------------------------------------------------------------\n * Sub-components\n * -------------------------------------------------------------------------- */\n\ninterface StepIndicatorProps {\n index: number;\n status: StepStatus;\n shape: 'rounded' | 'round';\n bulletType: 'text' | 'icon';\n}\n\nfunction StepIndicatorContent({\n index,\n status,\n shape,\n bulletType,\n}: StepIndicatorProps) {\n if (bulletType === 'icon') {\n if (status === 'complete') {\n return <Check className=\"size-[22px] delight-check-draw\" />;\n }\n if (status === 'active') {\n return (\n <div\n className={cn(\n 'size-5 bg-primary',\n shape === 'rounded' ? 'rounded-sm' : 'rounded-full',\n )}\n />\n );\n }\n\n return <div className=\"size-1.5 rounded-full bg-current\" />;\n }\n\n return index + 1;\n}\n\nfunction StepIndicator({\n index,\n status,\n shape,\n bulletType,\n}: StepIndicatorProps) {\n return (\n <div\n data-slot=\"steps-indicator\"\n aria-hidden=\"true\"\n className={cn(\n stepIndicatorVariants({ shape, status }),\n status === 'complete' && 'delight-check-bounce',\n status === 'active' && 'delight-pulse-once',\n )}\n >\n <StepIndicatorContent\n index={index}\n status={status}\n shape={shape}\n bulletType={bulletType}\n />\n </div>\n );\n}\n\nStepIndicator.displayName = 'StepIndicator';\n\ninterface StepConnectorProps {\n orientation: 'horizontal' | 'vertical';\n isComplete: boolean;\n}\n\nfunction StepConnector({ orientation, isComplete }: StepConnectorProps) {\n return (\n <div\n data-slot=\"steps-connector\"\n aria-hidden=\"true\"\n className={cn(\n stepConnectorVariants({\n orientation,\n status: isComplete ? 'complete' : 'incomplete',\n }),\n isComplete && 'delight-connector-fill',\n )}\n />\n );\n}\n\nStepConnector.displayName = 'StepConnector';\n\nfunction StepsSubtext({ children, className }: StepsSubtextProps) {\n return (\n <span\n data-slot=\"steps-subtext\"\n className={cn(stepSubtextVariants(), className)}\n >\n {children}\n </span>\n );\n}\n\nStepsSubtext.displayName = 'Steps.Subtext';\n\nfunction StepsItem({\n status: statusOverride,\n onClick,\n children,\n className,\n}: StepsItemProps) {\n const ctx = useStepsContext();\n const index = React.useContext(StepIndexContext);\n const status = statusOverride ?? ctx.getStepStatus(index);\n const isFirst = index === 0;\n const handleClick =\n onClick ?? (ctx.onStepClick ? () => ctx.onStepClick?.(index) : undefined);\n\n // Extract subtext from children\n let label: React.ReactNode = null;\n let subtext: React.ReactNode = null;\n\n React.Children.forEach(children, (child) => {\n if (React.isValidElement(child) && child.type === StepsSubtext) {\n subtext = child;\n } else if (child != null && child !== false) {\n label = child;\n }\n });\n\n // Connector colored based on previous step's completion (source step, not destination)\n const prevStepStatus = !isFirst ? ctx.getStepStatus(index - 1) : undefined;\n const connector = !isFirst && (\n <StepConnector\n orientation={ctx.orientation}\n isComplete={prevStepStatus === 'complete'}\n />\n );\n\n const isHorizontal = ctx.orientation === 'horizontal';\n\n // Build indicator element\n const indicator = (\n <StepIndicator\n index={index}\n status={status}\n shape={ctx.shape}\n bulletType={ctx.bulletType}\n />\n );\n\n // Build label element\n // In horizontal mode, w-0 ensures the label doesn't affect the indicator column width.\n // The text overflows visually (centered under the 38px indicator) but the layout\n // width stays fixed, keeping all connectors equally spaced (matching Figma spec).\n const labelElement = (\n <div\n data-slot=\"steps-label\"\n className={cn(\n 'flex flex-col',\n isHorizontal\n ? 'items-center gap-0.5 text-center w-0 whitespace-nowrap'\n : 'items-start gap-0.5 ml-2.5',\n )}\n >\n <span className={stepLabelVariants({ status })}>{label}</span>\n {subtext}\n </div>\n );\n\n // Layout differs by orientation:\n // - Horizontal: connector + (indicator column), items-start so indicators align at top\n // - Vertical: connector above, indicator + label in row\n const content = isHorizontal ? (\n <div className=\"flex w-full items-start\">\n {connector}\n <div className=\"flex flex-col items-center\">\n {indicator}\n {labelElement}\n </div>\n </div>\n ) : (\n <div className=\"flex flex-col items-start\">\n {connector}\n <div className=\"flex items-center\">\n {indicator}\n {labelElement}\n </div>\n </div>\n );\n\n const labelText = React.useMemo(() => extractText(label), [label]);\n const statusSuffix =\n status === 'complete'\n ? ', completed'\n : status === 'active'\n ? ', current'\n : '';\n\n return (\n <li\n data-slot=\"steps-item\"\n aria-current={status === 'active' ? 'step' : undefined}\n aria-label={\n !handleClick && labelText\n ? `Step ${index + 1}: ${labelText}${statusSuffix}`\n : undefined\n }\n className={cn(\n isHorizontal && !isFirst && 'flex-1',\n !handleClick && className,\n )}\n >\n {handleClick ? (\n <button\n type=\"button\"\n onClick={handleClick}\n aria-label={`Step ${index + 1}: ${labelText || ''}${statusSuffix}`}\n className={cn(\n 'cursor-pointer',\n isHorizontal && 'w-full',\n className,\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background rounded-sm',\n )}\n >\n {content}\n </button>\n ) : (\n content\n )}\n </li>\n );\n}\n\nStepsItem.displayName = 'Steps.Item';\n\n/* -----------------------------------------------------------------------------\n * Main Component\n * -------------------------------------------------------------------------- */\n\n/**\n * Steps displays a multi-step progress indicator for wizards and workflows.\n * Supports horizontal/vertical orientation, numbered or icon bullets, and clickable steps.\n *\n * @llms Wizard/workflow progress with horizontal/vertical layout, numbered or icon steps\n * @example\n * ```tsx\n * <Steps\n * steps={[{ label: 'Details' }, { label: 'Payment' }, { label: 'Confirm' }]}\n * currentStep={1}\n * orientation=\"horizontal\"\n * />\n * ```\n */\nfunction Steps({\n steps,\n currentStep = 0,\n orientation = 'horizontal',\n shape = 'rounded',\n bulletType = 'text',\n onStepClick,\n children,\n className,\n}: StepsProps) {\n const getStepStatus = React.useCallback(\n (index: number): StepStatus => {\n if (index < currentStep) return 'complete';\n if (index === currentStep) return 'active';\n return 'incomplete';\n },\n [currentStep],\n );\n\n const contextValue = React.useMemo<StepsContextValue>(\n () => ({\n orientation,\n shape,\n bulletType,\n onStepClick,\n getStepStatus,\n }),\n [orientation, shape, bulletType, onStepClick, getStepStatus],\n );\n\n // Determine if using flat API or compound API\n const useCompoundAPI = !steps && React.Children.count(children) > 0;\n\n const renderFlatAPI = () => {\n if (!steps || steps.length === 0) return null;\n\n return steps.map((step, index) => (\n <StepIndexContext.Provider key={`${index}-${step.label}`} value={index}>\n <StepsItem>\n {step.label}\n {step.subtext && <StepsSubtext>{step.subtext}</StepsSubtext>}\n </StepsItem>\n </StepIndexContext.Provider>\n ));\n };\n\n const renderCompoundAPI = () => {\n return React.Children.map(children, (child, index) => (\n <StepIndexContext.Provider value={index}>\n {child}\n </StepIndexContext.Provider>\n ));\n };\n\n return (\n <StepsContext.Provider value={contextValue}>\n <nav\n aria-label=\"Progress steps\"\n data-slot=\"steps\"\n // biome-ignore lint/a11y/noNoninteractiveTabindex: Focusable scroll region satisfies axe scrollable-region-focusable.\n tabIndex={0}\n className={cn(\n 'overflow-x-auto focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring',\n className,\n )}\n >\n <ol\n data-slot=\"steps-list\"\n className={cn(\n 'flex',\n orientation === 'horizontal'\n ? 'flex-row items-start px-4'\n : 'flex-col items-start',\n )}\n >\n {useCompoundAPI ? renderCompoundAPI() : renderFlatAPI()}\n </ol>\n </nav>\n </StepsContext.Provider>\n );\n}\n\nSteps.displayName = 'Steps';\n\n/* -----------------------------------------------------------------------------\n * Compound Export\n * -------------------------------------------------------------------------- */\n\n/**\n * @llms Wizard/workflow progress with horizontal/vertical layout, numbered or icon steps\n */\nexport const StepsCompound = Object.assign(Steps, {\n Item: StepsItem,\n Subtext: StepsSubtext,\n});\n\nexport {\n StepsCompound as Steps,\n StepsItem,\n StepsSubtext,\n stepConnectorVariants,\n stepIndicatorVariants,\n stepLabelVariants,\n stepSubtextVariants,\n};\n"],"mappings":"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"}