@webdevarif/dashui 0.2.0 → 0.2.2

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.mjs CHANGED
@@ -1880,12 +1880,11 @@ function MediaGrid({
1880
1880
  // src/components/media/media-picker-dialog.tsx
1881
1881
  import * as React20 from "react";
1882
1882
  import { Fragment as Fragment4, jsx as jsx34, jsxs as jsxs20 } from "react/jsx-runtime";
1883
- var TYPE_OPTIONS = [
1884
- { value: "", label: "All" },
1885
- { value: "image", label: "Images" },
1886
- { value: "video", label: "Videos" },
1887
- { value: "audio", label: "Audio" },
1888
- { value: "document", label: "Docs" }
1883
+ var ALL_TYPE_OPTIONS = [
1884
+ { value: "all", label: "All" },
1885
+ { value: "images", label: "Images" },
1886
+ { value: "videos", label: "Videos" },
1887
+ { value: "documents", label: "Docs" }
1889
1888
  ];
1890
1889
  function MediaPickerDialog({
1891
1890
  open,
@@ -1896,7 +1895,7 @@ function MediaPickerDialog({
1896
1895
  loading = false,
1897
1896
  total,
1898
1897
  uploads = [],
1899
- typeFilter = "",
1898
+ typeFilter = "all",
1900
1899
  onTypeChange,
1901
1900
  search = "",
1902
1901
  onSearch,
@@ -1911,22 +1910,21 @@ function MediaPickerDialog({
1911
1910
  }) {
1912
1911
  const [localSelected, setLocalSelected] = React20.useState(/* @__PURE__ */ new Set());
1913
1912
  const fileInputRef = React20.useRef(null);
1913
+ React20.useEffect(() => {
1914
+ if (!open) setLocalSelected(/* @__PURE__ */ new Set());
1915
+ }, [open]);
1916
+ const typeOptions = ALL_TYPE_OPTIONS.filter(
1917
+ (o) => accept === "images" ? o.value === "all" || o.value === "images" : true
1918
+ );
1914
1919
  const handleFileSelect = (file) => {
1915
- if (multiple) {
1916
- setLocalSelected((prev) => {
1920
+ setLocalSelected((prev) => {
1921
+ if (multiple) {
1917
1922
  const next = new Set(prev);
1918
- if (next.has(file.id)) {
1919
- next.delete(file.id);
1920
- } else {
1921
- next.add(file.id);
1922
- }
1923
+ next.has(file.id) ? next.delete(file.id) : next.add(file.id);
1923
1924
  return next;
1924
- });
1925
- } else {
1926
- const selected = files.filter((f) => f.id === file.id);
1927
- onSelect(selected);
1928
- onOpenChange(false);
1929
- }
1925
+ }
1926
+ return prev.has(file.id) ? /* @__PURE__ */ new Set() : /* @__PURE__ */ new Set([file.id]);
1927
+ });
1930
1928
  };
1931
1929
  const handleConfirm = () => {
1932
1930
  const selected = files.filter((f) => localSelected.has(f.id));
@@ -1939,163 +1937,179 @@ function MediaPickerDialog({
1939
1937
  }
1940
1938
  };
1941
1939
  const activeUploads = uploads.filter((u) => u.status === "uploading");
1942
- return /* @__PURE__ */ jsx34(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs20(DialogContent, { className: "flex h-[85vh] max-h-[700px] max-w-4xl flex-col gap-0 p-0", children: [
1943
- /* @__PURE__ */ jsxs20(DialogHeader, { className: "flex-row items-center justify-between border-b px-5 py-3", children: [
1944
- /* @__PURE__ */ jsx34(DialogTitle, { className: "text-base", children: title }),
1945
- /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2", children: [
1946
- /* @__PURE__ */ jsxs20("span", { className: "text-xs text-muted-foreground", children: [
1947
- total,
1948
- " files"
1949
- ] }),
1950
- onUpload && /* @__PURE__ */ jsxs20(Fragment4, { children: [
1951
- /* @__PURE__ */ jsx34(
1952
- "input",
1953
- {
1954
- ref: fileInputRef,
1955
- type: "file",
1956
- className: "hidden",
1957
- multiple: true,
1958
- accept: accept === "images" ? "image/*" : void 0,
1959
- onChange: handleUploadChange
1960
- }
1961
- ),
1962
- /* @__PURE__ */ jsxs20(
1963
- "button",
1964
- {
1965
- onClick: () => fileInputRef.current?.click(),
1966
- className: "flex items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground transition-opacity hover:opacity-90",
1967
- children: [
1968
- /* @__PURE__ */ jsxs20("svg", { className: "h-3.5 w-3.5", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1969
- /* @__PURE__ */ jsx34("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
1970
- /* @__PURE__ */ jsx34("polyline", { points: "17 8 12 3 7 8" }),
1971
- /* @__PURE__ */ jsx34("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
1972
- ] }),
1973
- "Upload"
1974
- ]
1975
- }
1976
- )
1977
- ] })
1978
- ] })
1979
- ] }),
1980
- /* @__PURE__ */ jsxs20("div", { className: "flex flex-1 overflow-hidden", children: [
1981
- folders.length > 0 && /* @__PURE__ */ jsxs20("aside", { className: "flex w-44 shrink-0 flex-col gap-0.5 overflow-y-auto border-r p-2", children: [
1982
- /* @__PURE__ */ jsxs20(
1983
- "button",
1984
- {
1985
- onClick: () => onFolderChange?.(""),
1986
- className: cn(
1987
- "flex w-full items-center gap-2 rounded-md px-2.5 py-1.5 text-sm transition-colors",
1988
- !activeFolderId ? "bg-primary/10 font-medium text-primary" : "text-muted-foreground hover:bg-accent"
1989
- ),
1990
- children: [
1991
- /* @__PURE__ */ jsx34("svg", { className: "h-3.5 w-3.5", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx34("path", { d: "M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" }) }),
1992
- "All files"
1993
- ]
1994
- }
1995
- ),
1996
- folders.map((folder) => /* @__PURE__ */ jsxs20(
1997
- "button",
1998
- {
1999
- onClick: () => onFolderChange?.(folder.id),
2000
- className: cn(
2001
- "flex w-full items-center gap-2 rounded-md px-2.5 py-1.5 text-sm transition-colors",
2002
- activeFolderId === folder.id ? "bg-primary/10 font-medium text-primary" : "text-muted-foreground hover:bg-accent"
2003
- ),
2004
- children: [
2005
- /* @__PURE__ */ jsx34("span", { className: "text-base leading-none", children: folder.icon ?? "\u{1F4C1}" }),
2006
- /* @__PURE__ */ jsx34("span", { className: "truncate", children: folder.name })
2007
- ]
2008
- },
2009
- folder.id
2010
- ))
2011
- ] }),
2012
- /* @__PURE__ */ jsxs20("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
2013
- /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2 border-b px-4 py-2", children: [
2014
- /* @__PURE__ */ jsxs20("div", { className: "relative flex-1", children: [
2015
- /* @__PURE__ */ jsxs20("svg", { className: "pointer-events-none absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2016
- /* @__PURE__ */ jsx34("circle", { cx: "11", cy: "11", r: "8" }),
2017
- /* @__PURE__ */ jsx34("path", { d: "m21 21-4.35-4.35" })
2018
- ] }),
1940
+ const firstSelected = files.find((f) => localSelected.has(f.id));
1941
+ return /* @__PURE__ */ jsx34(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs20(
1942
+ DialogContent,
1943
+ {
1944
+ "aria-describedby": void 0,
1945
+ className: "flex h-[85vh] max-h-[700px] max-w-4xl flex-col gap-0 p-0",
1946
+ children: [
1947
+ /* @__PURE__ */ jsxs20(DialogHeader, { className: "flex-row items-center gap-3 border-b px-5 py-3 pr-12 space-y-0 shrink-0", children: [
1948
+ onUpload && /* @__PURE__ */ jsxs20(Fragment4, { children: [
2019
1949
  /* @__PURE__ */ jsx34(
2020
1950
  "input",
2021
1951
  {
2022
- type: "search",
2023
- value: search,
2024
- onChange: (e) => onSearch?.(e.target.value),
2025
- placeholder: "Search files\u2026",
2026
- className: "h-7 w-full rounded-md border border-input bg-muted/50 pl-8 pr-3 text-xs outline-none focus:border-primary focus:ring-1 focus:ring-primary"
1952
+ ref: fileInputRef,
1953
+ type: "file",
1954
+ className: "hidden",
1955
+ multiple: true,
1956
+ accept: accept === "images" ? "image/*" : void 0,
1957
+ onChange: handleUploadChange
1958
+ }
1959
+ ),
1960
+ /* @__PURE__ */ jsxs20(
1961
+ "button",
1962
+ {
1963
+ onClick: () => fileInputRef.current?.click(),
1964
+ className: "flex shrink-0 items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground transition-opacity hover:opacity-90",
1965
+ children: [
1966
+ /* @__PURE__ */ jsxs20("svg", { className: "h-3.5 w-3.5", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1967
+ /* @__PURE__ */ jsx34("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
1968
+ /* @__PURE__ */ jsx34("polyline", { points: "17 8 12 3 7 8" }),
1969
+ /* @__PURE__ */ jsx34("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
1970
+ ] }),
1971
+ "Upload"
1972
+ ]
2027
1973
  }
2028
1974
  )
2029
1975
  ] }),
2030
- /* @__PURE__ */ jsx34("div", { className: "flex gap-1", children: TYPE_OPTIONS.filter((o) => accept === "images" ? o.value === "" || o.value === "image" : true).map((opt) => /* @__PURE__ */ jsx34(
2031
- "button",
2032
- {
2033
- onClick: () => onTypeChange?.(opt.value),
2034
- className: cn(
2035
- "rounded px-2 py-1 text-xs transition-colors",
2036
- typeFilter === opt.value ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-accent"
2037
- ),
2038
- children: opt.label
2039
- },
2040
- opt.value
2041
- )) })
1976
+ /* @__PURE__ */ jsx34(DialogTitle, { className: "text-sm font-semibold flex-1", children: title }),
1977
+ /* @__PURE__ */ jsxs20("span", { className: "text-xs text-muted-foreground shrink-0", children: [
1978
+ total,
1979
+ " files"
1980
+ ] })
2042
1981
  ] }),
2043
- activeUploads.length > 0 && /* @__PURE__ */ jsx34("div", { className: "border-b px-4 py-2 space-y-1.5", children: activeUploads.map((u, i) => /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2", children: [
2044
- /* @__PURE__ */ jsx34("span", { className: "flex-1 truncate text-xs text-muted-foreground", children: u.name }),
2045
- /* @__PURE__ */ jsx34("div", { className: "h-1.5 w-24 overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ jsx34(
2046
- "div",
2047
- {
2048
- className: "h-full rounded-full bg-primary transition-all",
2049
- style: { width: `${u.progress}%` }
2050
- }
2051
- ) }),
2052
- /* @__PURE__ */ jsxs20("span", { className: "text-[10px] text-muted-foreground", children: [
2053
- u.progress,
2054
- "%"
1982
+ /* @__PURE__ */ jsxs20("div", { className: "flex flex-1 overflow-hidden min-h-0", children: [
1983
+ folders.length > 0 && /* @__PURE__ */ jsxs20("aside", { className: "flex w-44 shrink-0 flex-col gap-0.5 overflow-y-auto border-r p-2", children: [
1984
+ /* @__PURE__ */ jsxs20(
1985
+ "button",
1986
+ {
1987
+ onClick: () => onFolderChange?.(""),
1988
+ className: cn(
1989
+ "flex w-full items-center gap-2 rounded-md px-2.5 py-1.5 text-sm transition-colors",
1990
+ !activeFolderId ? "bg-primary/10 font-medium text-primary" : "text-muted-foreground hover:bg-accent"
1991
+ ),
1992
+ children: [
1993
+ /* @__PURE__ */ jsx34("svg", { className: "h-3.5 w-3.5 shrink-0", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx34("path", { d: "M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" }) }),
1994
+ "All files"
1995
+ ]
1996
+ }
1997
+ ),
1998
+ folders.map((folder) => /* @__PURE__ */ jsxs20(
1999
+ "button",
2000
+ {
2001
+ onClick: () => onFolderChange?.(folder.id),
2002
+ className: cn(
2003
+ "flex w-full items-center gap-2 rounded-md px-2.5 py-1.5 text-sm transition-colors",
2004
+ activeFolderId === folder.id ? "bg-primary/10 font-medium text-primary" : "text-muted-foreground hover:bg-accent"
2005
+ ),
2006
+ children: [
2007
+ /* @__PURE__ */ jsx34("span", { className: "text-base leading-none", children: folder.icon ?? "\u{1F4C1}" }),
2008
+ /* @__PURE__ */ jsx34("span", { className: "truncate", children: folder.name })
2009
+ ]
2010
+ },
2011
+ folder.id
2012
+ ))
2013
+ ] }),
2014
+ /* @__PURE__ */ jsxs20("div", { className: "flex flex-1 flex-col overflow-hidden min-w-0", children: [
2015
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2 border-b px-4 py-2 shrink-0", children: [
2016
+ /* @__PURE__ */ jsx34("div", { className: "flex items-center gap-0.5 rounded-lg border border-input bg-muted/50 p-0.5", children: typeOptions.map((opt) => /* @__PURE__ */ jsx34(
2017
+ "button",
2018
+ {
2019
+ onClick: () => onTypeChange?.(opt.value),
2020
+ className: cn(
2021
+ "rounded-md px-2.5 py-1 text-xs font-medium transition-colors",
2022
+ typeFilter === opt.value ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
2023
+ ),
2024
+ children: opt.label
2025
+ },
2026
+ opt.value
2027
+ )) }),
2028
+ /* @__PURE__ */ jsxs20("div", { className: "relative flex-1 max-w-xs ml-auto", children: [
2029
+ /* @__PURE__ */ jsxs20("svg", { className: "pointer-events-none absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2030
+ /* @__PURE__ */ jsx34("circle", { cx: "11", cy: "11", r: "8" }),
2031
+ /* @__PURE__ */ jsx34("path", { d: "m21 21-4.35-4.35" })
2032
+ ] }),
2033
+ /* @__PURE__ */ jsx34(
2034
+ "input",
2035
+ {
2036
+ type: "search",
2037
+ value: search,
2038
+ onChange: (e) => onSearch?.(e.target.value),
2039
+ placeholder: "Search\u2026",
2040
+ className: "h-8 w-full rounded-lg border border-input bg-background pl-8 pr-3 text-xs outline-none focus:border-primary focus:ring-1 focus:ring-primary/30"
2041
+ }
2042
+ )
2043
+ ] })
2044
+ ] }),
2045
+ activeUploads.length > 0 && /* @__PURE__ */ jsx34("div", { className: "border-b px-4 py-2 space-y-1.5 shrink-0", children: activeUploads.map((u, i) => /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2", children: [
2046
+ /* @__PURE__ */ jsx34("span", { className: "flex-1 truncate text-xs text-muted-foreground", children: u.name }),
2047
+ /* @__PURE__ */ jsx34("div", { className: "h-1.5 w-24 overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ jsx34(
2048
+ "div",
2049
+ {
2050
+ className: "h-full rounded-full bg-primary transition-all duration-200",
2051
+ style: { width: `${u.progress}%` }
2052
+ }
2053
+ ) }),
2054
+ /* @__PURE__ */ jsxs20("span", { className: "text-[10px] text-muted-foreground w-6 text-right", children: [
2055
+ u.progress,
2056
+ "%"
2057
+ ] })
2058
+ ] }, i)) }),
2059
+ /* @__PURE__ */ jsxs20("div", { className: "flex-1 overflow-y-auto p-4", children: [
2060
+ /* @__PURE__ */ jsx34(
2061
+ MediaGrid,
2062
+ {
2063
+ files,
2064
+ selected: localSelected,
2065
+ onSelect: handleFileSelect,
2066
+ loading,
2067
+ columns: 5,
2068
+ onUploadClick: onUpload ? () => fileInputRef.current?.click() : void 0
2069
+ }
2070
+ ),
2071
+ hasMore && /* @__PURE__ */ jsx34("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx34(
2072
+ "button",
2073
+ {
2074
+ onClick: onLoadMore,
2075
+ className: "rounded-lg border px-4 py-2 text-xs text-muted-foreground transition-colors hover:bg-accent",
2076
+ children: "Load more"
2077
+ }
2078
+ ) })
2079
+ ] })
2055
2080
  ] })
2056
- ] }, i)) }),
2057
- /* @__PURE__ */ jsxs20("div", { className: "flex-1 overflow-y-auto p-4", children: [
2058
- /* @__PURE__ */ jsx34(
2059
- MediaGrid,
2060
- {
2061
- files,
2062
- selected: localSelected,
2063
- onSelect: handleFileSelect,
2064
- loading,
2065
- columns: 5,
2066
- onUploadClick: onUpload ? () => fileInputRef.current?.click() : void 0
2067
- }
2068
- ),
2069
- hasMore && /* @__PURE__ */ jsx34("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx34(
2070
- "button",
2071
- {
2072
- onClick: onLoadMore,
2073
- className: "rounded-md border px-4 py-2 text-sm text-muted-foreground transition-colors hover:bg-accent",
2074
- children: "Load more"
2075
- }
2076
- ) })
2077
2081
  ] }),
2078
- multiple && localSelected.size > 0 && /* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-between border-t px-4 py-3", children: [
2082
+ localSelected.size > 0 && /* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-between gap-4 border-t px-5 py-3 shrink-0 bg-muted/20", children: [
2079
2083
  /* @__PURE__ */ jsxs20("span", { className: "text-sm text-muted-foreground", children: [
2080
2084
  localSelected.size,
2085
+ " file",
2086
+ localSelected.size !== 1 ? "s" : "",
2081
2087
  " selected"
2082
2088
  ] }),
2083
- /* @__PURE__ */ jsxs20("div", { className: "flex gap-2", children: [
2089
+ firstSelected && firstSelected.mimeType.startsWith("image/") && /* @__PURE__ */ jsx34(
2090
+ "img",
2091
+ {
2092
+ src: firstSelected.url,
2093
+ alt: firstSelected.name,
2094
+ className: "h-9 w-9 rounded-lg border border-border object-cover shadow-sm"
2095
+ }
2096
+ ),
2097
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2", children: [
2084
2098
  /* @__PURE__ */ jsx34(
2085
2099
  "button",
2086
2100
  {
2087
2101
  onClick: () => setLocalSelected(/* @__PURE__ */ new Set()),
2088
- className: "rounded-md px-3 py-1.5 text-sm text-muted-foreground transition-colors hover:bg-accent",
2089
- children: "Clear"
2102
+ className: "rounded-lg px-3 py-1.5 text-sm text-muted-foreground transition-colors hover:bg-accent",
2103
+ children: "Cancel"
2090
2104
  }
2091
2105
  ),
2092
2106
  /* @__PURE__ */ jsxs20(
2093
2107
  "button",
2094
2108
  {
2095
2109
  onClick: handleConfirm,
2096
- className: "rounded-md bg-primary px-4 py-1.5 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90",
2110
+ className: "rounded-lg bg-primary px-4 py-1.5 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90",
2097
2111
  children: [
2098
- "Insert ",
2112
+ "Use ",
2099
2113
  localSelected.size,
2100
2114
  " file",
2101
2115
  localSelected.size !== 1 ? "s" : ""
@@ -2104,9 +2118,9 @@ function MediaPickerDialog({
2104
2118
  )
2105
2119
  ] })
2106
2120
  ] })
2107
- ] })
2108
- ] })
2109
- ] }) });
2121
+ ]
2122
+ }
2123
+ ) });
2110
2124
  }
2111
2125
 
2112
2126
  // src/components/media/image-picker-field.tsx