@object-ui/plugin-aggrid 3.3.2 → 3.4.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 (55) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/{AvatarField-CpFxJRdO.js → AvatarField-DuaF__ns.js} +2 -2
  3. package/dist/FileField-DtvoWRK-.js +214 -0
  4. package/dist/{GeolocationField-BfhC7QLw.js → GeolocationField-CyzG2dqR.js} +1 -1
  5. package/dist/ImageCropperDialog-BFlbM7vO.js +153 -0
  6. package/dist/ImageField-DoXNtXV_.js +145 -0
  7. package/dist/LookupField-DXGCnQ3q.js +1063 -0
  8. package/dist/{MasterDetailField-DGUmvg2f.js → MasterDetailField-JpmMudRV.js} +3 -3
  9. package/dist/{ObjectAgGridImpl-yiHlXYgp.js → ObjectAgGridImpl-Bz5whFec.js} +110 -108
  10. package/dist/{PasswordField-BJboeBJY.js → PasswordField-40E439oE.js} +1 -1
  11. package/dist/{QRCodeField-COLyc5iQ.js → QRCodeField-CrRsA1vB.js} +1 -1
  12. package/dist/{RatingField-B2momIna.js → RatingField-BVkroiQ4.js} +1 -1
  13. package/dist/{SelectField-oo6vnNhQ.js → SelectField-K-xoVDss.js} +1 -1
  14. package/dist/{SignatureField-DUgoK09r.js → SignatureField-D0nUx3Cb.js} +1 -1
  15. package/dist/TextAreaField-j4eJQ66C.js +125 -0
  16. package/dist/{UserField-eT5njHwQ.js → UserField-LrhYdvnz.js} +1 -1
  17. package/dist/check-CBAnx5TO.js +7 -0
  18. package/dist/{createLucideIcon-C_5JZ35b.js → createLucideIcon-BtZxPlua.js} +1 -1
  19. package/dist/crop-2wjrXKXD.js +10 -0
  20. package/dist/dist-BcXWTU-8.js +54 -0
  21. package/dist/index.js +1 -1
  22. package/dist/index.umd.cjs +79 -79
  23. package/dist/loader-circle-Cxg-xF4u.js +7 -0
  24. package/dist/{plus-bvZ2f9T_.js → plus-COkdZ2Fh.js} +1 -1
  25. package/dist/{upload-BdzwEMeV.js → upload-DWhfIa3Y.js} +1 -1
  26. package/dist/{x-98xe-fYG.js → x-BDi_yYx9.js} +1 -1
  27. package/package.json +8 -8
  28. package/dist/FileField-D3mZIrJ1.js +0 -158
  29. package/dist/ImageField-BZfSFwmJ.js +0 -75
  30. package/dist/LookupField-Cms1Cu_l.js +0 -1032
  31. package/dist/TextAreaField-CLzzmPce.js +0 -37
  32. package/dist/image-DmzU2ETO.js +0 -24
  33. /package/dist/{AgGridImpl-DJWnS8p3.js → AgGridImpl-DiTsK8F6.js} +0 -0
  34. /package/dist/{BooleanField-Chphr8cB.js → BooleanField-0QUz5DOy.js} +0 -0
  35. /package/dist/{CodeField-BWngVIw1.js → CodeField-iTabv7wS.js} +0 -0
  36. /package/dist/{ColorField-GygyYArR.js → ColorField-R7ZmLj1V.js} +0 -0
  37. /package/dist/{CurrencyField-O8Pn59RO.js → CurrencyField-CEu2SjEj.js} +0 -0
  38. /package/dist/{DateField-u6U8wmvI.js → DateField-DoaPu9GV.js} +0 -0
  39. /package/dist/{DateTimeField-D1z1Ovvy.js → DateTimeField-DcKX54zr.js} +0 -0
  40. /package/dist/{EmailField-IOcDmGjJ.js → EmailField-eYfpFAtE.js} +0 -0
  41. /package/dist/{FormulaField-MuyWzQx0.js → FormulaField-DF6-4u2b.js} +0 -0
  42. /package/dist/{GridField-gN34gk4b.js → GridField-BFlgbp8W.js} +0 -0
  43. /package/dist/{LocationField-B-zwfw3h.js → LocationField-BeYK6K9V.js} +0 -0
  44. /package/dist/{NumberField-BV5sKwZ7.js → NumberField-BYuCxbmU.js} +0 -0
  45. /package/dist/{ObjectField-DJ5s3ciA.js → ObjectField-Dlf_yrMC.js} +0 -0
  46. /package/dist/{PercentField-DO3be_bL.js → PercentField-BvdQEcfn.js} +0 -0
  47. /package/dist/{PhoneField-CT6XcO6O.js → PhoneField-CBuoC-vs.js} +0 -0
  48. /package/dist/{RichTextField-C7qzDPJy.js → RichTextField-DEYNcokk.js} +0 -0
  49. /package/dist/{SliderField-DrggtBSX.js → SliderField-C2EpGbj8.js} +0 -0
  50. /package/dist/{SummaryField-DuMsFoY5.js → SummaryField-S6Gt7IDC.js} +0 -0
  51. /package/dist/{TextField-CZE7SzK4.js → TextField-DccUZtd7.js} +0 -0
  52. /package/dist/{TimeField-Bha4cayv.js → TimeField-CWbpycPt.js} +0 -0
  53. /package/dist/{UrlField-Dff4WLlN.js → UrlField-BkPyImh9.js} +0 -0
  54. /package/dist/{VectorField-BHe8lDOH.js → VectorField-Baa_mHsO.js} +0 -0
  55. /package/dist/{useFieldTranslation-CfXaJRC4.js → useFieldTranslation-DtLNhrx3.js} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @object-ui/plugin-aggrid
