@appcorp/stellar-solutions-modules 0.1.50 → 0.1.52
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.
|
@@ -11,13 +11,11 @@ export type EnhancedDropzoneProps = {
|
|
|
11
11
|
maxSize?: number;
|
|
12
12
|
minSize?: number;
|
|
13
13
|
disabled?: boolean;
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
/** Called when selected
|
|
14
|
+
/** Remote image URLs to display as previews */
|
|
15
|
+
value?: string[];
|
|
16
|
+
/** Called when files are selected or removed */
|
|
17
17
|
onChange?: (files: File[]) => void;
|
|
18
|
-
/** Called when
|
|
19
|
-
|
|
20
|
-
/** Called when a provided remote URL preview is removed (if provided) */
|
|
21
|
-
onRemoveUrl?: (url: string) => void;
|
|
18
|
+
/** Called when a remote URL is removed */
|
|
19
|
+
onRemoveRemote?: (url: string) => void;
|
|
22
20
|
};
|
|
23
21
|
export declare const EnhancedDropzone: React.FC<EnhancedDropzoneProps>;
|
|
@@ -63,165 +63,107 @@ var button_1 = require("./button");
|
|
|
63
63
|
var lucide_react_1 = require("lucide-react");
|
|
64
64
|
var dropzone_1 = require("./shadcn-io/dropzone");
|
|
65
65
|
var EnhancedDropzone = function (_a) {
|
|
66
|
-
var id = _a.id, label = _a.label, info = _a.info, error = _a.error, accept = _a.accept, _b = _a.maxFiles, maxFiles = _b === void 0 ? 10 : _b, maxSize = _a.maxSize, minSize = _a.minSize, disabled = _a.disabled, _c = _a.
|
|
67
|
-
//
|
|
68
|
-
var _d = (0, react_1.useState)([]),
|
|
69
|
-
//
|
|
70
|
-
var
|
|
71
|
-
//
|
|
72
|
-
var _f = (0, react_1.useState)({}), remotePreviews = _f[0], setRemotePreviews = _f[1];
|
|
73
|
-
var createdUrlsRef = (0, react_1.useRef)([]);
|
|
74
|
-
// Track remote URLs removed by the user so they don't reappear when
|
|
75
|
-
// previews are rebuilt from the unchanged `initial` prop.
|
|
76
|
-
var removedRemoteRef = (0, react_1.useRef)(new Set());
|
|
77
|
-
var dropzoneOptions = {
|
|
78
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
79
|
-
accept: (Array.isArray(accept) ? undefined : accept) || undefined,
|
|
80
|
-
maxFiles: maxFiles,
|
|
81
|
-
maxSize: maxSize,
|
|
82
|
-
minSize: minSize,
|
|
83
|
-
disabled: disabled,
|
|
84
|
-
onDrop: function (acceptedFiles) {
|
|
85
|
-
// append files, respecting maxFiles
|
|
86
|
-
var nextFiles = __spreadArray(__spreadArray([], files, true), acceptedFiles, true);
|
|
87
|
-
if (maxFiles && nextFiles.length > maxFiles)
|
|
88
|
-
nextFiles = nextFiles.slice(0, maxFiles);
|
|
89
|
-
setFiles(nextFiles);
|
|
90
|
-
onChange === null || onChange === void 0 ? void 0 : onChange(nextFiles);
|
|
91
|
-
},
|
|
92
|
-
};
|
|
93
|
-
var _g = (0, react_dropzone_1.useDropzone)(dropzoneOptions), getRootProps = _g.getRootProps, getInputProps = _g.getInputProps, isDragActive = _g.isDragActive;
|
|
94
|
-
// Build previews from initial and files
|
|
66
|
+
var id = _a.id, label = _a.label, info = _a.info, error = _a.error, accept = _a.accept, _b = _a.maxFiles, maxFiles = _b === void 0 ? 10 : _b, maxSize = _a.maxSize, minSize = _a.minSize, disabled = _a.disabled, _c = _a.value, value = _c === void 0 ? [] : _c, onChange = _a.onChange, onRemoveRemote = _a.onRemoveRemote, className = _a.className;
|
|
67
|
+
// Local files selected by user
|
|
68
|
+
var _d = (0, react_1.useState)([]), localFiles = _d[0], setLocalFiles = _d[1];
|
|
69
|
+
// Track object URLs created for local files
|
|
70
|
+
var localPreviewsRef = (0, react_1.useRef)(new Map());
|
|
71
|
+
// Create object URLs for local files
|
|
95
72
|
(0, react_1.useEffect)(function () {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
catch (_a) { }
|
|
102
|
-
});
|
|
103
|
-
createdUrlsRef.current = [];
|
|
104
|
-
var next = [];
|
|
105
|
-
var remoteMap = {};
|
|
106
|
-
// start with initial items (may be File or string)
|
|
107
|
-
initial.forEach(function (item) {
|
|
108
|
-
if (typeof item === "string") {
|
|
109
|
-
// skip any remote URL the user removed earlier
|
|
110
|
-
if (removedRemoteRef.current.has(item))
|
|
111
|
-
return;
|
|
112
|
-
next.push(item);
|
|
113
|
-
remoteMap[item] = true;
|
|
114
|
-
}
|
|
115
|
-
else if (item instanceof File) {
|
|
73
|
+
var map = localPreviewsRef.current;
|
|
74
|
+
// Create URLs for new files
|
|
75
|
+
localFiles.forEach(function (file) {
|
|
76
|
+
if (!map.has(file)) {
|
|
116
77
|
try {
|
|
117
|
-
var url = URL.createObjectURL(
|
|
118
|
-
|
|
119
|
-
createdUrlsRef.current.push(url);
|
|
78
|
+
var url = URL.createObjectURL(file);
|
|
79
|
+
map.set(file, url);
|
|
120
80
|
}
|
|
121
|
-
catch (
|
|
122
|
-
|
|
81
|
+
catch (error) {
|
|
82
|
+
console.error("Failed to create object URL:", error);
|
|
123
83
|
}
|
|
124
84
|
}
|
|
125
|
-
else {
|
|
126
|
-
next.push("");
|
|
127
|
-
}
|
|
128
85
|
});
|
|
129
|
-
//
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
catch (_a) {
|
|
137
|
-
next.push("");
|
|
86
|
+
// Clean up URLs for removed files
|
|
87
|
+
var currentFiles = new Set(localFiles);
|
|
88
|
+
Array.from(map.entries()).forEach(function (_a) {
|
|
89
|
+
var file = _a[0], url = _a[1];
|
|
90
|
+
if (!currentFiles.has(file)) {
|
|
91
|
+
URL.revokeObjectURL(url);
|
|
92
|
+
map.delete(file);
|
|
138
93
|
}
|
|
139
94
|
});
|
|
140
|
-
|
|
141
|
-
setRemotePreviews(remoteMap);
|
|
142
|
-
// notify parent about the current rendered previews (object URLs and remote URLs)
|
|
143
|
-
onPreviewsChange === null || onPreviewsChange === void 0 ? void 0 : onPreviewsChange(next);
|
|
95
|
+
// Cleanup on unmount
|
|
144
96
|
return function () {
|
|
145
|
-
(
|
|
146
|
-
|
|
147
|
-
URL.revokeObjectURL(u);
|
|
148
|
-
}
|
|
149
|
-
catch (_a) { }
|
|
97
|
+
Array.from(map.values()).forEach(function (url) {
|
|
98
|
+
URL.revokeObjectURL(url);
|
|
150
99
|
});
|
|
151
|
-
|
|
100
|
+
map.clear();
|
|
152
101
|
};
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if (entry === undefined)
|
|
168
|
-
return;
|
|
169
|
-
var isRemote = Boolean(remotePreviews[entry]);
|
|
170
|
-
if (isRemote) {
|
|
171
|
-
// notify parent
|
|
172
|
-
onRemoveUrl === null || onRemoveUrl === void 0 ? void 0 : onRemoveUrl(entry);
|
|
173
|
-
// record removal locally so the value isn't re-added from the `initial`
|
|
174
|
-
// prop on the next rebuild
|
|
175
|
-
removedRemoteRef.current.add(entry);
|
|
176
|
-
// remove only the specific preview at previewIndex
|
|
177
|
-
setPreviews(function (p) {
|
|
178
|
-
var next = __spreadArray([], p, true);
|
|
179
|
-
next.splice(previewIndex, 1);
|
|
180
|
-
return next;
|
|
181
|
-
});
|
|
182
|
-
setRemotePreviews(function (m) {
|
|
183
|
-
var next = __assign({}, m);
|
|
184
|
-
delete next[entry];
|
|
185
|
-
return next;
|
|
102
|
+
}, [localFiles]);
|
|
103
|
+
var dropzoneOptions = {
|
|
104
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
105
|
+
accept: (Array.isArray(accept) ? undefined : accept) || undefined,
|
|
106
|
+
maxFiles: maxFiles,
|
|
107
|
+
maxSize: maxSize,
|
|
108
|
+
minSize: minSize,
|
|
109
|
+
disabled: disabled,
|
|
110
|
+
onDrop: (0, react_1.useCallback)(function (acceptedFiles) {
|
|
111
|
+
setLocalFiles(function (prev) {
|
|
112
|
+
var combined = __spreadArray(__spreadArray([], prev, true), acceptedFiles, true);
|
|
113
|
+
var limited = maxFiles ? combined.slice(0, maxFiles) : combined;
|
|
114
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(limited);
|
|
115
|
+
return limited;
|
|
186
116
|
});
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
// local file - compute index relative to files array and remove
|
|
190
|
-
var fileIndex = previewIndex - initial.length;
|
|
191
|
-
if (fileIndex >= 0 && fileIndex < files.length) {
|
|
192
|
-
handleRemoveLocal(fileIndex);
|
|
193
|
-
}
|
|
117
|
+
}, [maxFiles, onChange]),
|
|
194
118
|
};
|
|
195
|
-
|
|
196
|
-
//
|
|
197
|
-
|
|
198
|
-
|
|
119
|
+
var _e = (0, react_dropzone_1.useDropzone)(dropzoneOptions), getRootProps = _e.getRootProps, getInputProps = _e.getInputProps, isDragActive = _e.isDragActive;
|
|
120
|
+
// Remove remote URL
|
|
121
|
+
var handleRemoveRemote = (0, react_1.useCallback)(function (url) {
|
|
122
|
+
onRemoveRemote === null || onRemoveRemote === void 0 ? void 0 : onRemoveRemote(url);
|
|
123
|
+
}, [onRemoveRemote]);
|
|
124
|
+
// Remove local file
|
|
125
|
+
var handleRemoveLocal = (0, react_1.useCallback)(function (index) {
|
|
126
|
+
setLocalFiles(function (prev) {
|
|
127
|
+
var updated = prev.filter(function (_, i) { return i !== index; });
|
|
128
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(updated);
|
|
129
|
+
return updated;
|
|
130
|
+
});
|
|
131
|
+
}, [onChange]);
|
|
132
|
+
// Get all preview URLs (remote + local)
|
|
133
|
+
var allPreviews = __spreadArray(__spreadArray([], value.map(function (url) { return ({ type: "remote", url: url, index: 0 }); }), true), localFiles.map(function (file, index) { return ({
|
|
134
|
+
type: "local",
|
|
135
|
+
url: localPreviewsRef.current.get(file) || "",
|
|
136
|
+
index: index,
|
|
137
|
+
}); }), true);
|
|
138
|
+
return (react_1.default.createElement("div", { className: (0, utils_1.cn)("w-full", className) },
|
|
199
139
|
label && (react_1.default.createElement("label", { className: "mb-2 block text-sm font-medium" }, label)),
|
|
200
|
-
react_1.default.createElement("div", __assign({}, getRootProps(), { className: (0, utils_1.cn)("relative w-full rounded-md border border-dashed p-6 text-center
|
|
140
|
+
react_1.default.createElement("div", __assign({}, getRootProps(), { className: (0, utils_1.cn)("relative w-full rounded-md border border-dashed p-6 text-center", isDragActive && "ring-2 ring-ring ring-offset-2", disabled && "opacity-60 pointer-events-none") }),
|
|
201
141
|
react_1.default.createElement("input", __assign({}, getInputProps(), { id: id })),
|
|
202
|
-
|
|
203
|
-
react_1.default.createElement("div", { className: "relative w-
|
|
204
|
-
react_1.default.createElement(
|
|
205
|
-
react_1.default.createElement(carousel_1.
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
react_1.default.createElement(
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
142
|
+
allPreviews.length > 0 ? (react_1.default.createElement("div", { className: "flex flex-col items-center" },
|
|
143
|
+
react_1.default.createElement("div", { className: "relative w-full max-w-md" },
|
|
144
|
+
react_1.default.createElement(carousel_1.Carousel, { className: "w-full" },
|
|
145
|
+
react_1.default.createElement(carousel_1.CarouselPrevious, { type: "button", onClick: function (e) { return e.stopPropagation(); }, onPointerDown: function (e) { return e.stopPropagation(); }, onMouseDown: function (e) { return e.stopPropagation(); } }),
|
|
146
|
+
react_1.default.createElement(carousel_1.CarouselNext, { type: "button", onClick: function (e) { return e.stopPropagation(); }, onPointerDown: function (e) { return e.stopPropagation(); }, onMouseDown: function (e) { return e.stopPropagation(); } }),
|
|
147
|
+
react_1.default.createElement(carousel_1.CarouselContent, { className: "ml-0" }, allPreviews.map(function (preview, idx) { return (react_1.default.createElement(carousel_1.CarouselItem, { key: "".concat(preview.type, "-").concat(preview.url, "-").concat(idx), className: "pl-4" },
|
|
148
|
+
react_1.default.createElement("div", { className: "relative aspect-square w-full max-w-xs mx-auto" }, preview.url ? (react_1.default.createElement(react_1.default.Fragment, null,
|
|
149
|
+
react_1.default.createElement("img", { src: preview.url, alt: "Preview ".concat(idx + 1), className: "h-full w-full rounded-lg object-cover", onClick: function (e) { return e.stopPropagation(); } }),
|
|
150
|
+
react_1.default.createElement(button_1.Button, { type: "button", size: "icon", variant: "destructive", onClick: function (e) {
|
|
151
|
+
e.stopPropagation();
|
|
152
|
+
if (preview.type === "remote") {
|
|
153
|
+
handleRemoveRemote(preview.url);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
handleRemoveLocal(preview.index);
|
|
157
|
+
}
|
|
158
|
+
}, className: "absolute right-2 top-2 h-8 w-8 rounded-full", "aria-label": "Remove image" },
|
|
159
|
+
react_1.default.createElement(lucide_react_1.XIcon, { className: "h-4 w-4" })))) : (react_1.default.createElement("div", { className: "flex h-full w-full items-center justify-center rounded-lg bg-muted text-muted-foreground" },
|
|
160
|
+
react_1.default.createElement("span", { className: "text-sm" }, "Loading...")))))); })))),
|
|
161
|
+
react_1.default.createElement("p", { className: "mt-4 text-sm font-medium text-muted-foreground" },
|
|
162
|
+
allPreviews.length,
|
|
163
|
+
" image",
|
|
164
|
+
allPreviews.length !== 1 ? "s" : "",
|
|
165
|
+
" ",
|
|
166
|
+
"selected"))) : (react_1.default.createElement(dropzone_1.DropzoneEmptyState, null))),
|
|
225
167
|
(error || info) && (react_1.default.createElement("div", { className: "mt-2" }, error ? (react_1.default.createElement("p", { className: "text-xs text-destructive" }, error)) : info ? (react_1.default.createElement("p", { className: "text-xs text-blue-600 dark:text-blue-400" }, info)) : null))));
|
|
226
168
|
};
|
|
227
169
|
exports.EnhancedDropzone = EnhancedDropzone;
|
package/package.json
CHANGED