@brainfish-ai/components 0.35.7 → 0.35.9

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 (127) hide show
  1. package/dist/esm/chunks/{ChatSearch.D5IYAnPQ.js → ChatSearch.qg_5DlLP.js} +8 -8
  2. package/dist/esm/chunks/ChatSearch.qg_5DlLP.js.map +1 -0
  3. package/dist/esm/chunks/{Conversation.Dq66Znf4.js → Conversation.CfhUJm_Q.js} +2 -2
  4. package/dist/esm/chunks/{Conversation.Dq66Znf4.js.map → Conversation.CfhUJm_Q.js.map} +1 -1
  5. package/dist/esm/chunks/{FormattedMessage.Djy5cn5F.js → FormattedMessage.CEEjawib.js} +2 -2
  6. package/dist/esm/chunks/{FormattedMessage.Djy5cn5F.js.map → FormattedMessage.CEEjawib.js.map} +1 -1
  7. package/dist/esm/chunks/{ai-badge.Be0978vU.js → ai-badge.BxsWnJJZ.js} +2 -2
  8. package/dist/esm/chunks/{ai-badge.Be0978vU.js.map → ai-badge.BxsWnJJZ.js.map} +1 -1
  9. package/dist/esm/chunks/{button.Cs1X8upM.js → button.C7qRaFMP.js} +2 -2
  10. package/dist/esm/chunks/{button.Cs1X8upM.js.map → button.C7qRaFMP.js.map} +1 -1
  11. package/dist/esm/chunks/{chart.BDL2tf-S.js → chart.D9xvsrKX.js} +2 -2
  12. package/dist/esm/chunks/{chart.BDL2tf-S.js.map → chart.D9xvsrKX.js.map} +1 -1
  13. package/dist/esm/chunks/{chat-logo.CqPppEb9.js → chat-logo.F_m9SJrM.js} +2 -2
  14. package/dist/esm/chunks/{chat-logo.CqPppEb9.js.map → chat-logo.F_m9SJrM.js.map} +1 -1
  15. package/dist/esm/chunks/{combobox.CLT9CXUV.js → combobox.DKotd4uC.js} +2 -2
  16. package/dist/esm/chunks/{combobox.CLT9CXUV.js.map → combobox.DKotd4uC.js.map} +1 -1
  17. package/dist/esm/chunks/{data-table.bjvbLk2u.js → data-table.1ptJ47z8.js} +2 -2
  18. package/dist/esm/chunks/{data-table.bjvbLk2u.js.map → data-table.1ptJ47z8.js.map} +1 -1
  19. package/dist/esm/chunks/{date-picker.D9CRxYJf.js → date-picker.Bto-A8WE.js} +2 -2
  20. package/dist/esm/chunks/{date-picker.D9CRxYJf.js.map → date-picker.Bto-A8WE.js.map} +1 -1
  21. package/dist/esm/chunks/{feedback.CGFAP0XS.js → feedback.CbCOP40K.js} +2 -2
  22. package/dist/esm/chunks/{feedback.CGFAP0XS.js.map → feedback.CbCOP40K.js.map} +1 -1
  23. package/dist/esm/chunks/{file-upload-status.ClQeoQQB.js → file-upload-status.sUoGRgbH.js} +2 -2
  24. package/dist/esm/chunks/{file-upload-status.ClQeoQQB.js.map → file-upload-status.sUoGRgbH.js.map} +1 -1
  25. package/dist/esm/chunks/{filters.BRlRsGlZ.js → filters.Bxyw3eHZ.js} +2 -2
  26. package/dist/esm/chunks/{filters.BRlRsGlZ.js.map → filters.Bxyw3eHZ.js.map} +1 -1
  27. package/dist/esm/chunks/{font-picker.Dwwe5av-.js → font-picker.CVZovtmt.js} +2 -2
  28. package/dist/esm/chunks/{font-picker.Dwwe5av-.js.map → font-picker.CVZovtmt.js.map} +1 -1
  29. package/dist/esm/chunks/{generating-star.BN9p_FDu.js → generating-star.DN8DVygp.js} +2 -2
  30. package/dist/esm/chunks/{generating-star.BN9p_FDu.js.map → generating-star.DN8DVygp.js.map} +1 -1
  31. package/dist/esm/chunks/{header-nav.BjLSOrkO.js → header-nav.BY2ppP8j.js} +2 -2
  32. package/dist/esm/chunks/{header-nav.BjLSOrkO.js.map → header-nav.BY2ppP8j.js.map} +1 -1
  33. package/dist/esm/chunks/{header-pane.C0x3UKVB.js → header-pane.DCGet3RZ.js} +2 -2
  34. package/dist/esm/chunks/{header-pane.C0x3UKVB.js.map → header-pane.DCGet3RZ.js.map} +1 -1
  35. package/dist/esm/chunks/{hooks.BQTKhHSv.js → hooks.DjDPgQm6.js} +2 -2
  36. package/dist/esm/chunks/hooks.DjDPgQm6.js.map +1 -0
  37. package/dist/esm/chunks/{input-with-tags.pmOKv67d.js → input-with-tags.aktIpAck.js} +2 -2
  38. package/dist/esm/chunks/{input-with-tags.pmOKv67d.js.map → input-with-tags.aktIpAck.js.map} +1 -1
  39. package/dist/esm/chunks/{ripple-status.C20jzXjF.js → ripple-status.BiOlScXz.js} +2 -2
  40. package/dist/esm/chunks/{ripple-status.C20jzXjF.js.map → ripple-status.BiOlScXz.js.map} +1 -1
  41. package/dist/esm/chunks/{sidebar.BUQR4qJs.js → sidebar.tGcs3r4O.js} +2 -2
  42. package/dist/esm/chunks/{sidebar.BUQR4qJs.js.map → sidebar.tGcs3r4O.js.map} +1 -1
  43. package/dist/esm/chunks/{simpleSelect.CEUUfl3O.js → simpleSelect.BiNOqq3j.js} +2 -2
  44. package/dist/esm/chunks/{simpleSelect.CEUUfl3O.js.map → simpleSelect.BiNOqq3j.js.map} +1 -1
  45. package/dist/esm/chunks/{status-badge.Cf3R4nVr.js → status-badge.BVWcC9Dt.js} +2 -2
  46. package/dist/esm/chunks/{status-badge.Cf3R4nVr.js.map → status-badge.BVWcC9Dt.js.map} +1 -1
  47. package/dist/esm/chunks/{suggestion-card.C32KfQa5.js → suggestion-card.DKQAazak.js} +2 -2
  48. package/dist/esm/chunks/{suggestion-card.C32KfQa5.js.map → suggestion-card.DKQAazak.js.map} +1 -1
  49. package/dist/esm/chunks/{trend-value.BPBDBsk2.js → trend-value.lSWHqdkm.js} +2 -2
  50. package/dist/esm/chunks/{trend-value.BPBDBsk2.js.map → trend-value.lSWHqdkm.js.map} +1 -1
  51. package/dist/esm/chunks/{two-level-combobox.SDv7qc_m.js → two-level-combobox.CWKR1tXX.js} +2 -2
  52. package/dist/esm/chunks/{two-level-combobox.SDv7qc_m.js.map → two-level-combobox.CWKR1tXX.js.map} +1 -1
  53. package/dist/esm/chunks/utils.DtKoarLP.js +2 -0
  54. package/dist/esm/chunks/utils.DtKoarLP.js.map +1 -0
  55. package/dist/esm/components/article-suggestions-banner.js +1 -1
  56. package/dist/esm/components/articles-coverage.js +1 -1
  57. package/dist/esm/components/articles-updated.js +1 -1
  58. package/dist/esm/components/chart-area-linear.js +1 -1
  59. package/dist/esm/components/chart-radial-stacked.js +1 -1
  60. package/dist/esm/components/chat-search.js +1 -1
  61. package/dist/esm/components/combobox.js +1 -1
  62. package/dist/esm/components/conversation.js +1 -1
  63. package/dist/esm/components/convos.js +1 -1
  64. package/dist/esm/components/data-table.js +1 -1
  65. package/dist/esm/components/date-picker.js +1 -1
  66. package/dist/esm/components/discoveries-created.js +1 -1
  67. package/dist/esm/components/feedback.js +1 -1
  68. package/dist/esm/components/file-upload.js +1 -1
  69. package/dist/esm/components/filter.js +1 -1
  70. package/dist/esm/components/font-picker.js +1 -1
  71. package/dist/esm/components/generating-star.js +1 -1
  72. package/dist/esm/components/input-with-tags.js +1 -1
  73. package/dist/esm/components/logo.js +1 -1
  74. package/dist/esm/components/markdown.js +1 -1
  75. package/dist/esm/components/metric-card-group.js +1 -1
  76. package/dist/esm/components/metric-card.js +1 -1
  77. package/dist/esm/components/plan-usage-card.js +1 -1
  78. package/dist/esm/components/select.js +1 -1
  79. package/dist/esm/components/trend-value.js +1 -1
  80. package/dist/esm/components/two-level-combobox.js +1 -1
  81. package/dist/esm/components/ui/accordion.js +1 -1
  82. package/dist/esm/components/ui/alert-dialog.js +1 -1
  83. package/dist/esm/components/ui/alert.js +1 -1
  84. package/dist/esm/components/ui/avatar.js +1 -1
  85. package/dist/esm/components/ui/badge.js +1 -1
  86. package/dist/esm/components/ui/breadcrumb.js +1 -1
  87. package/dist/esm/components/ui/button-group.js +1 -1
  88. package/dist/esm/components/ui/button.js +1 -1
  89. package/dist/esm/components/ui/calendar.js +1 -1
  90. package/dist/esm/components/ui/card.js +1 -1
  91. package/dist/esm/components/ui/combobox.js +1 -1
  92. package/dist/esm/components/ui/command.js +1 -1
  93. package/dist/esm/components/ui/dialog.js +1 -1
  94. package/dist/esm/components/ui/div-button.js +1 -1
  95. package/dist/esm/components/ui/dropdown-menu.js +1 -1
  96. package/dist/esm/components/ui/input.js +1 -1
  97. package/dist/esm/components/ui/item.js +1 -1
  98. package/dist/esm/components/ui/label.js +1 -1
  99. package/dist/esm/components/ui/popover.js +1 -1
  100. package/dist/esm/components/ui/progress.js +1 -1
  101. package/dist/esm/components/ui/radio-group.js +1 -1
  102. package/dist/esm/components/ui/resizable.js +1 -1
  103. package/dist/esm/components/ui/scroll-area.js +1 -1
  104. package/dist/esm/components/ui/select.js +1 -1
  105. package/dist/esm/components/ui/separator.js +1 -1
  106. package/dist/esm/components/ui/sheet.js +1 -1
  107. package/dist/esm/components/ui/spinner.js +1 -1
  108. package/dist/esm/components/ui/switch.js +1 -1
  109. package/dist/esm/components/ui/table.js +1 -1
  110. package/dist/esm/components/ui/tabs.js +1 -1
  111. package/dist/esm/components/ui/textarea.js +1 -1
  112. package/dist/esm/components/ui/tooltip.js +1 -1
  113. package/dist/esm/global.css +1 -1
  114. package/dist/esm/index.js +1 -1
  115. package/dist/esm/layouts/full-layout.js +1 -1
  116. package/dist/esm/layouts/header-nav.js +1 -1
  117. package/dist/esm/layouts/sidebar.js +1 -1
  118. package/dist/esm/logos/microsoft-logo.js +1 -1
  119. package/dist/esm/logos/microsoft-teams-logo.js +1 -1
  120. package/dist/esm/logos/slack-logo.js +1 -1
  121. package/dist/esm/scenes/knowledge-review.js +1 -1
  122. package/dist/stats.html +1 -1
  123. package/package.json +1 -1
  124. package/dist/esm/chunks/ChatSearch.D5IYAnPQ.js.map +0 -1
  125. package/dist/esm/chunks/hooks.BQTKhHSv.js.map +0 -1
  126. package/dist/esm/chunks/utils.C6Qu-kwd.js +0 -2
  127. package/dist/esm/chunks/utils.C6Qu-kwd.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"file-upload-status.ClQeoQQB.js","sources":["../../../src/components/file-upload/utils.tsx","../../../src/components/file-upload/file-upload.tsx","../../../src/components/file-upload/file-upload-status.tsx"],"sourcesContent":["export const formatFileSize = (bytes: number) => {\n if (bytes === 0) return '0 Bytes';\n const k = 1024;\n const sizes = ['Bytes', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n};\n","import React from 'react';\nimport { useDropzone } from 'react-dropzone';\nimport { CloudArrowUp } from '@phosphor-icons/react';\n\nimport type { FileUploadProps } from './types';\nimport { formatFileSize } from './utils';\n\nimport { Card } from '@/components/ui/card';\nimport { cn } from '@/lib/utils';\n\nexport function FileUpload({\n onDropAccepted,\n onDropRejected,\n accept = {\n 'image/*': ['.png', '.jpg', '.jpeg', '.gif', '.mp4'],\n 'application/pdf': ['.pdf'],\n 'text/*': ['.txt', '.csv'],\n },\n maxSize = 5 * 1024 * 1024, // 5MB\n maxFiles = 5,\n multiple = true,\n className,\n disabled = false,\n title = 'Drag & drop files here, or click to select',\n description = '',\n supportsMessage = '',\n children,\n}: FileUploadProps) {\n const { getRootProps, getInputProps, isDragActive, isDragReject } = useDropzone({\n onDropAccepted,\n onDropRejected,\n accept,\n maxSize,\n multiple,\n disabled,\n maxFiles,\n });\n\n return (\n <div data-testid=\"file-upload\" className=\"w-full space-y-4\">\n <div className={cn('group', className, 'focus-visible:outline-none')} {...getRootProps()}>\n <Card\n className={cn(\n 'custom-dashed-border shadow-none p-8 text-center cursor-pointer',\n 'group-focus:custom-dashed-border-hover',\n 'group-hover:custom-dashed-border-hover',\n isDragActive && !isDragReject && 'border-primary bg-primary/5',\n isDragReject && 'border-destructive bg-destructive/5',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n >\n <input {...getInputProps()} />\n <div className=\"flex flex-col items-center gap-4\">\n <CloudArrowUp\n className={cn(\n 'size-12',\n isDragActive && !isDragReject && 'text-primary',\n isDragReject && 'text-destructive',\n )}\n />\n <div className=\"space-y-2\">\n <p className=\"text-lg font-medium\">\n {isDragActive ? (isDragReject ? 'Some files will be rejected' : 'Drop files here') : title}\n </p>\n {description && <p className=\"text-sm\">{description}</p>}\n {supportsMessage ? (\n <p className=\"text-sm\">{supportsMessage}</p>\n ) : (\n <p className=\"text-sm\">\n {`Supports: ${Object.values(accept).flat().join(', ')} • Max size: ${formatFileSize(maxSize)}${\n maxFiles > 1 ? ` • Max files: ${maxFiles}` : ''\n }`}\n </p>\n )}\n </div>\n </div>\n </Card>\n </div>\n {children}\n </div>\n );\n}\n","import React, { useState, useEffect, useCallback } from 'react';\nimport { createPortal } from 'react-dom';\nimport { CaretUp, CaretDown, FileVideo, CheckCircle, Circle } from '@phosphor-icons/react';\n\nimport type { UploadState } from './types';\nimport { formatFileSize } from './utils';\n\nimport { Card, CardContent } from '@/components/ui/card';\nimport { Button } from '@/components/ui/button';\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';\nimport { cn } from '@/lib/utils';\n\nexport interface ProcessingStep {\n id: string;\n label: string;\n status: 'completed' | 'current' | 'pending' | 'error';\n}\n\ninterface FileUploadStatusProps {\n uploads: UploadState[];\n className?: string;\n timeRemaining?: string;\n onCancelUpload?: (e: React.MouseEvent<HTMLButtonElement>) => void;\n steps?: ProcessingStep[];\n title?: string;\n}\n\nconst CheckCircleIcon = React.memo<{ className?: string }>(({ className }) => {\n return (\n <div className={cn('relative', className)}>\n <CheckCircle className=\"absolute size-6 text-green-400\" weight=\"fill\" />\n <CheckCircle className=\"absolute size-6 text-black\" weight=\"regular\" />\n </div>\n );\n});\n\nCheckCircleIcon.displayName = 'CheckCircleIcon';\n\nexport const FileUploadStatus: React.FC<FileUploadStatusProps> = ({\n uploads,\n className,\n onCancelUpload,\n steps = [\n { id: 'upload', label: 'Uploading video', status: 'current' },\n { id: 'analyze', label: 'Analyzing content', status: 'pending' },\n { id: 'create', label: 'Creating help articles', status: 'pending' },\n ],\n timeRemaining,\n title = 'Video Processing',\n}) => {\n const [mounted, setMounted] = useState(false);\n const [isOpen, setIsOpen] = useState(true);\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n const cancelButtonLabel = useCallback((uploadState: UploadState) => {\n if (uploadState.status === 'success') return 'Uploaded';\n if (uploadState.status === 'error') return 'Retry upload';\n\n return 'Cancel upload';\n }, []);\n\n if (!mounted || uploads.length === 0) return null;\n\n // Ensure we're in a browser environment\n if (typeof document === 'undefined') return null;\n\n const statusCard = (\n <Collapsible\n open={isOpen}\n onOpenChange={setIsOpen}\n className={cn(\n 'fixed bottom-3 right-3 w-96 shadow-lg border z-50 transition-all duration-200 h-auto p-0 gap-4 bg-dark-100 rounded-lg overflow-hidden',\n className,\n )}\n >\n <CollapsibleTrigger asChild>\n <div className=\"flex items-center justify-between py-4 px-6 bg-foreground text-background cursor-pointer\">\n <div className=\"flex flex-col gap-0\">\n <span className=\"font-semibold\">{title}</span>\n {timeRemaining && <span className=\"text-sm text-muted-foreground\">{timeRemaining}</span>}\n </div>\n <Button variant=\"ghost\" size=\"sm\" className=\"size-6 p-0\">\n {isOpen ? <CaretDown className=\"size-4\" /> : <CaretUp className=\"size-4\" />}\n </Button>\n </div>\n </CollapsibleTrigger>\n <CollapsibleContent>\n {uploads.map((upload) => (\n <Card key={upload.id} className={cn('rounded-none p-0')}>\n <CardContent className=\"p-0\">\n {/* File Info */}\n <div className=\"px-6 py-4 border-b\">\n <div className=\"flex items-center gap-4\">\n <div className=\"size-12 bg-yellow-400 border border-dark rounded-lg flex items-center justify-center text-dark shrink-0\">\n <FileVideo className=\"size-6\" />\n </div>\n <div className=\"flex-1 flex flex-col gap-0\">\n <h3 className=\"text-base font-medium flex items-center gap-1 whitespace-nowrap\">\n <span className=\"truncate max-w-56\">{upload.file.name}</span>\n <span className=\"shrink-0\"> • {formatFileSize(upload.file.size)}</span>\n </h3>\n <Button\n variant=\"dark\"\n size=\"sm\"\n className=\"self-start h-6 text-xs bg-foreground text-background\"\n onClick={onCancelUpload}\n data-id={upload.id}\n disabled={upload.status === 'success' || upload.progress === 100}\n data-status={upload.status}\n >\n {cancelButtonLabel(upload)}\n </Button>\n </div>\n </div>\n </div>\n\n {/* Steps */}\n <ol className=\"py-2\">\n {steps.map((step) => (\n <li\n key={step.id}\n className={cn(\n 'flex items-center gap-4 px-6 py-3 relative',\n 'after:absolute after:w-[1px] after:bg-foreground after:top-[38px] after:-bottom-[10px] after:left-[35px]',\n 'last-of-type:after:hidden',\n )}\n >\n {step.status === 'completed' ? (\n <CheckCircleIcon className=\"size-6\" />\n ) : (\n <Circle className=\"size-6\" />\n )}\n <span className=\"flex items-center gap-1\">\n {`${step.label} ${step.id === 'upload' ? `— ${Math.round(upload.progress)}%` : ''}`}\n </span>\n </li>\n ))}\n </ol>\n </CardContent>\n </Card>\n ))}\n </CollapsibleContent>\n </Collapsible>\n );\n\n return createPortal(statusCard, document.body);\n};\n"],"names":["formatFileSize","bytes","i","Math","floor","log","Number","parseFloat","pow","toFixed","FileUpload","onDropAccepted","onDropRejected","accept","maxSize","maxFiles","multiple","className","disabled","title","description","supportsMessage","children","getRootProps","getInputProps","isDragActive","isDragReject","useDropzone","React","createElement","cn","Card","CloudArrowUp","Object","values","flat","join","CheckCircleIcon","memo","CheckCircle","weight","displayName","FileUploadStatus","uploads","onCancelUpload","steps","id","label","status","timeRemaining","mounted","setMounted","useState","isOpen","setIsOpen","useEffect","cancelButtonLabel","useCallback","uploadState","length","document","statusCard","Collapsible","open","onOpenChange","CollapsibleTrigger","asChild","Button","variant","size","CaretDown","CaretUp","CollapsibleContent","map","upload","key","CardContent","FileVideo","file","name","onClick","progress","step","Circle","round","createPortal","body"],"mappings":"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"}
