@appcorp/shadcn 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/app-sidebar.js +1 -34
- package/components/audio.js +1 -13
- package/components/dashboard.js +1 -29
- package/components/drawer-generic.js +1 -39
- package/components/enhanced-checkbox.js +1 -39
- package/components/enhanced-combobox.js +1 -271
- package/components/enhanced-drawer-footer.js +1 -30
- package/components/enhanced-drawer-header.js +1 -7
- package/components/enhanced-dropzone-impl.js +1 -218
- package/components/enhanced-dropzone.js +1 -8
- package/components/enhanced-input.js +1 -40
- package/components/enhanced-label.js +1 -22
- package/components/enhanced-radio.js +1 -15
- package/components/enhanced-select.js +1 -33
- package/components/enhanced-slider.js +1 -33
- package/components/enhanced-switch.js +1 -42
- package/components/enhanced-table-footer-action.js +1 -102
- package/components/enhanced-table-footer-page.js +1 -124
- package/components/enhanced-table-footer-pagination.js +1 -108
- package/components/enhanced-table-header-action.js +1 -32
- package/components/enhanced-table-header-search.js +1 -10
- package/components/enhanced-table.js +1 -301
- package/components/enhanced-textarea.js +1 -40
- package/components/field.js +1 -96
- package/components/image-resize-dialog.js +1 -82
- package/components/nav-main.js +1 -40
- package/components/nav-projects.js +1 -39
- package/components/nav-user.js +1 -52
- package/components/show-toast.js +1 -7
- package/components/sidebar.js +1 -257
- package/components/team-switcher.js +1 -42
- package/components/theme-provider.js +1 -112
- package/components/timeline.js +1 -13
- package/components/tooltip.js +1 -36
- package/components/ui/accordion.js +1 -37
- package/components/ui/alert-dialog.js +1 -63
- package/components/ui/alert.js +1 -41
- package/components/ui/area-chart-v1-impl.js +1 -75
- package/components/ui/area-chart-v1.js +1 -5
- package/components/ui/aspect-ratio.js +1 -4
- package/components/ui/avatar.js +1 -31
- package/components/ui/badge.js +1 -32
- package/components/ui/breadcrumb.js +1 -54
- package/components/ui/button.js +1 -44
- package/components/ui/calendar-impl.js +1 -55
- package/components/ui/calendar.js +1 -6
- package/components/ui/card.js +1 -44
- package/components/ui/carousel-impl.js +1 -117
- package/components/ui/carousel.js +1 -9
- package/components/ui/chart-impl.js +6 -161
- package/components/ui/chart.js +1 -10
- package/components/ui/checkbox.js +1 -24
- package/components/ui/collapsible.js +1 -6
- package/components/ui/combobox.js +1 -52
- package/components/ui/command-impl.js +1 -63
- package/components/ui/command.js +1 -13
- package/components/ui/context-menu.js +1 -80
- package/components/ui/dialog.js +1 -57
- package/components/ui/drawer-impl.js +1 -56
- package/components/ui/drawer.js +1 -14
- package/components/ui/dropdown-menu.js +1 -82
- package/components/ui/form.d.ts +1 -1
- package/components/ui/form.js +1 -78
- package/components/ui/hover-card.js +1 -23
- package/components/ui/input-otp-impl.js +1 -43
- package/components/ui/input-otp.js +1 -8
- package/components/ui/input.js +1 -19
- package/components/ui/label.js +1 -23
- package/components/ui/language-selector.js +1 -25
- package/components/ui/menubar.js +1 -103
- package/components/ui/navigation-menu.js +1 -59
- package/components/ui/pagination.js +1 -60
- package/components/ui/popover.js +1 -25
- package/components/ui/progress.js +1 -22
- package/components/ui/radio-group.js +1 -29
- package/components/ui/resizable-impl.js +1 -27
- package/components/ui/resizable.js +1 -7
- package/components/ui/scroll-area.js +1 -32
- package/components/ui/select.js +1 -71
- package/components/ui/separator.js +1 -21
- package/components/ui/sheet.js +1 -71
- package/components/ui/skeleton.js +1 -18
- package/components/ui/slider.js +1 -32
- package/components/ui/sonner.js +1 -28
- package/components/ui/switch.js +1 -22
- package/components/ui/table.js +1 -55
- package/components/ui/tabs.js +1 -32
- package/components/ui/textarea.js +1 -19
- package/components/ui/theme-switcher.js +1 -102
- package/components/ui/toggle.js +1 -39
- package/data/admin-dashboard.js +1 -301
- package/hooks/use-enhanced-combobox.js +1 -73
- package/hooks/use-mobile.js +1 -15
- package/hooks/use-outside-click.js +1 -19
- package/lib/themes.js +1 -147
- package/lib/toast-utils.js +1 -170
- package/lib/utils.js +1 -5
- package/package.json +2 -2
- package/utils/transform-breadcrumbs.js +1 -7
- package/utils/transform-navitems.js +1 -18
|
@@ -1,218 +1 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
3
|
-
import { useDropzone } from "react-dropzone";
|
|
4
|
-
import { cn } from "../lib/utils";
|
|
5
|
-
import { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext, } from "./ui/carousel";
|
|
6
|
-
import { Button } from "./ui/button";
|
|
7
|
-
import { ImageResizeDialog } from "./image-resize-dialog";
|
|
8
|
-
import { XIcon } from "lucide-react";
|
|
9
|
-
export const EnhancedDropzone = ({ id, label, info, error, accept, maxFiles = 10, maxSize, minSize, disabled, value = [], onChange, onRemoveRemote, resize = false, className, testIdDropzone, testIdInput, testIdPrev, testIdNext, testIdPreviewPrefix, testIdImagePrefix, testIdRemovePrefix, testIdCount, testIdEmptyIcon, testIdEmptyTitle, testIdEmptySubtitle, testIdEmptyNote, testIdMessage, }) => {
|
|
10
|
-
const [localFiles, setLocalFiles] = useState([]);
|
|
11
|
-
const localPreviewsRef = useRef(new Map());
|
|
12
|
-
const [resizeDialogOpen, setResizeDialogOpen] = useState(false);
|
|
13
|
-
const [pendingFile, setPendingFile] = useState(null);
|
|
14
|
-
const [pendingFileUrl, setPendingFileUrl] = useState("");
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
const map = localPreviewsRef.current;
|
|
17
|
-
localFiles.forEach((file) => {
|
|
18
|
-
if (!map.has(file)) {
|
|
19
|
-
try {
|
|
20
|
-
const url = URL.createObjectURL(file);
|
|
21
|
-
map.set(file, url);
|
|
22
|
-
}
|
|
23
|
-
catch (error) {
|
|
24
|
-
console.error("Failed to create object URL:", error);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
const currentFiles = new Set(localFiles);
|
|
29
|
-
Array.from(map.entries()).forEach(([file, url]) => {
|
|
30
|
-
if (!currentFiles.has(file)) {
|
|
31
|
-
URL.revokeObjectURL(url);
|
|
32
|
-
map.delete(file);
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
}, [localFiles]);
|
|
36
|
-
useEffect(() => {
|
|
37
|
-
const map = localPreviewsRef.current;
|
|
38
|
-
return () => {
|
|
39
|
-
Array.from(map.values()).forEach((url) => {
|
|
40
|
-
URL.revokeObjectURL(url);
|
|
41
|
-
});
|
|
42
|
-
map.clear();
|
|
43
|
-
};
|
|
44
|
-
}, []);
|
|
45
|
-
useEffect(() => {
|
|
46
|
-
return () => {
|
|
47
|
-
if (pendingFileUrl) {
|
|
48
|
-
URL.revokeObjectURL(pendingFileUrl);
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
}, [pendingFileUrl]);
|
|
52
|
-
const isImageOnly = React.useMemo(() => {
|
|
53
|
-
if (!accept)
|
|
54
|
-
return false;
|
|
55
|
-
const acceptTypes = Array.isArray(accept)
|
|
56
|
-
? accept
|
|
57
|
-
: Object.keys(accept || {});
|
|
58
|
-
return acceptTypes.some((type) => typeof type === "string" && type.toLowerCase().includes("image"));
|
|
59
|
-
}, [accept]);
|
|
60
|
-
const normalizedAccept = React.useMemo(() => {
|
|
61
|
-
if (!accept)
|
|
62
|
-
return undefined;
|
|
63
|
-
if (Array.isArray(accept)) {
|
|
64
|
-
return accept.reduce((acc, type) => {
|
|
65
|
-
acc[type] = [];
|
|
66
|
-
return acc;
|
|
67
|
-
}, {});
|
|
68
|
-
}
|
|
69
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
70
|
-
return accept;
|
|
71
|
-
}, [accept]);
|
|
72
|
-
const dropzoneOptions = {
|
|
73
|
-
accept: normalizedAccept,
|
|
74
|
-
maxFiles,
|
|
75
|
-
maxSize,
|
|
76
|
-
minSize,
|
|
77
|
-
disabled,
|
|
78
|
-
onDrop: useCallback((acceptedFiles) => {
|
|
79
|
-
if (resize && acceptedFiles.length > 0) {
|
|
80
|
-
const file = acceptedFiles[0];
|
|
81
|
-
const url = URL.createObjectURL(file);
|
|
82
|
-
setPendingFile(file);
|
|
83
|
-
setPendingFileUrl(url);
|
|
84
|
-
setResizeDialogOpen(true);
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
setLocalFiles((prev) => {
|
|
88
|
-
const combined = [...prev, ...acceptedFiles];
|
|
89
|
-
const limited = maxFiles ? combined.slice(0, maxFiles) : combined;
|
|
90
|
-
onChange === null || onChange === void 0 ? void 0 : onChange(limited);
|
|
91
|
-
return limited;
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
}, [maxFiles, onChange, resize]),
|
|
95
|
-
};
|
|
96
|
-
const { getRootProps, getInputProps, isDragActive } = useDropzone(dropzoneOptions);
|
|
97
|
-
const handleRemoveRemote = useCallback((url) => {
|
|
98
|
-
onRemoveRemote === null || onRemoveRemote === void 0 ? void 0 : onRemoveRemote(url);
|
|
99
|
-
}, [onRemoveRemote]);
|
|
100
|
-
const handleRemoveLocal = useCallback((index) => {
|
|
101
|
-
setLocalFiles((prev) => {
|
|
102
|
-
const updated = prev.filter((_, i) => i !== index);
|
|
103
|
-
onChange === null || onChange === void 0 ? void 0 : onChange(updated);
|
|
104
|
-
return updated;
|
|
105
|
-
});
|
|
106
|
-
}, [onChange]);
|
|
107
|
-
const handleCropComplete = useCallback((croppedImage) => {
|
|
108
|
-
setLocalFiles((prev) => {
|
|
109
|
-
const combined = [...prev, croppedImage];
|
|
110
|
-
const limited = maxFiles ? combined.slice(0, maxFiles) : combined;
|
|
111
|
-
onChange === null || onChange === void 0 ? void 0 : onChange(limited);
|
|
112
|
-
return limited;
|
|
113
|
-
});
|
|
114
|
-
}, [maxFiles, onChange]);
|
|
115
|
-
const handleResizeDialogClose = useCallback(() => {
|
|
116
|
-
setResizeDialogOpen(false);
|
|
117
|
-
setPendingFileUrl("");
|
|
118
|
-
setPendingFile(null);
|
|
119
|
-
}, []);
|
|
120
|
-
const allPreviews = [
|
|
121
|
-
...value.map((url) => ({ type: "remote", url, index: 0 })),
|
|
122
|
-
...localFiles.map((file, index) => ({
|
|
123
|
-
type: "local",
|
|
124
|
-
url: localPreviewsRef.current.get(file) || "",
|
|
125
|
-
index,
|
|
126
|
-
})),
|
|
127
|
-
];
|
|
128
|
-
const formatBytes = (bytes) => {
|
|
129
|
-
if (bytes === 0)
|
|
130
|
-
return "0 B";
|
|
131
|
-
const k = 1024;
|
|
132
|
-
const sizes = ["B", "KB", "MB", "GB"];
|
|
133
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
134
|
-
return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + " " + sizes[i];
|
|
135
|
-
};
|
|
136
|
-
const getConstraintText = () => {
|
|
137
|
-
const constraints = [];
|
|
138
|
-
if (maxFiles && maxFiles > 1) {
|
|
139
|
-
constraints.push(`Up to ${maxFiles} files`);
|
|
140
|
-
}
|
|
141
|
-
if (minSize || maxSize) {
|
|
142
|
-
const sizes = [];
|
|
143
|
-
if (minSize)
|
|
144
|
-
sizes.push(`min ${formatBytes(minSize)}`);
|
|
145
|
-
if (maxSize)
|
|
146
|
-
sizes.push(`max ${formatBytes(maxSize)}`);
|
|
147
|
-
constraints.push(`${sizes.join(", ")}`);
|
|
148
|
-
}
|
|
149
|
-
return constraints.join(" • ");
|
|
150
|
-
};
|
|
151
|
-
return (React.createElement("div", { className: cn("w-full", className), "data-slot": "enhanced-dropzone", "data-testid": testIdDropzone },
|
|
152
|
-
label && (React.createElement("label", { className: "mb-2 block text-sm font-medium" }, label)),
|
|
153
|
-
React.createElement("div", Object.assign({}, getRootProps(), { className: cn("relative w-full rounded-md border border-dashed p-6 text-center min-h-70 flex items-center justify-center", isDragActive && "ring-2 ring-ring ring-offset-2", disabled && "opacity-60 pointer-events-none") }),
|
|
154
|
-
React.createElement("input", Object.assign({}, getInputProps(), { id: id, "data-testid": testIdInput })),
|
|
155
|
-
isImageOnly && allPreviews.length > 0 ? (React.createElement("div", { className: "flex flex-col items-center w-full" },
|
|
156
|
-
React.createElement("div", { className: "relative w-full max-w-md" },
|
|
157
|
-
React.createElement(Carousel, { className: "w-full" },
|
|
158
|
-
React.createElement(CarouselPrevious, { type: "button", onClick: (e) => e.stopPropagation(), onPointerDown: (e) => e.stopPropagation(), onMouseDown: (e) => e.stopPropagation(), "data-testid": testIdPrev }),
|
|
159
|
-
React.createElement(CarouselNext, { type: "button", onClick: (e) => e.stopPropagation(), onPointerDown: (e) => e.stopPropagation(), onMouseDown: (e) => e.stopPropagation(), "data-testid": testIdNext }),
|
|
160
|
-
React.createElement(CarouselContent, { className: "ml-0" }, allPreviews.map((preview, idx) => (React.createElement(CarouselItem, { key: `${preview.type}-${preview.url}-${idx}`, className: "pl-4", "data-testid": `${testIdPreviewPrefix !== null && testIdPreviewPrefix !== void 0 ? testIdPreviewPrefix : "dropzone-preview"}-${idx}` },
|
|
161
|
-
React.createElement("div", { className: "relative aspect-square w-full max-w-xs mx-auto" }, preview.url ? (React.createElement(React.Fragment, null,
|
|
162
|
-
React.createElement("img", { src: preview.url, alt: `Preview ${idx + 1}`, className: "h-full w-full rounded-lg object-cover", onClick: (e) => e.stopPropagation(), "data-testid": `${testIdImagePrefix !== null && testIdImagePrefix !== void 0 ? testIdImagePrefix : "dropzone-image"}-${idx}` }),
|
|
163
|
-
React.createElement(Button, { type: "button", size: "icon", variant: "destructive", onClick: (e) => {
|
|
164
|
-
e.stopPropagation();
|
|
165
|
-
if (preview.type === "remote") {
|
|
166
|
-
handleRemoveRemote(preview.url);
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
handleRemoveLocal(preview.index);
|
|
170
|
-
}
|
|
171
|
-
}, className: "absolute right-2 top-2 h-8 w-8 rounded-full", "aria-label": "Remove image", "data-testid": `${testIdRemovePrefix !== null && testIdRemovePrefix !== void 0 ? testIdRemovePrefix : "dropzone-remove"}-${idx}` },
|
|
172
|
-
React.createElement(XIcon, { className: "h-4 w-4" })))) : (React.createElement("div", { className: "flex h-full w-full items-center justify-center rounded-lg bg-muted text-muted-foreground" },
|
|
173
|
-
React.createElement("span", { className: "text-sm" }, "Loading...")))))))))),
|
|
174
|
-
React.createElement("p", { className: "mt-4 text-sm font-medium text-muted-foreground", "data-testid": testIdCount },
|
|
175
|
-
allPreviews.length,
|
|
176
|
-
" image",
|
|
177
|
-
allPreviews.length !== 1 ? "s" : "",
|
|
178
|
-
" ",
|
|
179
|
-
"selected"))) : !isImageOnly && allPreviews.length > 0 ? (React.createElement("div", { className: "flex flex-col items-center w-full gap-4" },
|
|
180
|
-
React.createElement("div", { className: "w-full max-w-md" },
|
|
181
|
-
React.createElement("div", { className: "space-y-2" }, allPreviews.map((preview, idx) => {
|
|
182
|
-
var _a;
|
|
183
|
-
return (React.createElement("div", { key: `${preview.type}-${preview.url}-${idx}`, "data-testid": `${testIdPreviewPrefix !== null && testIdPreviewPrefix !== void 0 ? testIdPreviewPrefix : "dropzone-preview"}-${idx}`, className: "flex items-center justify-between gap-3 p-3 rounded-lg border bg-muted/50" },
|
|
184
|
-
React.createElement("span", { className: "text-sm truncate flex-1", "data-testid": `${testIdImagePrefix !== null && testIdImagePrefix !== void 0 ? testIdImagePrefix : "dropzone-image"}-${idx}` }, preview.type === "remote"
|
|
185
|
-
? new URL(preview.url).pathname.split("/").pop() ||
|
|
186
|
-
"File"
|
|
187
|
-
: ((_a = localFiles[preview.index]) === null || _a === void 0 ? void 0 : _a.name) || "File"),
|
|
188
|
-
React.createElement(Button, { type: "button", size: "icon", variant: "ghost", onClick: (e) => {
|
|
189
|
-
e.stopPropagation();
|
|
190
|
-
if (preview.type === "remote") {
|
|
191
|
-
handleRemoveRemote(preview.url);
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
handleRemoveLocal(preview.index);
|
|
195
|
-
}
|
|
196
|
-
}, className: "h-8 w-8 shrink-0", "aria-label": "Remove file", "data-testid": `${testIdRemovePrefix !== null && testIdRemovePrefix !== void 0 ? testIdRemovePrefix : "dropzone-remove"}-${idx}` },
|
|
197
|
-
React.createElement(XIcon, { className: "h-4 w-4" }))));
|
|
198
|
-
}))),
|
|
199
|
-
React.createElement("p", { className: "text-sm font-medium text-muted-foreground", "data-testid": testIdCount },
|
|
200
|
-
allPreviews.length,
|
|
201
|
-
" file",
|
|
202
|
-
allPreviews.length !== 1 ? "s" : "",
|
|
203
|
-
" ",
|
|
204
|
-
"selected"))) : (React.createElement("div", { className: "flex flex-col items-center justify-center gap-2" },
|
|
205
|
-
React.createElement("div", { className: "flex h-12 w-12 items-center justify-center rounded-lg bg-muted text-muted-foreground", "data-testid": testIdEmptyIcon },
|
|
206
|
-
React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "lucide lucide-image" },
|
|
207
|
-
React.createElement("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2" }),
|
|
208
|
-
React.createElement("circle", { cx: "9", cy: "9", r: "2" }),
|
|
209
|
-
React.createElement("path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" }))),
|
|
210
|
-
React.createElement("div", { className: "space-y-1 text-center" },
|
|
211
|
-
React.createElement("p", { className: "font-medium text-sm", "data-testid": testIdEmptyTitle }, maxFiles === 1
|
|
212
|
-
? `Upload ${isImageOnly ? "an image" : "a file"}`
|
|
213
|
-
: `Upload ${isImageOnly ? "images" : "files"}`),
|
|
214
|
-
React.createElement("p", { className: "text-muted-foreground text-xs", "data-testid": testIdEmptySubtitle }, "Drag and drop or click to browse"),
|
|
215
|
-
(maxFiles > 1 || minSize || maxSize) && (React.createElement("p", { className: "text-muted-foreground text-xs", "data-testid": testIdEmptyNote }, getConstraintText())))))),
|
|
216
|
-
(error || info) && (React.createElement("div", { className: "mt-2", "data-testid": testIdMessage }, error ? (React.createElement("p", { className: "text-xs text-destructive" }, error)) : info ? (React.createElement("p", { className: "text-xs text-blue-600 dark:text-blue-400" }, info)) : null)),
|
|
217
|
-
resize && pendingFile && (React.createElement(ImageResizeDialog, { open: resizeDialogOpen, onClose: handleResizeDialogClose, imageUrl: pendingFileUrl, onCropComplete: handleCropComplete, fileName: pendingFile.name }))));
|
|
218
|
-
};
|
|
1
|
+
"use strict";"use client";import t,{useCallback as g,useEffect as L,useRef as re,useState as v}from"react";import{useDropzone as se}from"react-dropzone";import{cn as B}from"../lib/utils";import{Carousel as ce,CarouselContent as ie,CarouselItem as me,CarouselPrevious as ue,CarouselNext as de}from"./ui/carousel";import{Button as T}from"./ui/button";import{ImageResizeDialog as pe}from"./image-resize-dialog";import{XIcon as _}from"lucide-react";export const EnhancedDropzone=({id:q,label:j,info:y,error:b,accept:s,maxFiles:n=10,maxSize:d,minSize:p,disabled:U,value:G=[],onChange:r,onRemoveRemote:E,resize:$=!1,className:K,testIdDropzone:W,testIdInput:X,testIdPrev:H,testIdNext:J,testIdPreviewPrefix:i,testIdImagePrefix:m,testIdRemovePrefix:u,testIdCount:x,testIdEmptyIcon:Q,testIdEmptyTitle:V,testIdEmptySubtitle:Y,testIdEmptyNote:Z,testIdMessage:P})=>{const[f,w]=v([]),k=re(new Map),[F,D]=v(!1),[R,O]=v(null),[h,M]=v("");L(()=>{const e=k.current;f.forEach(a=>{if(!e.has(a))try{const o=URL.createObjectURL(a);e.set(a,o)}catch(o){console.error("Failed to create object URL:",o)}});const l=new Set(f);Array.from(e.entries()).forEach(([a,o])=>{l.has(a)||(URL.revokeObjectURL(o),e.delete(a))})},[f]),L(()=>{const e=k.current;return()=>{Array.from(e.values()).forEach(l=>{URL.revokeObjectURL(l)}),e.clear()}},[]),L(()=>()=>{h&&URL.revokeObjectURL(h)},[h]);const N=t.useMemo(()=>s?(Array.isArray(s)?s:Object.keys(s||{})).some(l=>typeof l=="string"&&l.toLowerCase().includes("image")):!1,[s]),S={accept:t.useMemo(()=>{if(s)return Array.isArray(s)?s.reduce((e,l)=>(e[l]=[],e),{}):s},[s]),maxFiles:n,maxSize:d,minSize:p,disabled:U,onDrop:g(e=>{if($&&e.length>0){const l=e[0],a=URL.createObjectURL(l);O(l),M(a),D(!0)}else w(l=>{const a=[...l,...e],o=n?a.slice(0,n):a;return r?.(o),o})},[n,r,$])},{getRootProps:I,getInputProps:ee,isDragActive:te}=se(S),z=g(e=>{E?.(e)},[E]),A=g(e=>{w(l=>{const a=l.filter((o,ne)=>ne!==e);return r?.(a),a})},[r]),le=g(e=>{w(l=>{const a=[...l,e],o=n?a.slice(0,n):a;return r?.(o),o})},[n,r]),ae=g(()=>{D(!1),M(""),O(null)},[]),c=[...G.map(e=>({type:"remote",url:e,index:0})),...f.map((e,l)=>({type:"local",url:k.current.get(e)||"",index:l}))],C=e=>{if(e===0)return"0 B";const l=1024,a=["B","KB","MB","GB"],o=Math.floor(Math.log(e)/Math.log(l));return Math.round(e/Math.pow(l,o)*100)/100+" "+a[o]},oe=()=>{const e=[];if(n&&n>1&&e.push(`Up to ${n} files`),p||d){const l=[];p&&l.push(`min ${C(p)}`),d&&l.push(`max ${C(d)}`),e.push(`${l.join(", ")}`)}return e.join(" \u2022 ")};return t.createElement("div",{className:B("w-full",K),"data-slot":"enhanced-dropzone","data-testid":W},j&&t.createElement("label",{className:"mb-2 block text-sm font-medium"},j),t.createElement("div",Object.assign({},I(),{className:B("relative w-full rounded-md border border-dashed p-6 text-center min-h-70 flex items-center justify-center",te&&"ring-2 ring-ring ring-offset-2",U&&"opacity-60 pointer-events-none")}),t.createElement("input",Object.assign({},ee(),{id:q,"data-testid":X})),N&&c.length>0?t.createElement("div",{className:"flex flex-col items-center w-full"},t.createElement("div",{className:"relative w-full max-w-md"},t.createElement(ce,{className:"w-full"},t.createElement(ue,{type:"button",onClick:e=>e.stopPropagation(),onPointerDown:e=>e.stopPropagation(),onMouseDown:e=>e.stopPropagation(),"data-testid":H}),t.createElement(de,{type:"button",onClick:e=>e.stopPropagation(),onPointerDown:e=>e.stopPropagation(),onMouseDown:e=>e.stopPropagation(),"data-testid":J}),t.createElement(ie,{className:"ml-0"},c.map((e,l)=>t.createElement(me,{key:`${e.type}-${e.url}-${l}`,className:"pl-4","data-testid":`${i??"dropzone-preview"}-${l}`},t.createElement("div",{className:"relative aspect-square w-full max-w-xs mx-auto"},e.url?t.createElement(t.Fragment,null,t.createElement("img",{src:e.url,alt:`Preview ${l+1}`,className:"h-full w-full rounded-lg object-cover",onClick:a=>a.stopPropagation(),"data-testid":`${m??"dropzone-image"}-${l}`}),t.createElement(T,{type:"button",size:"icon",variant:"destructive",onClick:a=>{a.stopPropagation(),e.type==="remote"?z(e.url):A(e.index)},className:"absolute right-2 top-2 h-8 w-8 rounded-full","aria-label":"Remove image","data-testid":`${u??"dropzone-remove"}-${l}`},t.createElement(_,{className:"h-4 w-4"}))):t.createElement("div",{className:"flex h-full w-full items-center justify-center rounded-lg bg-muted text-muted-foreground"},t.createElement("span",{className:"text-sm"},"Loading...")))))))),t.createElement("p",{className:"mt-4 text-sm font-medium text-muted-foreground","data-testid":x},c.length," image",c.length!==1?"s":""," ","selected")):!N&&c.length>0?t.createElement("div",{className:"flex flex-col items-center w-full gap-4"},t.createElement("div",{className:"w-full max-w-md"},t.createElement("div",{className:"space-y-2"},c.map((e,l)=>{var a;return t.createElement("div",{key:`${e.type}-${e.url}-${l}`,"data-testid":`${i??"dropzone-preview"}-${l}`,className:"flex items-center justify-between gap-3 p-3 rounded-lg border bg-muted/50"},t.createElement("span",{className:"text-sm truncate flex-1","data-testid":`${m??"dropzone-image"}-${l}`},e.type==="remote"?new URL(e.url).pathname.split("/").pop()||"File":((a=f[e.index])===null||a===void 0?void 0:a.name)||"File"),t.createElement(T,{type:"button",size:"icon",variant:"ghost",onClick:o=>{o.stopPropagation(),e.type==="remote"?z(e.url):A(e.index)},className:"h-8 w-8 shrink-0","aria-label":"Remove file","data-testid":`${u??"dropzone-remove"}-${l}`},t.createElement(_,{className:"h-4 w-4"})))}))),t.createElement("p",{className:"text-sm font-medium text-muted-foreground","data-testid":x},c.length," file",c.length!==1?"s":""," ","selected")):t.createElement("div",{className:"flex flex-col items-center justify-center gap-2"},t.createElement("div",{className:"flex h-12 w-12 items-center justify-center rounded-lg bg-muted text-muted-foreground","data-testid":Q},t.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"lucide lucide-image"},t.createElement("rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}),t.createElement("circle",{cx:"9",cy:"9",r:"2"}),t.createElement("path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"}))),t.createElement("div",{className:"space-y-1 text-center"},t.createElement("p",{className:"font-medium text-sm","data-testid":V},n===1?`Upload ${N?"an image":"a file"}`:`Upload ${N?"images":"files"}`),t.createElement("p",{className:"text-muted-foreground text-xs","data-testid":Y},"Drag and drop or click to browse"),(n>1||p||d)&&t.createElement("p",{className:"text-muted-foreground text-xs","data-testid":Z},oe())))),(b||y)&&t.createElement("div",{className:"mt-2","data-testid":P},b?t.createElement("p",{className:"text-xs text-destructive"},b):y?t.createElement("p",{className:"text-xs text-blue-600 dark:text-blue-400"},y):null),$&&R&&t.createElement(pe,{open:F,onClose:ae,imageUrl:h,onCropComplete:le,fileName:R.name}))};
|
|
@@ -1,8 +1 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import React, { Suspense } from "react";
|
|
3
|
-
const DropzoneImpl = React.lazy(() => import("./enhanced-dropzone-impl").then((m) => ({ default: m.EnhancedDropzone })));
|
|
4
|
-
export const EnhancedDropzone = (props) => {
|
|
5
|
-
return (React.createElement(Suspense, { fallback: React.createElement("div", { className: "w-full min-h-70 rounded-md border border-dashed p-6 text-center flex items-center justify-center" },
|
|
6
|
-
React.createElement("p", { className: "text-sm text-muted-foreground" }, "Loading dropzone...")) },
|
|
7
|
-
React.createElement(DropzoneImpl, Object.assign({}, props))));
|
|
8
|
-
};
|
|
1
|
+
"use strict";"use client";import e,{Suspense as n}from"react";const r=e.lazy(()=>import("./enhanced-dropzone-impl").then(t=>({default:t.EnhancedDropzone})));export const EnhancedDropzone=t=>e.createElement(n,{fallback:e.createElement("div",{className:"w-full min-h-70 rounded-md border border-dashed p-6 text-center flex items-center justify-center"},e.createElement("p",{className:"text-sm text-muted-foreground"},"Loading dropzone..."))},e.createElement(r,Object.assign({},t)));
|
|
@@ -1,40 +1 @@
|
|
|
1
|
-
var
|
|
2
|
-
var t = {};
|
|
3
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
-
t[p] = s[p];
|
|
5
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
-
t[p[i]] = s[p[i]];
|
|
9
|
-
}
|
|
10
|
-
return t;
|
|
11
|
-
};
|
|
12
|
-
import * as React from "react";
|
|
13
|
-
import { cn } from "../lib/utils";
|
|
14
|
-
import { EnhancedLabel } from "./enhanced-label";
|
|
15
|
-
import { Input } from "./ui/input";
|
|
16
|
-
const EnhancedInput = React.forwardRef((_a, ref) => {
|
|
17
|
-
var { className, type, error, info, label, required, id, testIdWrapper, testIdInput, testIdLabel, testIdMessage, testIdError, testIdInfo } = _a, props = __rest(_a, ["className", "type", "error", "info", "label", "required", "id", "testIdWrapper", "testIdInput", "testIdLabel", "testIdMessage", "testIdError", "testIdInfo"]);
|
|
18
|
-
// Determine if there's an error (for aria-invalid and styling)
|
|
19
|
-
const hasError = Boolean(error);
|
|
20
|
-
const inputElement = (React.createElement(Input, Object.assign({ type: type, ref: ref, id: id, "aria-invalid": hasError, required: required, "data-testid": testIdInput, className: cn(
|
|
21
|
-
// Error state styling
|
|
22
|
-
hasError &&
|
|
23
|
-
"border-destructive focus-visible:border-destructive focus-visible:ring-destructive/20",
|
|
24
|
-
// Normal state when no error
|
|
25
|
-
!hasError &&
|
|
26
|
-
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", className) }, props)));
|
|
27
|
-
// If label is provided, render the complete input with label structure
|
|
28
|
-
if (label) {
|
|
29
|
-
return (React.createElement("div", { className: "w-full space-y-2", "data-testid": testIdWrapper },
|
|
30
|
-
React.createElement(EnhancedLabel, { htmlFor: id, required: required, "data-testid": testIdLabel }, label),
|
|
31
|
-
inputElement,
|
|
32
|
-
(error || info) && (React.createElement("div", { "data-testid": testIdMessage }, error ? (React.createElement("p", { className: "text-xs text-destructive", "data-testid": testIdError }, error)) : info ? (React.createElement("p", { className: "text-xs text-blue-600 dark:text-blue-400", "data-testid": testIdInfo }, info)) : null))));
|
|
33
|
-
}
|
|
34
|
-
// If no label, render just the input with messages (backward compatibility)
|
|
35
|
-
return (React.createElement("div", { className: "w-full", "data-testid": testIdWrapper },
|
|
36
|
-
inputElement,
|
|
37
|
-
(error || info) && (React.createElement("div", { "data-testid": testIdMessage }, error ? (React.createElement("p", { className: "text-xs text-destructive", "data-testid": testIdError }, error)) : info ? (React.createElement("p", { className: "text-xs text-blue-600 dark:text-blue-400", "data-testid": testIdInfo }, info)) : null))));
|
|
38
|
-
});
|
|
39
|
-
EnhancedInput.displayName = "EnhancedInput";
|
|
40
|
-
export { EnhancedInput };
|
|
1
|
+
"use strict";var y=function(a,i){var d={};for(var t in a)Object.prototype.hasOwnProperty.call(a,t)&&i.indexOf(t)<0&&(d[t]=a[t]);if(a!=null&&typeof Object.getOwnPropertySymbols=="function")for(var e=0,t=Object.getOwnPropertySymbols(a);e<t.length;e++)i.indexOf(t[e])<0&&Object.prototype.propertyIsEnumerable.call(a,t[e])&&(d[t[e]]=a[t[e]]);return d};import*as r from"react";import{cn as N}from"../lib/utils";import{EnhancedLabel as O}from"./enhanced-label";import{Input as g}from"./ui/input";const b=r.forwardRef((a,i)=>{var{className:d,type:t,error:e,info:s,label:n,required:c,id:o,testIdWrapper:u,testIdInput:I,testIdLabel:E,testIdMessage:p,testIdError:m,testIdInfo:f}=a,x=y(a,["className","type","error","info","label","required","id","testIdWrapper","testIdInput","testIdLabel","testIdMessage","testIdError","testIdInfo"]);const l=!!e,v=r.createElement(g,Object.assign({type:t,ref:i,id:o,"aria-invalid":l,required:c,"data-testid":I,className:N(l&&"border-destructive focus-visible:border-destructive focus-visible:ring-destructive/20",!l&&"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",d)},x));return n?r.createElement("div",{className:"w-full space-y-2","data-testid":u},r.createElement(O,{htmlFor:o,required:c,"data-testid":E},n),v,(e||s)&&r.createElement("div",{"data-testid":p},e?r.createElement("p",{className:"text-xs text-destructive","data-testid":m},e):s?r.createElement("p",{className:"text-xs text-blue-600 dark:text-blue-400","data-testid":f},s):null)):r.createElement("div",{className:"w-full","data-testid":u},v,(e||s)&&r.createElement("div",{"data-testid":p},e?r.createElement("p",{className:"text-xs text-destructive","data-testid":m},e):s?r.createElement("p",{className:"text-xs text-blue-600 dark:text-blue-400","data-testid":f},s):null))});b.displayName="EnhancedInput";export{b as EnhancedInput};
|
|
@@ -1,22 +1 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
-
var t = {};
|
|
4
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
-
t[p] = s[p];
|
|
6
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
-
t[p[i]] = s[p[i]];
|
|
10
|
-
}
|
|
11
|
-
return t;
|
|
12
|
-
};
|
|
13
|
-
import * as React from "react";
|
|
14
|
-
import { cn } from "../lib/utils";
|
|
15
|
-
import { Label } from "./ui/label";
|
|
16
|
-
function EnhancedLabel(_a) {
|
|
17
|
-
var { className, required = false, children, testIdLabel, testIdRequired } = _a, props = __rest(_a, ["className", "required", "children", "testIdLabel", "testIdRequired"]);
|
|
18
|
-
return (React.createElement(Label, Object.assign({ "data-slot": "label", "data-testid": testIdLabel, className: cn("flex items-center gap-1 select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 min-h-5", className) }, props),
|
|
19
|
-
children,
|
|
20
|
-
required && (React.createElement("span", { className: "text-destructive text-sm", "aria-label": "required", "data-testid": testIdRequired }, "*"))));
|
|
21
|
-
}
|
|
22
|
-
export { EnhancedLabel };
|
|
1
|
+
"use strict";"use client";var i=function(t,n){var a={};for(var e in t)Object.prototype.hasOwnProperty.call(t,e)&&n.indexOf(e)<0&&(a[e]=t[e]);if(t!=null&&typeof Object.getOwnPropertySymbols=="function")for(var r=0,e=Object.getOwnPropertySymbols(t);r<e.length;r++)n.indexOf(e[r])<0&&Object.prototype.propertyIsEnumerable.call(t,e[r])&&(a[e[r]]=t[e[r]]);return a};import*as l from"react";import{cn as c}from"../lib/utils";import{Label as d}from"./ui/label";function p(t){var{className:n,required:a=!1,children:e,testIdLabel:r,testIdRequired:o}=t,s=i(t,["className","required","children","testIdLabel","testIdRequired"]);return l.createElement(d,Object.assign({"data-slot":"label","data-testid":r,className:c("flex items-center gap-1 select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 min-h-5",n)},s),e,a&&l.createElement("span",{className:"text-destructive text-sm","aria-label":"required","data-testid":o},"*"))}export{p as EnhancedLabel};
|
|
@@ -1,15 +1 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import React from "react";
|
|
3
|
-
import { EnhancedLabel } from "./enhanced-label";
|
|
4
|
-
import { RadioGroup, RadioGroupItem } from "./ui/radio-group";
|
|
5
|
-
import { cn } from "../lib/utils";
|
|
6
|
-
export const EnhancedRadio = ({ className, label, name, onValueChange, options, value, }) => {
|
|
7
|
-
return (React.createElement("div", { className: cn("w-full space-y-2", className) },
|
|
8
|
-
label ? React.createElement(EnhancedLabel, null, label) : null,
|
|
9
|
-
React.createElement(RadioGroup, { value: value, onValueChange: onValueChange }, options.map((option) => {
|
|
10
|
-
const id = `${name}-${option.value}`;
|
|
11
|
-
return (React.createElement("div", { key: option.value, className: "flex items-center space-x-2" },
|
|
12
|
-
React.createElement(RadioGroupItem, { id: id, value: option.value }),
|
|
13
|
-
React.createElement(EnhancedLabel, { htmlFor: id }, option.label)));
|
|
14
|
-
}))));
|
|
15
|
-
};
|
|
1
|
+
"use strict";"use client";import e from"react";import{EnhancedLabel as r}from"./enhanced-label";import{RadioGroup as i,RadioGroupItem as s}from"./ui/radio-group";import{cn as d}from"../lib/utils";export const EnhancedRadio=({className:m,label:l,name:c,onValueChange:n,options:u,value:o})=>e.createElement("div",{className:d("w-full space-y-2",m)},l?e.createElement(r,null,l):null,e.createElement(i,{value:o,onValueChange:n},u.map(a=>{const t=`${c}-${a.value}`;return e.createElement("div",{key:a.value,className:"flex items-center space-x-2"},e.createElement(s,{id:t,value:a.value}),e.createElement(r,{htmlFor:t},a.label))})));
|
|
@@ -1,33 +1 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
-
var t = {};
|
|
4
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
-
t[p] = s[p];
|
|
6
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
-
t[p[i]] = s[p[i]];
|
|
10
|
-
}
|
|
11
|
-
return t;
|
|
12
|
-
};
|
|
13
|
-
import * as React from "react";
|
|
14
|
-
import { cn } from "../lib/utils";
|
|
15
|
-
import { Select, SelectTrigger } from "./ui/select";
|
|
16
|
-
import { EnhancedLabel } from "./enhanced-label";
|
|
17
|
-
const EnhancedSelect = (_a) => {
|
|
18
|
-
var { error, info, label, required, id, children, testIdWrapper, testIdLabel, testIdMessage, testIdError, testIdInfo } = _a, selectProps = __rest(_a, ["error", "info", "label", "required", "id", "children", "testIdWrapper", "testIdLabel", "testIdMessage", "testIdError", "testIdInfo"]);
|
|
19
|
-
return (React.createElement("div", { className: "w-full space-y-2", "data-testid": testIdWrapper },
|
|
20
|
-
label && (React.createElement(EnhancedLabel, { htmlFor: id, required: required, testIdLabel: testIdLabel }, label)),
|
|
21
|
-
React.createElement(Select, Object.assign({}, selectProps), children),
|
|
22
|
-
(error || info) && (React.createElement("div", { "data-testid": testIdMessage }, error ? (React.createElement("p", { className: "text-xs text-destructive", "data-testid": testIdError }, error)) : info ? (React.createElement("p", { className: "text-xs text-blue-600 dark:text-blue-400", "data-testid": testIdInfo }, info)) : null))));
|
|
23
|
-
};
|
|
24
|
-
const EnhancedSelectTrigger = React.forwardRef((_a, ref) => {
|
|
25
|
-
var { className, error, children } = _a, props = __rest(_a, ["className", "error", "children"]);
|
|
26
|
-
const hasError = Boolean(error);
|
|
27
|
-
return (React.createElement(SelectTrigger, Object.assign({ ref: ref, "aria-invalid": hasError, className: cn(
|
|
28
|
-
// Error state styling
|
|
29
|
-
hasError &&
|
|
30
|
-
"border-destructive focus:ring-destructive/20 focus:border-destructive", className) }, props), children));
|
|
31
|
-
});
|
|
32
|
-
EnhancedSelectTrigger.displayName = "EnhancedSelectTrigger";
|
|
33
|
-
export { EnhancedSelect, EnhancedSelectTrigger };
|
|
1
|
+
"use strict";"use client";var o=function(t,s){var a={};for(var e in t)Object.prototype.hasOwnProperty.call(t,e)&&s.indexOf(e)<0&&(a[e]=t[e]);if(t!=null&&typeof Object.getOwnPropertySymbols=="function")for(var r=0,e=Object.getOwnPropertySymbols(t);r<e.length;r++)s.indexOf(e[r])<0&&Object.prototype.propertyIsEnumerable.call(t,e[r])&&(a[e[r]]=t[e[r]]);return a};import*as l from"react";import{cn as E}from"../lib/utils";import{Select as g,SelectTrigger as h}from"./ui/select";import{EnhancedLabel as I}from"./enhanced-label";const v=t=>{var{error:s,info:a,label:e,required:r,id:n,children:c,testIdWrapper:i,testIdLabel:m,testIdMessage:f,testIdError:p,testIdInfo:u}=t,b=o(t,["error","info","label","required","id","children","testIdWrapper","testIdLabel","testIdMessage","testIdError","testIdInfo"]);return l.createElement("div",{className:"w-full space-y-2","data-testid":i},e&&l.createElement(I,{htmlFor:n,required:r,testIdLabel:m},e),l.createElement(g,Object.assign({},b),c),(s||a)&&l.createElement("div",{"data-testid":f},s?l.createElement("p",{className:"text-xs text-destructive","data-testid":p},s):a?l.createElement("p",{className:"text-xs text-blue-600 dark:text-blue-400","data-testid":u},a):null))},d=l.forwardRef((t,s)=>{var{className:a,error:e,children:r}=t,n=o(t,["className","error","children"]);const c=!!e;return l.createElement(h,Object.assign({ref:s,"aria-invalid":c,className:E(c&&"border-destructive focus:ring-destructive/20 focus:border-destructive",a)},n),r)});d.displayName="EnhancedSelectTrigger";export{v as EnhancedSelect,d as EnhancedSelectTrigger};
|
|
@@ -1,33 +1 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
-
var t = {};
|
|
4
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
-
t[p] = s[p];
|
|
6
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
-
t[p[i]] = s[p[i]];
|
|
10
|
-
}
|
|
11
|
-
return t;
|
|
12
|
-
};
|
|
13
|
-
import * as React from "react";
|
|
14
|
-
import { cn } from "../lib/utils";
|
|
15
|
-
import { EnhancedLabel } from "./enhanced-label";
|
|
16
|
-
import { Slider } from "./ui/slider";
|
|
17
|
-
const EnhancedSlider = React.forwardRef((_a, ref) => {
|
|
18
|
-
var _b, _c, _d, _e;
|
|
19
|
-
var { className, label, info, error, min, max, testIdWrapper, testIdLabel, testIdMessage, testIdError, testIdInfo, testIdSlider, testIdMin, testIdMax } = _a, props = __rest(_a, ["className", "label", "info", "error", "min", "max", "testIdWrapper", "testIdLabel", "testIdMessage", "testIdError", "testIdInfo", "testIdSlider", "testIdMin", "testIdMax"]);
|
|
20
|
-
// Prefer explicit min/max props; fall back to Slider props
|
|
21
|
-
const sliderMin = (_c = min !== null && min !== void 0 ? min : (_b = props.defaultValue) === null || _b === void 0 ? void 0 : _b[0]) !== null && _c !== void 0 ? _c : 0;
|
|
22
|
-
const sliderMax = (_e = max !== null && max !== void 0 ? max : (_d = props.defaultValue) === null || _d === void 0 ? void 0 : _d[1]) !== null && _e !== void 0 ? _e : 100;
|
|
23
|
-
const sliderElement = (React.createElement(Slider, Object.assign({ ref: ref, className: cn("w-full", className), "data-testid": testIdSlider, min: sliderMin, max: sliderMax }, props)));
|
|
24
|
-
return (React.createElement("div", { className: "w-full space-y-2", "data-testid": testIdWrapper },
|
|
25
|
-
label && (React.createElement(EnhancedLabel, { "data-testid": testIdLabel, className: "mb-0" }, label)),
|
|
26
|
-
React.createElement("div", { className: "flex items-center justify-between text-xs text-muted-foreground" },
|
|
27
|
-
React.createElement("span", { "data-testid": testIdMin }, min),
|
|
28
|
-
React.createElement("span", { "data-testid": testIdMax }, max)),
|
|
29
|
-
sliderElement,
|
|
30
|
-
(error || info) && (React.createElement("div", { "data-testid": testIdMessage }, error ? (React.createElement("p", { className: "text-xs text-destructive", "data-testid": testIdError }, error)) : info ? (React.createElement("p", { className: "text-xs text-blue-600 dark:text-blue-400", "data-testid": testIdInfo }, info)) : null))));
|
|
31
|
-
});
|
|
32
|
-
EnhancedSlider.displayName = "EnhancedSlider";
|
|
33
|
-
export { EnhancedSlider };
|
|
1
|
+
"use strict";"use client";var w=function(t,s){var l={};for(var e in t)Object.prototype.hasOwnProperty.call(t,e)&&s.indexOf(e)<0&&(l[e]=t[e]);if(t!=null&&typeof Object.getOwnPropertySymbols=="function")for(var a=0,e=Object.getOwnPropertySymbols(t);a<e.length;a++)s.indexOf(e[a])<0&&Object.prototype.propertyIsEnumerable.call(t,e[a])&&(l[e[a]]=t[e[a]]);return l};import*as r from"react";import{cn as S}from"../lib/utils";import{EnhancedLabel as _}from"./enhanced-label";import{Slider as j}from"./ui/slider";const u=r.forwardRef((t,s)=>{var l,e,a,i,{className:p,label:f,info:o,error:c,min:d,max:n,testIdWrapper:x,testIdLabel:I,testIdMessage:b,testIdError:v,testIdInfo:E,testIdSlider:y,testIdMin:O,testIdMax:N}=t,m=w(t,["className","label","info","error","min","max","testIdWrapper","testIdLabel","testIdMessage","testIdError","testIdInfo","testIdSlider","testIdMin","testIdMax"]);const M=(e=d??((l=m.defaultValue)===null||l===void 0?void 0:l[0]))!==null&&e!==void 0?e:0,g=(i=n??((a=m.defaultValue)===null||a===void 0?void 0:a[1]))!==null&&i!==void 0?i:100,h=r.createElement(j,Object.assign({ref:s,className:S("w-full",p),"data-testid":y,min:M,max:g},m));return r.createElement("div",{className:"w-full space-y-2","data-testid":x},f&&r.createElement(_,{"data-testid":I,className:"mb-0"},f),r.createElement("div",{className:"flex items-center justify-between text-xs text-muted-foreground"},r.createElement("span",{"data-testid":O},d),r.createElement("span",{"data-testid":N},n)),h,(c||o)&&r.createElement("div",{"data-testid":b},c?r.createElement("p",{className:"text-xs text-destructive","data-testid":v},c):o?r.createElement("p",{className:"text-xs text-blue-600 dark:text-blue-400","data-testid":E},o):null))});u.displayName="EnhancedSlider";export{u as EnhancedSlider};
|
|
@@ -1,42 +1 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
-
var t = {};
|
|
4
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
-
t[p] = s[p];
|
|
6
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
-
t[p[i]] = s[p[i]];
|
|
10
|
-
}
|
|
11
|
-
return t;
|
|
12
|
-
};
|
|
13
|
-
import * as React from "react";
|
|
14
|
-
import * as SwitchPrimitives from "@radix-ui/react-switch";
|
|
15
|
-
import { cn } from "../lib/utils";
|
|
16
|
-
import { EnhancedLabel } from "./enhanced-label";
|
|
17
|
-
const EnhancedSwitch = React.forwardRef((_a, ref) => {
|
|
18
|
-
var { className, error, info, label, required, id, description, testIdWrapper, testIdLabel, testIdSwitch, testIdThumb, testIdDescription, testIdMessage, testIdError, testIdInfo } = _a, props = __rest(_a, ["className", "error", "info", "label", "required", "id", "description", "testIdWrapper", "testIdLabel", "testIdSwitch", "testIdThumb", "testIdDescription", "testIdMessage", "testIdError", "testIdInfo"]);
|
|
19
|
-
// Determine if there's an error (for aria-invalid and styling)
|
|
20
|
-
const hasError = Boolean(error);
|
|
21
|
-
const switchElement = (React.createElement(SwitchPrimitives.Root, Object.assign({ ref: ref, id: id, "data-slot": "switch", "data-testid": testIdSwitch, "aria-invalid": hasError, required: required, className: cn("peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
|
|
22
|
-
// Error state styling
|
|
23
|
-
hasError &&
|
|
24
|
-
"data-[state=checked]:bg-destructive data-[state=unchecked]:bg-destructive/20 border-destructive focus-visible:border-destructive focus-visible:ring-destructive/20", className) }, props),
|
|
25
|
-
React.createElement(SwitchPrimitives.Thumb, { "data-slot": "switch-thumb", "data-testid": testIdThumb, className: cn("pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0") })));
|
|
26
|
-
// If label is provided, render the complete switch with label structure
|
|
27
|
-
if (label) {
|
|
28
|
-
return (React.createElement("div", { className: "w-full space-y-2", "data-testid": testIdWrapper },
|
|
29
|
-
React.createElement("div", { className: "flex items-center justify-between space-x-2" },
|
|
30
|
-
React.createElement("div", null,
|
|
31
|
-
React.createElement(EnhancedLabel, { htmlFor: id, required: required, testIdLabel: testIdLabel }, label),
|
|
32
|
-
description && (React.createElement("p", { className: "text-sm text-gray-400", "data-testid": testIdDescription }, description))),
|
|
33
|
-
switchElement),
|
|
34
|
-
(error || info) && (React.createElement("div", { "data-testid": testIdMessage }, error ? (React.createElement("p", { className: "text-xs text-destructive", "data-testid": testIdError }, error)) : info ? (React.createElement("p", { className: "text-xs text-blue-600 dark:text-blue-400", "data-testid": testIdInfo }, info)) : null))));
|
|
35
|
-
}
|
|
36
|
-
// If no label, render just the switch with messages (backward compatibility)
|
|
37
|
-
return (React.createElement("div", { className: "w-full", "data-testid": testIdWrapper },
|
|
38
|
-
switchElement,
|
|
39
|
-
(error || info) && (React.createElement("div", { "data-testid": testIdMessage }, error ? (React.createElement("p", { className: "text-xs text-destructive", "data-testid": testIdError }, error)) : info ? (React.createElement("p", { className: "text-xs text-blue-600 dark:text-blue-400", "data-testid": testIdInfo }, info)) : null))));
|
|
40
|
-
});
|
|
41
|
-
EnhancedSwitch.displayName = "EnhancedSwitch";
|
|
42
|
-
export { EnhancedSwitch };
|
|
1
|
+
"use strict";"use client";var N=function(r,i){var s={};for(var e in r)Object.prototype.hasOwnProperty.call(r,e)&&i.indexOf(e)<0&&(s[e]=r[e]);if(r!=null&&typeof Object.getOwnPropertySymbols=="function")for(var a=0,e=Object.getOwnPropertySymbols(r);a<e.length;a++)i.indexOf(e[a])<0&&Object.prototype.propertyIsEnumerable.call(r,e[a])&&(s[e[a]]=r[e[a]]);return s};import*as t from"react";import*as h from"@radix-ui/react-switch";import{cn as v}from"../lib/utils";import{EnhancedLabel as k}from"./enhanced-label";const x=t.forwardRef((r,i)=>{var{className:s,error:e,info:a,label:d,required:n,id:c,description:l,testIdWrapper:o,testIdLabel:g,testIdSwitch:E,testIdThumb:w,testIdDescription:I,testIdMessage:u,testIdError:m,testIdInfo:b}=r,y=N(r,["className","error","info","label","required","id","description","testIdWrapper","testIdLabel","testIdSwitch","testIdThumb","testIdDescription","testIdMessage","testIdError","testIdInfo"]);const f=!!e,p=t.createElement(h.Root,Object.assign({ref:i,id:c,"data-slot":"switch","data-testid":E,"aria-invalid":f,required:n,className:v("peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",f&&"data-[state=checked]:bg-destructive data-[state=unchecked]:bg-destructive/20 border-destructive focus-visible:border-destructive focus-visible:ring-destructive/20",s)},y),t.createElement(h.Thumb,{"data-slot":"switch-thumb","data-testid":w,className:v("pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0")}));return d?t.createElement("div",{className:"w-full space-y-2","data-testid":o},t.createElement("div",{className:"flex items-center justify-between space-x-2"},t.createElement("div",null,t.createElement(k,{htmlFor:c,required:n,testIdLabel:g},d),l&&t.createElement("p",{className:"text-sm text-gray-400","data-testid":I},l)),p),(e||a)&&t.createElement("div",{"data-testid":u},e?t.createElement("p",{className:"text-xs text-destructive","data-testid":m},e):a?t.createElement("p",{className:"text-xs text-blue-600 dark:text-blue-400","data-testid":b},a):null)):t.createElement("div",{className:"w-full","data-testid":o},p,(e||a)&&t.createElement("div",{"data-testid":u},e?t.createElement("p",{className:"text-xs text-destructive","data-testid":m},e):a?t.createElement("p",{className:"text-xs text-blue-600 dark:text-blue-400","data-testid":b},a):null))});x.displayName="EnhancedSwitch";export{x as EnhancedSwitch};
|
|
@@ -1,102 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Enhanced Table Footer Action Component
|
|
3
|
-
*
|
|
4
|
-
* Navigation buttons for table pagination with RTL/LTR support.
|
|
5
|
-
* Automatically adjusts arrow directions and button order based on locale.
|
|
6
|
-
*
|
|
7
|
-
* Features:
|
|
8
|
-
* - RTL/LTR arrow direction adjustment
|
|
9
|
-
* - Button order reversal for RTL layouts
|
|
10
|
-
* - Accessibility attributes
|
|
11
|
-
* - Internationalized aria labels
|
|
12
|
-
* - Disabled state handling
|
|
13
|
-
* - Loading state support
|
|
14
|
-
*/
|
|
15
|
-
import React from "react";
|
|
16
|
-
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
17
|
-
import { Button } from "./ui/button";
|
|
18
|
-
export const EnhancedTableFooterAction = ({ handleNextOnClick, handlePreviousOnClick, isNextDisabled, isPreviousDisabled, isRTL = false, loading, nextPageLabel = "Next page", previousPageLabel = "Previous page", testIdWrapper, testIdPrevious, testIdNext, testIdPreviousIcon, testIdNextIcon, }) => {
|
|
19
|
-
// In RTL, arrows should be swapped:
|
|
20
|
-
// Previous should show → (ChevronRight) as it goes to the right in RTL reading order
|
|
21
|
-
// Next should show ← (ChevronLeft) as it goes to the left in RTL reading order
|
|
22
|
-
const PreviousIcon = isRTL ? ChevronRight : ChevronLeft;
|
|
23
|
-
const NextIcon = isRTL ? ChevronLeft : ChevronRight;
|
|
24
|
-
return (React.createElement("div", { className: `flex gap-1 ${isRTL ? "flex-row-reverse" : ""}`, "data-testid": testIdWrapper },
|
|
25
|
-
React.createElement(Button, { variant: "outline", size: "icon", "data-testid": testIdPrevious, onClick: handlePreviousOnClick, disabled: isPreviousDisabled || loading, "aria-label": previousPageLabel, title: previousPageLabel, className: `${isRTL ? "rotate-180" : ""}` },
|
|
26
|
-
React.createElement(PreviousIcon, { className: "h-4 w-4", "data-testid": testIdPreviousIcon })),
|
|
27
|
-
React.createElement(Button, { variant: "outline", size: "icon", "data-testid": testIdNext, onClick: handleNextOnClick, disabled: isNextDisabled || loading, "aria-label": nextPageLabel, title: nextPageLabel, className: `${isRTL ? "rotate-180" : ""}` },
|
|
28
|
-
React.createElement(NextIcon, { className: "h-4 w-4", "data-testid": testIdNextIcon }))));
|
|
29
|
-
};
|
|
30
|
-
// ============================================================================
|
|
31
|
-
// USAGE EXAMPLES
|
|
32
|
-
// ============================================================================
|
|
33
|
-
/*
|
|
34
|
-
Example 1: Basic usage with automatic i18n and RTL support
|
|
35
|
-
<EnhancedTableFooterAction
|
|
36
|
-
handlePreviousOnClick={() => setCurrentPage(prev => prev - 1)}
|
|
37
|
-
handleNextOnClick={() => setCurrentPage(prev => prev + 1)}
|
|
38
|
-
isPreviousDisabled={currentPage === 1}
|
|
39
|
-
isNextDisabled={currentPage === totalPages}
|
|
40
|
-
loading={false}
|
|
41
|
-
/>
|
|
42
|
-
|
|
43
|
-
Example 2: With custom aria labels
|
|
44
|
-
<EnhancedTableFooterAction
|
|
45
|
-
handlePreviousOnClick={handlePrevious}
|
|
46
|
-
handleNextOnClick={handleNext}
|
|
47
|
-
isPreviousDisabled={isPreviousDisabled}
|
|
48
|
-
isNextDisabled={isNextDisabled}
|
|
49
|
-
loading={isLoading}
|
|
50
|
-
ariaLabels={{
|
|
51
|
-
previous: "Go to previous page",
|
|
52
|
-
next: "Go to next page"
|
|
53
|
-
}}
|
|
54
|
-
/>
|
|
55
|
-
|
|
56
|
-
Example 3: Loading state
|
|
57
|
-
<EnhancedTableFooterAction
|
|
58
|
-
handlePreviousOnClick={handlePrevious}
|
|
59
|
-
handleNextOnClick={handleNext}
|
|
60
|
-
loading={true} // Both buttons will be disabled
|
|
61
|
-
/>
|
|
62
|
-
|
|
63
|
-
RTL Behavior:
|
|
64
|
-
- In LTR languages (English): Previous (←) | Next (→)
|
|
65
|
-
- In RTL languages (Arabic/Urdu): Previous (→) | Next (←)
|
|
66
|
-
- Button order is reversed in RTL: [Next] [Previous]
|
|
67
|
-
- Arrows automatically adjust to reading direction
|
|
68
|
-
*/
|
|
69
|
-
// ============================================================================
|
|
70
|
-
// COMPONENT ENHANCEMENTS SUMMARY
|
|
71
|
-
// ============================================================================
|
|
72
|
-
/*
|
|
73
|
-
Enhancements Applied:
|
|
74
|
-
|
|
75
|
-
1. **RTL/LTR Layout Support**
|
|
76
|
-
- Automatic arrow direction adjustment based on locale
|
|
77
|
-
- Button order reversal for RTL layouts (flex-row-reverse)
|
|
78
|
-
- Direction-aware icon selection (ChevronLeft/Right swap)
|
|
79
|
-
- Proper navigation flow for both reading directions
|
|
80
|
-
|
|
81
|
-
2. **Internationalization (i18n)**
|
|
82
|
-
- Translation support using next-intl
|
|
83
|
-
- Fallback aria labels for accessibility
|
|
84
|
-
- Custom aria label override capability
|
|
85
|
-
- Tooltip support with title attributes
|
|
86
|
-
|
|
87
|
-
3. **Accessibility Improvements**
|
|
88
|
-
- ARIA labels for screen readers
|
|
89
|
-
- Title attributes for tooltips
|
|
90
|
-
- Proper button semantics
|
|
91
|
-
- Keyboard navigation support
|
|
92
|
-
|
|
93
|
-
4. **Visual Consistency**
|
|
94
|
-
- Maintains button spacing and alignment
|
|
95
|
-
- Consistent with existing table footer components
|
|
96
|
-
- Proper disabled state handling
|
|
97
|
-
- Loading state support
|
|
98
|
-
|
|
99
|
-
Translation Keys Added:
|
|
100
|
-
- common.previousPage: "Previous page" / "پچھلا صفحہ"
|
|
101
|
-
- common.nextPage: "Next page" / "اگلا صفحہ"
|
|
102
|
-
*/
|
|
1
|
+
"use strict";import t from"react";import{ChevronLeft as i,ChevronRight as l}from"lucide-react";import{Button as n}from"./ui/button";export const EnhancedTableFooterAction=({handleNextOnClick:c,handlePreviousOnClick:s,isNextDisabled:m,isPreviousDisabled:d,isRTL:e=!1,loading:a,nextPageLabel:o="Next page",previousPageLabel:r="Previous page",testIdWrapper:f,testIdPrevious:v,testIdNext:N,testIdPreviousIcon:h,testIdNextIcon:p})=>{const E=e?l:i,u=e?i:l;return t.createElement("div",{className:`flex gap-1 ${e?"flex-row-reverse":""}`,"data-testid":f},t.createElement(n,{variant:"outline",size:"icon","data-testid":v,onClick:s,disabled:d||a,"aria-label":r,title:r,className:`${e?"rotate-180":""}`},t.createElement(E,{className:"h-4 w-4","data-testid":h})),t.createElement(n,{variant:"outline",size:"icon","data-testid":N,onClick:c,disabled:m||a,"aria-label":o,title:o,className:`${e?"rotate-180":""}`},t.createElement(u,{className:"h-4 w-4","data-testid":p})))};
|