@blakesteve/roster 5.14.0 → 5.16.0

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.
Files changed (33) hide show
  1. package/README.md +153 -38
  2. package/dist/components/molecules/FileUpload/FileUpload.cjs +1 -1
  3. package/dist/components/molecules/FileUpload/FileUpload.d.ts +20 -3
  4. package/dist/components/molecules/FileUpload/FileUpload.js +266 -216
  5. package/dist/components/molecules/FileUpload/file-upload-rejection.cjs +1 -0
  6. package/dist/components/molecules/FileUpload/file-upload-rejection.d.ts +24 -0
  7. package/dist/components/molecules/FileUpload/file-upload-rejection.js +11 -0
  8. package/dist/components/molecules/LiquidTabs/LiquidCount.d.ts +2 -2
  9. package/dist/components/molecules/LiquidTabs/LiquidTabPanel.cjs +1 -1
  10. package/dist/components/molecules/LiquidTabs/LiquidTabPanel.d.ts +10 -49
  11. package/dist/components/molecules/LiquidTabs/LiquidTabPanel.js +5 -28
  12. package/dist/components/molecules/LiquidTabs/LiquidTabs.cjs +1 -1
  13. package/dist/components/molecules/LiquidTabs/LiquidTabs.d.ts +13 -40
  14. package/dist/components/molecules/LiquidTabs/LiquidTabs.js +5 -95
  15. package/dist/components/molecules/LiquidTabs/liquid-count.d.ts +7 -5
  16. package/dist/components/molecules/LiquidTabs/liquid-tab-id.cjs +1 -1
  17. package/dist/components/molecules/LiquidTabs/liquid-tab-id.d.ts +4 -9
  18. package/dist/components/molecules/LiquidTabs/liquid-tab-id.js +3 -4
  19. package/dist/components/molecules/Tabs/TabPanel.cjs +1 -0
  20. package/dist/components/molecules/Tabs/TabPanel.d.ts +53 -0
  21. package/dist/components/molecules/Tabs/TabPanel.js +32 -0
  22. package/dist/components/molecules/Tabs/Tabs.cjs +1 -0
  23. package/dist/components/molecules/Tabs/Tabs.d.ts +118 -0
  24. package/dist/components/molecules/Tabs/Tabs.js +145 -0
  25. package/dist/components/molecules/Tabs/tab-id.cjs +1 -0
  26. package/dist/components/molecules/Tabs/tab-id.d.ts +13 -0
  27. package/dist/components/molecules/Tabs/tab-id.js +6 -0
  28. package/dist/index.d.ts +4 -0
  29. package/dist/meta.json +3 -3
  30. package/dist/roster.cjs +1 -1
  31. package/dist/roster.css +1 -1
  32. package/dist/roster.js +150 -142
  33. package/package.json +1 -1
@@ -1,219 +1,258 @@
1
1
  "use client";
2
- import { jsxs as p, jsx as n } from "react/jsx-runtime";
3
- import { useId as vr, useState as M, useRef as f, useCallback as U, useLayoutEffect as Y, useEffect as xr } from "react";
2
+ import { jsxs as x, jsx as n } from "react/jsx-runtime";
3
+ import { useEffect as rt, useId as $t, useState as C, useRef as y, useCallback as F, useLayoutEffect as et } from "react";
4
4
  import { cn as g } from "../../../lib/utils.js";