2
2
 
3
+ ## 3.4.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [a2d7023]
8
+ - Updated dependencies [f1ca238]
9
+ - Updated dependencies [de881ef]
10
+ - @object-ui/components@3.4.0
11
+ - @object-ui/fields@3.4.0
12
+ - @object-ui/types@3.4.0
13
+ - @object-ui/core@3.4.0
14
+ - @object-ui/data-objectstack@3.4.0
15
+ - @object-ui/react@3.4.0
16
+
3
17
  ## 3.3.2
4
18
 
5
19
  ### Patch Changes
@@ -1,7 +1,7 @@
1
1
  import { n as e } from "./rolldown-runtime-CkxV0rQ3.js";
2
2
  import { t } from "./jsx-runtime-CXSCp6pT.js";
3
- import { t as n } from "./upload-BdzwEMeV.js";
4
- import { t as r } from "./x-98xe-fYG.js";
3
+ import { t as n } from "./upload-DWhfIa3Y.js";
4
+ import { t as r } from "./x-BDi_yYx9.js";
5
5
  import i from "react";
6
6
  import { Avatar as a, AvatarFallback as o, AvatarImage as s, Button as c } from "@object-ui/components";
7
7
  //#region ../fields/src/widgets/AvatarField.tsx
@@ -0,0 +1,214 @@
1
+ import { n as e } from "./rolldown-runtime-CkxV0rQ3.js";
2
+ import { t } from "./jsx-runtime-CXSCp6pT.js";
3
+ import { t as n } from "./createLucideIcon-BtZxPlua.js";
4
+ import { n as r, t as i } from "./dist-BcXWTU-8.js";
5
+ import { t as a } from "./loader-circle-Cxg-xF4u.js";
6
+ import { t as o } from "./upload-DWhfIa3Y.js";
7
+ import { t as s } from "./x-BDi_yYx9.js";
8
+ import { useCallback as c, useRef as l, useState as u } from "react";
9
+ import { Button as d, EmptyValue as f } from "@object-ui/components";
10
+ var p = n("camera", [["path", {
11
+ d: "M13.997 4a2 2 0 0 1 1.76 1.05l.486.9A2 2 0 0 0 18.003 7H20a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h1.997a2 2 0 0 0 1.759-1.048l.489-.904A2 2 0 0 1 10.004 4z",
12
+ key: "18u6gg"
13
+ }], ["circle", {
14
+ cx: "12",
15
+ cy: "13",
16
+ r: "3",
17
+ key: "1vg3eu"
18
+ }]]), m = n("file", [["path", {
19
+ d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",
20
+ key: "1oefj6"
21
+ }], ["path", {
22
+ d: "M14 2v5a1 1 0 0 0 1 1h5",
23
+ key: "wfsgrz"
24
+ }]]), h = /* @__PURE__ */ e({ FileField: () => _ }), g = t();
25
+ function _({ value: e, onChange: t, field: n, readonly: h, ..._ }) {
26
+ let v = l(null), y = l(null), b = n || _.schema, x = b?.multiple || !1, S = b?.accept ? b.accept.join(",") : void 0, C = b?.maxSize, w = b?.capture ?? null, T = !S || S.split(",").some((e) => e.trim().startsWith("image/") || e.trim() === "image/*" || e.trim().startsWith(".jp") || e.trim().startsWith(".png") || e.trim().startsWith(".gif") || e.trim().startsWith(".webp")), E = typeof navigator < "u" && (navigator.maxTouchPoints > 0 || /Mobi|Android/i.test(navigator.userAgent)), D = w === !1 ? !1 : w ?? (T && E ? "environment" : null), [O, k] = u(!1), [A, j] = u([]), { upload: M } = i(), [N, P] = u({}), [F, I] = u(!1), L = e ? Array.isArray(e) ? e : [e] : [], R = c(async (e) => {
27
+ if (e.length === 0) return;
28
+ let n = [], r = e.filter((e) => {
29
+ if (C && e.size > C) {
30
+ let t = (C / (1024 * 1024)).toFixed(1);
31
+ return n.push(`"${e.name}" exceeds max size (${t} MB)`), !1;
32
+ }
33
+ return !0;
34
+ });
35
+ if (j(n), r.length !== 0) {
36
+ I(!0);
37
+ try {
38
+ let e = (await Promise.all(r.map(async (e) => {
39
+ try {
40
+ let t = await M(e, { onProgress: (t) => P((n) => ({
41
+ ...n,
42
+ [e.name]: t
43
+ })) });
44
+ return {
45
+ name: t.name,
46
+ original_name: e.name,
47
+ size: t.size,
48
+ mime_type: t.mimeType,
49
+ url: t.url
50
+ };
51
+ } catch (t) {
52
+ return n.push(`Failed to upload "${e.name}": ${t.message}`), j([...n]), null;
53
+ }
54
+ }))).filter(Boolean);
55
+ if (e.length === 0) return;
56
+ t(x ? [...L, ...e] : e[0]);
57
+ } finally {
58
+ I(!1), P({});
59
+ }
60
+ }
61
+ }, [
62
+ L,
63
+ x,
64
+ t,
65
+ C,
66
+ M
67
+ ]), z = c((e) => {
68
+ e.preventDefault(), e.stopPropagation(), k(!0);
69
+ }, []), B = c((e) => {
70
+ e.preventDefault(), e.stopPropagation(), k(!1);
71
+ }, []), V = c((e) => {
72
+ e.preventDefault(), e.stopPropagation(), k(!1);
73
+ let t = Array.from(e.dataTransfer.files);
74
+ if (S) {
75
+ let e = S.split(",").map((e) => e.trim().toLowerCase());
76
+ R(t.filter((t) => {
77
+ let n = t.name.split("."), r = n.length > 1 ? "." + n.pop()?.toLowerCase() : "";
78
+ return e.some((e) => e === t.type || r && e === r || e.endsWith("/*") && t.type.startsWith(e.replace("/*", "/")));
79
+ }));
80
+ } else R(t);
81
+ }, [S, R]);
82
+ if (h) return e ? /* @__PURE__ */ (0, g.jsx)("div", {
83
+ className: "flex flex-wrap gap-2",
84
+ children: (Array.isArray(e) ? e : [e]).map((e, t) => /* @__PURE__ */ (0, g.jsx)("span", {
85
+ className: "text-sm truncate max-w-xs",
86
+ children: e.name || e.original_name || "File"
87
+ }, t))
88
+ }) : /* @__PURE__ */ (0, g.jsx)(f, {});
89
+ let H = (e) => {
90
+ R(Array.from(e.target.files || []));
91
+ }, U = (e) => {
92
+ if (x) {
93
+ let n = L.filter((t, n) => n !== e);
94
+ t(n.length > 0 ? n : null);
95
+ } else t(null);
96
+ }, W = (e) => (e.mime_type || "").startsWith("image/");
97
+ return /* @__PURE__ */ (0, g.jsxs)("div", {
98
+ className: _.className,
99
+ children: [
100
+ /* @__PURE__ */ (0, g.jsx)("input", {
101
+ ref: v,
102
+ type: "file",
103
+ multiple: x,
104
+ accept: S,
105
+ onChange: H,
106
+ className: "hidden"
107
+ }),
108
+ D && /* @__PURE__ */ (0, g.jsx)("input", {
109
+ ref: y,
110
+ type: "file",
111
+ accept: "image/*",
112
+ capture: D,
113
+ onChange: H,
114
+ className: "hidden",
115
+ "aria-label": "Camera capture",
116
+ "data-testid": "file-field-camera-input"
117
+ }),
118
+ /* @__PURE__ */ (0, g.jsxs)("div", {
119
+ className: "space-y-2",
120
+ children: [
121
+ /* @__PURE__ */ (0, g.jsxs)("div", {
122
+ onDragOver: z,
123
+ onDragLeave: B,
124
+ onDrop: V,
125
+ onClick: () => v.current?.click(),
126
+ className: `
127
+ flex flex-col items-center justify-center gap-2 p-6
128
+ border-2 border-dashed rounded-lg cursor-pointer
129
+ transition-colors duration-200
130
+ ${O ? "border-primary bg-primary/5 text-primary" : "border-muted-foreground/25 hover:border-primary/50 text-muted-foreground hover:text-foreground"}
131
+ `,
132
+ role: "button",
133
+ tabIndex: 0,
134
+ onKeyDown: (e) => {
135
+ (e.key === "Enter" || e.key === " ") && (e.preventDefault(), v.current?.click());
136
+ },
137
+ children: [/* @__PURE__ */ (0, g.jsx)(o, { className: `size-8 ${O ? "text-primary" : "text-muted-foreground"}` }), /* @__PURE__ */ (0, g.jsxs)("div", {
138
+ className: "text-center",
139
+ children: [/* @__PURE__ */ (0, g.jsx)("p", {
140
+ className: "text-sm font-medium",
141
+ children: O ? "Drop files here" : "Drag & drop files here"
142
+ }), /* @__PURE__ */ (0, g.jsxs)("p", {
143
+ className: "text-xs text-muted-foreground mt-1",
144
+ children: ["or click to browse", D ? " • use the camera button below" : ""]
145
+ })]
146
+ })]
147
+ }),
148
+ D && /* @__PURE__ */ (0, g.jsxs)(d, {
149
+ type: "button",
150
+ variant: "outline",
151
+ size: "sm",
152
+ className: "w-full",
153
+ onClick: (e) => {
154
+ e.stopPropagation(), y.current?.click();
155
+ },
156
+ "data-testid": "file-field-camera-button",
157
+ children: [/* @__PURE__ */ (0, g.jsx)(p, { className: "size-4 mr-2" }), D === "user" ? "Take selfie" : "Take photo"]
158
+ }),
159
+ F && /* @__PURE__ */ (0, g.jsxs)("div", {
160
+ className: "flex items-center gap-2 text-xs text-muted-foreground",
161
+ "data-testid": "file-field-uploading",
162
+ children: [/* @__PURE__ */ (0, g.jsx)(a, { className: "size-3 animate-spin" }), /* @__PURE__ */ (0, g.jsxs)("span", { children: ["Uploading…", Object.keys(N).length > 0 && ` (${Math.round(Object.values(N).reduce((e, t) => e + t, 0) / Object.keys(N).length * 100)}%)`] })]
163
+ }),
164
+ A.length > 0 && /* @__PURE__ */ (0, g.jsx)("div", {
165
+ className: "space-y-0.5",
166
+ children: A.map((e, t) => /* @__PURE__ */ (0, g.jsx)("p", {
167
+ className: "text-xs text-destructive",
168
+ children: e
169
+ }, t))
170
+ }),
171
+ L.length > 0 && /* @__PURE__ */ (0, g.jsx)("div", {
172
+ className: "space-y-1",
173
+ children: L.map((e, t) => /* @__PURE__ */ (0, g.jsxs)("div", {
174
+ className: "flex items-center justify-between gap-2 p-2 bg-muted/50 rounded-md border",
175
+ children: [/* @__PURE__ */ (0, g.jsxs)("div", {
176
+ className: "flex items-center gap-2 flex-1 min-w-0",
177
+ children: [
178
+ W(e) && e.url ? /* @__PURE__ */ (0, g.jsx)("img", {
179
+ src: e.url,
180
+ alt: e.name,
181
+ className: "size-8 object-cover rounded flex-shrink-0"
182
+ }) : W(e) ? /* @__PURE__ */ (0, g.jsx)(r, { className: "size-4 text-muted-foreground flex-shrink-0" }) : /* @__PURE__ */ (0, g.jsx)(m, { className: "size-4 text-muted-foreground flex-shrink-0" }),
183
+ /* @__PURE__ */ (0, g.jsx)("span", {
184
+ className: "text-sm truncate",
185
+ children: e.name || e.original_name || "File"
186
+ }),
187
+ e.size && /* @__PURE__ */ (0, g.jsxs)("span", {
188
+ className: "text-xs text-muted-foreground",
189
+ children: [
190
+ "(",
191
+ (e.size / 1024).toFixed(1),
192
+ " KB)"
193
+ ]
194
+ })
195
+ ]
196
+ }), /* @__PURE__ */ (0, g.jsx)(d, {
197
+ type: "button",
198
+ variant: "ghost",
199
+ size: "sm",
200
+ onClick: (e) => {
201
+ e.stopPropagation(), U(t);
202
+ },
203
+ className: "h-6 w-6 p-0",
204
+ children: /* @__PURE__ */ (0, g.jsx)(s, { className: "size-3" })
205
+ })]
206
+ }, t))
207
+ })
208
+ ]
209
+ })
210
+ ]
211
+ });
212
+ }
213
+ //#endregion
214
+ export { h as t };
@@ -1,6 +1,6 @@
1
1
  import { n as e } from "./rolldown-runtime-CkxV0rQ3.js";
