UNPKG

@kopexa/sight

Version:

Kopexa Sight Design System — React component library for GRC applications

842 lines (830 loc) 28.2 kB
"use client"; "use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/components/file-upload/avatar-upload.tsx var avatar_upload_exports = {}; __export(avatar_upload_exports, { AvatarUpload: () => AvatarUpload }); module.exports = __toCommonJS(avatar_upload_exports); var import_button = require("@kopexa/button"); var import_callout = require("@kopexa/callout"); var import_i18n4 = require("@kopexa/i18n"); var import_icons2 = require("@kopexa/icons"); var import_image_crop = require("@kopexa/image-crop"); var import_shared_utils3 = require("@kopexa/shared-utils"); var import_theme2 = require("@kopexa/theme"); var import_react2 = require("react"); // src/hooks/use-file-upload/index.ts var import_i18n2 = require("@kopexa/i18n"); var import_shared_utils = require("@kopexa/shared-utils"); var import_react = require("react"); // src/hooks/use-file-upload/messages.ts var import_i18n = require("@kopexa/i18n"); var messages = (0, import_i18n.defineMessages)({ file_exceeds_max: { id: "use_file_upload.file_exceeds_max", defaultMessage: `File "{name}" exceeds the maximum size of {max}.`, description: "Shown when a single file is larger than allowed" }, file_not_accepted: { id: "use_file_upload.file_not_accepted", defaultMessage: `File "{name}" is not an accepted file type.`, description: "Shown when file type/extension doesn't match accept" }, too_many_files: { id: "file_upload.too_many_files", defaultMessage: "You can only upload a maximum of {max} files.", description: "Shown when maxFiles would be exceeded" } }); // src/hooks/use-file-upload/index.ts var useFileUpload = (options = {}) => { const { maxFiles = Number.POSITIVE_INFINITY, maxSize = Number.POSITIVE_INFINITY, accept = "*", multiple = false, initialFiles = [], onFilesChange, onFilesAdded, onError } = options; const t = (0, import_i18n2.useSafeIntl)(); const [state, setState] = (0, import_react.useState)({ files: initialFiles.map((file) => ({ file, id: file.id, preview: file.url })), isDragging: false, errors: [] }); const inputRef = (0, import_react.useRef)(null); const validateFile = (0, import_react.useCallback)( (file) => { if (file instanceof File) { if (file.size > maxSize) { return t.formatMessage(messages.file_exceeds_max, { name: file.name, max: (0, import_shared_utils.formatBytes)(maxSize) }); } } else { if (file.size > maxSize) { return t.formatMessage(messages.file_exceeds_max, { name: file.name, max: (0, import_shared_utils.formatBytes)(maxSize) }); } } if (accept !== "*") { const acceptedTypes = accept.split(",").map((type) => type.trim()); const fileType = file instanceof File ? file.type || "" : file.type; const fileExtension = `.${file instanceof File ? file.name.split(".").pop() : file.name.split(".").pop()}`; const isAccepted = acceptedTypes.some((type) => { if (type.startsWith(".")) { return fileExtension.toLowerCase() === type.toLowerCase(); } if (type.endsWith("/*")) { const baseType = type.split("/")[0]; return fileType.startsWith(`${baseType}/`); } return fileType === type; }); if (!isAccepted) { return t.formatMessage(messages.file_not_accepted, { name: file instanceof File ? file.name : file.name }); } } return null; }, [accept, maxSize, t.formatMessage] ); const createPreview = (0, import_react.useCallback)( (file) => { if (file instanceof File) { return URL.createObjectURL(file); } return file.url; }, [] ); const generateUniqueId = (0, import_react.useCallback)((file) => { if (file instanceof File) { return `${file.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`; } return file.id; }, []); const clearFiles = (0, import_react.useCallback)(() => { setState((prev) => { for (const file of prev.files) { if (file.preview && file.file instanceof File && file.file.type.startsWith("image/")) { URL.revokeObjectURL(file.preview); } } if (inputRef.current) { inputRef.current.value = ""; } const newState = { ...prev, files: [], errors: [] }; onFilesChange == null ? void 0 : onFilesChange(newState.files); return newState; }); }, [onFilesChange]); const addFiles = (0, import_react.useCallback)( (newFiles) => { if (!newFiles || newFiles.length === 0) return; const newFilesArray = Array.from(newFiles); const errors = []; setState((prev) => ({ ...prev, errors: [] })); if (!multiple) { clearFiles(); } if (multiple && maxFiles !== Number.POSITIVE_INFINITY && state.files.length + newFilesArray.length > maxFiles) { errors.push( t.formatMessage(messages.too_many_files, { max: maxFiles }) ); onError == null ? void 0 : onError(errors); setState((prev) => ({ ...prev, errors })); return; } const validFiles = []; for (const file of newFilesArray) { if (multiple) { const isDuplicate = state.files.some( (existingFile) => existingFile.file.name === file.name && existingFile.file.size === file.size ); if (isDuplicate) { return; } } if (file.size > maxSize) { errors.push( multiple ? `Some files exceed the maximum size of ${(0, import_shared_utils.formatBytes)(maxSize)}.` : `File exceeds the maximum size of ${(0, import_shared_utils.formatBytes)(maxSize)}.` ); continue; } const error = validateFile(file); if (error) { errors.push(error); } else { validFiles.push({ file, id: generateUniqueId(file), preview: createPreview(file) }); } } if (validFiles.length > 0) { onFilesAdded == null ? void 0 : onFilesAdded(validFiles); setState((prev) => { const newFiles2 = !multiple ? validFiles : [...prev.files, ...validFiles]; onFilesChange == null ? void 0 : onFilesChange(newFiles2); return { ...prev, files: newFiles2, errors }; }); } else if (errors.length > 0) { onError == null ? void 0 : onError(errors); setState((prev) => ({ ...prev, errors })); } if (inputRef.current) { inputRef.current.value = ""; } }, [ onError, state.files, maxFiles, multiple, maxSize, validateFile, createPreview, generateUniqueId, clearFiles, onFilesChange, onFilesAdded, t.formatMessage ] ); const removeFile = (0, import_react.useCallback)( (id) => { setState((prev) => { const fileToRemove = prev.files.find((file) => file.id === id); if ((fileToRemove == null ? void 0 : fileToRemove.preview) && fileToRemove.file instanceof File && fileToRemove.file.type.startsWith("image/")) { URL.revokeObjectURL(fileToRemove.preview); } const newFiles = prev.files.filter((file) => file.id !== id); onFilesChange == null ? void 0 : onFilesChange(newFiles); return { ...prev, files: newFiles, errors: [] }; }); }, [onFilesChange] ); const clearErrors = (0, import_react.useCallback)(() => { setState((prev) => ({ ...prev, errors: [] })); }, []); const handleDragEnter = (0, import_react.useCallback)((e) => { e.preventDefault(); e.stopPropagation(); setState((prev) => ({ ...prev, isDragging: true })); }, []); const handleDragLeave = (0, import_react.useCallback)((e) => { e.preventDefault(); e.stopPropagation(); if (e.currentTarget.contains(e.relatedTarget)) { return; } setState((prev) => ({ ...prev, isDragging: false })); }, []); const handleDragOver = (0, import_react.useCallback)((e) => { e.preventDefault(); e.stopPropagation(); }, []); const handleDrop = (0, import_react.useCallback)( (e) => { var _a; e.preventDefault(); e.stopPropagation(); setState((prev) => ({ ...prev, isDragging: false })); if ((_a = inputRef.current) == null ? void 0 : _a.disabled) { return; } if (e.dataTransfer.files && e.dataTransfer.files.length > 0) { if (!multiple) { const file = e.dataTransfer.files[0]; addFiles([file]); } else { addFiles(e.dataTransfer.files); } } }, [addFiles, multiple] ); const handleFileChange = (0, import_react.useCallback)( (e) => { if (e.target.files && e.target.files.length > 0) { addFiles(e.target.files); } }, [addFiles] ); const openFileDialog = (0, import_react.useCallback)(() => { if (inputRef.current) { inputRef.current.click(); } }, []); const getInputProps = (0, import_react.useCallback)( (props = {}) => { return { ...props, type: "file", onChange: handleFileChange, accept: props.accept || accept, multiple: props.multiple !== void 0 ? props.multiple : multiple, ref: inputRef }; }, [accept, multiple, handleFileChange] ); return [ state, { addFiles, removeFile, clearFiles, clearErrors, handleDragEnter, handleDragLeave, handleDragOver, handleDrop, handleFileChange, openFileDialog, getInputProps } ]; }; // src/components/dialog/dialog.tsx var import_dialog = require("@base-ui/react/dialog"); var import_icons = require("@kopexa/icons"); var import_react_utils = require("@kopexa/react-utils"); var import_shared_utils2 = require("@kopexa/shared-utils"); var import_theme = require("@kopexa/theme"); var import_use_controllable_state = require("@kopexa/use-controllable-state"); var import_jsx_runtime = require("react/jsx-runtime"); var [DialogProvider, useDialogContext] = (0, import_react_utils.createContext)(); var DialogRoot = (props) => { const { open: openProp, onOpenChange, size, radius, placement, scrollBehavior, ...restProps } = props; const [open, setOpen] = (0, import_use_controllable_state.useControllableState)({ value: openProp, onChange: onOpenChange, defaultValue: false }); const styles = (0, import_theme.dialog)({ size, radius, placement, scrollBehavior }); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogProvider, { value: { styles, open, placement, size, radius }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_dialog.Dialog.Root, { "data-slot": "dialog", open, onOpenChange: (open2) => setOpen(open2), ...restProps } ) }); }; function DialogTrigger({ ...props }) { return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dialog.Dialog.Trigger, { "data-slot": "dialog-trigger", ...props }); } function DialogPortal({ ...props }) { return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dialog.Dialog.Portal, { "data-slot": "dialog-portal", ...props }); } function DialogOverlay({ className, ...props }) { const { styles } = useDialogContext(); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_dialog.Dialog.Backdrop, { "data-slot": "dialog-overlay", className: (0, import_shared_utils2.cn)(styles.overlay(), className), ...props } ); } function DialogContent({ className, children, showCloseButton = true, ...props }) { const { styles } = useDialogContext(); return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogPortal, { "data-slot": "dialog-portal", children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogOverlay, {}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( import_dialog.Dialog.Popup, { "data-slot": "dialog-content", className: (0, import_shared_utils2.cn)(styles.content(), className), ...props, children: [ children, showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( import_dialog.Dialog.Close, { "data-slot": "dialog-close", className: styles.close(), children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.CloseIcon, {}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only", children: "Close" }) ] } ) ] } ) ] }); } function DialogHeader({ className, ...props }) { const { styles } = useDialogContext(); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "div", { "data-slot": "dialog-header", className: styles.header({ className }), ...props } ); } function DialogFooter({ className, ...props }) { const { styles } = useDialogContext(); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "div", { "data-slot": "dialog-footer", className: styles.footer({ className }), ...props } ); } function DialogBody({ className, ...props }) { const { styles } = useDialogContext(); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "div", { "data-slot": "dialog-body", className: styles.body({ className }), ...props } ); } function DialogTitle({ className, ...props }) { const { styles } = useDialogContext(); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_dialog.Dialog.Title, { "data-slot": "dialog-title", className: (0, import_shared_utils2.cn)(styles.title(), className), ...props } ); } function DialogDescription({ className, ...props }) { const { styles } = useDialogContext(); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_dialog.Dialog.Description, { "data-slot": "dialog-description", className: (0, import_shared_utils2.cn)(styles.description(), className), ...props } ); } function DialogCloseTrigger({ className, ...props }) { const { styles } = useDialogContext(); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_dialog.Dialog.Close, { "data-slot": "dialog-close-trigger", className: (0, import_shared_utils2.cn)(styles.closeTrigger(), className), ...props } ); } // src/components/dialog/index.ts var Dialog = Object.assign(DialogRoot, { Root: DialogRoot, Body: DialogBody, CloseTrigger: DialogCloseTrigger, Content: DialogContent, Description: DialogDescription, Footer: DialogFooter, Header: DialogHeader, Overlay: DialogOverlay, Portal: DialogPortal, Title: DialogTitle, Trigger: DialogTrigger }); // src/components/file-upload/messages.ts var import_i18n3 = require("@kopexa/i18n"); var messages2 = (0, import_i18n3.defineMessages)({ change_avatar: { id: "file_upload.change_avatar", defaultMessage: "Change Avatar", description: "Label for changing the avatar image" }, upload_avatar: { id: "file_upload.upload_avatar", defaultMessage: "Upload Avatar", description: "Label for uploading a new avatar image" }, remove_avatar: { id: "file_upload.remove_avatar", defaultMessage: "Remove Avatar", description: "Label for removing the current avatar image" }, avatar_uploaded: { id: "file_upload.avatar_uploaded", defaultMessage: "Avatar uploaded", description: "Message displayed when the avatar is uploaded successfully" }, accepted_file_types: { id: "file_upload.accepted_file_types", defaultMessage: "{types}{size, select, none {} other { up to {size}}}", description: "Message indicating the accepted file types for upload" }, cancel: { id: "file_upload.cancel", defaultMessage: "Cancel", description: "Label for canceling the file upload" }, apply_crop: { id: "file_upload.apply_crop", defaultMessage: "Apply", description: "Label for applying the crop to the image" } }); // src/components/file-upload/utils/data-url-to-file.ts async function dataUrlToFile(dataUrl, fileName, typeHint) { const res = await fetch(dataUrl); const blob = await res.blob(); const type = typeHint || blob.type || "image/png"; const ext = type.includes("jpeg") ? "jpg" : type.split("/")[1] || "png"; const safeName = fileName.replace(/\.[^.]+$/, ""); return new File([blob], `${safeName}-cropped.${ext}`, { type }); } // src/components/file-upload/utils/format-accept-types.ts var WILDCARD_GROUPS = { "image/*": "common image formats", "audio/*": "common audio formats", "video/*": "common video formats", "application/*": "common document formats" }; var MIME_TO_LABEL = { "image/png": "PNG", "image/jpeg": "JPG", "image/jpg": "JPG", "application/pdf": "PDF", "text/csv": "CSV", "text/plain": "TXT" }; var EXT_TO_LABEL = { ".png": "PNG", ".jpg": "JPG", ".jpeg": "JPG", ".pdf": "PDF", ".csv": "CSV", ".txt": "TXT" }; function normalizeToken(token) { return token.trim().toLowerCase(); } function formatAcceptedTypes(accept) { var _a, _b; if (!accept || typeof accept !== "string") return ""; const tokens = accept.split(",").map(normalizeToken).filter(Boolean); const labels = []; for (const token of tokens) { if (WILDCARD_GROUPS[token]) { labels.push(WILDCARD_GROUPS[token]); continue; } if (token.startsWith(".")) { labels.push( (_a = EXT_TO_LABEL[token]) != null ? _a : token.replace(/^\./, "").toUpperCase() ); continue; } if (token.includes("/")) { labels.push((_b = MIME_TO_LABEL[token]) != null ? _b : token.split("/")[1].toUpperCase()); } } const seen = /* @__PURE__ */ new Set(); return labels.filter((x) => { if (seen.has(x)) return false; seen.add(x); return true; }).join(", "); } // src/components/file-upload/utils/is-image-like.ts function isImageLike(file) { var _a, _b; if ((_a = file.type) == null ? void 0 : _a.startsWith("image/")) return true; const name = ((_b = file.name) == null ? void 0 : _b.toLowerCase()) || ""; return name.endsWith(".png") || name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".webp"); } // src/components/file-upload/avatar-upload.tsx var import_jsx_runtime2 = require("react/jsx-runtime"); var defaultMaxSize = 2 * 1024 * 1024; var AvatarUpload = (props) => { const { maxSize = defaultMaxSize, className, onFileChange, defaultAvatar, orientation, size, shape, accept = ".png,.jpg", cropperEnabled = true, cropAspect = 1, cropMaxImageSize = defaultMaxSize, onCroppedFile, ...rest } = props; const t = (0, import_i18n4.useSafeIntl)(); const [cropOpen, setCropOpen] = (0, import_react2.useState)(false); const [cropSourceFile, setCropSourceFile] = (0, import_react2.useState)(null); const pendingOriginalId = (0, import_react2.useRef)(null); const [ { files, isDragging, errors }, { removeFile, handleDragEnter, handleDragLeave, handleDragOver, handleDrop, openFileDialog, getInputProps, clearErrors, addFiles } ] = useFileUpload({ maxFiles: 1, maxSize, accept, multiple: false, onFilesChange: (files2) => { onFileChange == null ? void 0 : onFileChange(files2[0] || null); }, onFilesAdded: (added) => { var _a; if (!cropperEnabled) return; const raw = (_a = added[0]) == null ? void 0 : _a.file; if (raw instanceof File && isImageLike(raw)) { pendingOriginalId.current = added[0].id; setCropSourceFile(raw); setCropOpen(true); } } }); const currentFile = files[0]; const previewUrl = (currentFile == null ? void 0 : currentFile.preview) || defaultAvatar; const handleRemove = () => { if (currentFile) { removeFile(currentFile.id); clearErrors(); } }; const styles = (0, import_theme2.avatarUpload)({ size, shape, orientation }); const typesLabel = formatAcceptedTypes(accept); const handleCropCancel = (0, import_react2.useCallback)(() => { setCropOpen(false); setCropSourceFile(null); pendingOriginalId.current = null; }, []); const handleCropApply = (0, import_react2.useCallback)( async (croppedDataUrl) => { if (!croppedDataUrl || !cropSourceFile) { handleCropCancel(); return; } const newFile = await dataUrlToFile( croppedDataUrl, cropSourceFile.name, cropSourceFile.type ); if (pendingOriginalId.current) { removeFile(pendingOriginalId.current); pendingOriginalId.current = null; } addFiles([newFile]); onCroppedFile == null ? void 0 : onCroppedFile(newFile); setCropOpen(false); setCropSourceFile(null); }, [cropSourceFile, addFiles, removeFile, onCroppedFile, handleCropCancel] ); return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)( "div", { "data-slot": "avatar-upload", className: styles.root({ className }), ...rest, children: [ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: styles.previewAndText(), children: [ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: styles.previewContainer(), children: [ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)( "button", { type: "button", "aria-label": previewUrl ? t.formatMessage(messages2.change_avatar) : t.formatMessage(messages2.upload_avatar), "data-dragging": (0, import_shared_utils3.dataAttr)(isDragging), "data-hasimage": (0, import_shared_utils3.dataAttr)(!!previewUrl), className: styles.preview(), onDragEnter: handleDragEnter, onDragLeave: handleDragLeave, onDragOver: handleDragOver, onDrop: handleDrop, onClick: openFileDialog, children: [ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { ...getInputProps(), className: "sr-only" }), previewUrl ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( "img", { src: previewUrl, alt: "Avatar", className: styles.previewImg() } ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: styles.placeholderWrapper(), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons2.UserCircleIcon, { className: styles.placeholder() }) }) ] } ), currentFile && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_button.IconButton, { variant: "outline", color: "default", onClick: handleRemove, size: "sm", className: styles.removeButton(), "aria-label": t.formatMessage(messages2.remove_avatar), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons2.CloseIcon, {}) } ) ] }), /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: styles.instructionsContainer(), children: [ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: styles.instructions(), children: currentFile ? t.formatMessage(messages2.avatar_uploaded) : t.formatMessage(messages2.upload_avatar) }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: styles.acceptedFiles(), children: t.formatMessage(messages2.accepted_file_types, { types: typesLabel || "-", size: maxSize ? (0, import_shared_utils3.formatBytes)(maxSize) : "none" }) }) ] }) ] }), errors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_callout.Callout, { variant: "destructive", children: errors.map((error, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: styles.errorItem(), children: error }, index.toString())) }) ] } ), cropperEnabled && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( Dialog.Root, { open: cropOpen, onOpenChange: (v) => !v ? handleCropCancel() : null, size: "2xl", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Dialog.Content, { children: [ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Dialog.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Dialog.Title, { children: t.formatMessage(messages2.change_avatar) }) }), cropSourceFile && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)( import_image_crop.ImageCrop, { aspect: cropAspect, file: cropSourceFile, maxImageSize: cropMaxImageSize, onCrop: handleCropApply, children: [ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Dialog.Body, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_image_crop.ImageCropContent, { className: "max-w-md" }) }), /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Dialog.Footer, { children: [ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( Dialog.CloseTrigger, { render: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_button.Button, { variant: "ghost", color: "default", startContent: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons2.CloseIcon, {}), children: t.formatMessage(messages2.cancel) } ) } ), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_image_crop.ImageCropApply, { color: "primary", variant: "solid", render: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_button.Button, { startContent: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons2.CropIcon, {}), children: t.formatMessage(messages2.apply_crop) }) } ) ] }) ] } ) ] }) } ) ] }); }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { AvatarUpload });