5
- import { withLabels as yr } from "../../../lib/labels.js";
6
- import { Button as G } from "../../atoms/Button/Button.js";
7
- import { Progress as br } from "../../atoms/Progress/Progress.js";
8
- import { acceptList as kr, formatBytes as Z, sameFile as Nr, matchesType as wr } from "./file-rules.js";
9
- import { useKeyFocus as $r } from "../../../internal/key-focus.js";
10
- const jr = {
5
+ import { withLabels as Lt } from "../../../lib/labels.js";
6
+ import { Button as K } from "../../atoms/Button/Button.js";
7
+ import { Progress as Mt } from "../../atoms/Progress/Progress.js";
8
+ import { acceptList as Dt, formatBytes as st, sameFile as nt, matchesType as Tt } from "./file-rules.js";
9
+ import { isFileUploadRejection as Rt } from "./file-upload-rejection.js";
10
+ import { useKeyFocus as Et } from "../../../internal/key-focus.js";
11
+ import { isDevelopment as qt } from "../../../internal/dev.js";
12
+ const Ct = {
11
13
  choose: "Choose photos",
14
+ replace: "Replace photo",
12
15
  dropHint: "or drag them here",
13
16
  dropHere: "Drop to add them",
14
17
  queued: "Waiting",
15
- uploading: (s) => s === null ? "Uploading" : `Uploading, ${s}%`,
18
+ uploading: (e) => e === null ? "Uploading" : `Uploading, ${e}%`,
16
19
  processing: "Finishing up",
17
20
  done: "Uploaded",
18
21
  failed: "Didn't upload.",
19
22
  rejected: "Not added.",
20
- remove: (s) => `Remove ${s}`,
21
- retry: (s) => `Try ${s} again`,
23
+ remove: (e) => `Remove ${e}`,
24
+ retry: (e) => `Try ${e} again`,
22
25
  wrongType: () => "That type of file isn't accepted.",
23
- tooLarge: (s, d) => `It's over ${Z(d)}.`,
24
- tooMany: (s) => `Only ${s} can be added.`,
26
+ tooLarge: (e, l) => `It's over ${st(l)}.`,
27
+ tooMany: (e) => `Only ${e} can be added.`,
25
28
  duplicate: () => "It's already added.",
26
- uploadError: (s) => s instanceof Error && s.message ? s.message : "Something went wrong.",
27
- size: Z,
28
- added: (s) => `${s} ${s === 1 ? "photo" : "photos"} added.`,
29
- progress: (s, d) => `${s} of ${d} uploaded.`,
30
- failedNotice: (s, d) => `${s} didn't upload. ${d}`,
31
- rejectedNotice: (s, d) => `${s} wasn't added. ${d}`,
32
- removed: (s) => `${s} removed.`
29
+ uploadError: (e) => e instanceof Error && e.message ? e.message : "Something went wrong.",
30
+ size: st,
31
+ added: (e) => `${e} ${e === 1 ? "photo" : "photos"} added.`,
32
+ progress: (e, l) => `${e} of ${l} uploaded.`,
33
+ failedNotice: (e, l) => `${e} didn't upload. ${l}`,
34
+ rejectedNotice: (e, l) => `${e} wasn't added. ${l}`,
35
+ removed: (e) => `${e} removed.`
33
36
  };
34
- function Lr({ file: s, status: d }) {
35
- const [T, D] = M(!1), B = !T && (s.type.startsWith("image/") || /\.(jpe?g|png|gif|webp|avif|heic|heif)$/i.test(s.name)), $ = U(
36
- (q) => {
37
- if (!q) return;
38
- const j = URL.createObjectURL(s);
39
- return q.src = j, () => URL.revokeObjectURL(j);
37
+ function ot(e) {
38
+ const [l, h] = C(!1), b = !l && (e.type.startsWith("image/") || /\.(jpe?g|png|gif|webp|avif|heic|heif)$/i.test(e.name)), w = F(
39
+ (m) => {
40
+ if (!m) return;
41
+ const p = URL.createObjectURL(e);
42
+ return m.src = p, () => URL.revokeObjectURL(p);
40
43
  },
41
- [s]
42
- ), v = "rst:h-14 rst:w-14 rst:shrink-0 rst:rounded-md rst:border rst:border-[var(--roster-card-border)]";
43
- return B ? /* @__PURE__ */ n(
44
+ [e]
45
+ );
46
+ return { image: b, attach: w, broke: () => h(!0) };
47
+ }
48
+ const at = /* @__PURE__ */ x("svg", { viewBox: "0 0 24 24", width: "24", height: "24", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round", children: [
49
+ /* @__PURE__ */ n("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
50
+ /* @__PURE__ */ n("circle", { cx: "9", cy: "10", r: "1.6" }),
51
+ /* @__PURE__ */ n("path", { d: "m21 15-4.2-4.2a1.6 1.6 0 0 0-2.3 0L7 18" })
52
+ ] });
53
+ function zt({ file: e, status: l }) {
54
+ const { image: h, attach: b, broke: w } = ot(e), m = "rst:h-14 rst:w-14 rst:shrink-0 rst:rounded-md rst:border rst:border-[var(--roster-card-border)]";
55
+ return h ? /* @__PURE__ */ n(
44
56
  "img",
45
57
  {
46
- ref: $,
58
+ ref: b,
47
59
  alt: "",
48
- onError: () => D(!0),
49
- className: g(v, "rst:object-cover", d === "rejected" && "rst:opacity-50"),
60
+ onError: w,
61
+ className: g(m, "rst:object-cover", l === "rejected" && "rst:opacity-50"),
50
62
  "data-file-thumb": "image"
51
63
  }
52
64
  ) : /* @__PURE__ */ n(
53
65
  "span",
54
66
  {
55
67
  "aria-hidden": "true",
56
- className: g(v, "rst:flex rst:items-center rst:justify-center rst:text-gray-500 rst:dark:text-gray-400"),
68
+ className: g(m, "rst:flex rst:items-center rst:justify-center rst:text-gray-500 rst:dark:text-gray-400"),
57
69
  "data-file-thumb": "placeholder",
58
- children: /* @__PURE__ */ p("svg", { viewBox: "0 0 24 24", width: "24", height: "24", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round", children: [
59
- /* @__PURE__ */ n("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
60
- /* @__PURE__ */ n("circle", { cx: "9", cy: "10", r: "1.6" }),
61
- /* @__PURE__ */ n("path", { d: "m21 15-4.2-4.2a1.6 1.6 0 0 0-2.3 0L7 18" })
62
- ] })
70
+ children: at
71
+ }
72
+ );
73
+ }
74
+ function It({ file: e, status: l }) {
75
+ const { image: h, attach: b, broke: w } = ot(e);
76
+ return /* @__PURE__ */ n(
77
+ "span",
78
+ {
79
+ "aria-hidden": "true",
80
+ className: "rst:pointer-events-none rst:absolute rst:inset-3 rst:flex rst:items-center rst:justify-center",
81
+ "data-file-preview": h ? "image" : "placeholder",
82
+ children: h ? /* @__PURE__ */ n(
83
+ "img",
84
+ {
85
+ ref: b,
86
+ alt: "",
87
+ onError: w,
88
+ className: g("rst:h-full rst:w-full rst:rounded-md rst:object-contain", l === "rejected" && "rst:opacity-50")
89
+ }
90
+ ) : /* @__PURE__ */ n("span", { className: "rst:text-gray-500 rst:dark:text-gray-400", children: at })
63
91
  }
64
92
  );
65
93
  }
66
- const K = "rst:cursor-not-allowed rst:opacity-50", I = { width: 20, height: 20, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" };
67
- function Ur({
68
- label: s,
69
- upload: d,
70
- onChange: T,
71
- accept: D = "image/*",
72
- types: B,
73
- maxSize: $,
74
- maxFiles: v,
75
- validate: q,
76
- concurrency: j = 3,
77
- helperText: F,
78
- errorMessage: R,
79
- disabled: i = !1,
80
- strings: rr,
81
- className: tr
94
+ const V = "rst:cursor-not-allowed rst:opacity-50", B = { width: 20, height: 20, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" };
95
+ function Gt({
96
+ label: e,
97
+ upload: l,
98
+ onChange: h,
99
+ accept: b = "image/*",
100
+ types: w,
101
+ maxSize: m,
102
+ maxFiles: p,
103
+ validate: it,
104
+ concurrency: J = 3,
105
+ helperText: O,
106
+ errorMessage: z,
107
+ disabled: u = !1,
108
+ strings: ct,
109
+ className: dt,
110
+ preview: P = "row"
82
111
  }) {
83
- $r();
84
- const a = yr(jr, rr), C = vr(), S = `${C}-label`, V = `${C}-help`, _ = `${C}-error`, [z, er] = M([]), u = f(z), sr = f(0), x = f(/* @__PURE__ */ new Map()), O = f(null), J = f(null), h = f({ upload: d, onChange: T, concurrency: j, t: a, pump: () => {
85
- } }), [A, nr] = M({ text: "", n: 0 }), y = f([]), b = f(null), L = U((r, e = !1) => {
86
- e && (y.current = y.current.filter((t) => !t.count)), y.current.push({ text: r, count: e }), !b.current && (b.current = setTimeout(() => {
87
- b.current = null;
88
- const t = y.current.map((c) => c.text).join(" ");
89
- y.current = [], nr((c) => ({ text: t, n: c.n + 1 }));
112
+ Et();
113
+ const E = P === "dropzone" && p === 1;
114
+ rt(() => {
115
+ P === "dropzone" && p !== 1 && qt() && console.warn(`FileUpload: preview="dropzone" shows one file, so it takes maxFiles={1}. With maxFiles=${p}, the pictures stay on the rows.`);
116
+ }, [P, p]);
117
+ const a = Lt(Ct, ct), I = $t(), S = `${I}-label`, Q = `${I}-help`, X = `${I}-error`, [q, lt] = C([]), f = y(q), ut = y(0), v = y(/* @__PURE__ */ new Map()), A = y(null), Y = y(null), j = y({ upload: l, onChange: h, concurrency: J, t: a, pump: () => {
118
+ } }), [H, ft] = C({ text: "", n: 0 }), M = y([]), D = y(null), N = F((t, s = !1) => {
119
+ s && (M.current = M.current.filter((r) => !r.count)), M.current.push({ text: t, count: s }), !D.current && (D.current = setTimeout(() => {
120
+ D.current = null;
121
+ const r = M.current.map((i) => i.text).join(" ");
122
+ M.current = [], ft((i) => ({ text: r, n: i.n + 1 }));
90
123
  }, 0));
91
- }, []), H = f(null), [or, ar] = M(0), Q = (r) => {
92
- H.current = r, ar((e) => e + 1);
124
+ }, []), W = y(null), [pt, gt] = C(0), Z = (t) => {
125
+ W.current = t, gt((s) => s + 1);
93
126
  };
94
- Y(() => {
95
- const r = H.current;
96
- if (!r) return;
97
- H.current = null, (O.current?.querySelector(r) ?? O.current?.querySelector("[data-file-choose]"))?.focus();
98
- }, [or]);
99
- const k = U((r) => {
100
- u.current = r, er(r), h.current.onChange?.(r);
101
- }, []), N = U(
102
- (r, e) => {
103
- u.current.some((t) => t.id === r) && k(u.current.map((t) => t.id === r ? { ...t, ...e } : t));
127
+ et(() => {
128
+ const t = W.current;
129
+ if (!t) return;
130
+ W.current = null, (A.current?.querySelector(t) ?? A.current?.querySelector("[data-file-choose]"))?.focus();
131
+ }, [pt]);
132
+ const T = F((t) => {
133
+ f.current = t, lt(t), j.current.onChange?.(t);
134
+ }, []), $ = F(
135
+ (t, s) => {
136
+ f.current.some((r) => r.id === t) && T(f.current.map((r) => r.id === t ? { ...r, ...s } : r));
104
137
  },
105
- [k]
138
+ [T]
106
139
  );
107
- function w() {
108
- const { concurrency: r } = h.current, e = u.current.filter((c) => c.status === "uploading" || c.status === "processing").length, t = u.current.filter((c) => c.status === "queued").slice(0, Math.max(0, Math.max(1, r) - e));
109
- for (const c of t) cr(c);
140
+ function R() {
141
+ const { concurrency: t } = j.current, s = f.current.filter((i) => i.status === "uploading" || i.status === "processing").length, r = f.current.filter((i) => i.status === "queued").slice(0, Math.max(0, Math.max(1, t) - s));
142
+ for (const i of r) ht(i);
110
143
  }
111
- function cr(r) {
112
- const e = new AbortController();
113
- x.current.set(r.id, e), N(r.id, { status: "uploading", progress: null, reason: void 0 });
114
- const t = () => !e.signal.aborted && x.current.get(r.id) === e, c = {
115
- onProgress: (o) => {
116
- if (!t()) return;
117
- const l = Math.round(Math.min(1, Math.max(0, Number.isFinite(o) ? o : 0)) * 100) / 100, m = u.current.find((mr) => mr.id === r.id);
118
- m?.status === "uploading" && m.progress !== l && N(r.id, { progress: l });
144
+ function ht(t) {
145
+ const s = new AbortController();
146
+ v.current.set(t.id, s), $(t.id, { status: "uploading", progress: null, reason: void 0 });
147
+ const r = () => !s.signal.aborted && v.current.get(t.id) === s, i = {
148
+ onProgress: (c) => {
149
+ if (!r()) return;
150
+ const d = Math.round(Math.min(1, Math.max(0, Number.isFinite(c) ? c : 0)) * 100) / 100, o = f.current.find((L) => L.id === t.id);
151
+ o?.status === "uploading" && o.progress !== d && $(t.id, { progress: d });
119
152
  },
120
153
  onProcessing: () => {
121
- t() && N(r.id, { status: "processing" });
154
+ r() && $(t.id, { status: "processing" });
122
155
  },
123
- signal: e.signal
156
+ signal: s.signal
124
157
  };
125
- new Promise((o) => o(h.current.upload(r.file, c))).then(
126
- (o) => {
127
- if (!t()) return;
128
- x.current.delete(r.id), N(r.id, { status: "done", progress: 1, result: o });
129
- const l = u.current.filter((m) => m.status !== "rejected");
130
- L(h.current.t.progress(l.filter((m) => m.status === "done").length, l.length), !0), w();
158
+ new Promise((c) => c(j.current.upload(t.file, i))).then(
159
+ (c) => {
160
+ if (!r()) return;
161
+ v.current.delete(t.id), $(t.id, { status: "done", progress: 1, result: c });
162
+ const d = f.current.filter((o) => o.status !== "rejected");
163
+ N(j.current.t.progress(d.filter((o) => o.status === "done").length, d.length), !0), R();
131
164
  },
132
- (o) => {
133
- if (!t()) return;
134
- x.current.delete(r.id);
135
- const l = h.current.t.uploadError(o);
136
- N(r.id, { status: "failed", reason: l }), L(h.current.t.failedNotice(r.file.name, l)), w();
165
+ (c) => {
166
+ if (!r()) return;
167
+ v.current.delete(t.id);
168
+ const { t: d } = j.current;
169
+ if (Rt(c)) {
170
+ const o = c.message, L = typeof o == "string" && o ? o : d.uploadError(c);
171
+ $(t.id, { status: "rejected", progress: null, reason: L }), N(d.rejectedNotice(t.file.name, L));
172
+ } else {
173
+ const o = d.uploadError(c);
174
+ $(t.id, { status: "failed", reason: o }), N(d.failedNotice(t.file.name, o));
175
+ }
176
+ R();
137
177
  }
138
178
  );
139
179
  }
140
- Y(() => {
141
- h.current = { upload: d, onChange: T, concurrency: j, t: a, pump: w };
142
- }), xr(() => {
143
- const r = x.current;
144
- return u.current.some((t) => (t.status === "uploading" || t.status === "processing") && !r.has(t.id)) && (k(
145
- u.current.map(
146
- (t) => (t.status === "uploading" || t.status === "processing") && !r.has(t.id) ? { ...t, status: "queued", progress: null } : t
180
+ et(() => {
181
+ j.current = { upload: l, onChange: h, concurrency: J, t: a, pump: R };
182
+ }), rt(() => {
183
+ const t = v.current;
184
+ return f.current.some((r) => (r.status === "uploading" || r.status === "processing") && !t.has(r.id)) && (T(
185
+ f.current.map(
186
+ (r) => (r.status === "uploading" || r.status === "processing") && !t.has(r.id) ? { ...r, status: "queued", progress: null } : r
147
187
  )
148
- ), h.current.pump()), () => {
149
- for (const t of r.values()) t.abort();
150
- r.clear(), b.current && clearTimeout(b.current), b.current = null, y.current = [];
188
+ ), j.current.pump()), () => {
189
+ for (const r of t.values()) r.abort();
190
+ t.clear(), D.current && clearTimeout(D.current), D.current = null, M.current = [];
151
191
  };
152
- }, [k]);
153
- const ir = B ?? kr(D), dr = (r, e) => {
154
- if (e.some((c) => Nr(c.file, r))) return a.duplicate(r);
155
- const t = q?.(r);
156
- if (t) return t;
157
- if (!wr(r, ir)) return a.wrongType(r);
158
- if ($ !== void 0 && r.size > $) return a.tooLarge(r, $);
159
- if (v !== void 0 && e.length >= v) return a.tooMany(v);
160
- }, X = (r) => {
161
- if (i || r.length === 0) return;
162
- const e = u.current.filter((o) => o.status !== "rejected"), t = [];
163
- for (const o of r) {
164
- const l = dr(o, [...e, ...t.filter((m) => m.status !== "rejected")]);
165
- t.push({ id: `${C}-file-${sr.current++}`, file: o, status: l ? "rejected" : "queued", progress: null, reason: l });
192
+ }, [T]);
193
+ const mt = w ?? Dt(b), vt = (t, s) => {
194
+ if (s.some((i) => nt(i.file, t))) return a.duplicate(t);
195
+ const r = it?.(t);
196
+ if (r) return r;
197
+ if (!Tt(t, mt)) return a.wrongType(t);
198
+ if (m !== void 0 && t.size > m) return a.tooLarge(t, m);
199
+ if (p !== void 0 && s.length >= p) return a.tooMany(p);
200
+ }, tt = (t) => {
201
+ if (u || t.length === 0) return;
202
+ const s = E ? f.current.find((o) => o.status !== "rejected") : void 0, r = f.current.filter((o) => o.status !== "rejected" && o !== s), i = [];
203
+ for (const o of t) {
204
+ const L = s && nt(s.file, o) ? a.duplicate(o) : vt(o, [...r, ...i.filter((Nt) => Nt.status !== "rejected")]);
205
+ i.push({ id: `${I}-file-${ut.current++}`, file: o, status: L ? "rejected" : "queued", progress: null, reason: L });
166
206
  }
167
- k([...u.current, ...t]);
168
- const c = t.filter((o) => o.status === "queued").length;
169
- c && L(a.added(c));
170
- for (const o of t) o.reason && L(a.rejectedNotice(o.file.name, o.reason));
171
- w();
172
- }, ur = (r) => {
173
- if (i) return;
174
- const e = u.current, t = e.findIndex((o) => o.id === r);
175
- if (t < 0) return;
176
- x.current.get(r)?.abort(), x.current.delete(r);
177
- const c = e[t + 1] ?? e[t - 1];
178
- k(e.filter((o) => o.id !== r)), L(a.removed(e[t].file.name)), Q(c ? `[data-file-remove="${c.id}"]` : "[data-file-choose]"), w();
179
- }, lr = (r) => {
180
- i || (N(r, { status: "queued", progress: null, reason: void 0 }), Q(`[data-file-remove="${r}"]`), w());
181
- }, [fr, P] = M(0), E = (r) => Array.from(r.dataTransfer?.types ?? []).includes("Files"), pr = {
182
- onDragEnter: (r) => {
183
- E(r) && (r.preventDefault(), P((e) => e + 1));
207
+ const c = i.filter((o) => o.status === "queued").length, d = c ? s : void 0;
208
+ d && (v.current.get(d.id)?.abort(), v.current.delete(d.id)), T([...f.current.filter((o) => o !== d), ...i]), d && N(a.removed(d.file.name)), c && N(a.added(c));
209
+ for (const o of i) o.reason && N(a.rejectedNotice(o.file.name, o.reason));
210
+ R();
211
+ }, yt = (t) => {
212
+ if (u) return;
213
+ const s = f.current, r = s.findIndex((c) => c.id === t);
214
+ if (r < 0) return;
215
+ v.current.get(t)?.abort(), v.current.delete(t);
216
+ const i = s[r + 1] ?? s[r - 1];
217
+ T(s.filter((c) => c.id !== t)), N(a.removed(s[r].file.name)), Z(i ? `[data-file-remove="${i.id}"]` : "[data-file-choose]"), R();
218
+ }, xt = (t) => {
219
+ u || ($(t, { status: "queued", progress: null, reason: void 0 }), Z(`[data-file-remove="${t}"]`), R());
220
+ }, [bt, _] = C(0), U = (t) => Array.from(t.dataTransfer?.types ?? []).includes("Files"), kt = {
221
+ onDragEnter: (t) => {
222
+ U(t) && (t.preventDefault(), _((s) => s + 1));
184
223
  },
185
- onDragOver: (r) => {
186
- E(r) && (r.preventDefault(), r.dataTransfer.dropEffect = i ? "none" : "copy");
224
+ onDragOver: (t) => {
225
+ U(t) && (t.preventDefault(), t.dataTransfer.dropEffect = u ? "none" : "copy");
187
226
  },
188
- onDragLeave: (r) => {
189
- E(r) && P((e) => Math.max(0, e - 1));
227
+ onDragLeave: (t) => {
228
+ U(t) && _((s) => Math.max(0, s - 1));
190
229
  },
191
- onDrop: (r) => {
192
- E(r) && (r.preventDefault(), P(0), X(Array.from(r.dataTransfer.files)));
230
+ onDrop: (t) => {
231
+ U(t) && (t.preventDefault(), _(0), tt(Array.from(t.dataTransfer.files)));
193
232
  }
194
- }, W = fr > 0 && !i, gr = (r) => {
195
- switch (r.status) {
233
+ }, G = bt > 0 && !u, wt = (t) => {
234
+ switch (t.status) {
196
235
  case "queued":
197
236
  return a.queued;
198
237
  case "uploading":
199
- return a.uploading(r.progress === null ? null : Math.round(r.progress * 100));
238
+ return a.uploading(t.progress === null ? null : Math.round(t.progress * 100));
200
239
  case "processing":
201
240
  return a.processing;
202
241
  case "done":
203
242
  return a.done;
204
243
  case "failed":
205
- return `${a.failed} ${r.reason ?? ""}`.trim();
244
+ return `${a.failed} ${t.reason ?? ""}`.trim();
206
245
  case "rejected":
207
- return `${a.rejected} ${r.reason ?? ""}`.trim();
246
+ return `${a.rejected} ${t.reason ?? ""}`.trim();
208
247
  }
209
- }, hr = [F ? V : null, R ? _ : null].filter(Boolean).join(" ") || void 0;
210
- return /* @__PURE__ */ p(
248
+ }, jt = [O ? Q : null, z ? X : null].filter(Boolean).join(" ") || void 0, k = E ? q.find((t) => t.status !== "rejected") ?? q.at(-1) : void 0;
249
+ return /* @__PURE__ */ x(
211
250
  "div",
212
251
  {
213
- ref: O,
252
+ ref: A,
214
253
  role: "group",
215
254
  "aria-labelledby": S,
216
- className: g("rst:font-ui rst:w-full", tr),
255
+ className: g("rst:font-ui rst:w-full", dt),
217
256
  "data-file-upload": "",
218
257
  children: [
219
258
  /* @__PURE__ */ n(
@@ -222,58 +261,69 @@ function Ur({
222
261
  id: S,
223
262
  className: g(
224
263
  "rst:mb-1.5 rst:text-left rst:text-sm rst:font-medium rst:leading-none rst:text-[var(--roster-control-text)]",
225
- i && "rst:opacity-70"
264
+ u && "rst:opacity-70"
226
265
  ),
227
- children: s
266
+ children: e
228
267
  }
229
268
  ),
230
- /* @__PURE__ */ p(
269
+ /* @__PURE__ */ x(
231
270
  "div",
232
271
  {
233
- ...pr,
272
+ ...kt,
234
273
  "data-file-drop": "",
235
- "data-dragging": W ? "" : void 0,
274
+ "data-dragging": G ? "" : void 0,
236
275
  className: g(
237
276
  "rst:flex rst:flex-col rst:items-center rst:justify-center rst:gap-2 rst:rounded-lg rst:border-2 rst:border-dashed rst:px-4 rst:py-6 rst:text-center rst:transition-colors rst:motion-reduce:transition-none",
238
- W ? "rst:border-primary-500 rst:bg-primary-500/10" : R ? "rst:border-error-500 rst:dark:border-error-400" : "rst:border-gray-300 rst:dark:border-gray-600"
277
+ /* One height with a picture or without, so nothing below moves when
278
+ it arrives; the button sits at the foot of a picture. */
279
+ E && "rst:relative rst:h-[var(--roster-file-preview-height,13rem)]",
280
+ E && k && "rst:justify-end",
281
+ G ? "rst:border-primary-500 rst:bg-primary-500/10" : z ? "rst:border-error-500 rst:dark:border-error-400" : "rst:border-gray-300 rst:dark:border-gray-600"
239
282
  ),
240
283
  children: [
284
+ k && /* @__PURE__ */ n(It, { file: k.file, status: k.status }, k.id),
241
285
  /* @__PURE__ */ n(
242
- G,
286
+ K,
243
287
  {
244
288
  type: "button",
245
289
  variant: "outline",
246
290
  colorScheme: "neutral",
247
291
  size: "lg",
248
- className: g("rst:px-5", i && K),
249
- "aria-disabled": i || void 0,
250
- "aria-describedby": hr,
251
- onClick: () => J.current?.click(),
292
+ className: g(
293
+ "rst:px-5",
294
+ u && V,
295
+ /* Over a picture: above it, on a surface of its own, so it reads
296
+ whatever the photo is. */
297
+ k && "rst:relative rst:z-10 rst:bg-[var(--roster-card-bg)] rst:dark:hover:bg-gray-800"
298
+ ),
299
+ "aria-disabled": u || void 0,
300
+ "aria-describedby": jt,
301
+ onClick: () => Y.current?.click(),
252
302
  "data-file-choose": "",
253
- startIcon: /* @__PURE__ */ n("svg", { ...I, "aria-hidden": "true", children: /* @__PURE__ */ n("path", { d: "M12 16V4M7 9l5-5 5 5M5 20h14" }) }),
254
- children: a.choose
303
+ startIcon: /* @__PURE__ */ n("svg", { ...B, "aria-hidden": "true", children: /* @__PURE__ */ n("path", { d: "M12 16V4M7 9l5-5 5 5M5 20h14" }) }),
304
+ children: k ? a.replace : a.choose
255
305
  }
256
306
  ),
257
- /* @__PURE__ */ n(
307
+ !k && /* @__PURE__ */ n(
258
308
  "p",
259
309
  {
260
310
  className: "rst:hidden rst:text-xs rst:text-gray-600 rst:pointer-fine:block rst:dark:text-gray-400",
261
311
  "data-file-drop-hint": "",
262
- children: W ? a.dropHere : a.dropHint
312
+ children: G ? a.dropHere : a.dropHint
263
313
  }
264
314
  ),
265
315
  /* @__PURE__ */ n(
266
316
  "input",
267
317
  {
268
- ref: J,
318
+ ref: Y,
269
319
  type: "file",
270
320
  hidden: !0,
271
321
  tabIndex: -1,
272
- accept: D,
273
- multiple: v !== 1,
274
- disabled: i,
275
- onChange: (r) => {
276
- X(Array.from(r.currentTarget.files ?? [])), r.currentTarget.value = "";
322
+ accept: b,
323
+ multiple: p !== 1,
324
+ disabled: u,
325
+ onChange: (t) => {
326
+ tt(Array.from(t.currentTarget.files ?? [])), t.currentTarget.value = "";
277
327
  },
278
328
  "data-file-input": ""
279
329
  }
@@ -281,87 +331,87 @@ function Ur({
281
331
  ]
282
332
  }
283
333
  ),
284
- F && /* @__PURE__ */ n("p", { id: V, className: "rst:mt-1.5 rst:text-left rst:text-xs rst:text-gray-500 rst:dark:text-gray-400", children: F }),
285
- R && /* @__PURE__ */ n("p", { id: _, className: "rst:mt-1.5 rst:text-left rst:text-xs rst:font-medium rst:text-error-600 rst:dark:text-error-400", children: R }),
286
- z.length > 0 && /* @__PURE__ */ n("ul", { className: "rst:mt-3 rst:flex rst:flex-col rst:gap-2", "aria-labelledby": S, children: z.map((r) => {
287
- const e = r.status === "failed" || r.status === "rejected", t = r.status === "uploading" || r.status === "processing" || r.status === "queued";
288
- return /* @__PURE__ */ p(
334
+ O && /* @__PURE__ */ n("p", { id: Q, className: "rst:mt-1.5 rst:text-left rst:text-xs rst:text-gray-500 rst:dark:text-gray-400", children: O }),
335
+ z && /* @__PURE__ */ n("p", { id: X, className: "rst:mt-1.5 rst:text-left rst:text-xs rst:font-medium rst:text-error-600 rst:dark:text-error-400", children: z }),
336
+ q.length > 0 && /* @__PURE__ */ n("ul", { className: "rst:mt-3 rst:flex rst:flex-col rst:gap-2", "aria-labelledby": S, children: q.map((t) => {
337
+ const s = t.status === "failed" || t.status === "rejected", r = t.status === "uploading" || t.status === "processing" || t.status === "queued";
338
+ return /* @__PURE__ */ x(
289
339
  "li",
290
340
  {
291
- "data-file-item": r.id,
292
- "data-status": r.status,
341
+ "data-file-item": t.id,
342
+ "data-status": t.status,
293
343
  className: "rst:flex rst:items-center rst:gap-3 rst:rounded-md rst:border rst:border-[var(--roster-card-border)] rst:p-2",
294
344
  children: [
295
- /* @__PURE__ */ n(Lr, { file: r.file, status: r.status }),
296
- /* @__PURE__ */ p("div", { className: "rst:min-w-0 rst:flex-1 rst:text-left", children: [
297
- /* @__PURE__ */ n("p", { className: "rst:truncate rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)]", title: r.file.name, children: r.file.name }),
298
- /* @__PURE__ */ p(
345
+ !E && /* @__PURE__ */ n(zt, { file: t.file, status: t.status }),
346
+ /* @__PURE__ */ x("div", { className: "rst:min-w-0 rst:flex-1 rst:text-left", children: [
347
+ /* @__PURE__ */ n("p", { className: "rst:truncate rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)]", title: t.file.name, children: t.file.name }),
348
+ /* @__PURE__ */ x(
299
349
  "p",
300
350
  {
301
351
  className: g(
302
352
  "rst:mt-0.5 rst:flex rst:items-start rst:gap-1 rst:text-xs",
303
- e ? "rst:text-error-600 rst:dark:text-error-400" : "rst:text-gray-600 rst:dark:text-gray-400"
353
+ s ? "rst:text-error-600 rst:dark:text-error-400" : "rst:text-gray-600 rst:dark:text-gray-400"
304
354
  ),
305
355
  "data-file-status": "",
306
356
  children: [
307
- r.status === "done" && /* @__PURE__ */ n("svg", { ...I, width: 14, height: 14, "aria-hidden": "true", className: "rst:mt-px rst:shrink-0 rst:text-success-600 rst:dark:text-success-400", children: /* @__PURE__ */ n("path", { d: "M20 6 9 17l-5-5" }) }),
308
- /* @__PURE__ */ p("span", { children: [
309
- /* @__PURE__ */ n("span", { className: "rst:tabular-nums", children: a.size(r.file.size) }),
357
+ t.status === "done" && /* @__PURE__ */ n("svg", { ...B, width: 14, height: 14, "aria-hidden": "true", className: "rst:mt-px rst:shrink-0 rst:text-success-600 rst:dark:text-success-400", children: /* @__PURE__ */ n("path", { d: "M20 6 9 17l-5-5" }) }),
358
+ /* @__PURE__ */ x("span", { children: [
359
+ /* @__PURE__ */ n("span", { className: "rst:tabular-nums", children: a.size(t.file.size) }),
310
360
  /* @__PURE__ */ n("span", { "aria-hidden": "true", children: " · " }),
311
- gr(r)
361
+ wt(t)
312
362
  ] })
313
363
  ]
314
364
  }
315
365
  ),
316
- t && /* @__PURE__ */ n("div", { className: "rst:mt-1.5", "data-file-progress": "", children: /* @__PURE__ */ n(
317
- br,
366
+ r && /* @__PURE__ */ n("div", { className: "rst:mt-1.5", "data-file-progress": "", children: /* @__PURE__ */ n(
367
+ Mt,
318
368
  {
319
369
  size: "sm",
320
- value: r.status === "processing" ? 100 : r.status === "uploading" ? (r.progress ?? 0) * 100 : 0,
321
- busy: r.status === "processing" || r.status === "uploading" && r.progress === null,
370
+ value: t.status === "processing" ? 100 : t.status === "uploading" ? (t.progress ?? 0) * 100 : 0,
371
+ busy: t.status === "processing" || t.status === "uploading" && t.progress === null,
322
372
  announce: !1
323
373
  }
324
374
  ) })
325
375
  ] }),
326
- r.status === "failed" && /* @__PURE__ */ n(
327
- G,
376
+ t.status === "failed" && /* @__PURE__ */ n(
377
+ K,
328
378
  {
329
379
  type: "button",
330
380
  variant: "ghost",
331
381
  colorScheme: "neutral",
332
382
  size: "icon",
333
- className: g("rst:h-11 rst:w-11", i && K),
334
- "aria-disabled": i || void 0,
335
- "aria-label": a.retry(r.file.name),
336
- onClick: () => lr(r.id),
337
- "data-file-retry": r.id,
338
- children: /* @__PURE__ */ p("svg", { ...I, "aria-hidden": "true", children: [
383
+ className: g("rst:h-11 rst:w-11", u && V),
384
+ "aria-disabled": u || void 0,
385
+ "aria-label": a.retry(t.file.name),
386
+ onClick: () => xt(t.id),
387
+ "data-file-retry": t.id,
388
+ children: /* @__PURE__ */ x("svg", { ...B, "aria-hidden": "true", children: [
339
389
  /* @__PURE__ */ n("path", { d: "M3 12a9 9 0 1 0 3-6.7L3 8" }),
340
390
  /* @__PURE__ */ n("path", { d: "M3 3v5h5" })
341
391
  ] })
342
392
  }
343
393
  ),
344
394
  /* @__PURE__ */ n(
345
- G,
395
+ K,
346
396
  {
347
397
  type: "button",
348
398
  variant: "ghost",
349
399
  colorScheme: "neutral",
350
400
  size: "icon",
351
- className: g("rst:h-11 rst:w-11", i && K),
352
- "aria-disabled": i || void 0,
353
- "aria-label": a.remove(r.file.name),
354
- onClick: () => ur(r.id),
355
- "data-file-remove": r.id,
356
- children: /* @__PURE__ */ n("svg", { ...I, "aria-hidden": "true", children: /* @__PURE__ */ n("path", { d: "M18 6 6 18M6 6l12 12" }) })
401
+ className: g("rst:h-11 rst:w-11", u && V),
402
+ "aria-disabled": u || void 0,
403
+ "aria-label": a.remove(t.file.name),
404
+ onClick: () => yt(t.id),
405
+ "data-file-remove": t.id,
406
+ children: /* @__PURE__ */ n("svg", { ...B, "aria-hidden": "true", children: /* @__PURE__ */ n("path", { d: "M18 6 6 18M6 6l12 12" }) })
357
407
  }
358
408
  )
359
409
  ]
360
410
  },
361
- r.id
411
+ t.id
362
412
  );
363
413
  }) }),
364
- /* @__PURE__ */ p(
414
+ /* @__PURE__ */ x(
365
415
  "div",
366
416
  {
367
417
  role: "status",
@@ -369,10 +419,10 @@ function Ur({
369
419
  "aria-atomic": "true",
370
420
  className: "rst:sr-only",
371
421
  "data-file-live": "",
372
- "data-file-live-n": A.n,
422
+ "data-file-live-n": H.n,
373
423
  children: [
374
- A.text,
375
- A.n % 2 ? " " : ""
424
+ H.text,
425
+ H.n % 2 ? " " : ""
376
426
  ]
377
427
  }
378
428
  )
@@ -381,5 +431,5 @@ function Ur({
381
431
  );
382
432
  }
383
433
  export {
384
- Ur as FileUpload
434
+ Gt as FileUpload
385
435
  };