2
2
  import { t } from "./jsx-runtime-CXSCp6pT.js";
3
- import { t as n } from "./createLucideIcon-C_5JZ35b.js";
3
+ import { t as n } from "./createLucideIcon-BtZxPlua.js";
4
4
  import r from "react";
5
5
  import { Button as i, EmptyValue as a, Input as o, Label as s } from "@object-ui/components";
6
6
  var c = n("crosshair", [
@@ -0,0 +1,153 @@
1
+ import { n as e } from "./rolldown-runtime-CkxV0rQ3.js";
2
+ import { t } from "./jsx-runtime-CXSCp6pT.js";
3
+ import { t as n } from "./createLucideIcon-BtZxPlua.js";
4
+ import { t as r } from "./crop-2wjrXKXD.js";
5
+ import { useCallback as i, useEffect as a, useRef as o, useState as s } from "react";
6
+ import { Button as c, Dialog as l, DialogContent as u, DialogDescription as d, DialogFooter as f, DialogHeader as p, DialogTitle as m } from "@object-ui/components";
7
+ var h = n("rotate-cw", [["path", {
8
+ d: "M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8",
9
+ key: "1p45f6"
10
+ }], ["path", {
11
+ d: "M21 3v5h-5",
12
+ key: "1q7to0"
13
+ }]]), g = /* @__PURE__ */ e({ ImageCropperDialog: () => v }), _ = t(), v = ({ open: e, onOpenChange: t, src: n, outputType: g = "image/png", outputName: v = "cropped.png", onConfirm: y }) => {
14
+ let b = o(null), x = o(null), [S, C] = s(0), [w, T] = s({
15
+ x: 0,
16
+ y: 0,
17
+ width: 100,
18
+ height: 100
19
+ }), [E, D] = s(null), [O, k] = s(!1);
20
+ a(() => {
21
+ if (!e || !n) return;
22
+ k(!1);
23
+ let t = new Image();
24
+ t.crossOrigin = "anonymous", t.onload = () => {
25
+ x.current = t;
26
+ let e = t.naturalWidth * .8, n = t.naturalHeight * .8;
27
+ T({
28
+ x: (t.naturalWidth - e) / 2,
29
+ y: (t.naturalHeight - n) / 2,
30
+ width: e,
31
+ height: n
32
+ }), C(0), k(!0);
33
+ }, t.onerror = () => k(!1), t.src = n;
34
+ }, [e, n]), a(() => {
35
+ if (!O || !x.current || !b.current) return;
36
+ let e = x.current, t = b.current, n = t.getContext("2d");
37
+ if (!n) return;
38
+ let r = 480 / e.naturalWidth, i = e.naturalHeight * r;
39
+ t.width = 480, t.height = i, n.clearRect(0, 0, 480, i), n.save(), n.translate(480 / 2, i / 2), n.rotate(S * Math.PI / 180);
40
+ let a = S % 180 == 0 ? 480 : i, o = S % 180 == 0 ? i : 480;
41
+ n.drawImage(e, -a / 2, -o / 2, a, o), n.restore();
42
+ let s = w.x * r, c = w.y * r, l = w.width * r, u = w.height * r;
43
+ n.fillStyle = "rgba(0,0,0,0.45)", n.fillRect(0, 0, 480, c), n.fillRect(0, c + u, 480, i - c - u), n.fillRect(0, c, s, u), n.fillRect(s + l, c, 480 - s - l, u), n.strokeStyle = "#3b82f6", n.lineWidth = 2, n.strokeRect(s, c, l, u);
44
+ }, [
45
+ O,
46
+ w,
47
+ S
48
+ ]);
49
+ let A = i((e) => {
50
+ if (!x.current || !b.current) return;
51
+ let t = b.current.getBoundingClientRect(), n = x.current.naturalWidth / t.width;
52
+ D({
53
+ ox: (e.clientX - t.left) * n,
54
+ oy: (e.clientY - t.top) * n,
55
+ cx: w.x,
56
+ cy: w.y
57
+ }), e.target.setPointerCapture(e.pointerId);
58
+ }, [w]), j = i((e) => {
59
+ if (!E || !x.current || !b.current) return;
60
+ let t = b.current.getBoundingClientRect(), n = x.current.naturalWidth / t.width, r = (e.clientX - t.left) * n - E.ox, i = (e.clientY - t.top) * n - E.oy, a = Math.max(0, Math.min(E.cx + r, x.current.naturalWidth - w.width)), o = Math.max(0, Math.min(E.cy + i, x.current.naturalHeight - w.height));
61
+ T((e) => ({
62
+ ...e,
63
+ x: a,
64
+ y: o
65
+ }));
66
+ }, [
67
+ E,
68
+ w.width,
69
+ w.height
70
+ ]), M = i(() => D(null), []), N = i(() => C((e) => (e + 90) % 360), []), P = i(async () => {
71
+ if (!x.current) return;
72
+ let e = x.current, n = document.createElement("canvas"), r = w.width, i = w.height;
73
+ n.width = S % 180 == 0 ? r : i, n.height = S % 180 == 0 ? i : r;
74
+ let a = n.getContext("2d");
75
+ if (!a) return;
76
+ a.save(), a.translate(n.width / 2, n.height / 2), a.rotate(S * Math.PI / 180), a.drawImage(e, w.x, w.y, r, i, -r / 2, -i / 2, r, i), a.restore();
77
+ let o = await new Promise((e) => n.toBlob(e, g));
78
+ o && (y(o, v), t(!1));
79
+ }, [
80
+ w,
81
+ S,
82
+ v,
83
+ g,
84
+ y,
85
+ t
86
+ ]);
87
+ return /* @__PURE__ */ (0, _.jsx)(l, {
88
+ open: e,
89
+ onOpenChange: t,
90
+ children: /* @__PURE__ */ (0, _.jsxs)(u, {
91
+ className: "max-w-xl",
92
+ children: [
93
+ /* @__PURE__ */ (0, _.jsxs)(p, { children: [/* @__PURE__ */ (0, _.jsx)(m, { children: "Crop & rotate image" }), /* @__PURE__ */ (0, _.jsx)(d, { children: "Drag the highlighted box to reposition the crop. Use the rotate button to spin the image in 90° increments." })] }),
94
+ /* @__PURE__ */ (0, _.jsxs)("div", {
95
+ className: "flex flex-col items-center gap-3",
96
+ children: [O ? /* @__PURE__ */ (0, _.jsx)("canvas", {
97
+ ref: b,
98
+ "data-testid": "image-cropper-canvas",
99
+ role: "img",
100
+ "aria-label": "Image crop preview",
101
+ className: "border rounded-md cursor-move touch-none max-w-full",
102
+ onPointerDown: A,
103
+ onPointerMove: j,
104
+ onPointerUp: M,
105
+ onPointerCancel: M
106
+ }) : /* @__PURE__ */ (0, _.jsx)("div", {
107
+ className: "flex h-[270px] w-full items-center justify-center text-sm text-muted-foreground",
108
+ children: "Loading image…"
109
+ }), /* @__PURE__ */ (0, _.jsxs)("div", {
110
+ className: "flex w-full items-center justify-between text-xs text-muted-foreground",
111
+ children: [/* @__PURE__ */ (0, _.jsxs)("span", { children: [
112
+ "Crop: ",
113
+ Math.round(w.width),
114
+ " × ",
115
+ Math.round(w.height),
116
+ " px"
117
+ ] }), /* @__PURE__ */ (0, _.jsxs)("span", { children: [
118
+ "Rotation: ",
119
+ S,
120
+ "°"
121
+ ] })]
122
+ })]
123
+ }),
124
+ /* @__PURE__ */ (0, _.jsxs)(f, {
125
+ className: "flex justify-between sm:justify-between",
126
+ children: [/* @__PURE__ */ (0, _.jsxs)(c, {
127
+ type: "button",
128
+ variant: "outline",
129
+ onClick: N,
130
+ "data-testid": "image-cropper-rotate",
131
+ children: [/* @__PURE__ */ (0, _.jsx)(h, { className: "size-4 mr-2" }), "Rotate 90°"]
132
+ }), /* @__PURE__ */ (0, _.jsxs)("div", {
133
+ className: "flex gap-2",
134
+ children: [/* @__PURE__ */ (0, _.jsx)(c, {
135
+ type: "button",
136
+ variant: "ghost",
137
+ onClick: () => t(!1),
138
+ children: "Cancel"
139
+ }), /* @__PURE__ */ (0, _.jsxs)(c, {
140
+ type: "button",
141
+ onClick: P,
142
+ disabled: !O,
143
+ "data-testid": "image-cropper-confirm",
144
+ children: [/* @__PURE__ */ (0, _.jsx)(r, { className: "size-4 mr-2" }), "Apply crop"]
145
+ })]
146
+ })]
147
+ })
148
+ ]
149
+ })
150
+ });
151
+ };
152
+ //#endregion
153
+ export { g as t };
@@ -0,0 +1,145 @@
1
+ import { n as e } from "./rolldown-runtime-CkxV0rQ3.js";
2
+ import { t } from "./jsx-runtime-CXSCp6pT.js";
3
+ import { t as n } from "./crop-2wjrXKXD.js";
4
+ import { n as r, t as i } from "./dist-BcXWTU-8.js";
5
+ import { t as a } from "./loader-circle-Cxg-xF4u.js";
6
+ import { t as o } from "./x-BDi_yYx9.js";
7
+ import { Suspense as s, lazy as c, useCallback as l, useRef as u, useState as d } from "react";
8
+ import { Button as f, EmptyValue as p } from "@object-ui/components";
9
+ //#region ../fields/src/widgets/ImageField.tsx
10
+ var m = /* @__PURE__ */ e({ ImageField: () => _ }), h = t(), g = c(() => import("./ImageCropperDialog-BFlbM7vO.js").then((e) => e.t).then((e) => ({ default: e.ImageCropperDialog })));
11
+ function _({ value: e, onChange: t, field: c, readonly: m, ..._ }) {
12
+ let v = u(null), y = c || _.schema, b = y?.multiple || !1, x = y?.accept ? y.accept.join(",") : "image/*", S = y?.crop !== !1, [C, w] = d(null), { upload: T } = i(), [E, D] = d(!1);
13
+ if (m) return e ? /* @__PURE__ */ (0, h.jsx)("div", {
14
+ className: "flex flex-wrap gap-2",
15
+ children: (Array.isArray(e) ? e : [e]).map((e, t) => /* @__PURE__ */ (0, h.jsx)("img", {
16
+ src: e.url || "",
17
+ alt: e.name || `Image ${t + 1}`,
18
+ className: "size-20 rounded-md object-cover border border-gray-200"
19
+ }, t))
20
+ }) : /* @__PURE__ */ (0, h.jsx)(p, {});
21
+ let O = e ? Array.isArray(e) ? e : [e] : [], k = async (e) => {
22
+ let n = Array.from(e.target.files || []);
23
+ if (n.length !== 0) {
24
+ D(!0);
25
+ try {
26
+ let e = await Promise.all(n.map(async (e) => {
27
+ let t = await T(e);
28
+ return {
29
+ name: t.name,
30
+ original_name: e.name,
31
+ size: t.size,
32
+ mime_type: t.mimeType,
33
+ url: t.url
34
+ };
35
+ }));
36
+ t(b ? [...O, ...e] : e[0]);
37
+ } finally {
38
+ D(!1), v.current && (v.current.value = "");
39
+ }
40
+ }
41
+ }, A = (e) => {
42
+ if (b) {
43
+ let n = O.filter((t, n) => n !== e);
44
+ t(n.length > 0 ? n : null);
45
+ } else t(null);
46
+ }, j = l(async (e, n) => {
47
+ if (C) {
48
+ D(!0);
49
+ try {
50
+ let r = await T(e), i = {
51
+ name: r.name || n,
52
+ original_name: n,
53
+ size: r.size,
54
+ mime_type: r.mimeType,
55
+ url: r.url
56
+ };
57
+ if (b) {
58
+ let e = [...O];
59
+ e[C.index] = i, t(e);
60
+ } else t(i);
61
+ } finally {
62
+ D(!1), w(null);
63
+ }
64
+ }
65
+ }, [
66
+ C,
67
+ O,
68
+ b,
69
+ t,
70
+ T
71
+ ]), M = l((e) => {
72
+ let t = O[e];
73
+ t?.url && w({
74
+ index: e,
75
+ src: t.url,
76
+ name: t.name || `image-${e}.png`
77
+ });
78
+ }, [O]);
79
+ return /* @__PURE__ */ (0, h.jsxs)("div", {
80
+ className: _.className,
81
+ children: [
82
+ /* @__PURE__ */ (0, h.jsx)("input", {
83
+ ref: v,
84
+ type: "file",
85
+ multiple: b,
86
+ accept: x,
87
+ onChange: k,
88
+ className: "hidden"
89
+ }),
90
+ /* @__PURE__ */ (0, h.jsxs)("div", {
91
+ className: "space-y-2",
92
+ children: [O.length > 0 && /* @__PURE__ */ (0, h.jsx)("div", {
93
+ className: "grid grid-cols-4 gap-2",
94
+ children: O.map((e, t) => /* @__PURE__ */ (0, h.jsxs)("div", {
95
+ className: "relative group",
96
+ children: [/* @__PURE__ */ (0, h.jsx)("img", {
97
+ src: e.url || "",
98
+ alt: e.name || `Image ${t + 1}`,
99
+ className: "size-20 rounded-md object-cover border border-gray-200"
100
+ }), /* @__PURE__ */ (0, h.jsxs)("div", {
101
+ className: "absolute top-1 right-1 flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity",
102
+ children: [S && /* @__PURE__ */ (0, h.jsx)(f, {
103
+ type: "button",
104
+ variant: "secondary",
105
+ size: "sm",
106
+ onClick: () => M(t),
107
+ className: "h-6 w-6 p-0",
108
+ "aria-label": `Crop image ${t + 1}`,
109
+ "data-testid": `image-field-crop-${t}`,
110
+ children: /* @__PURE__ */ (0, h.jsx)(n, { className: "size-3" })
111
+ }), /* @__PURE__ */ (0, h.jsx)(f, {
112
+ type: "button",
113
+ variant: "destructive",
114
+ size: "sm",
115
+ onClick: () => A(t),
116
+ className: "h-6 w-6 p-0",
117
+ children: /* @__PURE__ */ (0, h.jsx)(o, { className: "size-3" })
118
+ })]
119
+ })]
120
+ }, t))
121
+ }), /* @__PURE__ */ (0, h.jsxs)(f, {
122
+ type: "button",
123
+ variant: "outline",
124
+ onClick: () => v.current?.click(),
125
+ className: "w-full",
126
+ disabled: E,
127
+ "data-testid": "image-field-upload-button",
128
+ children: [E ? /* @__PURE__ */ (0, h.jsx)(a, { className: "size-4 mr-2 animate-spin" }) : /* @__PURE__ */ (0, h.jsx)(r, { className: "size-4 mr-2" }), E ? "Uploading…" : O.length > 0 ? "Add More Images" : "Upload Image"]
129
+ })]
130
+ }),
131
+ S && C && /* @__PURE__ */ (0, h.jsx)(s, {
132
+ fallback: null,
133
+ children: /* @__PURE__ */ (0, h.jsx)(g, {
134
+ open: !0,
135
+ onOpenChange: (e) => !e && w(null),
136
+ src: C.src,
137
+ outputName: C.name,
138
+ onConfirm: j
139
+ })
140
+ })
141
+ ]
142
+ });
143
+ }
144
+ //#endregion
145
+ export { m as n, _ as t };