1
+ {"version":3,"file":"file-upload-status.sUoGRgbH.js","sources":["../../../src/components/file-upload/utils.tsx","../../../src/components/file-upload/file-upload.tsx","../../../src/components/file-upload/file-upload-status.tsx"],"sourcesContent":["export const formatFileSize = (bytes: number) => {\n if (bytes === 0) return '0 Bytes';\n const k = 1024;\n const sizes = ['Bytes', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n};\n","import React from 'react';\nimport { useDropzone } from 'react-dropzone';\nimport { CloudArrowUp } from '@phosphor-icons/react';\n\nimport type { FileUploadProps } from './types';\nimport { formatFileSize } from './utils';\n\nimport { Card } from '@/components/ui/card';\nimport { cn } from '@/lib/utils';\n\nexport function FileUpload({\n onDropAccepted,\n onDropRejected,\n accept = {\n 'image/*': ['.png', '.jpg', '.jpeg', '.gif', '.mp4'],\n 'application/pdf': ['.pdf'],\n 'text/*': ['.txt', '.csv'],\n },\n maxSize = 5 * 1024 * 1024, // 5MB\n maxFiles = 5,\n multiple = true,\n className,\n disabled = false,\n title = 'Drag & drop files here, or click to select',\n description = '',\n supportsMessage = '',\n children,\n}: FileUploadProps) {\n const { getRootProps, getInputProps, isDragActive, isDragReject } = useDropzone({\n onDropAccepted,\n onDropRejected,\n accept,\n maxSize,\n multiple,\n disabled,\n maxFiles,\n });\n\n return (\n <div data-testid=\"file-upload\" className=\"w-full space-y-4\">\n <div className={cn('group', className, 'focus-visible:outline-none')} {...getRootProps()}>\n <Card\n className={cn(\n 'custom-dashed-border shadow-none p-8 text-center cursor-pointer',\n 'group-focus:custom-dashed-border-hover',\n 'group-hover:custom-dashed-border-hover',\n isDragActive && !isDragReject && 'border-primary bg-primary/5',\n isDragReject && 'border-destructive bg-destructive/5',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n >\n <input {...getInputProps()} />\n <div className=\"flex flex-col items-center gap-4\">\n <CloudArrowUp\n className={cn(\n 'size-12',\n isDragActive && !isDragReject && 'text-primary',\n isDragReject && 'text-destructive',\n )}\n />\n <div className=\"space-y-2\">\n <p className=\"text-lg font-medium\">\n {isDragActive ? (isDragReject ? 'Some files will be rejected' : 'Drop files here') : title}\n </p>\n {description && <p className=\"text-sm\">{description}</p>}\n {supportsMessage ? (\n <p className=\"text-sm\">{supportsMessage}</p>\n ) : (\n <p className=\"text-sm\">\n {`Supports: ${Object.values(accept).flat().join(', ')} • Max size: ${formatFileSize(maxSize)}${\n maxFiles > 1 ? ` • Max files: ${maxFiles}` : ''\n }`}\n </p>\n )}\n </div>\n </div>\n </Card>\n </div>\n {children}\n </div>\n );\n}\n","import React, { useState, useEffect, useCallback } from 'react';\nimport { createPortal } from 'react-dom';\nimport { CaretUp, CaretDown, FileVideo, CheckCircle, Circle } from '@phosphor-icons/react';\n\nimport type { UploadState } from './types';\nimport { formatFileSize } from './utils';\n\nimport { Card, CardContent } from '@/components/ui/card';\nimport { Button } from '@/components/ui/button';\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';\nimport { cn } from '@/lib/utils';\n\nexport interface ProcessingStep {\n id: string;\n label: string;\n status: 'completed' | 'current' | 'pending' | 'error';\n}\n\ninterface FileUploadStatusProps {\n uploads: UploadState[];\n className?: string;\n timeRemaining?: string;\n onCancelUpload?: (e: React.MouseEvent<HTMLButtonElement>) => void;\n steps?: ProcessingStep[];\n title?: string;\n}\n\nconst CheckCircleIcon = React.memo<{ className?: string }>(({ className }) => {\n return (\n <div className={cn('relative', className)}>\n <CheckCircle className=\"absolute size-6 text-green-400\" weight=\"fill\" />\n <CheckCircle className=\"absolute size-6 text-black\" weight=\"regular\" />\n </div>\n );\n});\n\nCheckCircleIcon.displayName = 'CheckCircleIcon';\n\nexport const FileUploadStatus: React.FC<FileUploadStatusProps> = ({\n uploads,\n className,\n onCancelUpload,\n steps = [\n { id: 'upload', label: 'Uploading video', status: 'current' },\n { id: 'analyze', label: 'Analyzing content', status: 'pending' },\n { id: 'create', label: 'Creating help articles', status: 'pending' },\n ],\n timeRemaining,\n title = 'Video Processing',\n}) => {\n const [mounted, setMounted] = useState(false);\n const [isOpen, setIsOpen] = useState(true);\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n const cancelButtonLabel = useCallback((uploadState: UploadState) => {\n if (uploadState.status === 'success') return 'Uploaded';\n if (uploadState.status === 'error') return 'Retry upload';\n\n return 'Cancel upload';\n }, []);\n\n if (!mounted || uploads.length === 0) return null;\n\n // Ensure we're in a browser environment\n if (typeof document === 'undefined') return null;\n\n const statusCard = (\n <Collapsible\n open={isOpen}\n onOpenChange={setIsOpen}\n className={cn(\n 'fixed bottom-3 right-3 w-96 shadow-lg border z-50 transition-all duration-200 h-auto p-0 gap-4 bg-dark-100 rounded-lg overflow-hidden',\n className,\n )}\n >\n <CollapsibleTrigger asChild>\n <div className=\"flex items-center justify-between py-4 px-6 bg-foreground text-background cursor-pointer\">\n <div className=\"flex flex-col gap-0\">\n <span className=\"font-semibold\">{title}</span>\n {timeRemaining && <span className=\"text-sm text-muted-foreground\">{timeRemaining}</span>}\n </div>\n <Button variant=\"ghost\" size=\"sm\" className=\"size-6 p-0\">\n {isOpen ? <CaretDown className=\"size-4\" /> : <CaretUp className=\"size-4\" />}\n </Button>\n </div>\n </CollapsibleTrigger>\n <CollapsibleContent>\n {uploads.map((upload) => (\n <Card key={upload.id} className={cn('rounded-none p-0')}>\n <CardContent className=\"p-0\">\n {/* File Info */}\n <div className=\"px-6 py-4 border-b\">\n <div className=\"flex items-center gap-4\">\n <div className=\"size-12 bg-yellow-400 border border-dark rounded-lg flex items-center justify-center text-dark shrink-0\">\n <FileVideo className=\"size-6\" />\n </div>\n <div className=\"flex-1 flex flex-col gap-0\">\n <h3 className=\"text-base font-medium flex items-center gap-1 whitespace-nowrap\">\n <span className=\"truncate max-w-56\">{upload.file.name}</span>\n <span className=\"shrink-0\"> • {formatFileSize(upload.file.size)}</span>\n </h3>\n <Button\n variant=\"dark\"\n size=\"sm\"\n className=\"self-start h-6 text-xs bg-foreground text-background\"\n onClick={onCancelUpload}\n data-id={upload.id}\n disabled={upload.status === 'success' || upload.progress === 100}\n data-status={upload.status}\n >\n {cancelButtonLabel(upload)}\n </Button>\n </div>\n </div>\n </div>\n\n {/* Steps */}\n <ol className=\"py-2\">\n {steps.map((step) => (\n <li\n key={step.id}\n className={cn(\n 'flex items-center gap-4 px-6 py-3 relative',\n 'after:absolute after:w-[1px] after:bg-foreground after:top-[38px] after:-bottom-[10px] after:left-[35px]',\n 'last-of-type:after:hidden',\n )}\n >\n {step.status === 'completed' ? (\n <CheckCircleIcon className=\"size-6\" />\n ) : (\n <Circle className=\"size-6\" />\n )}\n <span className=\"flex items-center gap-1\">\n {`${step.label} ${step.id === 'upload' ? `— ${Math.round(upload.progress)}%` : ''}`}\n </span>\n </li>\n ))}\n </ol>\n </CardContent>\n </Card>\n ))}\n </CollapsibleContent>\n </Collapsible>\n );\n\n return createPortal(statusCard, document.body);\n};\n"],"names":["formatFileSize","bytes","i","Math","floor","log","Number","parseFloat","pow","toFixed","FileUpload","onDropAccepted","onDropRejected","accept","maxSize","maxFiles","multiple","className","disabled","title","description","supportsMessage","children","getRootProps","getInputProps","isDragActive","isDragReject","useDropzone","React","createElement","cn","Card","CloudArrowUp","Object","values","flat","join","CheckCircleIcon","memo","CheckCircle","weight","displayName","FileUploadStatus","uploads","onCancelUpload","steps","id","label","status","timeRemaining","mounted","setMounted","useState","isOpen","setIsOpen","useEffect","cancelButtonLabel","useCallback","uploadState","length","document","statusCard","Collapsible","open","onOpenChange","CollapsibleTrigger","asChild","Button","variant","size","CaretDown","CaretUp","CollapsibleContent","map","upload","key","CardContent","FileVideo","file","name","onClick","progress","step","Circle","round","createPortal","body"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import e,{useRef as t,useState as l,forwardRef as r,useImperativeHandle as a,useEffect as n}from"react";import{Check as o,XCircle as s,Plus as c}from"@phosphor-icons/react";import{createId as u}from"@paralleldrive/cuid2";import{B as i}from"./button.Cs1X8upM.js";import{Input as m}from"../components/ui/input.js";import{ButtonGroup as d}from"../components/ui/button-group.js";import{DropdownMenu as p,DropdownMenuTrigger as f,DropdownMenuContent as v,DropdownMenuItem as b}from"../components/ui/dropdown-menu.js";import{Popover as g,PopoverTrigger as h,PopoverContent as E}from"../components/ui/popover.js";import{c as y}from"./utils.C6Qu-kwd.js";var N=/* @__PURE__ */(e=>(e.IS="is",e.IS_NOT="is not",e.CONTAINS="contains",e.DOES_NOT_CONTAIN="does not contain",e.STARTS_WITH="starts with",e))(N||{});const S=({inputValue:l,setInputValue:r,customValuePlaceholder:a,customValueButtonLabel:n,onSubmit:o,handleKeyDown:s})=>{const c=t(null);/* @__PURE__ */
1
+ import e,{useRef as t,useState as l,forwardRef as r,useImperativeHandle as a,useEffect as n}from"react";import{Check as o,XCircle as s,Plus as c}from"@phosphor-icons/react";import{createId as u}from"@paralleldrive/cuid2";import{B as i}from"./button.C7qRaFMP.js";import{Input as m}from"../components/ui/input.js";import{ButtonGroup as d}from"../components/ui/button-group.js";import{DropdownMenu as p,DropdownMenuTrigger as f,DropdownMenuContent as v,DropdownMenuItem as b}from"../components/ui/dropdown-menu.js";import{Popover as g,PopoverTrigger as h,PopoverContent as E}from"../components/ui/popover.js";import{c as y}from"./utils.DtKoarLP.js";var N=/* @__PURE__ */(e=>(e.IS="is",e.IS_NOT="is not",e.CONTAINS="contains",e.DOES_NOT_CONTAIN="does not contain",e.STARTS_WITH="starts with",e))(N||{});const S=({inputValue:l,setInputValue:r,customValuePlaceholder:a,customValueButtonLabel:n,onSubmit:o,handleKeyDown:s})=>{const c=t(null);/* @__PURE__ */
2
2
  return e.createElement("form",{className:"p-3",onSubmit:e=>{e.preventDefault(),o()}},
3
3
  /* @__PURE__ */e.createElement(m,{ref:c,type:"text",value:l,onChange:e=>r(e.target.value),placeholder:a,className:"mb-2",onKeyDown:e=>s(e,!0)}),
4
4
  /* @__PURE__ */e.createElement(i,{type:"submit",variant:"dark",className:"w-full",onKeyDown:e=>s(e,!1),"data-custom-submit-button":!0},n))},w=({internalFilter:r,valueOptions:a,onConfirm:n,onClose:s})=>{const[c,u]=l(()=>{return e=r.value,Array.isArray(e)?e:e?[e]:[];var e}),[m,d]=l(""),p=t([]),f=t(null),v=e=>{const t=a.find(t=>t.id===e),l=c.includes(e);u(r=>{const a=r.includes(e)?r.filter(t=>t!==e):[...r,e];if(t){const e=l?"deselected":"selected";d(`${t.label} ${e}.`)}return a})},b=()=>{n(c),s()},g=e=>c.includes(e),h=e=>{e<a.length?p.current[e]?.focus():f.current?.focus()},E=(e,t)=>{switch(e.key){case"ArrowDown":{e.preventDefault();const l=Math.min(t+1,a.length);h(l);break}case"ArrowUp":{e.preventDefault();const l=Math.max(t-1,0);h(l);break}case"Enter":case"Spacebar":e.preventDefault(),t<a.length?v(a[t].id):b();break;case"Escape":e.preventDefault(),s()}};/* @__PURE__ */
@@ -19,4 +19,4 @@ return e.createElement(d,{ref:M,orientation:"horizontal",className:"rounded-full
19
19
  return e.createElement("fieldset",{className:y("flex flex-wrap gap-2",p)},/* @__PURE__ */e.createElement("legend",{className:"sr-only"},"Filters"),f?.map(t=>{const l=m.filter(e=>!g.includes(e.id)||e.id===t.source);/* @__PURE__ */
20
20
  return e.createElement(C,{key:t.id,ref:e=>{b.current[t.id]=e},filter:t,sourceOptions:l,rules:d,onRemoveFilter:()=>(e=>{const t=f.filter(t=>t.id!==e.id);v(t),o(e.id)})(t),onFilterChange:a})}),E&&/* @__PURE__ */e.createElement(i,{onClick:()=>{if(!E)return;const e={id:u(),source:h[0].id,operator:N.IS,value:d[h[0].id]?.multiSelect?[]:""},t=[...f,e];v(t),requestAnimationFrame(()=>{b.current[e.id]?.focus()}),s?.(e)},variant:"ghost",className:"border border-foreground rounded-full gap-1",size:"sm",title:"Add filter"},
21
21
  /* @__PURE__ */e.createElement(c,{size:16}),"Add filter"))};export{C as F,N as O,D as a};
22
- //# sourceMappingURL=filters.BRlRsGlZ.js.map
22
+ //# sourceMappingURL=filters.Bxyw3eHZ.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"filters.BRlRsGlZ.js","sources":["../../../src/components/filter/types.ts","../../../src/components/filter/hooks.ts","../../../src/components/filter/components/CustomValueInput.tsx","../../../src/components/filter/components/MultiSelectDropdown.tsx","../../../src/components/filter/components/SingleSelectDropdown.tsx","../../../src/components/filter/filter.tsx","../../../src/components/filter/filters.tsx"],"sourcesContent":["// Types\nexport interface FilterOption {\n id: string;\n label: string;\n}\n\nexport enum Operator {\n IS = 'is',\n IS_NOT = 'is not',\n CONTAINS = 'contains',\n DOES_NOT_CONTAIN = 'does not contain',\n STARTS_WITH = 'starts with',\n}\n\nexport interface FilterValue {\n id: string | number;\n source?: string;\n operator?: Operator;\n value?: string | string[];\n}\n\n/**\n * Filter rules for each source\n * How this works:\n * - You can define the rules for each source\n * - The rules are used to determine the available operators and value type\n * - The input type is used to determine the type of input displayed in when the dropdown is opened\n * - The getValueOptions function is used to determine the available options for the value\n * - multiSelect determines if multiple values can be selected for dropdown type\n *\n * @example\n * {\n * 'sourceId': {\n * operators: [\n * { id: 'is', label: 'is' },\n * { id: 'is not', label: 'is not' },\n * ],\n * inputType: 'dropdown' | 'custom',\n * multiSelect?: boolean,\n * getValueOptions?: () => FilterOption[],\n * },\n * }\n */\nexport interface FilterRules {\n [sourceId: string]: {\n operators: FilterOption[];\n inputType: 'dropdown' | 'custom';\n multiSelect?: boolean;\n getValueOptions?: () => FilterOption[];\n };\n}\n\nexport interface FilterProps {\n filter: FilterValue;\n sourceOptions: FilterOption[];\n rules: FilterRules;\n onSourceChange?: (sourceId: string) => void;\n onRemoveFilter: (id: string | number) => void;\n onFilterChange: (filter: FilterValue) => void;\n selectPlaceholder?: string;\n customValuePlaceholder?: string;\n customValueButtonLabel?: string;\n sourceFirstMessage?: string;\n}\n","import { FilterValue } from './types';\n\nexport const useMultiSelectHelpers = (\n internalFilter: FilterValue,\n valueOptions: Array<{ id: string; label: string }>,\n selectPlaceholder: string,\n) => {\n const getSelectedValues = (): string[] => {\n if (Array.isArray(internalFilter.value)) {\n return internalFilter.value;\n }\n\n return internalFilter.value ? [internalFilter.value] : [];\n };\n\n const isValueSelected = (valueId: string): boolean => {\n const selectedValues = getSelectedValues();\n\n return selectedValues.includes(valueId);\n };\n\n const getDisplayValue = (): string => {\n const selectedValues = getSelectedValues();\n if (selectedValues.length === 0) return selectPlaceholder;\n if (selectedValues.length === 1) {\n const option = valueOptions.find((opt) => opt.id === selectedValues[0]);\n\n return option?.label || selectedValues[0];\n }\n\n return `${selectedValues.length} selected`;\n };\n\n return {\n getSelectedValues,\n isValueSelected,\n getDisplayValue,\n };\n};\n","import React, { useRef } from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\n\ninterface CustomValueInputProps {\n inputValue: string;\n setInputValue: (value: string) => void;\n customValuePlaceholder: string;\n customValueButtonLabel: string;\n onSubmit: () => void;\n handleKeyDown: (e: React.KeyboardEvent<HTMLInputElement | HTMLButtonElement>, isInput: boolean) => void;\n}\n\nexport const CustomValueInput: React.FC<CustomValueInputProps> = ({\n inputValue,\n setInputValue,\n customValuePlaceholder,\n customValueButtonLabel,\n onSubmit,\n handleKeyDown,\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n\n return (\n <form\n className=\"p-3\"\n onSubmit={(e) => {\n e.preventDefault();\n onSubmit();\n }}\n >\n <Input\n ref={inputRef}\n type=\"text\"\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n placeholder={customValuePlaceholder}\n className=\"mb-2\"\n onKeyDown={(e) => handleKeyDown(e, true)}\n />\n <Button\n type=\"submit\"\n variant=\"dark\"\n className=\"w-full\"\n onKeyDown={(e) => handleKeyDown(e, false)}\n data-custom-submit-button\n >\n {customValueButtonLabel}\n </Button>\n </form>\n );\n};\n","import React, { useState, useRef } from 'react';\nimport { Check } from '@phosphor-icons/react';\n\nimport { FilterValue, FilterOption } from '../types';\n\nimport { Button } from '@/components/ui/button';\n\ninterface MultiSelectDropdownProps {\n internalFilter: FilterValue;\n valueOptions: FilterOption[];\n onConfirm: (selectedValues: string[]) => void;\n onClose: () => void;\n}\n\nconst getInitialValues = (value: FilterValue['value']): string[] => {\n if (Array.isArray(value)) {\n return value;\n } else if (value) {\n return [value];\n }\n\n return [];\n};\n\nexport const MultiSelectDropdown: React.FC<MultiSelectDropdownProps> = ({\n internalFilter,\n valueOptions,\n onConfirm,\n onClose,\n}) => {\n const [pendingValues, setPendingValues] = useState<string[]>(() => getInitialValues(internalFilter.value));\n const [announcement, setAnnouncement] = useState<string>('');\n const buttonRefs = useRef<(HTMLButtonElement | null)[]>([]);\n const applyButtonRef = useRef<HTMLButtonElement>(null);\n\n const handleValueToggle = (valueId: string) => {\n const option = valueOptions.find((opt) => opt.id === valueId);\n const isCurrentlySelected = pendingValues.includes(valueId);\n\n setPendingValues((prev) => {\n const newValues = prev.includes(valueId) ? prev.filter((id) => id !== valueId) : [...prev, valueId];\n\n // Announce the change\n if (option) {\n const action = isCurrentlySelected ? 'deselected' : 'selected';\n setAnnouncement(`${option.label} ${action}.`);\n }\n\n return newValues;\n });\n };\n\n const handleConfirm = () => {\n onConfirm(pendingValues);\n onClose();\n };\n\n const isValueSelected = (valueId: string): boolean => {\n return pendingValues.includes(valueId);\n };\n\n const focusButton = (index: number) => {\n if (index < valueOptions.length) {\n buttonRefs.current[index]?.focus();\n } else {\n applyButtonRef.current?.focus();\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent, index: number) => {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const nextIndex = Math.min(index + 1, valueOptions.length);\n focusButton(nextIndex);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const prevIndex = Math.max(index - 1, 0);\n focusButton(prevIndex);\n break;\n }\n case 'Enter':\n case 'Spacebar':\n e.preventDefault();\n if (index < valueOptions.length) {\n // If the user is selecting an option\n handleValueToggle(valueOptions[index].id);\n } else {\n // If the user is selecting the apply button\n handleConfirm();\n }\n break;\n case 'Escape':\n e.preventDefault();\n onClose();\n break;\n }\n };\n\n return (\n <div className=\"py-1\" role=\"listbox\" aria-multiselectable=\"true\">\n {/* Screen reader announcements */}\n <div aria-live=\"polite\" aria-atomic=\"true\" className=\"sr-only\">\n {announcement}\n </div>\n\n {valueOptions.map((option, index) => (\n <button\n key={option.id}\n ref={(el) => (buttonRefs.current[index] = el)}\n type=\"button\"\n className=\"relative flex w-full text-left cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground\"\n onClick={() => handleValueToggle(option.id)}\n onKeyDown={(e) => handleKeyDown(e, index)}\n role=\"option\"\n aria-selected={isValueSelected(option.id)}\n >\n {isValueSelected(option.id) && <Check size={14} className=\"mr-2\" />}\n {!isValueSelected(option.id) && <span className=\"mr-2 w-3.5\" />}\n {option.label}\n </button>\n ))}\n\n <div className=\"border-t border-border mt-1 pt-2 px-2 pb-2\">\n <Button\n ref={applyButtonRef}\n onClick={handleConfirm}\n size=\"sm\"\n className=\"w-full\"\n disabled={pendingValues.length === 0}\n onKeyDown={(e) => handleKeyDown(e, valueOptions.length)}\n >\n Apply ({pendingValues.length} selected)\n </Button>\n </div>\n </div>\n );\n};\n","import React, { useRef } from 'react';\nimport { Check } from '@phosphor-icons/react';\n\nimport { FilterOption } from '../types';\n\ninterface SingleSelectDropdownProps {\n valueOptions: FilterOption[];\n isValueSelected: (valueId: string) => boolean;\n onValueSelect: (valueId: string) => void;\n}\n\nexport const SingleSelectDropdown: React.FC<SingleSelectDropdownProps> = ({\n valueOptions,\n isValueSelected,\n onValueSelect,\n}) => {\n const buttonRefs = useRef<(HTMLButtonElement | null)[]>([]);\n\n const focusButton = (index: number) => {\n buttonRefs.current[index]?.focus();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent, index: number) => {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const nextIndex = Math.min(index + 1, valueOptions.length - 1);\n focusButton(nextIndex);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const prevIndex = Math.max(index - 1, 0);\n focusButton(prevIndex);\n break;\n }\n case 'Enter':\n case 'Spacebar':\n e.preventDefault();\n onValueSelect(valueOptions[index].id);\n break;\n }\n };\n\n return (\n <div className=\"py-1\" role=\"listbox\">\n {valueOptions.map((option, index) => (\n <button\n key={option.id}\n ref={(el) => (buttonRefs.current[index] = el)}\n type=\"button\"\n className=\"relative flex w-full text-left cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground\"\n onClick={() => onValueSelect(option.id)}\n onKeyDown={(e) => handleKeyDown(e, index)}\n >\n {isValueSelected(option.id) && <Check size={14} className=\"mr-2\" />}\n {!isValueSelected(option.id) && <span className=\"mr-2 w-3.5\" />}\n {option.label}\n </button>\n ))}\n </div>\n );\n};\n","import React, { useState, useEffect, forwardRef, useRef, useImperativeHandle } from 'react';\nimport { Check, XCircle } from '@phosphor-icons/react';\n\nimport { FilterProps, FilterValue, Operator } from './types';\nimport { useMultiSelectHelpers } from './hooks';\nimport { CustomValueInput } from './components/CustomValueInput';\nimport { MultiSelectDropdown } from './components/MultiSelectDropdown';\nimport { SingleSelectDropdown } from './components/SingleSelectDropdown';\n\nimport { Button } from '@/components/ui/button';\nimport { ButtonGroup } from '@/components/ui/button-group';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\n\nconst Filter = forwardRef<{ focus: () => void }, FilterProps>(\n (\n {\n filter,\n sourceOptions,\n rules,\n onSourceChange,\n onRemoveFilter,\n onFilterChange,\n selectPlaceholder = 'Select a value',\n customValuePlaceholder = 'Enter custom value',\n customValueButtonLabel = 'Done',\n sourceFirstMessage = 'Please select a source first',\n }: FilterProps,\n ref,\n ) => {\n // State\n const [internalFilter, setInternalFilter] = useState<FilterValue>({\n id: filter.id,\n source: filter.source,\n operator: filter.operator || Operator.IS,\n value: filter.value,\n });\n const [inputValue, setInputValue] = useState('');\n const [openDropdownType, setOpenDropdownType] = useState<'source' | 'operator' | 'value' | null>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const sourceButtonRef = useRef<HTMLButtonElement>(null);\n const divRef = useRef<HTMLDivElement>(null);\n\n // Expose focus method\n useImperativeHandle(ref, () => ({\n focus: () => {\n sourceButtonRef.current?.focus();\n },\n }));\n\n // Get current rules for selected source\n const currentRules = internalFilter.source ? rules[internalFilter.source] : undefined;\n const operatorOptions = currentRules?.operators || [];\n const isMultiSelect = currentRules?.multiSelect || false;\n let inputType = currentRules?.inputType || 'dropdown';\n if (internalFilter.operator === Operator.CONTAINS || internalFilter.operator === Operator.DOES_NOT_CONTAIN) {\n inputType = 'custom';\n }\n const valueOptions = currentRules?.getValueOptions ? currentRules.getValueOptions() : [];\n\n // Multi-select helpers\n const { getSelectedValues, isValueSelected, getDisplayValue } = useMultiSelectHelpers(\n internalFilter,\n valueOptions,\n selectPlaceholder,\n );\n\n // Auto-focus input when dropdown opens and custom input is needed\n useEffect(() => {\n if (openDropdownType === 'value' && inputType === 'custom') {\n const timeoutId = setTimeout(() => inputRef.current?.focus(), 50);\n\n return () => clearTimeout(timeoutId);\n }\n\n return undefined;\n }, [openDropdownType, inputType]);\n\n // Sync with external state\n useEffect(() => {\n setInternalFilter({\n id: filter.id,\n source: filter.source,\n operator: filter.operator || Operator.IS,\n value: filter.value,\n });\n }, [filter]);\n\n // Helper function to check if filter is complete and trigger onChange\n const checkAndTriggerChange = (newFilter: FilterValue) => {\n const hasValue = Array.isArray(newFilter.value) ? newFilter.value.length > 0 : !!newFilter.value?.trim();\n\n const isComplete = newFilter.source && newFilter.operator && hasValue;\n\n if (isComplete) {\n onFilterChange(newFilter);\n }\n };\n\n // Handle field updates\n const updateFilterField = (field: keyof FilterValue, value: string) => {\n const newFilter: FilterValue = { ...internalFilter, [field]: value };\n\n // Special handling for source changes\n if (field === 'source') {\n const sourceRules = rules[value];\n newFilter.operator = sourceRules?.operators[0]?.id as Operator;\n newFilter.value = sourceRules?.multiSelect ? [] : '';\n }\n // If operator changes, also clear value if inputType is dropdown\n if (field === 'operator') {\n if (internalFilter.source) {\n const sourceRules = rules[internalFilter.source];\n if (sourceRules?.inputType === 'dropdown') {\n newFilter.value = sourceRules?.multiSelect ? [] : '';\n }\n }\n }\n\n setInternalFilter(newFilter);\n checkAndTriggerChange(newFilter);\n\n if (!isMultiSelect || field !== 'value') {\n setOpenDropdownType(null);\n }\n };\n\n // Handle multi-select value changes\n const handleValueToggle = (valueId: string) => {\n const selectedValues = getSelectedValues();\n let newValues: string[];\n\n if (isMultiSelect) {\n if (selectedValues.includes(valueId)) {\n newValues = selectedValues.filter((id) => id !== valueId);\n } else {\n newValues = [...selectedValues, valueId];\n }\n } else {\n newValues = [valueId];\n }\n\n const newFilter = {\n ...internalFilter,\n value: isMultiSelect ? newValues : newValues[0] || '',\n };\n\n setInternalFilter(newFilter);\n checkAndTriggerChange(newFilter);\n\n // Close dropdown for single select, keep open for multi-select\n if (!isMultiSelect) {\n setOpenDropdownType(null);\n }\n };\n\n // Handle multi-select confirmation\n const handleMultiSelectConfirm = (selectedValues: string[]) => {\n const newFilter = {\n ...internalFilter,\n value: selectedValues,\n };\n\n setInternalFilter(newFilter);\n\n // Trigger onChange if filter is complete\n const isComplete = newFilter.source && newFilter.operator && selectedValues.length > 0;\n if (isComplete) onFilterChange(newFilter);\n\n setOpenDropdownType(null);\n };\n\n // Handle custom value submission\n const handleCustomValueSubmit = () => {\n if (inputValue.trim()) {\n const newFilter = { ...internalFilter, value: inputValue.trim() };\n setInternalFilter(newFilter);\n setInputValue('');\n setOpenDropdownType(null);\n if (newFilter.source && newFilter.operator && newFilter.value) {\n onFilterChange(newFilter);\n }\n }\n };\n\n // Tab trap handlers\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement | HTMLButtonElement>, isInput: boolean) => {\n if (e.key === 'Escape') {\n setOpenDropdownType(null);\n\n return;\n }\n if (e.key === 'Tab') {\n if (isInput && !e.shiftKey) {\n e.preventDefault();\n const button = document.querySelector('[data-custom-submit-button]') as HTMLButtonElement;\n button?.focus();\n } else if (!isInput) {\n e.preventDefault();\n inputRef.current?.focus();\n }\n }\n };\n\n return (\n <ButtonGroup\n ref={divRef}\n orientation=\"horizontal\"\n className=\"rounded-full border border-border divide-x-2 divide-dark-500\"\n >\n {/* Source Dropdown */}\n <DropdownMenu\n open={openDropdownType === 'source'}\n onOpenChange={(open) => setOpenDropdownType(open ? 'source' : null)}\n modal={false}\n >\n <DropdownMenuTrigger asChild>\n <Button ref={sourceButtonRef} variant=\"ghost\" size=\"xs\" className=\"rounded-l-full font-bold\">\n {sourceOptions.find((opt) => opt.id === internalFilter.source)?.label ||\n sourceOptions[0]?.label ||\n selectPlaceholder}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-48\">\n {sourceOptions.map((option) => (\n <DropdownMenuItem\n key={option.id}\n className=\"flex items-center\"\n onSelect={() => {\n updateFilterField('source', option.id);\n onSourceChange?.(option.id);\n }}\n >\n {option.id === internalFilter.source && <Check size={14} className=\"mr-2\" />}\n {option.label}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* Operator Dropdown */}\n <DropdownMenu\n open={openDropdownType === 'operator'}\n onOpenChange={(open) => setOpenDropdownType(open ? 'operator' : null)}\n modal={false}\n >\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"xs\">\n {operatorOptions.find((opt) => opt.id === internalFilter.operator)?.label || selectPlaceholder}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-48\">\n {operatorOptions.map((option) => (\n <DropdownMenuItem\n key={option.id}\n className=\"flex items-center\"\n onSelect={() => updateFilterField('operator', option.id)}\n >\n {option.id === internalFilter.operator && <Check size={14} className=\"mr-2\" />}\n {option.label}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* Value Popover */}\n <Popover\n open={openDropdownType === 'value'}\n onOpenChange={(open) => setOpenDropdownType(open ? 'value' : null)}\n >\n <PopoverTrigger asChild>\n <Button variant=\"ghost\" size=\"xs\" className=\"font-bold\">\n {getDisplayValue()}\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-64 max-h-[min(320px,50vh)] overflow-y-auto p-0\">\n {inputType === 'custom' && (\n <div className=\"p-3\">\n <CustomValueInput\n inputValue={inputValue}\n setInputValue={setInputValue}\n customValuePlaceholder={customValuePlaceholder}\n customValueButtonLabel={customValueButtonLabel}\n onSubmit={handleCustomValueSubmit}\n handleKeyDown={handleKeyDown}\n />\n </div>\n )}\n {inputType === 'dropdown' && (\n <>\n {internalFilter.source ? (\n <>\n {isMultiSelect ? (\n <MultiSelectDropdown\n internalFilter={internalFilter}\n valueOptions={valueOptions}\n onConfirm={handleMultiSelectConfirm}\n onClose={() => setOpenDropdownType(null)}\n />\n ) : (\n <SingleSelectDropdown\n valueOptions={valueOptions}\n isValueSelected={isValueSelected}\n onValueSelect={handleValueToggle}\n />\n )}\n </>\n ) : (\n <div className=\"p-3 text-sm text-gray-500\">{sourceFirstMessage}</div>\n )}\n </>\n )}\n </PopoverContent>\n </Popover>\n\n {/* Remove button */}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"xs\"\n onClick={() => {\n setInternalFilter({ id: filter.id });\n setOpenDropdownType(null);\n onRemoveFilter(filter.id);\n }}\n className=\"p-2 hover:bg-black/10 rounded-none rounded-r-full\"\n aria-label=\"Remove filter\"\n >\n <XCircle size={16} weight=\"fill\" />\n </Button>\n </ButtonGroup>\n );\n },\n);\n\nFilter.displayName = 'Filter';\n\nexport { Filter };\n","import React, { useState, useEffect, useRef } from 'react';\nimport { Plus } from '@phosphor-icons/react';\nimport { createId } from '@paralleldrive/cuid2';\n\nimport { Filter, FilterOption, FilterRules, FilterValue, Operator } from './index';\nimport { Button } from '../ui/button';\n\nimport { cn } from '@/lib/utils';\n\ninterface FiltersProps extends React.HTMLAttributes<HTMLDivElement> {\n filters: FilterValue[];\n onFilterChange: (filter: FilterValue) => void;\n onFilterRemove: (filterId: string | number) => void;\n onFilterAdd?: (filter: FilterValue) => void;\n sourceOptions: FilterOption[];\n rules: FilterRules;\n}\n\nconst Filters = ({\n filters,\n onFilterChange,\n onFilterRemove,\n onFilterAdd,\n sourceOptions,\n rules,\n className,\n}: FiltersProps) => {\n const [internalFilters, setInternalFilters] = useState<FilterValue[]>(filters || []);\n const filterRefs = useRef<{ [key: string]: { focus: () => void } | null }>({});\n\n // Sync internal state with props\n useEffect(() => {\n setInternalFilters(filters || []);\n }, [filters]);\n\n // Get sources that are already in use\n const usedSources = internalFilters.map((filter) => filter.source).filter(Boolean);\n\n // Get available sources that haven't been used yet\n const availableSources = sourceOptions.filter((option) => {\n // If the source has multiSelect enabled, filter out used sources\n if (rules[option.id]?.multiSelect) {\n return !usedSources.includes(option.id);\n }\n\n // If multiSelect is false or undefined, allow the source to be used multiple times\n return sourceOptions;\n });\n\n // Check if we can add more filters\n const canAddFilter = availableSources.length > 0;\n\n const handleAddFilter = () => {\n if (!canAddFilter) return;\n\n const newFilter = {\n id: createId(),\n source: availableSources[0].id,\n operator: Operator.IS,\n value: rules[availableSources[0].id]?.multiSelect ? [] : '',\n };\n\n const newFilters = [...internalFilters, newFilter];\n setInternalFilters(newFilters);\n\n // Focus the new filter after it's rendered\n requestAnimationFrame(() => {\n filterRefs.current[newFilter.id]?.focus();\n });\n\n // Notify parent if callback provided\n onFilterAdd?.(newFilter);\n };\n\n const handleRemoveFilter = (filter: FilterValue) => {\n const newFilters = internalFilters.filter((f) => f.id !== filter.id);\n setInternalFilters(newFilters);\n onFilterRemove(filter.id);\n };\n\n return (\n <fieldset className={cn('flex flex-wrap gap-2', className)}>\n <legend className=\"sr-only\">Filters</legend>\n {internalFilters?.map((filter) => {\n // For each filter, include available sources plus its own current source\n const filterSourceOptions = sourceOptions.filter(\n (option) =>\n !usedSources.includes(option.id) || // Available sources\n option.id === filter.source, // Or its own current source\n );\n\n return (\n <Filter\n key={filter.id}\n ref={(ref) => {\n filterRefs.current[filter.id] = ref;\n }}\n filter={filter}\n sourceOptions={filterSourceOptions}\n rules={rules}\n onRemoveFilter={() => handleRemoveFilter(filter)}\n onFilterChange={onFilterChange}\n />\n );\n })}\n {canAddFilter && (\n <Button\n onClick={handleAddFilter}\n variant=\"ghost\"\n className=\"border border-foreground rounded-full gap-1\"\n size=\"sm\"\n title=\"Add filter\"\n >\n <Plus size={16} />\n Add filter\n </Button>\n )}\n </fieldset>\n );\n};\n\nexport { Filters };\n"],"names":["Operator","CustomValueInput","inputValue","setInputValue","customValuePlaceholder","customValueButtonLabel","onSubmit","handleKeyDown","inputRef","useRef","React","createElement","className","e","preventDefault","Input","ref","type","value","onChange","target","placeholder","onKeyDown","Button","variant","MultiSelectDropdown","internalFilter","valueOptions","onConfirm","onClose","pendingValues","setPendingValues","useState","getInitialValues","Array","isArray","announcement","setAnnouncement","buttonRefs","applyButtonRef","handleValueToggle","valueId","option","find","opt","id","isCurrentlySelected","includes","prev","newValues","filter","action","label","handleConfirm","isValueSelected","focusButton","index","length","current","focus","key","nextIndex","Math","min","prevIndex","max","role","map","el","onClick","Check","size","disabled","SingleSelectDropdown","onValueSelect","Filter","forwardRef","sourceOptions","rules","onSourceChange","onRemoveFilter","onFilterChange","selectPlaceholder","sourceFirstMessage","setInternalFilter","source","operator","IS","openDropdownType","setOpenDropdownType","sourceButtonRef","divRef","useImperativeHandle","currentRules","operatorOptions","operators","isMultiSelect","multiSelect","inputType","CONTAINS","DOES_NOT_CONTAIN","getValueOptions","getSelectedValues","getDisplayValue","selectedValues","useMultiSelectHelpers","useEffect","timeoutId","setTimeout","clearTimeout","checkAndTriggerChange","newFilter","hasValue","trim","updateFilterField","field","sourceRules","ButtonGroup","orientation","DropdownMenu","open","onOpenChange","modal","DropdownMenuTrigger","asChild","DropdownMenuContent","align","DropdownMenuItem","onSelect","Popover","PopoverTrigger","PopoverContent","isInput","shiftKey","button","document","querySelector","XCircle","weight","displayName","Filters","filters","onFilterRemove","onFilterAdd","internalFilters","setInternalFilters","filterRefs","usedSources","Boolean","availableSources","canAddFilter","cn","filterSourceOptions","newFilters","f","handleRemoveFilter","createId","requestAnimationFrame","title","Plus"],"mappings":"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"}
1
+ {"version":3,"file":"filters.Bxyw3eHZ.js","sources":["../../../src/components/filter/types.ts","../../../src/components/filter/hooks.ts","../../../src/components/filter/components/CustomValueInput.tsx","../../../src/components/filter/components/MultiSelectDropdown.tsx","../../../src/components/filter/components/SingleSelectDropdown.tsx","../../../src/components/filter/filter.tsx","../../../src/components/filter/filters.tsx"],"sourcesContent":["// Types\nexport interface FilterOption {\n id: string;\n label: string;\n}\n\nexport enum Operator {\n IS = 'is',\n IS_NOT = 'is not',\n CONTAINS = 'contains',\n DOES_NOT_CONTAIN = 'does not contain',\n STARTS_WITH = 'starts with',\n}\n\nexport interface FilterValue {\n id: string | number;\n source?: string;\n operator?: Operator;\n value?: string | string[];\n}\n\n/**\n * Filter rules for each source\n * How this works:\n * - You can define the rules for each source\n * - The rules are used to determine the available operators and value type\n * - The input type is used to determine the type of input displayed in when the dropdown is opened\n * - The getValueOptions function is used to determine the available options for the value\n * - multiSelect determines if multiple values can be selected for dropdown type\n *\n * @example\n * {\n * 'sourceId': {\n * operators: [\n * { id: 'is', label: 'is' },\n * { id: 'is not', label: 'is not' },\n * ],\n * inputType: 'dropdown' | 'custom',\n * multiSelect?: boolean,\n * getValueOptions?: () => FilterOption[],\n * },\n * }\n */\nexport interface FilterRules {\n [sourceId: string]: {\n operators: FilterOption[];\n inputType: 'dropdown' | 'custom';\n multiSelect?: boolean;\n getValueOptions?: () => FilterOption[];\n };\n}\n\nexport interface FilterProps {\n filter: FilterValue;\n sourceOptions: FilterOption[];\n rules: FilterRules;\n onSourceChange?: (sourceId: string) => void;\n onRemoveFilter: (id: string | number) => void;\n onFilterChange: (filter: FilterValue) => void;\n selectPlaceholder?: string;\n customValuePlaceholder?: string;\n customValueButtonLabel?: string;\n sourceFirstMessage?: string;\n}\n","import { FilterValue } from './types';\n\nexport const useMultiSelectHelpers = (\n internalFilter: FilterValue,\n valueOptions: Array<{ id: string; label: string }>,\n selectPlaceholder: string,\n) => {\n const getSelectedValues = (): string[] => {\n if (Array.isArray(internalFilter.value)) {\n return internalFilter.value;\n }\n\n return internalFilter.value ? [internalFilter.value] : [];\n };\n\n const isValueSelected = (valueId: string): boolean => {\n const selectedValues = getSelectedValues();\n\n return selectedValues.includes(valueId);\n };\n\n const getDisplayValue = (): string => {\n const selectedValues = getSelectedValues();\n if (selectedValues.length === 0) return selectPlaceholder;\n if (selectedValues.length === 1) {\n const option = valueOptions.find((opt) => opt.id === selectedValues[0]);\n\n return option?.label || selectedValues[0];\n }\n\n return `${selectedValues.length} selected`;\n };\n\n return {\n getSelectedValues,\n isValueSelected,\n getDisplayValue,\n };\n};\n","import React, { useRef } from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\n\ninterface CustomValueInputProps {\n inputValue: string;\n setInputValue: (value: string) => void;\n customValuePlaceholder: string;\n customValueButtonLabel: string;\n onSubmit: () => void;\n handleKeyDown: (e: React.KeyboardEvent<HTMLInputElement | HTMLButtonElement>, isInput: boolean) => void;\n}\n\nexport const CustomValueInput: React.FC<CustomValueInputProps> = ({\n inputValue,\n setInputValue,\n customValuePlaceholder,\n customValueButtonLabel,\n onSubmit,\n handleKeyDown,\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n\n return (\n <form\n className=\"p-3\"\n onSubmit={(e) => {\n e.preventDefault();\n onSubmit();\n }}\n >\n <Input\n ref={inputRef}\n type=\"text\"\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n placeholder={customValuePlaceholder}\n className=\"mb-2\"\n onKeyDown={(e) => handleKeyDown(e, true)}\n />\n <Button\n type=\"submit\"\n variant=\"dark\"\n className=\"w-full\"\n onKeyDown={(e) => handleKeyDown(e, false)}\n data-custom-submit-button\n >\n {customValueButtonLabel}\n </Button>\n </form>\n );\n};\n","import React, { useState, useRef } from 'react';\nimport { Check } from '@phosphor-icons/react';\n\nimport { FilterValue, FilterOption } from '../types';\n\nimport { Button } from '@/components/ui/button';\n\ninterface MultiSelectDropdownProps {\n internalFilter: FilterValue;\n valueOptions: FilterOption[];\n onConfirm: (selectedValues: string[]) => void;\n onClose: () => void;\n}\n\nconst getInitialValues = (value: FilterValue['value']): string[] => {\n if (Array.isArray(value)) {\n return value;\n } else if (value) {\n return [value];\n }\n\n return [];\n};\n\nexport const MultiSelectDropdown: React.FC<MultiSelectDropdownProps> = ({\n internalFilter,\n valueOptions,\n onConfirm,\n onClose,\n}) => {\n const [pendingValues, setPendingValues] = useState<string[]>(() => getInitialValues(internalFilter.value));\n const [announcement, setAnnouncement] = useState<string>('');\n const buttonRefs = useRef<(HTMLButtonElement | null)[]>([]);\n const applyButtonRef = useRef<HTMLButtonElement>(null);\n\n const handleValueToggle = (valueId: string) => {\n const option = valueOptions.find((opt) => opt.id === valueId);\n const isCurrentlySelected = pendingValues.includes(valueId);\n\n setPendingValues((prev) => {\n const newValues = prev.includes(valueId) ? prev.filter((id) => id !== valueId) : [...prev, valueId];\n\n // Announce the change\n if (option) {\n const action = isCurrentlySelected ? 'deselected' : 'selected';\n setAnnouncement(`${option.label} ${action}.`);\n }\n\n return newValues;\n });\n };\n\n const handleConfirm = () => {\n onConfirm(pendingValues);\n onClose();\n };\n\n const isValueSelected = (valueId: string): boolean => {\n return pendingValues.includes(valueId);\n };\n\n const focusButton = (index: number) => {\n if (index < valueOptions.length) {\n buttonRefs.current[index]?.focus();\n } else {\n applyButtonRef.current?.focus();\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent, index: number) => {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const nextIndex = Math.min(index + 1, valueOptions.length);\n focusButton(nextIndex);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const prevIndex = Math.max(index - 1, 0);\n focusButton(prevIndex);\n break;\n }\n case 'Enter':\n case 'Spacebar':\n e.preventDefault();\n if (index < valueOptions.length) {\n // If the user is selecting an option\n handleValueToggle(valueOptions[index].id);\n } else {\n // If the user is selecting the apply button\n handleConfirm();\n }\n break;\n case 'Escape':\n e.preventDefault();\n onClose();\n break;\n }\n };\n\n return (\n <div className=\"py-1\" role=\"listbox\" aria-multiselectable=\"true\">\n {/* Screen reader announcements */}\n <div aria-live=\"polite\" aria-atomic=\"true\" className=\"sr-only\">\n {announcement}\n </div>\n\n {valueOptions.map((option, index) => (\n <button\n key={option.id}\n ref={(el) => (buttonRefs.current[index] = el)}\n type=\"button\"\n className=\"relative flex w-full text-left cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground\"\n onClick={() => handleValueToggle(option.id)}\n onKeyDown={(e) => handleKeyDown(e, index)}\n role=\"option\"\n aria-selected={isValueSelected(option.id)}\n >\n {isValueSelected(option.id) && <Check size={14} className=\"mr-2\" />}\n {!isValueSelected(option.id) && <span className=\"mr-2 w-3.5\" />}\n {option.label}\n </button>\n ))}\n\n <div className=\"border-t border-border mt-1 pt-2 px-2 pb-2\">\n <Button\n ref={applyButtonRef}\n onClick={handleConfirm}\n size=\"sm\"\n className=\"w-full\"\n disabled={pendingValues.length === 0}\n onKeyDown={(e) => handleKeyDown(e, valueOptions.length)}\n >\n Apply ({pendingValues.length} selected)\n </Button>\n </div>\n </div>\n );\n};\n","import React, { useRef } from 'react';\nimport { Check } from '@phosphor-icons/react';\n\nimport { FilterOption } from '../types';\n\ninterface SingleSelectDropdownProps {\n valueOptions: FilterOption[];\n isValueSelected: (valueId: string) => boolean;\n onValueSelect: (valueId: string) => void;\n}\n\nexport const SingleSelectDropdown: React.FC<SingleSelectDropdownProps> = ({\n valueOptions,\n isValueSelected,\n onValueSelect,\n}) => {\n const buttonRefs = useRef<(HTMLButtonElement | null)[]>([]);\n\n const focusButton = (index: number) => {\n buttonRefs.current[index]?.focus();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent, index: number) => {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const nextIndex = Math.min(index + 1, valueOptions.length - 1);\n focusButton(nextIndex);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const prevIndex = Math.max(index - 1, 0);\n focusButton(prevIndex);\n break;\n }\n case 'Enter':\n case 'Spacebar':\n e.preventDefault();\n onValueSelect(valueOptions[index].id);\n break;\n }\n };\n\n return (\n <div className=\"py-1\" role=\"listbox\">\n {valueOptions.map((option, index) => (\n <button\n key={option.id}\n ref={(el) => (buttonRefs.current[index] = el)}\n type=\"button\"\n className=\"relative flex w-full text-left cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground\"\n onClick={() => onValueSelect(option.id)}\n onKeyDown={(e) => handleKeyDown(e, index)}\n >\n {isValueSelected(option.id) && <Check size={14} className=\"mr-2\" />}\n {!isValueSelected(option.id) && <span className=\"mr-2 w-3.5\" />}\n {option.label}\n </button>\n ))}\n </div>\n );\n};\n","import React, { useState, useEffect, forwardRef, useRef, useImperativeHandle } from 'react';\nimport { Check, XCircle } from '@phosphor-icons/react';\n\nimport { FilterProps, FilterValue, Operator } from './types';\nimport { useMultiSelectHelpers } from './hooks';\nimport { CustomValueInput } from './components/CustomValueInput';\nimport { MultiSelectDropdown } from './components/MultiSelectDropdown';\nimport { SingleSelectDropdown } from './components/SingleSelectDropdown';\n\nimport { Button } from '@/components/ui/button';\nimport { ButtonGroup } from '@/components/ui/button-group';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\n\nconst Filter = forwardRef<{ focus: () => void }, FilterProps>(\n (\n {\n filter,\n sourceOptions,\n rules,\n onSourceChange,\n onRemoveFilter,\n onFilterChange,\n selectPlaceholder = 'Select a value',\n customValuePlaceholder = 'Enter custom value',\n customValueButtonLabel = 'Done',\n sourceFirstMessage = 'Please select a source first',\n }: FilterProps,\n ref,\n ) => {\n // State\n const [internalFilter, setInternalFilter] = useState<FilterValue>({\n id: filter.id,\n source: filter.source,\n operator: filter.operator || Operator.IS,\n value: filter.value,\n });\n const [inputValue, setInputValue] = useState('');\n const [openDropdownType, setOpenDropdownType] = useState<'source' | 'operator' | 'value' | null>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const sourceButtonRef = useRef<HTMLButtonElement>(null);\n const divRef = useRef<HTMLDivElement>(null);\n\n // Expose focus method\n useImperativeHandle(ref, () => ({\n focus: () => {\n sourceButtonRef.current?.focus();\n },\n }));\n\n // Get current rules for selected source\n const currentRules = internalFilter.source ? rules[internalFilter.source] : undefined;\n const operatorOptions = currentRules?.operators || [];\n const isMultiSelect = currentRules?.multiSelect || false;\n let inputType = currentRules?.inputType || 'dropdown';\n if (internalFilter.operator === Operator.CONTAINS || internalFilter.operator === Operator.DOES_NOT_CONTAIN) {\n inputType = 'custom';\n }\n const valueOptions = currentRules?.getValueOptions ? currentRules.getValueOptions() : [];\n\n // Multi-select helpers\n const { getSelectedValues, isValueSelected, getDisplayValue } = useMultiSelectHelpers(\n internalFilter,\n valueOptions,\n selectPlaceholder,\n );\n\n // Auto-focus input when dropdown opens and custom input is needed\n useEffect(() => {\n if (openDropdownType === 'value' && inputType === 'custom') {\n const timeoutId = setTimeout(() => inputRef.current?.focus(), 50);\n\n return () => clearTimeout(timeoutId);\n }\n\n return undefined;\n }, [openDropdownType, inputType]);\n\n // Sync with external state\n useEffect(() => {\n setInternalFilter({\n id: filter.id,\n source: filter.source,\n operator: filter.operator || Operator.IS,\n value: filter.value,\n });\n }, [filter]);\n\n // Helper function to check if filter is complete and trigger onChange\n const checkAndTriggerChange = (newFilter: FilterValue) => {\n const hasValue = Array.isArray(newFilter.value) ? newFilter.value.length > 0 : !!newFilter.value?.trim();\n\n const isComplete = newFilter.source && newFilter.operator && hasValue;\n\n if (isComplete) {\n onFilterChange(newFilter);\n }\n };\n\n // Handle field updates\n const updateFilterField = (field: keyof FilterValue, value: string) => {\n const newFilter: FilterValue = { ...internalFilter, [field]: value };\n\n // Special handling for source changes\n if (field === 'source') {\n const sourceRules = rules[value];\n newFilter.operator = sourceRules?.operators[0]?.id as Operator;\n newFilter.value = sourceRules?.multiSelect ? [] : '';\n }\n // If operator changes, also clear value if inputType is dropdown\n if (field === 'operator') {\n if (internalFilter.source) {\n const sourceRules = rules[internalFilter.source];\n if (sourceRules?.inputType === 'dropdown') {\n newFilter.value = sourceRules?.multiSelect ? [] : '';\n }\n }\n }\n\n setInternalFilter(newFilter);\n checkAndTriggerChange(newFilter);\n\n if (!isMultiSelect || field !== 'value') {\n setOpenDropdownType(null);\n }\n };\n\n // Handle multi-select value changes\n const handleValueToggle = (valueId: string) => {\n const selectedValues = getSelectedValues();\n let newValues: string[];\n\n if (isMultiSelect) {\n if (selectedValues.includes(valueId)) {\n newValues = selectedValues.filter((id) => id !== valueId);\n } else {\n newValues = [...selectedValues, valueId];\n }\n } else {\n newValues = [valueId];\n }\n\n const newFilter = {\n ...internalFilter,\n value: isMultiSelect ? newValues : newValues[0] || '',\n };\n\n setInternalFilter(newFilter);\n checkAndTriggerChange(newFilter);\n\n // Close dropdown for single select, keep open for multi-select\n if (!isMultiSelect) {\n setOpenDropdownType(null);\n }\n };\n\n // Handle multi-select confirmation\n const handleMultiSelectConfirm = (selectedValues: string[]) => {\n const newFilter = {\n ...internalFilter,\n value: selectedValues,\n };\n\n setInternalFilter(newFilter);\n\n // Trigger onChange if filter is complete\n const isComplete = newFilter.source && newFilter.operator && selectedValues.length > 0;\n if (isComplete) onFilterChange(newFilter);\n\n setOpenDropdownType(null);\n };\n\n // Handle custom value submission\n const handleCustomValueSubmit = () => {\n if (inputValue.trim()) {\n const newFilter = { ...internalFilter, value: inputValue.trim() };\n setInternalFilter(newFilter);\n setInputValue('');\n setOpenDropdownType(null);\n if (newFilter.source && newFilter.operator && newFilter.value) {\n onFilterChange(newFilter);\n }\n }\n };\n\n // Tab trap handlers\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement | HTMLButtonElement>, isInput: boolean) => {\n if (e.key === 'Escape') {\n setOpenDropdownType(null);\n\n return;\n }\n if (e.key === 'Tab') {\n if (isInput && !e.shiftKey) {\n e.preventDefault();\n const button = document.querySelector('[data-custom-submit-button]') as HTMLButtonElement;\n button?.focus();\n } else if (!isInput) {\n e.preventDefault();\n inputRef.current?.focus();\n }\n }\n };\n\n return (\n <ButtonGroup\n ref={divRef}\n orientation=\"horizontal\"\n className=\"rounded-full border border-border divide-x-2 divide-dark-500\"\n >\n {/* Source Dropdown */}\n <DropdownMenu\n open={openDropdownType === 'source'}\n onOpenChange={(open) => setOpenDropdownType(open ? 'source' : null)}\n modal={false}\n >\n <DropdownMenuTrigger asChild>\n <Button ref={sourceButtonRef} variant=\"ghost\" size=\"xs\" className=\"rounded-l-full font-bold\">\n {sourceOptions.find((opt) => opt.id === internalFilter.source)?.label ||\n sourceOptions[0]?.label ||\n selectPlaceholder}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-48\">\n {sourceOptions.map((option) => (\n <DropdownMenuItem\n key={option.id}\n className=\"flex items-center\"\n onSelect={() => {\n updateFilterField('source', option.id);\n onSourceChange?.(option.id);\n }}\n >\n {option.id === internalFilter.source && <Check size={14} className=\"mr-2\" />}\n {option.label}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* Operator Dropdown */}\n <DropdownMenu\n open={openDropdownType === 'operator'}\n onOpenChange={(open) => setOpenDropdownType(open ? 'operator' : null)}\n modal={false}\n >\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"xs\">\n {operatorOptions.find((opt) => opt.id === internalFilter.operator)?.label || selectPlaceholder}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-48\">\n {operatorOptions.map((option) => (\n <DropdownMenuItem\n key={option.id}\n className=\"flex items-center\"\n onSelect={() => updateFilterField('operator', option.id)}\n >\n {option.id === internalFilter.operator && <Check size={14} className=\"mr-2\" />}\n {option.label}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* Value Popover */}\n <Popover\n open={openDropdownType === 'value'}\n onOpenChange={(open) => setOpenDropdownType(open ? 'value' : null)}\n >\n <PopoverTrigger asChild>\n <Button variant=\"ghost\" size=\"xs\" className=\"font-bold\">\n {getDisplayValue()}\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-64 max-h-[min(320px,50vh)] overflow-y-auto p-0\">\n {inputType === 'custom' && (\n <div className=\"p-3\">\n <CustomValueInput\n inputValue={inputValue}\n setInputValue={setInputValue}\n customValuePlaceholder={customValuePlaceholder}\n customValueButtonLabel={customValueButtonLabel}\n onSubmit={handleCustomValueSubmit}\n handleKeyDown={handleKeyDown}\n />\n </div>\n )}\n {inputType === 'dropdown' && (\n <>\n {internalFilter.source ? (\n <>\n {isMultiSelect ? (\n <MultiSelectDropdown\n internalFilter={internalFilter}\n valueOptions={valueOptions}\n onConfirm={handleMultiSelectConfirm}\n onClose={() => setOpenDropdownType(null)}\n />\n ) : (\n <SingleSelectDropdown\n valueOptions={valueOptions}\n isValueSelected={isValueSelected}\n onValueSelect={handleValueToggle}\n />\n )}\n </>\n ) : (\n <div className=\"p-3 text-sm text-gray-500\">{sourceFirstMessage}</div>\n )}\n </>\n )}\n </PopoverContent>\n </Popover>\n\n {/* Remove button */}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"xs\"\n onClick={() => {\n setInternalFilter({ id: filter.id });\n setOpenDropdownType(null);\n onRemoveFilter(filter.id);\n }}\n className=\"p-2 hover:bg-black/10 rounded-none rounded-r-full\"\n aria-label=\"Remove filter\"\n >\n <XCircle size={16} weight=\"fill\" />\n </Button>\n </ButtonGroup>\n );\n },\n);\n\nFilter.displayName = 'Filter';\n\nexport { Filter };\n","import React, { useState, useEffect, useRef } from 'react';\nimport { Plus } from '@phosphor-icons/react';\nimport { createId } from '@paralleldrive/cuid2';\n\nimport { Filter, FilterOption, FilterRules, FilterValue, Operator } from './index';\nimport { Button } from '../ui/button';\n\nimport { cn } from '@/lib/utils';\n\ninterface FiltersProps extends React.HTMLAttributes<HTMLDivElement> {\n filters: FilterValue[];\n onFilterChange: (filter: FilterValue) => void;\n onFilterRemove: (filterId: string | number) => void;\n onFilterAdd?: (filter: FilterValue) => void;\n sourceOptions: FilterOption[];\n rules: FilterRules;\n}\n\nconst Filters = ({\n filters,\n onFilterChange,\n onFilterRemove,\n onFilterAdd,\n sourceOptions,\n rules,\n className,\n}: FiltersProps) => {\n const [internalFilters, setInternalFilters] = useState<FilterValue[]>(filters || []);\n const filterRefs = useRef<{ [key: string]: { focus: () => void } | null }>({});\n\n // Sync internal state with props\n useEffect(() => {\n setInternalFilters(filters || []);\n }, [filters]);\n\n // Get sources that are already in use\n const usedSources = internalFilters.map((filter) => filter.source).filter(Boolean);\n\n // Get available sources that haven't been used yet\n const availableSources = sourceOptions.filter((option) => {\n // If the source has multiSelect enabled, filter out used sources\n if (rules[option.id]?.multiSelect) {\n return !usedSources.includes(option.id);\n }\n\n // If multiSelect is false or undefined, allow the source to be used multiple times\n return sourceOptions;\n });\n\n // Check if we can add more filters\n const canAddFilter = availableSources.length > 0;\n\n const handleAddFilter = () => {\n if (!canAddFilter) return;\n\n const newFilter = {\n id: createId(),\n source: availableSources[0].id,\n operator: Operator.IS,\n value: rules[availableSources[0].id]?.multiSelect ? [] : '',\n };\n\n const newFilters = [...internalFilters, newFilter];\n setInternalFilters(newFilters);\n\n // Focus the new filter after it's rendered\n requestAnimationFrame(() => {\n filterRefs.current[newFilter.id]?.focus();\n });\n\n // Notify parent if callback provided\n onFilterAdd?.(newFilter);\n };\n\n const handleRemoveFilter = (filter: FilterValue) => {\n const newFilters = internalFilters.filter((f) => f.id !== filter.id);\n setInternalFilters(newFilters);\n onFilterRemove(filter.id);\n };\n\n return (\n <fieldset className={cn('flex flex-wrap gap-2', className)}>\n <legend className=\"sr-only\">Filters</legend>\n {internalFilters?.map((filter) => {\n // For each filter, include available sources plus its own current source\n const filterSourceOptions = sourceOptions.filter(\n (option) =>\n !usedSources.includes(option.id) || // Available sources\n option.id === filter.source, // Or its own current source\n );\n\n return (\n <Filter\n key={filter.id}\n ref={(ref) => {\n filterRefs.current[filter.id] = ref;\n }}\n filter={filter}\n sourceOptions={filterSourceOptions}\n rules={rules}\n onRemoveFilter={() => handleRemoveFilter(filter)}\n onFilterChange={onFilterChange}\n />\n );\n })}\n {canAddFilter && (\n <Button\n onClick={handleAddFilter}\n variant=\"ghost\"\n className=\"border border-foreground rounded-full gap-1\"\n size=\"sm\"\n title=\"Add filter\"\n >\n <Plus size={16} />\n Add filter\n </Button>\n )}\n </fieldset>\n );\n};\n\nexport { Filters };\n"],"names":["Operator","CustomValueInput","inputValue","setInputValue","customValuePlaceholder","customValueButtonLabel","onSubmit","handleKeyDown","inputRef","useRef","React","createElement","className","e","preventDefault","Input","ref","type","value","onChange","target","placeholder","onKeyDown","Button","variant","MultiSelectDropdown","internalFilter","valueOptions","onConfirm","onClose","pendingValues","setPendingValues","useState","getInitialValues","Array","isArray","announcement","setAnnouncement","buttonRefs","applyButtonRef","handleValueToggle","valueId","option","find","opt","id","isCurrentlySelected","includes","prev","newValues","filter","action","label","handleConfirm","isValueSelected","focusButton","index","length","current","focus","key","nextIndex","Math","min","prevIndex","max","role","map","el","onClick","Check","size","disabled","SingleSelectDropdown","onValueSelect","Filter","forwardRef","sourceOptions","rules","onSourceChange","onRemoveFilter","onFilterChange","selectPlaceholder","sourceFirstMessage","setInternalFilter","source","operator","IS","openDropdownType","setOpenDropdownType","sourceButtonRef","divRef","useImperativeHandle","currentRules","operatorOptions","operators","isMultiSelect","multiSelect","inputType","CONTAINS","DOES_NOT_CONTAIN","getValueOptions","getSelectedValues","getDisplayValue","selectedValues","useMultiSelectHelpers","useEffect","timeoutId","setTimeout","clearTimeout","checkAndTriggerChange","newFilter","hasValue","trim","updateFilterField","field","sourceRules","ButtonGroup","orientation","DropdownMenu","open","onOpenChange","modal","DropdownMenuTrigger","asChild","DropdownMenuContent","align","DropdownMenuItem","onSelect","Popover","PopoverTrigger","PopoverContent","isInput","shiftKey","button","document","querySelector","XCircle","weight","displayName","Filters","filters","onFilterRemove","onFilterAdd","internalFilters","setInternalFilters","filterRefs","usedSources","Boolean","availableSources","canAddFilter","cn","filterSourceOptions","newFilters","f","handleRemoveFilter","createId","requestAnimationFrame","title","Plus"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import*as e from"react";import{Check as t,SpinnerGap as o}from"@phosphor-icons/react";import{c as a}from"./utils.C6Qu-kwd.js";import{CommandItem as n}from"../components/ui/command.js";import{C as r}from"./combobox.CLT9CXUV.js";const s="brainfish-google-fonts-cache",l="brainfish-google-fonts-cache-timestamp",c=/* @__PURE__ */new Set,i=()=>{try{const e=localStorage.getItem(l);if(!e)return null;if(Date.now()-parseInt(e,10)>864e5)return localStorage.removeItem(s),localStorage.removeItem(l),null;const t=localStorage.getItem(s);return t?JSON.parse(t):null}catch{return null}},m=e=>{try{localStorage.setItem(s,JSON.stringify(e)),localStorage.setItem(l,Date.now().toString())}catch{}},f=e=>{if(c.has(e))return;const t=document.createElement("link");t.href=`https://fonts.googleapis.com/css2?family=${e.replace(/ /g,"+")}&display=swap`,t.rel="stylesheet",document.head.appendChild(t),c.add(e)},u=()=>{try{localStorage.removeItem(s),localStorage.removeItem(l)}catch{}};function d({apiKey:t,maxFonts:o=500,onError:a}){const[n,r]=e.useState([]),[s,l]=e.useState(!0),c=e.useRef(a);return e.useEffect(()=>{c.current=a},[a]),e.useEffect(()=>{(async()=>{const e=i();if(e&&e.length>0)return r(e.slice(0,o)),void l(!1);try{const e=await fetch(`https://www.googleapis.com/webfonts/v1/webfonts?key=${t}&sort=popularity`);if(!e.ok)throw new Error(`Failed to fetch fonts: ${e.statusText}`);const a=(await e.json()).items.map(e=>({value:e.family,label:e.family,category:e.category,variants:e.variants}));m(a),r(a.slice(0,o))}catch(a){const e=a instanceof Error?a:new Error("Failed to fetch fonts");console.error("FontPicker: Failed to fetch Google Fonts",e),c.current?.(e)}finally{l(!1)}})()},[t,o]),{fonts:n,isLoading:s,loadFont:f}}const g=e.memo(function({font:o,isSelected:r,onSelect:s}){const l=e.useRef(null),[c,i]=e.useState(!1);e.useEffect(()=>{const e=new IntersectionObserver(([t])=>{t.isIntersecting&&(i(!0),e.disconnect())},{threshold:.1});return l.current&&e.observe(l.current),()=>e.disconnect()},[]),e.useEffect(()=>{c&&f(o.value)},[c,o.value]);const m=`Select ${o.label} font${o.category?`, ${o.category} category`:""}`;/* @__PURE__ */
1
+ import*as e from"react";import{Check as t,SpinnerGap as o}from"@phosphor-icons/react";import{c as a}from"./utils.DtKoarLP.js";import{CommandItem as n}from"../components/ui/command.js";import{C as r}from"./combobox.DKotd4uC.js";const s="brainfish-google-fonts-cache",l="brainfish-google-fonts-cache-timestamp",c=/* @__PURE__ */new Set,i=()=>{try{const e=localStorage.getItem(l);if(!e)return null;if(Date.now()-parseInt(e,10)>864e5)return localStorage.removeItem(s),localStorage.removeItem(l),null;const t=localStorage.getItem(s);return t?JSON.parse(t):null}catch{return null}},m=e=>{try{localStorage.setItem(s,JSON.stringify(e)),localStorage.setItem(l,Date.now().toString())}catch{}},f=e=>{if(c.has(e))return;const t=document.createElement("link");t.href=`https://fonts.googleapis.com/css2?family=${e.replace(/ /g,"+")}&display=swap`,t.rel="stylesheet",document.head.appendChild(t),c.add(e)},u=()=>{try{localStorage.removeItem(s),localStorage.removeItem(l)}catch{}};function d({apiKey:t,maxFonts:o=500,onError:a}){const[n,r]=e.useState([]),[s,l]=e.useState(!0),c=e.useRef(a);return e.useEffect(()=>{c.current=a},[a]),e.useEffect(()=>{(async()=>{const e=i();if(e&&e.length>0)return r(e.slice(0,o)),void l(!1);try{const e=await fetch(`https://www.googleapis.com/webfonts/v1/webfonts?key=${t}&sort=popularity`);if(!e.ok)throw new Error(`Failed to fetch fonts: ${e.statusText}`);const a=(await e.json()).items.map(e=>({value:e.family,label:e.family,category:e.category,variants:e.variants}));m(a),r(a.slice(0,o))}catch(a){const e=a instanceof Error?a:new Error("Failed to fetch fonts");console.error("FontPicker: Failed to fetch Google Fonts",e),c.current?.(e)}finally{l(!1)}})()},[t,o]),{fonts:n,isLoading:s,loadFont:f}}const g=e.memo(function({font:o,isSelected:r,onSelect:s}){const l=e.useRef(null),[c,i]=e.useState(!1);e.useEffect(()=>{const e=new IntersectionObserver(([t])=>{t.isIntersecting&&(i(!0),e.disconnect())},{threshold:.1});return l.current&&e.observe(l.current),()=>e.disconnect()},[]),e.useEffect(()=>{c&&f(o.value)},[c,o.value]);const m=`Select ${o.label} font${o.category?`, ${o.category} category`:""}`;/* @__PURE__ */
2
2
  return e.createElement(n,{ref:l,value:o.label,onSelect:s,className:"cursor-pointer","aria-label":m,"aria-selected":r},
3
3
  /* @__PURE__ */e.createElement("span",{style:{fontFamily:c?o.value:void 0},className:"flex-1 truncate"},o.label),o.category&&/* @__PURE__ */e.createElement("span",{className:"text-xs text-muted-foreground capitalize"},o.category),
4
4
  /* @__PURE__ */e.createElement(t,{className:a("ml-2 h-4 w-4",r?"opacity-100":"opacity-0")}))});function p({value:t,onChange:a,apiKey:n,placeholder:s="Select a font...",searchPlaceholder:l="Search fonts...",noResultsText:c="No fonts found.",loadingText:i="Loading fonts...",disabled:m=!1,className:f,dropdownWidth:u,maxFonts:p=500,onError:h}){const{fonts:y,isLoading:S,loadFont:E}=d({apiKey:n,maxFonts:p,onError:h});e.useEffect(()=>{t&&E(t)},[t,E]);const v=y;/* @__PURE__ */
5
5
  return e.createElement(r,{options:v,value:t,onChange:a,defaultValueLabel:s,placeholder:l,noResultsLabel:c,disabled:m||S,className:f,dropdownWidth:u,renderTrigger:({selectedItem:t})=>S?/* @__PURE__ */e.createElement("span",{className:"flex items-center gap-2 text-muted-foreground"},/* @__PURE__ */e.createElement(o,{className:"h-4 w-4 animate-spin"}),i):t?/* @__PURE__ */e.createElement("span",{style:{fontFamily:t.value}},t.label):/* @__PURE__ */e.createElement("span",{className:"text-muted-foreground"},s),renderItem:({item:t,isSelected:o,onSelect:a})=>/* @__PURE__ */e.createElement(g,{font:t,isSelected:o,onSelect:a})})}export{p as F,g as a,u as c,i as g,f as l,m as s,d as u};
6
- //# sourceMappingURL=font-picker.Dwwe5av-.js.map
6
+ //# sourceMappingURL=font-picker.CVZovtmt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"font-picker.Dwwe5av-.js","sources":["../../../src/components/font-picker/font-utils.ts","../../../src/components/font-picker/use-font-options.ts","../../../src/components/font-picker/font-picker-item.tsx","../../../src/components/font-picker/font-picker.tsx"],"sourcesContent":["import { FontOption } from './types';\n\n// Cache keys for localStorage\nconst FONT_CACHE_KEY = 'brainfish-google-fonts-cache';\nconst FONT_CACHE_TIMESTAMP_KEY = 'brainfish-google-fonts-cache-timestamp';\nconst FONT_CACHE_DURATION_MS = 24 * 60 * 60 * 1000; // 24 hours\n\n// Cache for loaded font stylesheets to prevent duplicate loads\nconst loadedFonts = new Set<string>();\n\n/**\n * Get cached fonts from localStorage\n */\nexport const getCachedFonts = (): FontOption[] | null => {\n try {\n const timestamp = localStorage.getItem(FONT_CACHE_TIMESTAMP_KEY);\n if (!timestamp) return null;\n\n const cacheAge = Date.now() - parseInt(timestamp, 10);\n if (cacheAge > FONT_CACHE_DURATION_MS) {\n localStorage.removeItem(FONT_CACHE_KEY);\n localStorage.removeItem(FONT_CACHE_TIMESTAMP_KEY);\n\n return null;\n }\n\n const cached = localStorage.getItem(FONT_CACHE_KEY);\n if (!cached) return null;\n\n return JSON.parse(cached) as FontOption[];\n } catch {\n return null;\n }\n};\n\n/**\n * Save fonts to localStorage cache\n */\nexport const setCachedFonts = (fonts: FontOption[]): void => {\n try {\n localStorage.setItem(FONT_CACHE_KEY, JSON.stringify(fonts));\n localStorage.setItem(FONT_CACHE_TIMESTAMP_KEY, Date.now().toString());\n } catch {\n // localStorage might be full or unavailable, ignore\n }\n};\n\n/**\n * Load a Google Font stylesheet dynamically\n */\nexport const loadFont = (fontFamily: string): void => {\n if (loadedFonts.has(fontFamily)) return;\n\n const link = document.createElement('link');\n link.href = `https://fonts.googleapis.com/css2?family=${fontFamily.replace(/ /g, '+')}&display=swap`;\n link.rel = 'stylesheet';\n document.head.appendChild(link);\n loadedFonts.add(fontFamily);\n};\n\n/**\n * Clear the font cache from localStorage\n * Useful for forcing a fresh fetch of fonts\n */\nexport const clearFontCache = (): void => {\n try {\n localStorage.removeItem(FONT_CACHE_KEY);\n localStorage.removeItem(FONT_CACHE_TIMESTAMP_KEY);\n } catch {\n // localStorage might be unavailable, ignore\n }\n};\n","import * as React from 'react';\n\nimport { FontOption } from './types';\nimport { getCachedFonts, setCachedFonts, loadFont } from './font-utils';\n\nexport interface UseFontOptionsProps {\n apiKey: string;\n maxFonts?: number;\n onError?: (error: Error) => void;\n}\n\nexport interface UseFontOptionsReturn {\n fonts: FontOption[];\n isLoading: boolean;\n loadFont: typeof loadFont;\n}\n\n/**\n * Hook to fetch and manage Google Fonts options\n * Handles caching, loading state, and font stylesheet loading\n */\nexport function useFontOptions({ apiKey, maxFonts = 500, onError }: UseFontOptionsProps): UseFontOptionsReturn {\n const [fonts, setFonts] = React.useState<FontOption[]>([]);\n const [isLoading, setIsLoading] = React.useState(true);\n\n // Stabilize onError callback reference to prevent effect re-runs when\n // consumers pass inline functions (which create new references on every render)\n const onErrorRef = React.useRef(onError);\n React.useEffect(() => {\n onErrorRef.current = onError;\n }, [onError]);\n\n React.useEffect(() => {\n const fetchFonts = async () => {\n // Check cache first\n const cachedFonts = getCachedFonts();\n if (cachedFonts && cachedFonts.length > 0) {\n setFonts(cachedFonts.slice(0, maxFonts));\n setIsLoading(false);\n\n return;\n }\n\n try {\n const response = await fetch(`https://www.googleapis.com/webfonts/v1/webfonts?key=${apiKey}&sort=popularity`);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch fonts: ${response.statusText}`);\n }\n\n const data = await response.json();\n\n const fontOptions: FontOption[] = data.items.map((fontItem: { family: string; category: string; variants: string[] }) => ({\n value: fontItem.family,\n label: fontItem.family,\n category: fontItem.category,\n variants: fontItem.variants,\n }));\n\n // Cache all fonts, but only display up to maxFonts\n setCachedFonts(fontOptions);\n setFonts(fontOptions.slice(0, maxFonts));\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch fonts');\n\n console.error('FontPicker: Failed to fetch Google Fonts', error);\n onErrorRef.current?.(error);\n } finally {\n setIsLoading(false);\n }\n };\n\n void fetchFonts();\n }, [apiKey, maxFonts]);\n\n return { fonts, isLoading, loadFont };\n}\n","import * as React from 'react';\nimport { Check } from '@phosphor-icons/react';\n\nimport { FontOption } from './types';\nimport { loadFont } from './font-utils';\n\nimport { cn } from '@/lib/utils';\nimport { CommandItem } from '@/components/ui/command';\n\nexport interface FontPickerItemProps {\n font: FontOption;\n isSelected: boolean;\n onSelect: () => void;\n}\n\n/**\n * Individual font item in the dropdown list\n * Loads font on mount for preview using Intersection Observer\n * Memoized to prevent unnecessary re-renders\n */\nexport const FontPickerItem = React.memo(function FontPickerItem({ font, isSelected, onSelect }: FontPickerItemProps) {\n const itemRef = React.useRef<HTMLDivElement>(null);\n const [isVisible, setIsVisible] = React.useState(false);\n\n // Use Intersection Observer to lazy-load fonts\n React.useEffect(() => {\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) {\n setIsVisible(true);\n observer.disconnect();\n }\n },\n { threshold: 0.1 },\n );\n\n if (itemRef.current) {\n observer.observe(itemRef.current);\n }\n\n return () => observer.disconnect();\n }, []);\n\n // Load font when visible\n React.useEffect(() => {\n if (isVisible) {\n loadFont(font.value);\n }\n }, [isVisible, font.value]);\n\n // Build accessible label\n const ariaLabel = `Select ${font.label} font${font.category ? `, ${font.category} category` : ''}`;\n\n return (\n <CommandItem\n ref={itemRef}\n value={font.label}\n onSelect={onSelect}\n className=\"cursor-pointer\"\n aria-label={ariaLabel}\n aria-selected={isSelected}\n >\n <span style={{ fontFamily: isVisible ? font.value : undefined }} className=\"flex-1 truncate\">\n {font.label}\n </span>\n {font.category && <span className=\"text-xs text-muted-foreground capitalize\">{font.category}</span>}\n <Check className={cn('ml-2 h-4 w-4', isSelected ? 'opacity-100' : 'opacity-0')} />\n </CommandItem>\n );\n});\n","import * as React from 'react';\nimport { SpinnerGap } from '@phosphor-icons/react';\n\nimport { useFontOptions } from './use-font-options';\nimport { FontPickerItem } from './font-picker-item';\n\nimport { Combobox } from '@/components/combobox/combobox';\n\nexport interface FontPickerProps {\n /** Currently selected font family */\n value?: string;\n /** Callback when font selection changes */\n onChange?: (fontFamily: string) => void;\n /** Google Fonts API key (required) */\n apiKey: string;\n /** Placeholder text when no font is selected */\n placeholder?: string;\n /** Text shown in search input */\n searchPlaceholder?: string;\n /** Text shown when no fonts match the search */\n noResultsText?: string;\n /** Text shown while fonts are loading */\n loadingText?: string;\n /** Whether the picker is disabled */\n disabled?: boolean;\n /** Additional CSS classes for the trigger button */\n className?: string;\n /** Width of the dropdown (defaults to trigger width) */\n dropdownWidth?: number;\n /** Maximum number of fonts to display (for performance) */\n maxFonts?: number;\n /** Callback when an error occurs fetching fonts */\n onError?: (error: Error) => void;\n}\n\n/**\n * FontPicker - A searchable dropdown for selecting Google Fonts\n *\n * @example\n * ```tsx\n * const [font, setFont] = useState('Inter');\n *\n * <FontPicker\n * apiKey=\"YOUR_API_KEY\"\n * value={font}\n * onChange={setFont}\n * placeholder=\"Select a font\"\n * />\n * ```\n */\nexport function FontPicker({\n value,\n onChange,\n apiKey,\n placeholder = 'Select a font...',\n searchPlaceholder = 'Search fonts...',\n noResultsText = 'No fonts found.',\n loadingText = 'Loading fonts...',\n disabled = false,\n className,\n dropdownWidth,\n maxFonts = 500,\n onError,\n}: FontPickerProps) {\n const { fonts, isLoading, loadFont } = useFontOptions({ apiKey, maxFonts, onError });\n\n // Load font stylesheet when selected\n React.useEffect(() => {\n if (value) {\n loadFont(value);\n }\n }, [value, loadFont]);\n\n // fonts already have value/label which Combobox requires\n const options = fonts;\n\n return (\n <Combobox\n options={options}\n value={value}\n onChange={onChange}\n defaultValueLabel={placeholder}\n placeholder={searchPlaceholder}\n noResultsLabel={noResultsText}\n disabled={disabled || isLoading}\n className={className}\n dropdownWidth={dropdownWidth}\n renderTrigger={({ selectedItem }) => {\n if (isLoading) {\n return (\n <span className=\"flex items-center gap-2 text-muted-foreground\">\n <SpinnerGap className=\"h-4 w-4 animate-spin\" />\n {loadingText}\n </span>\n );\n }\n\n if (selectedItem) {\n return <span style={{ fontFamily: selectedItem.value }}>{selectedItem.label}</span>;\n }\n\n return <span className=\"text-muted-foreground\">{placeholder}</span>;\n }}\n renderItem={({ item, isSelected, onSelect }) => (\n <FontPickerItem font={item} isSelected={isSelected} onSelect={onSelect} />\n )}\n />\n );\n}\n\nexport default FontPicker;\n"],"names":["FONT_CACHE_KEY","FONT_CACHE_TIMESTAMP_KEY","loadedFonts","Set","getCachedFonts","timestamp","localStorage","getItem","Date","now","parseInt","removeItem","cached","JSON","parse","setCachedFonts","fonts","setItem","stringify","toString","loadFont","fontFamily","has","link","document","createElement","href","replace","rel","head","appendChild","add","clearFontCache","useFontOptions","apiKey","maxFonts","onError","setFonts","React","useState","isLoading","setIsLoading","onErrorRef","useRef","useEffect","current","async","cachedFonts","length","slice","response","fetch","ok","Error","statusText","fontOptions","json","items","map","fontItem","value","family","label","category","variants","err","error","console","fetchFonts","FontPickerItem","memo","font","isSelected","onSelect","itemRef","isVisible","setIsVisible","observer","IntersectionObserver","entry","isIntersecting","disconnect","threshold","observe","ariaLabel","CommandItem","ref","className","style","Check","cn","FontPicker","onChange","placeholder","searchPlaceholder","noResultsText","loadingText","disabled","dropdownWidth","options","Combobox","defaultValueLabel","noResultsLabel","renderTrigger","selectedItem","SpinnerGap","renderItem","item"],"mappings":"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"}
1
+ {"version":3,"file":"font-picker.CVZovtmt.js","sources":["../../../src/components/font-picker/font-utils.ts","../../../src/components/font-picker/use-font-options.ts","../../../src/components/font-picker/font-picker-item.tsx","../../../src/components/font-picker/font-picker.tsx"],"sourcesContent":["import { FontOption } from './types';\n\n// Cache keys for localStorage\nconst FONT_CACHE_KEY = 'brainfish-google-fonts-cache';\nconst FONT_CACHE_TIMESTAMP_KEY = 'brainfish-google-fonts-cache-timestamp';\nconst FONT_CACHE_DURATION_MS = 24 * 60 * 60 * 1000; // 24 hours\n\n// Cache for loaded font stylesheets to prevent duplicate loads\nconst loadedFonts = new Set<string>();\n\n/**\n * Get cached fonts from localStorage\n */\nexport const getCachedFonts = (): FontOption[] | null => {\n try {\n const timestamp = localStorage.getItem(FONT_CACHE_TIMESTAMP_KEY);\n if (!timestamp) return null;\n\n const cacheAge = Date.now() - parseInt(timestamp, 10);\n if (cacheAge > FONT_CACHE_DURATION_MS) {\n localStorage.removeItem(FONT_CACHE_KEY);\n localStorage.removeItem(FONT_CACHE_TIMESTAMP_KEY);\n\n return null;\n }\n\n const cached = localStorage.getItem(FONT_CACHE_KEY);\n if (!cached) return null;\n\n return JSON.parse(cached) as FontOption[];\n } catch {\n return null;\n }\n};\n\n/**\n * Save fonts to localStorage cache\n */\nexport const setCachedFonts = (fonts: FontOption[]): void => {\n try {\n localStorage.setItem(FONT_CACHE_KEY, JSON.stringify(fonts));\n localStorage.setItem(FONT_CACHE_TIMESTAMP_KEY, Date.now().toString());\n } catch {\n // localStorage might be full or unavailable, ignore\n }\n};\n\n/**\n * Load a Google Font stylesheet dynamically\n */\nexport const loadFont = (fontFamily: string): void => {\n if (loadedFonts.has(fontFamily)) return;\n\n const link = document.createElement('link');\n link.href = `https://fonts.googleapis.com/css2?family=${fontFamily.replace(/ /g, '+')}&display=swap`;\n link.rel = 'stylesheet';\n document.head.appendChild(link);\n loadedFonts.add(fontFamily);\n};\n\n/**\n * Clear the font cache from localStorage\n * Useful for forcing a fresh fetch of fonts\n */\nexport const clearFontCache = (): void => {\n try {\n localStorage.removeItem(FONT_CACHE_KEY);\n localStorage.removeItem(FONT_CACHE_TIMESTAMP_KEY);\n } catch {\n // localStorage might be unavailable, ignore\n }\n};\n","import * as React from 'react';\n\nimport { FontOption } from './types';\nimport { getCachedFonts, setCachedFonts, loadFont } from './font-utils';\n\nexport interface UseFontOptionsProps {\n apiKey: string;\n maxFonts?: number;\n onError?: (error: Error) => void;\n}\n\nexport interface UseFontOptionsReturn {\n fonts: FontOption[];\n isLoading: boolean;\n loadFont: typeof loadFont;\n}\n\n/**\n * Hook to fetch and manage Google Fonts options\n * Handles caching, loading state, and font stylesheet loading\n */\nexport function useFontOptions({ apiKey, maxFonts = 500, onError }: UseFontOptionsProps): UseFontOptionsReturn {\n const [fonts, setFonts] = React.useState<FontOption[]>([]);\n const [isLoading, setIsLoading] = React.useState(true);\n\n // Stabilize onError callback reference to prevent effect re-runs when\n // consumers pass inline functions (which create new references on every render)\n const onErrorRef = React.useRef(onError);\n React.useEffect(() => {\n onErrorRef.current = onError;\n }, [onError]);\n\n React.useEffect(() => {\n const fetchFonts = async () => {\n // Check cache first\n const cachedFonts = getCachedFonts();\n if (cachedFonts && cachedFonts.length > 0) {\n setFonts(cachedFonts.slice(0, maxFonts));\n setIsLoading(false);\n\n return;\n }\n\n try {\n const response = await fetch(`https://www.googleapis.com/webfonts/v1/webfonts?key=${apiKey}&sort=popularity`);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch fonts: ${response.statusText}`);\n }\n\n const data = await response.json();\n\n const fontOptions: FontOption[] = data.items.map((fontItem: { family: string; category: string; variants: string[] }) => ({\n value: fontItem.family,\n label: fontItem.family,\n category: fontItem.category,\n variants: fontItem.variants,\n }));\n\n // Cache all fonts, but only display up to maxFonts\n setCachedFonts(fontOptions);\n setFonts(fontOptions.slice(0, maxFonts));\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch fonts');\n\n console.error('FontPicker: Failed to fetch Google Fonts', error);\n onErrorRef.current?.(error);\n } finally {\n setIsLoading(false);\n }\n };\n\n void fetchFonts();\n }, [apiKey, maxFonts]);\n\n return { fonts, isLoading, loadFont };\n}\n","import * as React from 'react';\nimport { Check } from '@phosphor-icons/react';\n\nimport { FontOption } from './types';\nimport { loadFont } from './font-utils';\n\nimport { cn } from '@/lib/utils';\nimport { CommandItem } from '@/components/ui/command';\n\nexport interface FontPickerItemProps {\n font: FontOption;\n isSelected: boolean;\n onSelect: () => void;\n}\n\n/**\n * Individual font item in the dropdown list\n * Loads font on mount for preview using Intersection Observer\n * Memoized to prevent unnecessary re-renders\n */\nexport const FontPickerItem = React.memo(function FontPickerItem({ font, isSelected, onSelect }: FontPickerItemProps) {\n const itemRef = React.useRef<HTMLDivElement>(null);\n const [isVisible, setIsVisible] = React.useState(false);\n\n // Use Intersection Observer to lazy-load fonts\n React.useEffect(() => {\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) {\n setIsVisible(true);\n observer.disconnect();\n }\n },\n { threshold: 0.1 },\n );\n\n if (itemRef.current) {\n observer.observe(itemRef.current);\n }\n\n return () => observer.disconnect();\n }, []);\n\n // Load font when visible\n React.useEffect(() => {\n if (isVisible) {\n loadFont(font.value);\n }\n }, [isVisible, font.value]);\n\n // Build accessible label\n const ariaLabel = `Select ${font.label} font${font.category ? `, ${font.category} category` : ''}`;\n\n return (\n <CommandItem\n ref={itemRef}\n value={font.label}\n onSelect={onSelect}\n className=\"cursor-pointer\"\n aria-label={ariaLabel}\n aria-selected={isSelected}\n >\n <span style={{ fontFamily: isVisible ? font.value : undefined }} className=\"flex-1 truncate\">\n {font.label}\n </span>\n {font.category && <span className=\"text-xs text-muted-foreground capitalize\">{font.category}</span>}\n <Check className={cn('ml-2 h-4 w-4', isSelected ? 'opacity-100' : 'opacity-0')} />\n </CommandItem>\n );\n});\n","import * as React from 'react';\nimport { SpinnerGap } from '@phosphor-icons/react';\n\nimport { useFontOptions } from './use-font-options';\nimport { FontPickerItem } from './font-picker-item';\n\nimport { Combobox } from '@/components/combobox/combobox';\n\nexport interface FontPickerProps {\n /** Currently selected font family */\n value?: string;\n /** Callback when font selection changes */\n onChange?: (fontFamily: string) => void;\n /** Google Fonts API key (required) */\n apiKey: string;\n /** Placeholder text when no font is selected */\n placeholder?: string;\n /** Text shown in search input */\n searchPlaceholder?: string;\n /** Text shown when no fonts match the search */\n noResultsText?: string;\n /** Text shown while fonts are loading */\n loadingText?: string;\n /** Whether the picker is disabled */\n disabled?: boolean;\n /** Additional CSS classes for the trigger button */\n className?: string;\n /** Width of the dropdown (defaults to trigger width) */\n dropdownWidth?: number;\n /** Maximum number of fonts to display (for performance) */\n maxFonts?: number;\n /** Callback when an error occurs fetching fonts */\n onError?: (error: Error) => void;\n}\n\n/**\n * FontPicker - A searchable dropdown for selecting Google Fonts\n *\n * @example\n * ```tsx\n * const [font, setFont] = useState('Inter');\n *\n * <FontPicker\n * apiKey=\"YOUR_API_KEY\"\n * value={font}\n * onChange={setFont}\n * placeholder=\"Select a font\"\n * />\n * ```\n */\nexport function FontPicker({\n value,\n onChange,\n apiKey,\n placeholder = 'Select a font...',\n searchPlaceholder = 'Search fonts...',\n noResultsText = 'No fonts found.',\n loadingText = 'Loading fonts...',\n disabled = false,\n className,\n dropdownWidth,\n maxFonts = 500,\n onError,\n}: FontPickerProps) {\n const { fonts, isLoading, loadFont } = useFontOptions({ apiKey, maxFonts, onError });\n\n // Load font stylesheet when selected\n React.useEffect(() => {\n if (value) {\n loadFont(value);\n }\n }, [value, loadFont]);\n\n // fonts already have value/label which Combobox requires\n const options = fonts;\n\n return (\n <Combobox\n options={options}\n value={value}\n onChange={onChange}\n defaultValueLabel={placeholder}\n placeholder={searchPlaceholder}\n noResultsLabel={noResultsText}\n disabled={disabled || isLoading}\n className={className}\n dropdownWidth={dropdownWidth}\n renderTrigger={({ selectedItem }) => {\n if (isLoading) {\n return (\n <span className=\"flex items-center gap-2 text-muted-foreground\">\n <SpinnerGap className=\"h-4 w-4 animate-spin\" />\n {loadingText}\n </span>\n );\n }\n\n if (selectedItem) {\n return <span style={{ fontFamily: selectedItem.value }}>{selectedItem.label}</span>;\n }\n\n return <span className=\"text-muted-foreground\">{placeholder}</span>;\n }}\n renderItem={({ item, isSelected, onSelect }) => (\n <FontPickerItem font={item} isSelected={isSelected} onSelect={onSelect} />\n )}\n />\n );\n}\n\nexport default FontPicker;\n"],"names":["FONT_CACHE_KEY","FONT_CACHE_TIMESTAMP_KEY","loadedFonts","Set","getCachedFonts","timestamp","localStorage","getItem","Date","now","parseInt","removeItem","cached","JSON","parse","setCachedFonts","fonts","setItem","stringify","toString","loadFont","fontFamily","has","link","document","createElement","href","replace","rel","head","appendChild","add","clearFontCache","useFontOptions","apiKey","maxFonts","onError","setFonts","React","useState","isLoading","setIsLoading","onErrorRef","useRef","useEffect","current","async","cachedFonts","length","slice","response","fetch","ok","Error","statusText","fontOptions","json","items","map","fontItem","value","family","label","category","variants","err","error","console","fetchFonts","FontPickerItem","memo","font","isSelected","onSelect","itemRef","isVisible","setIsVisible","observer","IntersectionObserver","entry","isIntersecting","disconnect","threshold","observe","ariaLabel","CommandItem","ref","className","style","Check","cn","FontPicker","onChange","placeholder","searchPlaceholder","noResultsText","loadingText","disabled","dropdownWidth","options","Combobox","defaultValueLabel","noResultsLabel","renderTrigger","selectedItem","SpinnerGap","renderItem","item"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import e,{useState as t,useEffect as a,useId as r}from"react";import{cva as n}from"class-variance-authority";import{c as o}from"./utils.C6Qu-kwd.js";import{_ as s}from"./extends.DPdBf6DS.js";function i(e){return i=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},i(e)}function l(e,t){return l=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},l(e,t)}function f(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(f=function(){return!!e})()}function u(e){var t="function"==typeof Map?new Map:void 0;return u=function(e){if(null===e||!function(e){try{return-1!==Function.toString.call(e).indexOf("[native code]")}catch(t){return"function"==typeof e}}(e))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,a)}function a(){return function(e,t,a){if(f())return Reflect.construct.apply(null,arguments);var r=[null];r.push.apply(r,t);var n=new(e.bind.apply(e,r));return a&&l(n,a.prototype),n}(e,arguments,i(this).constructor)}return a.prototype=Object.create(e.prototype,{constructor:{value:a,enumerable:!1,writable:!0,configurable:!0}}),l(a,e)},u(e)}var p={1:"Passed invalid arguments to hsl, please pass multiple numbers e.g. hsl(360, 0.75, 0.4) or an object e.g. rgb({ hue: 255, saturation: 0.4, lightness: 0.75 }).\n\n",2:"Passed invalid arguments to hsla, please pass multiple numbers e.g. hsla(360, 0.75, 0.4, 0.7) or an object e.g. rgb({ hue: 255, saturation: 0.4, lightness: 0.75, alpha: 0.7 }).\n\n",3:"Passed an incorrect argument to a color function, please pass a string representation of a color.\n\n",4:"Couldn't generate valid rgb string from %s, it returned %s.\n\n",5:"Couldn't parse the color string. Please provide the color as a string in hex, rgb, rgba, hsl or hsla notation.\n\n",6:"Passed invalid arguments to rgb, please pass multiple numbers e.g. rgb(255, 205, 100) or an object e.g. rgb({ red: 255, green: 205, blue: 100 }).\n\n",7:"Passed invalid arguments to rgba, please pass multiple numbers e.g. rgb(255, 205, 100, 0.75) or an object e.g. rgb({ red: 255, green: 205, blue: 100, alpha: 0.75 }).\n\n",8:"Passed invalid argument to toColorString, please pass a RgbColor, RgbaColor, HslColor or HslaColor object.\n\n",9:"Please provide a number of steps to the modularScale helper.\n\n",10:"Please pass a number or one of the predefined scales to the modularScale helper as the ratio.\n\n",11:'Invalid value passed as base to modularScale, expected number or em string but got "%s"\n\n',12:'Expected a string ending in "px" or a number passed as the first argument to %s(), got "%s" instead.\n\n',13:'Expected a string ending in "px" or a number passed as the second argument to %s(), got "%s" instead.\n\n',14:'Passed invalid pixel value ("%s") to %s(), please pass a value like "12px" or 12.\n\n',15:'Passed invalid base value ("%s") to %s(), please pass a value like "12px" or 12.\n\n',16:"You must provide a template to this method.\n\n",17:"You passed an unsupported selector state to this method.\n\n",18:"minScreen and maxScreen must be provided as stringified numbers with the same units.\n\n",19:"fromSize and toSize must be provided as stringified numbers with the same units.\n\n",20:"expects either an array of objects or a single object with the properties prop, fromSize, and toSize.\n\n",21:"expects the objects in the first argument array to have the properties `prop`, `fromSize`, and `toSize`.\n\n",22:"expects the first argument object to have the properties `prop`, `fromSize`, and `toSize`.\n\n",23:"fontFace expects a name of a font-family.\n\n",24:"fontFace expects either the path to the font file(s) or a name of a local copy.\n\n",25:"fontFace expects localFonts to be an array.\n\n",26:"fontFace expects fileFormats to be an array.\n\n",27:"radialGradient requries at least 2 color-stops to properly render.\n\n",28:"Please supply a filename to retinaImage() as the first argument.\n\n",29:"Passed invalid argument to triangle, please pass correct pointingDirection e.g. 'right'.\n\n",30:"Passed an invalid value to `height` or `width`. Please provide a pixel based unit.\n\n",31:"The animation shorthand only takes 8 arguments. See the specification for more information: http://mdn.io/animation\n\n",32:"To pass multiple animations please supply them in arrays, e.g. animation(['rotate', '2s'], ['move', '1s'])\nTo pass a single animation please supply them in simple values, e.g. animation('rotate', '2s')\n\n",33:"The animation shorthand arrays can only have 8 elements. See the specification for more information: http://mdn.io/animation\n\n",34:"borderRadius expects a radius value as a string or number as the second argument.\n\n",35:'borderRadius expects one of "top", "bottom", "left" or "right" as the first argument.\n\n',36:"Property must be a string value.\n\n",37:"Syntax Error at %s.\n\n",38:"Formula contains a function that needs parentheses at %s.\n\n",39:"Formula is missing closing parenthesis at %s.\n\n",40:"Formula has too many closing parentheses at %s.\n\n",41:"All values in a formula must have the same unit or be unitless.\n\n",42:"Please provide a number of steps to the modularScale helper.\n\n",43:"Please pass a number or one of the predefined scales to the modularScale helper as the ratio.\n\n",44:"Invalid value passed as base to modularScale, expected number or em/rem string but got %s.\n\n",45:"Passed invalid argument to hslToColorString, please pass a HslColor or HslaColor object.\n\n",46:"Passed invalid argument to rgbToColorString, please pass a RgbColor or RgbaColor object.\n\n",47:"minScreen and maxScreen must be provided as stringified numbers with the same units.\n\n",48:"fromSize and toSize must be provided as stringified numbers with the same units.\n\n",49:"Expects either an array of objects or a single object with the properties prop, fromSize, and toSize.\n\n",50:"Expects the objects in the first argument array to have the properties prop, fromSize, and toSize.\n\n",51:"Expects the first argument object to have the properties prop, fromSize, and toSize.\n\n",52:"fontFace expects either the path to the font file(s) or a name of a local copy.\n\n",53:"fontFace expects localFonts to be an array.\n\n",54:"fontFace expects fileFormats to be an array.\n\n",55:"fontFace expects a name of a font-family.\n\n",56:"linearGradient requries at least 2 color-stops to properly render.\n\n",57:"radialGradient requries at least 2 color-stops to properly render.\n\n",58:"Please supply a filename to retinaImage() as the first argument.\n\n",59:"Passed invalid argument to triangle, please pass correct pointingDirection e.g. 'right'.\n\n",60:"Passed an invalid value to `height` or `width`. Please provide a pixel based unit.\n\n",61:"Property must be a string value.\n\n",62:"borderRadius expects a radius value as a string or number as the second argument.\n\n",63:'borderRadius expects one of "top", "bottom", "left" or "right" as the first argument.\n\n',64:"The animation shorthand only takes 8 arguments. See the specification for more information: http://mdn.io/animation.\n\n",65:"To pass multiple animations please supply them in arrays, e.g. animation(['rotate', '2s'], ['move', '1s'])\\nTo pass a single animation please supply them in simple values, e.g. animation('rotate', '2s').\n\n",66:"The animation shorthand arrays can only have 8 elements. See the specification for more information: http://mdn.io/animation.\n\n",67:"You must provide a template to this method.\n\n",68:"You passed an unsupported selector state to this method.\n\n",69:'Expected a string ending in "px" or a number passed as the first argument to %s(), got %s instead.\n\n',70:'Expected a string ending in "px" or a number passed as the second argument to %s(), got %s instead.\n\n',71:'Passed invalid pixel value %s to %s(), please pass a value like "12px" or 12.\n\n',72:'Passed invalid base value %s to %s(), please pass a value like "12px" or 12.\n\n',73:"Please provide a valid CSS variable.\n\n",74:"CSS variable not found and no default was provided.\n\n",75:"important requires a valid style object, got a %s instead.\n\n",76:"fromSize and toSize must be provided as stringified numbers with the same units as minScreen and maxScreen.\n\n",77:'remToPx expects a value in "rem" but you provided it in "%s".\n\n',78:'base must be set in "px" or "%" but you set it in "%s".\n'};function d(){for(var e=arguments.length,t=new Array(e),a=0;a<e;a++)t[a]=arguments[a];var r,n=t[0],o=[];for(r=1;r<t.length;r+=1)o.push(t[r]);return o.forEach(function(e){n=n.replace(/%[a-z]/,e)}),n}var c=/*#__PURE__*/function(e){var t,a;function r(t){var a;if("production"===process.env.NODE_ENV)a=e.call(this,"An error occurred. See https://github.com/styled-components/polished/blob/main/src/internalHelpers/errors.md#"+t+" for more information.")||this;else{for(var r=arguments.length,n=new Array(r>1?r-1:0),o=1;o<r;o++)n[o-1]=arguments[o];a=e.call(this,d.apply(void 0,[p[t]].concat(n)))||this}return function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(a)}return a=e,(t=r).prototype=Object.create(a.prototype),t.prototype.constructor=t,l(t,a),r}(/*#__PURE__*/u(Error)),m=/--[\S]*/g;function h(e,t){if(!e||!e.match(m))throw new c(73);var a;if("undefined"!=typeof document&&null!==document.documentElement&&(a=getComputedStyle(document.documentElement).getPropertyValue(e)),a)return a.trim();throw new c(74)}function b(e){return Math.round(255*e)}function g(e,t,a){return b(e)+","+b(t)+","+b(a)}function v(e,t,a,r){if(void 0===r&&(r=g),0===t)return r(a,a,a);var n=(e%360+360)%360/60,o=(1-Math.abs(2*a-1))*t,s=o*(1-Math.abs(n%2-1)),i=0,l=0,f=0;n>=0&&n<1?(i=o,l=s):n>=1&&n<2?(i=s,l=o):n>=2&&n<3?(l=o,f=s):n>=3&&n<4?(l=s,f=o):n>=4&&n<5?(i=s,f=o):n>=5&&n<6&&(i=o,f=s);var u=a-o/2;return r(i+u,l+u,f+u)}var y={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"00ffff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"0000ff",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"00ffff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"ff00ff",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"639",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"};var C=/^#[a-fA-F0-9]{6}$/,w=/^#[a-fA-F0-9]{8}$/,x=/^#[a-fA-F0-9]{3}$/,F=/^#[a-fA-F0-9]{4}$/,S=/^rgb\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*\)$/i,k=/^rgb(?:a)?\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,|\/)\s*([-+]?\d*[.]?\d+[%]?)\s*\)$/i,I=/^hsl\(\s*(\d{0,3}[.]?[0-9]+(?:deg)?)\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*\)$/i,L=/^hsl(?:a)?\(\s*(\d{0,3}[.]?[0-9]+(?:deg)?)\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*(?:,|\/)\s*([-+]?\d*[.]?\d+[%]?)\s*\)$/i;function P(e){if("string"!=typeof e)throw new c(3);var t=function(e){if("string"!=typeof e)return e;var t=e.toLowerCase();return y[t]?"#"+y[t]:e}(e);if(t.match(C))return{red:parseInt(""+t[1]+t[2],16),green:parseInt(""+t[3]+t[4],16),blue:parseInt(""+t[5]+t[6],16)};if(t.match(w)){var a=parseFloat((parseInt(""+t[7]+t[8],16)/255).toFixed(2));return{red:parseInt(""+t[1]+t[2],16),green:parseInt(""+t[3]+t[4],16),blue:parseInt(""+t[5]+t[6],16),alpha:a}}if(t.match(x))return{red:parseInt(""+t[1]+t[1],16),green:parseInt(""+t[2]+t[2],16),blue:parseInt(""+t[3]+t[3],16)};if(t.match(F)){var r=parseFloat((parseInt(""+t[4]+t[4],16)/255).toFixed(2));return{red:parseInt(""+t[1]+t[1],16),green:parseInt(""+t[2]+t[2],16),blue:parseInt(""+t[3]+t[3],16),alpha:r}}var n=S.exec(t);if(n)return{red:parseInt(""+n[1],10),green:parseInt(""+n[2],10),blue:parseInt(""+n[3],10)};var o=k.exec(t.substring(0,50));if(o)return{red:parseInt(""+o[1],10),green:parseInt(""+o[2],10),blue:parseInt(""+o[3],10),alpha:parseFloat(""+o[4])>1?parseFloat(""+o[4])/100:parseFloat(""+o[4])};var s=I.exec(t);if(s){var i="rgb("+v(parseInt(""+s[1],10),parseInt(""+s[2],10)/100,parseInt(""+s[3],10)/100)+")",l=S.exec(i);if(!l)throw new c(4,t,i);return{red:parseInt(""+l[1],10),green:parseInt(""+l[2],10),blue:parseInt(""+l[3],10)}}var f=L.exec(t.substring(0,50));if(f){var u="rgb("+v(parseInt(""+f[1],10),parseInt(""+f[2],10)/100,parseInt(""+f[3],10)/100)+")",p=S.exec(u);if(!p)throw new c(4,t,u);return{red:parseInt(""+p[1],10),green:parseInt(""+p[2],10),blue:parseInt(""+p[3],10),alpha:parseFloat(""+f[4])>1?parseFloat(""+f[4])/100:parseFloat(""+f[4])}}throw new c(5)}function j(e){return function(e){var t,a=e.red/255,r=e.green/255,n=e.blue/255,o=Math.max(a,r,n),s=Math.min(a,r,n),i=(o+s)/2;if(o===s)return void 0!==e.alpha?{hue:0,saturation:0,lightness:i,alpha:e.alpha}:{hue:0,saturation:0,lightness:i};var l=o-s,f=i>.5?l/(2-o-s):l/(o+s);switch(o){case a:t=(r-n)/l+(r<n?6:0);break;case r:t=(n-a)/l+2;break;default:t=(a-r)/l+4}return t*=60,void 0!==e.alpha?{hue:t,saturation:f,lightness:i,alpha:e.alpha}:{hue:t,saturation:f,lightness:i}}(P(e))}var E=function(e){return 7===e.length&&e[1]===e[2]&&e[3]===e[4]&&e[5]===e[6]?"#"+e[1]+e[3]+e[5]:e};function z(e){var t=e.toString(16);return 1===t.length?"0"+t:t}function M(e){return z(Math.round(255*e))}function O(e,t,a){return E("#"+M(e)+M(t)+M(a))}function H(e,t,a){return v(e,t,a,O)}function q(e,t,a){if("number"==typeof e&&"number"==typeof t&&"number"==typeof a)return E("#"+z(e)+z(t)+z(a));if("object"==typeof e&&void 0===t&&void 0===a)return E("#"+z(e.red)+z(e.green)+z(e.blue));throw new c(6)}function $(e,t,a,r){if("object"==typeof e&&void 0===t&&void 0===a&&void 0===r)return e.alpha>=1?q(e.red,e.green,e.blue):"rgba("+e.red+","+e.green+","+e.blue+","+e.alpha+")";throw new c(7)}function T(e){if("object"!=typeof e)throw new c(8);if(function(e){return"number"==typeof e.red&&"number"==typeof e.green&&"number"==typeof e.blue&&"number"==typeof e.alpha}(e))return $(e);if(function(e){return"number"==typeof e.red&&"number"==typeof e.green&&"number"==typeof e.blue&&("number"!=typeof e.alpha||void 0===e.alpha)}(e))return q(e);if(function(e){return"number"==typeof e.hue&&"number"==typeof e.saturation&&"number"==typeof e.lightness&&"number"==typeof e.alpha}(e))return function(e,t,a,r){if("object"==typeof e&&void 0===t&&void 0===a&&void 0===r)return e.alpha>=1?H(e.hue,e.saturation,e.lightness):"rgba("+v(e.hue,e.saturation,e.lightness)+","+e.alpha+")";throw new c(2)}(e);if(function(e){return"number"==typeof e.hue&&"number"==typeof e.saturation&&"number"==typeof e.lightness&&("number"!=typeof e.alpha||void 0===e.alpha)}(e))return function(e,t,a){if("object"==typeof e&&void 0===t&&void 0===a)return H(e.hue,e.saturation,e.lightness);throw new c(1)}(e);throw new c(8)}function V(e,t,a){return function(){var r=a.concat(Array.prototype.slice.call(arguments));return r.length>=t?e.apply(this,r):V(e,t,r)}}function R(e){return V(e,e.length,[])}function _(e,t,a){return Math.max(e,Math.min(t,a))}R(function(e,t){if("transparent"===t)return t;var a=j(t);return T(s({},a,{hue:a.hue+parseFloat(e)}))}),R(function(e,t){if("transparent"===t)return t;var a=j(t);return T(s({},a,{lightness:_(0,1,a.lightness-parseFloat(e))}))}),R(function(e,t){if("transparent"===t)return t;var a=j(t);return T(s({},a,{saturation:_(0,1,a.saturation-parseFloat(e))}))}),R(function(e,t){if("transparent"===t)return t;var a=j(t);return T(s({},a,{lightness:_(0,1,a.lightness+parseFloat(e))}))});var A=R(function(e,t,a){if("transparent"===t)return a;if("transparent"===a)return t;if(0===e)return a;var r=P(t),n=s({},r,{alpha:"number"==typeof r.alpha?r.alpha:1}),o=P(a),i=s({},o,{alpha:"number"==typeof o.alpha?o.alpha:1}),l=n.alpha-i.alpha,f=2*parseFloat(e)-1,u=((f*l===-1?f:f+l)/(1+f*l)+1)/2,p=1-u;return $({red:Math.floor(n.red*u+i.red*p),green:Math.floor(n.green*u+i.green*p),blue:Math.floor(n.blue*u+i.blue*p),alpha:n.alpha*parseFloat(e)+i.alpha*(1-parseFloat(e))})});R(function(e,t){if("transparent"===t)return t;var a=P(t),r="number"==typeof a.alpha?a.alpha:1;return $(s({},a,{alpha:_(0,1,(100*r+100*parseFloat(e))/100)}))}),R(function(e,t){if("transparent"===t)return t;var a=j(t);return T(s({},a,{saturation:_(0,1,a.saturation+parseFloat(e))}))}),R(function(e,t){return"transparent"===t?t:T(s({},j(t),{hue:parseFloat(e)}))}),R(function(e,t){return"transparent"===t?t:T(s({},j(t),{lightness:parseFloat(e)}))}),R(function(e,t){return"transparent"===t?t:T(s({},j(t),{saturation:parseFloat(e)}))}),R(function(e,t){return"transparent"===t?t:A(parseFloat(e),"rgb(0, 0, 0)",t)}),R(function(e,t){return"transparent"===t?t:A(parseFloat(e),"rgb(255, 255, 255)",t)}),R(function(e,t){if("transparent"===t)return t;var a=P(t),r="number"==typeof a.alpha?a.alpha:1;return $(s({},a,{alpha:_(0,1,+(100*r-100*parseFloat(e)).toFixed(2)/100)}))});const N=(e,r)=>{const[n,o]=t(`var(${r})`),s=(()=>{const[e,r]=t(()=>document.documentElement.classList.contains("dark"));return a(()=>{const e=new MutationObserver(()=>{r(document.documentElement.classList.contains("dark"))});return e.observe(document.documentElement,{attributes:!0,attributeFilter:["class"]}),()=>e.disconnect()},[]),e})();return a(()=>{const t=h(e),a=h(r);if(t&&a){const a=function(e){if("transparent"===e)return 0;var t=P(e),a=Object.keys(t).map(function(e){var a=t[e]/255;return a<=.03928?a/12.92:Math.pow((a+.055)/1.055,2.4)}),r=a[0],n=a[1],o=a[2];return parseFloat((.2126*r+.7152*n+.0722*o).toFixed(3))}(t.toString());o(a<=.5?s?"var(--bfc-ring)":`var(${e})`:s?`var(${e})`:`var(${r})`)}},[e,r,s]),n},G=n("min-w-5",{variants:{variant:{default:"size-6",gradient:"size-8",disabled:"size-8 grayscale"},loading:{true:"animate-spin"}},defaultVariants:{variant:"default"}}),Z="M16.0127 3.5C16.5221 3.50002 17.0197 3.65584 17.4375 3.94727C17.8553 4.23871 18.1736 4.65182 18.3496 5.12988L20.6445 11.3652L26.876 13.6689L27.0283 13.7246L27.0391 13.7402C27.4497 13.9244 27.8038 14.2171 28.0625 14.5879C28.3539 15.0057 28.5098 15.5032 28.5098 16.0127C28.5097 16.5221 28.3539 17.0197 28.0625 17.4375C27.7711 17.8552 27.3579 18.1737 26.8799 18.3496L20.6426 20.6445L18.334 26.8809C18.158 27.3587 17.8396 27.7712 17.4219 28.0625C17.0042 28.3538 16.5073 28.5097 15.998 28.5098C15.4886 28.5098 14.9911 28.3539 14.5732 28.0625C14.1554 27.771 13.8371 27.358 13.6611 26.8799L11.3652 20.6436L5.12891 18.334V18.333C4.65135 18.1569 4.23846 17.8394 3.94727 17.4219C3.65606 17.0042 3.5001 16.5072 3.5 15.998C3.5 15.4887 3.65596 14.991 3.94727 14.5732C4.2387 14.1554 4.65182 13.8371 5.12988 13.6611L11.3652 11.3652L13.6758 5.12891C13.8518 4.65116 14.1703 4.23855 14.5879 3.94727C15.0057 3.65585 15.5033 3.5 16.0127 3.5ZM13.9463 13.0498L13.9473 13.0508C13.8723 13.2565 13.7535 13.4438 13.5986 13.5986C13.4438 13.7535 13.2565 13.8723 13.0508 13.9473L13.0498 13.9463L7.46875 16.0049L13.0498 18.0625H13.0508C13.2564 18.1374 13.4438 18.2564 13.5986 18.4111C13.7529 18.5654 13.8713 18.7521 13.9463 18.957L16.0049 24.541L18.0684 18.9521L18.1328 18.8027C18.2049 18.6578 18.3001 18.5251 18.415 18.4102C18.5684 18.2568 18.7535 18.1385 18.957 18.0635L24.541 16.0049L18.9521 13.9414C18.7486 13.8664 18.5636 13.7481 18.4102 13.5947C18.2568 13.4413 18.1385 13.2563 18.0635 13.0527L16.0049 7.46875L13.9463 13.0498Z",D=[{offset:"0%",color:"rgba(232, 122, 249, 1)"},{offset:"14%",color:"rgba(251, 191, 37, 1)"},{offset:"33%",color:"rgba(251, 146, 61, 1)"},{offset:"51%",color:"rgba(244, 64, 94, 1)"},{offset:"68%",color:"rgba(140, 93, 246, 1)"},{offset:"83%",color:"rgba(60, 130, 246, 1)"},{offset:"100%",color:"rgba(232, 122, 249, 1)"}];function Y({loading:t,variant:a,className:n,...s}){const i=N("--bfc-primary","--bfc-border"),l="gradient"===a,f="disabled"===a,u=!l&&!f,p=r(),d=e=>l?e:f?"var(--bfc-v2-color-mono-600)":"var(--bfc-primary)";/* @__PURE__ */
1
+ import e,{useState as t,useEffect as a,useId as r}from"react";import{cva as n}from"class-variance-authority";import{c as o}from"./utils.DtKoarLP.js";import{_ as s}from"./extends.DPdBf6DS.js";function i(e){return i=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},i(e)}function l(e,t){return l=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},l(e,t)}function f(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(f=function(){return!!e})()}function u(e){var t="function"==typeof Map?new Map:void 0;return u=function(e){if(null===e||!function(e){try{return-1!==Function.toString.call(e).indexOf("[native code]")}catch(t){return"function"==typeof e}}(e))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,a)}function a(){return function(e,t,a){if(f())return Reflect.construct.apply(null,arguments);var r=[null];r.push.apply(r,t);var n=new(e.bind.apply(e,r));return a&&l(n,a.prototype),n}(e,arguments,i(this).constructor)}return a.prototype=Object.create(e.prototype,{constructor:{value:a,enumerable:!1,writable:!0,configurable:!0}}),l(a,e)},u(e)}var p={1:"Passed invalid arguments to hsl, please pass multiple numbers e.g. hsl(360, 0.75, 0.4) or an object e.g. rgb({ hue: 255, saturation: 0.4, lightness: 0.75 }).\n\n",2:"Passed invalid arguments to hsla, please pass multiple numbers e.g. hsla(360, 0.75, 0.4, 0.7) or an object e.g. rgb({ hue: 255, saturation: 0.4, lightness: 0.75, alpha: 0.7 }).\n\n",3:"Passed an incorrect argument to a color function, please pass a string representation of a color.\n\n",4:"Couldn't generate valid rgb string from %s, it returned %s.\n\n",5:"Couldn't parse the color string. Please provide the color as a string in hex, rgb, rgba, hsl or hsla notation.\n\n",6:"Passed invalid arguments to rgb, please pass multiple numbers e.g. rgb(255, 205, 100) or an object e.g. rgb({ red: 255, green: 205, blue: 100 }).\n\n",7:"Passed invalid arguments to rgba, please pass multiple numbers e.g. rgb(255, 205, 100, 0.75) or an object e.g. rgb({ red: 255, green: 205, blue: 100, alpha: 0.75 }).\n\n",8:"Passed invalid argument to toColorString, please pass a RgbColor, RgbaColor, HslColor or HslaColor object.\n\n",9:"Please provide a number of steps to the modularScale helper.\n\n",10:"Please pass a number or one of the predefined scales to the modularScale helper as the ratio.\n\n",11:'Invalid value passed as base to modularScale, expected number or em string but got "%s"\n\n',12:'Expected a string ending in "px" or a number passed as the first argument to %s(), got "%s" instead.\n\n',13:'Expected a string ending in "px" or a number passed as the second argument to %s(), got "%s" instead.\n\n',14:'Passed invalid pixel value ("%s") to %s(), please pass a value like "12px" or 12.\n\n',15:'Passed invalid base value ("%s") to %s(), please pass a value like "12px" or 12.\n\n',16:"You must provide a template to this method.\n\n",17:"You passed an unsupported selector state to this method.\n\n",18:"minScreen and maxScreen must be provided as stringified numbers with the same units.\n\n",19:"fromSize and toSize must be provided as stringified numbers with the same units.\n\n",20:"expects either an array of objects or a single object with the properties prop, fromSize, and toSize.\n\n",21:"expects the objects in the first argument array to have the properties `prop`, `fromSize`, and `toSize`.\n\n",22:"expects the first argument object to have the properties `prop`, `fromSize`, and `toSize`.\n\n",23:"fontFace expects a name of a font-family.\n\n",24:"fontFace expects either the path to the font file(s) or a name of a local copy.\n\n",25:"fontFace expects localFonts to be an array.\n\n",26:"fontFace expects fileFormats to be an array.\n\n",27:"radialGradient requries at least 2 color-stops to properly render.\n\n",28:"Please supply a filename to retinaImage() as the first argument.\n\n",29:"Passed invalid argument to triangle, please pass correct pointingDirection e.g. 'right'.\n\n",30:"Passed an invalid value to `height` or `width`. Please provide a pixel based unit.\n\n",31:"The animation shorthand only takes 8 arguments. See the specification for more information: http://mdn.io/animation\n\n",32:"To pass multiple animations please supply them in arrays, e.g. animation(['rotate', '2s'], ['move', '1s'])\nTo pass a single animation please supply them in simple values, e.g. animation('rotate', '2s')\n\n",33:"The animation shorthand arrays can only have 8 elements. See the specification for more information: http://mdn.io/animation\n\n",34:"borderRadius expects a radius value as a string or number as the second argument.\n\n",35:'borderRadius expects one of "top", "bottom", "left" or "right" as the first argument.\n\n',36:"Property must be a string value.\n\n",37:"Syntax Error at %s.\n\n",38:"Formula contains a function that needs parentheses at %s.\n\n",39:"Formula is missing closing parenthesis at %s.\n\n",40:"Formula has too many closing parentheses at %s.\n\n",41:"All values in a formula must have the same unit or be unitless.\n\n",42:"Please provide a number of steps to the modularScale helper.\n\n",43:"Please pass a number or one of the predefined scales to the modularScale helper as the ratio.\n\n",44:"Invalid value passed as base to modularScale, expected number or em/rem string but got %s.\n\n",45:"Passed invalid argument to hslToColorString, please pass a HslColor or HslaColor object.\n\n",46:"Passed invalid argument to rgbToColorString, please pass a RgbColor or RgbaColor object.\n\n",47:"minScreen and maxScreen must be provided as stringified numbers with the same units.\n\n",48:"fromSize and toSize must be provided as stringified numbers with the same units.\n\n",49:"Expects either an array of objects or a single object with the properties prop, fromSize, and toSize.\n\n",50:"Expects the objects in the first argument array to have the properties prop, fromSize, and toSize.\n\n",51:"Expects the first argument object to have the properties prop, fromSize, and toSize.\n\n",52:"fontFace expects either the path to the font file(s) or a name of a local copy.\n\n",53:"fontFace expects localFonts to be an array.\n\n",54:"fontFace expects fileFormats to be an array.\n\n",55:"fontFace expects a name of a font-family.\n\n",56:"linearGradient requries at least 2 color-stops to properly render.\n\n",57:"radialGradient requries at least 2 color-stops to properly render.\n\n",58:"Please supply a filename to retinaImage() as the first argument.\n\n",59:"Passed invalid argument to triangle, please pass correct pointingDirection e.g. 'right'.\n\n",60:"Passed an invalid value to `height` or `width`. Please provide a pixel based unit.\n\n",61:"Property must be a string value.\n\n",62:"borderRadius expects a radius value as a string or number as the second argument.\n\n",63:'borderRadius expects one of "top", "bottom", "left" or "right" as the first argument.\n\n',64:"The animation shorthand only takes 8 arguments. See the specification for more information: http://mdn.io/animation.\n\n",65:"To pass multiple animations please supply them in arrays, e.g. animation(['rotate', '2s'], ['move', '1s'])\\nTo pass a single animation please supply them in simple values, e.g. animation('rotate', '2s').\n\n",66:"The animation shorthand arrays can only have 8 elements. See the specification for more information: http://mdn.io/animation.\n\n",67:"You must provide a template to this method.\n\n",68:"You passed an unsupported selector state to this method.\n\n",69:'Expected a string ending in "px" or a number passed as the first argument to %s(), got %s instead.\n\n',70:'Expected a string ending in "px" or a number passed as the second argument to %s(), got %s instead.\n\n',71:'Passed invalid pixel value %s to %s(), please pass a value like "12px" or 12.\n\n',72:'Passed invalid base value %s to %s(), please pass a value like "12px" or 12.\n\n',73:"Please provide a valid CSS variable.\n\n",74:"CSS variable not found and no default was provided.\n\n",75:"important requires a valid style object, got a %s instead.\n\n",76:"fromSize and toSize must be provided as stringified numbers with the same units as minScreen and maxScreen.\n\n",77:'remToPx expects a value in "rem" but you provided it in "%s".\n\n',78:'base must be set in "px" or "%" but you set it in "%s".\n'};function d(){for(var e=arguments.length,t=new Array(e),a=0;a<e;a++)t[a]=arguments[a];var r,n=t[0],o=[];for(r=1;r<t.length;r+=1)o.push(t[r]);return o.forEach(function(e){n=n.replace(/%[a-z]/,e)}),n}var c=/*#__PURE__*/function(e){var t,a;function r(t){var a;if("production"===process.env.NODE_ENV)a=e.call(this,"An error occurred. See https://github.com/styled-components/polished/blob/main/src/internalHelpers/errors.md#"+t+" for more information.")||this;else{for(var r=arguments.length,n=new Array(r>1?r-1:0),o=1;o<r;o++)n[o-1]=arguments[o];a=e.call(this,d.apply(void 0,[p[t]].concat(n)))||this}return function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(a)}return a=e,(t=r).prototype=Object.create(a.prototype),t.prototype.constructor=t,l(t,a),r}(/*#__PURE__*/u(Error)),m=/--[\S]*/g;function h(e,t){if(!e||!e.match(m))throw new c(73);var a;if("undefined"!=typeof document&&null!==document.documentElement&&(a=getComputedStyle(document.documentElement).getPropertyValue(e)),a)return a.trim();throw new c(74)}function b(e){return Math.round(255*e)}function g(e,t,a){return b(e)+","+b(t)+","+b(a)}function v(e,t,a,r){if(void 0===r&&(r=g),0===t)return r(a,a,a);var n=(e%360+360)%360/60,o=(1-Math.abs(2*a-1))*t,s=o*(1-Math.abs(n%2-1)),i=0,l=0,f=0;n>=0&&n<1?(i=o,l=s):n>=1&&n<2?(i=s,l=o):n>=2&&n<3?(l=o,f=s):n>=3&&n<4?(l=s,f=o):n>=4&&n<5?(i=s,f=o):n>=5&&n<6&&(i=o,f=s);var u=a-o/2;return r(i+u,l+u,f+u)}var y={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"00ffff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"0000ff",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"00ffff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"ff00ff",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"639",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"};var C=/^#[a-fA-F0-9]{6}$/,w=/^#[a-fA-F0-9]{8}$/,x=/^#[a-fA-F0-9]{3}$/,F=/^#[a-fA-F0-9]{4}$/,S=/^rgb\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*\)$/i,k=/^rgb(?:a)?\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,|\/)\s*([-+]?\d*[.]?\d+[%]?)\s*\)$/i,I=/^hsl\(\s*(\d{0,3}[.]?[0-9]+(?:deg)?)\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*\)$/i,L=/^hsl(?:a)?\(\s*(\d{0,3}[.]?[0-9]+(?:deg)?)\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*(?:,|\/)\s*([-+]?\d*[.]?\d+[%]?)\s*\)$/i;function P(e){if("string"!=typeof e)throw new c(3);var t=function(e){if("string"!=typeof e)return e;var t=e.toLowerCase();return y[t]?"#"+y[t]:e}(e);if(t.match(C))return{red:parseInt(""+t[1]+t[2],16),green:parseInt(""+t[3]+t[4],16),blue:parseInt(""+t[5]+t[6],16)};if(t.match(w)){var a=parseFloat((parseInt(""+t[7]+t[8],16)/255).toFixed(2));return{red:parseInt(""+t[1]+t[2],16),green:parseInt(""+t[3]+t[4],16),blue:parseInt(""+t[5]+t[6],16),alpha:a}}if(t.match(x))return{red:parseInt(""+t[1]+t[1],16),green:parseInt(""+t[2]+t[2],16),blue:parseInt(""+t[3]+t[3],16)};if(t.match(F)){var r=parseFloat((parseInt(""+t[4]+t[4],16)/255).toFixed(2));return{red:parseInt(""+t[1]+t[1],16),green:parseInt(""+t[2]+t[2],16),blue:parseInt(""+t[3]+t[3],16),alpha:r}}var n=S.exec(t);if(n)return{red:parseInt(""+n[1],10),green:parseInt(""+n[2],10),blue:parseInt(""+n[3],10)};var o=k.exec(t.substring(0,50));if(o)return{red:parseInt(""+o[1],10),green:parseInt(""+o[2],10),blue:parseInt(""+o[3],10),alpha:parseFloat(""+o[4])>1?parseFloat(""+o[4])/100:parseFloat(""+o[4])};var s=I.exec(t);if(s){var i="rgb("+v(parseInt(""+s[1],10),parseInt(""+s[2],10)/100,parseInt(""+s[3],10)/100)+")",l=S.exec(i);if(!l)throw new c(4,t,i);return{red:parseInt(""+l[1],10),green:parseInt(""+l[2],10),blue:parseInt(""+l[3],10)}}var f=L.exec(t.substring(0,50));if(f){var u="rgb("+v(parseInt(""+f[1],10),parseInt(""+f[2],10)/100,parseInt(""+f[3],10)/100)+")",p=S.exec(u);if(!p)throw new c(4,t,u);return{red:parseInt(""+p[1],10),green:parseInt(""+p[2],10),blue:parseInt(""+p[3],10),alpha:parseFloat(""+f[4])>1?parseFloat(""+f[4])/100:parseFloat(""+f[4])}}throw new c(5)}function j(e){return function(e){var t,a=e.red/255,r=e.green/255,n=e.blue/255,o=Math.max(a,r,n),s=Math.min(a,r,n),i=(o+s)/2;if(o===s)return void 0!==e.alpha?{hue:0,saturation:0,lightness:i,alpha:e.alpha}:{hue:0,saturation:0,lightness:i};var l=o-s,f=i>.5?l/(2-o-s):l/(o+s);switch(o){case a:t=(r-n)/l+(r<n?6:0);break;case r:t=(n-a)/l+2;break;default:t=(a-r)/l+4}return t*=60,void 0!==e.alpha?{hue:t,saturation:f,lightness:i,alpha:e.alpha}:{hue:t,saturation:f,lightness:i}}(P(e))}var E=function(e){return 7===e.length&&e[1]===e[2]&&e[3]===e[4]&&e[5]===e[6]?"#"+e[1]+e[3]+e[5]:e};function z(e){var t=e.toString(16);return 1===t.length?"0"+t:t}function M(e){return z(Math.round(255*e))}function O(e,t,a){return E("#"+M(e)+M(t)+M(a))}function H(e,t,a){return v(e,t,a,O)}function q(e,t,a){if("number"==typeof e&&"number"==typeof t&&"number"==typeof a)return E("#"+z(e)+z(t)+z(a));if("object"==typeof e&&void 0===t&&void 0===a)return E("#"+z(e.red)+z(e.green)+z(e.blue));throw new c(6)}function $(e,t,a,r){if("object"==typeof e&&void 0===t&&void 0===a&&void 0===r)return e.alpha>=1?q(e.red,e.green,e.blue):"rgba("+e.red+","+e.green+","+e.blue+","+e.alpha+")";throw new c(7)}function T(e){if("object"!=typeof e)throw new c(8);if(function(e){return"number"==typeof e.red&&"number"==typeof e.green&&"number"==typeof e.blue&&"number"==typeof e.alpha}(e))return $(e);if(function(e){return"number"==typeof e.red&&"number"==typeof e.green&&"number"==typeof e.blue&&("number"!=typeof e.alpha||void 0===e.alpha)}(e))return q(e);if(function(e){return"number"==typeof e.hue&&"number"==typeof e.saturation&&"number"==typeof e.lightness&&"number"==typeof e.alpha}(e))return function(e,t,a,r){if("object"==typeof e&&void 0===t&&void 0===a&&void 0===r)return e.alpha>=1?H(e.hue,e.saturation,e.lightness):"rgba("+v(e.hue,e.saturation,e.lightness)+","+e.alpha+")";throw new c(2)}(e);if(function(e){return"number"==typeof e.hue&&"number"==typeof e.saturation&&"number"==typeof e.lightness&&("number"!=typeof e.alpha||void 0===e.alpha)}(e))return function(e,t,a){if("object"==typeof e&&void 0===t&&void 0===a)return H(e.hue,e.saturation,e.lightness);throw new c(1)}(e);throw new c(8)}function V(e,t,a){return function(){var r=a.concat(Array.prototype.slice.call(arguments));return r.length>=t?e.apply(this,r):V(e,t,r)}}function R(e){return V(e,e.length,[])}function _(e,t,a){return Math.max(e,Math.min(t,a))}R(function(e,t){if("transparent"===t)return t;var a=j(t);return T(s({},a,{hue:a.hue+parseFloat(e)}))}),R(function(e,t){if("transparent"===t)return t;var a=j(t);return T(s({},a,{lightness:_(0,1,a.lightness-parseFloat(e))}))}),R(function(e,t){if("transparent"===t)return t;var a=j(t);return T(s({},a,{saturation:_(0,1,a.saturation-parseFloat(e))}))}),R(function(e,t){if("transparent"===t)return t;var a=j(t);return T(s({},a,{lightness:_(0,1,a.lightness+parseFloat(e))}))});var A=R(function(e,t,a){if("transparent"===t)return a;if("transparent"===a)return t;if(0===e)return a;var r=P(t),n=s({},r,{alpha:"number"==typeof r.alpha?r.alpha:1}),o=P(a),i=s({},o,{alpha:"number"==typeof o.alpha?o.alpha:1}),l=n.alpha-i.alpha,f=2*parseFloat(e)-1,u=((f*l===-1?f:f+l)/(1+f*l)+1)/2,p=1-u;return $({red:Math.floor(n.red*u+i.red*p),green:Math.floor(n.green*u+i.green*p),blue:Math.floor(n.blue*u+i.blue*p),alpha:n.alpha*parseFloat(e)+i.alpha*(1-parseFloat(e))})});R(function(e,t){if("transparent"===t)return t;var a=P(t),r="number"==typeof a.alpha?a.alpha:1;return $(s({},a,{alpha:_(0,1,(100*r+100*parseFloat(e))/100)}))}),R(function(e,t){if("transparent"===t)return t;var a=j(t);return T(s({},a,{saturation:_(0,1,a.saturation+parseFloat(e))}))}),R(function(e,t){return"transparent"===t?t:T(s({},j(t),{hue:parseFloat(e)}))}),R(function(e,t){return"transparent"===t?t:T(s({},j(t),{lightness:parseFloat(e)}))}),R(function(e,t){return"transparent"===t?t:T(s({},j(t),{saturation:parseFloat(e)}))}),R(function(e,t){return"transparent"===t?t:A(parseFloat(e),"rgb(0, 0, 0)",t)}),R(function(e,t){return"transparent"===t?t:A(parseFloat(e),"rgb(255, 255, 255)",t)}),R(function(e,t){if("transparent"===t)return t;var a=P(t),r="number"==typeof a.alpha?a.alpha:1;return $(s({},a,{alpha:_(0,1,+(100*r-100*parseFloat(e)).toFixed(2)/100)}))});const N=(e,r)=>{const[n,o]=t(`var(${r})`),s=(()=>{const[e,r]=t(()=>document.documentElement.classList.contains("dark"));return a(()=>{const e=new MutationObserver(()=>{r(document.documentElement.classList.contains("dark"))});return e.observe(document.documentElement,{attributes:!0,attributeFilter:["class"]}),()=>e.disconnect()},[]),e})();return a(()=>{const t=h(e),a=h(r);if(t&&a){const a=function(e){if("transparent"===e)return 0;var t=P(e),a=Object.keys(t).map(function(e){var a=t[e]/255;return a<=.03928?a/12.92:Math.pow((a+.055)/1.055,2.4)}),r=a[0],n=a[1],o=a[2];return parseFloat((.2126*r+.7152*n+.0722*o).toFixed(3))}(t.toString());o(a<=.5?s?"var(--bfc-ring)":`var(${e})`:s?`var(${e})`:`var(${r})`)}},[e,r,s]),n},G=n("min-w-5",{variants:{variant:{default:"size-6",gradient:"size-8",disabled:"size-8 grayscale"},loading:{true:"animate-spin"}},defaultVariants:{variant:"default"}}),Z="M16.0127 3.5C16.5221 3.50002 17.0197 3.65584 17.4375 3.94727C17.8553 4.23871 18.1736 4.65182 18.3496 5.12988L20.6445 11.3652L26.876 13.6689L27.0283 13.7246L27.0391 13.7402C27.4497 13.9244 27.8038 14.2171 28.0625 14.5879C28.3539 15.0057 28.5098 15.5032 28.5098 16.0127C28.5097 16.5221 28.3539 17.0197 28.0625 17.4375C27.7711 17.8552 27.3579 18.1737 26.8799 18.3496L20.6426 20.6445L18.334 26.8809C18.158 27.3587 17.8396 27.7712 17.4219 28.0625C17.0042 28.3538 16.5073 28.5097 15.998 28.5098C15.4886 28.5098 14.9911 28.3539 14.5732 28.0625C14.1554 27.771 13.8371 27.358 13.6611 26.8799L11.3652 20.6436L5.12891 18.334V18.333C4.65135 18.1569 4.23846 17.8394 3.94727 17.4219C3.65606 17.0042 3.5001 16.5072 3.5 15.998C3.5 15.4887 3.65596 14.991 3.94727 14.5732C4.2387 14.1554 4.65182 13.8371 5.12988 13.6611L11.3652 11.3652L13.6758 5.12891C13.8518 4.65116 14.1703 4.23855 14.5879 3.94727C15.0057 3.65585 15.5033 3.5 16.0127 3.5ZM13.9463 13.0498L13.9473 13.0508C13.8723 13.2565 13.7535 13.4438 13.5986 13.5986C13.4438 13.7535 13.2565 13.8723 13.0508 13.9473L13.0498 13.9463L7.46875 16.0049L13.0498 18.0625H13.0508C13.2564 18.1374 13.4438 18.2564 13.5986 18.4111C13.7529 18.5654 13.8713 18.7521 13.9463 18.957L16.0049 24.541L18.0684 18.9521L18.1328 18.8027C18.2049 18.6578 18.3001 18.5251 18.415 18.4102C18.5684 18.2568 18.7535 18.1385 18.957 18.0635L24.541 16.0049L18.9521 13.9414C18.7486 13.8664 18.5636 13.7481 18.4102 13.5947C18.2568 13.4413 18.1385 13.2563 18.0635 13.0527L16.0049 7.46875L13.9463 13.0498Z",D=[{offset:"0%",color:"rgba(232, 122, 249, 1)"},{offset:"14%",color:"rgba(251, 191, 37, 1)"},{offset:"33%",color:"rgba(251, 146, 61, 1)"},{offset:"51%",color:"rgba(244, 64, 94, 1)"},{offset:"68%",color:"rgba(140, 93, 246, 1)"},{offset:"83%",color:"rgba(60, 130, 246, 1)"},{offset:"100%",color:"rgba(232, 122, 249, 1)"}];function Y({loading:t,variant:a,className:n,...s}){const i=N("--bfc-primary","--bfc-border"),l="gradient"===a,f="disabled"===a,u=!l&&!f,p=r(),d=e=>l?e:f?"var(--bfc-v2-color-mono-600)":"var(--bfc-primary)";/* @__PURE__ */
2
2
  return e.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",width:"32",height:"32",viewBox:"0 0 32 32",fill:"none",className:o(G({variant:a}),n),...s},
3
3
  /* @__PURE__ */e.createElement("path",{d:Z,fill:l?`url(#${p})`:f?"var(--bfc-v2-color-mono-600)":"var(--bfc-primary)"!==i?"var(--bfc-border)":"var(--bfc-primary)",className:o({"animate-spin [transform-box:fill-box]":t})}),
4
4
  /* @__PURE__ */e.createElement("path",{stroke:"var(--bfc-v2-color-mono-100)",className:o({"animate-spin [transform-box:fill-box]":t}),d:Z}),u&&/* @__PURE__ */e.createElement("g",{className:"transform origin-center scale-125"},/* @__PURE__ */e.createElement("g",{className:o({"animate-spin [transform-box:fill-box]":t})},/* @__PURE__ */e.createElement("path",{fill:"var(--bfc-primary)",d:"M13.9463 13.0498L13.9473 13.0508C13.8723 13.2565 13.7535 13.4438 13.5986 13.5986C13.4438 13.7535 13.2565 13.8723 13.0508 13.9473L13.0498 13.9463L7.46875 16.0049L13.0498 18.0625H13.0508C13.2564 18.1374 13.4438 18.2564 13.5986 18.4111C13.7529 18.5654 13.8713 18.7521 13.9463 18.957L16.0049 24.541L18.0684 18.9521L18.1328 18.8027C18.2049 18.6578 18.3001 18.5251 18.415 18.4102C18.5684 18.2568 18.7535 18.1385 18.957 18.0635L24.541 16.0049L18.9521 13.9414C18.7486 13.8664 18.5636 13.7481 18.4102 13.5947C18.2568 13.4413 18.1385 13.2563 18.0635 13.0527L16.0049 7.46875L13.9463 13.0498Z"}))),
5
5
  /* @__PURE__ */e.createElement("path",{fill:d("#3C82F6"),d:"M31.7071 9.70711C31.8946 9.51957 32 9.26522 32 9C32 8.73478 31.8946 8.48043 31.7071 8.29289C31.5196 8.10536 31.2652 8 31 8H30V7C30 6.73478 29.8946 6.48043 29.7071 6.29289C29.5196 6.10536 29.2652 6 29 6C28.7348 6 28.4804 6.10536 28.2929 6.29289C28.1054 6.48043 28 6.73478 28 7V8H27C26.7348 8 26.4804 8.10536 26.2929 8.29289C26.1054 8.48043 26 8.73478 26 9C26 9.26522 26.1054 9.51957 26.2929 9.70711C26.4804 9.89464 26.7348 10 27 10H28V11C28 11.2652 28.1054 11.5196 28.2929 11.7071C28.4804 11.8946 28.7348 12 29 12C29.2652 12 29.5196 11.8946 29.7071 11.7071C29.8946 11.5196 30 11.2652 30 11V10H31C31.2652 10 31.5196 9.89464 31.7071 9.70711Z"}),
6
6
  /* @__PURE__ */e.createElement("path",{fill:d("#35D399"),d:"M19.2929 3.29289C19.1054 3.48043 19 3.73478 19 4C19 4.26522 19.1054 4.51957 19.2929 4.70711C19.4804 4.89464 19.7348 5 20 5H22V7C22 7.26522 22.1054 7.51957 22.2929 7.70711C22.4804 7.89464 22.7348 8 23 8C23.2652 8 23.5196 7.89464 23.7071 7.70711C23.8946 7.51957 24 7.26522 24 7V5H26C26.2652 5 26.5196 4.89464 26.7071 4.70711C26.8946 4.51957 27 4.26522 27 4C27 3.73478 26.8946 3.48043 26.7071 3.29289C26.5196 3.10536 26.2652 3 26 3H24V1C24 0.734784 23.8946 0.48043 23.7071 0.292893C23.5196 0.105357 23.2652 0 23 0C22.7348 0 22.4804 0.105357 22.2929 0.292893C22.1054 0.48043 22 0.734784 22 1V3H20C19.7348 3 19.4804 3.10536 19.2929 3.29289Z"}),l&&/* @__PURE__ */e.createElement("defs",null,/* @__PURE__ */e.createElement("linearGradient",{id:p,x1:"0%",y1:"0%",x2:"100%",y2:"100%"},D.map(t=>/* @__PURE__ */e.createElement("stop",{key:t.offset,offset:t.offset,stopColor:t.color})))))}export{Y as G,G as g};
7
- //# sourceMappingURL=generating-star.BN9p_FDu.js.map
7
+ //# sourceMappingURL=generating-star.DN8DVygp.js.map