jaci-ui 0.9.4 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +11 -1
- package/dist/_virtual/_rolldown/runtime.cjs +1 -1
- package/dist/components/accordion/accordion.cjs.map +1 -1
- package/dist/components/accordion/accordion.js.map +1 -1
- package/dist/components/alert/alert.cjs.map +1 -1
- package/dist/components/alert/alert.js.map +1 -1
- package/dist/components/alert-dialog/alert-dialog.cjs.map +1 -1
- package/dist/components/alert-dialog/alert-dialog.js.map +1 -1
- package/dist/components/aspect-ratio/aspect-ratio.cjs.map +1 -1
- package/dist/components/avatar/avatar.cjs.map +1 -1
- package/dist/components/avatar/avatar.js.map +1 -1
- package/dist/components/breadcrumbs/breadcrumbs.cjs.map +1 -1
- package/dist/components/button/button.cjs +1 -0
- package/dist/components/button/button.cjs.map +1 -1
- package/dist/components/button/button.d.cts +2 -1
- package/dist/components/button/button.d.ts +2 -1
- package/dist/components/button/button.js +1 -0
- package/dist/components/button/button.js.map +1 -1
- package/dist/components/button-group/button-group.cjs.map +1 -1
- package/dist/components/calendar/calendar.cjs +4 -6
- package/dist/components/calendar/calendar.cjs.map +1 -1
- package/dist/components/calendar/calendar.js +4 -6
- package/dist/components/calendar/calendar.js.map +1 -1
- package/dist/components/card/card.cjs.map +1 -1
- package/dist/components/carousel/carousel.cjs.map +1 -1
- package/dist/components/carousel/carousel.js.map +1 -1
- package/dist/components/checkbox-group/checkbox-group.cjs +7 -3
- package/dist/components/checkbox-group/checkbox-group.cjs.map +1 -1
- package/dist/components/checkbox-group/checkbox-group.js +7 -3
- package/dist/components/checkbox-group/checkbox-group.js.map +1 -1
- package/dist/components/code/code.cjs.map +1 -1
- package/dist/components/code/code.js.map +1 -1
- package/dist/components/collapsible/collapsible.cjs.map +1 -1
- package/dist/components/collapsible/collapsible.js.map +1 -1
- package/dist/components/color-picker/color-picker.cjs.map +1 -1
- package/dist/components/color-picker/color-picker.js.map +1 -1
- package/dist/components/color-swatch/color-swatch.cjs.map +1 -1
- package/dist/components/combobox/combobox.cjs +2 -1
- package/dist/components/combobox/combobox.cjs.map +1 -1
- package/dist/components/combobox/combobox.js +2 -1
- package/dist/components/combobox/combobox.js.map +1 -1
- package/dist/components/command/command.cjs.map +1 -1
- package/dist/components/command/command.js.map +1 -1
- package/dist/components/context-menu/context-menu.cjs.map +1 -1
- package/dist/components/controls/checkbox.cjs.map +1 -1
- package/dist/components/controls/checkbox.js.map +1 -1
- package/dist/components/controls/input.cjs.map +1 -1
- package/dist/components/controls/input.js.map +1 -1
- package/dist/components/controls/radio.cjs.map +1 -1
- package/dist/components/controls/switch.cjs.map +1 -1
- package/dist/components/controls/switch.js.map +1 -1
- package/dist/components/controls/textarea.cjs.map +1 -1
- package/dist/components/controls/textarea.js.map +1 -1
- package/dist/components/copyable/copyable.cjs.map +1 -1
- package/dist/components/copyable/copyable.js.map +1 -1
- package/dist/components/data-toolbar/data-toolbar.cjs.map +1 -1
- package/dist/components/data-toolbar/data-toolbar.js.map +1 -1
- package/dist/components/data-view/data-view.cjs.map +1 -1
- package/dist/components/date-picker/date-picker.cjs +4 -7
- package/dist/components/date-picker/date-picker.cjs.map +1 -1
- package/dist/components/date-picker/date-picker.js +4 -7
- package/dist/components/date-picker/date-picker.js.map +1 -1
- package/dist/components/date-range-picker/date-range-picker.cjs +4 -6
- package/dist/components/date-range-picker/date-range-picker.cjs.map +1 -1
- package/dist/components/date-range-picker/date-range-picker.js +4 -6
- package/dist/components/date-range-picker/date-range-picker.js.map +1 -1
- package/dist/components/dialog/dialog.cjs.map +1 -1
- package/dist/components/dialog/dialog.js.map +1 -1
- package/dist/components/download-trigger/download-trigger.cjs.map +1 -1
- package/dist/components/drawer/drawer.cjs.map +1 -1
- package/dist/components/drawer/drawer.js.map +1 -1
- package/dist/components/empty-state/empty-state.cjs.map +1 -1
- package/dist/components/feedback/badge.cjs.map +1 -1
- package/dist/components/field/field.cjs.map +1 -1
- package/dist/components/field/field.js.map +1 -1
- package/dist/components/fieldset/fieldset.cjs.map +1 -1
- package/dist/components/figure/figure.cjs.map +1 -1
- package/dist/components/figure/figure.js.map +1 -1
- package/dist/components/form/form.cjs.map +1 -1
- package/dist/components/form/form.js.map +1 -1
- package/dist/components/icon-button/icon-button.cjs.map +1 -1
- package/dist/components/icon-button/icon-button.js.map +1 -1
- package/dist/components/image/image.cjs.map +1 -1
- package/dist/components/image/image.js.map +1 -1
- package/dist/components/input-group/input-group.cjs.map +1 -1
- package/dist/components/kbd/kbd.cjs.map +1 -1
- package/dist/components/layout/index.cjs.map +1 -1
- package/dist/components/list/list.cjs.map +1 -1
- package/dist/components/menu/menu.cjs.map +1 -1
- package/dist/components/menubar/menubar.cjs.map +1 -1
- package/dist/components/menubar/menubar.js.map +1 -1
- package/dist/components/meter/meter.cjs.map +1 -1
- package/dist/components/meter/meter.js.map +1 -1
- package/dist/components/navigation/navigation.cjs.map +1 -1
- package/dist/components/navigation/navigation.js.map +1 -1
- package/dist/components/navigation-menu/navigation-menu.cjs.map +1 -1
- package/dist/components/navigation-menu/navigation-menu.js.map +1 -1
- package/dist/components/number-field/number-field.cjs +2 -1
- package/dist/components/number-field/number-field.cjs.map +1 -1
- package/dist/components/number-field/number-field.js +2 -1
- package/dist/components/number-field/number-field.js.map +1 -1
- package/dist/components/option-selector/option-selector.cjs.map +1 -1
- package/dist/components/option-selector/option-selector.js.map +1 -1
- package/dist/components/pagination/pagination.cjs.map +1 -1
- package/dist/components/pagination/pagination.js.map +1 -1
- package/dist/components/pin-input/pin-input.cjs.map +1 -1
- package/dist/components/pin-input/pin-input.js.map +1 -1
- package/dist/components/popover/popover.cjs.map +1 -1
- package/dist/components/popover/popover.js.map +1 -1
- package/dist/components/progress/progress.cjs.map +1 -1
- package/dist/components/progress/progress.js.map +1 -1
- package/dist/components/qr-code/qr-code.cjs.map +1 -1
- package/dist/components/qr-code/qr-code.js.map +1 -1
- package/dist/components/quote/quote.cjs.map +1 -1
- package/dist/components/quote/quote.js.map +1 -1
- package/dist/components/radio-group/radio-group.cjs +7 -3
- package/dist/components/radio-group/radio-group.cjs.map +1 -1
- package/dist/components/radio-group/radio-group.js +7 -3
- package/dist/components/radio-group/radio-group.js.map +1 -1
- package/dist/components/range-slider/range-slider.cjs.map +1 -1
- package/dist/components/range-slider/range-slider.js.map +1 -1
- package/dist/components/scroll-area/scroll-area.cjs.map +1 -1
- package/dist/components/select/select.cjs.map +1 -1
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/sidebar/sidebar.cjs.map +1 -1
- package/dist/components/sidebar/sidebar.js.map +1 -1
- package/dist/components/skeleton/skeleton.cjs.map +1 -1
- package/dist/components/slider/slider.cjs.map +1 -1
- package/dist/components/slider/slider.js.map +1 -1
- package/dist/components/spacer/spacer.cjs.map +1 -1
- package/dist/components/stat/stat.cjs.map +1 -1
- package/dist/components/stat/stat.js.map +1 -1
- package/dist/components/stepper/stepper.cjs +2 -1
- package/dist/components/stepper/stepper.cjs.map +1 -1
- package/dist/components/stepper/stepper.js +2 -1
- package/dist/components/stepper/stepper.js.map +1 -1
- package/dist/components/table/table.cjs.map +1 -1
- package/dist/components/table/table.js.map +1 -1
- package/dist/components/tabs/tabs.cjs.map +1 -1
- package/dist/components/tabs/tabs.js.map +1 -1
- package/dist/components/tags-input/tags-input.cjs.map +1 -1
- package/dist/components/tags-input/tags-input.js.map +1 -1
- package/dist/components/toast/toast.cjs.map +1 -1
- package/dist/components/toast/toast.js.map +1 -1
- package/dist/components/toggle/toggle.cjs.map +1 -1
- package/dist/components/toggle-group/toggle-group.cjs.map +1 -1
- package/dist/components/toolbar/toolbar.cjs.map +1 -1
- package/dist/components/tooltip/tooltip.cjs.map +1 -1
- package/dist/components/tree-view/tree-view.cjs.map +1 -1
- package/dist/components/tree-view/tree-view.js.map +1 -1
- package/dist/components/typography/heading.cjs.map +1 -1
- package/dist/components/typography/link.cjs.map +1 -1
- package/dist/components/typography/paragraph.cjs.map +1 -1
- package/dist/components/typography/text.cjs.map +1 -1
- package/dist/components/upload/upload.cjs +2 -2
- package/dist/components/upload/upload.cjs.map +1 -1
- package/dist/components/upload/upload.js +2 -2
- package/dist/components/upload/upload.js.map +1 -1
- package/dist/components/visually-hidden/visually-hidden.cjs.map +1 -1
- package/dist/panda-preset.cjs.map +1 -1
- package/dist/styles.css +0 -21
- package/dist/theme/theme-provider.cjs.map +1 -1
- package/dist/theme/theme-provider.js.map +1 -1
- package/dist/theme/theme-scope.cjs.map +1 -1
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paragraph.cjs","names":["cx","paragraph"],"sources":["../../../src/components/typography/paragraph.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\n\nimport { cx } from \"../../styled-system/css\";\nimport { paragraph } from \"../../styled-system/recipes\";\nimport type { TypographyLineClamp, TypographyWeight, TypographyWidth } from \"./heading\";\n\nexport interface ParagraphProps extends ComponentPropsWithoutRef<\"p\"> {\n weight?: TypographyWeight;\n truncate?: boolean;\n lineClamp?: TypographyLineClamp;\n width?: TypographyWidth;\n}\n\nexport const Paragraph = forwardRef<HTMLParagraphElement, ParagraphProps>(function Paragraph(\n { className, lineClamp, truncate = false, weight, width = \"auto\", ...props },\n ref,\n) {\n return (\n <p\n {...props}\n ref={ref}\n className={cx(\n paragraph({\n lineClamp: lineClamp ? (String(lineClamp) as \"1\" | \"2\" | \"3\" | \"4\") : undefined,\n truncate,\n weight,\n width,\n }),\n className,\n )}\n data-jaci-component=\"paragraph\"\n data-slot=\"paragraph\"\n />\n );\n});\n"],"mappings":";;;;;AAcA,MAAa,aAAA,
|
|
1
|
+
{"version":3,"file":"paragraph.cjs","names":["forwardRef","cx","paragraph"],"sources":["../../../src/components/typography/paragraph.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\n\nimport { cx } from \"../../styled-system/css\";\nimport { paragraph } from \"../../styled-system/recipes\";\nimport type { TypographyLineClamp, TypographyWeight, TypographyWidth } from \"./heading\";\n\nexport interface ParagraphProps extends ComponentPropsWithoutRef<\"p\"> {\n weight?: TypographyWeight;\n truncate?: boolean;\n lineClamp?: TypographyLineClamp;\n width?: TypographyWidth;\n}\n\nexport const Paragraph = forwardRef<HTMLParagraphElement, ParagraphProps>(function Paragraph(\n { className, lineClamp, truncate = false, weight, width = \"auto\", ...props },\n ref,\n) {\n return (\n <p\n {...props}\n ref={ref}\n className={cx(\n paragraph({\n lineClamp: lineClamp ? (String(lineClamp) as \"1\" | \"2\" | \"3\" | \"4\") : undefined,\n truncate,\n weight,\n width,\n }),\n className,\n )}\n data-jaci-component=\"paragraph\"\n data-slot=\"paragraph\"\n />\n );\n});\n"],"mappings":";;;;;AAcA,MAAa,aAAA,GAAYA,MAAAA,WAAAA,CAAiD,SAAS,UACjF,EAAE,WAAW,WAAW,WAAW,OAAO,QAAQ,QAAQ,QAAQ,GAAG,SACrE,KACA;CACA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;EACE,GAAI;EACC;EACL,WAAWC,WAAAA,GACTC,kBAAAA,UAAU;GACR,WAAW,YAAa,OAAO,SAAS,IAA8B,KAAA;GACtE;GACA;GACA;EACF,CAAC,GACD,SACF;EACA,uBAAoB;EACpB,aAAU;CACX,CAAA;AAEL,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.cjs","names":["Component","cx","text"],"sources":["../../../src/components/typography/text.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ElementType, ReactElement, Ref } from \"react\";\nimport type { TypographyLineClamp, TypographyWeight, TypographyWidth } from \"./heading\";\n\nimport { cx } from \"../../styled-system/css\";\nimport { text } from \"../../styled-system/recipes\";\n\nexport type TextSize = \"sm\" | \"md\" | \"lg\";\nexport type TextTone = \"default\" | \"muted\";\nexport type TextElement = \"p\" | \"span\" | \"div\";\n\nexport interface TextProps extends Omit<ComponentPropsWithoutRef<\"p\">, \"color\"> {\n as?: TextElement;\n size?: TextSize;\n tone?: TextTone;\n weight?: TypographyWeight;\n truncate?: boolean;\n lineClamp?: TypographyLineClamp;\n width?: TypographyWidth;\n}\n\nexport const Text = forwardRef<HTMLElement, TextProps>(function Text(\n {\n as = \"p\",\n className,\n lineClamp,\n size = \"md\",\n tone = \"default\",\n truncate = false,\n weight,\n width = \"auto\",\n ...props\n },\n ref,\n) {\n const Component = as as ElementType;\n\n return (\n <Component\n {...props}\n ref={ref as Ref<HTMLElement>}\n className={cx(\n text({\n lineClamp: lineClamp ? (String(lineClamp) as \"1\" | \"2\" | \"3\" | \"4\") : undefined,\n size,\n tone,\n truncate,\n weight,\n width,\n }),\n className,\n )}\n data-jaci-component=\"text\"\n data-slot=\"text\"\n />\n ) as ReactElement;\n});\n"],"mappings":";;;;;AAqBA,MAAa,QAAA,
|
|
1
|
+
{"version":3,"file":"text.cjs","names":["forwardRef","Component","cx","text"],"sources":["../../../src/components/typography/text.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ElementType, ReactElement, Ref } from \"react\";\nimport type { TypographyLineClamp, TypographyWeight, TypographyWidth } from \"./heading\";\n\nimport { cx } from \"../../styled-system/css\";\nimport { text } from \"../../styled-system/recipes\";\n\nexport type TextSize = \"sm\" | \"md\" | \"lg\";\nexport type TextTone = \"default\" | \"muted\";\nexport type TextElement = \"p\" | \"span\" | \"div\";\n\nexport interface TextProps extends Omit<ComponentPropsWithoutRef<\"p\">, \"color\"> {\n as?: TextElement;\n size?: TextSize;\n tone?: TextTone;\n weight?: TypographyWeight;\n truncate?: boolean;\n lineClamp?: TypographyLineClamp;\n width?: TypographyWidth;\n}\n\nexport const Text = forwardRef<HTMLElement, TextProps>(function Text(\n {\n as = \"p\",\n className,\n lineClamp,\n size = \"md\",\n tone = \"default\",\n truncate = false,\n weight,\n width = \"auto\",\n ...props\n },\n ref,\n) {\n const Component = as as ElementType;\n\n return (\n <Component\n {...props}\n ref={ref as Ref<HTMLElement>}\n className={cx(\n text({\n lineClamp: lineClamp ? (String(lineClamp) as \"1\" | \"2\" | \"3\" | \"4\") : undefined,\n size,\n tone,\n truncate,\n weight,\n width,\n }),\n className,\n )}\n data-jaci-component=\"text\"\n data-slot=\"text\"\n />\n ) as ReactElement;\n});\n"],"mappings":";;;;;AAqBA,MAAa,QAAA,GAAOA,MAAAA,WAAAA,CAAmC,SAAS,KAC9D,EACE,KAAK,KACL,WACA,WACA,OAAO,MACP,OAAO,WACP,WAAW,OACX,QACA,QAAQ,QACR,GAAG,SAEL,KACA;CAGA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,IAAD;EACE,GAAI;EACC;EACL,WAAWC,WAAAA,GACTC,aAAAA,KAAK;GACH,WAAW,YAAa,OAAO,SAAS,IAA8B,KAAA;GACtE;GACA;GACA;GACA;GACA;EACF,CAAC,GACD,SACF;EACA,uBAAoB;EACpB,aAAU;CACX,CAAA;AAEL,CAAC"}
|
|
@@ -15,8 +15,8 @@ function fileKey(file) {
|
|
|
15
15
|
}
|
|
16
16
|
function formatBytes(bytes) {
|
|
17
17
|
if (bytes < 1024) return `${bytes} B`;
|
|
18
|
-
if (bytes <
|
|
19
|
-
return `${(bytes /
|
|
18
|
+
if (bytes < 1048576) return `${Math.round(bytes / 1024)} KB`;
|
|
19
|
+
return `${(bytes / 1048576).toFixed(1)} MB`;
|
|
20
20
|
}
|
|
21
21
|
function acceptsFile(file, accept) {
|
|
22
22
|
if (!accept) return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.cjs","names":["upload","cx"],"sources":["../../../src/components/upload/upload.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { ChangeEvent, ComponentPropsWithoutRef, ReactNode, RefObject } from \"react\";\n\nimport { cx } from \"../../styled-system/css\";\nimport { upload } from \"../../styled-system/recipes\";\n\nexport type UploadRejectionReason = \"type\" | \"size\" | \"count\" | \"duplicate\" | \"validation\";\n\nexport type UploadFileStatus = \"queued\" | \"uploading\" | \"success\" | \"error\" | \"canceled\";\n\nexport interface UploadFileState {\n status: UploadFileStatus;\n progress?: number;\n error?: ReactNode;\n}\n\nexport interface UploadRejection {\n file: File;\n message: string;\n reason: UploadRejectionReason;\n}\n\ninterface UploadContextValue {\n accept: string | undefined;\n addFiles: (files: FileList | File[]) => void;\n disabled: boolean;\n dropActive: boolean;\n files: File[];\n inputId: string;\n inputRef: RefObject<HTMLInputElement | null>;\n fileState: ((file: File) => UploadFileState | undefined) | undefined;\n maxFiles: number | undefined;\n maxSize: number | undefined;\n multiple: boolean;\n removeFile: (file: File) => void;\n cancelFile: (file: File) => void;\n rejections: UploadRejection[];\n setDropActive: (active: boolean) => void;\n styles: ReturnType<typeof upload>;\n}\n\nconst UploadContext = createContext<UploadContextValue | null>(null);\n\nfunction useUploadContext() {\n const context = useContext(UploadContext);\n if (!context) {\n throw new Error(\"Upload parts must be rendered inside Upload.Root.\");\n }\n\n return context;\n}\n\nfunction fileKey(file: File) {\n return `${file.name}-${file.size}-${file.lastModified}`;\n}\n\nfunction formatBytes(bytes: number) {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction acceptsFile(file: File, accept: string | undefined) {\n if (!accept) {\n return true;\n }\n\n const fileName = file.name.toLowerCase();\n const fileType = file.type.toLowerCase();\n\n return accept.split(\",\").some((entry) => {\n const pattern = entry.trim().toLowerCase();\n if (!pattern) return true;\n if (pattern.startsWith(\".\")) return fileName.endsWith(pattern);\n if (pattern.endsWith(\"/*\")) return fileType.startsWith(pattern.slice(0, -1));\n return pattern === fileType;\n });\n}\n\nexport interface UploadRootProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"onChange\"> {\n /** Accepted MIME types or file extensions, using the native input syntax. */\n accept?: string;\n /** Controlled files. Use with `onFilesChange`. */\n files?: File[];\n /** Initial files for an uncontrolled upload. */\n defaultFiles?: File[];\n /** Called whenever accepted files are added or removed. */\n onFilesChange?: (files: File[]) => void;\n /** Called with files rejected by `accept`, `maxSize`, `maxFiles` or duplicates. */\n onReject?: (rejections: UploadRejection[]) => void;\n /** Maximum number of accepted files. Defaults to one when `multiple` is false. */\n maxFiles?: number;\n /** Maximum size per file, in bytes. */\n maxSize?: number;\n /** Allows selecting more than one file. */\n multiple?: boolean;\n /** Disables file selection and drag-and-drop. */\n disabled?: boolean;\n /** Optional asynchronous validation. Return an error message to reject a file. */\n validateFile?: (file: File) => string | null | Promise<string | null>;\n /** Controlled status used by the status, progress and cancel slots. */\n fileState?: (file: File) => UploadFileState | undefined;\n /** Called when a consumer cancels an upload. */\n onCancel?: (file: File) => void;\n children?: ReactNode;\n}\n\nexport const UploadRoot = forwardRef<HTMLDivElement, UploadRootProps>(function UploadRoot(\n {\n accept,\n fileState,\n children,\n className,\n defaultFiles = [],\n disabled = false,\n files: controlledFiles,\n maxFiles,\n maxSize,\n multiple = false,\n onFilesChange,\n onCancel,\n onReject,\n validateFile,\n ...props\n },\n ref,\n) {\n const [uncontrolledFiles, setUncontrolledFiles] = useState<File[]>(defaultFiles);\n const [dropActive, setDropActive] = useState(false);\n const [rejections, setRejections] = useState<UploadRejection[]>([]);\n const inputRef = useRef<HTMLInputElement>(null);\n const inputId = useId();\n const styles = upload({ disabled, dropActive });\n const currentFiles = controlledFiles ?? uncontrolledFiles;\n const fileLimit = maxFiles ?? (multiple ? undefined : 1);\n\n const updateFiles = useCallback(\n (nextFiles: File[]) => {\n if (controlledFiles === undefined) setUncontrolledFiles(nextFiles);\n onFilesChange?.(nextFiles);\n },\n [controlledFiles, onFilesChange],\n );\n\n const removeFile = useCallback(\n (file: File) => {\n updateFiles(currentFiles.filter((current) => fileKey(current) !== fileKey(file)));\n },\n [currentFiles, updateFiles],\n );\n\n const addFiles = useCallback(\n (fileList: FileList | File[]) => {\n if (disabled) return;\n\n const candidates = Array.from(fileList);\n const acceptedFiles: File[] = [];\n const nextRejections: UploadRejection[] = [];\n const pendingValidations = new Map<File, Promise<string | null>>();\n const existingKeys = new Set(currentFiles.map(fileKey));\n\n for (const file of candidates) {\n const key = fileKey(file);\n if (existingKeys.has(key) || acceptedFiles.some((accepted) => fileKey(accepted) === key)) {\n nextRejections.push({\n file,\n reason: \"duplicate\",\n message: `${file.name} was already added.`,\n });\n continue;\n }\n if (!acceptsFile(file, accept)) {\n nextRejections.push({\n file,\n reason: \"type\",\n message: `${file.name} is not an accepted file type.`,\n });\n continue;\n }\n if (maxSize !== undefined && file.size > maxSize) {\n nextRejections.push({\n file,\n reason: \"size\",\n message: `${file.name} is larger than the allowed limit.`,\n });\n continue;\n }\n if (\n fileLimit !== undefined &&\n (multiple ? currentFiles.length + acceptedFiles.length : acceptedFiles.length) >=\n fileLimit\n ) {\n nextRejections.push({\n file,\n reason: \"count\",\n message: `Only ${fileLimit} file${fileLimit === 1 ? \"\" : \"s\"} can be selected.`,\n });\n continue;\n }\n if (validateFile) {\n const validation = validateFile(file);\n if (validation && typeof validation !== \"object\") {\n nextRejections.push({ file, reason: \"validation\", message: validation });\n continue;\n }\n if (validation && typeof validation === \"object\" && \"then\" in validation) {\n pendingValidations.set(file, Promise.resolve(validation));\n }\n }\n acceptedFiles.push(file);\n }\n\n const nextFiles = multiple ? [...currentFiles, ...acceptedFiles] : acceptedFiles.slice(0, 1);\n if (acceptedFiles.length > 0) {\n updateFiles(nextFiles);\n }\n if (validateFile) {\n for (const file of acceptedFiles) {\n const validation = pendingValidations.get(file);\n if (validation) {\n void validation\n .then((message) => {\n if (!message) return;\n const rejection = { file, reason: \"validation\" as const, message };\n updateFiles(nextFiles.filter((current) => fileKey(current) !== fileKey(file)));\n setRejections((current) => [...current, rejection]);\n onReject?.([rejection]);\n })\n .catch((error: unknown) => {\n const message = error instanceof Error ? error.message : \"File validation failed.\";\n const rejection = { file, reason: \"validation\" as const, message };\n updateFiles(nextFiles.filter((current) => fileKey(current) !== fileKey(file)));\n setRejections((current) => [...current, rejection]);\n onReject?.([rejection]);\n });\n }\n }\n }\n if (nextRejections.length > 0) {\n setRejections(nextRejections);\n onReject?.(nextRejections);\n } else {\n setRejections([]);\n }\n },\n [\n accept,\n currentFiles,\n disabled,\n fileLimit,\n maxSize,\n multiple,\n onReject,\n updateFiles,\n validateFile,\n ],\n );\n\n const cancelFile = useCallback((file: File) => onCancel?.(file), [onCancel]);\n\n const context = useMemo<UploadContextValue>(\n () => ({\n accept,\n addFiles,\n cancelFile,\n disabled,\n dropActive,\n files: currentFiles,\n inputId,\n inputRef,\n fileState,\n maxFiles: fileLimit,\n maxSize,\n multiple,\n removeFile,\n rejections,\n setDropActive,\n styles,\n }),\n [\n accept,\n addFiles,\n cancelFile,\n currentFiles,\n disabled,\n dropActive,\n fileLimit,\n fileState,\n inputId,\n maxSize,\n multiple,\n rejections,\n removeFile,\n styles,\n ],\n );\n\n return (\n <UploadContext.Provider value={context}>\n <div\n {...props}\n ref={ref}\n className={cx(styles.root, className)}\n data-disabled={disabled || undefined}\n data-jaci-component=\"upload\"\n data-slot=\"upload\"\n >\n {children}\n </div>\n </UploadContext.Provider>\n );\n});\n\nexport interface UploadDropzoneProps extends ComponentPropsWithoutRef<\"label\"> {\n children?: ReactNode;\n}\n\nexport const UploadDropzone = forwardRef<HTMLLabelElement, UploadDropzoneProps>(\n function UploadDropzone(\n { children, className, htmlFor, onDragEnter, onDragLeave, onDragOver, onDrop, ...props },\n ref,\n ) {\n const { addFiles, disabled, dropActive, inputId, setDropActive, styles } = useUploadContext();\n\n return (\n <label\n {...props}\n ref={ref}\n aria-disabled={disabled || undefined}\n className={cx(styles.dropzone, className)}\n data-drag-active={dropActive || undefined}\n data-slot=\"upload-dropzone\"\n htmlFor={htmlFor ?? inputId}\n onDragEnter={(event) => {\n event.preventDefault();\n if (!disabled) {\n setDropActive(true);\n event.currentTarget.dataset.dragActive = \"true\";\n }\n onDragEnter?.(event);\n }}\n onDragLeave={(event) => {\n event.preventDefault();\n if (event.currentTarget === event.target) {\n setDropActive(false);\n event.currentTarget.dataset.dragActive = \"false\";\n }\n onDragLeave?.(event);\n }}\n onDragOver={(event) => {\n event.preventDefault();\n if (!disabled) setDropActive(true);\n onDragOver?.(event);\n }}\n onDrop={(event) => {\n event.preventDefault();\n setDropActive(false);\n event.currentTarget.dataset.dragActive = \"false\";\n if (!disabled) addFiles(event.dataTransfer.files);\n onDrop?.(event);\n }}\n >\n {children}\n </label>\n );\n },\n);\n\nexport type UploadInputProps = ComponentPropsWithoutRef<\"input\">;\n\nexport const UploadInput = forwardRef<HTMLInputElement, UploadInputProps>(function UploadInput(\n { accept, className, id, multiple, onChange, ...props },\n ref,\n) {\n const {\n addFiles,\n accept: rootAccept,\n disabled,\n inputId,\n inputRef,\n multiple: rootMultiple,\n styles,\n } = useUploadContext();\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (event.currentTarget.files) addFiles(event.currentTarget.files);\n event.currentTarget.value = \"\";\n onChange?.(event);\n };\n\n return (\n <input\n {...props}\n accept={accept ?? rootAccept}\n aria-label={props[\"aria-label\"] ?? \"Select files\"}\n className={cx(styles.input, className)}\n disabled={disabled}\n id={id ?? inputId}\n multiple={multiple ?? rootMultiple}\n onChange={handleChange}\n ref={(node) => {\n inputRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n }}\n tabIndex={-1}\n type=\"file\"\n />\n );\n});\n\nexport type UploadTriggerProps = ComponentPropsWithoutRef<\"button\">;\n\nexport const UploadTrigger = forwardRef<HTMLButtonElement, UploadTriggerProps>(\n function UploadTrigger(\n { children = \"Choose files\", className, disabled, onClick, ...props },\n ref,\n ) {\n const { disabled: rootDisabled, inputRef, styles } = useUploadContext();\n\n return (\n <button\n {...props}\n className={cx(styles.trigger, className)}\n data-slot=\"upload-trigger\"\n disabled={disabled ?? rootDisabled}\n onClick={(event) => {\n inputRef.current?.click();\n onClick?.(event);\n }}\n ref={ref}\n type=\"button\"\n >\n {children}\n </button>\n );\n },\n);\n\nexport type UploadIconProps = ComponentPropsWithoutRef<\"span\">;\n\nexport const UploadIcon = forwardRef<HTMLSpanElement, UploadIconProps>(function UploadIcon(\n { children = \"↥\", className, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n return (\n <span\n {...props}\n ref={ref}\n aria-hidden=\"true\"\n className={cx(styles.icon, className)}\n data-slot=\"upload-icon\"\n >\n {children}\n </span>\n );\n});\n\nexport type UploadTextProps = ComponentPropsWithoutRef<\"span\">;\n\nexport const UploadText = forwardRef<HTMLSpanElement, UploadTextProps>(function UploadText(\n { className, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n return (\n <span {...props} ref={ref} className={cx(styles.text, className)} data-slot=\"upload-text\" />\n );\n});\n\nexport type UploadHintProps = ComponentPropsWithoutRef<\"span\">;\n\nexport const UploadHint = forwardRef<HTMLSpanElement, UploadHintProps>(function UploadHint(\n { className, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n return (\n <span {...props} ref={ref} className={cx(styles.hint, className)} data-slot=\"upload-hint\" />\n );\n});\n\nexport interface UploadPreviewProps extends ComponentPropsWithoutRef<\"span\"> {\n /** File whose preview should be rendered. Image files use a temporary object URL. */\n file: File;\n /** Alternative text for image previews. Defaults to the file name. */\n alt?: string;\n /** Content rendered while the preview is unavailable or the file is not an image. */\n fallback?: ReactNode;\n}\n\nexport const UploadPreview = forwardRef<HTMLSpanElement, UploadPreviewProps>(function UploadPreview(\n { alt, className, fallback = \"Preview unavailable\", file, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n const [src, setSrc] = useState<string | null>(null);\n\n useEffect(() => {\n if (\n !file.type.startsWith(\"image/\") ||\n typeof URL === \"undefined\" ||\n typeof URL.createObjectURL !== \"function\"\n ) {\n setSrc(null);\n return;\n }\n\n const objectUrl = URL.createObjectURL(file);\n setSrc(objectUrl);\n return () => URL.revokeObjectURL(objectUrl);\n }, [file]);\n\n return (\n <span\n {...props}\n ref={ref}\n aria-hidden={props[\"aria-label\"] ? undefined : true}\n className={cx(styles.preview, className)}\n data-slot=\"upload-preview\"\n role={props[\"aria-label\"] ? \"img\" : undefined}\n >\n {src ? <img alt={alt ?? file.name} src={src} /> : fallback}\n </span>\n );\n});\n\nexport interface UploadProgressProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n /** Progress from 0 to 100. Omit it for an indeterminate upload. */\n value?: number;\n /** Accessible label and optional visible status text. */\n label?: ReactNode;\n file?: File;\n}\n\nexport const UploadProgress = forwardRef<HTMLDivElement, UploadProgressProps>(\n function UploadProgress({ className, file, label = \"Uploading\", value, ...props }, ref) {\n const { fileState, styles } = useUploadContext();\n const state = file ? fileState?.(file) : undefined;\n const normalizedValue =\n value === undefined\n ? state?.progress === undefined\n ? undefined\n : Math.min(100, Math.max(0, state.progress))\n : Math.min(100, Math.max(0, value));\n\n return (\n <div\n {...props}\n ref={ref}\n aria-label={typeof label === \"string\" ? label : \"Upload progress\"}\n aria-valuemax={100}\n aria-valuemin={0}\n aria-valuenow={normalizedValue}\n className={cx(styles.progress, className)}\n data-indeterminate={normalizedValue === undefined || undefined}\n data-slot=\"upload-progress\"\n role=\"progressbar\"\n >\n <span className={styles.progressTrack} data-slot=\"upload-progress-track\">\n <span\n className={styles.progressIndicator}\n data-indeterminate={normalizedValue === undefined || undefined}\n data-slot=\"upload-progress-indicator\"\n style={{ width: normalizedValue === undefined ? undefined : `${normalizedValue}%` }}\n />\n </span>\n <span className={styles.progressLabel} data-slot=\"upload-progress-label\">\n {label}\n </span>\n </div>\n );\n },\n);\n\nexport type UploadListProps = ComponentPropsWithoutRef<\"ul\">;\n\nexport const UploadList = forwardRef<HTMLUListElement, UploadListProps>(function UploadList(\n { children, className, ...props },\n ref,\n) {\n const { files, styles } = useUploadContext();\n return (\n <ul {...props} ref={ref} className={cx(styles.list, className)} data-slot=\"upload-list\">\n {children ?? files.map((file) => <UploadItem file={file} key={fileKey(file)} />)}\n </ul>\n );\n});\n\nexport interface UploadItemProps extends Omit<ComponentPropsWithoutRef<\"li\">, \"children\"> {\n file: File;\n children?: ReactNode;\n}\n\nexport const UploadItem = forwardRef<HTMLLIElement, UploadItemProps>(function UploadItem(\n { children, className, file, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n return (\n <li {...props} ref={ref} className={cx(styles.item, className)} data-slot=\"upload-item\">\n {children ?? (\n <>\n <span className={styles.itemName} data-slot=\"upload-item-name\" title={file.name}>\n {file.name}\n </span>\n <span className={styles.itemMeta} data-slot=\"upload-item-meta\">\n {formatBytes(file.size)}\n </span>\n <UploadRemove file={file} />\n </>\n )}\n </li>\n );\n});\n\nexport interface UploadRemoveProps extends ComponentPropsWithoutRef<\"button\"> {\n file: File;\n}\n\nexport const UploadRemove = forwardRef<HTMLButtonElement, UploadRemoveProps>(function UploadRemove(\n { children = \"×\", className, file, onClick, ...props },\n ref,\n) {\n const { disabled, removeFile, styles } = useUploadContext();\n return (\n <button\n {...props}\n aria-label={props[\"aria-label\"] ?? `Remove ${file.name}`}\n className={cx(styles.remove, className)}\n data-slot=\"upload-remove\"\n disabled={disabled}\n onClick={(event) => {\n removeFile(file);\n onClick?.(event);\n }}\n ref={ref}\n type=\"button\"\n >\n {children}\n </button>\n );\n});\n\nexport interface UploadStatusProps extends ComponentPropsWithoutRef<\"span\"> {\n file: File;\n}\n\nexport const UploadStatus = forwardRef<HTMLSpanElement, UploadStatusProps>(function UploadStatus(\n { children, className, file, ...props },\n ref,\n) {\n const { fileState, styles } = useUploadContext();\n const state = fileState?.(file);\n const content = children ?? state?.error ?? state?.status ?? \"queued\";\n return (\n <span\n {...props}\n aria-live=\"polite\"\n className={cx(styles.status, className)}\n data-status={state?.status}\n data-slot=\"upload-status\"\n ref={ref}\n >\n {content}\n </span>\n );\n});\n\nexport interface UploadCancelProps extends ComponentPropsWithoutRef<\"button\"> {\n file: File;\n}\n\nexport const UploadCancel = forwardRef<HTMLButtonElement, UploadCancelProps>(function UploadCancel(\n { children = \"Cancel\", className, file, onClick, ...props },\n ref,\n) {\n const { cancelFile, disabled, fileState, styles } = useUploadContext();\n const state = fileState?.(file);\n return (\n <button\n {...props}\n aria-label={props[\"aria-label\"] ?? `Cancel ${file.name}`}\n className={cx(styles.cancel, className)}\n data-slot=\"upload-cancel\"\n disabled={disabled || state?.status === \"canceled\" || state?.status === \"success\"}\n onClick={(event) => {\n cancelFile(file);\n onClick?.(event);\n }}\n ref={ref}\n type=\"button\"\n >\n {children}\n </button>\n );\n});\n\nexport type UploadErrorProps = ComponentPropsWithoutRef<\"p\">;\n\nexport const UploadError = forwardRef<HTMLParagraphElement, UploadErrorProps>(function UploadError(\n { children, className, ...props },\n ref,\n) {\n const { rejections, styles } = useUploadContext();\n if (children === undefined && rejections.length === 0) return null;\n\n return (\n <p\n {...props}\n ref={ref}\n className={cx(styles.error, className)}\n data-slot=\"upload-error\"\n role=\"alert\"\n >\n {children ?? rejections.map((rejection) => rejection.message).join(\" \")}\n </p>\n );\n});\n\nexport const Upload = {\n Root: UploadRoot,\n Dropzone: UploadDropzone,\n Input: UploadInput,\n Trigger: UploadTrigger,\n Icon: UploadIcon,\n Text: UploadText,\n Hint: UploadHint,\n Preview: UploadPreview,\n Progress: UploadProgress,\n List: UploadList,\n Item: UploadItem,\n Remove: UploadRemove,\n Status: UploadStatus,\n Cancel: UploadCancel,\n Error: UploadError,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"upload.cjs","names":["createContext","useContext","forwardRef","useState","useRef","useId","upload","useCallback","useMemo","cx"],"sources":["../../../src/components/upload/upload.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { ChangeEvent, ComponentPropsWithoutRef, ReactNode, RefObject } from \"react\";\n\nimport { cx } from \"../../styled-system/css\";\nimport { upload } from \"../../styled-system/recipes\";\n\nexport type UploadRejectionReason = \"type\" | \"size\" | \"count\" | \"duplicate\" | \"validation\";\n\nexport type UploadFileStatus = \"queued\" | \"uploading\" | \"success\" | \"error\" | \"canceled\";\n\nexport interface UploadFileState {\n status: UploadFileStatus;\n progress?: number;\n error?: ReactNode;\n}\n\nexport interface UploadRejection {\n file: File;\n message: string;\n reason: UploadRejectionReason;\n}\n\ninterface UploadContextValue {\n accept: string | undefined;\n addFiles: (files: FileList | File[]) => void;\n disabled: boolean;\n dropActive: boolean;\n files: File[];\n inputId: string;\n inputRef: RefObject<HTMLInputElement | null>;\n fileState: ((file: File) => UploadFileState | undefined) | undefined;\n maxFiles: number | undefined;\n maxSize: number | undefined;\n multiple: boolean;\n removeFile: (file: File) => void;\n cancelFile: (file: File) => void;\n rejections: UploadRejection[];\n setDropActive: (active: boolean) => void;\n styles: ReturnType<typeof upload>;\n}\n\nconst UploadContext = createContext<UploadContextValue | null>(null);\n\nfunction useUploadContext() {\n const context = useContext(UploadContext);\n if (!context) {\n throw new Error(\"Upload parts must be rendered inside Upload.Root.\");\n }\n\n return context;\n}\n\nfunction fileKey(file: File) {\n return `${file.name}-${file.size}-${file.lastModified}`;\n}\n\nfunction formatBytes(bytes: number) {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction acceptsFile(file: File, accept: string | undefined) {\n if (!accept) {\n return true;\n }\n\n const fileName = file.name.toLowerCase();\n const fileType = file.type.toLowerCase();\n\n return accept.split(\",\").some((entry) => {\n const pattern = entry.trim().toLowerCase();\n if (!pattern) return true;\n if (pattern.startsWith(\".\")) return fileName.endsWith(pattern);\n if (pattern.endsWith(\"/*\")) return fileType.startsWith(pattern.slice(0, -1));\n return pattern === fileType;\n });\n}\n\nexport interface UploadRootProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"onChange\"> {\n /** Accepted MIME types or file extensions, using the native input syntax. */\n accept?: string;\n /** Controlled files. Use with `onFilesChange`. */\n files?: File[];\n /** Initial files for an uncontrolled upload. */\n defaultFiles?: File[];\n /** Called whenever accepted files are added or removed. */\n onFilesChange?: (files: File[]) => void;\n /** Called with files rejected by `accept`, `maxSize`, `maxFiles` or duplicates. */\n onReject?: (rejections: UploadRejection[]) => void;\n /** Maximum number of accepted files. Defaults to one when `multiple` is false. */\n maxFiles?: number;\n /** Maximum size per file, in bytes. */\n maxSize?: number;\n /** Allows selecting more than one file. */\n multiple?: boolean;\n /** Disables file selection and drag-and-drop. */\n disabled?: boolean;\n /** Optional asynchronous validation. Return an error message to reject a file. */\n validateFile?: (file: File) => string | null | Promise<string | null>;\n /** Controlled status used by the status, progress and cancel slots. */\n fileState?: (file: File) => UploadFileState | undefined;\n /** Called when a consumer cancels an upload. */\n onCancel?: (file: File) => void;\n children?: ReactNode;\n}\n\nexport const UploadRoot = forwardRef<HTMLDivElement, UploadRootProps>(function UploadRoot(\n {\n accept,\n fileState,\n children,\n className,\n defaultFiles = [],\n disabled = false,\n files: controlledFiles,\n maxFiles,\n maxSize,\n multiple = false,\n onFilesChange,\n onCancel,\n onReject,\n validateFile,\n ...props\n },\n ref,\n) {\n const [uncontrolledFiles, setUncontrolledFiles] = useState<File[]>(defaultFiles);\n const [dropActive, setDropActive] = useState(false);\n const [rejections, setRejections] = useState<UploadRejection[]>([]);\n const inputRef = useRef<HTMLInputElement>(null);\n const inputId = useId();\n const styles = upload({ disabled, dropActive });\n const currentFiles = controlledFiles ?? uncontrolledFiles;\n const fileLimit = maxFiles ?? (multiple ? undefined : 1);\n\n const updateFiles = useCallback(\n (nextFiles: File[]) => {\n if (controlledFiles === undefined) setUncontrolledFiles(nextFiles);\n onFilesChange?.(nextFiles);\n },\n [controlledFiles, onFilesChange],\n );\n\n const removeFile = useCallback(\n (file: File) => {\n updateFiles(currentFiles.filter((current) => fileKey(current) !== fileKey(file)));\n },\n [currentFiles, updateFiles],\n );\n\n const addFiles = useCallback(\n (fileList: FileList | File[]) => {\n if (disabled) return;\n\n const candidates = Array.from(fileList);\n const acceptedFiles: File[] = [];\n const nextRejections: UploadRejection[] = [];\n const pendingValidations = new Map<File, Promise<string | null>>();\n const existingKeys = new Set(currentFiles.map(fileKey));\n\n for (const file of candidates) {\n const key = fileKey(file);\n if (existingKeys.has(key) || acceptedFiles.some((accepted) => fileKey(accepted) === key)) {\n nextRejections.push({\n file,\n reason: \"duplicate\",\n message: `${file.name} was already added.`,\n });\n continue;\n }\n if (!acceptsFile(file, accept)) {\n nextRejections.push({\n file,\n reason: \"type\",\n message: `${file.name} is not an accepted file type.`,\n });\n continue;\n }\n if (maxSize !== undefined && file.size > maxSize) {\n nextRejections.push({\n file,\n reason: \"size\",\n message: `${file.name} is larger than the allowed limit.`,\n });\n continue;\n }\n if (\n fileLimit !== undefined &&\n (multiple ? currentFiles.length + acceptedFiles.length : acceptedFiles.length) >=\n fileLimit\n ) {\n nextRejections.push({\n file,\n reason: \"count\",\n message: `Only ${fileLimit} file${fileLimit === 1 ? \"\" : \"s\"} can be selected.`,\n });\n continue;\n }\n if (validateFile) {\n const validation = validateFile(file);\n if (validation && typeof validation !== \"object\") {\n nextRejections.push({ file, reason: \"validation\", message: validation });\n continue;\n }\n if (validation && typeof validation === \"object\" && \"then\" in validation) {\n pendingValidations.set(file, Promise.resolve(validation));\n }\n }\n acceptedFiles.push(file);\n }\n\n const nextFiles = multiple ? [...currentFiles, ...acceptedFiles] : acceptedFiles.slice(0, 1);\n if (acceptedFiles.length > 0) {\n updateFiles(nextFiles);\n }\n if (validateFile) {\n for (const file of acceptedFiles) {\n const validation = pendingValidations.get(file);\n if (validation) {\n void validation\n .then((message) => {\n if (!message) return;\n const rejection = { file, reason: \"validation\" as const, message };\n updateFiles(nextFiles.filter((current) => fileKey(current) !== fileKey(file)));\n setRejections((current) => [...current, rejection]);\n onReject?.([rejection]);\n })\n .catch((error: unknown) => {\n const message = error instanceof Error ? error.message : \"File validation failed.\";\n const rejection = { file, reason: \"validation\" as const, message };\n updateFiles(nextFiles.filter((current) => fileKey(current) !== fileKey(file)));\n setRejections((current) => [...current, rejection]);\n onReject?.([rejection]);\n });\n }\n }\n }\n if (nextRejections.length > 0) {\n setRejections(nextRejections);\n onReject?.(nextRejections);\n } else {\n setRejections([]);\n }\n },\n [\n accept,\n currentFiles,\n disabled,\n fileLimit,\n maxSize,\n multiple,\n onReject,\n updateFiles,\n validateFile,\n ],\n );\n\n const cancelFile = useCallback((file: File) => onCancel?.(file), [onCancel]);\n\n const context = useMemo<UploadContextValue>(\n () => ({\n accept,\n addFiles,\n cancelFile,\n disabled,\n dropActive,\n files: currentFiles,\n inputId,\n inputRef,\n fileState,\n maxFiles: fileLimit,\n maxSize,\n multiple,\n removeFile,\n rejections,\n setDropActive,\n styles,\n }),\n [\n accept,\n addFiles,\n cancelFile,\n currentFiles,\n disabled,\n dropActive,\n fileLimit,\n fileState,\n inputId,\n maxSize,\n multiple,\n rejections,\n removeFile,\n styles,\n ],\n );\n\n return (\n <UploadContext.Provider value={context}>\n <div\n {...props}\n ref={ref}\n className={cx(styles.root, className)}\n data-disabled={disabled || undefined}\n data-jaci-component=\"upload\"\n data-slot=\"upload\"\n >\n {children}\n </div>\n </UploadContext.Provider>\n );\n});\n\nexport interface UploadDropzoneProps extends ComponentPropsWithoutRef<\"label\"> {\n children?: ReactNode;\n}\n\nexport const UploadDropzone = forwardRef<HTMLLabelElement, UploadDropzoneProps>(\n function UploadDropzone(\n { children, className, htmlFor, onDragEnter, onDragLeave, onDragOver, onDrop, ...props },\n ref,\n ) {\n const { addFiles, disabled, dropActive, inputId, setDropActive, styles } = useUploadContext();\n\n return (\n <label\n {...props}\n ref={ref}\n aria-disabled={disabled || undefined}\n className={cx(styles.dropzone, className)}\n data-drag-active={dropActive || undefined}\n data-slot=\"upload-dropzone\"\n htmlFor={htmlFor ?? inputId}\n onDragEnter={(event) => {\n event.preventDefault();\n if (!disabled) {\n setDropActive(true);\n event.currentTarget.dataset.dragActive = \"true\";\n }\n onDragEnter?.(event);\n }}\n onDragLeave={(event) => {\n event.preventDefault();\n if (event.currentTarget === event.target) {\n setDropActive(false);\n event.currentTarget.dataset.dragActive = \"false\";\n }\n onDragLeave?.(event);\n }}\n onDragOver={(event) => {\n event.preventDefault();\n if (!disabled) setDropActive(true);\n onDragOver?.(event);\n }}\n onDrop={(event) => {\n event.preventDefault();\n setDropActive(false);\n event.currentTarget.dataset.dragActive = \"false\";\n if (!disabled) addFiles(event.dataTransfer.files);\n onDrop?.(event);\n }}\n >\n {children}\n </label>\n );\n },\n);\n\nexport type UploadInputProps = ComponentPropsWithoutRef<\"input\">;\n\nexport const UploadInput = forwardRef<HTMLInputElement, UploadInputProps>(function UploadInput(\n { accept, className, id, multiple, onChange, ...props },\n ref,\n) {\n const {\n addFiles,\n accept: rootAccept,\n disabled,\n inputId,\n inputRef,\n multiple: rootMultiple,\n styles,\n } = useUploadContext();\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (event.currentTarget.files) addFiles(event.currentTarget.files);\n event.currentTarget.value = \"\";\n onChange?.(event);\n };\n\n return (\n <input\n {...props}\n accept={accept ?? rootAccept}\n aria-label={props[\"aria-label\"] ?? \"Select files\"}\n className={cx(styles.input, className)}\n disabled={disabled}\n id={id ?? inputId}\n multiple={multiple ?? rootMultiple}\n onChange={handleChange}\n ref={(node) => {\n inputRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n }}\n tabIndex={-1}\n type=\"file\"\n />\n );\n});\n\nexport type UploadTriggerProps = ComponentPropsWithoutRef<\"button\">;\n\nexport const UploadTrigger = forwardRef<HTMLButtonElement, UploadTriggerProps>(\n function UploadTrigger(\n { children = \"Choose files\", className, disabled, onClick, ...props },\n ref,\n ) {\n const { disabled: rootDisabled, inputRef, styles } = useUploadContext();\n\n return (\n <button\n {...props}\n className={cx(styles.trigger, className)}\n data-slot=\"upload-trigger\"\n disabled={disabled ?? rootDisabled}\n onClick={(event) => {\n inputRef.current?.click();\n onClick?.(event);\n }}\n ref={ref}\n type=\"button\"\n >\n {children}\n </button>\n );\n },\n);\n\nexport type UploadIconProps = ComponentPropsWithoutRef<\"span\">;\n\nexport const UploadIcon = forwardRef<HTMLSpanElement, UploadIconProps>(function UploadIcon(\n { children = \"↥\", className, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n return (\n <span\n {...props}\n ref={ref}\n aria-hidden=\"true\"\n className={cx(styles.icon, className)}\n data-slot=\"upload-icon\"\n >\n {children}\n </span>\n );\n});\n\nexport type UploadTextProps = ComponentPropsWithoutRef<\"span\">;\n\nexport const UploadText = forwardRef<HTMLSpanElement, UploadTextProps>(function UploadText(\n { className, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n return (\n <span {...props} ref={ref} className={cx(styles.text, className)} data-slot=\"upload-text\" />\n );\n});\n\nexport type UploadHintProps = ComponentPropsWithoutRef<\"span\">;\n\nexport const UploadHint = forwardRef<HTMLSpanElement, UploadHintProps>(function UploadHint(\n { className, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n return (\n <span {...props} ref={ref} className={cx(styles.hint, className)} data-slot=\"upload-hint\" />\n );\n});\n\nexport interface UploadPreviewProps extends ComponentPropsWithoutRef<\"span\"> {\n /** File whose preview should be rendered. Image files use a temporary object URL. */\n file: File;\n /** Alternative text for image previews. Defaults to the file name. */\n alt?: string;\n /** Content rendered while the preview is unavailable or the file is not an image. */\n fallback?: ReactNode;\n}\n\nexport const UploadPreview = forwardRef<HTMLSpanElement, UploadPreviewProps>(function UploadPreview(\n { alt, className, fallback = \"Preview unavailable\", file, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n const [src, setSrc] = useState<string | null>(null);\n\n useEffect(() => {\n if (\n !file.type.startsWith(\"image/\") ||\n typeof URL === \"undefined\" ||\n typeof URL.createObjectURL !== \"function\"\n ) {\n setSrc(null);\n return;\n }\n\n const objectUrl = URL.createObjectURL(file);\n setSrc(objectUrl);\n return () => URL.revokeObjectURL(objectUrl);\n }, [file]);\n\n return (\n <span\n {...props}\n ref={ref}\n aria-hidden={props[\"aria-label\"] ? undefined : true}\n className={cx(styles.preview, className)}\n data-slot=\"upload-preview\"\n role={props[\"aria-label\"] ? \"img\" : undefined}\n >\n {src ? <img alt={alt ?? file.name} src={src} /> : fallback}\n </span>\n );\n});\n\nexport interface UploadProgressProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n /** Progress from 0 to 100. Omit it for an indeterminate upload. */\n value?: number;\n /** Accessible label and optional visible status text. */\n label?: ReactNode;\n file?: File;\n}\n\nexport const UploadProgress = forwardRef<HTMLDivElement, UploadProgressProps>(\n function UploadProgress({ className, file, label = \"Uploading\", value, ...props }, ref) {\n const { fileState, styles } = useUploadContext();\n const state = file ? fileState?.(file) : undefined;\n const normalizedValue =\n value === undefined\n ? state?.progress === undefined\n ? undefined\n : Math.min(100, Math.max(0, state.progress))\n : Math.min(100, Math.max(0, value));\n\n return (\n <div\n {...props}\n ref={ref}\n aria-label={typeof label === \"string\" ? label : \"Upload progress\"}\n aria-valuemax={100}\n aria-valuemin={0}\n aria-valuenow={normalizedValue}\n className={cx(styles.progress, className)}\n data-indeterminate={normalizedValue === undefined || undefined}\n data-slot=\"upload-progress\"\n role=\"progressbar\"\n >\n <span className={styles.progressTrack} data-slot=\"upload-progress-track\">\n <span\n className={styles.progressIndicator}\n data-indeterminate={normalizedValue === undefined || undefined}\n data-slot=\"upload-progress-indicator\"\n style={{ width: normalizedValue === undefined ? undefined : `${normalizedValue}%` }}\n />\n </span>\n <span className={styles.progressLabel} data-slot=\"upload-progress-label\">\n {label}\n </span>\n </div>\n );\n },\n);\n\nexport type UploadListProps = ComponentPropsWithoutRef<\"ul\">;\n\nexport const UploadList = forwardRef<HTMLUListElement, UploadListProps>(function UploadList(\n { children, className, ...props },\n ref,\n) {\n const { files, styles } = useUploadContext();\n return (\n <ul {...props} ref={ref} className={cx(styles.list, className)} data-slot=\"upload-list\">\n {children ?? files.map((file) => <UploadItem file={file} key={fileKey(file)} />)}\n </ul>\n );\n});\n\nexport interface UploadItemProps extends Omit<ComponentPropsWithoutRef<\"li\">, \"children\"> {\n file: File;\n children?: ReactNode;\n}\n\nexport const UploadItem = forwardRef<HTMLLIElement, UploadItemProps>(function UploadItem(\n { children, className, file, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n return (\n <li {...props} ref={ref} className={cx(styles.item, className)} data-slot=\"upload-item\">\n {children ?? (\n <>\n <span className={styles.itemName} data-slot=\"upload-item-name\" title={file.name}>\n {file.name}\n </span>\n <span className={styles.itemMeta} data-slot=\"upload-item-meta\">\n {formatBytes(file.size)}\n </span>\n <UploadRemove file={file} />\n </>\n )}\n </li>\n );\n});\n\nexport interface UploadRemoveProps extends ComponentPropsWithoutRef<\"button\"> {\n file: File;\n}\n\nexport const UploadRemove = forwardRef<HTMLButtonElement, UploadRemoveProps>(function UploadRemove(\n { children = \"×\", className, file, onClick, ...props },\n ref,\n) {\n const { disabled, removeFile, styles } = useUploadContext();\n return (\n <button\n {...props}\n aria-label={props[\"aria-label\"] ?? `Remove ${file.name}`}\n className={cx(styles.remove, className)}\n data-slot=\"upload-remove\"\n disabled={disabled}\n onClick={(event) => {\n removeFile(file);\n onClick?.(event);\n }}\n ref={ref}\n type=\"button\"\n >\n {children}\n </button>\n );\n});\n\nexport interface UploadStatusProps extends ComponentPropsWithoutRef<\"span\"> {\n file: File;\n}\n\nexport const UploadStatus = forwardRef<HTMLSpanElement, UploadStatusProps>(function UploadStatus(\n { children, className, file, ...props },\n ref,\n) {\n const { fileState, styles } = useUploadContext();\n const state = fileState?.(file);\n const content = children ?? state?.error ?? state?.status ?? \"queued\";\n return (\n <span\n {...props}\n aria-live=\"polite\"\n className={cx(styles.status, className)}\n data-status={state?.status}\n data-slot=\"upload-status\"\n ref={ref}\n >\n {content}\n </span>\n );\n});\n\nexport interface UploadCancelProps extends ComponentPropsWithoutRef<\"button\"> {\n file: File;\n}\n\nexport const UploadCancel = forwardRef<HTMLButtonElement, UploadCancelProps>(function UploadCancel(\n { children = \"Cancel\", className, file, onClick, ...props },\n ref,\n) {\n const { cancelFile, disabled, fileState, styles } = useUploadContext();\n const state = fileState?.(file);\n return (\n <button\n {...props}\n aria-label={props[\"aria-label\"] ?? `Cancel ${file.name}`}\n className={cx(styles.cancel, className)}\n data-slot=\"upload-cancel\"\n disabled={disabled || state?.status === \"canceled\" || state?.status === \"success\"}\n onClick={(event) => {\n cancelFile(file);\n onClick?.(event);\n }}\n ref={ref}\n type=\"button\"\n >\n {children}\n </button>\n );\n});\n\nexport type UploadErrorProps = ComponentPropsWithoutRef<\"p\">;\n\nexport const UploadError = forwardRef<HTMLParagraphElement, UploadErrorProps>(function UploadError(\n { children, className, ...props },\n ref,\n) {\n const { rejections, styles } = useUploadContext();\n if (children === undefined && rejections.length === 0) return null;\n\n return (\n <p\n {...props}\n ref={ref}\n className={cx(styles.error, className)}\n data-slot=\"upload-error\"\n role=\"alert\"\n >\n {children ?? rejections.map((rejection) => rejection.message).join(\" \")}\n </p>\n );\n});\n\nexport const Upload = {\n Root: UploadRoot,\n Dropzone: UploadDropzone,\n Input: UploadInput,\n Trigger: UploadTrigger,\n Icon: UploadIcon,\n Text: UploadText,\n Hint: UploadHint,\n Preview: UploadPreview,\n Progress: UploadProgress,\n List: UploadList,\n Item: UploadItem,\n Remove: UploadRemove,\n Status: UploadStatus,\n Cancel: UploadCancel,\n Error: UploadError,\n};\n"],"mappings":"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"}
|
|
@@ -15,8 +15,8 @@ function fileKey(file) {
|
|
|
15
15
|
}
|
|
16
16
|
function formatBytes(bytes) {
|
|
17
17
|
if (bytes < 1024) return `${bytes} B`;
|
|
18
|
-
if (bytes <
|
|
19
|
-
return `${(bytes /
|
|
18
|
+
if (bytes < 1048576) return `${Math.round(bytes / 1024)} KB`;
|
|
19
|
+
return `${(bytes / 1048576).toFixed(1)} MB`;
|
|
20
20
|
}
|
|
21
21
|
function acceptsFile(file, accept) {
|
|
22
22
|
if (!accept) return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.js","names":[],"sources":["../../../src/components/upload/upload.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { ChangeEvent, ComponentPropsWithoutRef, ReactNode, RefObject } from \"react\";\n\nimport { cx } from \"../../styled-system/css\";\nimport { upload } from \"../../styled-system/recipes\";\n\nexport type UploadRejectionReason = \"type\" | \"size\" | \"count\" | \"duplicate\" | \"validation\";\n\nexport type UploadFileStatus = \"queued\" | \"uploading\" | \"success\" | \"error\" | \"canceled\";\n\nexport interface UploadFileState {\n status: UploadFileStatus;\n progress?: number;\n error?: ReactNode;\n}\n\nexport interface UploadRejection {\n file: File;\n message: string;\n reason: UploadRejectionReason;\n}\n\ninterface UploadContextValue {\n accept: string | undefined;\n addFiles: (files: FileList | File[]) => void;\n disabled: boolean;\n dropActive: boolean;\n files: File[];\n inputId: string;\n inputRef: RefObject<HTMLInputElement | null>;\n fileState: ((file: File) => UploadFileState | undefined) | undefined;\n maxFiles: number | undefined;\n maxSize: number | undefined;\n multiple: boolean;\n removeFile: (file: File) => void;\n cancelFile: (file: File) => void;\n rejections: UploadRejection[];\n setDropActive: (active: boolean) => void;\n styles: ReturnType<typeof upload>;\n}\n\nconst UploadContext = createContext<UploadContextValue | null>(null);\n\nfunction useUploadContext() {\n const context = useContext(UploadContext);\n if (!context) {\n throw new Error(\"Upload parts must be rendered inside Upload.Root.\");\n }\n\n return context;\n}\n\nfunction fileKey(file: File) {\n return `${file.name}-${file.size}-${file.lastModified}`;\n}\n\nfunction formatBytes(bytes: number) {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction acceptsFile(file: File, accept: string | undefined) {\n if (!accept) {\n return true;\n }\n\n const fileName = file.name.toLowerCase();\n const fileType = file.type.toLowerCase();\n\n return accept.split(\",\").some((entry) => {\n const pattern = entry.trim().toLowerCase();\n if (!pattern) return true;\n if (pattern.startsWith(\".\")) return fileName.endsWith(pattern);\n if (pattern.endsWith(\"/*\")) return fileType.startsWith(pattern.slice(0, -1));\n return pattern === fileType;\n });\n}\n\nexport interface UploadRootProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"onChange\"> {\n /** Accepted MIME types or file extensions, using the native input syntax. */\n accept?: string;\n /** Controlled files. Use with `onFilesChange`. */\n files?: File[];\n /** Initial files for an uncontrolled upload. */\n defaultFiles?: File[];\n /** Called whenever accepted files are added or removed. */\n onFilesChange?: (files: File[]) => void;\n /** Called with files rejected by `accept`, `maxSize`, `maxFiles` or duplicates. */\n onReject?: (rejections: UploadRejection[]) => void;\n /** Maximum number of accepted files. Defaults to one when `multiple` is false. */\n maxFiles?: number;\n /** Maximum size per file, in bytes. */\n maxSize?: number;\n /** Allows selecting more than one file. */\n multiple?: boolean;\n /** Disables file selection and drag-and-drop. */\n disabled?: boolean;\n /** Optional asynchronous validation. Return an error message to reject a file. */\n validateFile?: (file: File) => string | null | Promise<string | null>;\n /** Controlled status used by the status, progress and cancel slots. */\n fileState?: (file: File) => UploadFileState | undefined;\n /** Called when a consumer cancels an upload. */\n onCancel?: (file: File) => void;\n children?: ReactNode;\n}\n\nexport const UploadRoot = forwardRef<HTMLDivElement, UploadRootProps>(function UploadRoot(\n {\n accept,\n fileState,\n children,\n className,\n defaultFiles = [],\n disabled = false,\n files: controlledFiles,\n maxFiles,\n maxSize,\n multiple = false,\n onFilesChange,\n onCancel,\n onReject,\n validateFile,\n ...props\n },\n ref,\n) {\n const [uncontrolledFiles, setUncontrolledFiles] = useState<File[]>(defaultFiles);\n const [dropActive, setDropActive] = useState(false);\n const [rejections, setRejections] = useState<UploadRejection[]>([]);\n const inputRef = useRef<HTMLInputElement>(null);\n const inputId = useId();\n const styles = upload({ disabled, dropActive });\n const currentFiles = controlledFiles ?? uncontrolledFiles;\n const fileLimit = maxFiles ?? (multiple ? undefined : 1);\n\n const updateFiles = useCallback(\n (nextFiles: File[]) => {\n if (controlledFiles === undefined) setUncontrolledFiles(nextFiles);\n onFilesChange?.(nextFiles);\n },\n [controlledFiles, onFilesChange],\n );\n\n const removeFile = useCallback(\n (file: File) => {\n updateFiles(currentFiles.filter((current) => fileKey(current) !== fileKey(file)));\n },\n [currentFiles, updateFiles],\n );\n\n const addFiles = useCallback(\n (fileList: FileList | File[]) => {\n if (disabled) return;\n\n const candidates = Array.from(fileList);\n const acceptedFiles: File[] = [];\n const nextRejections: UploadRejection[] = [];\n const pendingValidations = new Map<File, Promise<string | null>>();\n const existingKeys = new Set(currentFiles.map(fileKey));\n\n for (const file of candidates) {\n const key = fileKey(file);\n if (existingKeys.has(key) || acceptedFiles.some((accepted) => fileKey(accepted) === key)) {\n nextRejections.push({\n file,\n reason: \"duplicate\",\n message: `${file.name} was already added.`,\n });\n continue;\n }\n if (!acceptsFile(file, accept)) {\n nextRejections.push({\n file,\n reason: \"type\",\n message: `${file.name} is not an accepted file type.`,\n });\n continue;\n }\n if (maxSize !== undefined && file.size > maxSize) {\n nextRejections.push({\n file,\n reason: \"size\",\n message: `${file.name} is larger than the allowed limit.`,\n });\n continue;\n }\n if (\n fileLimit !== undefined &&\n (multiple ? currentFiles.length + acceptedFiles.length : acceptedFiles.length) >=\n fileLimit\n ) {\n nextRejections.push({\n file,\n reason: \"count\",\n message: `Only ${fileLimit} file${fileLimit === 1 ? \"\" : \"s\"} can be selected.`,\n });\n continue;\n }\n if (validateFile) {\n const validation = validateFile(file);\n if (validation && typeof validation !== \"object\") {\n nextRejections.push({ file, reason: \"validation\", message: validation });\n continue;\n }\n if (validation && typeof validation === \"object\" && \"then\" in validation) {\n pendingValidations.set(file, Promise.resolve(validation));\n }\n }\n acceptedFiles.push(file);\n }\n\n const nextFiles = multiple ? [...currentFiles, ...acceptedFiles] : acceptedFiles.slice(0, 1);\n if (acceptedFiles.length > 0) {\n updateFiles(nextFiles);\n }\n if (validateFile) {\n for (const file of acceptedFiles) {\n const validation = pendingValidations.get(file);\n if (validation) {\n void validation\n .then((message) => {\n if (!message) return;\n const rejection = { file, reason: \"validation\" as const, message };\n updateFiles(nextFiles.filter((current) => fileKey(current) !== fileKey(file)));\n setRejections((current) => [...current, rejection]);\n onReject?.([rejection]);\n })\n .catch((error: unknown) => {\n const message = error instanceof Error ? error.message : \"File validation failed.\";\n const rejection = { file, reason: \"validation\" as const, message };\n updateFiles(nextFiles.filter((current) => fileKey(current) !== fileKey(file)));\n setRejections((current) => [...current, rejection]);\n onReject?.([rejection]);\n });\n }\n }\n }\n if (nextRejections.length > 0) {\n setRejections(nextRejections);\n onReject?.(nextRejections);\n } else {\n setRejections([]);\n }\n },\n [\n accept,\n currentFiles,\n disabled,\n fileLimit,\n maxSize,\n multiple,\n onReject,\n updateFiles,\n validateFile,\n ],\n );\n\n const cancelFile = useCallback((file: File) => onCancel?.(file), [onCancel]);\n\n const context = useMemo<UploadContextValue>(\n () => ({\n accept,\n addFiles,\n cancelFile,\n disabled,\n dropActive,\n files: currentFiles,\n inputId,\n inputRef,\n fileState,\n maxFiles: fileLimit,\n maxSize,\n multiple,\n removeFile,\n rejections,\n setDropActive,\n styles,\n }),\n [\n accept,\n addFiles,\n cancelFile,\n currentFiles,\n disabled,\n dropActive,\n fileLimit,\n fileState,\n inputId,\n maxSize,\n multiple,\n rejections,\n removeFile,\n styles,\n ],\n );\n\n return (\n <UploadContext.Provider value={context}>\n <div\n {...props}\n ref={ref}\n className={cx(styles.root, className)}\n data-disabled={disabled || undefined}\n data-jaci-component=\"upload\"\n data-slot=\"upload\"\n >\n {children}\n </div>\n </UploadContext.Provider>\n );\n});\n\nexport interface UploadDropzoneProps extends ComponentPropsWithoutRef<\"label\"> {\n children?: ReactNode;\n}\n\nexport const UploadDropzone = forwardRef<HTMLLabelElement, UploadDropzoneProps>(\n function UploadDropzone(\n { children, className, htmlFor, onDragEnter, onDragLeave, onDragOver, onDrop, ...props },\n ref,\n ) {\n const { addFiles, disabled, dropActive, inputId, setDropActive, styles } = useUploadContext();\n\n return (\n <label\n {...props}\n ref={ref}\n aria-disabled={disabled || undefined}\n className={cx(styles.dropzone, className)}\n data-drag-active={dropActive || undefined}\n data-slot=\"upload-dropzone\"\n htmlFor={htmlFor ?? inputId}\n onDragEnter={(event) => {\n event.preventDefault();\n if (!disabled) {\n setDropActive(true);\n event.currentTarget.dataset.dragActive = \"true\";\n }\n onDragEnter?.(event);\n }}\n onDragLeave={(event) => {\n event.preventDefault();\n if (event.currentTarget === event.target) {\n setDropActive(false);\n event.currentTarget.dataset.dragActive = \"false\";\n }\n onDragLeave?.(event);\n }}\n onDragOver={(event) => {\n event.preventDefault();\n if (!disabled) setDropActive(true);\n onDragOver?.(event);\n }}\n onDrop={(event) => {\n event.preventDefault();\n setDropActive(false);\n event.currentTarget.dataset.dragActive = \"false\";\n if (!disabled) addFiles(event.dataTransfer.files);\n onDrop?.(event);\n }}\n >\n {children}\n </label>\n );\n },\n);\n\nexport type UploadInputProps = ComponentPropsWithoutRef<\"input\">;\n\nexport const UploadInput = forwardRef<HTMLInputElement, UploadInputProps>(function UploadInput(\n { accept, className, id, multiple, onChange, ...props },\n ref,\n) {\n const {\n addFiles,\n accept: rootAccept,\n disabled,\n inputId,\n inputRef,\n multiple: rootMultiple,\n styles,\n } = useUploadContext();\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (event.currentTarget.files) addFiles(event.currentTarget.files);\n event.currentTarget.value = \"\";\n onChange?.(event);\n };\n\n return (\n <input\n {...props}\n accept={accept ?? rootAccept}\n aria-label={props[\"aria-label\"] ?? \"Select files\"}\n className={cx(styles.input, className)}\n disabled={disabled}\n id={id ?? inputId}\n multiple={multiple ?? rootMultiple}\n onChange={handleChange}\n ref={(node) => {\n inputRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n }}\n tabIndex={-1}\n type=\"file\"\n />\n );\n});\n\nexport type UploadTriggerProps = ComponentPropsWithoutRef<\"button\">;\n\nexport const UploadTrigger = forwardRef<HTMLButtonElement, UploadTriggerProps>(\n function UploadTrigger(\n { children = \"Choose files\", className, disabled, onClick, ...props },\n ref,\n ) {\n const { disabled: rootDisabled, inputRef, styles } = useUploadContext();\n\n return (\n <button\n {...props}\n className={cx(styles.trigger, className)}\n data-slot=\"upload-trigger\"\n disabled={disabled ?? rootDisabled}\n onClick={(event) => {\n inputRef.current?.click();\n onClick?.(event);\n }}\n ref={ref}\n type=\"button\"\n >\n {children}\n </button>\n );\n },\n);\n\nexport type UploadIconProps = ComponentPropsWithoutRef<\"span\">;\n\nexport const UploadIcon = forwardRef<HTMLSpanElement, UploadIconProps>(function UploadIcon(\n { children = \"↥\", className, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n return (\n <span\n {...props}\n ref={ref}\n aria-hidden=\"true\"\n className={cx(styles.icon, className)}\n data-slot=\"upload-icon\"\n >\n {children}\n </span>\n );\n});\n\nexport type UploadTextProps = ComponentPropsWithoutRef<\"span\">;\n\nexport const UploadText = forwardRef<HTMLSpanElement, UploadTextProps>(function UploadText(\n { className, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n return (\n <span {...props} ref={ref} className={cx(styles.text, className)} data-slot=\"upload-text\" />\n );\n});\n\nexport type UploadHintProps = ComponentPropsWithoutRef<\"span\">;\n\nexport const UploadHint = forwardRef<HTMLSpanElement, UploadHintProps>(function UploadHint(\n { className, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n return (\n <span {...props} ref={ref} className={cx(styles.hint, className)} data-slot=\"upload-hint\" />\n );\n});\n\nexport interface UploadPreviewProps extends ComponentPropsWithoutRef<\"span\"> {\n /** File whose preview should be rendered. Image files use a temporary object URL. */\n file: File;\n /** Alternative text for image previews. Defaults to the file name. */\n alt?: string;\n /** Content rendered while the preview is unavailable or the file is not an image. */\n fallback?: ReactNode;\n}\n\nexport const UploadPreview = forwardRef<HTMLSpanElement, UploadPreviewProps>(function UploadPreview(\n { alt, className, fallback = \"Preview unavailable\", file, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n const [src, setSrc] = useState<string | null>(null);\n\n useEffect(() => {\n if (\n !file.type.startsWith(\"image/\") ||\n typeof URL === \"undefined\" ||\n typeof URL.createObjectURL !== \"function\"\n ) {\n setSrc(null);\n return;\n }\n\n const objectUrl = URL.createObjectURL(file);\n setSrc(objectUrl);\n return () => URL.revokeObjectURL(objectUrl);\n }, [file]);\n\n return (\n <span\n {...props}\n ref={ref}\n aria-hidden={props[\"aria-label\"] ? undefined : true}\n className={cx(styles.preview, className)}\n data-slot=\"upload-preview\"\n role={props[\"aria-label\"] ? \"img\" : undefined}\n >\n {src ? <img alt={alt ?? file.name} src={src} /> : fallback}\n </span>\n );\n});\n\nexport interface UploadProgressProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n /** Progress from 0 to 100. Omit it for an indeterminate upload. */\n value?: number;\n /** Accessible label and optional visible status text. */\n label?: ReactNode;\n file?: File;\n}\n\nexport const UploadProgress = forwardRef<HTMLDivElement, UploadProgressProps>(\n function UploadProgress({ className, file, label = \"Uploading\", value, ...props }, ref) {\n const { fileState, styles } = useUploadContext();\n const state = file ? fileState?.(file) : undefined;\n const normalizedValue =\n value === undefined\n ? state?.progress === undefined\n ? undefined\n : Math.min(100, Math.max(0, state.progress))\n : Math.min(100, Math.max(0, value));\n\n return (\n <div\n {...props}\n ref={ref}\n aria-label={typeof label === \"string\" ? label : \"Upload progress\"}\n aria-valuemax={100}\n aria-valuemin={0}\n aria-valuenow={normalizedValue}\n className={cx(styles.progress, className)}\n data-indeterminate={normalizedValue === undefined || undefined}\n data-slot=\"upload-progress\"\n role=\"progressbar\"\n >\n <span className={styles.progressTrack} data-slot=\"upload-progress-track\">\n <span\n className={styles.progressIndicator}\n data-indeterminate={normalizedValue === undefined || undefined}\n data-slot=\"upload-progress-indicator\"\n style={{ width: normalizedValue === undefined ? undefined : `${normalizedValue}%` }}\n />\n </span>\n <span className={styles.progressLabel} data-slot=\"upload-progress-label\">\n {label}\n </span>\n </div>\n );\n },\n);\n\nexport type UploadListProps = ComponentPropsWithoutRef<\"ul\">;\n\nexport const UploadList = forwardRef<HTMLUListElement, UploadListProps>(function UploadList(\n { children, className, ...props },\n ref,\n) {\n const { files, styles } = useUploadContext();\n return (\n <ul {...props} ref={ref} className={cx(styles.list, className)} data-slot=\"upload-list\">\n {children ?? files.map((file) => <UploadItem file={file} key={fileKey(file)} />)}\n </ul>\n );\n});\n\nexport interface UploadItemProps extends Omit<ComponentPropsWithoutRef<\"li\">, \"children\"> {\n file: File;\n children?: ReactNode;\n}\n\nexport const UploadItem = forwardRef<HTMLLIElement, UploadItemProps>(function UploadItem(\n { children, className, file, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n return (\n <li {...props} ref={ref} className={cx(styles.item, className)} data-slot=\"upload-item\">\n {children ?? (\n <>\n <span className={styles.itemName} data-slot=\"upload-item-name\" title={file.name}>\n {file.name}\n </span>\n <span className={styles.itemMeta} data-slot=\"upload-item-meta\">\n {formatBytes(file.size)}\n </span>\n <UploadRemove file={file} />\n </>\n )}\n </li>\n );\n});\n\nexport interface UploadRemoveProps extends ComponentPropsWithoutRef<\"button\"> {\n file: File;\n}\n\nexport const UploadRemove = forwardRef<HTMLButtonElement, UploadRemoveProps>(function UploadRemove(\n { children = \"×\", className, file, onClick, ...props },\n ref,\n) {\n const { disabled, removeFile, styles } = useUploadContext();\n return (\n <button\n {...props}\n aria-label={props[\"aria-label\"] ?? `Remove ${file.name}`}\n className={cx(styles.remove, className)}\n data-slot=\"upload-remove\"\n disabled={disabled}\n onClick={(event) => {\n removeFile(file);\n onClick?.(event);\n }}\n ref={ref}\n type=\"button\"\n >\n {children}\n </button>\n );\n});\n\nexport interface UploadStatusProps extends ComponentPropsWithoutRef<\"span\"> {\n file: File;\n}\n\nexport const UploadStatus = forwardRef<HTMLSpanElement, UploadStatusProps>(function UploadStatus(\n { children, className, file, ...props },\n ref,\n) {\n const { fileState, styles } = useUploadContext();\n const state = fileState?.(file);\n const content = children ?? state?.error ?? state?.status ?? \"queued\";\n return (\n <span\n {...props}\n aria-live=\"polite\"\n className={cx(styles.status, className)}\n data-status={state?.status}\n data-slot=\"upload-status\"\n ref={ref}\n >\n {content}\n </span>\n );\n});\n\nexport interface UploadCancelProps extends ComponentPropsWithoutRef<\"button\"> {\n file: File;\n}\n\nexport const UploadCancel = forwardRef<HTMLButtonElement, UploadCancelProps>(function UploadCancel(\n { children = \"Cancel\", className, file, onClick, ...props },\n ref,\n) {\n const { cancelFile, disabled, fileState, styles } = useUploadContext();\n const state = fileState?.(file);\n return (\n <button\n {...props}\n aria-label={props[\"aria-label\"] ?? `Cancel ${file.name}`}\n className={cx(styles.cancel, className)}\n data-slot=\"upload-cancel\"\n disabled={disabled || state?.status === \"canceled\" || state?.status === \"success\"}\n onClick={(event) => {\n cancelFile(file);\n onClick?.(event);\n }}\n ref={ref}\n type=\"button\"\n >\n {children}\n </button>\n );\n});\n\nexport type UploadErrorProps = ComponentPropsWithoutRef<\"p\">;\n\nexport const UploadError = forwardRef<HTMLParagraphElement, UploadErrorProps>(function UploadError(\n { children, className, ...props },\n ref,\n) {\n const { rejections, styles } = useUploadContext();\n if (children === undefined && rejections.length === 0) return null;\n\n return (\n <p\n {...props}\n ref={ref}\n className={cx(styles.error, className)}\n data-slot=\"upload-error\"\n role=\"alert\"\n >\n {children ?? rejections.map((rejection) => rejection.message).join(\" \")}\n </p>\n );\n});\n\nexport const Upload = {\n Root: UploadRoot,\n Dropzone: UploadDropzone,\n Input: UploadInput,\n Trigger: UploadTrigger,\n Icon: UploadIcon,\n Text: UploadText,\n Hint: UploadHint,\n Preview: UploadPreview,\n Progress: UploadProgress,\n List: UploadList,\n Item: UploadItem,\n Remove: UploadRemove,\n Status: UploadStatus,\n Cancel: UploadCancel,\n Error: UploadError,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"upload.js","names":[],"sources":["../../../src/components/upload/upload.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { ChangeEvent, ComponentPropsWithoutRef, ReactNode, RefObject } from \"react\";\n\nimport { cx } from \"../../styled-system/css\";\nimport { upload } from \"../../styled-system/recipes\";\n\nexport type UploadRejectionReason = \"type\" | \"size\" | \"count\" | \"duplicate\" | \"validation\";\n\nexport type UploadFileStatus = \"queued\" | \"uploading\" | \"success\" | \"error\" | \"canceled\";\n\nexport interface UploadFileState {\n status: UploadFileStatus;\n progress?: number;\n error?: ReactNode;\n}\n\nexport interface UploadRejection {\n file: File;\n message: string;\n reason: UploadRejectionReason;\n}\n\ninterface UploadContextValue {\n accept: string | undefined;\n addFiles: (files: FileList | File[]) => void;\n disabled: boolean;\n dropActive: boolean;\n files: File[];\n inputId: string;\n inputRef: RefObject<HTMLInputElement | null>;\n fileState: ((file: File) => UploadFileState | undefined) | undefined;\n maxFiles: number | undefined;\n maxSize: number | undefined;\n multiple: boolean;\n removeFile: (file: File) => void;\n cancelFile: (file: File) => void;\n rejections: UploadRejection[];\n setDropActive: (active: boolean) => void;\n styles: ReturnType<typeof upload>;\n}\n\nconst UploadContext = createContext<UploadContextValue | null>(null);\n\nfunction useUploadContext() {\n const context = useContext(UploadContext);\n if (!context) {\n throw new Error(\"Upload parts must be rendered inside Upload.Root.\");\n }\n\n return context;\n}\n\nfunction fileKey(file: File) {\n return `${file.name}-${file.size}-${file.lastModified}`;\n}\n\nfunction formatBytes(bytes: number) {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction acceptsFile(file: File, accept: string | undefined) {\n if (!accept) {\n return true;\n }\n\n const fileName = file.name.toLowerCase();\n const fileType = file.type.toLowerCase();\n\n return accept.split(\",\").some((entry) => {\n const pattern = entry.trim().toLowerCase();\n if (!pattern) return true;\n if (pattern.startsWith(\".\")) return fileName.endsWith(pattern);\n if (pattern.endsWith(\"/*\")) return fileType.startsWith(pattern.slice(0, -1));\n return pattern === fileType;\n });\n}\n\nexport interface UploadRootProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"onChange\"> {\n /** Accepted MIME types or file extensions, using the native input syntax. */\n accept?: string;\n /** Controlled files. Use with `onFilesChange`. */\n files?: File[];\n /** Initial files for an uncontrolled upload. */\n defaultFiles?: File[];\n /** Called whenever accepted files are added or removed. */\n onFilesChange?: (files: File[]) => void;\n /** Called with files rejected by `accept`, `maxSize`, `maxFiles` or duplicates. */\n onReject?: (rejections: UploadRejection[]) => void;\n /** Maximum number of accepted files. Defaults to one when `multiple` is false. */\n maxFiles?: number;\n /** Maximum size per file, in bytes. */\n maxSize?: number;\n /** Allows selecting more than one file. */\n multiple?: boolean;\n /** Disables file selection and drag-and-drop. */\n disabled?: boolean;\n /** Optional asynchronous validation. Return an error message to reject a file. */\n validateFile?: (file: File) => string | null | Promise<string | null>;\n /** Controlled status used by the status, progress and cancel slots. */\n fileState?: (file: File) => UploadFileState | undefined;\n /** Called when a consumer cancels an upload. */\n onCancel?: (file: File) => void;\n children?: ReactNode;\n}\n\nexport const UploadRoot = forwardRef<HTMLDivElement, UploadRootProps>(function UploadRoot(\n {\n accept,\n fileState,\n children,\n className,\n defaultFiles = [],\n disabled = false,\n files: controlledFiles,\n maxFiles,\n maxSize,\n multiple = false,\n onFilesChange,\n onCancel,\n onReject,\n validateFile,\n ...props\n },\n ref,\n) {\n const [uncontrolledFiles, setUncontrolledFiles] = useState<File[]>(defaultFiles);\n const [dropActive, setDropActive] = useState(false);\n const [rejections, setRejections] = useState<UploadRejection[]>([]);\n const inputRef = useRef<HTMLInputElement>(null);\n const inputId = useId();\n const styles = upload({ disabled, dropActive });\n const currentFiles = controlledFiles ?? uncontrolledFiles;\n const fileLimit = maxFiles ?? (multiple ? undefined : 1);\n\n const updateFiles = useCallback(\n (nextFiles: File[]) => {\n if (controlledFiles === undefined) setUncontrolledFiles(nextFiles);\n onFilesChange?.(nextFiles);\n },\n [controlledFiles, onFilesChange],\n );\n\n const removeFile = useCallback(\n (file: File) => {\n updateFiles(currentFiles.filter((current) => fileKey(current) !== fileKey(file)));\n },\n [currentFiles, updateFiles],\n );\n\n const addFiles = useCallback(\n (fileList: FileList | File[]) => {\n if (disabled) return;\n\n const candidates = Array.from(fileList);\n const acceptedFiles: File[] = [];\n const nextRejections: UploadRejection[] = [];\n const pendingValidations = new Map<File, Promise<string | null>>();\n const existingKeys = new Set(currentFiles.map(fileKey));\n\n for (const file of candidates) {\n const key = fileKey(file);\n if (existingKeys.has(key) || acceptedFiles.some((accepted) => fileKey(accepted) === key)) {\n nextRejections.push({\n file,\n reason: \"duplicate\",\n message: `${file.name} was already added.`,\n });\n continue;\n }\n if (!acceptsFile(file, accept)) {\n nextRejections.push({\n file,\n reason: \"type\",\n message: `${file.name} is not an accepted file type.`,\n });\n continue;\n }\n if (maxSize !== undefined && file.size > maxSize) {\n nextRejections.push({\n file,\n reason: \"size\",\n message: `${file.name} is larger than the allowed limit.`,\n });\n continue;\n }\n if (\n fileLimit !== undefined &&\n (multiple ? currentFiles.length + acceptedFiles.length : acceptedFiles.length) >=\n fileLimit\n ) {\n nextRejections.push({\n file,\n reason: \"count\",\n message: `Only ${fileLimit} file${fileLimit === 1 ? \"\" : \"s\"} can be selected.`,\n });\n continue;\n }\n if (validateFile) {\n const validation = validateFile(file);\n if (validation && typeof validation !== \"object\") {\n nextRejections.push({ file, reason: \"validation\", message: validation });\n continue;\n }\n if (validation && typeof validation === \"object\" && \"then\" in validation) {\n pendingValidations.set(file, Promise.resolve(validation));\n }\n }\n acceptedFiles.push(file);\n }\n\n const nextFiles = multiple ? [...currentFiles, ...acceptedFiles] : acceptedFiles.slice(0, 1);\n if (acceptedFiles.length > 0) {\n updateFiles(nextFiles);\n }\n if (validateFile) {\n for (const file of acceptedFiles) {\n const validation = pendingValidations.get(file);\n if (validation) {\n void validation\n .then((message) => {\n if (!message) return;\n const rejection = { file, reason: \"validation\" as const, message };\n updateFiles(nextFiles.filter((current) => fileKey(current) !== fileKey(file)));\n setRejections((current) => [...current, rejection]);\n onReject?.([rejection]);\n })\n .catch((error: unknown) => {\n const message = error instanceof Error ? error.message : \"File validation failed.\";\n const rejection = { file, reason: \"validation\" as const, message };\n updateFiles(nextFiles.filter((current) => fileKey(current) !== fileKey(file)));\n setRejections((current) => [...current, rejection]);\n onReject?.([rejection]);\n });\n }\n }\n }\n if (nextRejections.length > 0) {\n setRejections(nextRejections);\n onReject?.(nextRejections);\n } else {\n setRejections([]);\n }\n },\n [\n accept,\n currentFiles,\n disabled,\n fileLimit,\n maxSize,\n multiple,\n onReject,\n updateFiles,\n validateFile,\n ],\n );\n\n const cancelFile = useCallback((file: File) => onCancel?.(file), [onCancel]);\n\n const context = useMemo<UploadContextValue>(\n () => ({\n accept,\n addFiles,\n cancelFile,\n disabled,\n dropActive,\n files: currentFiles,\n inputId,\n inputRef,\n fileState,\n maxFiles: fileLimit,\n maxSize,\n multiple,\n removeFile,\n rejections,\n setDropActive,\n styles,\n }),\n [\n accept,\n addFiles,\n cancelFile,\n currentFiles,\n disabled,\n dropActive,\n fileLimit,\n fileState,\n inputId,\n maxSize,\n multiple,\n rejections,\n removeFile,\n styles,\n ],\n );\n\n return (\n <UploadContext.Provider value={context}>\n <div\n {...props}\n ref={ref}\n className={cx(styles.root, className)}\n data-disabled={disabled || undefined}\n data-jaci-component=\"upload\"\n data-slot=\"upload\"\n >\n {children}\n </div>\n </UploadContext.Provider>\n );\n});\n\nexport interface UploadDropzoneProps extends ComponentPropsWithoutRef<\"label\"> {\n children?: ReactNode;\n}\n\nexport const UploadDropzone = forwardRef<HTMLLabelElement, UploadDropzoneProps>(\n function UploadDropzone(\n { children, className, htmlFor, onDragEnter, onDragLeave, onDragOver, onDrop, ...props },\n ref,\n ) {\n const { addFiles, disabled, dropActive, inputId, setDropActive, styles } = useUploadContext();\n\n return (\n <label\n {...props}\n ref={ref}\n aria-disabled={disabled || undefined}\n className={cx(styles.dropzone, className)}\n data-drag-active={dropActive || undefined}\n data-slot=\"upload-dropzone\"\n htmlFor={htmlFor ?? inputId}\n onDragEnter={(event) => {\n event.preventDefault();\n if (!disabled) {\n setDropActive(true);\n event.currentTarget.dataset.dragActive = \"true\";\n }\n onDragEnter?.(event);\n }}\n onDragLeave={(event) => {\n event.preventDefault();\n if (event.currentTarget === event.target) {\n setDropActive(false);\n event.currentTarget.dataset.dragActive = \"false\";\n }\n onDragLeave?.(event);\n }}\n onDragOver={(event) => {\n event.preventDefault();\n if (!disabled) setDropActive(true);\n onDragOver?.(event);\n }}\n onDrop={(event) => {\n event.preventDefault();\n setDropActive(false);\n event.currentTarget.dataset.dragActive = \"false\";\n if (!disabled) addFiles(event.dataTransfer.files);\n onDrop?.(event);\n }}\n >\n {children}\n </label>\n );\n },\n);\n\nexport type UploadInputProps = ComponentPropsWithoutRef<\"input\">;\n\nexport const UploadInput = forwardRef<HTMLInputElement, UploadInputProps>(function UploadInput(\n { accept, className, id, multiple, onChange, ...props },\n ref,\n) {\n const {\n addFiles,\n accept: rootAccept,\n disabled,\n inputId,\n inputRef,\n multiple: rootMultiple,\n styles,\n } = useUploadContext();\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (event.currentTarget.files) addFiles(event.currentTarget.files);\n event.currentTarget.value = \"\";\n onChange?.(event);\n };\n\n return (\n <input\n {...props}\n accept={accept ?? rootAccept}\n aria-label={props[\"aria-label\"] ?? \"Select files\"}\n className={cx(styles.input, className)}\n disabled={disabled}\n id={id ?? inputId}\n multiple={multiple ?? rootMultiple}\n onChange={handleChange}\n ref={(node) => {\n inputRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n }}\n tabIndex={-1}\n type=\"file\"\n />\n );\n});\n\nexport type UploadTriggerProps = ComponentPropsWithoutRef<\"button\">;\n\nexport const UploadTrigger = forwardRef<HTMLButtonElement, UploadTriggerProps>(\n function UploadTrigger(\n { children = \"Choose files\", className, disabled, onClick, ...props },\n ref,\n ) {\n const { disabled: rootDisabled, inputRef, styles } = useUploadContext();\n\n return (\n <button\n {...props}\n className={cx(styles.trigger, className)}\n data-slot=\"upload-trigger\"\n disabled={disabled ?? rootDisabled}\n onClick={(event) => {\n inputRef.current?.click();\n onClick?.(event);\n }}\n ref={ref}\n type=\"button\"\n >\n {children}\n </button>\n );\n },\n);\n\nexport type UploadIconProps = ComponentPropsWithoutRef<\"span\">;\n\nexport const UploadIcon = forwardRef<HTMLSpanElement, UploadIconProps>(function UploadIcon(\n { children = \"↥\", className, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n return (\n <span\n {...props}\n ref={ref}\n aria-hidden=\"true\"\n className={cx(styles.icon, className)}\n data-slot=\"upload-icon\"\n >\n {children}\n </span>\n );\n});\n\nexport type UploadTextProps = ComponentPropsWithoutRef<\"span\">;\n\nexport const UploadText = forwardRef<HTMLSpanElement, UploadTextProps>(function UploadText(\n { className, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n return (\n <span {...props} ref={ref} className={cx(styles.text, className)} data-slot=\"upload-text\" />\n );\n});\n\nexport type UploadHintProps = ComponentPropsWithoutRef<\"span\">;\n\nexport const UploadHint = forwardRef<HTMLSpanElement, UploadHintProps>(function UploadHint(\n { className, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n return (\n <span {...props} ref={ref} className={cx(styles.hint, className)} data-slot=\"upload-hint\" />\n );\n});\n\nexport interface UploadPreviewProps extends ComponentPropsWithoutRef<\"span\"> {\n /** File whose preview should be rendered. Image files use a temporary object URL. */\n file: File;\n /** Alternative text for image previews. Defaults to the file name. */\n alt?: string;\n /** Content rendered while the preview is unavailable or the file is not an image. */\n fallback?: ReactNode;\n}\n\nexport const UploadPreview = forwardRef<HTMLSpanElement, UploadPreviewProps>(function UploadPreview(\n { alt, className, fallback = \"Preview unavailable\", file, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n const [src, setSrc] = useState<string | null>(null);\n\n useEffect(() => {\n if (\n !file.type.startsWith(\"image/\") ||\n typeof URL === \"undefined\" ||\n typeof URL.createObjectURL !== \"function\"\n ) {\n setSrc(null);\n return;\n }\n\n const objectUrl = URL.createObjectURL(file);\n setSrc(objectUrl);\n return () => URL.revokeObjectURL(objectUrl);\n }, [file]);\n\n return (\n <span\n {...props}\n ref={ref}\n aria-hidden={props[\"aria-label\"] ? undefined : true}\n className={cx(styles.preview, className)}\n data-slot=\"upload-preview\"\n role={props[\"aria-label\"] ? \"img\" : undefined}\n >\n {src ? <img alt={alt ?? file.name} src={src} /> : fallback}\n </span>\n );\n});\n\nexport interface UploadProgressProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n /** Progress from 0 to 100. Omit it for an indeterminate upload. */\n value?: number;\n /** Accessible label and optional visible status text. */\n label?: ReactNode;\n file?: File;\n}\n\nexport const UploadProgress = forwardRef<HTMLDivElement, UploadProgressProps>(\n function UploadProgress({ className, file, label = \"Uploading\", value, ...props }, ref) {\n const { fileState, styles } = useUploadContext();\n const state = file ? fileState?.(file) : undefined;\n const normalizedValue =\n value === undefined\n ? state?.progress === undefined\n ? undefined\n : Math.min(100, Math.max(0, state.progress))\n : Math.min(100, Math.max(0, value));\n\n return (\n <div\n {...props}\n ref={ref}\n aria-label={typeof label === \"string\" ? label : \"Upload progress\"}\n aria-valuemax={100}\n aria-valuemin={0}\n aria-valuenow={normalizedValue}\n className={cx(styles.progress, className)}\n data-indeterminate={normalizedValue === undefined || undefined}\n data-slot=\"upload-progress\"\n role=\"progressbar\"\n >\n <span className={styles.progressTrack} data-slot=\"upload-progress-track\">\n <span\n className={styles.progressIndicator}\n data-indeterminate={normalizedValue === undefined || undefined}\n data-slot=\"upload-progress-indicator\"\n style={{ width: normalizedValue === undefined ? undefined : `${normalizedValue}%` }}\n />\n </span>\n <span className={styles.progressLabel} data-slot=\"upload-progress-label\">\n {label}\n </span>\n </div>\n );\n },\n);\n\nexport type UploadListProps = ComponentPropsWithoutRef<\"ul\">;\n\nexport const UploadList = forwardRef<HTMLUListElement, UploadListProps>(function UploadList(\n { children, className, ...props },\n ref,\n) {\n const { files, styles } = useUploadContext();\n return (\n <ul {...props} ref={ref} className={cx(styles.list, className)} data-slot=\"upload-list\">\n {children ?? files.map((file) => <UploadItem file={file} key={fileKey(file)} />)}\n </ul>\n );\n});\n\nexport interface UploadItemProps extends Omit<ComponentPropsWithoutRef<\"li\">, \"children\"> {\n file: File;\n children?: ReactNode;\n}\n\nexport const UploadItem = forwardRef<HTMLLIElement, UploadItemProps>(function UploadItem(\n { children, className, file, ...props },\n ref,\n) {\n const { styles } = useUploadContext();\n return (\n <li {...props} ref={ref} className={cx(styles.item, className)} data-slot=\"upload-item\">\n {children ?? (\n <>\n <span className={styles.itemName} data-slot=\"upload-item-name\" title={file.name}>\n {file.name}\n </span>\n <span className={styles.itemMeta} data-slot=\"upload-item-meta\">\n {formatBytes(file.size)}\n </span>\n <UploadRemove file={file} />\n </>\n )}\n </li>\n );\n});\n\nexport interface UploadRemoveProps extends ComponentPropsWithoutRef<\"button\"> {\n file: File;\n}\n\nexport const UploadRemove = forwardRef<HTMLButtonElement, UploadRemoveProps>(function UploadRemove(\n { children = \"×\", className, file, onClick, ...props },\n ref,\n) {\n const { disabled, removeFile, styles } = useUploadContext();\n return (\n <button\n {...props}\n aria-label={props[\"aria-label\"] ?? `Remove ${file.name}`}\n className={cx(styles.remove, className)}\n data-slot=\"upload-remove\"\n disabled={disabled}\n onClick={(event) => {\n removeFile(file);\n onClick?.(event);\n }}\n ref={ref}\n type=\"button\"\n >\n {children}\n </button>\n );\n});\n\nexport interface UploadStatusProps extends ComponentPropsWithoutRef<\"span\"> {\n file: File;\n}\n\nexport const UploadStatus = forwardRef<HTMLSpanElement, UploadStatusProps>(function UploadStatus(\n { children, className, file, ...props },\n ref,\n) {\n const { fileState, styles } = useUploadContext();\n const state = fileState?.(file);\n const content = children ?? state?.error ?? state?.status ?? \"queued\";\n return (\n <span\n {...props}\n aria-live=\"polite\"\n className={cx(styles.status, className)}\n data-status={state?.status}\n data-slot=\"upload-status\"\n ref={ref}\n >\n {content}\n </span>\n );\n});\n\nexport interface UploadCancelProps extends ComponentPropsWithoutRef<\"button\"> {\n file: File;\n}\n\nexport const UploadCancel = forwardRef<HTMLButtonElement, UploadCancelProps>(function UploadCancel(\n { children = \"Cancel\", className, file, onClick, ...props },\n ref,\n) {\n const { cancelFile, disabled, fileState, styles } = useUploadContext();\n const state = fileState?.(file);\n return (\n <button\n {...props}\n aria-label={props[\"aria-label\"] ?? `Cancel ${file.name}`}\n className={cx(styles.cancel, className)}\n data-slot=\"upload-cancel\"\n disabled={disabled || state?.status === \"canceled\" || state?.status === \"success\"}\n onClick={(event) => {\n cancelFile(file);\n onClick?.(event);\n }}\n ref={ref}\n type=\"button\"\n >\n {children}\n </button>\n );\n});\n\nexport type UploadErrorProps = ComponentPropsWithoutRef<\"p\">;\n\nexport const UploadError = forwardRef<HTMLParagraphElement, UploadErrorProps>(function UploadError(\n { children, className, ...props },\n ref,\n) {\n const { rejections, styles } = useUploadContext();\n if (children === undefined && rejections.length === 0) return null;\n\n return (\n <p\n {...props}\n ref={ref}\n className={cx(styles.error, className)}\n data-slot=\"upload-error\"\n role=\"alert\"\n >\n {children ?? rejections.map((rejection) => rejection.message).join(\" \")}\n </p>\n );\n});\n\nexport const Upload = {\n Root: UploadRoot,\n Dropzone: UploadDropzone,\n Input: UploadInput,\n Trigger: UploadTrigger,\n Icon: UploadIcon,\n Text: UploadText,\n Hint: UploadHint,\n Preview: UploadPreview,\n Progress: UploadProgress,\n List: UploadList,\n Item: UploadItem,\n Remove: UploadRemove,\n Status: UploadStatus,\n Cancel: UploadCancel,\n Error: UploadError,\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visually-hidden.cjs","names":["cx","screenReaderOnly"],"sources":["../../../src/components/visually-hidden/visually-hidden.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\n\nimport { cx } from \"../../styled-system/css\";\nimport { screenReaderOnly } from \"../../styled-system/recipes\";\n\nexport type VisuallyHiddenProps = ComponentPropsWithoutRef<\"span\">;\n\nexport const VisuallyHidden = forwardRef<HTMLSpanElement, VisuallyHiddenProps>(\n function VisuallyHidden({ className, ...props }, ref) {\n return (\n <span\n {...props}\n ref={ref}\n className={cx(screenReaderOnly(), className)}\n data-jaci-component=\"visually-hidden\"\n data-slot=\"visually-hidden\"\n />\n );\n },\n);\n"],"mappings":";;;;;AAQA,MAAa,kBAAA,
|
|
1
|
+
{"version":3,"file":"visually-hidden.cjs","names":["forwardRef","cx","screenReaderOnly"],"sources":["../../../src/components/visually-hidden/visually-hidden.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\n\nimport { cx } from \"../../styled-system/css\";\nimport { screenReaderOnly } from \"../../styled-system/recipes\";\n\nexport type VisuallyHiddenProps = ComponentPropsWithoutRef<\"span\">;\n\nexport const VisuallyHidden = forwardRef<HTMLSpanElement, VisuallyHiddenProps>(\n function VisuallyHidden({ className, ...props }, ref) {\n return (\n <span\n {...props}\n ref={ref}\n className={cx(screenReaderOnly(), className)}\n data-jaci-component=\"visually-hidden\"\n data-slot=\"visually-hidden\"\n />\n );\n },\n);\n"],"mappings":";;;;;AAQA,MAAa,kBAAA,GAAiBA,MAAAA,WAAAA,CAC5B,SAAS,eAAe,EAAE,WAAW,GAAG,SAAS,KAAK;CACpD,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;EACE,GAAI;EACC;EACL,WAAWC,WAAAA,GAAGC,2BAAAA,iBAAiB,GAAG,SAAS;EAC3C,uBAAoB;EACpB,aAAU;CACX,CAAA;AAEL,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"panda-preset.cjs","names":["jaciConditions","jaciTheme"],"sources":["../src/panda-preset.ts"],"sourcesContent":["import { definePreset } from \"@pandacss/dev\";\n\nimport { jaciConditions, jaciTheme } from \"./styles/theme\";\n\nconst jaciPreset = definePreset({\n name: \"jaci-ui\",\n conditions: jaciConditions,\n theme: jaciTheme,\n});\n\nexport default jaciPreset;\n"],"mappings":";;AAIA,MAAM,cAAA,
|
|
1
|
+
{"version":3,"file":"panda-preset.cjs","names":["definePreset","jaciConditions","jaciTheme"],"sources":["../src/panda-preset.ts"],"sourcesContent":["import { definePreset } from \"@pandacss/dev\";\n\nimport { jaciConditions, jaciTheme } from \"./styles/theme\";\n\nconst jaciPreset = definePreset({\n name: \"jaci-ui\",\n conditions: jaciConditions,\n theme: jaciTheme,\n});\n\nexport default jaciPreset;\n"],"mappings":";;AAIA,MAAM,cAAA,0BAAaA,CAAAA,CAAAA,aAAAA,CAAa;CAC9B,MAAM;CACN,YAAYC,cAAAA;CACZ,OAAOC,cAAAA;AACT,CAAC"}
|
package/dist/styles.css
CHANGED
|
@@ -525,27 +525,6 @@
|
|
|
525
525
|
--jaci-colors-link-hover: var(--jaci-colors-neutral-900);
|
|
526
526
|
}
|
|
527
527
|
|
|
528
|
-
[data-jaci-theme="dark"] {
|
|
529
|
-
--jaci-colors-surface-canvas: var(--jaci-colors-neutral-950);
|
|
530
|
-
--jaci-colors-surface-default: var(--jaci-colors-neutral-900);
|
|
531
|
-
--jaci-colors-surface-raised: var(--jaci-colors-neutral-800);
|
|
532
|
-
--jaci-colors-surface-subtle: var(--jaci-colors-neutral-800);
|
|
533
|
-
--jaci-colors-surface-overlay: rgb(9 9 11 / 0.4);
|
|
534
|
-
--jaci-colors-fg-default: var(--jaci-colors-neutral-100);
|
|
535
|
-
--jaci-colors-fg-muted: var(--jaci-colors-neutral-400);
|
|
536
|
-
--jaci-colors-border-default: var(--jaci-colors-neutral-700);
|
|
537
|
-
--jaci-colors-border-strong: var(--jaci-colors-neutral-500);
|
|
538
|
-
--jaci-colors-border-interactive: var(--jaci-colors-neutral-200);
|
|
539
|
-
--jaci-colors-disabled: var(--jaci-colors-neutral-600);
|
|
540
|
-
--jaci-colors-selected: var(--jaci-colors-blue-950);
|
|
541
|
-
--jaci-colors-link-default: var(--jaci-colors-neutral-400);
|
|
542
|
-
--jaci-colors-link-hover: var(--jaci-colors-neutral-200);
|
|
543
|
-
--jaci-shadows-sm: 0 1px 2px rgb(255 255 255 / 0.08);
|
|
544
|
-
--jaci-shadows-md: 0 10px 24px rgb(255 255 255 / 0.1);
|
|
545
|
-
--jaci-shadows-lg: 0 18px 42px rgb(255 255 255 / 0.12);
|
|
546
|
-
--jaci-shadows-xl: 0 24px 52px rgb(255 255 255 / 0.14)
|
|
547
|
-
}
|
|
548
|
-
|
|
549
528
|
@keyframes ping {
|
|
550
529
|
75%,100% {
|
|
551
530
|
transform: scale(2);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-provider.cjs","names":["ThemeScopeContext"],"sources":["../../src/theme/theme-provider.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n createElement,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\nimport type { ComponentPropsWithoutRef, CSSProperties, ElementType, ReactNode, Ref } from \"react\";\n\nimport { ThemeScopeContext } from \"./theme-scope\";\n\nexport type ThemeMode = \"light\" | \"dark\" | \"system\";\n\n/** A leaf value accepted by the theme variable mapper. */\nexport type JaciThemeTokenValue = string | number;\n\n/**\n * Semantic theme values. The groups intentionally accept additional keys so\n * applications can extend the token vocabulary without waiting for a package\n * release. Known semantic groups are documented in the public README.\n */\nexport type JaciThemeTokenGroup = {\n readonly [key: string]: JaciThemeTokenValue | JaciThemeTokenGroup | undefined;\n};\n\nexport interface JaciThemeColorTokens extends JaciThemeTokenGroup {\n surface?: JaciThemeTokenGroup;\n fg?: JaciThemeTokenGroup;\n border?: JaciThemeTokenGroup;\n accent?: JaciThemeTokenGroup;\n success?: JaciThemeTokenValue;\n warning?: JaciThemeTokenValue;\n danger?: JaciThemeTokenValue;\n info?: JaciThemeTokenValue;\n link?: JaciThemeTokenGroup;\n focus?: JaciThemeTokenValue;\n disabled?: JaciThemeTokenValue;\n selected?: JaciThemeTokenValue;\n}\n\nexport interface JaciThemeTokens {\n colors?: JaciThemeColorTokens;\n radii?: JaciThemeTokenGroup;\n shadows?: JaciThemeTokenGroup;\n durations?: JaciThemeTokenGroup;\n easings?: JaciThemeTokenGroup;\n transitions?: JaciThemeTokenGroup;\n spacing?: JaciThemeTokenGroup;\n fontSizes?: JaciThemeTokenGroup;\n lineHeights?: JaciThemeTokenGroup;\n typography?: JaciThemeTokenGroup;\n textStyles?: JaciThemeTokenGroup;\n fonts?: JaciThemeTokenGroup;\n}\n\nexport interface ThemeProviderProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n /** The controlled color mode. */\n theme?: ThemeMode;\n /** The initial color mode for an uncontrolled provider. */\n defaultTheme?: ThemeMode;\n /** The deterministic mode used for `system` while rendering on the server. */\n ssrTheme?: \"light\" | \"dark\";\n /** Scoped semantic token overrides. */\n tokens?: JaciThemeTokens;\n /** Called when a controlled provider requests a mode change. */\n onThemeChange?: (theme: ThemeMode) => void;\n /** The element that owns the theme scope. */\n as?: ElementType;\n children?: ReactNode;\n}\n\nexport interface ThemeContextValue {\n theme: ThemeMode;\n resolvedTheme: \"light\" | \"dark\";\n setTheme: (theme: ThemeMode) => void;\n}\n\nconst defaultThemeContext: ThemeContextValue = {\n theme: \"light\",\n resolvedTheme: \"light\",\n setTheme: () => undefined,\n};\n\nconst ThemeContext = createContext<ThemeContextValue>(defaultThemeContext);\n\nfunction kebabCase(value: string) {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1-$2\")\n .replace(/[\\s_]+/g, \"-\")\n .toLowerCase();\n}\n\nfunction flattenTokens(\n group: JaciThemeTokenGroup | undefined,\n path: string[],\n output: Record<string, string>,\n) {\n if (!group) return;\n\n for (const [key, value] of Object.entries(group)) {\n if (value === undefined) continue;\n const nextPath = [...path, kebabCase(key)];\n\n if (typeof value === \"object\") {\n flattenTokens(value, nextPath, output);\n } else {\n output[`--jaci-${nextPath.join(\"-\")}`] = String(value);\n }\n }\n}\n\nfunction tokenStyles(tokens: JaciThemeTokens | undefined): CSSProperties {\n if (!tokens) return {};\n\n const variables: Record<string, string> = {};\n for (const [group, values] of Object.entries(tokens)) {\n flattenTokens(values, [kebabCase(group)], variables);\n }\n\n return variables as CSSProperties;\n}\n\nfunction initialSystemTheme(ssrTheme: \"light\" | \"dark\" | undefined) {\n return ssrTheme ?? \"light\";\n}\n\nexport const ThemeProvider = forwardRef<HTMLElement, ThemeProviderProps>(function ThemeProvider(\n {\n as = \"div\",\n children,\n defaultTheme = \"light\",\n onThemeChange,\n ssrTheme,\n style,\n theme,\n tokens,\n ...props\n },\n ref,\n) {\n const [uncontrolledTheme, setUncontrolledTheme] = useState<ThemeMode>(defaultTheme);\n const [systemTheme, setSystemTheme] = useState<\"light\" | \"dark\">(() =>\n initialSystemTheme(ssrTheme),\n );\n const [scopeElement, setScopeElement] = useState<HTMLElement | null>(null);\n const [portalContainer, setPortalContainer] = useState<HTMLElement | null>(null);\n const currentTheme = theme ?? uncontrolledTheme;\n\n useEffect(() => {\n if (currentTheme !== \"system\") return;\n\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") return;\n\n const media = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const update = () => setSystemTheme(media.matches ? \"dark\" : \"light\");\n update();\n if (typeof media.addEventListener === \"function\") media.addEventListener(\"change\", update);\n else media.addListener?.(update);\n\n return () => {\n if (typeof media.removeEventListener === \"function\")\n media.removeEventListener(\"change\", update);\n else media.removeListener?.(update);\n };\n }, [currentTheme]);\n\n const resolvedTheme = currentTheme === \"system\" ? systemTheme : currentTheme;\n const setTheme = useCallback(\n (nextTheme: ThemeMode) => {\n if (theme === undefined) setUncontrolledTheme(nextTheme);\n onThemeChange?.(nextTheme);\n },\n [onThemeChange, theme],\n );\n const contextValue = useMemo(\n () => ({ theme: currentTheme, resolvedTheme, setTheme }),\n [currentTheme, resolvedTheme, setTheme],\n );\n const mergedStyle = useMemo(() => ({ ...style, ...tokenStyles(tokens) }), [style, tokens]);\n const scopedTokenStyles = useMemo(() => tokenStyles(tokens), [tokens]);\n const Root = as;\n const setRootRef = useCallback(\n (element: HTMLElement | null) => {\n setScopeElement((current) => (current === element ? current : element));\n if (typeof ref === \"function\") ref(element);\n else if (ref) (ref as { current: HTMLElement | null }).current = element;\n },\n [ref],\n );\n\n useEffect(() => {\n if (!scopeElement || typeof document === \"undefined\") return;\n\n const host = document.createElement(\"div\");\n host.dataset.jaciThemePortal = \"true\";\n host.dataset.jaciComponent = \"theme-portal\";\n host.dataset.slot = \"theme-portal\";\n // Keep the host out of the Storybook/app layout. Its descendants still\n // inherit the theme attribute and scoped custom properties.\n host.style.display = \"contents\";\n document.body.append(host);\n setPortalContainer(host);\n\n return () => {\n setPortalContainer((current) => (current === host ? null : current));\n host.remove();\n };\n }, [scopeElement]);\n\n useEffect(() => {\n if (!portalContainer) return;\n\n portalContainer.dataset.jaciTheme = resolvedTheme;\n for (const [property, value] of Object.entries(scopedTokenStyles)) {\n portalContainer.style.setProperty(property, value);\n }\n\n return () => {\n for (const property of Object.keys(scopedTokenStyles)) {\n portalContainer.style.removeProperty(property);\n }\n };\n }, [portalContainer, resolvedTheme, scopedTokenStyles]);\n\n return (\n <ThemeContext.Provider value={contextValue}>\n <ThemeScopeContext.Provider value={{ container: portalContainer }}>\n {createElement(\n Root,\n {\n ...props,\n \"data-jaci-theme\": resolvedTheme,\n \"data-jaci-component\": \"theme-provider\",\n \"data-slot\": \"theme-provider\",\n ref: setRootRef as Ref<HTMLElement>,\n style: mergedStyle,\n },\n children,\n )}\n </ThemeScopeContext.Provider>\n </ThemeContext.Provider>\n );\n});\n\nexport function useTheme() {\n return useContext(ThemeContext);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"theme-provider.cjs","names":["createContext","forwardRef","useState","useCallback","useMemo","ThemeScopeContext","createElement","useContext"],"sources":["../../src/theme/theme-provider.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n createElement,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\nimport type { ComponentPropsWithoutRef, CSSProperties, ElementType, ReactNode, Ref } from \"react\";\n\nimport { ThemeScopeContext } from \"./theme-scope\";\n\nexport type ThemeMode = \"light\" | \"dark\" | \"system\";\n\n/** A leaf value accepted by the theme variable mapper. */\nexport type JaciThemeTokenValue = string | number;\n\n/**\n * Semantic theme values. The groups intentionally accept additional keys so\n * applications can extend the token vocabulary without waiting for a package\n * release. Known semantic groups are documented in the public README.\n */\nexport type JaciThemeTokenGroup = {\n readonly [key: string]: JaciThemeTokenValue | JaciThemeTokenGroup | undefined;\n};\n\nexport interface JaciThemeColorTokens extends JaciThemeTokenGroup {\n surface?: JaciThemeTokenGroup;\n fg?: JaciThemeTokenGroup;\n border?: JaciThemeTokenGroup;\n accent?: JaciThemeTokenGroup;\n success?: JaciThemeTokenValue;\n warning?: JaciThemeTokenValue;\n danger?: JaciThemeTokenValue;\n info?: JaciThemeTokenValue;\n link?: JaciThemeTokenGroup;\n focus?: JaciThemeTokenValue;\n disabled?: JaciThemeTokenValue;\n selected?: JaciThemeTokenValue;\n}\n\nexport interface JaciThemeTokens {\n colors?: JaciThemeColorTokens;\n radii?: JaciThemeTokenGroup;\n shadows?: JaciThemeTokenGroup;\n durations?: JaciThemeTokenGroup;\n easings?: JaciThemeTokenGroup;\n transitions?: JaciThemeTokenGroup;\n spacing?: JaciThemeTokenGroup;\n fontSizes?: JaciThemeTokenGroup;\n lineHeights?: JaciThemeTokenGroup;\n typography?: JaciThemeTokenGroup;\n textStyles?: JaciThemeTokenGroup;\n fonts?: JaciThemeTokenGroup;\n}\n\nexport interface ThemeProviderProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n /** The controlled color mode. */\n theme?: ThemeMode;\n /** The initial color mode for an uncontrolled provider. */\n defaultTheme?: ThemeMode;\n /** The deterministic mode used for `system` while rendering on the server. */\n ssrTheme?: \"light\" | \"dark\";\n /** Scoped semantic token overrides. */\n tokens?: JaciThemeTokens;\n /** Called when a controlled provider requests a mode change. */\n onThemeChange?: (theme: ThemeMode) => void;\n /** The element that owns the theme scope. */\n as?: ElementType;\n children?: ReactNode;\n}\n\nexport interface ThemeContextValue {\n theme: ThemeMode;\n resolvedTheme: \"light\" | \"dark\";\n setTheme: (theme: ThemeMode) => void;\n}\n\nconst defaultThemeContext: ThemeContextValue = {\n theme: \"light\",\n resolvedTheme: \"light\",\n setTheme: () => undefined,\n};\n\nconst ThemeContext = createContext<ThemeContextValue>(defaultThemeContext);\n\nfunction kebabCase(value: string) {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1-$2\")\n .replace(/[\\s_]+/g, \"-\")\n .toLowerCase();\n}\n\nfunction flattenTokens(\n group: JaciThemeTokenGroup | undefined,\n path: string[],\n output: Record<string, string>,\n) {\n if (!group) return;\n\n for (const [key, value] of Object.entries(group)) {\n if (value === undefined) continue;\n const nextPath = [...path, kebabCase(key)];\n\n if (typeof value === \"object\") {\n flattenTokens(value, nextPath, output);\n } else {\n output[`--jaci-${nextPath.join(\"-\")}`] = String(value);\n }\n }\n}\n\nfunction tokenStyles(tokens: JaciThemeTokens | undefined): CSSProperties {\n if (!tokens) return {};\n\n const variables: Record<string, string> = {};\n for (const [group, values] of Object.entries(tokens)) {\n flattenTokens(values, [kebabCase(group)], variables);\n }\n\n return variables as CSSProperties;\n}\n\nfunction initialSystemTheme(ssrTheme: \"light\" | \"dark\" | undefined) {\n return ssrTheme ?? \"light\";\n}\n\nexport const ThemeProvider = forwardRef<HTMLElement, ThemeProviderProps>(function ThemeProvider(\n {\n as = \"div\",\n children,\n defaultTheme = \"light\",\n onThemeChange,\n ssrTheme,\n style,\n theme,\n tokens,\n ...props\n },\n ref,\n) {\n const [uncontrolledTheme, setUncontrolledTheme] = useState<ThemeMode>(defaultTheme);\n const [systemTheme, setSystemTheme] = useState<\"light\" | \"dark\">(() =>\n initialSystemTheme(ssrTheme),\n );\n const [scopeElement, setScopeElement] = useState<HTMLElement | null>(null);\n const [portalContainer, setPortalContainer] = useState<HTMLElement | null>(null);\n const currentTheme = theme ?? uncontrolledTheme;\n\n useEffect(() => {\n if (currentTheme !== \"system\") return;\n\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") return;\n\n const media = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const update = () => setSystemTheme(media.matches ? \"dark\" : \"light\");\n update();\n if (typeof media.addEventListener === \"function\") media.addEventListener(\"change\", update);\n else media.addListener?.(update);\n\n return () => {\n if (typeof media.removeEventListener === \"function\")\n media.removeEventListener(\"change\", update);\n else media.removeListener?.(update);\n };\n }, [currentTheme]);\n\n const resolvedTheme = currentTheme === \"system\" ? systemTheme : currentTheme;\n const setTheme = useCallback(\n (nextTheme: ThemeMode) => {\n if (theme === undefined) setUncontrolledTheme(nextTheme);\n onThemeChange?.(nextTheme);\n },\n [onThemeChange, theme],\n );\n const contextValue = useMemo(\n () => ({ theme: currentTheme, resolvedTheme, setTheme }),\n [currentTheme, resolvedTheme, setTheme],\n );\n const mergedStyle = useMemo(() => ({ ...style, ...tokenStyles(tokens) }), [style, tokens]);\n const scopedTokenStyles = useMemo(() => tokenStyles(tokens), [tokens]);\n const Root = as;\n const setRootRef = useCallback(\n (element: HTMLElement | null) => {\n setScopeElement((current) => (current === element ? current : element));\n if (typeof ref === \"function\") ref(element);\n else if (ref) (ref as { current: HTMLElement | null }).current = element;\n },\n [ref],\n );\n\n useEffect(() => {\n if (!scopeElement || typeof document === \"undefined\") return;\n\n const host = document.createElement(\"div\");\n host.dataset.jaciThemePortal = \"true\";\n host.dataset.jaciComponent = \"theme-portal\";\n host.dataset.slot = \"theme-portal\";\n // Keep the host out of the Storybook/app layout. Its descendants still\n // inherit the theme attribute and scoped custom properties.\n host.style.display = \"contents\";\n document.body.append(host);\n setPortalContainer(host);\n\n return () => {\n setPortalContainer((current) => (current === host ? null : current));\n host.remove();\n };\n }, [scopeElement]);\n\n useEffect(() => {\n if (!portalContainer) return;\n\n portalContainer.dataset.jaciTheme = resolvedTheme;\n for (const [property, value] of Object.entries(scopedTokenStyles)) {\n portalContainer.style.setProperty(property, value);\n }\n\n return () => {\n for (const property of Object.keys(scopedTokenStyles)) {\n portalContainer.style.removeProperty(property);\n }\n };\n }, [portalContainer, resolvedTheme, scopedTokenStyles]);\n\n return (\n <ThemeContext.Provider value={contextValue}>\n <ThemeScopeContext.Provider value={{ container: portalContainer }}>\n {createElement(\n Root,\n {\n ...props,\n \"data-jaci-theme\": resolvedTheme,\n \"data-jaci-component\": \"theme-provider\",\n \"data-slot\": \"theme-provider\",\n ref: setRootRef as Ref<HTMLElement>,\n style: mergedStyle,\n },\n children,\n )}\n </ThemeScopeContext.Provider>\n </ThemeContext.Provider>\n );\n});\n\nexport function useTheme() {\n return useContext(ThemeContext);\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-provider.js","names":[],"sources":["../../src/theme/theme-provider.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n createElement,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\nimport type { ComponentPropsWithoutRef, CSSProperties, ElementType, ReactNode, Ref } from \"react\";\n\nimport { ThemeScopeContext } from \"./theme-scope\";\n\nexport type ThemeMode = \"light\" | \"dark\" | \"system\";\n\n/** A leaf value accepted by the theme variable mapper. */\nexport type JaciThemeTokenValue = string | number;\n\n/**\n * Semantic theme values. The groups intentionally accept additional keys so\n * applications can extend the token vocabulary without waiting for a package\n * release. Known semantic groups are documented in the public README.\n */\nexport type JaciThemeTokenGroup = {\n readonly [key: string]: JaciThemeTokenValue | JaciThemeTokenGroup | undefined;\n};\n\nexport interface JaciThemeColorTokens extends JaciThemeTokenGroup {\n surface?: JaciThemeTokenGroup;\n fg?: JaciThemeTokenGroup;\n border?: JaciThemeTokenGroup;\n accent?: JaciThemeTokenGroup;\n success?: JaciThemeTokenValue;\n warning?: JaciThemeTokenValue;\n danger?: JaciThemeTokenValue;\n info?: JaciThemeTokenValue;\n link?: JaciThemeTokenGroup;\n focus?: JaciThemeTokenValue;\n disabled?: JaciThemeTokenValue;\n selected?: JaciThemeTokenValue;\n}\n\nexport interface JaciThemeTokens {\n colors?: JaciThemeColorTokens;\n radii?: JaciThemeTokenGroup;\n shadows?: JaciThemeTokenGroup;\n durations?: JaciThemeTokenGroup;\n easings?: JaciThemeTokenGroup;\n transitions?: JaciThemeTokenGroup;\n spacing?: JaciThemeTokenGroup;\n fontSizes?: JaciThemeTokenGroup;\n lineHeights?: JaciThemeTokenGroup;\n typography?: JaciThemeTokenGroup;\n textStyles?: JaciThemeTokenGroup;\n fonts?: JaciThemeTokenGroup;\n}\n\nexport interface ThemeProviderProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n /** The controlled color mode. */\n theme?: ThemeMode;\n /** The initial color mode for an uncontrolled provider. */\n defaultTheme?: ThemeMode;\n /** The deterministic mode used for `system` while rendering on the server. */\n ssrTheme?: \"light\" | \"dark\";\n /** Scoped semantic token overrides. */\n tokens?: JaciThemeTokens;\n /** Called when a controlled provider requests a mode change. */\n onThemeChange?: (theme: ThemeMode) => void;\n /** The element that owns the theme scope. */\n as?: ElementType;\n children?: ReactNode;\n}\n\nexport interface ThemeContextValue {\n theme: ThemeMode;\n resolvedTheme: \"light\" | \"dark\";\n setTheme: (theme: ThemeMode) => void;\n}\n\nconst defaultThemeContext: ThemeContextValue = {\n theme: \"light\",\n resolvedTheme: \"light\",\n setTheme: () => undefined,\n};\n\nconst ThemeContext = createContext<ThemeContextValue>(defaultThemeContext);\n\nfunction kebabCase(value: string) {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1-$2\")\n .replace(/[\\s_]+/g, \"-\")\n .toLowerCase();\n}\n\nfunction flattenTokens(\n group: JaciThemeTokenGroup | undefined,\n path: string[],\n output: Record<string, string>,\n) {\n if (!group) return;\n\n for (const [key, value] of Object.entries(group)) {\n if (value === undefined) continue;\n const nextPath = [...path, kebabCase(key)];\n\n if (typeof value === \"object\") {\n flattenTokens(value, nextPath, output);\n } else {\n output[`--jaci-${nextPath.join(\"-\")}`] = String(value);\n }\n }\n}\n\nfunction tokenStyles(tokens: JaciThemeTokens | undefined): CSSProperties {\n if (!tokens) return {};\n\n const variables: Record<string, string> = {};\n for (const [group, values] of Object.entries(tokens)) {\n flattenTokens(values, [kebabCase(group)], variables);\n }\n\n return variables as CSSProperties;\n}\n\nfunction initialSystemTheme(ssrTheme: \"light\" | \"dark\" | undefined) {\n return ssrTheme ?? \"light\";\n}\n\nexport const ThemeProvider = forwardRef<HTMLElement, ThemeProviderProps>(function ThemeProvider(\n {\n as = \"div\",\n children,\n defaultTheme = \"light\",\n onThemeChange,\n ssrTheme,\n style,\n theme,\n tokens,\n ...props\n },\n ref,\n) {\n const [uncontrolledTheme, setUncontrolledTheme] = useState<ThemeMode>(defaultTheme);\n const [systemTheme, setSystemTheme] = useState<\"light\" | \"dark\">(() =>\n initialSystemTheme(ssrTheme),\n );\n const [scopeElement, setScopeElement] = useState<HTMLElement | null>(null);\n const [portalContainer, setPortalContainer] = useState<HTMLElement | null>(null);\n const currentTheme = theme ?? uncontrolledTheme;\n\n useEffect(() => {\n if (currentTheme !== \"system\") return;\n\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") return;\n\n const media = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const update = () => setSystemTheme(media.matches ? \"dark\" : \"light\");\n update();\n if (typeof media.addEventListener === \"function\") media.addEventListener(\"change\", update);\n else media.addListener?.(update);\n\n return () => {\n if (typeof media.removeEventListener === \"function\")\n media.removeEventListener(\"change\", update);\n else media.removeListener?.(update);\n };\n }, [currentTheme]);\n\n const resolvedTheme = currentTheme === \"system\" ? systemTheme : currentTheme;\n const setTheme = useCallback(\n (nextTheme: ThemeMode) => {\n if (theme === undefined) setUncontrolledTheme(nextTheme);\n onThemeChange?.(nextTheme);\n },\n [onThemeChange, theme],\n );\n const contextValue = useMemo(\n () => ({ theme: currentTheme, resolvedTheme, setTheme }),\n [currentTheme, resolvedTheme, setTheme],\n );\n const mergedStyle = useMemo(() => ({ ...style, ...tokenStyles(tokens) }), [style, tokens]);\n const scopedTokenStyles = useMemo(() => tokenStyles(tokens), [tokens]);\n const Root = as;\n const setRootRef = useCallback(\n (element: HTMLElement | null) => {\n setScopeElement((current) => (current === element ? current : element));\n if (typeof ref === \"function\") ref(element);\n else if (ref) (ref as { current: HTMLElement | null }).current = element;\n },\n [ref],\n );\n\n useEffect(() => {\n if (!scopeElement || typeof document === \"undefined\") return;\n\n const host = document.createElement(\"div\");\n host.dataset.jaciThemePortal = \"true\";\n host.dataset.jaciComponent = \"theme-portal\";\n host.dataset.slot = \"theme-portal\";\n // Keep the host out of the Storybook/app layout. Its descendants still\n // inherit the theme attribute and scoped custom properties.\n host.style.display = \"contents\";\n document.body.append(host);\n setPortalContainer(host);\n\n return () => {\n setPortalContainer((current) => (current === host ? null : current));\n host.remove();\n };\n }, [scopeElement]);\n\n useEffect(() => {\n if (!portalContainer) return;\n\n portalContainer.dataset.jaciTheme = resolvedTheme;\n for (const [property, value] of Object.entries(scopedTokenStyles)) {\n portalContainer.style.setProperty(property, value);\n }\n\n return () => {\n for (const property of Object.keys(scopedTokenStyles)) {\n portalContainer.style.removeProperty(property);\n }\n };\n }, [portalContainer, resolvedTheme, scopedTokenStyles]);\n\n return (\n <ThemeContext.Provider value={contextValue}>\n <ThemeScopeContext.Provider value={{ container: portalContainer }}>\n {createElement(\n Root,\n {\n ...props,\n \"data-jaci-theme\": resolvedTheme,\n \"data-jaci-component\": \"theme-provider\",\n \"data-slot\": \"theme-provider\",\n ref: setRootRef as Ref<HTMLElement>,\n style: mergedStyle,\n },\n children,\n )}\n </ThemeScopeContext.Provider>\n </ThemeContext.Provider>\n );\n});\n\nexport function useTheme() {\n return useContext(ThemeContext);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"theme-provider.js","names":[],"sources":["../../src/theme/theme-provider.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n createElement,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\nimport type { ComponentPropsWithoutRef, CSSProperties, ElementType, ReactNode, Ref } from \"react\";\n\nimport { ThemeScopeContext } from \"./theme-scope\";\n\nexport type ThemeMode = \"light\" | \"dark\" | \"system\";\n\n/** A leaf value accepted by the theme variable mapper. */\nexport type JaciThemeTokenValue = string | number;\n\n/**\n * Semantic theme values. The groups intentionally accept additional keys so\n * applications can extend the token vocabulary without waiting for a package\n * release. Known semantic groups are documented in the public README.\n */\nexport type JaciThemeTokenGroup = {\n readonly [key: string]: JaciThemeTokenValue | JaciThemeTokenGroup | undefined;\n};\n\nexport interface JaciThemeColorTokens extends JaciThemeTokenGroup {\n surface?: JaciThemeTokenGroup;\n fg?: JaciThemeTokenGroup;\n border?: JaciThemeTokenGroup;\n accent?: JaciThemeTokenGroup;\n success?: JaciThemeTokenValue;\n warning?: JaciThemeTokenValue;\n danger?: JaciThemeTokenValue;\n info?: JaciThemeTokenValue;\n link?: JaciThemeTokenGroup;\n focus?: JaciThemeTokenValue;\n disabled?: JaciThemeTokenValue;\n selected?: JaciThemeTokenValue;\n}\n\nexport interface JaciThemeTokens {\n colors?: JaciThemeColorTokens;\n radii?: JaciThemeTokenGroup;\n shadows?: JaciThemeTokenGroup;\n durations?: JaciThemeTokenGroup;\n easings?: JaciThemeTokenGroup;\n transitions?: JaciThemeTokenGroup;\n spacing?: JaciThemeTokenGroup;\n fontSizes?: JaciThemeTokenGroup;\n lineHeights?: JaciThemeTokenGroup;\n typography?: JaciThemeTokenGroup;\n textStyles?: JaciThemeTokenGroup;\n fonts?: JaciThemeTokenGroup;\n}\n\nexport interface ThemeProviderProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n /** The controlled color mode. */\n theme?: ThemeMode;\n /** The initial color mode for an uncontrolled provider. */\n defaultTheme?: ThemeMode;\n /** The deterministic mode used for `system` while rendering on the server. */\n ssrTheme?: \"light\" | \"dark\";\n /** Scoped semantic token overrides. */\n tokens?: JaciThemeTokens;\n /** Called when a controlled provider requests a mode change. */\n onThemeChange?: (theme: ThemeMode) => void;\n /** The element that owns the theme scope. */\n as?: ElementType;\n children?: ReactNode;\n}\n\nexport interface ThemeContextValue {\n theme: ThemeMode;\n resolvedTheme: \"light\" | \"dark\";\n setTheme: (theme: ThemeMode) => void;\n}\n\nconst defaultThemeContext: ThemeContextValue = {\n theme: \"light\",\n resolvedTheme: \"light\",\n setTheme: () => undefined,\n};\n\nconst ThemeContext = createContext<ThemeContextValue>(defaultThemeContext);\n\nfunction kebabCase(value: string) {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1-$2\")\n .replace(/[\\s_]+/g, \"-\")\n .toLowerCase();\n}\n\nfunction flattenTokens(\n group: JaciThemeTokenGroup | undefined,\n path: string[],\n output: Record<string, string>,\n) {\n if (!group) return;\n\n for (const [key, value] of Object.entries(group)) {\n if (value === undefined) continue;\n const nextPath = [...path, kebabCase(key)];\n\n if (typeof value === \"object\") {\n flattenTokens(value, nextPath, output);\n } else {\n output[`--jaci-${nextPath.join(\"-\")}`] = String(value);\n }\n }\n}\n\nfunction tokenStyles(tokens: JaciThemeTokens | undefined): CSSProperties {\n if (!tokens) return {};\n\n const variables: Record<string, string> = {};\n for (const [group, values] of Object.entries(tokens)) {\n flattenTokens(values, [kebabCase(group)], variables);\n }\n\n return variables as CSSProperties;\n}\n\nfunction initialSystemTheme(ssrTheme: \"light\" | \"dark\" | undefined) {\n return ssrTheme ?? \"light\";\n}\n\nexport const ThemeProvider = forwardRef<HTMLElement, ThemeProviderProps>(function ThemeProvider(\n {\n as = \"div\",\n children,\n defaultTheme = \"light\",\n onThemeChange,\n ssrTheme,\n style,\n theme,\n tokens,\n ...props\n },\n ref,\n) {\n const [uncontrolledTheme, setUncontrolledTheme] = useState<ThemeMode>(defaultTheme);\n const [systemTheme, setSystemTheme] = useState<\"light\" | \"dark\">(() =>\n initialSystemTheme(ssrTheme),\n );\n const [scopeElement, setScopeElement] = useState<HTMLElement | null>(null);\n const [portalContainer, setPortalContainer] = useState<HTMLElement | null>(null);\n const currentTheme = theme ?? uncontrolledTheme;\n\n useEffect(() => {\n if (currentTheme !== \"system\") return;\n\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") return;\n\n const media = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const update = () => setSystemTheme(media.matches ? \"dark\" : \"light\");\n update();\n if (typeof media.addEventListener === \"function\") media.addEventListener(\"change\", update);\n else media.addListener?.(update);\n\n return () => {\n if (typeof media.removeEventListener === \"function\")\n media.removeEventListener(\"change\", update);\n else media.removeListener?.(update);\n };\n }, [currentTheme]);\n\n const resolvedTheme = currentTheme === \"system\" ? systemTheme : currentTheme;\n const setTheme = useCallback(\n (nextTheme: ThemeMode) => {\n if (theme === undefined) setUncontrolledTheme(nextTheme);\n onThemeChange?.(nextTheme);\n },\n [onThemeChange, theme],\n );\n const contextValue = useMemo(\n () => ({ theme: currentTheme, resolvedTheme, setTheme }),\n [currentTheme, resolvedTheme, setTheme],\n );\n const mergedStyle = useMemo(() => ({ ...style, ...tokenStyles(tokens) }), [style, tokens]);\n const scopedTokenStyles = useMemo(() => tokenStyles(tokens), [tokens]);\n const Root = as;\n const setRootRef = useCallback(\n (element: HTMLElement | null) => {\n setScopeElement((current) => (current === element ? current : element));\n if (typeof ref === \"function\") ref(element);\n else if (ref) (ref as { current: HTMLElement | null }).current = element;\n },\n [ref],\n );\n\n useEffect(() => {\n if (!scopeElement || typeof document === \"undefined\") return;\n\n const host = document.createElement(\"div\");\n host.dataset.jaciThemePortal = \"true\";\n host.dataset.jaciComponent = \"theme-portal\";\n host.dataset.slot = \"theme-portal\";\n // Keep the host out of the Storybook/app layout. Its descendants still\n // inherit the theme attribute and scoped custom properties.\n host.style.display = \"contents\";\n document.body.append(host);\n setPortalContainer(host);\n\n return () => {\n setPortalContainer((current) => (current === host ? null : current));\n host.remove();\n };\n }, [scopeElement]);\n\n useEffect(() => {\n if (!portalContainer) return;\n\n portalContainer.dataset.jaciTheme = resolvedTheme;\n for (const [property, value] of Object.entries(scopedTokenStyles)) {\n portalContainer.style.setProperty(property, value);\n }\n\n return () => {\n for (const property of Object.keys(scopedTokenStyles)) {\n portalContainer.style.removeProperty(property);\n }\n };\n }, [portalContainer, resolvedTheme, scopedTokenStyles]);\n\n return (\n <ThemeContext.Provider value={contextValue}>\n <ThemeScopeContext.Provider value={{ container: portalContainer }}>\n {createElement(\n Root,\n {\n ...props,\n \"data-jaci-theme\": resolvedTheme,\n \"data-jaci-component\": \"theme-provider\",\n \"data-slot\": \"theme-provider\",\n ref: setRootRef as Ref<HTMLElement>,\n style: mergedStyle,\n },\n children,\n )}\n </ThemeScopeContext.Provider>\n </ThemeContext.Provider>\n );\n});\n\nexport function useTheme() {\n return useContext(ThemeContext);\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-scope.cjs","names":[],"sources":["../../src/theme/theme-scope.ts"],"sourcesContent":["\"use client\";\n\nimport { createContext, useContext } from \"react\";\nimport type { RefObject } from \"react\";\n\nexport type ThemePortalContainer =\n | HTMLElement\n | ShadowRoot\n | null\n | RefObject<HTMLElement | ShadowRoot | null>;\n\nexport interface ThemeScopeValue {\n container: HTMLElement | null;\n}\n\nexport const ThemeScopeContext = createContext<ThemeScopeValue>({ container: null });\n\nexport function useThemePortalContainer() {\n return useContext(ThemeScopeContext).container;\n}\n\nexport function useThemePortalProps<T extends { container?: ThemePortalContainer | undefined }>(\n props: T,\n): T {\n const scopedContainer = useThemePortalContainer();\n\n if (props.container !== undefined || scopedContainer === null) return props;\n\n return { ...props, container: scopedContainer };\n}\n"],"mappings":";;;AAeA,MAAa,qBAAA,
|
|
1
|
+
{"version":3,"file":"theme-scope.cjs","names":["createContext","useContext"],"sources":["../../src/theme/theme-scope.ts"],"sourcesContent":["\"use client\";\n\nimport { createContext, useContext } from \"react\";\nimport type { RefObject } from \"react\";\n\nexport type ThemePortalContainer =\n | HTMLElement\n | ShadowRoot\n | null\n | RefObject<HTMLElement | ShadowRoot | null>;\n\nexport interface ThemeScopeValue {\n container: HTMLElement | null;\n}\n\nexport const ThemeScopeContext = createContext<ThemeScopeValue>({ container: null });\n\nexport function useThemePortalContainer() {\n return useContext(ThemeScopeContext).container;\n}\n\nexport function useThemePortalProps<T extends { container?: ThemePortalContainer | undefined }>(\n props: T,\n): T {\n const scopedContainer = useThemePortalContainer();\n\n if (props.container !== undefined || scopedContainer === null) return props;\n\n return { ...props, container: scopedContainer };\n}\n"],"mappings":";;;AAeA,MAAa,qBAAA,GAAoBA,MAAAA,cAAAA,CAA+B,EAAE,WAAW,KAAK,CAAC;AAEnF,SAAgB,0BAA0B;CACxC,QAAA,GAAOC,MAAAA,WAAAA,CAAW,iBAAiB,CAAC,CAAC;AACvC;AAEA,SAAgB,oBACd,OACG;CACH,MAAM,kBAAkB,wBAAwB;CAEhD,IAAI,MAAM,cAAc,KAAA,KAAa,oBAAoB,MAAM,OAAO;CAEtE,OAAO;EAAE,GAAG;EAAO,WAAW;CAAgB;AAChD"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jaci-ui",
|
|
3
3
|
"description": "Accessible, themeable React components by Jaci UI",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Richard Borges",
|
|
@@ -78,22 +78,22 @@
|
|
|
78
78
|
}
|
|
79
79
|
},
|
|
80
80
|
"dependencies": {
|
|
81
|
-
"@base-ui/react": "^1.
|
|
82
|
-
"date-fns": "^4.
|
|
81
|
+
"@base-ui/react": "^1.7.0",
|
|
82
|
+
"date-fns": "^4.4.0",
|
|
83
83
|
"qrcode": "^1.5.4"
|
|
84
84
|
},
|
|
85
85
|
"publishConfig": {
|
|
86
86
|
"access": "public"
|
|
87
87
|
},
|
|
88
88
|
"devDependencies": {
|
|
89
|
-
"@pandacss/dev": "^1.
|
|
89
|
+
"@pandacss/dev": "^1.12.0",
|
|
90
90
|
"@types/qrcode": "^1.5.6",
|
|
91
91
|
"@types/react": "^19.2.18",
|
|
92
92
|
"@types/react-dom": "^19.2.4",
|
|
93
93
|
"jsdom": "^27.4.0",
|
|
94
94
|
"react": "^19.2.8",
|
|
95
95
|
"react-dom": "^19.2.8",
|
|
96
|
-
"tsdown": "^0.22.
|
|
96
|
+
"tsdown": "^0.22.14"
|
|
97
97
|
},
|
|
98
98
|
"scripts": {
|
|
99
99
|
"clean": "rimraf dist src/styled-system",
|