@fanvue/ui 1.2.0 → 1.2.1

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 (135) hide show
  1. package/dist/cjs/components/Alert/Alert.cjs +4 -4
  2. package/dist/cjs/components/Alert/Alert.cjs.map +1 -1
  3. package/dist/cjs/components/Avatar/Avatar.cjs.map +1 -1
  4. package/dist/cjs/components/Badge/Badge.cjs.map +1 -1
  5. package/dist/cjs/components/Button/Button.cjs +9 -9
  6. package/dist/cjs/components/Button/Button.cjs.map +1 -1
  7. package/dist/cjs/components/Checkbox/Checkbox.cjs +6 -7
  8. package/dist/cjs/components/Checkbox/Checkbox.cjs.map +1 -1
  9. package/dist/cjs/components/Chip/Chip.cjs +2 -2
  10. package/dist/cjs/components/Chip/Chip.cjs.map +1 -1
  11. package/dist/cjs/components/Count/Count.cjs.map +1 -1
  12. package/dist/cjs/components/DatePicker/DatePicker.cjs +30 -7
  13. package/dist/cjs/components/DatePicker/DatePicker.cjs.map +1 -1
  14. package/dist/cjs/components/Divider/Divider.cjs.map +1 -1
  15. package/dist/cjs/components/IconButton/IconButton.cjs +10 -10
  16. package/dist/cjs/components/IconButton/IconButton.cjs.map +1 -1
  17. package/dist/cjs/components/Icons/ArrowRightIcon.cjs.map +1 -1
  18. package/dist/cjs/components/Icons/ArrowUpRightIcon.cjs.map +1 -1
  19. package/dist/cjs/components/Icons/CheckCircleIcon.cjs.map +1 -1
  20. package/dist/cjs/components/Icons/ChevronLeftIcon.cjs.map +1 -1
  21. package/dist/cjs/components/Icons/ChevronRightIcon.cjs.map +1 -1
  22. package/dist/cjs/components/Icons/CloseIcon.cjs.map +1 -1
  23. package/dist/cjs/components/Icons/CrossIcon.cjs.map +1 -1
  24. package/dist/cjs/components/Icons/CrownIcon.cjs.map +1 -1
  25. package/dist/cjs/components/Icons/ErrorCircleIcon.cjs.map +1 -1
  26. package/dist/cjs/components/Icons/ErrorIcon.cjs.map +1 -1
  27. package/dist/cjs/components/Icons/EyeIcon.cjs.map +1 -1
  28. package/dist/cjs/components/Icons/FireIcon.cjs.map +1 -1
  29. package/dist/cjs/components/Icons/HomeIcon.cjs.map +1 -1
  30. package/dist/cjs/components/Icons/InfoCircleIcon.cjs.map +1 -1
  31. package/dist/cjs/components/Icons/InfoIcon.cjs.map +1 -1
  32. package/dist/cjs/components/Icons/MicrophoneIcon.cjs.map +1 -1
  33. package/dist/cjs/components/Icons/PlusIcon.cjs.map +1 -1
  34. package/dist/cjs/components/Icons/SpinnerIcon.cjs.map +1 -1
  35. package/dist/cjs/components/Icons/StopIcon.cjs.map +1 -1
  36. package/dist/cjs/components/Icons/SuccessIcon.cjs.map +1 -1
  37. package/dist/cjs/components/Icons/WarningIcon.cjs.map +1 -1
  38. package/dist/cjs/components/Icons/WarningTriangleIcon.cjs.map +1 -1
  39. package/dist/cjs/components/Logo/Logo.cjs +11 -11
  40. package/dist/cjs/components/Logo/Logo.cjs.map +1 -1
  41. package/dist/cjs/components/Pagination/Pagination.cjs +3 -3
  42. package/dist/cjs/components/Pagination/Pagination.cjs.map +1 -1
  43. package/dist/cjs/components/Pill/Pill.cjs.map +1 -1
  44. package/dist/cjs/components/ProgressBar/ProgressBar.cjs.map +1 -1
  45. package/dist/cjs/components/Radio/Radio.cjs +1 -1
  46. package/dist/cjs/components/Radio/Radio.cjs.map +1 -1
  47. package/dist/cjs/components/RadioGroup/RadioGroup.cjs.map +1 -1
  48. package/dist/cjs/components/Slider/Slider.cjs.map +1 -1
  49. package/dist/cjs/components/Slider/SliderThumb.cjs +1 -0
  50. package/dist/cjs/components/Slider/SliderThumb.cjs.map +1 -1
  51. package/dist/cjs/components/Snackbar/Snackbar.cjs.map +1 -1
  52. package/dist/cjs/components/Switch/Switch.cjs +1 -0
  53. package/dist/cjs/components/Switch/Switch.cjs.map +1 -1
  54. package/dist/cjs/components/SwitchField/SwitchField.cjs.map +1 -1
  55. package/dist/cjs/components/SwitchToggle/SwitchToggle.cjs +48 -31
  56. package/dist/cjs/components/SwitchToggle/SwitchToggle.cjs.map +1 -1
  57. package/dist/cjs/components/Tabs/Tabs.cjs.map +1 -1
  58. package/dist/cjs/components/Tabs/TabsContent.cjs.map +1 -1
  59. package/dist/cjs/components/Tabs/TabsList.cjs.map +1 -1
  60. package/dist/cjs/components/Tabs/TabsTrigger.cjs +2 -0
  61. package/dist/cjs/components/Tabs/TabsTrigger.cjs.map +1 -1
  62. package/dist/cjs/components/TextField/TextField.cjs +1 -1
  63. package/dist/cjs/components/TextField/TextField.cjs.map +1 -1
  64. package/dist/cjs/components/Toast/Toast.cjs +1 -1
  65. package/dist/cjs/components/Toast/Toast.cjs.map +1 -1
  66. package/dist/cjs/components/Tooltip/Tooltip.cjs.map +1 -1
  67. package/dist/components/Alert/Alert.mjs +4 -4
  68. package/dist/components/Alert/Alert.mjs.map +1 -1
  69. package/dist/components/Avatar/Avatar.mjs.map +1 -1
  70. package/dist/components/Badge/Badge.mjs.map +1 -1
  71. package/dist/components/Button/Button.mjs +9 -9
  72. package/dist/components/Button/Button.mjs.map +1 -1
  73. package/dist/components/Checkbox/Checkbox.mjs +6 -7
  74. package/dist/components/Checkbox/Checkbox.mjs.map +1 -1
  75. package/dist/components/Chip/Chip.mjs +2 -2
  76. package/dist/components/Chip/Chip.mjs.map +1 -1
  77. package/dist/components/Count/Count.mjs.map +1 -1
  78. package/dist/components/DatePicker/DatePicker.mjs +30 -7
  79. package/dist/components/DatePicker/DatePicker.mjs.map +1 -1
  80. package/dist/components/Divider/Divider.mjs.map +1 -1
  81. package/dist/components/IconButton/IconButton.mjs +10 -10
  82. package/dist/components/IconButton/IconButton.mjs.map +1 -1
  83. package/dist/components/Icons/ArrowRightIcon.mjs.map +1 -1
  84. package/dist/components/Icons/ArrowUpRightIcon.mjs.map +1 -1
  85. package/dist/components/Icons/CheckCircleIcon.mjs.map +1 -1
  86. package/dist/components/Icons/ChevronLeftIcon.mjs.map +1 -1
  87. package/dist/components/Icons/ChevronRightIcon.mjs.map +1 -1
  88. package/dist/components/Icons/CloseIcon.mjs.map +1 -1
  89. package/dist/components/Icons/CrossIcon.mjs.map +1 -1
  90. package/dist/components/Icons/CrownIcon.mjs.map +1 -1
  91. package/dist/components/Icons/ErrorCircleIcon.mjs.map +1 -1
  92. package/dist/components/Icons/ErrorIcon.mjs.map +1 -1
  93. package/dist/components/Icons/EyeIcon.mjs.map +1 -1
  94. package/dist/components/Icons/FireIcon.mjs.map +1 -1
  95. package/dist/components/Icons/HomeIcon.mjs.map +1 -1
  96. package/dist/components/Icons/InfoCircleIcon.mjs.map +1 -1
  97. package/dist/components/Icons/InfoIcon.mjs.map +1 -1
  98. package/dist/components/Icons/MicrophoneIcon.mjs.map +1 -1
  99. package/dist/components/Icons/PlusIcon.mjs.map +1 -1
  100. package/dist/components/Icons/SpinnerIcon.mjs.map +1 -1
  101. package/dist/components/Icons/StopIcon.mjs.map +1 -1
  102. package/dist/components/Icons/SuccessIcon.mjs.map +1 -1
  103. package/dist/components/Icons/WarningIcon.mjs.map +1 -1
  104. package/dist/components/Icons/WarningTriangleIcon.mjs.map +1 -1
  105. package/dist/components/Logo/Logo.mjs +11 -11
  106. package/dist/components/Logo/Logo.mjs.map +1 -1
  107. package/dist/components/Pagination/Pagination.mjs +3 -3
  108. package/dist/components/Pagination/Pagination.mjs.map +1 -1
  109. package/dist/components/Pill/Pill.mjs.map +1 -1
  110. package/dist/components/ProgressBar/ProgressBar.mjs.map +1 -1
  111. package/dist/components/Radio/Radio.mjs +1 -1
  112. package/dist/components/Radio/Radio.mjs.map +1 -1
  113. package/dist/components/RadioGroup/RadioGroup.mjs.map +1 -1
  114. package/dist/components/Slider/Slider.mjs.map +1 -1
  115. package/dist/components/Slider/SliderThumb.mjs +1 -0
  116. package/dist/components/Slider/SliderThumb.mjs.map +1 -1
  117. package/dist/components/Snackbar/Snackbar.mjs.map +1 -1
  118. package/dist/components/Switch/Switch.mjs +1 -0
  119. package/dist/components/Switch/Switch.mjs.map +1 -1
  120. package/dist/components/SwitchField/SwitchField.mjs.map +1 -1
  121. package/dist/components/SwitchToggle/SwitchToggle.mjs +48 -31
  122. package/dist/components/SwitchToggle/SwitchToggle.mjs.map +1 -1
  123. package/dist/components/Tabs/Tabs.mjs.map +1 -1
  124. package/dist/components/Tabs/TabsContent.mjs.map +1 -1
  125. package/dist/components/Tabs/TabsList.mjs.map +1 -1
  126. package/dist/components/Tabs/TabsTrigger.mjs +2 -0
  127. package/dist/components/Tabs/TabsTrigger.mjs.map +1 -1
  128. package/dist/components/TextField/TextField.mjs +1 -1
  129. package/dist/components/TextField/TextField.mjs.map +1 -1
  130. package/dist/components/Toast/Toast.mjs +1 -1
  131. package/dist/components/Toast/Toast.mjs.map +1 -1
  132. package/dist/components/Tooltip/Tooltip.mjs.map +1 -1
  133. package/dist/index.d.ts +521 -142
  134. package/dist/styles/theme.css +6 -0
  135. package/package.json +2 -2
@@ -24,10 +24,10 @@ function _interopNamespaceDefault(e) {
24
24
  }
25
25
  const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
26
26
  const CLOSE_BUTTON_CLASSES = {
27
- info: "hover:bg-info-500/10 text-info-500 motion-safe:transition-colors motion-safe:duration-150",
28
- success: "hover:bg-success-500/10 text-success-500 motion-safe:transition-colors motion-safe:duration-150",
29
- warning: "hover:bg-warning-500/10 text-warning-500 motion-safe:transition-colors motion-safe:duration-150",
30
- error: "hover:bg-error-500/10 text-error-500 motion-safe:transition-colors motion-safe:duration-150"
27
+ info: "hover:bg-info-500/10 active:bg-info-500/10 text-info-500 motion-safe:transition-colors motion-safe:duration-150",
28
+ success: "hover:bg-success-500/10 active:bg-success-500/10 text-success-500 motion-safe:transition-colors motion-safe:duration-150",
29
+ warning: "hover:bg-warning-500/10 active:bg-warning-500/10 text-warning-500 motion-safe:transition-colors motion-safe:duration-150",
30
+ error: "hover:bg-error-500/10 active:bg-error-500/10 text-error-500 motion-safe:transition-colors motion-safe:duration-150"
31
31
  };
