@appcorp/stellar-solutions-modules 0.1.51 → 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,208 +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
|
-
// Track previous previews and remote map to avoid emitting unchanged values
|
|
78
|
-
var previewsRef = (0, react_1.useRef)([]);
|
|
79
|
-
var remotePreviewsRef = (0, react_1.useRef)({});
|
|
80
|
-
var dropzoneOptions = {
|
|
81
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
82
|
-
accept: (Array.isArray(accept) ? undefined : accept) || undefined,
|
|
83
|
-
maxFiles: maxFiles,
|
|
84
|
-
maxSize: maxSize,
|
|
85
|
-
minSize: minSize,
|
|
86
|
-
disabled: disabled,
|
|
87
|
-
onDrop: function (acceptedFiles) {
|
|
88
|
-
// append files, respecting maxFiles
|
|
89
|
-
var nextFiles = __spreadArray(__spreadArray([], files, true), acceptedFiles, true);
|
|
90
|
-
if (maxFiles && nextFiles.length > maxFiles)
|
|
91
|
-
nextFiles = nextFiles.slice(0, maxFiles);
|
|
92
|
-
setFiles(nextFiles);
|
|
93
|
-
onChange === null || onChange === void 0 ? void 0 : onChange(nextFiles);
|
|
94
|
-
},
|
|
95
|
-
};
|
|
96
|
-
var _g = (0, react_dropzone_1.useDropzone)(dropzoneOptions), getRootProps = _g.getRootProps, getInputProps = _g.getInputProps, isDragActive = _g.isDragActive;
|
|
97
|
-
// 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
|
|
98
72
|
(0, react_1.useEffect)(function () {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
catch (_a) { }
|
|
105
|
-
});
|
|
106
|
-
createdUrlsRef.current = [];
|
|
107
|
-
var next = [];
|
|
108
|
-
var remoteMap = {};
|
|
109
|
-
// start with initial items (may be File or string)
|
|
110
|
-
initial.forEach(function (item) {
|
|
111
|
-
if (typeof item === "string") {
|
|
112
|
-
// skip any remote URL the user removed earlier
|
|
113
|
-
if (removedRemoteRef.current.has(item))
|
|
114
|
-
return;
|
|
115
|
-
next.push(item);
|
|
116
|
-
remoteMap[item] = true;
|
|
117
|
-
}
|
|
118
|
-
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)) {
|
|
119
77
|
try {
|
|
120
|
-
var url = URL.createObjectURL(
|
|
121
|
-
|
|
122
|
-
createdUrlsRef.current.push(url);
|
|
78
|
+
var url = URL.createObjectURL(file);
|
|
79
|
+
map.set(file, url);
|
|
123
80
|
}
|
|
124
|
-
catch (
|
|
125
|
-
|
|
81
|
+
catch (error) {
|
|
82
|
+
console.error("Failed to create object URL:", error);
|
|
126
83
|
}
|
|
127
84
|
}
|
|
128
|
-
else {
|
|
129
|
-
next.push("");
|
|
130
|
-
}
|
|
131
85
|
});
|
|
132
|
-
//
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
catch (_a) {
|
|
140
|
-
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);
|
|
141
93
|
}
|
|
142
94
|
});
|
|
143
|
-
//
|
|
144
|
-
// or remoteMap actually changed (shallow equality check). This prevents
|
|
145
|
-
// a cycle when parent mirrors the previews back into `initial`.
|
|
146
|
-
var prev = previewsRef.current || [];
|
|
147
|
-
var arraysEqual = function (a, b) {
|
|
148
|
-
if (a === b)
|
|
149
|
-
return true;
|
|
150
|
-
if (!a || !b)
|
|
151
|
-
return false;
|
|
152
|
-
if (a.length !== b.length)
|
|
153
|
-
return false;
|
|
154
|
-
for (var i = 0; i < a.length; i++)
|
|
155
|
-
if (a[i] !== b[i])
|
|
156
|
-
return false;
|
|
157
|
-
return true;
|
|
158
|
-
};
|
|
159
|
-
var remoteKeysEqual = function (m1, m2) {
|
|
160
|
-
var k1 = Object.keys(m1 || {});
|
|
161
|
-
var k2 = Object.keys(m2 || {});
|
|
162
|
-
if (k1.length !== k2.length)
|
|
163
|
-
return false;
|
|
164
|
-
k1.sort();
|
|
165
|
-
k2.sort();
|
|
166
|
-
for (var i = 0; i < k1.length; i++)
|
|
167
|
-
if (k1[i] !== k2[i])
|
|
168
|
-
return false;
|
|
169
|
-
return true;
|
|
170
|
-
};
|
|
171
|
-
var previewsChanged = !arraysEqual(prev, next);
|
|
172
|
-
var remoteChanged = !remoteKeysEqual(remotePreviewsRef.current || {}, remoteMap);
|
|
173
|
-
if (previewsChanged) {
|
|
174
|
-
setPreviews(next);
|
|
175
|
-
previewsRef.current = next.slice();
|
|
176
|
-
}
|
|
177
|
-
if (remoteChanged) {
|
|
178
|
-
setRemotePreviews(remoteMap);
|
|
179
|
-
remotePreviewsRef.current = __assign({}, remoteMap);
|
|
180
|
-
}
|
|
181
|
-
if (previewsChanged) {
|
|
182
|
-
onPreviewsChange === null || onPreviewsChange === void 0 ? void 0 : onPreviewsChange(next);
|
|
183
|
-
}
|
|
184
|
-
// notify parent about the current rendered previews (object URLs and remote URLs)
|
|
185
|
-
onPreviewsChange === null || onPreviewsChange === void 0 ? void 0 : onPreviewsChange(next);
|
|
95
|
+
// Cleanup on unmount
|
|
186
96
|
return function () {
|
|
187
|
-
(
|
|
188
|
-
|
|
189
|
-
URL.revokeObjectURL(u);
|
|
190
|
-
}
|
|
191
|
-
catch (_a) { }
|
|
97
|
+
Array.from(map.values()).forEach(function (url) {
|
|
98
|
+
URL.revokeObjectURL(url);
|
|
192
99
|
});
|
|
193
|
-
|
|
100
|
+
map.clear();
|
|
194
101
|
};
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if (entry === undefined)
|
|
210
|
-
return;
|
|
211
|
-
var isRemote = Boolean(remotePreviews[entry]);
|
|
212
|
-
if (isRemote) {
|
|
213
|
-
// notify parent and mark as removed so it won't reappear from `initial`
|
|
214
|
-
onRemoveUrl === null || onRemoveUrl === void 0 ? void 0 : onRemoveUrl(entry);
|
|
215
|
-
removedRemoteRef.current.add(entry);
|
|
216
|
-
// remove only the specific preview at previewIndex
|
|
217
|
-
setPreviews(function (p) {
|
|
218
|
-
var next = __spreadArray([], p, true);
|
|
219
|
-
next.splice(previewIndex, 1);
|
|
220
|
-
return next;
|
|
221
|
-
});
|
|
222
|
-
setRemotePreviews(function (m) {
|
|
223
|
-
var next = __assign({}, m);
|
|
224
|
-
delete next[entry];
|
|
225
|
-
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;
|
|
226
116
|
});
|
|
227
|
-
|
|
228
|
-
var updatedPreviews = previews.filter(function (_, i) { return i !== previewIndex; });
|
|
229
|
-
onPreviewsChange === null || onPreviewsChange === void 0 ? void 0 : onPreviewsChange(updatedPreviews);
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
// local file - compute index relative to files array and remove
|
|
233
|
-
var fileIndex = previewIndex - initial.length;
|
|
234
|
-
if (fileIndex >= 0 && fileIndex < files.length) {
|
|
235
|
-
handleRemoveLocal(fileIndex);
|
|
236
|
-
}
|
|
117
|
+
}, [maxFiles, onChange]),
|
|
237
118
|
};
|
|
238
|
-
|
|
239
|
-
//
|
|
240
|
-
|
|
241
|
-
|
|
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) },
|
|
242
139
|
label && (react_1.default.createElement("label", { className: "mb-2 block text-sm font-medium" }, label)),
|
|
243
|
-
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") }),
|
|
244
141
|
react_1.default.createElement("input", __assign({}, getInputProps(), { id: id })),
|
|
245
|
-
|
|
246
|
-
react_1.default.createElement("div", { className: "relative w-
|
|
247
|
-
react_1.default.createElement(
|
|
248
|
-
react_1.default.createElement(carousel_1.
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
react_1.default.createElement(
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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))),
|
|
268
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))));
|
|
269
168
|
};
|
|
270
169
|
exports.EnhancedDropzone = EnhancedDropzone;
|
package/package.json
CHANGED