@webdevarif/dashui 0.2.2 → 0.2.4

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/dist/index.d.mts CHANGED
@@ -367,7 +367,6 @@ interface MediaPickerDialogProps {
367
367
  folders?: MediaPickerDialogFolder[];
368
368
  loading?: boolean;
369
369
  total: number;
370
- uploads?: UploadItem[];
371
370
  typeFilter?: string;
372
371
  onTypeChange?: (type: string) => void;
373
372
  search?: string;
@@ -378,11 +377,12 @@ interface MediaPickerDialogProps {
378
377
  onLoadMore?: () => void;
379
378
  hasMore?: boolean;
380
379
  multiple?: boolean;
380
+ initialSelected?: string[];
381
381
  /** "images" = only show image type tabs; "all" = show all type tabs */
382
382
  accept?: "images" | "all";
383
383
  onSelect: (files: MediaCardFile[]) => void;
384
384
  }
385
- declare function MediaPickerDialog({ open, onOpenChange, title, files, folders, loading, total, uploads, typeFilter, onTypeChange, search, onSearch, activeFolderId, onFolderChange, onUpload, onLoadMore, hasMore, multiple, accept, onSelect, }: MediaPickerDialogProps): react_jsx_runtime.JSX.Element;
385
+ declare function MediaPickerDialog({ open, onOpenChange, title, files, folders, loading, total, typeFilter, onTypeChange, search, onSearch, activeFolderId, onFolderChange, onUpload, onLoadMore, hasMore, multiple, initialSelected, accept, onSelect, }: MediaPickerDialogProps): react_jsx_runtime.JSX.Element;
386
386
 
387
387
  interface ImagePickerFieldProps {
388
388
  value?: string;
package/dist/index.d.ts CHANGED
@@ -367,7 +367,6 @@ interface MediaPickerDialogProps {
367
367
  folders?: MediaPickerDialogFolder[];
368
368
  loading?: boolean;
369
369
  total: number;
370
- uploads?: UploadItem[];
371
370
  typeFilter?: string;
372
371
  onTypeChange?: (type: string) => void;
373
372
  search?: string;
@@ -378,11 +377,12 @@ interface MediaPickerDialogProps {
378
377
  onLoadMore?: () => void;
379
378
  hasMore?: boolean;
380
379
  multiple?: boolean;
380
+ initialSelected?: string[];
381
381
  /** "images" = only show image type tabs; "all" = show all type tabs */
382
382
  accept?: "images" | "all";
383
383
  onSelect: (files: MediaCardFile[]) => void;
384
384
  }
385
- declare function MediaPickerDialog({ open, onOpenChange, title, files, folders, loading, total, uploads, typeFilter, onTypeChange, search, onSearch, activeFolderId, onFolderChange, onUpload, onLoadMore, hasMore, multiple, accept, onSelect, }: MediaPickerDialogProps): react_jsx_runtime.JSX.Element;
385
+ declare function MediaPickerDialog({ open, onOpenChange, title, files, folders, loading, total, typeFilter, onTypeChange, search, onSearch, activeFolderId, onFolderChange, onUpload, onLoadMore, hasMore, multiple, initialSelected, accept, onSelect, }: MediaPickerDialogProps): react_jsx_runtime.JSX.Element;
386
386
 
387
387
  interface ImagePickerFieldProps {
388
388
  value?: string;
package/dist/index.js CHANGED
@@ -2030,7 +2030,6 @@ function MediaPickerDialog({
2030
2030
  folders = [],
2031
2031
  loading = false,
2032
2032
  total,
2033
- uploads = [],
2034
2033
  typeFilter = "all",
2035
2034
  onTypeChange,
2036
2035
  search = "",
@@ -2041,14 +2040,56 @@ function MediaPickerDialog({
2041
2040
  onLoadMore,
2042
2041
  hasMore = false,
2043
2042
  multiple = false,
2043
+ initialSelected = [],
2044
2044
  accept = "all",
2045
2045
  onSelect
2046
2046
  }) {
2047
- const [localSelected, setLocalSelected] = React20.useState(/* @__PURE__ */ new Set());
2047
+ const [localSelected, setLocalSelected] = React20.useState(new Set(initialSelected));
2048
+ const [isDragging, setIsDragging] = React20.useState(false);
2048
2049
  const fileInputRef = React20.useRef(null);
2050
+ const dragCounterRef = React20.useRef(0);
2049
2051
  React20.useEffect(() => {
2050
- if (!open) setLocalSelected(/* @__PURE__ */ new Set());
2052
+ if (open) {
2053
+ setLocalSelected(new Set(initialSelected));
2054
+ } else {
2055
+ setLocalSelected(/* @__PURE__ */ new Set());
2056
+ setIsDragging(false);
2057
+ dragCounterRef.current = 0;
2058
+ }
2051
2059
  }, [open]);
2060
+ const handleDragEnter = (e) => {
2061
+ e.preventDefault();
2062
+ e.stopPropagation();
2063
+ if (e.dataTransfer.types.includes("Files")) {
2064
+ dragCounterRef.current++;
2065
+ setIsDragging(true);
2066
+ }
2067
+ };
2068
+ const handleDragLeave = (e) => {
2069
+ e.preventDefault();
2070
+ e.stopPropagation();
2071
+ dragCounterRef.current--;
2072
+ if (dragCounterRef.current <= 0) {
2073
+ dragCounterRef.current = 0;
2074
+ setIsDragging(false);
2075
+ }
2076
+ };
2077
+ const handleDragOver = (e) => {
2078
+ e.preventDefault();
2079
+ e.stopPropagation();
2080
+ };
2081
+ const handleDrop = (e) => {
2082
+ e.preventDefault();
2083
+ e.stopPropagation();
2084
+ dragCounterRef.current = 0;
2085
+ setIsDragging(false);
2086
+ if (!onUpload || !e.dataTransfer.files.length) return;
2087
+ const accepted = accept === "images" ? Array.from(e.dataTransfer.files).filter((f) => f.type.startsWith("image/")) : Array.from(e.dataTransfer.files);
2088
+ if (!accepted.length) return;
2089
+ const dt = new DataTransfer();
2090
+ accepted.forEach((f) => dt.items.add(f));
2091
+ onUpload(dt.files);
2092
+ };
2052
2093
  const typeOptions = ALL_TYPE_OPTIONS.filter(
2053
2094
  (o) => accept === "images" ? o.value === "all" || o.value === "images" : true
2054
2095
  );
@@ -2072,7 +2113,6 @@ function MediaPickerDialog({
2072
2113
  onUpload(e.target.files);
2073
2114
  }
2074
2115
  };
2075
- const activeUploads = uploads.filter((u) => u.status === "uploading");
2076
2116
  const firstSelected = files.find((f) => localSelected.has(f.id));
2077
2117
  return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Dialog, { open, onOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
2078
2118
  DialogContent,
@@ -2178,41 +2218,49 @@ function MediaPickerDialog({
2178
2218
  )
2179
2219
  ] })
2180
2220
  ] }),
2181
- activeUploads.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "border-b px-4 py-2 space-y-1.5 shrink-0", children: activeUploads.map((u, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center gap-2", children: [
2182
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "flex-1 truncate text-xs text-muted-foreground", children: u.name }),
2183
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "h-1.5 w-24 overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
2184
- "div",
2185
- {
2186
- className: "h-full rounded-full bg-primary transition-all duration-200",
2187
- style: { width: `${u.progress}%` }
2188
- }
2189
- ) }),
2190
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { className: "text-[10px] text-muted-foreground w-6 text-right", children: [
2191
- u.progress,
2192
- "%"
2193
- ] })
2194
- ] }, i)) }),
2195
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex-1 overflow-y-auto p-4", children: [
2196
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
2197
- MediaGrid,
2198
- {
2199
- files,
2200
- selected: localSelected,
2201
- onSelect: handleFileSelect,
2202
- loading,
2203
- columns: 5,
2204
- onUploadClick: onUpload ? () => fileInputRef.current?.click() : void 0
2205
- }
2206
- ),
2207
- hasMore && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
2208
- "button",
2209
- {
2210
- onClick: onLoadMore,
2211
- className: "rounded-lg border px-4 py-2 text-xs text-muted-foreground transition-colors hover:bg-accent",
2212
- children: "Load more"
2213
- }
2214
- ) })
2215
- ] })
2221
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
2222
+ "div",
2223
+ {
2224
+ className: "relative flex-1 overflow-y-auto p-4",
2225
+ onDragEnter: handleDragEnter,
2226
+ onDragLeave: handleDragLeave,
2227
+ onDragOver: handleDragOver,
2228
+ onDrop: handleDrop,
2229
+ children: [
2230
+ isDragging && onUpload && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "pointer-events-none absolute inset-0 z-10 flex flex-col items-center justify-center gap-3 rounded-lg border-2 border-dashed border-primary bg-primary/5 backdrop-blur-[1px]", children: [
2231
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("svg", { className: "h-10 w-10 text-primary opacity-70", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
2232
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
2233
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("polyline", { points: "17 8 12 3 7 8" }),
2234
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
2235
+ ] }),
2236
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("p", { className: "text-sm font-medium text-primary", children: [
2237
+ "Drop ",
2238
+ accept === "images" ? "images" : "files",
2239
+ " to upload"
2240
+ ] })
2241
+ ] }),
2242
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
2243
+ MediaGrid,
2244
+ {
2245
+ files,
2246
+ selected: localSelected,
2247
+ onSelect: handleFileSelect,
2248
+ loading,
2249
+ columns: 5,
2250
+ onUploadClick: onUpload ? () => fileInputRef.current?.click() : void 0
2251
+ }
2252
+ ),
2253
+ hasMore && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
2254
+ "button",
2255
+ {
2256
+ onClick: onLoadMore,
2257
+ className: "rounded-lg border px-4 py-2 text-xs text-muted-foreground transition-colors hover:bg-accent",
2258
+ children: "Load more"
2259
+ }
2260
+ ) })
2261
+ ]
2262
+ }
2263
+ )
2216
2264
  ] })
2217
2265
  ] }),
2218
2266
  localSelected.size > 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center justify-between gap-4 border-t px-5 py-3 shrink-0 bg-muted/20", children: [