@crestbase/web-shared-ui 1.0.1 → 1.0.2
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/README.md +117 -4
- package/dist/components/button/CircleBtn.d.ts +9 -0
- package/dist/components/button/CircleBtn.js +5 -0
- package/dist/components/button/ShadowButton.d.ts +8 -0
- package/dist/components/button/ShadowButton.js +5 -0
- package/dist/components/button/index.d.ts +12 -3
- package/dist/components/button/index.js +17 -3
- package/dist/components/core/Accordion.d.ts +11 -0
- package/dist/components/core/Accordion.js +7 -0
- package/dist/components/core/AddressInput.d.ts +34 -0
- package/dist/components/core/AddressInput.js +88 -0
- package/dist/components/core/BottomSheet.d.ts +10 -0
- package/dist/components/core/BottomSheet.js +15 -0
- package/dist/components/core/Calendar.d.ts +9 -0
- package/dist/components/core/Calendar.js +98 -0
- package/dist/components/core/CalendarExtended.d.ts +27 -0
- package/dist/components/core/CalendarExtended.js +147 -0
- package/dist/components/core/Checkbox.d.ts +13 -0
- package/dist/components/core/Checkbox.js +10 -0
- package/dist/components/core/CustomDropdown.d.ts +19 -0
- package/dist/components/core/CustomDropdown.js +41 -0
- package/dist/components/core/Modal.d.ts +12 -0
- package/dist/components/core/Modal.js +12 -0
- package/dist/components/core/NumberInput.d.ts +12 -0
- package/dist/components/core/NumberInput.js +34 -0
- package/dist/components/core/NumberInputWithCommas.d.ts +10 -0
- package/dist/components/core/NumberInputWithCommas.js +19 -0
- package/dist/components/core/OptionsDropdown.d.ts +17 -0
- package/dist/components/core/OptionsDropdown.js +44 -0
- package/dist/components/core/OtpInput.d.ts +9 -0
- package/dist/components/core/OtpInput.js +54 -0
- package/dist/components/core/PreviewArea.d.ts +18 -0
- package/dist/components/core/PreviewArea.js +31 -0
- package/dist/components/core/SelectionList.d.ts +16 -0
- package/dist/components/core/SelectionList.js +9 -0
- package/dist/components/core/SquareCheckbox.d.ts +10 -0
- package/dist/components/core/SquareCheckbox.js +5 -0
- package/dist/components/core/TabNavigation.d.ts +19 -0
- package/dist/components/core/TabNavigation.js +11 -0
- package/dist/components/core/Textarea.d.ts +10 -0
- package/dist/components/core/Textarea.js +8 -0
- package/dist/components/core/Toggle.d.ts +10 -0
- package/dist/components/core/Toggle.js +11 -0
- package/dist/components/core/Upload.d.ts +28 -0
- package/dist/components/core/Upload.js +76 -0
- package/dist/components/core/UploadArea.d.ts +14 -0
- package/dist/components/core/UploadArea.js +13 -0
- package/dist/components/core/input.d.ts +11 -0
- package/dist/components/core/input.js +24 -0
- package/dist/components/index.d.ts +41 -1
- package/dist/components/index.js +25 -1
- package/dist/components/navigation/Logo.d.ts +7 -0
- package/dist/components/navigation/Logo.js +7 -0
- package/dist/components/notification/GlobalNotificationProvider.d.ts +4 -0
- package/dist/components/notification/GlobalNotificationProvider.js +6 -0
- package/dist/components/notification/NotificationPopup.d.ts +1 -0
- package/dist/components/notification/NotificationPopup.js +73 -0
- package/dist/components/notification/notificationStore.d.ts +15 -0
- package/dist/components/notification/notificationStore.js +12 -0
- package/dist/components/svg/Crestbase.d.ts +6 -0
- package/dist/components/svg/Crestbase.js +5 -0
- package/dist/components/svg/CrestbaseColored.d.ts +6 -0
- package/dist/components/svg/CrestbaseColored.js +5 -0
- package/dist/components/svg/UploadIcon.d.ts +5 -0
- package/dist/components/svg/UploadIcon.js +4 -0
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/useFileUpload.d.ts +35 -0
- package/dist/hooks/useFileUpload.js +219 -0
- package/dist/hooks/useFileUploadWithNotifications.d.ts +36 -0
- package/dist/hooks/useFileUploadWithNotifications.js +39 -0
- package/dist/hooks/useResponsive.d.ts +38 -0
- package/dist/hooks/useResponsive.js +97 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/styles.css +2 -0
- package/dist/types/property.d.ts +17 -0
- package/dist/types/property.js +2 -0
- package/dist/utils/fileValidation.d.ts +21 -0
- package/dist/utils/fileValidation.js +82 -0
- package/dist/utils/googleMapsLoader.d.ts +40 -0
- package/dist/utils/googleMapsLoader.js +108 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +13 -0
- package/package.json +22 -12
- package/dist/components/button/index.d.ts.map +0 -1
- package/dist/components/button/index.js.map +0 -1
- package/dist/components/index.d.ts.map +0 -1
- package/dist/components/index.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef } from "react";
|
|
4
|
+
const Textarea = forwardRef(({ label, name, placeholder, required = false, error, disabled = false, className = "", rows = 4, ...props }, ref) => {
|
|
5
|
+
return (_jsxs("div", { className: `w-full text-sm ${className}`, children: [label && (_jsx("label", { htmlFor: name, className: "block mb-2 text-xs text-gray-500", children: label })), _jsx("div", { className: "relative", children: _jsx("textarea", { ref: ref, id: name, name: name, placeholder: placeholder, required: required, disabled: disabled, rows: rows, autoComplete: "off", className: `w-full h-25 sm:h-auto text-base sm:text-xs p-3 sm:p-4 border border-gray-200 rounded-xl bg-gray-50 focus:border-gray-300 focus:bg-white outline-none placeholder-gray-400 resize-vertical min-h-[160px] ${error ? "border-red-500" : "border-gray-200"} text-black`, ...props }) }), error && _jsx("p", { className: "mt-1 text-sm text-red-500", children: error })] }));
|
|
6
|
+
});
|
|
7
|
+
Textarea.displayName = "Textarea";
|
|
8
|
+
export default Textarea;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface ToggleProps {
|
|
3
|
+
checked: boolean;
|
|
4
|
+
onChange: (checked: boolean) => void;
|
|
5
|
+
label?: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
declare const _default: (props: ToggleProps) => React.JSX.Element;
|
|
10
|
+
export default _default;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
const Toggle = ({ checked, onChange, label, disabled = false, className = "", }) => {
|
|
4
|
+
const handleClick = () => {
|
|
5
|
+
if (disabled)
|
|
6
|
+
return;
|
|
7
|
+
onChange(!checked);
|
|
8
|
+
};
|
|
9
|
+
return (_jsxs("div", { className: `flex items-center gap-3 ${className}`, children: [_jsx("button", { type: "button", role: "switch", "aria-checked": checked, onClick: handleClick, disabled: disabled, className: `relative inline-flex h-5 w-9 items-center rounded-full transition-colors focus:outline-none border border-gray-200 ${checked ? "bg-primaryblue" : "bg-gray-200"} ${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}`, children: _jsx("span", { className: `inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${checked ? "translate-x-4" : "translate-x-1"}` }) }), label && _jsx("span", { className: "text-xs text-black", children: label })] }));
|
|
10
|
+
};
|
|
11
|
+
export default Toggle;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { type ExistingFile } from "../../hooks/useFileUpload";
|
|
3
|
+
export interface UploadRef extends HTMLInputElement {
|
|
4
|
+
markFilesAsUploaded: (tabId: string, fileNames: string[]) => void;
|
|
5
|
+
getUnuploadedFiles: (tabId: string) => File[];
|
|
6
|
+
getAllSelectedFiles: () => Record<string, File[]>;
|
|
7
|
+
getUploadedFiles: () => Record<string, string[]>;
|
|
8
|
+
getFileChanges: () => {
|
|
9
|
+
newFiles: Record<string, File[]>;
|
|
10
|
+
existingFiles: Record<string, ExistingFile[]>;
|
|
11
|
+
removedFiles: Record<string, ExistingFile[]>;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export interface UploadProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "className" | "type"> {
|
|
15
|
+
label?: string;
|
|
16
|
+
error?: string;
|
|
17
|
+
className?: string;
|
|
18
|
+
onFileSelect?: (files: FileList | null, tabId?: string) => void;
|
|
19
|
+
tabs?: {
|
|
20
|
+
id: string;
|
|
21
|
+
label: string;
|
|
22
|
+
}[];
|
|
23
|
+
uploadedFiles?: Record<string, string[]>;
|
|
24
|
+
onUploadStatusChange?: (tabId: string, uploadedFileNames: string[]) => void;
|
|
25
|
+
existingFiles?: ExistingFile[];
|
|
26
|
+
}
|
|
27
|
+
declare const _default: (props: UploadProps) => React.JSX.Element;
|
|
28
|
+
export default _default;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React, { forwardRef, useRef, useState } from "react";
|
|
4
|
+
import { useFileUpload } from "../../hooks/useFileUpload";
|
|
5
|
+
import { isVideoFileGeneric } from "../../utils";
|
|
6
|
+
import { useIsMobile } from "../../hooks/useResponsive";
|
|
7
|
+
import TabNavigation from "./TabNavigation";
|
|
8
|
+
import UploadArea from "./UploadArea";
|
|
9
|
+
import PreviewArea from "./PreviewArea";
|
|
10
|
+
const Upload = forwardRef(({ name, required = false, error, disabled = false, className = "", onFileSelect, multiple = true, accept = "image/*,video/*", tabs, existingFiles, ...props }, ref) => {
|
|
11
|
+
const [isDragOver, setIsDragOver] = useState(false);
|
|
12
|
+
const [activeTab, setActiveTab] = useState(tabs && tabs.length > 0 ? tabs[0].id : "photo1");
|
|
13
|
+
const fileInputRef = useRef(null);
|
|
14
|
+
const isMobile = useIsMobile();
|
|
15
|
+
const { selectedFiles, filePreviewUrls, existingFilesByTab, uploadedFiles, defaultTabs, validationError, addFiles, removeFile, markFilesAsUploaded, getUnuploadedFiles, getFileChanges, } = useFileUpload({
|
|
16
|
+
existingFiles,
|
|
17
|
+
uploadedFiles: props.uploadedFiles,
|
|
18
|
+
onFileSelect,
|
|
19
|
+
onUploadStatusChange: props.onUploadStatusChange,
|
|
20
|
+
});
|
|
21
|
+
const tabsToUse = tabs || defaultTabs;
|
|
22
|
+
const currentFiles = selectedFiles[activeTab] || [];
|
|
23
|
+
const currentPreviewUrls = filePreviewUrls[activeTab] || [];
|
|
24
|
+
const currentExistingFiles = existingFilesByTab[activeTab] || [];
|
|
25
|
+
const existingUrls = currentExistingFiles.map((file) => file.url);
|
|
26
|
+
const allPreviewUrls = currentFiles.length > 0 ? currentPreviewUrls : existingUrls;
|
|
27
|
+
const handleFileChange = (event) => {
|
|
28
|
+
const files = event.target.files;
|
|
29
|
+
if (files) {
|
|
30
|
+
const fileArray = Array.from(files);
|
|
31
|
+
addFiles(activeTab, fileArray);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const handleDragOver = (event) => {
|
|
35
|
+
event.preventDefault();
|
|
36
|
+
setIsDragOver(true);
|
|
37
|
+
};
|
|
38
|
+
const handleDragLeave = (event) => {
|
|
39
|
+
event.preventDefault();
|
|
40
|
+
setIsDragOver(false);
|
|
41
|
+
};
|
|
42
|
+
const handleDrop = (event) => {
|
|
43
|
+
event.preventDefault();
|
|
44
|
+
setIsDragOver(false);
|
|
45
|
+
const files = event.dataTransfer.files;
|
|
46
|
+
if (files && files.length > 0) {
|
|
47
|
+
const fileArray = Array.from(files);
|
|
48
|
+
addFiles(activeTab, fileArray);
|
|
49
|
+
if (fileInputRef.current) {
|
|
50
|
+
fileInputRef.current.files = files;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
const handleClick = () => {
|
|
55
|
+
fileInputRef.current?.click();
|
|
56
|
+
};
|
|
57
|
+
const handleRemoveFile = (indexToRemove) => {
|
|
58
|
+
removeFile(activeTab, indexToRemove);
|
|
59
|
+
};
|
|
60
|
+
// Expose methods via ref
|
|
61
|
+
React.useImperativeHandle(ref, () => ({
|
|
62
|
+
...fileInputRef.current,
|
|
63
|
+
markFilesAsUploaded,
|
|
64
|
+
getUnuploadedFiles,
|
|
65
|
+
getAllSelectedFiles: () => selectedFiles,
|
|
66
|
+
getUploadedFiles: () => uploadedFiles,
|
|
67
|
+
getFileChanges,
|
|
68
|
+
}));
|
|
69
|
+
return (_jsxs("div", { className: `w-full text-sm ${className} relative`, children: [_jsx(TabNavigation, { tabs: tabsToUse, activeTab: activeTab, onTabChange: setActiveTab, selectedFiles: selectedFiles, existingFilesByTab: existingFilesByTab }), isMobile ? (
|
|
70
|
+
// Mobile layout: Show preview full-width if media exists, otherwise show upload area
|
|
71
|
+
_jsx("div", { className: "w-full", children: allPreviewUrls.length > 0 ? (_jsx("div", { onClick: handleClick, className: "cursor-pointer", children: _jsx(PreviewArea, { allPreviewUrls: allPreviewUrls, currentFiles: currentFiles, currentExistingFiles: currentExistingFiles, currentPreviewUrls: currentPreviewUrls, uploadedFiles: uploadedFiles[activeTab] || [], onRemoveFile: handleRemoveFile, isVideoFile: isVideoFileGeneric }) })) : (_jsx(UploadArea, { isDragOver: isDragOver, error: error, disabled: disabled, currentFiles: currentFiles, activeTabLabel: tabsToUse.find((t) => t.id === activeTab)?.label || "", onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, onClick: handleClick })) })) : (
|
|
72
|
+
// Desktop layout: Show both side by side
|
|
73
|
+
_jsxs("div", { className: "flex gap-6", children: [_jsx(UploadArea, { isDragOver: isDragOver, error: error, disabled: disabled, currentFiles: currentFiles, activeTabLabel: tabsToUse.find((t) => t.id === activeTab)?.label || "", onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, onClick: handleClick }), _jsx(PreviewArea, { allPreviewUrls: allPreviewUrls, currentFiles: currentFiles, currentExistingFiles: currentExistingFiles, currentPreviewUrls: currentPreviewUrls, uploadedFiles: uploadedFiles[activeTab] || [], onRemoveFile: handleRemoveFile, isVideoFile: isVideoFileGeneric })] })), _jsx("input", { ref: fileInputRef, id: name, name: name, type: "file", required: required, disabled: disabled, multiple: multiple, accept: accept, onChange: handleFileChange, className: "sr-only", ...props }), (error || validationError) && (_jsx("p", { className: "mt-1 text-sm text-red-500", children: error || validationError }))] }));
|
|
74
|
+
});
|
|
75
|
+
Upload.displayName = "Upload";
|
|
76
|
+
export default Upload;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
interface UploadAreaProps {
|
|
3
|
+
isDragOver: boolean;
|
|
4
|
+
error?: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
currentFiles: File[];
|
|
7
|
+
activeTabLabel: string;
|
|
8
|
+
onDragOver: (event: React.DragEvent) => void;
|
|
9
|
+
onDragLeave: (event: React.DragEvent) => void;
|
|
10
|
+
onDrop: (event: React.DragEvent) => void;
|
|
11
|
+
onClick: () => void;
|
|
12
|
+
}
|
|
13
|
+
declare const UploadArea: React.FC<UploadAreaProps>;
|
|
14
|
+
export default UploadArea;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import UploadIcon from "../svg/UploadIcon";
|
|
4
|
+
const UploadArea = ({ isDragOver, error, disabled = false, currentFiles, activeTabLabel, onDragOver, onDragLeave, onDrop, onClick, }) => {
|
|
5
|
+
return (_jsx("div", { className: "flex-1", children: _jsxs("div", { className: `w-full h-25 sm:h-[220px] min-h-[160px] border border-dashed rounded-xl bg-gray-50 flex flex-col items-center justify-center cursor-pointer transition-colors ${isDragOver
|
|
6
|
+
? "border-blue-400 bg-blue-50"
|
|
7
|
+
: error
|
|
8
|
+
? "border-red-500"
|
|
9
|
+
: "border-gray-300 hover:border-gray-400 hover:bg-gray-100"} ${disabled ? "opacity-50 cursor-not-allowed" : ""}`, onDragOver: onDragOver, onDragLeave: onDragLeave, onDrop: onDrop, onClick: onClick, children: [_jsx(UploadIcon, { className: "w-12 h-12 text-gray-400 mb-4" }), _jsx("p", { className: "text-gray-500 text-center mb-2", children: currentFiles.length > 0
|
|
10
|
+
? `${currentFiles.length} file(s) selected for ${activeTabLabel}`
|
|
11
|
+
: `Drag and drop files here for ${activeTabLabel}, or click to select` }), _jsx("p", { className: "text-xs text-gray-400 text-center", children: "Supports images and videos" }), currentFiles.length > 0 && (_jsx("div", { className: "mt-4 w-full px-4", children: _jsxs("div", { className: "flex flex-wrap gap-2", children: [currentFiles.slice(0, 3).map((file, index) => (_jsx("span", { className: "px-2 py-1 bg-blue-100 text-blue-800 text-xs rounded-md truncate max-w-[120px]", children: file.name }, index))), currentFiles.length > 3 && (_jsxs("span", { className: "px-2 py-1 bg-gray-100 text-gray-600 text-xs rounded-md", children: ["+", currentFiles.length - 3, " more"] }))] }) }))] }) }));
|
|
12
|
+
};
|
|
13
|
+
export default UploadArea;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "className"> {
|
|
3
|
+
label?: string;
|
|
4
|
+
error?: string;
|
|
5
|
+
className?: string;
|
|
6
|
+
hideLabel?: boolean;
|
|
7
|
+
}
|
|
8
|
+
declare const _default: (props: InputProps & {
|
|
9
|
+
ref?: React.Ref<HTMLInputElement>;
|
|
10
|
+
}) => React.JSX.Element;
|
|
11
|
+
export default _default;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { forwardRef, useState } from "react";
|
|
4
|
+
const Input = forwardRef(({ label, name, type = "text", placeholder, required = false, error, disabled = false, autoFocus = false, className = "", hideLabel = false, ...props }, ref) => {
|
|
5
|
+
const [showPassword, setShowPassword] = useState(false);
|
|
6
|
+
const isPasswordType = type === "password";
|
|
7
|
+
const inputType = isPasswordType && showPassword ? "text" : type;
|
|
8
|
+
return (_jsxs("div", { className: `w-full text-sm ${className}`, children: [label && !hideLabel && (_jsx("label", { htmlFor: name, className: "block mb-2 text-xs text-gray-500", children: label })), _jsxs("div", { className: "relative", children: [_jsx("input", { ref: ref, id: name, name: name, type: inputType, placeholder: placeholder, required: required, disabled: disabled, autoFocus: autoFocus, autoComplete: "off", className: [
|
|
9
|
+
// Base styles (from former cb-input)
|
|
10
|
+
"w-full text-base h-13.5 sm:h-auto sm:text-xs p-0 px-3 sm:px-4 sm:p-4",
|
|
11
|
+
"border border-gray-200 rounded-xl bg-gray-50",
|
|
12
|
+
"focus:border-gray-300 focus:bg-white outline-none",
|
|
13
|
+
"placeholder-gray-300 text-black",
|
|
14
|
+
// Conditional states
|
|
15
|
+
error ? "border-red-500" : "",
|
|
16
|
+
isPasswordType ? "pr-12" : "",
|
|
17
|
+
]
|
|
18
|
+
.filter(Boolean)
|
|
19
|
+
.join(" "), ...props }), isPasswordType && (_jsx("button", { type: "button", onClick: () => setShowPassword(!showPassword), className: "absolute right-3 top-1/2 transform -translate-y-1/2 text-black hover:text-black", children: _jsxs("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: [showPassword ? (_jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.878 9.878L3 3m6.878 6.878L21 21" })) : (_jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z" })), !showPassword && (_jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" }))] }) }))] }), error && _jsx("p", { className: "mt-1 text-xs text-red-500", children: error })] }));
|
|
20
|
+
});
|
|
21
|
+
Input.displayName = "Input";
|
|
22
|
+
// Cast to a function component type to satisfy Next 15 + React 19 JSX typing
|
|
23
|
+
// while preserving the underlying forwardRef behavior at runtime.
|
|
24
|
+
export default Input;
|
|
@@ -1,2 +1,42 @@
|
|
|
1
1
|
export { default as Button } from "./button";
|
|
2
|
-
|
|
2
|
+
export { default as CircleBtn } from "./button/CircleBtn";
|
|
3
|
+
export { default as ShadowButton } from "./button/ShadowButton";
|
|
4
|
+
export { default as Modal } from "./core/Modal";
|
|
5
|
+
export { default as BottomSheet } from "./core/BottomSheet";
|
|
6
|
+
export { default as Input } from "./core/input";
|
|
7
|
+
export { default as Textarea } from "./core/Textarea";
|
|
8
|
+
export { default as OtpInput } from "./core/OtpInput";
|
|
9
|
+
export { default as NumberInput } from "./core/NumberInput";
|
|
10
|
+
export { default as NumberInputWithCommas } from "./core/NumberInputWithCommas";
|
|
11
|
+
export { default as SelectionList } from "./core/SelectionList";
|
|
12
|
+
export { default as Checkbox } from "./core/Checkbox";
|
|
13
|
+
export { default as SquareCheckbox } from "./core/SquareCheckbox";
|
|
14
|
+
export { default as AddressInput } from "./core/AddressInput";
|
|
15
|
+
export { default as Toggle } from "./core/Toggle";
|
|
16
|
+
export { default as Accordion } from "./core/Accordion";
|
|
17
|
+
export { default as Calendar } from "./core/Calendar";
|
|
18
|
+
export { default as CalendarExtended } from "./core/CalendarExtended";
|
|
19
|
+
export { default as OptionsDropdown } from "./core/OptionsDropdown";
|
|
20
|
+
export { default as CustomDropdown } from "./core/CustomDropdown";
|
|
21
|
+
export { default as Logo } from "./navigation/Logo";
|
|
22
|
+
export { default as Crestbase } from "./svg/Crestbase";
|
|
23
|
+
export { default as CrestbaseColored } from "./svg/CrestbaseColored";
|
|
24
|
+
export { default as GlobalNotificationProvider } from "./notification/GlobalNotificationProvider";
|
|
25
|
+
export { useNotificationStore } from "./notification/notificationStore";
|
|
26
|
+
export { default as Upload } from "./core/Upload";
|
|
27
|
+
export type { UploadProps, UploadRef } from "./core/Upload";
|
|
28
|
+
export type { AccordionProps } from "./core/Accordion";
|
|
29
|
+
export type { ToggleProps } from "./core/Toggle";
|
|
30
|
+
export type { CheckboxProps } from "./core/Checkbox";
|
|
31
|
+
export type { AddressInputProps } from "./core/AddressInput";
|
|
32
|
+
export type { InputProps } from "./core/input";
|
|
33
|
+
export type { TextareaProps } from "./core/Textarea";
|
|
34
|
+
export type { OtpInputProps } from "./core/OtpInput";
|
|
35
|
+
export type { NumberInputProps } from "./core/NumberInput";
|
|
36
|
+
export type { NumberInputWithCommasProps } from "./core/NumberInputWithCommas";
|
|
37
|
+
export type { SelectionOption, SelectionListProps } from "./core/SelectionList";
|
|
38
|
+
export type { OptionsDropdownProps, OptionItem } from "./core/OptionsDropdown";
|
|
39
|
+
export type { CustomDropdownProps, DropdownOption, } from "./core/CustomDropdown";
|
|
40
|
+
export type { LogoProps } from "./navigation/Logo";
|
|
41
|
+
export type { CrestbaseProps } from "./svg/Crestbase";
|
|
42
|
+
export type { CrestbaseColoredProps } from "./svg/CrestbaseColored";
|
package/dist/components/index.js
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
1
|
// Component index file | Barrel file
|
|
2
2
|
export { default as Button } from "./button";
|
|
3
|
-
|
|
3
|
+
export { default as CircleBtn } from "./button/CircleBtn";
|
|
4
|
+
export { default as ShadowButton } from "./button/ShadowButton";
|
|
5
|
+
export { default as Modal } from "./core/Modal";
|
|
6
|
+
export { default as BottomSheet } from "./core/BottomSheet";
|
|
7
|
+
export { default as Input } from "./core/input";
|
|
8
|
+
export { default as Textarea } from "./core/Textarea";
|
|
9
|
+
export { default as OtpInput } from "./core/OtpInput";
|
|
10
|
+
export { default as NumberInput } from "./core/NumberInput";
|
|
11
|
+
export { default as NumberInputWithCommas } from "./core/NumberInputWithCommas";
|
|
12
|
+
export { default as SelectionList } from "./core/SelectionList";
|
|
13
|
+
export { default as Checkbox } from "./core/Checkbox";
|
|
14
|
+
export { default as SquareCheckbox } from "./core/SquareCheckbox";
|
|
15
|
+
export { default as AddressInput } from "./core/AddressInput";
|
|
16
|
+
export { default as Toggle } from "./core/Toggle";
|
|
17
|
+
export { default as Accordion } from "./core/Accordion";
|
|
18
|
+
export { default as Calendar } from "./core/Calendar";
|
|
19
|
+
export { default as CalendarExtended } from "./core/CalendarExtended";
|
|
20
|
+
export { default as OptionsDropdown } from "./core/OptionsDropdown";
|
|
21
|
+
export { default as CustomDropdown } from "./core/CustomDropdown";
|
|
22
|
+
export { default as Logo } from "./navigation/Logo";
|
|
23
|
+
export { default as Crestbase } from "./svg/Crestbase";
|
|
24
|
+
export { default as CrestbaseColored } from "./svg/CrestbaseColored";
|
|
25
|
+
export { default as GlobalNotificationProvider } from "./notification/GlobalNotificationProvider";
|
|
26
|
+
export { useNotificationStore } from "./notification/notificationStore";
|
|
27
|
+
export { default as Upload } from "./core/Upload";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import CrestbaseColored from "../svg/CrestbaseColored";
|
|
3
|
+
import Crestbase from "../svg/Crestbase";
|
|
4
|
+
const Logo = ({ isCollapsed = false, useWhiteVariant = false, }) => {
|
|
5
|
+
return (_jsxs("div", { className: "flex items-center gap-2", children: [useWhiteVariant ? (_jsx(Crestbase, { className: "w-8 h-8" })) : (_jsx(CrestbaseColored, { className: "w-8 h-8" })), _jsx("span", { className: `text-lg font-bold ${useWhiteVariant ? "text-white" : "text-secondaryblue"} transition-opacity duration-300 ${isCollapsed ? "opacity-0 w-0 overflow-hidden" : "opacity-100"}`, children: "crestbase" })] }));
|
|
6
|
+
};
|
|
7
|
+
export default Logo;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import NotificationPopup from "./NotificationPopup";
|
|
4
|
+
export default function GlobalNotificationProvider({ children, }) {
|
|
5
|
+
return (_jsxs(_Fragment, { children: [_jsx(NotificationPopup, {}), children] }));
|
|
6
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function NotificationPopup(): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { AlertCircle, CheckCircle, Info, X } from "lucide-react";
|
|
5
|
+
import { useNotificationStore } from "./notificationStore";
|
|
6
|
+
const getIcon = (type) => {
|
|
7
|
+
switch (type) {
|
|
8
|
+
case "success":
|
|
9
|
+
return _jsx(CheckCircle, { className: "w-5 h-5 text-green-500" });
|
|
10
|
+
case "error":
|
|
11
|
+
return _jsx(AlertCircle, { className: "w-5 h-5 text-red-500" });
|
|
12
|
+
case "info":
|
|
13
|
+
return _jsx(Info, { className: "w-5 h-5 text-blue-500" });
|
|
14
|
+
default:
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const getBackgroundColor = (type) => {
|
|
19
|
+
switch (type) {
|
|
20
|
+
case "success":
|
|
21
|
+
return "bg-green-50 border-green-200";
|
|
22
|
+
case "error":
|
|
23
|
+
return "bg-red-50 border-red-200";
|
|
24
|
+
case "info":
|
|
25
|
+
return "bg-blue-50 border-blue-200";
|
|
26
|
+
default:
|
|
27
|
+
return "bg-gray-50 border-gray-200";
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
export default function NotificationPopup() {
|
|
31
|
+
const { notifications, removeNotification } = useNotificationStore();
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
// Auto-remove after duration (default 5000ms)
|
|
34
|
+
const timers = notifications.map((n) => setTimeout(() => removeNotification(n.id), n.duration ?? 5000));
|
|
35
|
+
return () => {
|
|
36
|
+
for (const t of timers)
|
|
37
|
+
clearTimeout(t);
|
|
38
|
+
};
|
|
39
|
+
}, [notifications, removeNotification]);
|
|
40
|
+
if (!notifications.length)
|
|
41
|
+
return null;
|
|
42
|
+
return (_jsx("div", { className: "fixed top-4 right-4 space-y-2", style: { zIndex: 2147483647 }, children: notifications.map((notification) => (_jsx(NotificationItemView, { notification: notification, onRemove: removeNotification }, notification.id))) }));
|
|
43
|
+
}
|
|
44
|
+
function NotificationItemView({ notification, onRemove, }) {
|
|
45
|
+
const [isVisible, setIsVisible] = useState(false);
|
|
46
|
+
const [isLeaving, setIsLeaving] = useState(false);
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
// Trigger entrance animation
|
|
49
|
+
const enterTimer = setTimeout(() => setIsVisible(true), 10);
|
|
50
|
+
// Auto-remove after duration
|
|
51
|
+
const duration = notification.duration ?? 5000;
|
|
52
|
+
const exitTimer = setTimeout(() => {
|
|
53
|
+
setIsLeaving(true);
|
|
54
|
+
setTimeout(() => onRemove(notification.id), 300);
|
|
55
|
+
}, duration);
|
|
56
|
+
return () => {
|
|
57
|
+
clearTimeout(enterTimer);
|
|
58
|
+
clearTimeout(exitTimer);
|
|
59
|
+
};
|
|
60
|
+
}, [notification.id, notification.duration, onRemove]);
|
|
61
|
+
const handleClose = () => {
|
|
62
|
+
setIsLeaving(true);
|
|
63
|
+
setTimeout(() => onRemove(notification.id), 300);
|
|
64
|
+
};
|
|
65
|
+
return (_jsx("div", { className: `
|
|
66
|
+
transform transition-all duration-300 ease-in-out
|
|
67
|
+
${isVisible && !isLeaving
|
|
68
|
+
? "translate-x-0 opacity-100"
|
|
69
|
+
: "translate-x-full opacity-0"}
|
|
70
|
+
${getBackgroundColor(notification.type)}
|
|
71
|
+
border rounded-xl shadow-lg p-4 min-w-80 max-w-96
|
|
72
|
+
`, children: _jsxs("div", { className: "flex items-start space-x-3", children: [getIcon(notification.type), _jsx("div", { className: "flex-1", children: _jsx("p", { className: "text-xs font-medium text-gray-900", children: notification.message }) }), _jsx("button", { onClick: handleClose, className: "flex-shrink-0 text-gray-400 hover:text-gray-600 transition-colors", "aria-label": "Close notification", children: _jsx(X, { className: "w-4 h-4" }) })] }) }));
|
|
73
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type NotificationType = "success" | "error" | "info";
|
|
2
|
+
export interface NotificationItem {
|
|
3
|
+
id: string;
|
|
4
|
+
type: NotificationType;
|
|
5
|
+
message: string;
|
|
6
|
+
duration?: number;
|
|
7
|
+
}
|
|
8
|
+
interface NotificationStoreState {
|
|
9
|
+
notifications: NotificationItem[];
|
|
10
|
+
addNotification: (item: Omit<NotificationItem, "id">) => string;
|
|
11
|
+
removeNotification: (id: string) => void;
|
|
12
|
+
clearAllNotifications: () => void;
|
|
13
|
+
}
|
|
14
|
+
export declare const useNotificationStore: import("zustand").UseBoundStore<import("zustand").StoreApi<NotificationStoreState>>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { create } from "zustand";
|
|
2
|
+
export const useNotificationStore = create((set, get) => ({
|
|
3
|
+
notifications: [],
|
|
4
|
+
addNotification: (item) => {
|
|
5
|
+
const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
6
|
+
const notif = { id, duration: 3500, ...item };
|
|
7
|
+
set((state) => ({ notifications: [notif, ...state.notifications] }));
|
|
8
|
+
return id;
|
|
9
|
+
},
|
|
10
|
+
removeNotification: (id) => set((state) => ({ notifications: state.notifications.filter((n) => n.id !== id) })),
|
|
11
|
+
clearAllNotifications: () => set({ notifications: [] }),
|
|
12
|
+
}));
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
const Crestbase = ({ className }) => {
|
|
3
|
+
return (_jsxs("svg", { className: className, viewBox: "0 0 30 28", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [_jsx("path", { d: "M17.8375 8.27314L11.2717 2.24259C10.5066 1.5399 9.33094 1.5399 8.56588 2.24259L2.64711 7.67879C2.23472 8.05756 2 8.59185 2 9.15178V24.2979C2 25.4025 2.89543 26.2979 4 26.2979H16.1161V26.2979C17.0668 26.2979 17.8375 25.5272 17.8375 24.5764V20.9221", stroke: "white", strokeWidth: "2.2", strokeLinecap: "round" }), _jsx("path", { d: "M16.5156 1.31641L22.0658 6.41408C22.4782 6.79285 22.7129 7.32714 22.7129 7.88707V26.2981", stroke: "white", strokeWidth: "2.2", strokeLinecap: "round" }), _jsx("path", { d: "M22.7109 1.31641L28.2611 6.41408C28.6735 6.79285 28.9082 7.32714 28.9082 7.88707V26.2981", stroke: "white", strokeWidth: "2.2", strokeLinecap: "round" }), _jsx("circle", { cx: "17.6004", cy: "14.9148", r: "2.10817", fill: "white" })] }));
|
|
4
|
+
};
|
|
5
|
+
export default Crestbase;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
const CrestbaseColored = ({ className }) => {
|
|
3
|
+
return (_jsxs("svg", { className: className, viewBox: "0 0 30 28", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [_jsx("path", { d: "M17.8375 8.27314L11.2717 2.24259C10.5066 1.5399 9.33094 1.5399 8.56588 2.24259L2.64711 7.67879C2.23472 8.05756 2 8.59185 2 9.15178V24.2979C2 25.4025 2.89543 26.2979 4 26.2979H16.1161V26.2979C17.0668 26.2979 17.8375 25.5272 17.8375 24.5764V20.9221", stroke: "#3D79EF", strokeWidth: "2.2", strokeLinecap: "round" }), _jsx("path", { d: "M16.5156 1.31641L22.0658 6.41408C22.4782 6.79285 22.7129 7.32714 22.7129 7.88707V26.2981", stroke: "url(#paint0_linear_4690_24705)", strokeWidth: "2.2", strokeLinecap: "round" }), _jsx("path", { d: "M22.7109 1.31641L28.2611 6.41408C28.6735 6.79285 28.9082 7.32714 28.9082 7.88707V26.2981", stroke: "url(#paint1_linear_4690_24705)", strokeWidth: "2.2", strokeLinecap: "round" }), _jsx("circle", { cx: "17.6004", cy: "14.9148", r: "2.10817", fill: "#3D79EF" }), _jsxs("defs", { children: [_jsxs("linearGradient", { id: "paint0_linear_4690_24705", x1: "19.6143", y1: "1.31641", x2: "19.6143", y2: "26.2981", gradientUnits: "userSpaceOnUse", children: [_jsx("stop", { stopColor: "#3D79EF" }), _jsx("stop", { offset: "1", stopColor: "#F1A5C2" })] }), _jsxs("linearGradient", { id: "paint1_linear_4690_24705", x1: "25.8096", y1: "1.31641", x2: "25.8096", y2: "26.2981", gradientUnits: "userSpaceOnUse", children: [_jsx("stop", { stopColor: "#3D79EF" }), _jsx("stop", { offset: "1", stopColor: "#F1A5C2" })] })] })] }));
|
|
4
|
+
};
|
|
5
|
+
export default CrestbaseColored;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
const UploadIcon = (props) => (_jsxs("svg", { viewBox: "0 0 51 46", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: [_jsx("path", { d: "M44.4387 15.7166V15.2293C44.3336 11.1044 42.5803 7.18813 39.5615 4.33536C36.5428 1.48259 32.5038 -0.0749428 28.3263 0.00277481C25.2151 -0.0222956 22.1628 0.841027 19.5368 2.48886C16.9108 4.13668 14.8229 6.4988 13.5244 9.29097C9.86834 9.69373 6.48915 11.4077 4.02789 14.1078C1.56663 16.8078 0.194521 20.3061 0.171875 23.9389C0.175918 25.8638 0.564094 27.769 1.31421 29.5456C2.06433 31.3223 3.16168 32.9355 4.54352 34.2931C5.92537 35.6506 7.56461 36.7259 9.36753 37.4574C11.1704 38.189 13.1017 38.5624 15.0508 38.5564H20.8328V35.5111H15.0508C12.0706 35.3518 9.26238 34.0828 7.19211 31.9597C5.12184 29.8367 3.94351 27.0176 3.89462 24.0706C3.84573 21.1236 4.92992 18.2679 6.92866 16.079C8.9274 13.8902 11.6921 12.531 14.6654 12.2754H15.6984L16.0531 11.3161C17.0093 8.86331 18.705 6.75953 20.911 5.28906C23.1169 3.81859 25.7268 3.05231 28.388 3.09376C31.7477 3.01581 35.0026 4.25245 37.443 6.53418C39.8835 8.81592 41.3118 11.9578 41.4167 15.275C41.4379 15.6808 41.4379 16.0874 41.4167 16.4931L41.2933 17.5894L42.2956 18.0462C44.2339 18.9086 45.8124 20.404 46.7653 22.2808C47.7183 24.1576 47.9876 26.3013 47.5279 28.3512C47.0683 30.401 45.9077 32.232 44.2415 33.536C42.5753 34.84 40.5051 35.5375 38.3792 35.5111H30.084V38.5564H38.3792C41.1214 38.5758 43.7919 37.6923 45.9688 36.0455C48.1457 34.3987 49.7049 32.0824 50.3999 29.4628C51.0949 26.8431 50.8861 24.0694 49.8066 21.58C48.727 19.0906 46.8383 17.0275 44.4387 15.7166Z", fill: "currentColor", fillOpacity: "0.3" }), _jsx("path", { d: "M28.3359 0.50293C32.3833 0.427725 36.2949 1.93706 39.2178 4.69922C42.0491 7.37485 43.73 11.0151 43.9248 14.8682L43.9385 15.2422V16.0127L44.1992 16.1553C46.5018 17.4133 48.3128 19.3929 49.3477 21.7793C50.3824 24.1656 50.5831 26.8242 49.917 29.335C49.2508 31.8457 47.7554 34.0666 45.667 35.6465C43.5783 37.2265 41.0154 38.0753 38.3828 38.0566H30.584V36.0107H38.3789V36.0098C40.6159 36.0362 42.795 35.303 44.5498 33.9297C46.3061 32.5551 47.5304 30.6242 48.0156 28.4609C48.5008 26.2974 48.2164 24.0349 47.2109 22.0547C46.2061 20.0756 44.5429 18.4997 42.502 17.5908H42.5029L41.8301 17.2842L41.9131 16.5488L41.915 16.5342L41.916 16.5195C41.9326 16.2022 41.937 15.884 41.9287 15.5664L41.916 15.249C41.8043 11.8017 40.3186 8.53847 37.7842 6.16895C35.2475 3.7974 31.8656 2.51278 28.376 2.59375C25.6208 2.55482 22.919 3.3498 20.6338 4.87305C18.3431 6.40002 16.5808 8.58561 15.5869 11.1348L15.584 11.1426L15.3496 11.7754H14.6436L14.6221 11.7773C11.5247 12.0437 8.64355 13.46 6.55957 15.7422C4.47538 18.0247 3.34351 21.0037 3.39453 24.0791C3.4456 27.1543 4.67543 30.0949 6.83398 32.3086C8.99253 34.5221 11.9197 35.8448 15.0244 36.0107H20.333V38.0566H15.0488C13.1647 38.0624 11.2981 37.7011 9.55566 36.9941C7.81306 36.2871 6.22854 35.2481 4.89355 33.9365C3.55868 32.6251 2.49872 31.067 1.77441 29.3516C1.05068 27.6374 0.676376 25.7991 0.671875 23.9424C0.693746 20.4339 2.0189 17.0537 4.39746 14.4443C6.77614 11.835 10.0431 10.1776 13.5791 9.78809L13.8594 9.75684L13.9775 9.50195C15.2351 6.79793 17.2579 4.50901 19.8027 2.91211C22.1886 1.41502 24.9382 0.585527 27.7578 0.507812L28.3223 0.50293H28.3359Z", stroke: "currentColor", strokeOpacity: "0.3" }), _jsx("path", { d: "M32.0542 29.1936C32.3618 29.1984 32.6638 29.1123 32.9214 28.9463C33.179 28.7803 33.3805 28.542 33.4998 28.262C33.6192 27.982 33.651 27.6732 33.5913 27.3752C33.5315 27.0772 33.3828 26.8037 33.1644 26.5898L25.4551 18.9766L17.7458 26.5898C17.4932 26.8811 17.3612 27.2558 17.3761 27.639C17.3911 28.0222 17.552 28.3858 17.8266 28.6569C18.1012 28.9281 18.4693 29.087 18.8574 29.1018C19.2454 29.1166 19.6248 28.9862 19.9198 28.7368L23.9132 24.854V43.5065C23.9132 43.9104 24.0756 44.2977 24.3648 44.5832C24.654 44.8688 25.0461 45.0292 25.4551 45.0292C25.864 45.0292 26.2562 44.8688 26.5453 44.5832C26.8345 44.2977 26.9969 43.9104 26.9969 43.5065V24.854L30.9595 28.7672C31.253 29.0467 31.6466 29.2 32.0542 29.1936Z", fill: "currentColor", fillOpacity: "0.3" }), _jsx("path", { d: "M32.8135 26.9453L32.8145 26.9473C32.9616 27.0913 33.0607 27.2747 33.1006 27.4736C33.1405 27.6724 33.1197 27.8783 33.04 28.0654C32.9602 28.2528 32.8246 28.4141 32.6504 28.5264C32.4763 28.6385 32.2715 28.6966 32.0625 28.6934H32.0459C31.8033 28.6971 31.5691 28.6177 31.3818 28.4717L31.3047 28.4053L27.3486 24.498L26.4971 23.6572V43.5068C26.497 43.7759 26.3889 44.0353 26.1943 44.2275C25.9994 44.42 25.7334 44.5293 25.4551 44.5293C25.1767 44.5293 24.9107 44.42 24.7158 44.2275C24.5213 44.0353 24.4132 43.7759 24.4131 43.5068V23.6709L23.5645 24.4951L19.5859 28.3633C19.3883 28.526 19.1354 28.6124 18.876 28.6025C18.6121 28.5924 18.3627 28.4835 18.1777 28.3008C17.993 28.1182 17.886 27.8745 17.876 27.6191C17.8662 27.3681 17.9501 27.121 18.1143 26.9268L25.4551 19.6787L32.8135 26.9453Z", stroke: "currentColor", strokeOpacity: "0.3" })] }));
|
|
4
|
+
export default UploadIcon;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface ExistingFile {
|
|
2
|
+
name: string;
|
|
3
|
+
url: string;
|
|
4
|
+
_id: string;
|
|
5
|
+
id: string;
|
|
6
|
+
}
|
|
7
|
+
export interface UseFileUploadProps {
|
|
8
|
+
existingFiles?: ExistingFile[];
|
|
9
|
+
uploadedFiles?: Record<string, string[]>;
|
|
10
|
+
onFileSelect?: (files: FileList | null, tabId?: string) => void;
|
|
11
|
+
onUploadStatusChange?: (tabId: string, uploadedFileNames: string[]) => void;
|
|
12
|
+
onError?: (message: string) => void;
|
|
13
|
+
}
|
|
14
|
+
export declare const useFileUpload: ({ existingFiles, uploadedFiles: initialUploadedFiles, onFileSelect, onUploadStatusChange, onError, }: UseFileUploadProps) => {
|
|
15
|
+
selectedFiles: Record<string, File[]>;
|
|
16
|
+
filePreviewUrls: Record<string, string[]>;
|
|
17
|
+
existingFilesByTab: Record<string, ExistingFile[]>;
|
|
18
|
+
uploadedFiles: Record<string, string[]>;
|
|
19
|
+
defaultTabs: {
|
|
20
|
+
id: string;
|
|
21
|
+
label: string;
|
|
22
|
+
}[];
|
|
23
|
+
validationError: string | undefined;
|
|
24
|
+
addFiles: (tabId: string, files: File[]) => void;
|
|
25
|
+
removeFile: (tabId: string, index: number) => void;
|
|
26
|
+
markFilesAsUploaded: (tabId: string, fileNames: string[]) => void;
|
|
27
|
+
getUnuploadedFiles: (tabId: string) => File[];
|
|
28
|
+
getFileChanges: () => {
|
|
29
|
+
newFiles: Record<string, File[]>;
|
|
30
|
+
existingFiles: Record<string, ExistingFile[]>;
|
|
31
|
+
removedFiles: Record<string, ExistingFile[]>;
|
|
32
|
+
};
|
|
33
|
+
clearAllFiles: () => void;
|
|
34
|
+
updateExistingFiles: (files: ExistingFile[]) => void;
|
|
35
|
+
};
|