32
32
  const Alert = React__namespace.forwardRef(
33
33
  ({
@@ -1 +1 @@
1
- {"version":3,"file":"Alert.cjs","sources":["../../../../src/components/Alert/Alert.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button/Button\";\nimport { CrossIcon } from \"../Icons/CrossIcon\";\n\nexport type AlertVariant = \"info\" | \"success\" | \"warning\" | \"error\";\n\nexport interface AlertProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Visual style variant of the alert (matches Figma \"Variant\" property) */\n variant?: AlertVariant;\n /** Optional title text (bold) */\n title?: string;\n /** Left icon element */\n icon?: React.ReactNode;\n /** Show close button */\n closable?: boolean;\n /** Callback when close button is clicked */\n onClose?: () => void;\n /** Accessible label for the close button. @default \"Close alert\" */\n closeLabel?: string;\n}\n\nconst CLOSE_BUTTON_CLASSES: Record<AlertVariant, string> = {\n info: \"hover:bg-info-500/10 text-info-500 motion-safe:transition-colors motion-safe:duration-150\",\n success:\n \"hover:bg-success-500/10 text-success-500 motion-safe:transition-colors motion-safe:duration-150\",\n warning:\n \"hover:bg-warning-500/10 text-warning-500 motion-safe:transition-colors motion-safe:duration-150\",\n error:\n \"hover:bg-error-500/10 text-error-500 motion-safe:transition-colors motion-safe:duration-150\",\n};\n\nexport const Alert = React.forwardRef<HTMLDivElement, AlertProps>(\n (\n {\n className,\n variant = \"info\",\n title,\n icon,\n closable = false,\n onClose,\n closeLabel = \"Close alert\",\n children,\n ...props\n },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n role=\"alert\"\n data-testid=\"alert\"\n className={cn(\n \"grid gap-x-3 rounded-lg p-4 text-sm leading-[18px]\",\n icon && closable && \"grid-cols-[auto_1fr_auto]\",\n icon && !closable && \"grid-cols-[auto_1fr]\",\n !icon && closable && \"grid-cols-[1fr_auto]\",\n !icon && !closable && \"grid-cols-[1fr]\",\n title && children ? \"items-start\" : \"items-center\",\n variant === \"info\" && \"bg-info-50 text-info-500\",\n variant === \"success\" && \"bg-success-50 text-success-500\",\n variant === \"warning\" && \"bg-warning-50 text-warning-500\",\n variant === \"error\" && \"bg-error-50 text-error-500\",\n className,\n )}\n {...props}\n >\n {icon && (\n <span className=\"flex shrink-0 items-start\" aria-hidden=\"true\">\n {icon}\n </span>\n )}\n\n <div className=\"flex min-w-0 flex-col gap-2\">\n {title && <div className=\"typography-body-2-semibold text-body-100\">{title}</div>}\n <div className=\"typography-body-2-regular text-body-200\">{children}</div>\n </div>\n\n {closable && (\n <Button\n variant=\"tertiary\"\n size=\"24\"\n onClick={onClose}\n className={cn(\"self-start\", CLOSE_BUTTON_CLASSES[variant])}\n aria-label={closeLabel}\n >\n <CrossIcon />\n </Button>\n )}\n </div>\n );\n },\n);\n\nAlert.displayName = \"Alert\";\n"],"names":["React","jsxs","cn","jsx","Button","CrossIcon"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAsBA,MAAM,uBAAqD;AAAA,EACzD,MAAM;AAAA,EACN,SACE;AAAA,EACF,SACE;AAAA,EACF,OACE;AACJ;AAEO,MAAM,QAAQA,iBAAM;AAAA,EACzB,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,eAAY;AAAA,QACZ,WAAWC,GAAAA;AAAAA,UACT;AAAA,UACA,QAAQ,YAAY;AAAA,UACpB,QAAQ,CAAC,YAAY;AAAA,UACrB,CAAC,QAAQ,YAAY;AAAA,UACrB,CAAC,QAAQ,CAAC,YAAY;AAAA,UACtB,SAAS,WAAW,gBAAgB;AAAA,UACpC,YAAY,UAAU;AAAA,UACtB,YAAY,aAAa;AAAA,UACzB,YAAY,aAAa;AAAA,UACzB,YAAY,WAAW;AAAA,UACvB;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,uCACE,QAAA,EAAK,WAAU,6BAA4B,eAAY,QACrD,UAAA,MACH;AAAA,UAGFD,2BAAAA,KAAC,OAAA,EAAI,WAAU,+BACZ,UAAA;AAAA,YAAA,SAASE,2BAAAA,IAAC,OAAA,EAAI,WAAU,4CAA4C,UAAA,OAAM;AAAA,YAC3EA,2BAAAA,IAAC,OAAA,EAAI,WAAU,2CAA2C,SAAA,CAAS;AAAA,UAAA,GACrE;AAAA,UAEC,YACCA,2BAAAA;AAAAA,YAACC,OAAAA;AAAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS;AAAA,cACT,WAAWF,GAAAA,GAAG,cAAc,qBAAqB,OAAO,CAAC;AAAA,cACzD,cAAY;AAAA,cAEZ,yCAACG,UAAAA,WAAA,CAAA,CAAU;AAAA,YAAA;AAAA,UAAA;AAAA,QACb;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,MAAM,cAAc;;"}
1
+ {"version":3,"file":"Alert.cjs","sources":["../../../../src/components/Alert/Alert.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button/Button\";\nimport { CrossIcon } from \"../Icons/CrossIcon\";\n\n/** Visual style variant of the alert. */\nexport type AlertVariant = \"info\" | \"success\" | \"warning\" | \"error\";\n\nexport interface AlertProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Visual style variant of the alert. @default \"info\" */\n variant?: AlertVariant;\n /** Optional title text displayed in bold above the description. */\n title?: string;\n /** Icon element displayed at the leading edge of the alert. */\n icon?: React.ReactNode;\n /** Whether to show the close button. @default false */\n closable?: boolean;\n /** Callback fired when the close button is clicked. */\n onClose?: () => void;\n /** Accessible label for the close button. @default \"Close alert\" */\n closeLabel?: string;\n}\n\nconst CLOSE_BUTTON_CLASSES: Record<AlertVariant, string> = {\n info: \"hover:bg-info-500/10 active:bg-info-500/10 text-info-500 motion-safe:transition-colors motion-safe:duration-150\",\n success:\n \"hover:bg-success-500/10 active:bg-success-500/10 text-success-500 motion-safe:transition-colors motion-safe:duration-150\",\n warning:\n \"hover:bg-warning-500/10 active:bg-warning-500/10 text-warning-500 motion-safe:transition-colors motion-safe:duration-150\",\n error:\n \"hover:bg-error-500/10 active:bg-error-500/10 text-error-500 motion-safe:transition-colors motion-safe:duration-150\",\n};\n\n/**\n * Displays a contextual feedback message to the user.\n *\n * Supports `info`, `success`, `warning`, and `error` variants with an optional\n * icon, title, description, and dismiss button.\n *\n * @example\n * ```tsx\n * <Alert variant=\"success\" title=\"Saved\" closable onClose={handleClose}>\n * Your changes have been saved.\n * </Alert>\n * ```\n */\nexport const Alert = React.forwardRef<HTMLDivElement, AlertProps>(\n (\n {\n className,\n variant = \"info\",\n title,\n icon,\n closable = false,\n onClose,\n closeLabel = \"Close alert\",\n children,\n ...props\n },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n role=\"alert\"\n data-testid=\"alert\"\n className={cn(\n \"grid gap-x-3 rounded-lg p-4 text-sm leading-[18px]\",\n icon && closable && \"grid-cols-[auto_1fr_auto]\",\n icon && !closable && \"grid-cols-[auto_1fr]\",\n !icon && closable && \"grid-cols-[1fr_auto]\",\n !icon && !closable && \"grid-cols-[1fr]\",\n title && children ? \"items-start\" : \"items-center\",\n variant === \"info\" && \"bg-info-50 text-info-500\",\n variant === \"success\" && \"bg-success-50 text-success-500\",\n variant === \"warning\" && \"bg-warning-50 text-warning-500\",\n variant === \"error\" && \"bg-error-50 text-error-500\",\n className,\n )}\n {...props}\n >\n {icon && (\n <span className=\"flex shrink-0 items-start\" aria-hidden=\"true\">\n {icon}\n </span>\n )}\n\n <div className=\"flex min-w-0 flex-col gap-2\">\n {title && <div className=\"typography-body-2-semibold text-body-100\">{title}</div>}\n <div className=\"typography-body-2-regular text-body-200\">{children}</div>\n </div>\n\n {closable && (\n <Button\n variant=\"tertiary\"\n size=\"24\"\n onClick={onClose}\n className={cn(\"self-start\", CLOSE_BUTTON_CLASSES[variant])}\n aria-label={closeLabel}\n >\n <CrossIcon />\n </Button>\n )}\n </div>\n );\n },\n);\n\nAlert.displayName = \"Alert\";\n"],"names":["React","jsxs","cn","jsx","Button","CrossIcon"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAuBA,MAAM,uBAAqD;AAAA,EACzD,MAAM;AAAA,EACN,SACE;AAAA,EACF,SACE;AAAA,EACF,OACE;AACJ;AAeO,MAAM,QAAQA,iBAAM;AAAA,EACzB,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,eAAY;AAAA,QACZ,WAAWC,GAAAA;AAAAA,UACT;AAAA,UACA,QAAQ,YAAY;AAAA,UACpB,QAAQ,CAAC,YAAY;AAAA,UACrB,CAAC,QAAQ,YAAY;AAAA,UACrB,CAAC,QAAQ,CAAC,YAAY;AAAA,UACtB,SAAS,WAAW,gBAAgB;AAAA,UACpC,YAAY,UAAU;AAAA,UACtB,YAAY,aAAa;AAAA,UACzB,YAAY,aAAa;AAAA,UACzB,YAAY,WAAW;AAAA,UACvB;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,uCACE,QAAA,EAAK,WAAU,6BAA4B,eAAY,QACrD,UAAA,MACH;AAAA,UAGFD,2BAAAA,KAAC,OAAA,EAAI,WAAU,+BACZ,UAAA;AAAA,YAAA,SAASE,2BAAAA,IAAC,OAAA,EAAI,WAAU,4CAA4C,UAAA,OAAM;AAAA,YAC3EA,2BAAAA,IAAC,OAAA,EAAI,WAAU,2CAA2C,SAAA,CAAS;AAAA,UAAA,GACrE;AAAA,UAEC,YACCA,2BAAAA;AAAAA,YAACC,OAAAA;AAAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS;AAAA,cACT,WAAWF,GAAAA,GAAG,cAAc,qBAAqB,OAAO,CAAC;AAAA,cACzD,cAAY;AAAA,cAEZ,yCAACG,UAAAA,WAAA,CAAA,CAAU;AAAA,YAAA;AAAA,UAAA;AAAA,QACb;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,MAAM,cAAc;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.cjs","sources":["../../../../src/components/Avatar/Avatar.tsx"],"sourcesContent":["import * as AvatarPrimitive from \"@radix-ui/react-avatar\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport type AvatarSize = 16 | 24 | 32 | 40 | 48 | 64 | 88 | 148;\n\nconst AvatarContext = React.createContext<{ size: AvatarSize; NSFWShow: boolean }>({\n size: 40,\n NSFWShow: false,\n});\n\nconst STATUS_POSITIONS: Record<AvatarSize, { top: number; right: number }> = {\n 16: { top: -4, right: -4 },\n 24: { top: -3, right: -3 },\n 32: { top: -2, right: -2 },\n 40: { top: -1, right: -1 },\n 48: { top: 0, right: 0 },\n 64: { top: 2, right: 2 },\n 88: { top: 6, right: 6 },\n 148: { top: 15, right: 15 },\n};\n\n/** Shared avatar styling props */\ninterface AvatarStyleProps {\n /** Size variant of the avatar (matches Figma \"Size\" property) */\n size?: AvatarSize;\n /** Show online status indicator */\n onlineIndicator?: boolean;\n /** Show platinum gradient border (matches Figma \"Platinum show\" property) */\n platinumShow?: boolean;\n /** Show NSFW blur filter (matches Figma \"NSFW show\" property) */\n NSFWShow?: boolean;\n}\n\nexport interface AvatarRootProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>,\n AvatarStyleProps {}\n\nconst AvatarRoot = React.forwardRef<\n React.ComponentRef<typeof AvatarPrimitive.Root>,\n AvatarRootProps\n>(\n (\n {\n className,\n size = 40,\n onlineIndicator = false,\n platinumShow = false,\n NSFWShow = false,\n children,\n ...props\n },\n ref,\n ) => {\n const statusPosition = STATUS_POSITIONS[size];\n\n return (\n <AvatarContext.Provider value={{ size, NSFWShow }}>\n <div className=\"relative inline-flex\">\n <AvatarPrimitive.Root\n ref={ref}\n data-testid=\"avatar\"\n className={cn(\n \"relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-neutral-100\",\n size === 16 && \"typography-caption-semibold size-4\",\n size === 24 && \"typography-caption-semibold size-6\",\n size === 32 && \"typography-body-2-semibold size-8\",\n size === 40 && \"typography-body-1-semibold size-10\",\n size === 48 && \"typography-heading-4 size-12\",\n size === 64 && \"typography-heading-3 size-16\",\n size === 88 && \"typography-heading-2 size-[88px]\",\n size === 148 && \"typography-heading-1 size-[148px]\",\n className,\n )}\n {...props}\n >\n {children}\n </AvatarPrimitive.Root>\n {platinumShow && (\n <div\n className=\"pointer-events-none absolute inset-0 rounded-full\"\n style={{\n background: `linear-gradient(143deg, #504F54 0%, #B1B1B1 20.3154%, #13181C 37.3727%, #C6C6C8 58.8154%, #FFFFFF 69.3154%, #0C0F14 81.3154%, #696A6E 100%)`,\n WebkitMask: \"radial-gradient(circle closest-side, transparent 96%, black 96%)\",\n mask: \"radial-gradient(circle closest-side, transparent 96%, black 96%)\",\n }}\n aria-hidden=\"true\"\n />\n )}\n {onlineIndicator && (\n <span\n className=\"absolute size-3 rounded-full border-2 border-background-150 bg-brand-green-500\"\n style={{\n top: `${statusPosition.top}px`,\n right: `${statusPosition.right}px`,\n }}\n aria-hidden=\"true\"\n />\n )}\n </div>\n </AvatarContext.Provider>\n );\n },\n);\n\nAvatarRoot.displayName = \"AvatarRoot\";\n\nexport interface AvatarImageProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image> {}\n\nconst AvatarImage = React.forwardRef<\n React.ComponentRef<typeof AvatarPrimitive.Image>,\n AvatarImageProps\n>(({ className, ...props }, ref) => {\n const { NSFWShow } = React.useContext(AvatarContext);\n return (\n <AvatarPrimitive.Image\n ref={ref}\n className={cn(\"size-full bg-neutral-200 object-cover\", NSFWShow && \"blur-md\", className)}\n {...props}\n />\n );\n});\n\nAvatarImage.displayName = \"AvatarImage\";\n\nexport interface AvatarFallbackProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback> {}\n\nconst AvatarFallback = React.forwardRef<\n React.ComponentRef<typeof AvatarPrimitive.Fallback>,\n AvatarFallbackProps\n>(({ className, children, ...props }, ref) => (\n <AvatarPrimitive.Fallback\n ref={ref}\n className={cn(\n \"flex size-full items-center justify-center bg-neutral-200 text-neutral-400 uppercase leading-none\",\n className,\n )}\n delayMs={0}\n {...props}\n >\n {children}\n </AvatarPrimitive.Fallback>\n));\n\nAvatarFallback.displayName = \"AvatarFallback\";\n\nexport interface AvatarProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>,\n AvatarStyleProps {\n /** URL of the avatar image */\n src?: string;\n /** Alt text for the avatar image */\n alt?: string;\n /** Fallback content (initials, icon, etc.) */\n fallback?: React.ReactNode;\n}\n\nexport const Avatar = React.forwardRef<\n React.ComponentRef<typeof AvatarPrimitive.Root>,\n AvatarProps\n>(\n (\n {\n className,\n size = 40,\n src,\n alt,\n fallback,\n onlineIndicator = false,\n platinumShow = false,\n NSFWShow = false,\n children,\n ...props\n },\n ref,\n ) => {\n const rootProps = {\n ref,\n size,\n onlineIndicator,\n platinumShow,\n NSFWShow,\n className,\n ...props,\n };\n\n if (children) {\n return <AvatarRoot {...rootProps}>{children}</AvatarRoot>;\n }\n\n return (\n <AvatarRoot {...rootProps}>\n {src && <AvatarImage src={src} alt={alt ?? \"Avatar\"} />}\n <AvatarFallback>{fallback}</AvatarFallback>\n </AvatarRoot>\n );\n },\n);\n\nAvatar.displayName = \"Avatar\";\n\nexport { AvatarRoot, AvatarImage, AvatarFallback };\n"],"names":["React","jsx","jsxs","AvatarPrimitive","cn"],"mappings":"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"}
1
+ {"version":3,"file":"Avatar.cjs","sources":["../../../../src/components/Avatar/Avatar.tsx"],"sourcesContent":["import * as AvatarPrimitive from \"@radix-ui/react-avatar\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Allowed pixel sizes for the avatar. */\nexport type AvatarSize = 16 | 24 | 32 | 40 | 48 | 64 | 88 | 148;\n\nconst AvatarContext = React.createContext<{ size: AvatarSize; NSFWShow: boolean }>({\n size: 40,\n NSFWShow: false,\n});\n\nconst STATUS_POSITIONS: Record<AvatarSize, { top: number; right: number }> = {\n 16: { top: -4, right: -4 },\n 24: { top: -3, right: -3 },\n 32: { top: -2, right: -2 },\n 40: { top: -1, right: -1 },\n 48: { top: 0, right: 0 },\n 64: { top: 2, right: 2 },\n 88: { top: 6, right: 6 },\n 148: { top: 15, right: 15 },\n};\n\n/** Shared avatar styling props. */\ninterface AvatarStyleProps {\n /** Pixel size of the avatar. @default 40 */\n size?: AvatarSize;\n /** Whether to show the online-status indicator dot. @default false */\n onlineIndicator?: boolean;\n /** Whether to show the platinum gradient border ring. @default false */\n platinumShow?: boolean;\n /** Whether to apply the NSFW blur filter over the image. @default false */\n NSFWShow?: boolean;\n}\n\n/** Props for the low-level {@link AvatarRoot} compound component. */\nexport interface AvatarRootProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>,\n AvatarStyleProps {}\n\n/**\n * Low-level avatar root for custom compositions. Provides size context to\n * child `AvatarImage` and `AvatarFallback` components.\n *\n * Prefer the higher-level {@link Avatar} component for most use cases.\n */\nconst AvatarRoot = React.forwardRef<\n React.ComponentRef<typeof AvatarPrimitive.Root>,\n AvatarRootProps\n>(\n (\n {\n className,\n size = 40,\n onlineIndicator = false,\n platinumShow = false,\n NSFWShow = false,\n children,\n ...props\n },\n ref,\n ) => {\n const statusPosition = STATUS_POSITIONS[size];\n\n return (\n <AvatarContext.Provider value={{ size, NSFWShow }}>\n <div className=\"relative inline-flex\">\n <AvatarPrimitive.Root\n ref={ref}\n data-testid=\"avatar\"\n className={cn(\n \"relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-neutral-100\",\n size === 16 && \"typography-caption-semibold size-4\",\n size === 24 && \"typography-caption-semibold size-6\",\n size === 32 && \"typography-body-2-semibold size-8\",\n size === 40 && \"typography-body-1-semibold size-10\",\n size === 48 && \"typography-heading-4 size-12\",\n size === 64 && \"typography-heading-3 size-16\",\n size === 88 && \"typography-heading-2 size-[88px]\",\n size === 148 && \"typography-heading-1 size-[148px]\",\n className,\n )}\n {...props}\n >\n {children}\n </AvatarPrimitive.Root>\n {platinumShow && (\n <div\n className=\"pointer-events-none absolute inset-0 rounded-full\"\n style={{\n background: `linear-gradient(143deg, #504F54 0%, #B1B1B1 20.3154%, #13181C 37.3727%, #C6C6C8 58.8154%, #FFFFFF 69.3154%, #0C0F14 81.3154%, #696A6E 100%)`,\n WebkitMask: \"radial-gradient(circle closest-side, transparent 96%, black 96%)\",\n mask: \"radial-gradient(circle closest-side, transparent 96%, black 96%)\",\n }}\n aria-hidden=\"true\"\n />\n )}\n {onlineIndicator && (\n <span\n className=\"absolute size-3 rounded-full border-2 border-background-150 bg-brand-green-500\"\n style={{\n top: `${statusPosition.top}px`,\n right: `${statusPosition.right}px`,\n }}\n aria-hidden=\"true\"\n />\n )}\n </div>\n </AvatarContext.Provider>\n );\n },\n);\n\nAvatarRoot.displayName = \"AvatarRoot\";\n\n/** Props for the {@link AvatarImage} compound component. */\nexport interface AvatarImageProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image> {}\n\n/** Renders the avatar image. Automatically applies the NSFW blur when enabled on the parent `AvatarRoot`. */\nconst AvatarImage = React.forwardRef<\n React.ComponentRef<typeof AvatarPrimitive.Image>,\n AvatarImageProps\n>(({ className, ...props }, ref) => {\n const { NSFWShow } = React.useContext(AvatarContext);\n return (\n <AvatarPrimitive.Image\n ref={ref}\n className={cn(\"size-full bg-neutral-200 object-cover\", NSFWShow && \"blur-md\", className)}\n {...props}\n />\n );\n});\n\nAvatarImage.displayName = \"AvatarImage\";\n\n/** Props for the {@link AvatarFallback} compound component. */\nexport interface AvatarFallbackProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback> {}\n\n/** Renders fallback content (e.g. initials or an icon) when the avatar image has not loaded. */\nconst AvatarFallback = React.forwardRef<\n React.ComponentRef<typeof AvatarPrimitive.Fallback>,\n AvatarFallbackProps\n>(({ className, children, ...props }, ref) => (\n <AvatarPrimitive.Fallback\n ref={ref}\n className={cn(\n \"flex size-full items-center justify-center bg-neutral-200 text-neutral-400 uppercase leading-none\",\n className,\n )}\n delayMs={0}\n {...props}\n >\n {children}\n </AvatarPrimitive.Fallback>\n));\n\nAvatarFallback.displayName = \"AvatarFallback\";\n\nexport interface AvatarProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>,\n AvatarStyleProps {\n /** URL of the avatar image. */\n src?: string;\n /** Alt text for the avatar image. @default \"Avatar\" */\n alt?: string;\n /** Fallback content rendered when the image has not loaded (e.g. initials or an icon). */\n fallback?: React.ReactNode;\n}\n\n/**\n * Displays a user avatar with optional online indicator, platinum border, and\n * NSFW blur. Pass `src` and `fallback` for the simple API, or compose your own\n * layout with `AvatarRoot`, `AvatarImage`, and `AvatarFallback` as children.\n *\n * @example\n * ```tsx\n * <Avatar src=\"/photo.jpg\" alt=\"Jane Doe\" fallback=\"JD\" size={48} />\n * ```\n */\nexport const Avatar = React.forwardRef<\n React.ComponentRef<typeof AvatarPrimitive.Root>,\n AvatarProps\n>(\n (\n {\n className,\n size = 40,\n src,\n alt,\n fallback,\n onlineIndicator = false,\n platinumShow = false,\n NSFWShow = false,\n children,\n ...props\n },\n ref,\n ) => {\n const rootProps = {\n ref,\n size,\n onlineIndicator,\n platinumShow,\n NSFWShow,\n className,\n ...props,\n };\n\n if (children) {\n return <AvatarRoot {...rootProps}>{children}</AvatarRoot>;\n }\n\n return (\n <AvatarRoot {...rootProps}>\n {src && <AvatarImage src={src} alt={alt ?? \"Avatar\"} />}\n <AvatarFallback>{fallback}</AvatarFallback>\n </AvatarRoot>\n );\n },\n);\n\nAvatar.displayName = \"Avatar\";\n\nexport { AvatarRoot, AvatarImage, AvatarFallback };\n"],"names":["React","jsx","jsxs","AvatarPrimitive","cn"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Badge.cjs","sources":["../../../../src/components/Badge/Badge.tsx"],"sourcesContent":["import { Slot, Slottable } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nconst badgeVariants = {\n variant: {\n default: \"bg-neutral-100 text-neutral-400\",\n dark: \"bg-background-800 text-body-300 dark:text-body-white-solid-constant\",\n success: \"bg-neutral-100 text-neutral-400\",\n warning: \"bg-neutral-100 text-neutral-400\",\n error: \"bg-neutral-100 text-neutral-400\",\n special: \"bg-neutral-100 text-neutral-400\",\n info: \"bg-neutral-100 text-neutral-400\",\n online: \"bg-background-200 text-brand-green-500\",\n brand: \"bg-brand-green-500 text-body-black-solid-constant\",\n pink: \"bg-brand-pink-500 text-body-black-solid-constant\",\n brandLight: \"bg-brand-green-50 text-body-black-solid-constant\",\n pinkLight: \"bg-brand-pink-50 text-body-black-solid-constant\",\n },\n dotColor: {\n default: \"bg-body-black-solid-constant\",\n dark: \"bg-body-300 dark:bg-body-white-solid-constant\",\n success: \"bg-success-500\",\n warning: \"bg-warning-500\",\n error: \"bg-error-500\",\n special: \"bg-special-500\",\n info: \"bg-info-500\",\n online: \"bg-brand-green-500\",\n brand: \"bg-body-black-solid-constant\",\n pink: \"bg-body-black-solid-constant\",\n brandLight: \"bg-body-black-solid-constant\",\n pinkLight: \"bg-body-black-solid-constant\",\n },\n} as const;\n\nexport type BadgeVariant =\n | \"default\"\n | \"dark\"\n | \"success\"\n | \"warning\"\n | \"error\"\n | \"special\"\n | \"info\"\n | \"online\"\n | \"brand\"\n | \"pink\"\n | \"brandLight\"\n | \"pinkLight\";\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Visual style variant of the badge */\n variant?: BadgeVariant;\n /** Show left status indicator dot */\n leftDot?: boolean;\n /** Left icon element */\n leftIcon?: React.ReactNode;\n /** Right icon element */\n rightIcon?: React.ReactNode;\n /** Render as a different element using Radix Slot */\n asChild?: boolean;\n}\n\nexport const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n (\n {\n className,\n variant = \"default\",\n leftDot = true,\n leftIcon,\n rightIcon,\n asChild = false,\n children,\n ...props\n },\n ref,\n ) => {\n const Comp = asChild ? Slot : \"span\";\n\n return (\n <Comp\n ref={ref}\n data-testid=\"badge\"\n className={cn(\n // Base styles\n \"typography-caption-semibold inline-flex h-5 items-center gap-2 rounded-full px-2\",\n // Variant styles\n badgeVariants.variant[variant],\n // Manual CSS overrides\n className,\n )}\n {...props}\n >\n {leftIcon && (\n <span className=\"flex\" aria-hidden=\"true\">\n {leftIcon}\n </span>\n )}\n {leftDot && (\n <span\n className={cn(\"size-1 shrink-0 rounded-full\", badgeVariants.dotColor[variant])}\n aria-hidden=\"true\"\n />\n )}\n <Slottable>{children}</Slottable>\n {rightIcon && (\n <span className=\"flex\" aria-hidden=\"true\">\n {rightIcon}\n </span>\n )}\n </Comp>\n );\n },\n);\n\nBadge.displayName = \"Badge\";\n"],"names":["React","Slot","jsxs","cn","jsx","Slottable"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAIA,MAAM,gBAAgB;AAAA,EACpB,SAAS;AAAA,IACP,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,WAAW;AAAA,EAAA;AAAA,EAEb,UAAU;AAAA,IACR,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,WAAW;AAAA,EAAA;AAEf;AA6BO,MAAM,QAAQA,iBAAM;AAAA,EACzB,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,OAAO,UAAUC,UAAAA,OAAO;AAE9B,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,eAAY;AAAA,QACZ,WAAWC,GAAAA;AAAAA;AAAAA,UAET;AAAA;AAAA,UAEA,cAAc,QAAQ,OAAO;AAAA;AAAA,UAE7B;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,2CACE,QAAA,EAAK,WAAU,QAAO,eAAY,QAChC,UAAA,UACH;AAAA,UAED,WACCC,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAWD,GAAAA,GAAG,gCAAgC,cAAc,SAAS,OAAO,CAAC;AAAA,cAC7E,eAAY;AAAA,YAAA;AAAA,UAAA;AAAA,UAGhBC,+BAACC,UAAAA,aAAW,UAAS;AAAA,UACpB,aACCD,2BAAAA,IAAC,QAAA,EAAK,WAAU,QAAO,eAAY,QAChC,UAAA,UAAA,CACH;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,MAAM,cAAc;;"}
1
+ {"version":3,"file":"Badge.cjs","sources":["../../../../src/components/Badge/Badge.tsx"],"sourcesContent":["import { Slot, Slottable } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nconst badgeVariants = {\n variant: {\n default: \"bg-neutral-100 text-neutral-400\",\n dark: \"bg-background-800 text-body-300 dark:text-body-white-solid-constant\",\n success: \"bg-neutral-100 text-neutral-400\",\n warning: \"bg-neutral-100 text-neutral-400\",\n error: \"bg-neutral-100 text-neutral-400\",\n special: \"bg-neutral-100 text-neutral-400\",\n info: \"bg-neutral-100 text-neutral-400\",\n online: \"bg-background-200 text-brand-green-500\",\n brand: \"bg-brand-green-500 text-body-black-solid-constant\",\n pink: \"bg-brand-pink-500 text-body-black-solid-constant\",\n brandLight: \"bg-brand-green-50 text-body-black-solid-constant\",\n pinkLight: \"bg-brand-pink-50 text-body-black-solid-constant\",\n },\n dotColor: {\n default: \"bg-body-black-solid-constant\",\n dark: \"bg-body-300 dark:bg-body-white-solid-constant\",\n success: \"bg-success-500\",\n warning: \"bg-warning-500\",\n error: \"bg-error-500\",\n special: \"bg-special-500\",\n info: \"bg-info-500\",\n online: \"bg-brand-green-500\",\n brand: \"bg-body-black-solid-constant\",\n pink: \"bg-body-black-solid-constant\",\n brandLight: \"bg-body-black-solid-constant\",\n pinkLight: \"bg-body-black-solid-constant\",\n },\n} as const;\n\n/** Visual style variant of the badge. */\nexport type BadgeVariant =\n | \"default\"\n | \"dark\"\n | \"success\"\n | \"warning\"\n | \"error\"\n | \"special\"\n | \"info\"\n | \"online\"\n | \"brand\"\n | \"pink\"\n | \"brandLight\"\n | \"pinkLight\";\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Visual style variant of the badge. @default \"default\" */\n variant?: BadgeVariant;\n /** Whether to show a coloured status dot at the leading edge. @default true */\n leftDot?: boolean;\n /** Icon element displayed before the label. */\n leftIcon?: React.ReactNode;\n /** Icon element displayed after the label. */\n rightIcon?: React.ReactNode;\n /** Merge props onto a child element instead of rendering a `<span>`. @default false */\n asChild?: boolean;\n}\n\n/**\n * A small inline label for status, category, or metadata information.\n *\n * @example\n * ```tsx\n * <Badge variant=\"success\">Active</Badge>\n * ```\n */\nexport const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n (\n {\n className,\n variant = \"default\",\n leftDot = true,\n leftIcon,\n rightIcon,\n asChild = false,\n children,\n ...props\n },\n ref,\n ) => {\n const Comp = asChild ? Slot : \"span\";\n\n return (\n <Comp\n ref={ref}\n data-testid=\"badge\"\n className={cn(\n // Base styles\n \"typography-caption-semibold inline-flex h-5 items-center gap-2 rounded-full px-2\",\n // Variant styles\n badgeVariants.variant[variant],\n // Manual CSS overrides\n className,\n )}\n {...props}\n >\n {leftIcon && (\n <span className=\"flex\" aria-hidden=\"true\">\n {leftIcon}\n </span>\n )}\n {leftDot && (\n <span\n className={cn(\"size-1 shrink-0 rounded-full\", badgeVariants.dotColor[variant])}\n aria-hidden=\"true\"\n />\n )}\n <Slottable>{children}</Slottable>\n {rightIcon && (\n <span className=\"flex\" aria-hidden=\"true\">\n {rightIcon}\n </span>\n )}\n </Comp>\n );\n },\n);\n\nBadge.displayName = \"Badge\";\n"],"names":["React","Slot","jsxs","cn","jsx","Slottable"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAIA,MAAM,gBAAgB;AAAA,EACpB,SAAS;AAAA,IACP,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,WAAW;AAAA,EAAA;AAAA,EAEb,UAAU;AAAA,IACR,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,WAAW;AAAA,EAAA;AAEf;AAsCO,MAAM,QAAQA,iBAAM;AAAA,EACzB,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,OAAO,UAAUC,UAAAA,OAAO;AAE9B,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,eAAY;AAAA,QACZ,WAAWC,GAAAA;AAAAA;AAAAA,UAET;AAAA;AAAA,UAEA,cAAc,QAAQ,OAAO;AAAA;AAAA,UAE7B;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,2CACE,QAAA,EAAK,WAAU,QAAO,eAAY,QAChC,UAAA,UACH;AAAA,UAED,WACCC,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAWD,GAAAA,GAAG,gCAAgC,cAAc,SAAS,OAAO,CAAC;AAAA,cAC7E,eAAY;AAAA,YAAA;AAAA,UAAA;AAAA,UAGhBC,+BAACC,UAAAA,aAAW,UAAS;AAAA,UACpB,aACCD,2BAAAA,IAAC,QAAA,EAAK,WAAU,QAAO,eAAY,QAChC,UAAA,UAAA,CACH;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,MAAM,cAAc;;"}
@@ -36,15 +36,15 @@ const ICON_SIZE_CLASS = {
36
36
  "24": "size-3.5"
37
37
  };
38
38
  const VARIANT_CLASSES = {
39
- primary: "bg-neutral-400 text-body-300 hover:bg-brand-green-500 hover:text-body-black-solid-constant",
40
- secondary: "border-body-100 border border-1 border-body-100 bg-transparent text-body-100 hover:bg-brand-green-50",
41
- tertiary: "bg-transparent text-body-100 hover:bg-brand-green-50",
42
- link: "bg-transparent text-body-100 underline decoration-solid hover:bg-brand-green-50",
43
- brand: "bg-brand-green-500 text-body-black-solid-constant hover:bg-brand-pink-500",
44
- destructive: "bg-error-500 text-body-white-solid-constant hover:bg-background-solid dark:hover:bg-background-white-solid-constant dark:hover:text-error-500",
45
- white: "bg-background-white-solid-constant text-body-black-solid-constant hover:bg-brand-green-500",
46
- tertiaryDestructive: "bg-transparent text-error-500 hover:bg-error-50",
47
- text: "bg-transparent text-body-100 hover:underline"
39
+ primary: "bg-neutral-400 text-body-300 hover:bg-brand-green-500 hover:text-body-black-solid-constant active:bg-brand-green-500 active:text-body-black-solid-constant",
40
+ secondary: "border-body-100 border border-1 border-body-100 bg-transparent text-body-100 hover:bg-brand-green-50 active:bg-brand-green-50",
41
+ tertiary: "bg-transparent text-body-100 hover:bg-brand-green-50 active:bg-brand-green-50",
42
+ link: "bg-transparent text-body-100 underline decoration-solid hover:bg-brand-green-50 active:bg-brand-green-50",
43
+ brand: "bg-brand-green-500 text-body-black-solid-constant hover:bg-brand-pink-500 active:bg-brand-pink-500",
44
+ destructive: "bg-error-500 text-body-white-solid-constant hover:bg-background-solid dark:hover:bg-background-white-solid-constant dark:hover:text-error-500 active:bg-background-solid dark:active:bg-background-white-solid-constant dark:active:text-error-500",
45
+ white: "bg-background-white-solid-constant text-body-black-solid-constant hover:bg-brand-green-500 active:bg-brand-green-500",
46
+ tertiaryDestructive: "bg-transparent text-error-500 hover:bg-error-50 active:bg-error-50",
47
+ text: "bg-transparent text-body-100 hover:underline active:underline"
48
48
  };
49
49
  function getTextContent(node) {
50
50
  if (typeof node === "string") return node;
@@ -1 +1 @@
1
- {"version":3,"file":"Button.cjs","sources":["../../../../src/components/Button/Button.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { SpinnerIcon } from \"../Icons/SpinnerIcon\";\n\nexport type ButtonVariant =\n | \"primary\"\n | \"secondary\"\n | \"tertiary\"\n | \"link\"\n | \"brand\"\n | \"destructive\"\n | \"white\"\n | \"tertiaryDestructive\"\n | \"text\";\n\nexport type ButtonSize = \"48\" | \"40\" | \"32\" | \"24\";\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Visual style variant of the button */\n variant?: ButtonVariant;\n /** Size of the button in pixels */\n size?: ButtonSize;\n /** Left icon element */\n leftIcon?: React.ReactNode;\n /** Right icon element */\n rightIcon?: React.ReactNode;\n /** Show loading spinner */\n loading?: boolean;\n /** Render as a different element using Radix Slot */\n asChild?: boolean;\n /** Old price shown with strikethrough before the current price */\n discount?: string;\n /** Current price shown inside the button after the label/icons */\n price?: string;\n}\n\nconst SIZE_CLASSES: Record<ButtonSize, string> = {\n \"48\": \"h-12 px-4 py-3 typography-button-large\",\n \"40\": \"h-10 px-4 py-2 typography-button-small\",\n \"32\": \"h-8 px-3 py-2 typography-body-2-semibold\",\n \"24\": \"h-6 px-0 py-1 typography-body-2-semibold\",\n};\n\nconst ICON_SIZE_CLASS: Record<ButtonSize, string> = {\n \"48\": \"size-5\",\n \"40\": \"size-5\",\n \"32\": \"size-4\",\n \"24\": \"size-3.5\",\n};\n\nconst VARIANT_CLASSES: Record<ButtonVariant, string> = {\n primary:\n \"bg-neutral-400 text-body-300 hover:bg-brand-green-500 hover:text-body-black-solid-constant\",\n secondary:\n \"border-body-100 border border-1 border-body-100 bg-transparent text-body-100 hover:bg-brand-green-50\",\n tertiary: \"bg-transparent text-body-100 hover:bg-brand-green-50\",\n link: \"bg-transparent text-body-100 underline decoration-solid hover:bg-brand-green-50\",\n brand: \"bg-brand-green-500 text-body-black-solid-constant hover:bg-brand-pink-500\",\n destructive:\n \"bg-error-500 text-body-white-solid-constant hover:bg-background-solid dark:hover:bg-background-white-solid-constant dark:hover:text-error-500\",\n white:\n \"bg-background-white-solid-constant text-body-black-solid-constant hover:bg-brand-green-500\",\n tertiaryDestructive: \"bg-transparent text-error-500 hover:bg-error-50\",\n text: \"bg-transparent text-body-100 hover:underline\",\n};\n\n/** Recursively extract text content from React nodes for accessible labels */\nfunction getTextContent(node: React.ReactNode): string | undefined {\n if (typeof node === \"string\") return node;\n if (typeof node === \"number\") return String(node);\n if (React.isValidElement(node)) {\n return getTextContent((node.props as { children?: React.ReactNode }).children);\n }\n if (Array.isArray(node)) {\n const text = node.map(getTextContent).filter(Boolean).join(\"\");\n return text || undefined;\n }\n return undefined;\n}\n\nconst LoadingSpinner = ({ size }: { size: ButtonSize }) => {\n return (\n <span className=\"animate-spin\" aria-hidden=\"true\">\n <SpinnerIcon className={ICON_SIZE_CLASS[size]}>\n <title>Loading</title>\n </SpinnerIcon>\n </span>\n );\n};\n\nfunction renderContent({\n loading,\n asChild,\n children,\n size,\n leftIcon,\n rightIcon,\n iconSizeClass,\n discount,\n price,\n}: {\n loading: boolean;\n asChild: boolean;\n children: React.ReactNode;\n size: ButtonSize;\n leftIcon: React.ReactNode;\n rightIcon: React.ReactNode;\n iconSizeClass: string;\n discount?: string;\n price?: string;\n}) {\n if (loading) {\n // When asChild, clone the child element with spinner content instead of\n // wrapping in sr-only span (which would nest interactive elements)\n if (asChild && React.isValidElement(children)) {\n return React.cloneElement(\n children as React.ReactElement<{ children?: React.ReactNode }>,\n undefined,\n <LoadingSpinner size={size} />,\n );\n }\n return (\n <>\n <LoadingSpinner size={size} />\n <span className=\"sr-only\">{children}</span>\n </>\n );\n }\n\n if (asChild) return children;\n\n return (\n <>\n {leftIcon && (\n <span\n className={cn(\"flex shrink-0 items-center justify-center\", iconSizeClass)}\n aria-hidden=\"true\"\n >\n {leftIcon}\n </span>\n )}\n {children}\n {rightIcon && (\n <span\n className={cn(\"flex shrink-0 items-center justify-center\", iconSizeClass)}\n aria-hidden=\"true\"\n >\n {rightIcon}\n </span>\n )}\n {discount != null && (\n <span className=\"typography-body-1-regular line-through\" aria-hidden=\"true\">\n {discount}\n </span>\n )}\n {price != null && <span aria-hidden=\"true\">{price}</span>}\n </>\n );\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant = \"primary\",\n size = \"48\",\n leftIcon,\n rightIcon,\n loading = false,\n asChild = false,\n disabled,\n children,\n discount,\n price,\n ...props\n },\n ref,\n ) => {\n const Comp = asChild ? Slot : \"button\";\n const isDisabled = disabled || loading;\n const iconSizeClass = ICON_SIZE_CLASS[size];\n\n const buttonSpecificProps = !asChild\n ? { type: \"button\" as const, \"data-testid\": \"button\", disabled: isDisabled }\n : isDisabled\n ? { \"aria-disabled\": true }\n : {};\n\n // When asChild + loading, extract text from children for aria-label since we\n // can't wrap element children in an sr-only span (creates invalid nested markup)\n const loadingLabelProps = loading && asChild ? { \"aria-label\": getTextContent(children) } : {};\n\n const content = renderContent({\n loading,\n asChild,\n children,\n size,\n leftIcon,\n rightIcon,\n iconSizeClass,\n discount,\n price,\n });\n\n return (\n <Comp\n ref={ref}\n {...buttonSpecificProps}\n aria-busy={loading}\n {...loadingLabelProps}\n className={cn(\n // Base styles\n \"inline-flex cursor-pointer items-center justify-center gap-2 rounded-full transition-colors\",\n // Focus ring\n \"focus-visible:shadow-focus-ring focus-visible:outline-none\",\n // Disabled state\n \"disabled:pointer-events-none disabled:opacity-50\",\n \"aria-disabled:pointer-events-none aria-disabled:opacity-50\",\n // Size styles\n SIZE_CLASSES[size],\n // Variant styles\n VARIANT_CLASSES[variant],\n // Manual CSS overrides\n className,\n )}\n {...props}\n >\n {content}\n </Comp>\n );\n },\n);\n\nButton.displayName = \"Button\";\n"],"names":["React","jsx","SpinnerIcon","jsxs","Fragment","cn","Slot"],"mappings":"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"}
1
+ {"version":3,"file":"Button.cjs","sources":["../../../../src/components/Button/Button.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { SpinnerIcon } from \"../Icons/SpinnerIcon\";\n\n/** Visual style variant of the button. */\nexport type ButtonVariant =\n | \"primary\"\n | \"secondary\"\n | \"tertiary\"\n | \"link\"\n | \"brand\"\n | \"destructive\"\n | \"white\"\n | \"tertiaryDestructive\"\n | \"text\";\n\n/** Button height in pixels. */\nexport type ButtonSize = \"48\" | \"40\" | \"32\" | \"24\";\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Visual style variant of the button. @default \"primary\" */\n variant?: ButtonVariant;\n /** Height of the button in pixels. @default \"48\" */\n size?: ButtonSize;\n /** Icon element displayed before the label. */\n leftIcon?: React.ReactNode;\n /** Icon element displayed after the label. */\n rightIcon?: React.ReactNode;\n /** When `true`, replaces the label with a spinner and disables interaction. @default false */\n loading?: boolean;\n /** Merge props onto a child element instead of rendering a `<button>`. @default false */\n asChild?: boolean;\n /** Old price shown with a strikethrough before the current price. */\n discount?: string;\n /** Current price shown inside the button after the label and icons. */\n price?: string;\n}\n\nconst SIZE_CLASSES: Record<ButtonSize, string> = {\n \"48\": \"h-12 px-4 py-3 typography-button-large\",\n \"40\": \"h-10 px-4 py-2 typography-button-small\",\n \"32\": \"h-8 px-3 py-2 typography-body-2-semibold\",\n \"24\": \"h-6 px-0 py-1 typography-body-2-semibold\",\n};\n\nconst ICON_SIZE_CLASS: Record<ButtonSize, string> = {\n \"48\": \"size-5\",\n \"40\": \"size-5\",\n \"32\": \"size-4\",\n \"24\": \"size-3.5\",\n};\n\nconst VARIANT_CLASSES: Record<ButtonVariant, string> = {\n primary:\n \"bg-neutral-400 text-body-300 hover:bg-brand-green-500 hover:text-body-black-solid-constant active:bg-brand-green-500 active:text-body-black-solid-constant\",\n secondary:\n \"border-body-100 border border-1 border-body-100 bg-transparent text-body-100 hover:bg-brand-green-50 active:bg-brand-green-50\",\n tertiary: \"bg-transparent text-body-100 hover:bg-brand-green-50 active:bg-brand-green-50\",\n link: \"bg-transparent text-body-100 underline decoration-solid hover:bg-brand-green-50 active:bg-brand-green-50\",\n brand:\n \"bg-brand-green-500 text-body-black-solid-constant hover:bg-brand-pink-500 active:bg-brand-pink-500\",\n destructive:\n \"bg-error-500 text-body-white-solid-constant hover:bg-background-solid dark:hover:bg-background-white-solid-constant dark:hover:text-error-500 active:bg-background-solid dark:active:bg-background-white-solid-constant dark:active:text-error-500\",\n white:\n \"bg-background-white-solid-constant text-body-black-solid-constant hover:bg-brand-green-500 active:bg-brand-green-500\",\n tertiaryDestructive: \"bg-transparent text-error-500 hover:bg-error-50 active:bg-error-50\",\n text: \"bg-transparent text-body-100 hover:underline active:underline\",\n};\n\n/** Recursively extract text content from React nodes for accessible labels */\nfunction getTextContent(node: React.ReactNode): string | undefined {\n if (typeof node === \"string\") return node;\n if (typeof node === \"number\") return String(node);\n if (React.isValidElement(node)) {\n return getTextContent((node.props as { children?: React.ReactNode }).children);\n }\n if (Array.isArray(node)) {\n const text = node.map(getTextContent).filter(Boolean).join(\"\");\n return text || undefined;\n }\n return undefined;\n}\n\nconst LoadingSpinner = ({ size }: { size: ButtonSize }) => {\n return (\n <span className=\"animate-spin\" aria-hidden=\"true\">\n <SpinnerIcon className={ICON_SIZE_CLASS[size]}>\n <title>Loading</title>\n </SpinnerIcon>\n </span>\n );\n};\n\nfunction renderContent({\n loading,\n asChild,\n children,\n size,\n leftIcon,\n rightIcon,\n iconSizeClass,\n discount,\n price,\n}: {\n loading: boolean;\n asChild: boolean;\n children: React.ReactNode;\n size: ButtonSize;\n leftIcon: React.ReactNode;\n rightIcon: React.ReactNode;\n iconSizeClass: string;\n discount?: string;\n price?: string;\n}) {\n if (loading) {\n // When asChild, clone the child element with spinner content instead of\n // wrapping in sr-only span (which would nest interactive elements)\n if (asChild && React.isValidElement(children)) {\n return React.cloneElement(\n children as React.ReactElement<{ children?: React.ReactNode }>,\n undefined,\n <LoadingSpinner size={size} />,\n );\n }\n return (\n <>\n <LoadingSpinner size={size} />\n <span className=\"sr-only\">{children}</span>\n </>\n );\n }\n\n if (asChild) return children;\n\n return (\n <>\n {leftIcon && (\n <span\n className={cn(\"flex shrink-0 items-center justify-center\", iconSizeClass)}\n aria-hidden=\"true\"\n >\n {leftIcon}\n </span>\n )}\n {children}\n {rightIcon && (\n <span\n className={cn(\"flex shrink-0 items-center justify-center\", iconSizeClass)}\n aria-hidden=\"true\"\n >\n {rightIcon}\n </span>\n )}\n {discount != null && (\n <span className=\"typography-body-1-regular line-through\" aria-hidden=\"true\">\n {discount}\n </span>\n )}\n {price != null && <span aria-hidden=\"true\">{price}</span>}\n </>\n );\n}\n\n/**\n * A versatile button component with multiple visual variants, sizes, icon\n * slots, loading state, and optional pricing display.\n *\n * @example\n * ```tsx\n * <Button variant=\"brand\" size=\"40\" leftIcon={<StarIcon />}>\n * Subscribe\n * </Button>\n * ```\n */\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant = \"primary\",\n size = \"48\",\n leftIcon,\n rightIcon,\n loading = false,\n asChild = false,\n disabled,\n children,\n discount,\n price,\n ...props\n },\n ref,\n ) => {\n const Comp = asChild ? Slot : \"button\";\n const isDisabled = disabled || loading;\n const iconSizeClass = ICON_SIZE_CLASS[size];\n\n const buttonSpecificProps = !asChild\n ? { type: \"button\" as const, \"data-testid\": \"button\", disabled: isDisabled }\n : isDisabled\n ? { \"aria-disabled\": true }\n : {};\n\n // When asChild + loading, extract text from children for aria-label since we\n // can't wrap element children in an sr-only span (creates invalid nested markup)\n const loadingLabelProps = loading && asChild ? { \"aria-label\": getTextContent(children) } : {};\n\n const content = renderContent({\n loading,\n asChild,\n children,\n size,\n leftIcon,\n rightIcon,\n iconSizeClass,\n discount,\n price,\n });\n\n return (\n <Comp\n ref={ref}\n {...buttonSpecificProps}\n aria-busy={loading}\n {...loadingLabelProps}\n className={cn(\n // Base styles\n \"inline-flex cursor-pointer items-center justify-center gap-2 rounded-full transition-colors\",\n // Focus ring\n \"focus-visible:shadow-focus-ring focus-visible:outline-none\",\n // Disabled state\n \"disabled:pointer-events-none disabled:opacity-50\",\n \"aria-disabled:pointer-events-none aria-disabled:opacity-50\",\n // Size styles\n SIZE_CLASSES[size],\n // Variant styles\n VARIANT_CLASSES[variant],\n // Manual CSS overrides\n className,\n )}\n {...props}\n >\n {content}\n </Comp>\n );\n },\n);\n\nButton.displayName = \"Button\";\n"],"names":["React","jsx","SpinnerIcon","jsxs","Fragment","cn","Slot"],"mappings":"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"}
@@ -30,12 +30,10 @@ const Checkbox = React__namespace.forwardRef(
30
30
  const id = React__namespace.useId();
31
31
  const helperTextId = helperText ? `${id}-helper` : void 0;
32
32
  const hasLabel = Boolean(label || helperText);
33
- if (process.env.NODE_ENV !== "production") {
34
- if (!label && !props["aria-label"] && !props["aria-labelledby"]) {
35
- console.warn(
36
- "Checkbox: No accessible name provided. Add a `label`, `aria-label`, or `aria-labelledby` prop so screen readers can announce this checkbox."
37
- );
38
- }
33
+ if (process.env.NODE_ENV !== "production" && !label && !props["aria-label"] && !props["aria-labelledby"]) {
34
+ console.warn(
35
+ "Checkbox: No accessible name provided. Add a `label`, `aria-label`, or `aria-labelledby` prop so screen readers can announce this checkbox."
36
+ );
39
37
  }
40
38
  const inputRef = React__namespace.useRef(null);
41
39
  React__namespace.useImperativeHandle(ref, () => inputRef.current);
@@ -90,8 +88,9 @@ const Checkbox = React__namespace.forwardRef(
90
88
  "data-[state=checked]:border-body-100 data-[state=checked]:bg-body-100 data-[state=checked]:text-body-300",
91
89
  // Indeterminate state
92
90
  "data-[state=indeterminate]:border-body-100 data-[state=indeterminate]:bg-body-100 data-[state=indeterminate]:text-body-300",
93
- // Hover state
91
+ // Hover & active state
94
92
  "hover:ring-2 hover:ring-brand-green-500 group-hover:ring-2 group-hover:ring-brand-green-500",
93
+ "not-disabled:active:ring-2 not-disabled:active:ring-brand-green-500",
95
94
  // Focus state
96
95
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-purple-500 focus-visible:ring-offset-2 focus-visible:ring-offset-background-inverse-solid",
97
96
  // Disabled state
@@ -1 +1 @@
1
- {"version":3,"file":"Checkbox.cjs","sources":["../../../../src/components/Checkbox/Checkbox.tsx"],"sourcesContent":["import * as CheckboxPrimitive from \"@radix-ui/react-checkbox\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { CheckIcon } from \"../Icons/CheckIcon\";\nimport { MinusIcon } from \"../Icons/MinusIcon\";\n\nexport type CheckboxSize = \"default\" | \"small\";\n\nexport interface CheckboxProps\n extends Omit<React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>, \"asChild\"> {\n /** Size variant for label and helper text */\n size?: CheckboxSize;\n /** Label text displayed next to the checkbox */\n label?: string;\n /** Helper text displayed below the label */\n helperText?: string;\n}\n\n/**\n * The ref type is intentionally `HTMLInputElement` (not `HTMLButtonElement`) for form library\n * compatibility. Libraries like react-hook-form call `register()` which expects an `HTMLInputElement`\n * ref. A hidden `<input>` is synced to the Radix checkbox state via `useImperativeHandle`.\n */\nexport const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(\n ({ className, size = \"default\", label, helperText, disabled, name, ...props }, ref) => {\n const id = React.useId();\n const helperTextId = helperText ? `${id}-helper` : undefined;\n const hasLabel = Boolean(label || helperText);\n\n if (process.env.NODE_ENV !== \"production\") {\n if (!label && !props[\"aria-label\"] && !props[\"aria-labelledby\"]) {\n console.warn(\n \"Checkbox: No accessible name provided. Add a `label`, `aria-label`, or `aria-labelledby` prop so screen readers can announce this checkbox.\",\n );\n }\n }\n\n // Hidden input for form library compatibility (e.g. react-hook-form register)\n const inputRef = React.useRef<HTMLInputElement>(null);\n React.useImperativeHandle(ref, () => inputRef.current as HTMLInputElement);\n\n const handleCheckedChange = (value: boolean | \"indeterminate\") => {\n const checked = value === true;\n if (inputRef.current) {\n inputRef.current.checked = checked;\n inputRef.current.dispatchEvent(new Event(\"change\", { bubbles: true }));\n }\n props.onCheckedChange?.(value);\n };\n\n const checkboxElement = (\n <span\n className={cn(\n \"relative inline-flex size-5 shrink-0\",\n // Alignment when used with label\n label && (helperText ? \"mt-1\" : \"mt-0.5\"),\n )}\n >\n <input\n ref={inputRef}\n type=\"checkbox\"\n name={name}\n disabled={disabled}\n aria-hidden\n tabIndex={-1}\n onChange={() => {}}\n className=\"pointer-events-none absolute size-px overflow-hidden opacity-0\"\n style={{ clip: \"rect(0,0,0,0)\" }}\n />\n <CheckboxPrimitive.Root\n id={id}\n disabled={disabled}\n aria-describedby={helperTextId}\n data-testid=\"checkbox\"\n {...props}\n onCheckedChange={handleCheckedChange}\n className={cn(\n // Base styles\n \"flex size-5 items-center justify-center rounded border-2\",\n \"transition-[border-color,background-color,color,box-shadow] duration-150\",\n // Default state\n \"border-body-100 bg-transparent text-transparent\",\n // Checked state\n \"data-[state=checked]:border-body-100 data-[state=checked]:bg-body-100 data-[state=checked]:text-body-300\",\n // Indeterminate state\n \"data-[state=indeterminate]:border-body-100 data-[state=indeterminate]:bg-body-100 data-[state=indeterminate]:text-body-300\",\n // Hover state\n \"hover:ring-2 hover:ring-brand-green-500 group-hover:ring-2 group-hover:ring-brand-green-500\",\n // Focus state\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-purple-500 focus-visible:ring-offset-2 focus-visible:ring-offset-background-inverse-solid\",\n // Disabled state\n \"disabled:cursor-not-allowed disabled:border-disabled-400 disabled:ring-0 disabled:group-hover:ring-0\",\n \"disabled:data-[state=checked]:border-disabled-400 disabled:data-[state=checked]:bg-disabled-400 disabled:data-[state=checked]:text-disabled-100\",\n !hasLabel && className,\n )}\n >\n <CheckboxPrimitive.Indicator\n forceMount\n className={cn(\n \"flex size-3 items-center justify-center text-body-300\",\n \"data-[state=unchecked]:invisible\",\n )}\n >\n {props.checked === \"indeterminate\" ? <MinusIcon /> : <CheckIcon />}\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n </span>\n );\n\n if (!hasLabel) {\n return checkboxElement;\n }\n\n return (\n <div\n className={cn(\n \"inline-flex flex-col gap-0.5\",\n disabled && \"is-disabled cursor-not-allowed\",\n className,\n )}\n >\n <div className=\"group inline-flex items-start gap-2\">\n {checkboxElement}\n {label && (\n <label\n htmlFor={id}\n className={cn(\n \"cursor-pointer select-none text-body-100\",\n \"group-has-disabled:cursor-not-allowed group-has-disabled:text-disabled-100\",\n size === \"small\" ? \"typography-body-2-semibold\" : \"typography-body-1-semibold\",\n )}\n >\n {label}\n </label>\n )}\n </div>\n {helperText && (\n <span\n id={helperTextId}\n className={cn(\n \"ml-7 text-body-200\",\n \"in-[.is-disabled]:cursor-not-allowed in-[.is-disabled]:text-disabled-100\",\n size === \"small\" ? \"typography-caption-regular\" : \"typography-body-2-regular\",\n )}\n >\n {helperText}\n </span>\n )}\n </div>\n );\n },\n);\n\nCheckbox.displayName = \"Checkbox\";\n"],"names":["React","jsxs","cn","jsx","CheckboxPrimitive","MinusIcon","CheckIcon"],"mappings":"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"}
1
+ {"version":3,"file":"Checkbox.cjs","sources":["../../../../src/components/Checkbox/Checkbox.tsx"],"sourcesContent":["import * as CheckboxPrimitive from \"@radix-ui/react-checkbox\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { CheckIcon } from \"../Icons/CheckIcon\";\nimport { MinusIcon } from \"../Icons/MinusIcon\";\n\n/** Size variant controlling label and helper text typography. */\nexport type CheckboxSize = \"default\" | \"small\";\n\nexport interface CheckboxProps\n extends Omit<React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>, \"asChild\"> {\n /** Size variant that controls label and helper text typography. @default \"default\" */\n size?: CheckboxSize;\n /** Label text displayed next to the checkbox. */\n label?: string;\n /** Descriptive text displayed below the label. */\n helperText?: string;\n}\n\n/**\n * A checkbox input with optional label and helper text. Supports checked,\n * unchecked, and indeterminate states.\n *\n * The ref type is intentionally `HTMLInputElement` (not `HTMLButtonElement`) for\n * form-library compatibility libraries like react-hook-form call `register()`\n * which expects an `HTMLInputElement` ref. A hidden `<input>` is synced to the\n * Radix checkbox state via `useImperativeHandle`.\n *\n * @example\n * ```tsx\n * <Checkbox label=\"Accept terms\" helperText=\"Required to continue\" />\n * ```\n */\nexport const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(\n ({ className, size = \"default\", label, helperText, disabled, name, ...props }, ref) => {\n const id = React.useId();\n const helperTextId = helperText ? `${id}-helper` : undefined;\n const hasLabel = Boolean(label || helperText);\n\n if (\n process.env.NODE_ENV !== \"production\" &&\n !label &&\n !props[\"aria-label\"] &&\n !props[\"aria-labelledby\"]\n ) {\n console.warn(\n \"Checkbox: No accessible name provided. Add a `label`, `aria-label`, or `aria-labelledby` prop so screen readers can announce this checkbox.\",\n );\n }\n\n // Hidden input for form library compatibility (e.g. react-hook-form register)\n const inputRef = React.useRef<HTMLInputElement>(null);\n React.useImperativeHandle(ref, () => inputRef.current as HTMLInputElement);\n\n const handleCheckedChange = (value: boolean | \"indeterminate\") => {\n const checked = value === true;\n if (inputRef.current) {\n inputRef.current.checked = checked;\n inputRef.current.dispatchEvent(new Event(\"change\", { bubbles: true }));\n }\n props.onCheckedChange?.(value);\n };\n\n const checkboxElement = (\n <span\n className={cn(\n \"relative inline-flex size-5 shrink-0\",\n // Alignment when used with label\n label && (helperText ? \"mt-1\" : \"mt-0.5\"),\n )}\n >\n <input\n ref={inputRef}\n type=\"checkbox\"\n name={name}\n disabled={disabled}\n aria-hidden\n tabIndex={-1}\n onChange={() => {}}\n className=\"pointer-events-none absolute size-px overflow-hidden opacity-0\"\n style={{ clip: \"rect(0,0,0,0)\" }}\n />\n <CheckboxPrimitive.Root\n id={id}\n disabled={disabled}\n aria-describedby={helperTextId}\n data-testid=\"checkbox\"\n {...props}\n onCheckedChange={handleCheckedChange}\n className={cn(\n // Base styles\n \"flex size-5 items-center justify-center rounded border-2\",\n \"transition-[border-color,background-color,color,box-shadow] duration-150\",\n // Default state\n \"border-body-100 bg-transparent text-transparent\",\n // Checked state\n \"data-[state=checked]:border-body-100 data-[state=checked]:bg-body-100 data-[state=checked]:text-body-300\",\n // Indeterminate state\n \"data-[state=indeterminate]:border-body-100 data-[state=indeterminate]:bg-body-100 data-[state=indeterminate]:text-body-300\",\n // Hover & active state\n \"hover:ring-2 hover:ring-brand-green-500 group-hover:ring-2 group-hover:ring-brand-green-500\",\n \"not-disabled:active:ring-2 not-disabled:active:ring-brand-green-500\",\n // Focus state\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-purple-500 focus-visible:ring-offset-2 focus-visible:ring-offset-background-inverse-solid\",\n // Disabled state\n \"disabled:cursor-not-allowed disabled:border-disabled-400 disabled:ring-0 disabled:group-hover:ring-0\",\n \"disabled:data-[state=checked]:border-disabled-400 disabled:data-[state=checked]:bg-disabled-400 disabled:data-[state=checked]:text-disabled-100\",\n !hasLabel && className,\n )}\n >\n <CheckboxPrimitive.Indicator\n forceMount\n className={cn(\n \"flex size-3 items-center justify-center text-body-300\",\n \"data-[state=unchecked]:invisible\",\n )}\n >\n {props.checked === \"indeterminate\" ? <MinusIcon /> : <CheckIcon />}\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n </span>\n );\n\n if (!hasLabel) {\n return checkboxElement;\n }\n\n return (\n <div\n className={cn(\n \"inline-flex flex-col gap-0.5\",\n disabled && \"is-disabled cursor-not-allowed\",\n className,\n )}\n >\n <div className=\"group inline-flex items-start gap-2\">\n {checkboxElement}\n {label && (\n <label\n htmlFor={id}\n className={cn(\n \"cursor-pointer select-none text-body-100\",\n \"group-has-disabled:cursor-not-allowed group-has-disabled:text-disabled-100\",\n size === \"small\" ? \"typography-body-2-semibold\" : \"typography-body-1-semibold\",\n )}\n >\n {label}\n </label>\n )}\n </div>\n {helperText && (\n <span\n id={helperTextId}\n className={cn(\n \"ml-7 text-body-200\",\n \"in-[.is-disabled]:cursor-not-allowed in-[.is-disabled]:text-disabled-100\",\n size === \"small\" ? \"typography-caption-regular\" : \"typography-body-2-regular\",\n )}\n >\n {helperText}\n </span>\n )}\n </div>\n );\n },\n);\n\nCheckbox.displayName = \"Checkbox\";\n"],"names":["React","jsxs","cn","jsx","CheckboxPrimitive","MinusIcon","CheckIcon"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCO,MAAM,WAAWA,iBAAM;AAAA,EAC5B,CAAC,EAAE,WAAW,OAAO,WAAW,OAAO,YAAY,UAAU,MAAM,GAAG,MAAA,GAAS,QAAQ;AACrF,UAAM,KAAKA,iBAAM,MAAA;AACjB,UAAM,eAAe,aAAa,GAAG,EAAE,YAAY;AACnD,UAAM,WAAW,QAAQ,SAAS,UAAU;AAE5C,QACE,QAAQ,IAAI,aAAa,gBACzB,CAAC,SACD,CAAC,MAAM,YAAY,KACnB,CAAC,MAAM,iBAAiB,GACxB;AACA,cAAQ;AAAA,QACN;AAAA,MAAA;AAAA,IAEJ;AAGA,UAAM,WAAWA,iBAAM,OAAyB,IAAI;AACpDA,qBAAM,oBAAoB,KAAK,MAAM,SAAS,OAA2B;AAEzE,UAAM,sBAAsB,CAAC,UAAqC;AAChE,YAAM,UAAU,UAAU;AAC1B,UAAI,SAAS,SAAS;AACpB,iBAAS,QAAQ,UAAU;AAC3B,iBAAS,QAAQ,cAAc,IAAI,MAAM,UAAU,EAAE,SAAS,KAAA,CAAM,CAAC;AAAA,MACvE;AACA,YAAM,kBAAkB,KAAK;AAAA,IAC/B;AAEA,UAAM,kBACJC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAWC,GAAAA;AAAAA,UACT;AAAA;AAAA,UAEA,UAAU,aAAa,SAAS;AAAA,QAAA;AAAA,QAGlC,UAAA;AAAA,UAAAC,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,KAAK;AAAA,cACL,MAAK;AAAA,cACL;AAAA,cACA;AAAA,cACA,eAAW;AAAA,cACX,UAAU;AAAA,cACV,UAAU,MAAM;AAAA,cAAC;AAAA,cACjB,WAAU;AAAA,cACV,OAAO,EAAE,MAAM,gBAAA;AAAA,YAAgB;AAAA,UAAA;AAAA,UAEjCA,2BAAAA;AAAAA,YAACC,6BAAkB;AAAA,YAAlB;AAAA,cACC;AAAA,cACA;AAAA,cACA,oBAAkB;AAAA,cAClB,eAAY;AAAA,cACX,GAAG;AAAA,cACJ,iBAAiB;AAAA,cACjB,WAAWF,GAAAA;AAAAA;AAAAA,gBAET;AAAA,gBACA;AAAA;AAAA,gBAEA;AAAA;AAAA,gBAEA;AAAA;AAAA,gBAEA;AAAA;AAAA,gBAEA;AAAA,gBACA;AAAA;AAAA,gBAEA;AAAA;AAAA,gBAEA;AAAA,gBACA;AAAA,gBACA,CAAC,YAAY;AAAA,cAAA;AAAA,cAGf,UAAAC,2BAAAA;AAAAA,gBAACC,6BAAkB;AAAA,gBAAlB;AAAA,kBACC,YAAU;AAAA,kBACV,WAAWF,GAAAA;AAAAA,oBACT;AAAA,oBACA;AAAA,kBAAA;AAAA,kBAGD,gBAAM,YAAY,iDAAmBG,UAAAA,WAAA,EAAU,mCAAMC,UAAAA,WAAA,CAAA,CAAU;AAAA,gBAAA;AAAA,cAAA;AAAA,YAClE;AAAA,UAAA;AAAA,QACF;AAAA,MAAA;AAAA,IAAA;AAIJ,QAAI,CAAC,UAAU;AACb,aAAO;AAAA,IACT;AAEA,WACEL,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAWC,GAAAA;AAAAA,UACT;AAAA,UACA,YAAY;AAAA,UACZ;AAAA,QAAA;AAAA,QAGF,UAAA;AAAA,UAAAD,2BAAAA,KAAC,OAAA,EAAI,WAAU,uCACZ,UAAA;AAAA,YAAA;AAAA,YACA,SACCE,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBACC,SAAS;AAAA,gBACT,WAAWD,GAAAA;AAAAA,kBACT;AAAA,kBACA;AAAA,kBACA,SAAS,UAAU,+BAA+B;AAAA,gBAAA;AAAA,gBAGnD,UAAA;AAAA,cAAA;AAAA,YAAA;AAAA,UACH,GAEJ;AAAA,UACC,cACCC,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,IAAI;AAAA,cACJ,WAAWD,GAAAA;AAAAA,gBACT;AAAA,gBACA;AAAA,gBACA,SAAS,UAAU,+BAA+B;AAAA,cAAA;AAAA,cAGnD,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,SAAS,cAAc;;"}
@@ -58,8 +58,8 @@ const Chip = React__namespace.forwardRef(
58
58
  !isDark && selected && "bg-brand-green-50 text-neutral-400",
59
59
  !isDark && !selected && "bg-neutral-100 text-neutral-400",
60
60
  // Hover
61
- isInteractive && !disabled && !isDark && selected && "hover:bg-brand-green-500 hover:text-body-black-solid-constant",
62
- isInteractive && !disabled && !isDark && !selected && "hover:bg-hover-400",
61
+ isInteractive && !disabled && !isDark && selected && "hover:bg-brand-green-500 hover:text-body-black-solid-constant active:bg-brand-green-500 active:text-body-black-solid-constant",
62
+ isInteractive && !disabled && !isDark && !selected && "hover:bg-hover-400 active:bg-hover-400",
63
63
  // Focus
64
64
  "focus-visible:shadow-focus-ring focus-visible:outline-none",
65
65
  // Disabled
@@ -1 +1 @@
1
- {"version":3,"file":"Chip.cjs","sources":["../../../../src/components/Chip/Chip.tsx"],"sourcesContent":["import { Slot, Slottable } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport type ChipVariant = \"rounded\" | \"square\" | \"dark\";\nexport type ChipSize = \"32\" | \"40\";\n\nexport interface ChipProps extends React.HTMLAttributes<HTMLElement> {\n /** Visual shape variant of the chip */\n variant?: ChipVariant;\n /** Size of the chip */\n size?: ChipSize;\n /** Whether the chip is in a selected state */\n selected?: boolean;\n /** Whether the chip is disabled */\n disabled?: boolean;\n /** Show left status dot */\n leftDot?: boolean;\n /** Left icon element */\n leftIcon?: React.ReactNode;\n /** Right icon element */\n rightIcon?: React.ReactNode;\n /** Notification badge content (e.g., \"99+\"). Passed as a string for i18n support. */\n notificationLabel?: string;\n /** Click handler — when provided, the chip renders as a `<button>` for accessibility */\n onClick?: React.MouseEventHandler<HTMLElement>;\n /** Render as a different element using Radix Slot */\n asChild?: boolean;\n}\n\nexport const Chip = React.forwardRef<HTMLButtonElement, ChipProps>(\n (\n {\n className,\n variant = \"rounded\",\n size = \"32\",\n selected = false,\n disabled = false,\n leftDot = false,\n leftIcon,\n rightIcon,\n notificationLabel,\n onClick,\n asChild = false,\n children,\n ...props\n },\n ref,\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Variant-heavy UI component\n ) => {\n const isInteractive = !!onClick && !asChild;\n const Comp = asChild ? Slot : isInteractive ? \"button\" : \"span\";\n const isDark = variant === \"dark\";\n\n return (\n <Comp\n ref={ref}\n data-testid=\"chip\"\n className={cn(\n \"typography-caption-semibold relative inline-flex items-center gap-2 px-3 motion-safe:transition-colors motion-safe:duration-150\",\n // Shape\n variant === \"square\" ? \"rounded-lg\" : \"rounded-full\",\n // Size\n size === \"32\" && \"h-8 py-1\",\n size === \"40\" && \"h-10 py-2.5\",\n // Variant colors\n isDark && \"bg-background-800 text-body-white-solid-constant\",\n !isDark && selected && \"bg-brand-green-50 text-neutral-400\",\n !isDark && !selected && \"bg-neutral-100 text-neutral-400\",\n // Hover\n isInteractive &&\n !disabled &&\n !isDark &&\n selected &&\n \"hover:bg-brand-green-500 hover:text-body-black-solid-constant\",\n isInteractive && !disabled && !isDark && !selected && \"hover:bg-hover-400\",\n // Focus\n \"focus-visible:shadow-focus-ring focus-visible:outline-none\",\n // Disabled\n disabled && isDark && \"pointer-events-none opacity-50\",\n disabled && !isDark && \"pointer-events-none text-neutral-300\",\n className,\n )}\n {...(isInteractive && {\n type: \"button\" as const,\n disabled,\n \"aria-pressed\": selected,\n onClick,\n })}\n {...(!isInteractive && disabled && { \"aria-disabled\": true })}\n {...(selected && { \"data-selected\": \"\" })}\n {...props}\n >\n {leftDot && <span className=\"size-2 shrink-0 rounded-full bg-current\" aria-hidden=\"true\" />}\n {leftIcon && (\n <span className=\"flex size-5 shrink-0 items-center justify-center\" aria-hidden=\"true\">\n {leftIcon}\n </span>\n )}\n <Slottable>{children}</Slottable>\n {rightIcon && (\n <span className=\"flex size-5 shrink-0 items-center justify-center\" aria-hidden=\"true\">\n {rightIcon}\n </span>\n )}\n {notificationLabel && (\n <span className=\"typography-caption-semibold absolute -top-1 -right-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-body-100 px-1 text-body-300\">\n {notificationLabel}\n </span>\n )}\n </Comp>\n );\n },\n);\n\nChip.displayName = \"Chip\";\n"],"names":["React","Slot","jsxs","cn","jsx","Slottable"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA8BO,MAAM,OAAOA,iBAAM;AAAA,EACxB,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV,OAAO;AAAA,IACP,WAAW;AAAA,IACX,WAAW;AAAA,IACX,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QAEG;AACH,UAAM,gBAAgB,CAAC,CAAC,WAAW,CAAC;AACpC,UAAM,OAAO,UAAUC,UAAAA,OAAO,gBAAgB,WAAW;AACzD,UAAM,SAAS,YAAY;AAE3B,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,eAAY;AAAA,QACZ,WAAWC,GAAAA;AAAAA,UACT;AAAA;AAAA,UAEA,YAAY,WAAW,eAAe;AAAA;AAAA,UAEtC,SAAS,QAAQ;AAAA,UACjB,SAAS,QAAQ;AAAA;AAAA,UAEjB,UAAU;AAAA,UACV,CAAC,UAAU,YAAY;AAAA,UACvB,CAAC,UAAU,CAAC,YAAY;AAAA;AAAA,UAExB,iBACE,CAAC,YACD,CAAC,UACD,YACA;AAAA,UACF,iBAAiB,CAAC,YAAY,CAAC,UAAU,CAAC,YAAY;AAAA;AAAA,UAEtD;AAAA;AAAA,UAEA,YAAY,UAAU;AAAA,UACtB,YAAY,CAAC,UAAU;AAAA,UACvB;AAAA,QAAA;AAAA,QAED,GAAI,iBAAiB;AAAA,UACpB,MAAM;AAAA,UACN;AAAA,UACA,gBAAgB;AAAA,UAChB;AAAA,QAAA;AAAA,QAED,GAAI,CAAC,iBAAiB,YAAY,EAAE,iBAAiB,KAAA;AAAA,QACrD,GAAI,YAAY,EAAE,iBAAiB,GAAA;AAAA,QACnC,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,WAAWC,2BAAAA,IAAC,QAAA,EAAK,WAAU,2CAA0C,eAAY,QAAO;AAAA,UACxF,YACCA,2BAAAA,IAAC,QAAA,EAAK,WAAU,oDAAmD,eAAY,QAC5E,UAAA,UACH;AAAA,UAEFA,+BAACC,UAAAA,aAAW,UAAS;AAAA,UACpB,aACCD,2BAAAA,IAAC,QAAA,EAAK,WAAU,oDAAmD,eAAY,QAC5E,UAAA,WACH;AAAA,UAED,qBACCA,2BAAAA,IAAC,QAAA,EAAK,WAAU,iJACb,UAAA,kBAAA,CACH;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,KAAK,cAAc;;"}
1
+ {"version":3,"file":"Chip.cjs","sources":["../../../../src/components/Chip/Chip.tsx"],"sourcesContent":["import { Slot, Slottable } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Visual variant of the chip. */\nexport type ChipVariant = \"rounded\" | \"square\" | \"dark\";\n/** Height of the chip in pixels. */\nexport type ChipSize = \"32\" | \"40\";\n\nexport interface ChipProps extends React.HTMLAttributes<HTMLElement> {\n /** Visual variant of the chip. @default \"rounded\" */\n variant?: ChipVariant;\n /** Height of the chip in pixels. @default \"32\" */\n size?: ChipSize;\n /** Whether the chip is in a selected (pressed) state. @default false */\n selected?: boolean;\n /** Whether the chip is disabled. @default false */\n disabled?: boolean;\n /** Whether to show a coloured status dot at the leading edge. @default false */\n leftDot?: boolean;\n /** Icon element displayed before the label. */\n leftIcon?: React.ReactNode;\n /** Icon element displayed after the label. */\n rightIcon?: React.ReactNode;\n /** Notification badge content (e.g. `\"99+\"`). Passed as a string for i18n support. */\n notificationLabel?: string;\n /** Click handler — when provided, the chip renders as a `<button>` for accessibility. */\n onClick?: React.MouseEventHandler<HTMLElement>;\n /** Merge props onto a child element instead of rendering a wrapper. @default false */\n asChild?: boolean;\n}\n\n/**\n * A compact element for filters, tags, or toggleable actions. When an `onClick`\n * handler is provided, the chip renders as an interactive `<button>` with\n * `aria-pressed` support.\n *\n * @example\n * ```tsx\n * <Chip selected onClick={toggle}>Music</Chip>\n * ```\n */\nexport const Chip = React.forwardRef<HTMLButtonElement, ChipProps>(\n (\n {\n className,\n variant = \"rounded\",\n size = \"32\",\n selected = false,\n disabled = false,\n leftDot = false,\n leftIcon,\n rightIcon,\n notificationLabel,\n onClick,\n asChild = false,\n children,\n ...props\n },\n ref,\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Variant-heavy UI component\n ) => {\n const isInteractive = !!onClick && !asChild;\n const Comp = asChild ? Slot : isInteractive ? \"button\" : \"span\";\n const isDark = variant === \"dark\";\n\n return (\n <Comp\n ref={ref}\n data-testid=\"chip\"\n className={cn(\n \"typography-caption-semibold relative inline-flex items-center gap-2 px-3 motion-safe:transition-colors motion-safe:duration-150\",\n // Shape\n variant === \"square\" ? \"rounded-lg\" : \"rounded-full\",\n // Size\n size === \"32\" && \"h-8 py-1\",\n size === \"40\" && \"h-10 py-2.5\",\n // Variant colors\n isDark && \"bg-background-800 text-body-white-solid-constant\",\n !isDark && selected && \"bg-brand-green-50 text-neutral-400\",\n !isDark && !selected && \"bg-neutral-100 text-neutral-400\",\n // Hover\n isInteractive &&\n !disabled &&\n !isDark &&\n selected &&\n \"hover:bg-brand-green-500 hover:text-body-black-solid-constant active:bg-brand-green-500 active:text-body-black-solid-constant\",\n isInteractive &&\n !disabled &&\n !isDark &&\n !selected &&\n \"hover:bg-hover-400 active:bg-hover-400\",\n // Focus\n \"focus-visible:shadow-focus-ring focus-visible:outline-none\",\n // Disabled\n disabled && isDark && \"pointer-events-none opacity-50\",\n disabled && !isDark && \"pointer-events-none text-neutral-300\",\n className,\n )}\n {...(isInteractive && {\n type: \"button\" as const,\n disabled,\n \"aria-pressed\": selected,\n onClick,\n })}\n {...(!isInteractive && disabled && { \"aria-disabled\": true })}\n {...(selected && { \"data-selected\": \"\" })}\n {...props}\n >\n {leftDot && <span className=\"size-2 shrink-0 rounded-full bg-current\" aria-hidden=\"true\" />}\n {leftIcon && (\n <span className=\"flex size-5 shrink-0 items-center justify-center\" aria-hidden=\"true\">\n {leftIcon}\n </span>\n )}\n <Slottable>{children}</Slottable>\n {rightIcon && (\n <span className=\"flex size-5 shrink-0 items-center justify-center\" aria-hidden=\"true\">\n {rightIcon}\n </span>\n )}\n {notificationLabel && (\n <span className=\"typography-caption-semibold absolute -top-1 -right-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-body-100 px-1 text-body-300\">\n {notificationLabel}\n </span>\n )}\n </Comp>\n );\n },\n);\n\nChip.displayName = \"Chip\";\n"],"names":["React","Slot","jsxs","cn","jsx","Slottable"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA0CO,MAAM,OAAOA,iBAAM;AAAA,EACxB,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV,OAAO;AAAA,IACP,WAAW;AAAA,IACX,WAAW;AAAA,IACX,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QAEG;AACH,UAAM,gBAAgB,CAAC,CAAC,WAAW,CAAC;AACpC,UAAM,OAAO,UAAUC,UAAAA,OAAO,gBAAgB,WAAW;AACzD,UAAM,SAAS,YAAY;AAE3B,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,eAAY;AAAA,QACZ,WAAWC,GAAAA;AAAAA,UACT;AAAA;AAAA,UAEA,YAAY,WAAW,eAAe;AAAA;AAAA,UAEtC,SAAS,QAAQ;AAAA,UACjB,SAAS,QAAQ;AAAA;AAAA,UAEjB,UAAU;AAAA,UACV,CAAC,UAAU,YAAY;AAAA,UACvB,CAAC,UAAU,CAAC,YAAY;AAAA;AAAA,UAExB,iBACE,CAAC,YACD,CAAC,UACD,YACA;AAAA,UACF,iBACE,CAAC,YACD,CAAC,UACD,CAAC,YACD;AAAA;AAAA,UAEF;AAAA;AAAA,UAEA,YAAY,UAAU;AAAA,UACtB,YAAY,CAAC,UAAU;AAAA,UACvB;AAAA,QAAA;AAAA,QAED,GAAI,iBAAiB;AAAA,UACpB,MAAM;AAAA,UACN;AAAA,UACA,gBAAgB;AAAA,UAChB;AAAA,QAAA;AAAA,QAED,GAAI,CAAC,iBAAiB,YAAY,EAAE,iBAAiB,KAAA;AAAA,QACrD,GAAI,YAAY,EAAE,iBAAiB,GAAA;AAAA,QACnC,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,WAAWC,2BAAAA,IAAC,QAAA,EAAK,WAAU,2CAA0C,eAAY,QAAO;AAAA,UACxF,YACCA,2BAAAA,IAAC,QAAA,EAAK,WAAU,oDAAmD,eAAY,QAC5E,UAAA,UACH;AAAA,UAEFA,+BAACC,UAAAA,aAAW,UAAS;AAAA,UACpB,aACCD,2BAAAA,IAAC,QAAA,EAAK,WAAU,oDAAmD,eAAY,QAC5E,UAAA,WACH;AAAA,UAED,qBACCA,2BAAAA,IAAC,QAAA,EAAK,WAAU,iJACb,UAAA,kBAAA,CACH;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,KAAK,cAAc;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Count.cjs","sources":["../../../../src/components/Count/Count.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport type CountVariant = \"default\" | \"brand\" | \"pink\" | \"info\" | \"success\" | \"warning\";\n\nfunction getDisplayValue(value: number, max: number): string {\n return value > max ? `${max}+` : value.toString();\n}\n\nexport interface CountProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Visual style variant of the count */\n variant?: CountVariant;\n /** The count value to display */\n value?: number;\n /** Maximum value to display before showing overflow (e.g., \"99+\") */\n max?: number;\n /** Render as a different element using Radix Slot */\n asChild?: boolean;\n}\n\nexport const Count = React.forwardRef<HTMLSpanElement, CountProps>(\n (\n { className, variant = \"default\", value = 0, max = 99, asChild = false, children, ...props },\n ref,\n ) => {\n if (value === 0 && !children) {\n return null;\n }\n\n const Comp = asChild ? Slot : \"span\";\n\n return (\n <Comp\n ref={ref}\n className={cn(\n \"typography-caption-semibold inline-flex h-5 min-w-5 shrink-0 items-center justify-center rounded-full px-1.5 tabular-nums leading-none\",\n variant === \"default\" && \"bg-error-500 text-body-white-solid-constant\",\n variant === \"brand\" && \"bg-brand-green-500 text-body-black-solid-constant\",\n variant === \"pink\" && \"bg-brand-pink-500 text-body-black-solid-constant\",\n variant === \"info\" && \"bg-info-500 text-body-white-solid-constant\",\n variant === \"success\" && \"bg-success-500 text-body-white-solid-constant\",\n variant === \"warning\" && \"bg-warning-500 text-body-black-solid-constant\",\n className,\n )}\n {...props}\n >\n {children ?? getDisplayValue(value, max)}\n </Comp>\n );\n },\n);\n\nCount.displayName = \"Count\";\n"],"names":["React","Slot","jsx","cn"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAMA,SAAS,gBAAgB,OAAe,KAAqB;AAC3D,SAAO,QAAQ,MAAM,GAAG,GAAG,MAAM,MAAM,SAAA;AACzC;AAaO,MAAM,QAAQA,iBAAM;AAAA,EACzB,CACE,EAAE,WAAW,UAAU,WAAW,QAAQ,GAAG,MAAM,IAAI,UAAU,OAAO,UAAU,GAAG,MAAA,GACrF,QACG;AACH,QAAI,UAAU,KAAK,CAAC,UAAU;AAC5B,aAAO;AAAA,IACT;AAEA,UAAM,OAAO,UAAUC,UAAAA,OAAO;AAE9B,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWC,GAAAA;AAAAA,UACT;AAAA,UACA,YAAY,aAAa;AAAA,UACzB,YAAY,WAAW;AAAA,UACvB,YAAY,UAAU;AAAA,UACtB,YAAY,UAAU;AAAA,UACtB,YAAY,aAAa;AAAA,UACzB,YAAY,aAAa;AAAA,UACzB;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH,UAAA,YAAY,gBAAgB,OAAO,GAAG;AAAA,MAAA;AAAA,IAAA;AAAA,EAG7C;AACF;AAEA,MAAM,cAAc;;"}
1
+ {"version":3,"file":"Count.cjs","sources":["../../../../src/components/Count/Count.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Colour variant for the count badge. */\nexport type CountVariant = \"default\" | \"brand\" | \"pink\" | \"info\" | \"success\" | \"warning\";\n\nfunction getDisplayValue(value: number, max: number): string {\n return value > max ? `${max}+` : value.toString();\n}\n\nexport interface CountProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Colour variant of the count badge. @default \"default\" */\n variant?: CountVariant;\n /** Numeric value to display. Renders nothing when `0` and no `children` are provided. @default 0 */\n value?: number;\n /** Maximum value before showing overflow (e.g. `\"99+\"`). @default 99 */\n max?: number;\n /** Merge props onto a child element instead of rendering a `<span>`. @default false */\n asChild?: boolean;\n}\n\n/**\n * A numeric badge typically used for notification counts. Automatically\n * truncates values above `max` (e.g. `\"99+\"`). Renders nothing when the\n * value is `0` and no children are provided.\n *\n * @example\n * ```tsx\n * <Count value={5} variant=\"brand\" />\n * ```\n */\nexport const Count = React.forwardRef<HTMLSpanElement, CountProps>(\n (\n { className, variant = \"default\", value = 0, max = 99, asChild = false, children, ...props },\n ref,\n ) => {\n if (value === 0 && !children) {\n return null;\n }\n\n const Comp = asChild ? Slot : \"span\";\n\n return (\n <Comp\n ref={ref}\n className={cn(\n \"typography-caption-semibold inline-flex h-5 min-w-5 shrink-0 items-center justify-center rounded-full px-1.5 tabular-nums leading-none\",\n variant === \"default\" && \"bg-error-500 text-body-white-solid-constant\",\n variant === \"brand\" && \"bg-brand-green-500 text-body-black-solid-constant\",\n variant === \"pink\" && \"bg-brand-pink-500 text-body-black-solid-constant\",\n variant === \"info\" && \"bg-info-500 text-body-white-solid-constant\",\n variant === \"success\" && \"bg-success-500 text-body-white-solid-constant\",\n variant === \"warning\" && \"bg-warning-500 text-body-black-solid-constant\",\n className,\n )}\n {...props}\n >\n {children ?? getDisplayValue(value, max)}\n </Comp>\n );\n },\n);\n\nCount.displayName = \"Count\";\n"],"names":["React","Slot","jsx","cn"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAOA,SAAS,gBAAgB,OAAe,KAAqB;AAC3D,SAAO,QAAQ,MAAM,GAAG,GAAG,MAAM,MAAM,SAAA;AACzC;AAuBO,MAAM,QAAQA,iBAAM;AAAA,EACzB,CACE,EAAE,WAAW,UAAU,WAAW,QAAQ,GAAG,MAAM,IAAI,UAAU,OAAO,UAAU,GAAG,MAAA,GACrF,QACG;AACH,QAAI,UAAU,KAAK,CAAC,UAAU;AAC5B,aAAO;AAAA,IACT;AAEA,UAAM,OAAO,UAAUC,UAAAA,OAAO;AAE9B,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWC,GAAAA;AAAAA,UACT;AAAA,UACA,YAAY,aAAa;AAAA,UACzB,YAAY,WAAW;AAAA,UACvB,YAAY,UAAU;AAAA,UACtB,YAAY,UAAU;AAAA,UACtB,YAAY,aAAa;AAAA,UACzB,YAAY,aAAa;AAAA,UACzB;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH,UAAA,YAAY,gBAAgB,OAAO,GAAG;AAAA,MAAA;AAAA,IAAA;AAAA,EAG7C;AACF;AAEA,MAAM,cAAc;;"}
@@ -37,8 +37,8 @@ function DayButton({ day, modifiers, className, ...buttonProps }) {
37
37
  className: cn.cn(
38
38
  "relative z-10 inline-flex size-10 cursor-pointer items-center justify-center rounded-lg",
39
39
  "typography-body-2-regular",
40
- "transition-colors hover:bg-brand-green-50",
41
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-purple-500 focus-visible:outline-offset-[-2px]",
40
+ "transition-colors hover:bg-brand-green-50 not-disabled:active:bg-brand-green-50",
41
+ "focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-brand-purple-500",
42
42
  "disabled:cursor-not-allowed disabled:opacity-50",
43
43
  modifiers.today && !modifiers.selected && "border border-brand-green-500",
44
44
  modifiers.selected && !modifiers.range_middle ? "bg-brand-green-500 text-body-black-solid-constant hover:bg-brand-green-500" : "text-body-100",
@@ -51,7 +51,7 @@ function DayButton({ day, modifiers, className, ...buttonProps }) {
51
51
  }
52
52
  const DatePicker = React.forwardRef(
53
53
  ({
54
- type = "single",
54
+ variant = "single",
55
55
  onApply,
56
56
  onCancel,
57
57
  cancelLabel = "Cancel",
@@ -61,8 +61,31 @@ const DatePicker = React.forwardRef(
61
61
  formatters,
62
62
  ...dayPickerProps
63
63
  }, ref) => {
64
- const numberOfMonths = type === "double" ? 2 : 1;
64
+ const numberOfMonths = variant === "double" ? 2 : 1;
65
65
  const isMulti = numberOfMonths > 1;
66
+ const resolvedDayPickerProps = (() => {
67
+ if (dayPickerProps.mode !== "range") return dayPickerProps;
68
+ const { selected, onSelect } = dayPickerProps;
69
+ if (!onSelect || !selected?.from || !selected?.to) return dayPickerProps;
70
+ const { from, to } = selected;
71
+ return {
72
+ ...dayPickerProps,
73
+ onSelect: (range, triggerDate, modifiers, e) => {
74
+ const clickedTime = triggerDate.getTime();
75
+ const fromTime = from.getTime();
76
+ const toTime = to.getTime();
77
+ if (clickedTime > fromTime && clickedTime < toTime) {
78
+ if (clickedTime - fromTime <= toTime - clickedTime) {
79
+ onSelect({ from: triggerDate, to }, triggerDate, modifiers, e);
80
+ } else {
81
+ onSelect({ from, to: triggerDate }, triggerDate, modifiers, e);
82
+ }
83
+ return;
84
+ }
85
+ onSelect(range, triggerDate, modifiers, e);
86
+ }
87
+ };
88
+ })();
66
89
  return /* @__PURE__ */ jsxRuntime.jsxs(
67
90
  "div",
68
91
  {
@@ -91,9 +114,9 @@ const DatePicker = React.forwardRef(
91
114
  "absolute top-4 z-20 flex",
92
115
  isMulti ? "pointer-events-none inset-x-3 justify-between" : "right-3 gap-1"
93
116
  ),
94
- button_previous: "pointer-events-auto inline-flex size-8 cursor-pointer items-center justify-center rounded-full text-body-100 transition-colors hover:bg-brand-green-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-purple-500 disabled:cursor-not-allowed disabled:opacity-50",
117
+ button_previous: "pointer-events-auto inline-flex size-8 cursor-pointer items-center justify-center rounded-full text-body-100 transition-colors hover:bg-brand-green-50 not-disabled:active:bg-brand-green-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-purple-500 disabled:cursor-not-allowed disabled:opacity-50",
95
118
  // !TODO https://linear.app/fanvue/issue/ENG-7301/swap-out-typography-tailwind-utility-classes
96
- button_next: "pointer-events-auto inline-flex size-8 cursor-pointer items-center justify-center rounded-full text-body-100 transition-colors hover:bg-brand-green-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-purple-500 disabled:cursor-not-allowed disabled:opacity-50",
119
+ button_next: "pointer-events-auto inline-flex size-8 cursor-pointer items-center justify-center rounded-full text-body-100 transition-colors hover:bg-brand-green-50 not-disabled:active:bg-brand-green-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-purple-500 disabled:cursor-not-allowed disabled:opacity-50",
97
120
  // !TODO https://linear.app/fanvue/issue/ENG-7301/swap-out-typography-tailwind-utility-classes
98
121
  month_grid: cn.cn("mb-4", isMulti ? "mx-2" : "mx-4"),
99
122
  weekdays: "flex",
@@ -116,7 +139,7 @@ const DatePicker = React.forwardRef(
116
139
  Day,
117
140
  DayButton
118
141
  },
119
- ...dayPickerProps
142
+ ...resolvedDayPickerProps
120
143
  }
121
144
  ),
122
145
  showFooter && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4 px-5 pb-4", children: [
@@ -1 +1 @@
1
- {"version":3,"file":"DatePicker.cjs","sources":["../../../../src/components/DatePicker/DatePicker.tsx"],"sourcesContent":["import { forwardRef, useEffect, useRef } from \"react\";\nimport {\n type ChevronProps,\n type DateRange,\n type DayButtonProps,\n DayPicker,\n type DayPickerProps,\n type DayProps,\n type MonthGridProps,\n type WeekdayProps,\n type WeekdaysProps,\n type WeekProps,\n type WeeksProps,\n} from \"react-day-picker\";\nimport { cn } from \"../../utils/cn\";\nimport type { OmitDistributed } from \"../../utils/types\";\nimport { Button } from \"../Button/Button\";\nimport { ChevronLeftIcon } from \"../Icons/ChevronLeftIcon\";\nimport { ChevronRightIcon } from \"../Icons/ChevronRightIcon\";\n\nexport type { DateRange }; // Needed by consumers when passing props\n\nexport type DatePickerType = \"single\" | \"double\";\n\nexport interface DatePickerOwnProps {\n /** Display one month or two side-by-side. @default \"single\" */\n type?: DatePickerType;\n /** Called when the Apply button is clicked. */\n onApply?: () => void;\n /** Called when the Cancel button is clicked. */\n onCancel?: () => void;\n /** Label for the cancel button. @default \"Cancel\" */\n cancelLabel?: string;\n /** Label for the apply button. @default \"Apply\" */\n applyLabel?: string;\n /** Whether to render cancel / apply footer buttons. @default true */\n showFooter?: boolean;\n /** Additional className for the outer container. */\n className?: string;\n}\n\nfunction Day({ day, modifiers, className, ...divProps }: DayProps) {\n const { range_start, range_end } = modifiers;\n const isSingleDayRange = range_start && range_end;\n\n return (\n <div\n className={cn(\n className,\n (range_start || range_end) && !isSingleDayRange && \"from-50% from-transparent to-50%\",\n range_start && !isSingleDayRange && \"bg-linear-to-r to-brand-green-50\",\n range_end && !isSingleDayRange && \"bg-linear-to-l to-brand-green-50\",\n )}\n {...divProps}\n />\n );\n}\n\nfunction DayButton({ day, modifiers, className, ...buttonProps }: DayButtonProps) {\n const ref = useRef<HTMLButtonElement>(null);\n\n useEffect(() => {\n if (modifiers.focused) ref.current?.focus();\n }, [modifiers.focused]);\n\n return (\n <button\n ref={ref}\n type=\"button\"\n className={cn(\n \"relative z-10 inline-flex size-10 cursor-pointer items-center justify-center rounded-lg\",\n \"typography-body-2-regular\",\n \"transition-colors hover:bg-brand-green-50\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-purple-500 focus-visible:outline-offset-[-2px]\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n modifiers.today && !modifiers.selected && \"border border-brand-green-500\",\n modifiers.selected && !modifiers.range_middle\n ? \"bg-brand-green-500 text-body-black-solid-constant hover:bg-brand-green-500\"\n : \"text-body-100\",\n modifiers.range_middle && \"rounded-none bg-transparent\",\n modifiers.outside && \"pointer-events-none opacity-50\",\n )}\n {...buttonProps}\n />\n );\n}\n\nexport type DatePickerProps = DatePickerOwnProps &\n OmitDistributed<DayPickerProps, \"numberOfMonths\">;\n\nexport const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>(\n (\n {\n type = \"single\",\n onApply,\n onCancel,\n cancelLabel = \"Cancel\",\n applyLabel = \"Apply\",\n showFooter = true,\n className,\n formatters,\n ...dayPickerProps\n },\n ref,\n ) => {\n const numberOfMonths = type === \"double\" ? 2 : 1;\n const isMulti = numberOfMonths > 1;\n\n return (\n <div\n ref={ref}\n className={cn(\n \"inline-flex flex-col rounded-2xl border border-neutral-200 bg-background-inverse-solid shadow-[0px_6px_12px_0px_rgba(0,0,0,0.1)] backdrop-blur-sm\",\n className,\n )}\n >\n <DayPicker\n showOutsideDays\n numberOfMonths={numberOfMonths}\n formatters={{\n formatCaption: (date: Date) =>\n date.toLocaleDateString(\"en-US\", { month: \"short\", year: \"numeric\" }),\n ...formatters,\n }}\n classNames={{\n root: \"w-full\",\n months: \"relative flex\",\n month: \"flex flex-1 flex-col\",\n month_caption: cn(\"flex items-center py-4\", isMulti ? \"justify-center px-2\" : \"px-5\"),\n caption_label: \"typography-body-1-semibold text-body-100\",\n nav: cn(\n \"absolute top-4 z-20 flex\",\n isMulti ? \"pointer-events-none inset-x-3 justify-between\" : \"right-3 gap-1\",\n ),\n button_previous:\n \"pointer-events-auto inline-flex size-8 cursor-pointer items-center justify-center rounded-full text-body-100 transition-colors hover:bg-brand-green-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-purple-500 disabled:cursor-not-allowed disabled:opacity-50\", // !TODO https://linear.app/fanvue/issue/ENG-7301/swap-out-typography-tailwind-utility-classes\n button_next:\n \"pointer-events-auto inline-flex size-8 cursor-pointer items-center justify-center rounded-full text-body-100 transition-colors hover:bg-brand-green-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-purple-500 disabled:cursor-not-allowed disabled:opacity-50\", // !TODO https://linear.app/fanvue/issue/ENG-7301/swap-out-typography-tailwind-utility-classes\n month_grid: cn(\"mb-4\", isMulti ? \"mx-2\" : \"mx-4\"),\n weekdays: \"flex\",\n weekday:\n \"flex h-[30px] w-10 flex-1 items-center justify-center typography-body-2-regular text-body-200\",\n week: \"flex overflow-hidden rounded-lg\",\n day: \"relative flex w-10 flex-1 items-center justify-center\",\n range_middle: \"bg-brand-green-50\",\n hidden: \"hidden\",\n }}\n components={{\n /**\n * !NOTE: We're unable to use semantic elements for the grid due to rdp, as such we've disabled the a11y lint rules for these elements in biome.json.\n */\n Chevron: ({ orientation }: ChevronProps) =>\n orientation === \"left\" ? <ChevronLeftIcon /> : <ChevronRightIcon />,\n MonthGrid: (props: MonthGridProps) => <div role=\"grid\" {...props} />,\n Weekdays: (props: WeekdaysProps) => <div role=\"row\" {...props} />,\n Weekday: (props: WeekdayProps) => <div role=\"columnheader\" {...props} />,\n Weeks: (props: WeeksProps) => <div role=\"rowgroup\" {...props} />,\n Week: ({ week, ...props }: WeekProps) => <div role=\"row\" {...props} />,\n Day,\n DayButton,\n }}\n {...dayPickerProps}\n />\n\n {showFooter && (\n <div className=\"flex gap-4 px-5 pb-4\">\n <Button variant=\"secondary\" size=\"40\" className=\"flex-1\" onClick={onCancel}>\n {cancelLabel}\n </Button>\n <Button variant=\"primary\" size=\"40\" className=\"flex-1\" onClick={onApply}>\n {applyLabel}\n </Button>\n </div>\n )}\n </div>\n );\n },\n);\n\nDatePicker.displayName = \"DatePicker\";\n"],"names":["jsx","cn","useRef","useEffect","forwardRef","jsxs","DayPicker","ChevronLeftIcon","ChevronRightIcon","Button"],"mappings":"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"}
1
+ {"version":3,"file":"DatePicker.cjs","sources":["../../../../src/components/DatePicker/DatePicker.tsx"],"sourcesContent":["import { forwardRef, useEffect, useRef } from \"react\";\nimport {\n type ChevronProps,\n type DateRange,\n type DayButtonProps,\n DayPicker,\n type DayPickerProps,\n type DayProps,\n type Modifiers,\n type MonthGridProps,\n type WeekdayProps,\n type WeekdaysProps,\n type WeekProps,\n type WeeksProps,\n} from \"react-day-picker\";\nimport { cn } from \"../../utils/cn\";\nimport type { OmitDistributed } from \"../../utils/types\";\nimport { Button } from \"../Button/Button\";\nimport { ChevronLeftIcon } from \"../Icons/ChevronLeftIcon\";\nimport { ChevronRightIcon } from \"../Icons/ChevronRightIcon\";\n\nexport type { DateRange }; // Needed by consumers when passing props\n\n/** Layout variant — single or side-by-side month display. */\nexport type DatePickerVariant = \"single\" | \"double\";\n\n/** Props specific to the DatePicker wrapper (not inherited from react-day-picker). */\nexport interface DatePickerOwnProps {\n /** Display one month or two side-by-side. @default \"single\" */\n variant?: DatePickerVariant;\n /** Callback fired when the Apply button is clicked. */\n onApply?: () => void;\n /** Callback fired when the Cancel button is clicked. */\n onCancel?: () => void;\n /** Label for the cancel button. @default \"Cancel\" */\n cancelLabel?: string;\n /** Label for the apply button. @default \"Apply\" */\n applyLabel?: string;\n /** Whether to render the cancel / apply footer buttons. @default true */\n showFooter?: boolean;\n /** Additional CSS class name for the outer container. */\n className?: string;\n}\n\nfunction Day({ day, modifiers, className, ...divProps }: DayProps) {\n const { range_start, range_end } = modifiers;\n const isSingleDayRange = range_start && range_end;\n\n return (\n <div\n className={cn(\n className,\n (range_start || range_end) && !isSingleDayRange && \"from-50% from-transparent to-50%\",\n range_start && !isSingleDayRange && \"bg-linear-to-r to-brand-green-50\",\n range_end && !isSingleDayRange && \"bg-linear-to-l to-brand-green-50\",\n )}\n {...divProps}\n />\n );\n}\n\nfunction DayButton({ day, modifiers, className, ...buttonProps }: DayButtonProps) {\n const ref = useRef<HTMLButtonElement>(null);\n\n useEffect(() => {\n if (modifiers.focused) ref.current?.focus();\n }, [modifiers.focused]);\n\n return (\n <button\n ref={ref}\n type=\"button\"\n className={cn(\n \"relative z-10 inline-flex size-10 cursor-pointer items-center justify-center rounded-lg\",\n \"typography-body-2-regular\",\n \"transition-colors hover:bg-brand-green-50 not-disabled:active:bg-brand-green-50\",\n \"focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-brand-purple-500\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n modifiers.today && !modifiers.selected && \"border border-brand-green-500\",\n modifiers.selected && !modifiers.range_middle\n ? \"bg-brand-green-500 text-body-black-solid-constant hover:bg-brand-green-500\"\n : \"text-body-100\",\n modifiers.range_middle && \"rounded-none bg-transparent\",\n modifiers.outside && \"pointer-events-none opacity-50\",\n )}\n {...buttonProps}\n />\n );\n}\n\n/** Combined props — own DatePicker options plus all react-day-picker props (except `numberOfMonths`). */\nexport type DatePickerProps = DatePickerOwnProps &\n OmitDistributed<DayPickerProps, \"numberOfMonths\">;\n\n/**\n * A calendar date picker supporting single-date and date-range selection with\n * optional side-by-side month display and footer action buttons.\n *\n * Built on top of [react-day-picker](https://react-day-picker.js.org/) — all\n * `DayPickerProps` (except `numberOfMonths`) are forwarded.\n *\n * @example\n * ```tsx\n * <DatePicker\n * mode=\"range\"\n * type=\"double\"\n * selected={range}\n * onSelect={setRange}\n * onApply={save}\n * onCancel={close}\n * />\n * ```\n */\nexport const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>(\n (\n {\n variant = \"single\",\n onApply,\n onCancel,\n cancelLabel = \"Cancel\",\n applyLabel = \"Apply\",\n showFooter = true,\n className,\n formatters,\n ...dayPickerProps\n },\n ref,\n ) => {\n const numberOfMonths = variant === \"double\" ? 2 : 1;\n const isMulti = numberOfMonths > 1;\n\n // Wrap onSelect for range mode: when clicking inside a complete range,\n // move the nearest boundary instead of always resetting the end date.\n const resolvedDayPickerProps = (() => {\n if (dayPickerProps.mode !== \"range\") return dayPickerProps;\n\n const { selected, onSelect } = dayPickerProps as {\n selected?: DateRange;\n onSelect?: (\n range: DateRange | undefined,\n triggerDate: Date,\n modifiers: Modifiers,\n e: React.MouseEvent | React.KeyboardEvent,\n ) => void;\n };\n\n if (!onSelect || !selected?.from || !selected?.to) return dayPickerProps;\n\n const { from, to } = selected;\n\n return {\n ...dayPickerProps,\n onSelect: (\n range: DateRange | undefined,\n triggerDate: Date,\n modifiers: Modifiers,\n e: React.MouseEvent | React.KeyboardEvent,\n ) => {\n const clickedTime = triggerDate.getTime();\n const fromTime = from.getTime();\n const toTime = to.getTime();\n\n if (clickedTime > fromTime && clickedTime < toTime) {\n if (clickedTime - fromTime <= toTime - clickedTime) {\n onSelect({ from: triggerDate, to }, triggerDate, modifiers, e);\n } else {\n onSelect({ from, to: triggerDate }, triggerDate, modifiers, e);\n }\n return;\n }\n\n onSelect(range, triggerDate, modifiers, e);\n },\n } as typeof dayPickerProps;\n })();\n\n return (\n <div\n ref={ref}\n className={cn(\n \"inline-flex flex-col rounded-2xl border border-neutral-200 bg-background-inverse-solid shadow-[0px_6px_12px_0px_rgba(0,0,0,0.1)] backdrop-blur-sm\",\n className,\n )}\n >\n <DayPicker\n showOutsideDays\n numberOfMonths={numberOfMonths}\n formatters={{\n formatCaption: (date: Date) =>\n date.toLocaleDateString(\"en-US\", { month: \"short\", year: \"numeric\" }),\n ...formatters,\n }}\n classNames={{\n root: \"w-full\",\n months: \"relative flex\",\n month: \"flex flex-1 flex-col\",\n month_caption: cn(\"flex items-center py-4\", isMulti ? \"justify-center px-2\" : \"px-5\"),\n caption_label: \"typography-body-1-semibold text-body-100\",\n nav: cn(\n \"absolute top-4 z-20 flex\",\n isMulti ? \"pointer-events-none inset-x-3 justify-between\" : \"right-3 gap-1\",\n ),\n button_previous:\n \"pointer-events-auto inline-flex size-8 cursor-pointer items-center justify-center rounded-full text-body-100 transition-colors hover:bg-brand-green-50 not-disabled:active:bg-brand-green-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-purple-500 disabled:cursor-not-allowed disabled:opacity-50\", // !TODO https://linear.app/fanvue/issue/ENG-7301/swap-out-typography-tailwind-utility-classes\n button_next:\n \"pointer-events-auto inline-flex size-8 cursor-pointer items-center justify-center rounded-full text-body-100 transition-colors hover:bg-brand-green-50 not-disabled:active:bg-brand-green-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-purple-500 disabled:cursor-not-allowed disabled:opacity-50\", // !TODO https://linear.app/fanvue/issue/ENG-7301/swap-out-typography-tailwind-utility-classes\n month_grid: cn(\"mb-4\", isMulti ? \"mx-2\" : \"mx-4\"),\n weekdays: \"flex\",\n weekday:\n \"flex h-[30px] w-10 flex-1 items-center justify-center typography-body-2-regular text-body-200\",\n week: \"flex overflow-hidden rounded-lg\",\n day: \"relative flex w-10 flex-1 items-center justify-center\",\n range_middle: \"bg-brand-green-50\",\n hidden: \"hidden\",\n }}\n components={{\n /**\n * !NOTE: We're unable to use semantic elements for the grid due to rdp, as such we've disabled the a11y lint rules for these elements in biome.json.\n */\n Chevron: ({ orientation }: ChevronProps) =>\n orientation === \"left\" ? <ChevronLeftIcon /> : <ChevronRightIcon />,\n MonthGrid: (props: MonthGridProps) => <div role=\"grid\" {...props} />,\n Weekdays: (props: WeekdaysProps) => <div role=\"row\" {...props} />,\n Weekday: (props: WeekdayProps) => <div role=\"columnheader\" {...props} />,\n Weeks: (props: WeeksProps) => <div role=\"rowgroup\" {...props} />,\n Week: ({ week, ...props }: WeekProps) => <div role=\"row\" {...props} />,\n Day,\n DayButton,\n }}\n {...resolvedDayPickerProps}\n />\n\n {showFooter && (\n <div className=\"flex gap-4 px-5 pb-4\">\n <Button variant=\"secondary\" size=\"40\" className=\"flex-1\" onClick={onCancel}>\n {cancelLabel}\n </Button>\n <Button variant=\"primary\" size=\"40\" className=\"flex-1\" onClick={onApply}>\n {applyLabel}\n </Button>\n </div>\n )}\n </div>\n );\n },\n);\n\nDatePicker.displayName = \"DatePicker\";\n"],"names":["jsx","cn","useRef","useEffect","forwardRef","jsxs","DayPicker","ChevronLeftIcon","ChevronRightIcon","Button"],"mappings":";;;;;;;;;;AA4CA,SAAS,IAAI,EAAE,KAAK,WAAW,WAAW,GAAG,YAAsB;AACjE,QAAM,EAAE,aAAa,UAAA,IAAc;AACnC,QAAM,mBAAmB,eAAe;AAExC,SACEA,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC,GAAAA;AAAAA,QACT;AAAA,SACC,eAAe,cAAc,CAAC,oBAAoB;AAAA,QACnD,eAAe,CAAC,oBAAoB;AAAA,QACpC,aAAa,CAAC,oBAAoB;AAAA,MAAA;AAAA,MAEnC,GAAG;AAAA,IAAA;AAAA,EAAA;AAGV;AAEA,SAAS,UAAU,EAAE,KAAK,WAAW,WAAW,GAAG,eAA+B;AAChF,QAAM,MAAMC,MAAAA,OAA0B,IAAI;AAE1CC,QAAAA,UAAU,MAAM;AACd,QAAI,UAAU,QAAS,KAAI,SAAS,MAAA;AAAA,EACtC,GAAG,CAAC,UAAU,OAAO,CAAC;AAEtB,SACEH,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,MAAK;AAAA,MACL,WAAWC,GAAAA;AAAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,UAAU,SAAS,CAAC,UAAU,YAAY;AAAA,QAC1C,UAAU,YAAY,CAAC,UAAU,eAC7B,+EACA;AAAA,QACJ,UAAU,gBAAgB;AAAA,QAC1B,UAAU,WAAW;AAAA,MAAA;AAAA,MAEtB,GAAG;AAAA,IAAA;AAAA,EAAA;AAGV;AAyBO,MAAM,aAAaG,MAAAA;AAAAA,EACxB,CACE;AAAA,IACE,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,cAAc;AAAA,IACd,aAAa;AAAA,IACb,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,iBAAiB,YAAY,WAAW,IAAI;AAClD,UAAM,UAAU,iBAAiB;AAIjC,UAAM,0BAA0B,MAAM;AACpC,UAAI,eAAe,SAAS,QAAS,QAAO;AAE5C,YAAM,EAAE,UAAU,SAAA,IAAa;AAU/B,UAAI,CAAC,YAAY,CAAC,UAAU,QAAQ,CAAC,UAAU,GAAI,QAAO;AAE1D,YAAM,EAAE,MAAM,GAAA,IAAO;AAErB,aAAO;AAAA,QACL,GAAG;AAAA,QACH,UAAU,CACR,OACA,aACA,WACA,MACG;AACH,gBAAM,cAAc,YAAY,QAAA;AAChC,gBAAM,WAAW,KAAK,QAAA;AACtB,gBAAM,SAAS,GAAG,QAAA;AAElB,cAAI,cAAc,YAAY,cAAc,QAAQ;AAClD,gBAAI,cAAc,YAAY,SAAS,aAAa;AAClD,uBAAS,EAAE,MAAM,aAAa,MAAM,aAAa,WAAW,CAAC;AAAA,YAC/D,OAAO;AACL,uBAAS,EAAE,MAAM,IAAI,eAAe,aAAa,WAAW,CAAC;AAAA,YAC/D;AACA;AAAA,UACF;AAEA,mBAAS,OAAO,aAAa,WAAW,CAAC;AAAA,QAC3C;AAAA,MAAA;AAAA,IAEJ,GAAA;AAEA,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWJ,GAAAA;AAAAA,UACT;AAAA,UACA;AAAA,QAAA;AAAA,QAGF,UAAA;AAAA,UAAAD,2BAAAA;AAAAA,YAACM,eAAAA;AAAAA,YAAA;AAAA,cACC,iBAAe;AAAA,cACf;AAAA,cACA,YAAY;AAAA,gBACV,eAAe,CAAC,SACd,KAAK,mBAAmB,SAAS,EAAE,OAAO,SAAS,MAAM,WAAW;AAAA,gBACtE,GAAG;AAAA,cAAA;AAAA,cAEL,YAAY;AAAA,gBACV,MAAM;AAAA,gBACN,QAAQ;AAAA,gBACR,OAAO;AAAA,gBACP,eAAeL,GAAAA,GAAG,0BAA0B,UAAU,wBAAwB,MAAM;AAAA,gBACpF,eAAe;AAAA,gBACf,KAAKA,GAAAA;AAAAA,kBACH;AAAA,kBACA,UAAU,kDAAkD;AAAA,gBAAA;AAAA,gBAE9D,iBACE;AAAA;AAAA,gBACF,aACE;AAAA;AAAA,gBACF,YAAYA,GAAAA,GAAG,QAAQ,UAAU,SAAS,MAAM;AAAA,gBAChD,UAAU;AAAA,gBACV,SACE;AAAA,gBACF,MAAM;AAAA,gBACN,KAAK;AAAA,gBACL,cAAc;AAAA,gBACd,QAAQ;AAAA,cAAA;AAAA,cAEV,YAAY;AAAA;AAAA;AAAA;AAAA,gBAIV,SAAS,CAAC,EAAE,YAAA,MACV,gBAAgB,SAASD,+BAACO,gBAAAA,iBAAA,CAAA,CAAgB,IAAKP,+BAACQ,iBAAAA,kBAAA,CAAA,CAAiB;AAAA,gBACnE,WAAW,CAAC,UAA0BR,+BAAC,SAAI,MAAK,QAAQ,GAAG,OAAO;AAAA,gBAClE,UAAU,CAAC,UAAyBA,+BAAC,SAAI,MAAK,OAAO,GAAG,OAAO;AAAA,gBAC/D,SAAS,CAAC,UAAwBA,+BAAC,SAAI,MAAK,gBAAgB,GAAG,OAAO;AAAA,gBACtE,OAAO,CAAC,UAAsBA,+BAAC,SAAI,MAAK,YAAY,GAAG,OAAO;AAAA,gBAC9D,MAAM,CAAC,EAAE,MAAM,GAAG,MAAA,MAAuBA,2BAAAA,IAAC,OAAA,EAAI,MAAK,OAAO,GAAG,MAAA,CAAO;AAAA,gBACpE;AAAA,gBACA;AAAA,cAAA;AAAA,cAED,GAAG;AAAA,YAAA;AAAA,UAAA;AAAA,UAGL,cACCK,2BAAAA,KAAC,OAAA,EAAI,WAAU,wBACb,UAAA;AAAA,YAAAL,2BAAAA,IAACS,OAAAA,QAAA,EAAO,SAAQ,aAAY,MAAK,MAAK,WAAU,UAAS,SAAS,UAC/D,UAAA,YAAA,CACH;AAAA,YACAT,2BAAAA,IAACS,OAAAA,QAAA,EAAO,SAAQ,WAAU,MAAK,MAAK,WAAU,UAAS,SAAS,SAC7D,UAAA,WAAA,CACH;AAAA,UAAA,EAAA,CACF;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,WAAW,cAAc;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Divider.cjs","sources":["../../../../src/components/Divider/Divider.tsx"],"sourcesContent":["import * as SeparatorPrimitive from \"@radix-ui/react-separator\";\nimport * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\n\nexport type DividerOrientation = \"horizontal\" | \"vertical\";\nexport type DividerType = \"default\" | \"text\";\n\nexport interface DividerProps\n extends React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root> {\n /** Custom label to display*/\n label?: string;\n}\n\nexport const Divider = React.forwardRef<\n React.ElementRef<typeof SeparatorPrimitive.Root>,\n DividerProps\n>(({ label, className, ...props }, ref) => {\n if (label !== undefined) {\n return (\n <div\n ref={ref}\n className={cn(`my-2 flex w-full items-center justify-center gap-2`, className)}\n >\n <SeparatorPrimitive.Root\n decorative\n orientation=\"horizontal\"\n className=\"h-px flex-1 bg-neutral-200\"\n {...props}\n />\n <span className=\"typography-body-2-regular shrink-0 text-body-100\">{label}</span>\n <SeparatorPrimitive.Root\n decorative\n orientation=\"horizontal\"\n className=\"h-px flex-1 bg-neutral-200\"\n />\n </div>\n );\n }\n\n return (\n <SeparatorPrimitive.Root\n ref={ref}\n decorative\n orientation=\"horizontal\"\n className={cn(`mx-auto my-2 h-px w-full bg-neutral-200`, className)}\n {...props}\n />\n );\n});\n\nDivider.displayName = \"Divider\";\n"],"names":["React","jsxs","cn","jsx","SeparatorPrimitive"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAaO,MAAM,UAAUA,iBAAM,WAG3B,CAAC,EAAE,OAAO,WAAW,GAAG,MAAA,GAAS,QAAQ;AACzC,MAAI,UAAU,QAAW;AACvB,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWC,GAAAA,GAAG,sDAAsD,SAAS;AAAA,QAE7E,UAAA;AAAA,UAAAC,2BAAAA;AAAAA,YAACC,8BAAmB;AAAA,YAAnB;AAAA,cACC,YAAU;AAAA,cACV,aAAY;AAAA,cACZ,WAAU;AAAA,cACT,GAAG;AAAA,YAAA;AAAA,UAAA;AAAA,UAEND,2BAAAA,IAAC,QAAA,EAAK,WAAU,oDAAoD,UAAA,OAAM;AAAA,UAC1EA,2BAAAA;AAAAA,YAACC,8BAAmB;AAAA,YAAnB;AAAA,cACC,YAAU;AAAA,cACV,aAAY;AAAA,cACZ,WAAU;AAAA,YAAA;AAAA,UAAA;AAAA,QACZ;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AAEA,SACED,2BAAAA;AAAAA,IAACC,8BAAmB;AAAA,IAAnB;AAAA,MACC;AAAA,MACA,YAAU;AAAA,MACV,aAAY;AAAA,MACZ,WAAWF,GAAAA,GAAG,2CAA2C,SAAS;AAAA,MACjE,GAAG;AAAA,IAAA;AAAA,EAAA;AAGV,CAAC;AAED,QAAQ,cAAc;;"}
1
+ {"version":3,"file":"Divider.cjs","sources":["../../../../src/components/Divider/Divider.tsx"],"sourcesContent":["import * as SeparatorPrimitive from \"@radix-ui/react-separator\";\nimport * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\n\n/** Orientation of the divider line. */\nexport type DividerOrientation = \"horizontal\" | \"vertical\";\n\nexport interface DividerProps\n extends React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root> {\n /** Optional centred label text. When provided, the divider renders as two lines with the label between them. */\n label?: string;\n}\n\n/**\n * A horizontal separator used to divide content sections. Optionally displays a\n * centred text label between two lines.\n *\n * @example\n * ```tsx\n * <Divider />\n * <Divider label=\"or\" />\n * ```\n */\nexport const Divider = React.forwardRef<\n React.ElementRef<typeof SeparatorPrimitive.Root>,\n DividerProps\n>(({ label, className, ...props }, ref) => {\n if (label !== undefined) {\n return (\n <div\n ref={ref}\n className={cn(`my-2 flex w-full items-center justify-center gap-2`, className)}\n >\n <SeparatorPrimitive.Root\n decorative\n orientation=\"horizontal\"\n className=\"h-px flex-1 bg-neutral-200\"\n {...props}\n />\n <span className=\"typography-body-2-regular shrink-0 text-body-100\">{label}</span>\n <SeparatorPrimitive.Root\n decorative\n orientation=\"horizontal\"\n className=\"h-px flex-1 bg-neutral-200\"\n />\n </div>\n );\n }\n\n return (\n <SeparatorPrimitive.Root\n ref={ref}\n decorative\n orientation=\"horizontal\"\n className={cn(`mx-auto my-2 h-px w-full bg-neutral-200`, className)}\n {...props}\n />\n );\n});\n\nDivider.displayName = \"Divider\";\n"],"names":["React","jsxs","cn","jsx","SeparatorPrimitive"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAuBO,MAAM,UAAUA,iBAAM,WAG3B,CAAC,EAAE,OAAO,WAAW,GAAG,MAAA,GAAS,QAAQ;AACzC,MAAI,UAAU,QAAW;AACvB,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWC,GAAAA,GAAG,sDAAsD,SAAS;AAAA,QAE7E,UAAA;AAAA,UAAAC,2BAAAA;AAAAA,YAACC,8BAAmB;AAAA,YAAnB;AAAA,cACC,YAAU;AAAA,cACV,aAAY;AAAA,cACZ,WAAU;AAAA,cACT,GAAG;AAAA,YAAA;AAAA,UAAA;AAAA,UAEND,2BAAAA,IAAC,QAAA,EAAK,WAAU,oDAAoD,UAAA,OAAM;AAAA,UAC1EA,2BAAAA;AAAAA,YAACC,8BAAmB;AAAA,YAAnB;AAAA,cACC,YAAU;AAAA,cACV,aAAY;AAAA,cACZ,WAAU;AAAA,YAAA;AAAA,UAAA;AAAA,QACZ;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AAEA,SACED,2BAAAA;AAAAA,IAACC,8BAAmB;AAAA,IAAnB;AAAA,MACC;AAAA,MACA,YAAU;AAAA,MACV,aAAY;AAAA,MACZ,WAAWF,GAAAA,GAAG,2CAA2C,SAAS;AAAA,MACjE,GAAG;AAAA,IAAA;AAAA,EAAA;AAGV,CAAC;AAED,QAAQ,cAAc;;"}
@@ -23,16 +23,16 @@ function _interopNamespaceDefault(e) {
23
23
  }
24
24
  const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
25
25
  const iconButtonVariants = {
26
- primary: "bg-neutral-400 text-body-300 hover:bg-hover-100 disabled:opacity-50 focus-visible:shadow-focus-ring",
27
- secondary: "bg-neutral-100 text-neutral-400 hover:bg-neutral-200 disabled:opacity-50 focus-visible:shadow-focus-ring",
28
- tertiary: "bg-transparent text-neutral-400 hover:bg-hover-300 disabled:opacity-50 focus-visible:shadow-focus-ring active:bg-brand-green-50",
29
- brand: "bg-body-black-solid-constant text-brand-green-500 hover:bg-brand-green-500 hover:text-body-black-solid-constant disabled:opacity-50 focus-visible:shadow-focus-ring",
30
- contrast: "bg-transparent text-body-white-solid-constant disabled:opacity-50 focus-visible:shadow-focus-ring",
31
- messaging: "bg-body-black-solid-constant text-brand-green-500 hover:bg-brand-green-500 hover:text-body-black-solid-constant disabled:opacity-50 focus-visible:shadow-focus-ring",
32
- navTray: "bg-transparent text-neutral-400 disabled:opacity-50 focus-visible:shadow-focus-ring active:bg-brand-green-50",
33
- tertiaryDestructive: "bg-transparent text-error-500 hover:bg-hover-300 disabled:opacity-50 focus-visible:shadow-focus-ring",
34
- stop: "bg-neutral-400 text-body-300 hover:bg-brand-green-500 hover:text-body-black-solid-constant disabled:opacity-50 focus-visible:shadow-focus-ring",
35
- microphone: "bg-neutral-400 text-body-300 hover:bg-brand-green-500 hover:text-body-black-solid-constant disabled:opacity-50 focus-visible:shadow-focus-ring"
26
+ primary: "bg-neutral-400 text-body-300 hover:bg-hover-100 not-disabled:active:bg-hover-100 disabled:opacity-50 focus-visible:shadow-focus-ring",
27
+ secondary: "bg-neutral-100 text-neutral-400 hover:bg-neutral-200 not-disabled:active:bg-neutral-200 disabled:opacity-50 focus-visible:shadow-focus-ring",
28
+ tertiary: "bg-transparent text-neutral-400 hover:bg-hover-300 not-disabled:active:bg-brand-green-50 disabled:opacity-50 focus-visible:shadow-focus-ring",
29
+ brand: "bg-body-black-solid-constant text-brand-green-500 hover:bg-brand-green-500 hover:text-body-black-solid-constant not-disabled:active:bg-brand-green-500 not-disabled:active:text-body-black-solid-constant disabled:opacity-50 focus-visible:shadow-focus-ring",
30
+ contrast: "bg-transparent text-body-white-solid-constant hover:bg-hover-300 not-disabled:active:bg-hover-300 disabled:opacity-50 focus-visible:shadow-focus-ring",
31
+ messaging: "bg-body-black-solid-constant text-brand-green-500 hover:bg-brand-green-500 hover:text-body-black-solid-constant not-disabled:active:bg-brand-green-500 not-disabled:active:text-body-black-solid-constant disabled:opacity-50 focus-visible:shadow-focus-ring",
32
+ navTray: "bg-transparent text-neutral-400 hover:bg-hover-300 not-disabled:active:bg-brand-green-50 disabled:opacity-50 focus-visible:shadow-focus-ring",
33
+ tertiaryDestructive: "bg-transparent text-error-500 hover:bg-hover-300 not-disabled:active:bg-hover-300 disabled:opacity-50 focus-visible:shadow-focus-ring",
34
+ stop: "bg-neutral-400 text-body-300 hover:bg-brand-green-500 hover:text-body-black-solid-constant not-disabled:active:bg-brand-green-500 not-disabled:active:text-body-black-solid-constant disabled:opacity-50 focus-visible:shadow-focus-ring",
35
+ microphone: "bg-neutral-400 text-body-300 hover:bg-brand-green-500 hover:text-body-black-solid-constant not-disabled:active:bg-brand-green-500 not-disabled:active:text-body-black-solid-constant disabled:opacity-50 focus-visible:shadow-focus-ring"
36
36
  };
37
37
  const iconSizeVariants = {
38
38
  24: "[&>svg]:size-4",
@@ -1 +1 @@
1
- {"version":3,"file":"IconButton.cjs","sources":["../../../../src/components/IconButton/IconButton.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Count } from \"../Count/Count\";\n\nconst iconButtonVariants = {\n primary:\n \"bg-neutral-400 text-body-300 hover:bg-hover-100 disabled:opacity-50 focus-visible:shadow-focus-ring\",\n secondary:\n \"bg-neutral-100 text-neutral-400 hover:bg-neutral-200 disabled:opacity-50 focus-visible:shadow-focus-ring\",\n tertiary:\n \"bg-transparent text-neutral-400 hover:bg-hover-300 disabled:opacity-50 focus-visible:shadow-focus-ring active:bg-brand-green-50\",\n brand:\n \"bg-body-black-solid-constant text-brand-green-500 hover:bg-brand-green-500 hover:text-body-black-solid-constant disabled:opacity-50 focus-visible:shadow-focus-ring\",\n contrast:\n \"bg-transparent text-body-white-solid-constant disabled:opacity-50 focus-visible:shadow-focus-ring\",\n messaging:\n \"bg-body-black-solid-constant text-brand-green-500 hover:bg-brand-green-500 hover:text-body-black-solid-constant disabled:opacity-50 focus-visible:shadow-focus-ring\",\n navTray:\n \"bg-transparent text-neutral-400 disabled:opacity-50 focus-visible:shadow-focus-ring active:bg-brand-green-50\",\n tertiaryDestructive:\n \"bg-transparent text-error-500 hover:bg-hover-300 disabled:opacity-50 focus-visible:shadow-focus-ring\",\n stop: \"bg-neutral-400 text-body-300 hover:bg-brand-green-500 hover:text-body-black-solid-constant disabled:opacity-50 focus-visible:shadow-focus-ring\",\n microphone:\n \"bg-neutral-400 text-body-300 hover:bg-brand-green-500 hover:text-body-black-solid-constant disabled:opacity-50 focus-visible:shadow-focus-ring\",\n};\n\nconst iconSizeVariants = {\n 24: \"[&>svg]:size-4\",\n 32: \"[&>svg]:size-5\",\n 40: \"[&>svg]:size-6\",\n 52: \"[&>svg]:size-7\",\n 72: \"[&>svg]:size-8\",\n} as const;\n\nconst sizeVariants = {\n 24: \"p-1\",\n 32: \"p-1.5\",\n 40: \"p-[10px]\",\n 52: \"p-2\",\n 72: \"p-4\",\n} as const;\n\nexport type IconButtonVariant =\n | \"primary\"\n | \"secondary\"\n | \"tertiary\"\n | \"brand\"\n | \"contrast\"\n | \"messaging\"\n | \"navTray\"\n | \"tertiaryDestructive\"\n | \"stop\"\n | \"microphone\";\n\nexport type IconButtonSize = \"24\" | \"32\" | \"40\" | \"52\" | \"72\";\n\nexport interface IconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Visual style variant of the icon button */\n variant?: IconButtonVariant;\n /** Size of the button */\n size?: IconButtonSize;\n /** Icon element to display */\n icon: React.ReactNode;\n /** Counter value to display */\n counterValue?: number;\n}\n\nexport const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(\n (\n { className, variant = \"primary\", size = \"40\", icon, counterValue, disabled = false, ...props },\n ref,\n ) => {\n if (process.env.NODE_ENV !== \"production\") {\n if (!props[\"aria-label\"] && !props[\"aria-labelledby\"] && !props.title) {\n console.warn(\n \"IconButton: No accessible name provided. Add an `aria-label`, `aria-labelledby`, or `title` prop so screen readers can announce this button.\",\n );\n }\n }\n\n return (\n <button\n ref={ref}\n type=\"button\"\n data-testid=\"icon-button\"\n disabled={disabled}\n className={cn(\n // Base styles\n \"relative inline-flex shrink-0 items-center justify-center focus-visible:outline-none\",\n \"cursor-pointer rounded-full transition-all duration-150 ease-in-out disabled:cursor-default\",\n // Size variants\n sizeVariants[size],\n // Variant styles\n iconButtonVariants[variant],\n // Manual CSS overrides\n className,\n )}\n {...props}\n >\n <span\n className={cn(\"flex shrink-0 items-center justify-center\", iconSizeVariants[size])}\n aria-hidden=\"true\"\n >\n {icon}\n </span>\n\n {counterValue !== undefined && (variant === \"tertiary\" || variant === \"navTray\") && (\n <div className=\"absolute top-0 right-0\">\n <Count value={counterValue} />\n </div>\n )}\n </button>\n );\n },\n);\n\nIconButton.displayName = \"IconButton\";\n"],"names":["React","jsxs","cn","jsx","Count"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAIA,MAAM,qBAAqB;AAAA,EACzB,SACE;AAAA,EACF,WACE;AAAA,EACF,UACE;AAAA,EACF,OACE;AAAA,EACF,UACE;AAAA,EACF,WACE;AAAA,EACF,SACE;AAAA,EACF,qBACE;AAAA,EACF,MAAM;AAAA,EACN,YACE;AACJ;AAEA,MAAM,mBAAmB;AAAA,EACvB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAEA,MAAM,eAAe;AAAA,EACnB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AA2BO,MAAM,aAAaA,iBAAM;AAAA,EAC9B,CACE,EAAE,WAAW,UAAU,WAAW,OAAO,MAAM,MAAM,cAAc,WAAW,OAAO,GAAG,MAAA,GACxF,QACG;AACH,QAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,UAAI,CAAC,MAAM,YAAY,KAAK,CAAC,MAAM,iBAAiB,KAAK,CAAC,MAAM,OAAO;AACrE,gBAAQ;AAAA,UACN;AAAA,QAAA;AAAA,MAEJ;AAAA,IACF;AAEA,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,eAAY;AAAA,QACZ;AAAA,QACA,WAAWC,GAAAA;AAAAA;AAAAA,UAET;AAAA,UACA;AAAA;AAAA,UAEA,aAAa,IAAI;AAAA;AAAA,UAEjB,mBAAmB,OAAO;AAAA;AAAA,UAE1B;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAAC,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAWD,GAAAA,GAAG,6CAA6C,iBAAiB,IAAI,CAAC;AAAA,cACjF,eAAY;AAAA,cAEX,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGF,iBAAiB,WAAc,YAAY,cAAc,YAAY,cACpEC,2BAAAA,IAAC,OAAA,EAAI,WAAU,0BACb,UAAAA,2BAAAA,IAACC,MAAAA,OAAA,EAAM,OAAO,cAAc,EAAA,CAC9B;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,WAAW,cAAc;;"}
1
+ {"version":3,"file":"IconButton.cjs","sources":["../../../../src/components/IconButton/IconButton.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Count } from \"../Count/Count\";\n\nconst iconButtonVariants = {\n primary:\n \"bg-neutral-400 text-body-300 hover:bg-hover-100 not-disabled:active:bg-hover-100 disabled:opacity-50 focus-visible:shadow-focus-ring\",\n secondary:\n \"bg-neutral-100 text-neutral-400 hover:bg-neutral-200 not-disabled:active:bg-neutral-200 disabled:opacity-50 focus-visible:shadow-focus-ring\",\n tertiary:\n \"bg-transparent text-neutral-400 hover:bg-hover-300 not-disabled:active:bg-brand-green-50 disabled:opacity-50 focus-visible:shadow-focus-ring\",\n brand:\n \"bg-body-black-solid-constant text-brand-green-500 hover:bg-brand-green-500 hover:text-body-black-solid-constant not-disabled:active:bg-brand-green-500 not-disabled:active:text-body-black-solid-constant disabled:opacity-50 focus-visible:shadow-focus-ring\",\n contrast:\n \"bg-transparent text-body-white-solid-constant hover:bg-hover-300 not-disabled:active:bg-hover-300 disabled:opacity-50 focus-visible:shadow-focus-ring\",\n messaging:\n \"bg-body-black-solid-constant text-brand-green-500 hover:bg-brand-green-500 hover:text-body-black-solid-constant not-disabled:active:bg-brand-green-500 not-disabled:active:text-body-black-solid-constant disabled:opacity-50 focus-visible:shadow-focus-ring\",\n navTray:\n \"bg-transparent text-neutral-400 hover:bg-hover-300 not-disabled:active:bg-brand-green-50 disabled:opacity-50 focus-visible:shadow-focus-ring\",\n tertiaryDestructive:\n \"bg-transparent text-error-500 hover:bg-hover-300 not-disabled:active:bg-hover-300 disabled:opacity-50 focus-visible:shadow-focus-ring\",\n stop: \"bg-neutral-400 text-body-300 hover:bg-brand-green-500 hover:text-body-black-solid-constant not-disabled:active:bg-brand-green-500 not-disabled:active:text-body-black-solid-constant disabled:opacity-50 focus-visible:shadow-focus-ring\",\n microphone:\n \"bg-neutral-400 text-body-300 hover:bg-brand-green-500 hover:text-body-black-solid-constant not-disabled:active:bg-brand-green-500 not-disabled:active:text-body-black-solid-constant disabled:opacity-50 focus-visible:shadow-focus-ring\",\n};\n\nconst iconSizeVariants = {\n 24: \"[&>svg]:size-4\",\n 32: \"[&>svg]:size-5\",\n 40: \"[&>svg]:size-6\",\n 52: \"[&>svg]:size-7\",\n 72: \"[&>svg]:size-8\",\n} as const;\n\nconst sizeVariants = {\n 24: \"p-1\",\n 32: \"p-1.5\",\n 40: \"p-[10px]\",\n 52: \"p-2\",\n 72: \"p-4\",\n} as const;\n\n/** Visual style variant of the icon button. */\nexport type IconButtonVariant =\n | \"primary\"\n | \"secondary\"\n | \"tertiary\"\n | \"brand\"\n | \"contrast\"\n | \"messaging\"\n | \"navTray\"\n | \"tertiaryDestructive\"\n | \"stop\"\n | \"microphone\";\n\n/** Icon button size in pixels. */\nexport type IconButtonSize = \"24\" | \"32\" | \"40\" | \"52\" | \"72\";\n\nexport interface IconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Visual style variant of the icon button. @default \"primary\" */\n variant?: IconButtonVariant;\n /** Size of the button in pixels. @default \"40\" */\n size?: IconButtonSize;\n /** Icon element to render inside the button. */\n icon: React.ReactNode;\n /** When provided, displays a {@link Count} badge at the top-right corner (tertiary & navTray variants only). */\n counterValue?: number;\n}\n\n/**\n * A circular button containing only an icon. Use when an action can be\n * represented by an icon alone (e.g. close, send, mic). Pair with an\n * `aria-label` for accessibility.\n *\n * @example\n * ```tsx\n * <IconButton icon={<CloseIcon />} aria-label=\"Close\" variant=\"tertiary\" />\n * ```\n */\nexport const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(\n (\n { className, variant = \"primary\", size = \"40\", icon, counterValue, disabled = false, ...props },\n ref,\n ) => {\n if (process.env.NODE_ENV !== \"production\") {\n if (!props[\"aria-label\"] && !props[\"aria-labelledby\"] && !props.title) {\n console.warn(\n \"IconButton: No accessible name provided. Add an `aria-label`, `aria-labelledby`, or `title` prop so screen readers can announce this button.\",\n );\n }\n }\n\n return (\n <button\n ref={ref}\n type=\"button\"\n data-testid=\"icon-button\"\n disabled={disabled}\n className={cn(\n // Base styles\n \"relative inline-flex shrink-0 items-center justify-center focus-visible:outline-none\",\n \"cursor-pointer rounded-full transition-all duration-150 ease-in-out disabled:cursor-default\",\n // Size variants\n sizeVariants[size],\n // Variant styles\n iconButtonVariants[variant],\n // Manual CSS overrides\n className,\n )}\n {...props}\n >\n <span\n className={cn(\"flex shrink-0 items-center justify-center\", iconSizeVariants[size])}\n aria-hidden=\"true\"\n >\n {icon}\n </span>\n\n {counterValue !== undefined && (variant === \"tertiary\" || variant === \"navTray\") && (\n <div className=\"absolute top-0 right-0\">\n <Count value={counterValue} />\n </div>\n )}\n </button>\n );\n },\n);\n\nIconButton.displayName = \"IconButton\";\n"],"names":["React","jsxs","cn","jsx","Count"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAIA,MAAM,qBAAqB;AAAA,EACzB,SACE;AAAA,EACF,WACE;AAAA,EACF,UACE;AAAA,EACF,OACE;AAAA,EACF,UACE;AAAA,EACF,WACE;AAAA,EACF,SACE;AAAA,EACF,qBACE;AAAA,EACF,MAAM;AAAA,EACN,YACE;AACJ;AAEA,MAAM,mBAAmB;AAAA,EACvB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAEA,MAAM,eAAe;AAAA,EACnB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAuCO,MAAM,aAAaA,iBAAM;AAAA,EAC9B,CACE,EAAE,WAAW,UAAU,WAAW,OAAO,MAAM,MAAM,cAAc,WAAW,OAAO,GAAG,MAAA,GACxF,QACG;AACH,QAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,UAAI,CAAC,MAAM,YAAY,KAAK,CAAC,MAAM,iBAAiB,KAAK,CAAC,MAAM,OAAO;AACrE,gBAAQ;AAAA,UACN;AAAA,QAAA;AAAA,MAEJ;AAAA,IACF;AAEA,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,eAAY;AAAA,QACZ;AAAA,QACA,WAAWC,GAAAA;AAAAA;AAAAA,UAET;AAAA,UACA;AAAA;AAAA,UAEA,aAAa,IAAI;AAAA;AAAA,UAEjB,mBAAmB,OAAO;AAAA;AAAA,UAE1B;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAAC,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAWD,GAAAA,GAAG,6CAA6C,iBAAiB,IAAI,CAAC;AAAA,cACjF,eAAY;AAAA,cAEX,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGF,iBAAiB,WAAc,YAAY,cAAc,YAAY,cACpEC,2BAAAA,IAAC,OAAA,EAAI,WAAU,0BACb,UAAAA,2BAAAA,IAACC,MAAAA,OAAA,EAAM,OAAO,cAAc,EAAA,CAC9B;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,WAAW,cAAc;;"}