@webdevarif/dashui 0.2.2 → 0.2.3

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.js CHANGED
@@ -2045,10 +2045,49 @@ function MediaPickerDialog({
2045
2045
  onSelect
2046
2046
  }) {
2047
2047
  const [localSelected, setLocalSelected] = React20.useState(/* @__PURE__ */ new Set());
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(/* @__PURE__ */ new Set());
2054
+ setIsDragging(false);
2055
+ dragCounterRef.current = 0;
2056
+ }
2051
2057
  }, [open]);
2058
+ const handleDragEnter = (e) => {
2059
+ e.preventDefault();
2060
+ e.stopPropagation();
2061
+ if (e.dataTransfer.types.includes("Files")) {
2062
+ dragCounterRef.current++;
2063
+ setIsDragging(true);
2064
+ }
2065
+ };
2066
+ const handleDragLeave = (e) => {
2067
+ e.preventDefault();
2068
+ e.stopPropagation();
2069
+ dragCounterRef.current--;
2070
+ if (dragCounterRef.current <= 0) {
2071
+ dragCounterRef.current = 0;
2072
+ setIsDragging(false);
2073
+ }
2074
+ };
2075
+ const handleDragOver = (e) => {
2076
+ e.preventDefault();
2077
+ e.stopPropagation();
2078
+ };
2079
+ const handleDrop = (e) => {
2080
+ e.preventDefault();
2081
+ e.stopPropagation();
2082
+ dragCounterRef.current = 0;
2083
+ setIsDragging(false);
2084
+ if (!onUpload || !e.dataTransfer.files.length) return;
2085
+ const accepted = accept === "images" ? Array.from(e.dataTransfer.files).filter((f) => f.type.startsWith("image/")) : Array.from(e.dataTransfer.files);
2086
+ if (!accepted.length) return;
2087
+ const dt = new DataTransfer();
2088
+ accepted.forEach((f) => dt.items.add(f));
2089
+ onUpload(dt.files);
2090
+ };
2052
2091
  const typeOptions = ALL_TYPE_OPTIONS.filter(
2053
2092
  (o) => accept === "images" ? o.value === "all" || o.value === "images" : true
2054
2093
  );
@@ -2192,27 +2231,49 @@ function MediaPickerDialog({
2192
2231
  "%"
2193
2232
  ] })
2194
2233
  ] }, 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
- ] })
2234
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
2235
+ "div",
2236
+ {
2237
+ className: "relative flex-1 overflow-y-auto p-4",
2238
+ onDragEnter: handleDragEnter,
2239
+ onDragLeave: handleDragLeave,
2240
+ onDragOver: handleDragOver,
2241
+ onDrop: handleDrop,
2242
+ children: [
2243
+ 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: [
2244
+ /* @__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: [
2245
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
2246
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("polyline", { points: "17 8 12 3 7 8" }),
2247
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
2248
+ ] }),
2249
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("p", { className: "text-sm font-medium text-primary", children: [
2250
+ "Drop ",
2251
+ accept === "images" ? "images" : "files",
2252
+ " to upload"
2253
+ ] })
2254
+ ] }),
2255
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
2256
+ MediaGrid,
2257
+ {
2258
+ files,
2259
+ selected: localSelected,
2260
+ onSelect: handleFileSelect,
2261
+ loading,
2262
+ columns: 5,
2263
+ onUploadClick: onUpload ? () => fileInputRef.current?.click() : void 0
2264
+ }
2265
+ ),
2266
+ hasMore && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
2267
+ "button",
2268
+ {
2269
+ onClick: onLoadMore,
2270
+ className: "rounded-lg border px-4 py-2 text-xs text-muted-foreground transition-colors hover:bg-accent",
2271
+ children: "Load more"
2272
+ }
2273
+ ) })
2274
+ ]
2275
+ }
2276
+ )
2216
2277
  ] })
2217
2278
  ] }),
2218
2279
  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: [