@snowcone-app/canvas 0.33.1 → 0.34.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 (29) hide show
  1. package/dist/{ContextualToolbars-BrllZJTn.js → ContextualToolbars-BxnFwtTH.js} +3 -3
  2. package/dist/{ContextualToolbars-BrllZJTn.js.map → ContextualToolbars-BxnFwtTH.js.map} +1 -1
  3. package/dist/{EditorCanvasImpl-BiNG1dIj.js → EditorCanvasImpl-B9GjC1h6.js} +5 -5
  4. package/dist/{EditorCanvasImpl-BiNG1dIj.js.map → EditorCanvasImpl-B9GjC1h6.js.map} +1 -1
  5. package/dist/ImagePanel-Ih9e9cOQ.js +984 -0
  6. package/dist/ImagePanel-Ih9e9cOQ.js.map +1 -0
  7. package/dist/{SnowconeCanvas-DjQFFTDh.js → SnowconeCanvas-B4Nhk7JQ.js} +6 -6
  8. package/dist/{SnowconeCanvas-DjQFFTDh.js.map → SnowconeCanvas-B4Nhk7JQ.js.map} +1 -1
  9. package/dist/advanced.mjs +7 -7
  10. package/dist/components/ImageBrowserDrawer.d.ts +4 -1
  11. package/dist/contexts/CanvasServicesContext.d.ts +17 -1
  12. package/dist/{custom-icons-QEBlxVyq.js → custom-icons-CblWjgt-.js} +2 -2
  13. package/dist/{custom-icons-QEBlxVyq.js.map → custom-icons-CblWjgt-.js.map} +1 -1
  14. package/dist/{embed-C6kwN09N.js → embed-CxSoTDTw.js} +5 -5
  15. package/dist/{embed-C6kwN09N.js.map → embed-CxSoTDTw.js.map} +1 -1
  16. package/dist/embed.mjs +3 -3
  17. package/dist/index.mjs +5 -5
  18. package/dist/services/imageSearch.d.ts +24 -0
  19. package/dist/style.css +1 -1
  20. package/dist/{template-fields-xVQZRXvc.js → template-fields-ClO9mflO.js} +2 -2
  21. package/dist/{template-fields-xVQZRXvc.js.map → template-fields-ClO9mflO.js.map} +1 -1
  22. package/dist/{useCommands-DmewMc5w.js → useCommands-Bj9QHZ35.js} +513 -495
  23. package/dist/{useCommands-DmewMc5w.js.map → useCommands-Bj9QHZ35.js.map} +1 -1
  24. package/dist/{validation-CA6cMSOX.js → validation-BU8STi7a.js} +7 -7
  25. package/dist/{validation-CA6cMSOX.js.map → validation-BU8STi7a.js.map} +1 -1
  26. package/example/package.json +1 -1
  27. package/package.json +1 -1
  28. package/dist/ImagePanel-Ckpc6QqR.js +0 -951
  29. package/dist/ImagePanel-Ckpc6QqR.js.map +0 -1
@@ -1,951 +0,0 @@
1
- import { jsx as e, jsxs as c, Fragment as K } from "react/jsx-runtime";
2
- import * as Ze from "react";
3
- import Be, { useMemo as Je, useState as r, useRef as U, useEffect as J, useCallback as ae } from "react";
4
- import { u as Ke, g as Oe } from "./design-builder-D4izkvlb.js";
5
- import { o as es, N as ss, d as cs, W as ts, I as v, O as re, B as _, u as rs, C as as } from "./useCommands-DmewMc5w.js";
6
- import { c as ns, I as os } from "./FontAnalyzer-BrKY6XYn.js";
7
- import { T as k, S as Te, a as xe, I as ye, L as be } from "./custom-icons-QEBlxVyq.js";
8
- import { a as ls } from "./guards-BhaQgJrE.js";
9
- const De = Ze.forwardRef(
10
- ({ className: d, isInvalid: t, disabled: N, readOnly: E, required: u, variant: n, ...x }, l) => {
11
- const i = es(), m = n ?? (i.variant === "default" ? "filled" : "default");
12
- return /* @__PURE__ */ e(
13
- "textarea",
14
- {
15
- className: ss(
16
- "sc:flex sc:min-h-[80px] sc:w-full sc:rounded-input sc:px-2.5 sc:py-2 sc:text-sm sc:transition-colors",
17
- "sc:text-foreground sc:border-none",
18
- "sc:placeholder:text-foreground/50",
19
- "sc:focus-visible:outline-none sc:focus-visible:ring-2 sc:focus-visible:ring-focus",
20
- "sc:disabled:cursor-not-allowed sc:disabled:opacity-50",
21
- // Variant styles - semantic: field on page vs field on surface
22
- m === "default" && "sc:bg-field sc:shadow-soft sc:dark:shadow-none",
23
- m === "filled" && "sc:bg-[var(--color-field-on-surface)]",
24
- t && "sc:ring-2 sc:ring-danger sc:focus-visible:ring-danger",
25
- d
26
- ),
27
- ref: l,
28
- disabled: N,
29
- readOnly: E,
30
- required: u,
31
- "aria-invalid": t,
32
- ...x
33
- }
34
- );
35
- }
36
- );
37
- De.displayName = "Textarea";
38
- const $e = De;
39
- $e.displayName = "TextArea";
40
- const ie = ns("ImageBrowser"), is = "Image search is temporarily unavailable.", ze = "Image generation is temporarily unavailable.", ds = "Vector search is temporarily unavailable.", Ve = "Background removal is temporarily unavailable.";
41
- function us(d, t) {
42
- const N = d instanceof Error ? d.message : "";
43
- return !N || /VITE_|NEXT_PUBLIC_|\.env/i.test(N) ? t : N;
44
- }
45
- const ms = "1px", Ie = "1px", Pe = Be.memo(function({ image: t, onImageSelect: N, fixedHeight: E = !1 }) {
46
- const [u, n] = r(!1), [x, l] = r(!1), [i, m] = r("top"), h = U(null), C = U(null), w = U(null), V = U(!0), [S, R] = r(!1), f = U(null), Y = () => {
47
- x || N(t);
48
- }, W = (g) => {
49
- if (!w.current) return "top";
50
- const y = w.current.getBoundingClientRect(), L = g.clientX - y.left, M = g.clientY - y.top, A = y.width, se = y.height, T = {
51
- top: M,
52
- bottom: se - M,
53
- left: L,
54
- right: A - L
55
- }, $ = Math.min(T.top, T.bottom, T.left, T.right);
56
- return $ === T.top ? "top" : $ === T.bottom ? "bottom" : $ === T.left ? "left" : "right";
57
- }, Q = (g) => {
58
- const y = W(g);
59
- f.current && (cancelAnimationFrame(f.current), f.current = null), y !== i ? (R(!0), m(y), f.current = requestAnimationFrame(() => {
60
- f.current = requestAnimationFrame(() => {
61
- R(!1), n(!0), f.current = null;
62
- });
63
- })) : (m(y), n(!0)), V.current = !1;
64
- }, b = (g) => {
65
- f.current && (cancelAnimationFrame(f.current), f.current = null);
66
- const y = W(g);
67
- m(y), R(!1), n(!1);
68
- }, B = () => {
69
- C.current && (clearTimeout(C.current), C.current = null), h.current = setTimeout(() => {
70
- l(!0);
71
- }, 400);
72
- }, O = () => {
73
- h.current && (clearTimeout(h.current), h.current = null), l(!1);
74
- }, ee = () => {
75
- h.current && (clearTimeout(h.current), h.current = null), C.current && (clearTimeout(C.current), C.current = null);
76
- }, D = () => {
77
- l(!1);
78
- }, F = t.source === "unsplash" ? "Unsplash" : "Pixabay", j = u || x, P = () => {
79
- if (!u) return `scale(${1.12})`;
80
- switch (i) {
81
- case "top":
82
- return `scale(${1.12}) translateY(5%)`;
83
- case "bottom":
84
- return `scale(${1.12}) translateY(-5%)`;
85
- case "left":
86
- return `scale(${1.12}) translateX(5%)`;
87
- case "right":
88
- return `scale(${1.12}) translateX(-5%)`;
89
- default:
90
- return `scale(${1.12})`;
91
- }
92
- };
93
- return /* @__PURE__ */ c(
94
- "div",
95
- {
96
- ref: w,
97
- onClick: Y,
98
- onMouseEnter: Q,
99
- onMouseLeave: b,
100
- className: `sc:group sc:relative sc:cursor-pointer sc:overflow-hidden ${E ? "sc:h-full sc:rounded-xs" : "sc:break-inside-avoid sc:rounded-lg"}`,
101
- children: [
102
- /* @__PURE__ */ e(
103
- "img",
104
- {
105
- src: t.urls.small,
106
- alt: t.alt || "Image",
107
- className: `sc:duration-500 sc:ease-out ${S ? "sc:transition-none" : "sc:transition-transform"} ${E ? "sc:h-full sc:w-full sc:object-cover" : "sc:w-full sc:object-cover"}`,
108
- style: {
109
- transform: P(),
110
- filter: u ? "brightness(1)" : "brightness(0.95)"
111
- }
112
- }
113
- ),
114
- /* @__PURE__ */ e("div", { className: "sc:absolute sc:top-2 sc:right-2 sc:z-10", children: /* @__PURE__ */ e(
115
- "button",
116
- {
117
- className: `sc:relative sc:flex sc:h-6 sc:w-6 sc:items-center sc:justify-center sc:rounded-full sc:bg-black/30 sc:backdrop-blur-sm sc:transition-all sc:duration-300 sc:ease-in-out sc:hover:scale-110 ${j ? "sc:opacity-100" : "sc:pointer-events-none sc:opacity-0"}`,
118
- "aria-label": "Image info",
119
- onMouseEnter: B,
120
- onMouseLeave: O,
121
- children: /* @__PURE__ */ e(v, { icon: "lucide:aperture", className: "sc:size-4 sc:text-white/80" })
122
- }
123
- ) }),
124
- /* @__PURE__ */ e(
125
- "div",
126
- {
127
- className: `sc:absolute sc:inset-x-0 sc:bottom-0 sc:z-0 sc:bg-linear-to-t sc:from-black/80 sc:via-black/60 sc:to-transparent sc:px-3 sc:py-3 sc:pt-8 sc:transition-transform sc:duration-300 sc:ease-out ${x ? "sc:translate-y-0" : "sc:translate-y-full"}`,
128
- onMouseEnter: ee,
129
- onMouseLeave: D,
130
- children: /* @__PURE__ */ c("div", { className: "sc:flex sc:flex-col sc:gap-1", children: [
131
- /* @__PURE__ */ c("div", { className: "sc:flex sc:items-center sc:gap-2", children: [
132
- /* @__PURE__ */ e(
133
- v,
134
- {
135
- icon: t.source === "unsplash" ? "simple-icons:unsplash" : "simple-icons:pixabay",
136
- className: "sc:size-3 sc:text-white/80"
137
- }
138
- ),
139
- /* @__PURE__ */ e("span", { className: "sc:text-xs sc:font-medium sc:text-white/80", children: F })
140
- ] }),
141
- /* @__PURE__ */ c("div", { className: "sc:flex sc:flex-col sc:gap-0.5", children: [
142
- /* @__PURE__ */ e("span", { className: "sc:text-xs sc:text-white/60", children: "Photo by" }),
143
- /* @__PURE__ */ c("span", { className: "sc:text-sm sc:font-medium sc:text-white", children: [
144
- t.attribution.profileUrl ? /* @__PURE__ */ e(
145
- "a",
146
- {
147
- href: t.attribution.profileUrl,
148
- target: "_blank",
149
- rel: "noopener noreferrer",
150
- onClick: (g) => g.stopPropagation(),
151
- className: "sc:underline sc:decoration-white/40 sc:underline-offset-2 sc:hover:decoration-white",
152
- children: t.attribution.name
153
- }
154
- ) : t.attribution.name,
155
- t.attribution.sourceUrl && /* @__PURE__ */ c(K, { children: [
156
- " ",
157
- /* @__PURE__ */ e("span", { className: "sc:font-normal sc:text-white/60", children: "on" }),
158
- " ",
159
- /* @__PURE__ */ e(
160
- "a",
161
- {
162
- href: t.attribution.sourceUrl,
163
- target: "_blank",
164
- rel: "noopener noreferrer",
165
- onClick: (g) => g.stopPropagation(),
166
- className: "sc:underline sc:decoration-white/40 sc:underline-offset-2 sc:hover:decoration-white",
167
- children: F
168
- }
169
- )
170
- ] })
171
- ] })
172
- ] })
173
- ] })
174
- }
175
- )
176
- ]
177
- }
178
- );
179
- }), Ue = Be.memo(function({ vector: t, onVectorSelect: N, fixedHeight: E = !1 }) {
180
- const [u, n] = r(!1), [x, l] = r(!1), i = U(null), m = U(null), h = () => {
181
- x || N(t);
182
- }, C = () => {
183
- m.current && (clearTimeout(m.current), m.current = null), i.current = setTimeout(() => {
184
- l(!0);
185
- }, 400);
186
- }, w = () => {
187
- i.current && (clearTimeout(i.current), i.current = null), l(!1);
188
- }, V = () => {
189
- i.current && (clearTimeout(i.current), i.current = null), m.current && (clearTimeout(m.current), m.current = null);
190
- }, S = () => {
191
- l(!1);
192
- }, R = u || x;
193
- return /* @__PURE__ */ c(
194
- "div",
195
- {
196
- onClick: h,
197
- onMouseEnter: () => n(!0),
198
- onMouseLeave: () => n(!1),
199
- className: `sc:group sc:relative sc:cursor-pointer sc:overflow-hidden sc:bg-white/10 sc:transition-all sc:duration-300 ${E ? "sc:h-full sc:rounded-xs" : "sc:break-inside-avoid sc:rounded-lg"} ${u ? "sc:scale-105 sc:bg-white/20" : ""}`,
200
- children: [
201
- /* @__PURE__ */ e(
202
- "div",
203
- {
204
- className: `sc:flex sc:items-center sc:justify-center sc:p-6 sc:transition-all sc:duration-300 ${E ? "sc:h-full sc:w-full" : "sc:aspect-square sc:w-full"}`,
205
- children: /* @__PURE__ */ e(
206
- "img",
207
- {
208
- src: t.urls.preview,
209
- alt: t.term,
210
- className: `sc:max-h-full sc:max-w-full sc:object-contain sc:transition-all sc:duration-300 ${u ? "sc:scale-110" : "sc:scale-100"}`,
211
- style: {
212
- filter: u ? "brightness(1.1)" : "brightness(0.95)"
213
- }
214
- }
215
- )
216
- }
217
- ),
218
- /* @__PURE__ */ c("div", { className: "sc:absolute sc:top-2 sc:right-2 sc:z-10 sc:flex sc:items-center sc:gap-2", children: [
219
- !t.urls.svg && /* @__PURE__ */ e(
220
- "span",
221
- {
222
- className: `sc:rounded-xs sc:bg-amber-500/90 sc:px-1.5 sc:py-0.5 sc:text-[10px] sc:font-semibold sc:uppercase sc:tracking-wide sc:text-white sc:shadow-sm sc:transition-all sc:duration-300 sc:ease-in-out ${R ? "sc:opacity-100" : "sc:pointer-events-none sc:opacity-0"}`,
223
- children: "PNG"
224
- }
225
- ),
226
- /* @__PURE__ */ e(
227
- "button",
228
- {
229
- className: `sc:relative sc:flex sc:h-6 sc:w-6 sc:items-center sc:justify-center sc:rounded-full sc:bg-black/30 sc:backdrop-blur-sm sc:transition-all sc:duration-300 sc:ease-in-out sc:hover:scale-110 ${R ? "sc:opacity-100" : "sc:pointer-events-none sc:opacity-0"}`,
230
- "aria-label": "Vector info",
231
- onMouseEnter: C,
232
- onMouseLeave: w,
233
- children: /* @__PURE__ */ e(v, { icon: "lucide:aperture", className: "sc:size-4 sc:text-white/80" })
234
- }
235
- )
236
- ] }),
237
- /* @__PURE__ */ c(
238
- "div",
239
- {
240
- className: `sc:absolute sc:inset-x-0 sc:bottom-0 sc:z-0 sc:bg-linear-to-t sc:from-black/80 sc:via-black/60 sc:to-transparent sc:px-3 sc:py-3 sc:pt-8 sc:transition-transform sc:duration-300 sc:ease-out ${x ? "sc:translate-y-0" : "sc:translate-y-full"}`,
241
- onMouseEnter: V,
242
- onMouseLeave: S,
243
- children: [
244
- /* @__PURE__ */ c("div", { className: "sc:mb-1", children: [
245
- /* @__PURE__ */ e(v, { icon: "mdi:cube-outline", className: "sc:mr-2 sc:inline-block sc:size-3 sc:text-white/80" }),
246
- /* @__PURE__ */ e("span", { className: "sc:text-xs sc:font-medium sc:text-white/80", children: "Noun Project" })
247
- ] }),
248
- /* @__PURE__ */ e("div", { className: "sc:text-xs sc:text-white/60", children: "Icon by" }),
249
- /* @__PURE__ */ e("div", { className: "sc:text-sm sc:font-medium sc:text-white", children: t.uploader.name })
250
- ]
251
- }
252
- )
253
- ]
254
- }
255
- );
256
- }), fs = ({
257
- isOpen: d,
258
- onToggle: t,
259
- onImageSelect: N,
260
- currentImageUrl: E,
261
- placement: u = "bottom"
262
- }) => {
263
- const { imageSearch: n, generate: x, vectors: l, removeBackground: i } = cs(), m = Je(
264
- () => [
265
- ...n ? ["search"] : [],
266
- "url",
267
- ...l ? ["vector"] : [],
268
- ...x ? ["ai"] : []
269
- ],
270
- [n, l, x]
271
- ), [h, C] = r(""), [w, V] = r(""), [S, R] = r([]), [f, Y] = r(!1), [W, Q] = r(null), [b, B] = r(m[0]), [O, ee] = r(1), [D, F] = r(!0), [j, P] = r("masonry"), [g, y] = r(""), [L, M] = r([]), [A, se] = r(!1), [T, $] = r(null), [ce, ne] = r(null), [z, G] = r(!0), [o, q] = r("grid"), [X, de] = r(""), [oe, le] = r(!1), [Ee, ve] = r(null), [Z, Ne] = r(null), [ue, me] = r(!1), [fe, he] = r(null), ke = U(null), Ce = U(null), Re = U(null);
272
- J(() => {
273
- m.includes(b) || B(m[0]);
274
- }, [m, b]), J(() => {
275
- d && E && (V(E), B("url"));
276
- }, [d, E]), J(() => {
277
- d || (C(""), V(""), R([]), Q(null), ee(1), F(!0), y(""), M([]), $(null), ne(null), G(!0));
278
- }, [d]);
279
- const ge = ae(
280
- async (s, a, p) => {
281
- if (n) {
282
- Y(!0), Q(null);
283
- try {
284
- const I = await n.search({ query: s, page: a, perPage: 30 });
285
- R((H) => p ? [...H, ...I.results] : I.results), ee(I.page), F(I.hasMore);
286
- } catch (I) {
287
- Q(is), ie.error("Error searching images:", I);
288
- } finally {
289
- Y(!1);
290
- }
291
- }
292
- },
293
- [n]
294
- );
295
- J(() => {
296
- d && !h && b === "search" && S.length === 0 && n && ge("", 1, !1);
297
- }, [d, b, n]);
298
- const je = (s) => {
299
- s.preventDefault(), ge(h, 1, !1);
300
- }, Se = ae(() => {
301
- f || !D || ge(h, O + 1, !0);
302
- }, [f, D, h, O, ge]);
303
- J(() => {
304
- const s = ke.current;
305
- if (!s || !d || b !== "search") return;
306
- const a = new IntersectionObserver(
307
- (p) => {
308
- p[0].isIntersecting && D && !f && Se();
309
- },
310
- {
311
- root: null,
312
- // viewport
313
- rootMargin: "200px",
314
- // Trigger 200px before sentinel is visible
315
- threshold: 0
316
- }
317
- );
318
- return a.observe(s), () => {
319
- a.disconnect();
320
- };
321
- }, [d, b, D, f, Se]);
322
- const pe = ae(
323
- async (s, a) => {
324
- if (l) {
325
- se(!0), $(null);
326
- try {
327
- const { results: p, nextPage: I } = await l.search({ query: s, nextPage: a ?? null });
328
- M(a ? (H) => {
329
- const we = new Set(H.map((te) => te.id));
330
- return [...H, ...p.filter((te) => !we.has(te.id))];
331
- } : p), ne(I), G(I !== null);
332
- } catch (p) {
333
- $(ds), ie.error("Error searching vectors:", p);
334
- } finally {
335
- se(!1);
336
- }
337
- }
338
- },
339
- [l]
340
- );
341
- J(() => {
342
- d && !g && b === "vector" && L.length === 0 && l && pe("");
343
- }, [d, b, l]);
344
- const Ge = (s) => {
345
- s.preventDefault(), pe(g);
346
- }, Le = ae(() => {
347
- A || !z || !ce || pe(g, ce);
348
- }, [A, z, ce, g, pe]);
349
- J(() => {
350
- const s = Ce.current;
351
- if (!s || !d || b !== "vector") return;
352
- const a = new IntersectionObserver(
353
- (p) => {
354
- p[0].isIntersecting && z && !A && Le();
355
- },
356
- {
357
- root: null,
358
- rootMargin: "200px",
359
- threshold: 0
360
- }
361
- );
362
- return a.observe(s), () => {
363
- a.disconnect();
364
- };
365
- }, [d, b, z, A, Le]);
366
- const Me = (s) => {
367
- const a = s.selectUrl || s.urls.svg || s.urls.png;
368
- a && (N(a), t(!1));
369
- }, Ae = (s) => {
370
- var a;
371
- try {
372
- Promise.resolve((a = n == null ? void 0 : n.trackSelect) == null ? void 0 : a.call(n, s)).catch(() => {
373
- });
374
- } catch {
375
- }
376
- N(s.urls.regular), t(!1);
377
- }, He = (s) => {
378
- s.preventDefault(), w.trim() && (N(w.trim()), t(!1));
379
- }, _e = (s) => {
380
- var p;
381
- const a = (p = s.target.files) == null ? void 0 : p[0];
382
- if (a && a.type.startsWith("image/")) {
383
- const I = new FileReader();
384
- I.onload = (H) => {
385
- var te;
386
- const we = (te = H.target) == null ? void 0 : te.result;
387
- V(we);
388
- }, I.readAsDataURL(a);
389
- }
390
- }, Fe = () => {
391
- var s;
392
- (s = Re.current) == null || s.click();
393
- }, Xe = async () => {
394
- if (!(!i || !w.trim())) {
395
- me(!0), he(null);
396
- try {
397
- const s = await i(w);
398
- V(s);
399
- } catch (s) {
400
- he(Ve), ie.error("Error removing background:", s);
401
- } finally {
402
- me(!1);
403
- }
404
- }
405
- }, Ye = async (s) => {
406
- var a, p;
407
- if (s.preventDefault(), !!x) {
408
- if (!X.trim()) {
409
- ve("Please enter a prompt");
410
- return;
411
- }
412
- le(!0), ve(null), Ne(null);
413
- try {
414
- const H = (p = (a = (await x.generate({
415
- prompt: X,
416
- width: 1024,
417
- height: 1024,
418
- numberResults: 1
419
- })).images) == null ? void 0 : a[0]) == null ? void 0 : p.imageUrl;
420
- if (!H)
421
- throw new Error(ze);
422
- Ne(H);
423
- } catch (I) {
424
- ve(us(I, ze)), ie.error("Error generating AI image:", I);
425
- } finally {
426
- le(!1);
427
- }
428
- }
429
- }, We = () => {
430
- Z && (N(Z), t(!1));
431
- }, Qe = async () => {
432
- if (!(!i || !Z)) {
433
- me(!0), he(null);
434
- try {
435
- const s = await i(Z);
436
- Ne(s);
437
- } catch (s) {
438
- he(Ve), ie.error("Error removing background:", s);
439
- } finally {
440
- me(!1);
441
- }
442
- }
443
- }, qe = (s, a) => {
444
- const p = s.width / s.height;
445
- return a % 12 === 0 && p > 0.8 && p < 1.2 ? "sc:col-span-2 sc:row-span-2" : p < 0.75 ? "sc:row-span-2" : p > 1.5 ? "sc:col-span-2" : "";
446
- };
447
- return /* @__PURE__ */ e(
448
- ts,
449
- {
450
- isOpen: d,
451
- onClose: () => t(!1),
452
- title: "Image Browser",
453
- description: "Browse images or enter a custom image URL",
454
- placement: u,
455
- height: u === "bottom" ? "90vh" : void 0,
456
- width: u !== "bottom" ? "500px" : void 0,
457
- hideHandle: !0,
458
- hideVisibleTitle: !0,
459
- showCloseButton: !1,
460
- "data-testid": "image-browser-drawer",
461
- children: /* @__PURE__ */ c(
462
- k,
463
- {
464
- value: b,
465
- onValueChange: (s) => B(s),
466
- className: "sc:flex sc:flex-col",
467
- "data-testid": "image-browser-container",
468
- children: [
469
- /* @__PURE__ */ e(k.ListContainer, { className: "sc:flex sc:justify-center sc:pt-4 sc:pb-2", children: /* @__PURE__ */ c(
470
- k.List,
471
- {
472
- className: "sc:h-14 sc:gap-1 sc:px-1.5 sc:md:h-12",
473
- "aria-label": "Image source",
474
- children: [
475
- n && /* @__PURE__ */ c(
476
- k.Tab,
477
- {
478
- id: "search",
479
- className: "sc:h-11 sc:w-14 sc:px-0 sc:md:h-9 sc:md:w-11",
480
- "data-testid": "image-tab-search",
481
- children: [
482
- /* @__PURE__ */ e(v, { icon: re.image, className: "sc:size-6" }),
483
- /* @__PURE__ */ e(k.Indicator, {})
484
- ]
485
- }
486
- ),
487
- /* @__PURE__ */ c(
488
- k.Tab,
489
- {
490
- id: "url",
491
- className: "sc:h-11 sc:w-14 sc:px-0 sc:md:h-9 sc:md:w-11",
492
- "data-testid": "image-tab-url",
493
- children: [
494
- /* @__PURE__ */ e(v, { icon: re.link, className: "sc:size-6" }),
495
- /* @__PURE__ */ e(k.Indicator, {})
496
- ]
497
- }
498
- ),
499
- l && /* @__PURE__ */ c(
500
- k.Tab,
501
- {
502
- id: "vector",
503
- className: "sc:h-11 sc:w-14 sc:px-0 sc:md:h-9 sc:md:w-11",
504
- "data-testid": "image-tab-vector",
505
- children: [
506
- /* @__PURE__ */ e(v, { icon: "fa6-solid:icons", className: "sc:size-5" }),
507
- /* @__PURE__ */ e(k.Indicator, {})
508
- ]
509
- }
510
- ),
511
- x && /* @__PURE__ */ c(
512
- k.Tab,
513
- {
514
- id: "ai",
515
- className: "sc:h-11 sc:w-14 sc:px-0 sc:md:h-9 sc:md:w-11",
516
- "data-testid": "image-tab-ai",
517
- children: [
518
- /* @__PURE__ */ e(Te, { size: 24 }),
519
- /* @__PURE__ */ e(k.Indicator, {})
520
- ]
521
- }
522
- )
523
- ]
524
- }
525
- ) }),
526
- n && /* @__PURE__ */ c(k.Panel, { id: "search", className: "sc:flex sc:flex-col", children: [
527
- /* @__PURE__ */ c("form", { onSubmit: je, className: "sc:sticky sc:top-0 sc:z-9 sc:flex sc:gap-2 sc:bg-surface sc:px-6 sc:pt-4 sc:pb-3", children: [
528
- /* @__PURE__ */ e(xe, { className: "sc:flex-1", "aria-label": "Search for images", children: /* @__PURE__ */ e(
529
- ye,
530
- {
531
- type: "text",
532
- placeholder: "Search for images...",
533
- value: h,
534
- onChange: (s) => C(s.target.value),
535
- variant: "subtle",
536
- "data-testid": "image-search-input"
537
- }
538
- ) }),
539
- /* @__PURE__ */ e(_, { type: "submit", size: "icon", variant: "secondary", disabled: f, "aria-label": "Search", children: /* @__PURE__ */ e(v, { icon: re.search, className: "sc:size-5" }) }),
540
- /* @__PURE__ */ e(
541
- _,
542
- {
543
- size: "icon",
544
- variant: "secondary",
545
- onClick: () => P(j === "grid" ? "masonry" : "grid"),
546
- "aria-label": j === "grid" ? "Switch to masonry view" : "Switch to grid view",
547
- children: j === "grid" ? /* @__PURE__ */ e(v, { icon: "lucide:layout-grid", className: "sc:size-5" }) : /* @__PURE__ */ e(v, { icon: re.grip, className: "sc:size-5" })
548
- }
549
- )
550
- ] }),
551
- W && /* @__PURE__ */ e("div", { className: "sc:border-danger sc:bg-danger/10 sc:text-danger sc:mx-6 sc:mb-3 sc:rounded-2xl sc:border-2 sc:px-4 sc:py-3 sc:text-sm", children: W }),
552
- f && S.length === 0 && /* @__PURE__ */ e("div", { className: "sc:text-muted sc:px-6 sc:py-8 sc:text-center sc:text-sm", children: "Loading images..." }),
553
- S.length > 0 && /* @__PURE__ */ c("div", { className: "sc:mx-6 sc:overflow-hidden sc:rounded-t-2xl", children: [
554
- j === "masonry" ? (
555
- /* CSS Grid Masonry (Dense) */
556
- /* @__PURE__ */ e(
557
- "div",
558
- {
559
- className: "sc:grid sc:grid-flow-dense sc:pb-4",
560
- style: {
561
- display: "grid",
562
- gridTemplateColumns: u === "bottom" ? "repeat(auto-fill, minmax(200px, 1fr))" : "repeat(3, 1fr)",
563
- gridAutoRows: u === "bottom" ? "200px" : "120px",
564
- gap: ms
565
- },
566
- children: S.map((s, a) => /* @__PURE__ */ e("div", { className: qe(s, a), children: /* @__PURE__ */ e(Pe, { image: s, onImageSelect: Ae, fixedHeight: !0 }) }, s.id))
567
- }
568
- )
569
- ) : (
570
- /* Fixed Height Grid - Square Tiles */
571
- /* @__PURE__ */ e(
572
- "div",
573
- {
574
- className: "sc:pb-4",
575
- style: {
576
- display: "grid",
577
- gridTemplateColumns: u === "bottom" ? "repeat(auto-fill, minmax(150px, 1fr))" : "repeat(auto-fill, minmax(120px, 1fr))",
578
- gap: Ie
579
- },
580
- children: S.map((s) => /* @__PURE__ */ e("div", { style: { aspectRatio: "1 / 1" }, children: /* @__PURE__ */ e(Pe, { image: s, onImageSelect: Ae, fixedHeight: !0 }) }, s.id))
581
- }
582
- )
583
- ),
584
- D && /* @__PURE__ */ e("div", { ref: ke, className: "sc:h-px" }),
585
- f && /* @__PURE__ */ e("div", { className: "sc:text-muted sc:py-4 sc:text-center sc:text-sm", children: "Loading more..." }),
586
- !D && !f && /* @__PURE__ */ e("div", { className: "sc:text-muted sc:py-6 sc:text-center sc:text-sm", children: "No more images" })
587
- ] }),
588
- !f && S.length === 0 && h && /* @__PURE__ */ c("div", { className: "sc:text-muted sc:px-6 sc:py-12 sc:text-center sc:text-sm", children: [
589
- 'No images found for "',
590
- h,
591
- '"'
592
- ] })
593
- ] }),
594
- /* @__PURE__ */ c(k.Panel, { id: "url", className: "sc:flex sc:flex-col sc:gap-5 sc:p-6", children: [
595
- /* @__PURE__ */ e(
596
- "input",
597
- {
598
- ref: Re,
599
- type: "file",
600
- accept: "image/*",
601
- onChange: _e,
602
- className: "sc:hidden"
603
- }
604
- ),
605
- /* @__PURE__ */ c(
606
- "button",
607
- {
608
- type: "button",
609
- onClick: Fe,
610
- className: "sc:flex sc:flex-col sc:items-center sc:justify-center sc:gap-3 sc:rounded-2xl sc:border-2 sc:border-dashed sc:border-divider sc:bg-muted/30 sc:px-6 sc:py-10 sc:transition-colors sc:hover:bg-muted/50 sc:active:bg-muted/60",
611
- "data-testid": "image-upload-btn",
612
- children: [
613
- /* @__PURE__ */ e(
614
- v,
615
- {
616
- icon: "lucide:upload-cloud",
617
- className: "sc:size-10 sc:text-foreground/60"
618
- }
619
- ),
620
- /* @__PURE__ */ c("div", { className: "sc:flex sc:flex-col sc:items-center sc:gap-1", children: [
621
- /* @__PURE__ */ e("span", { className: "sc:text-base sc:font-medium sc:text-foreground", children: "Upload from device" }),
622
- /* @__PURE__ */ e("span", { className: "sc:text-xs sc:text-muted-foreground", children: "PNG · JPG · SVG · GIF" })
623
- ] })
624
- ]
625
- }
626
- ),
627
- /* @__PURE__ */ c("div", { className: "sc:relative sc:flex sc:items-center sc:gap-3", children: [
628
- /* @__PURE__ */ e("div", { className: "sc:h-px sc:flex-1 sc:bg-divider" }),
629
- /* @__PURE__ */ e("span", { className: "sc:text-muted-foreground sc:text-xs sc:uppercase sc:tracking-wider", children: "or paste a link" }),
630
- /* @__PURE__ */ e("div", { className: "sc:h-px sc:flex-1 sc:bg-divider" })
631
- ] }),
632
- /* @__PURE__ */ c(
633
- "form",
634
- {
635
- onSubmit: He,
636
- className: "sc:flex sc:flex-col sc:gap-3",
637
- children: [
638
- /* @__PURE__ */ c(xe, { children: [
639
- /* @__PURE__ */ e(be, { className: "sc:sr-only", children: "Image URL" }),
640
- /* @__PURE__ */ e(
641
- ye,
642
- {
643
- type: "url",
644
- placeholder: "https://example.com/image.jpg",
645
- value: w,
646
- onChange: (s) => V(s.target.value),
647
- variant: "subtle",
648
- "data-testid": "image-url-input"
649
- }
650
- )
651
- ] }),
652
- /* @__PURE__ */ e(
653
- _,
654
- {
655
- type: "submit",
656
- variant: "default",
657
- disabled: !w.trim(),
658
- className: "sc:w-full",
659
- "data-testid": "image-url-submit-btn",
660
- children: "Use This Image"
661
- }
662
- )
663
- ]
664
- }
665
- ),
666
- w.trim() && /* @__PURE__ */ c("div", { className: "sc:flex sc:flex-col sc:gap-3 sc:rounded-2xl sc:border sc:border-divider sc:bg-muted/30 sc:p-4", children: [
667
- /* @__PURE__ */ c("div", { className: "sc:flex sc:items-center sc:justify-between sc:gap-3", children: [
668
- /* @__PURE__ */ e("span", { className: "sc:text-xs sc:font-medium sc:uppercase sc:tracking-wider sc:text-muted-foreground", children: "Preview" }),
669
- i && /* @__PURE__ */ e(
670
- _,
671
- {
672
- onClick: Xe,
673
- disabled: ue || !w.trim(),
674
- variant: "secondary",
675
- size: "sm",
676
- className: "sc:gap-2",
677
- "data-testid": "remove-background-btn",
678
- children: ue ? /* @__PURE__ */ c(K, { children: [
679
- /* @__PURE__ */ e(
680
- v,
681
- {
682
- icon: "eos-icons:loading",
683
- className: "sc:size-4 sc:animate-spin"
684
- }
685
- ),
686
- "Removing…"
687
- ] }) : /* @__PURE__ */ c(K, { children: [
688
- /* @__PURE__ */ e(v, { icon: "mdi:image-remove", className: "sc:size-4" }),
689
- "Remove BG"
690
- ] })
691
- }
692
- )
693
- ] }),
694
- fe && /* @__PURE__ */ e("div", { className: "sc:rounded-lg sc:border sc:border-danger sc:bg-danger/10 sc:px-3 sc:py-2 sc:text-xs sc:text-danger", children: fe }),
695
- /* @__PURE__ */ e(
696
- "img",
697
- {
698
- src: w,
699
- alt: "Preview",
700
- className: "sc:max-h-[280px] sc:w-full sc:rounded-lg sc:object-contain",
701
- onError: (s) => {
702
- s.target.style.display = "none";
703
- },
704
- onLoad: (s) => {
705
- s.target.style.display = "block";
706
- }
707
- }
708
- )
709
- ] })
710
- ] }),
711
- l && /* @__PURE__ */ c(k.Panel, { id: "vector", className: "sc:flex sc:flex-col", children: [
712
- /* @__PURE__ */ c("form", { onSubmit: Ge, className: "sc:sticky sc:top-0 sc:z-9 sc:flex sc:gap-2 sc:bg-surface sc:px-6 sc:pt-4 sc:pb-3", children: [
713
- /* @__PURE__ */ e(xe, { className: "sc:flex-1", "aria-label": "Search for vector graphics", children: /* @__PURE__ */ e(
714
- ye,
715
- {
716
- type: "text",
717
- placeholder: "Search for icons...",
718
- value: g,
719
- onChange: (s) => y(s.target.value),
720
- variant: "subtle",
721
- "data-testid": "vector-search-input"
722
- }
723
- ) }),
724
- /* @__PURE__ */ e(_, { type: "submit", size: "icon", variant: "secondary", disabled: A, "aria-label": "Search", children: /* @__PURE__ */ e(v, { icon: re.search, className: "sc:size-5" }) }),
725
- /* @__PURE__ */ e(
726
- _,
727
- {
728
- size: "icon",
729
- variant: "secondary",
730
- onClick: () => q(o === "grid" ? "masonry" : "grid"),
731
- "aria-label": o === "grid" ? "Switch to masonry view" : "Switch to grid view",
732
- children: o === "grid" ? /* @__PURE__ */ e(v, { icon: "lucide:layout-grid", className: "sc:size-5" }) : /* @__PURE__ */ e(v, { icon: re.grip, className: "sc:size-5" })
733
- }
734
- )
735
- ] }),
736
- T && /* @__PURE__ */ e("div", { className: "sc:border-danger sc:bg-danger/10 sc:text-danger sc:mx-6 sc:mb-3 sc:rounded-2xl sc:border-2 sc:px-4 sc:py-3 sc:text-sm", children: T }),
737
- A && L.length === 0 && /* @__PURE__ */ e("div", { className: "sc:text-muted sc:px-6 sc:py-8 sc:text-center sc:text-sm", children: "Loading vectors..." }),
738
- L.length > 0 && /* @__PURE__ */ c("div", { className: "sc:mx-6 sc:overflow-hidden sc:rounded-t-2xl", children: [
739
- o === "masonry" ? (
740
- /* CSS Grid Masonry */
741
- /* @__PURE__ */ e(
742
- "div",
743
- {
744
- className: "sc:grid sc:grid-flow-dense sc:pb-4",
745
- style: {
746
- display: "grid",
747
- gridTemplateColumns: u === "bottom" ? "repeat(auto-fill, minmax(150px, 1fr))" : "repeat(3, 1fr)",
748
- gridAutoRows: u === "bottom" ? "150px" : "120px",
749
- gap: Ie
750
- },
751
- children: L.map((s) => /* @__PURE__ */ e("div", { children: /* @__PURE__ */ e(Ue, { vector: s, onVectorSelect: Me, fixedHeight: !0 }) }, s.id))
752
- }
753
- )
754
- ) : (
755
- /* Fixed Height Grid - Square Tiles */
756
- /* @__PURE__ */ e(
757
- "div",
758
- {
759
- className: "sc:pb-4",
760
- style: {
761
- display: "grid",
762
- gridTemplateColumns: u === "bottom" ? "repeat(auto-fill, minmax(120px, 1fr))" : "repeat(auto-fill, minmax(100px, 1fr))",
763
- gap: Ie
764
- },
765
- children: L.map((s) => /* @__PURE__ */ e("div", { style: { aspectRatio: "1 / 1" }, children: /* @__PURE__ */ e(Ue, { vector: s, onVectorSelect: Me, fixedHeight: !0 }) }, s.id))
766
- }
767
- )
768
- ),
769
- z && /* @__PURE__ */ e("div", { ref: Ce, className: "sc:h-px" }),
770
- A && /* @__PURE__ */ e("div", { className: "sc:text-muted sc:py-4 sc:text-center sc:text-sm", children: "Loading more..." }),
771
- !z && !A && /* @__PURE__ */ e("div", { className: "sc:text-muted sc:py-6 sc:text-center sc:text-sm", children: "No more vectors" })
772
- ] }),
773
- !A && L.length === 0 && g && /* @__PURE__ */ c("div", { className: "sc:text-muted sc:px-6 sc:py-12 sc:text-center sc:text-sm", children: [
774
- 'No vectors found for "',
775
- g,
776
- '"'
777
- ] })
778
- ] }),
779
- x && /* @__PURE__ */ c(k.Panel, { id: "ai", className: "sc:flex sc:flex-col sc:gap-6 sc:p-6", children: [
780
- /* @__PURE__ */ c("form", { onSubmit: Ye, className: "sc:flex sc:flex-col sc:gap-6", children: [
781
- /* @__PURE__ */ c(xe, { children: [
782
- /* @__PURE__ */ e(be, { children: "Prompt" }),
783
- /* @__PURE__ */ e(
784
- $e,
785
- {
786
- placeholder: "Describe the image you want to generate... (e.g., 'avocado, transparent background')",
787
- value: X,
788
- onChange: (s) => de(s.target.value),
789
- className: "sc:min-h-[100px] sc:resize-y",
790
- rows: 4,
791
- "data-testid": "ai-prompt-input",
792
- disabled: oe
793
- }
794
- )
795
- ] }),
796
- /* @__PURE__ */ e(
797
- _,
798
- {
799
- type: "submit",
800
- variant: "default",
801
- disabled: !X.trim() || oe,
802
- className: "sc:w-full",
803
- "data-testid": "ai-generate-btn",
804
- children: oe ? /* @__PURE__ */ c(K, { children: [
805
- /* @__PURE__ */ e(v, { icon: "eos-icons:loading", className: "sc:size-5 sc:animate-spin" }),
806
- "Generating..."
807
- ] }) : /* @__PURE__ */ c(K, { children: [
808
- /* @__PURE__ */ e(Te, { size: 24 }),
809
- "Generate Image"
810
- ] })
811
- }
812
- )
813
- ] }),
814
- Ee && /* @__PURE__ */ e("div", { className: "sc:border-danger sc:bg-danger/10 sc:text-danger sc:rounded-2xl sc:border-2 sc:px-4 sc:py-3 sc:text-sm", children: Ee }),
815
- Z && /* @__PURE__ */ c("div", { className: "sc:flex sc:flex-col sc:gap-4 sc:rounded-2xl sc:border sc:border-divider sc:bg-muted/40 sc:p-6", children: [
816
- /* @__PURE__ */ e("div", { className: "sc:flex sc:items-center sc:justify-between", children: /* @__PURE__ */ e(be, { className: "sc:text-muted sc:text-xs sc:uppercase sc:tracking-wide", children: "Generated Image" }) }),
817
- /* @__PURE__ */ e("div", { className: "sc:flex sc:w-fit sc:items-center sc:justify-center sc:overflow-hidden sc:rounded-lg sc:bg-white/50 sc:dark:bg-black/50", style: { maxHeight: "500px", maxWidth: "100%" }, children: /* @__PURE__ */ e(
818
- "img",
819
- {
820
- src: Z,
821
- alt: X,
822
- className: "sc:max-h-full sc:max-w-full sc:object-contain"
823
- }
824
- ) }),
825
- /* @__PURE__ */ c("div", { className: "sc:flex sc:flex-col sc:gap-1", children: [
826
- /* @__PURE__ */ e(be, { className: "sc:text-muted sc:text-xs", children: "Prompt" }),
827
- /* @__PURE__ */ e("p", { className: "sc:text-sm", children: X })
828
- ] }),
829
- /* @__PURE__ */ c("div", { className: "sc:flex sc:flex-col sc:gap-3", children: [
830
- i && /* @__PURE__ */ e(
831
- _,
832
- {
833
- onClick: Qe,
834
- disabled: ue || !Z,
835
- variant: "secondary",
836
- size: "sm",
837
- className: "sc:w-full sc:gap-2",
838
- "data-testid": "ai-remove-background-btn",
839
- children: ue ? /* @__PURE__ */ c(K, { children: [
840
- /* @__PURE__ */ e(v, { icon: "eos-icons:loading", className: "sc:size-4 sc:animate-spin" }),
841
- "Removing..."
842
- ] }) : /* @__PURE__ */ c(K, { children: [
843
- /* @__PURE__ */ e(v, { icon: "mdi:image-remove", className: "sc:size-4" }),
844
- "Remove Background"
845
- ] })
846
- }
847
- ),
848
- fe && /* @__PURE__ */ e("div", { className: "sc:border-danger sc:bg-danger/10 sc:text-danger sc:rounded-xl sc:border-2 sc:px-3 sc:py-2 sc:text-xs", children: fe }),
849
- /* @__PURE__ */ e(
850
- _,
851
- {
852
- onClick: We,
853
- variant: "default",
854
- className: "sc:w-full",
855
- "data-testid": "ai-use-image-btn",
856
- children: "Use This Image"
857
- }
858
- )
859
- ] })
860
- ] })
861
- ] })
862
- ]
863
- }
864
- )
865
- }
866
- );
867
- }, ws = ({
868
- isOpen: d,
869
- onOpenChange: t,
870
- onImageAdded: N,
871
- onImageChanged: E,
872
- changingElementId: u,
873
- onChangingElementIdChange: n,
874
- services: x
875
- }) => {
876
- var j;
877
- const { elements: l, setElements: i, canvasEditorRef: m, artboardManager: h, executeAddElement: C, executeElementUpdate: w } = Ke(), { selectedId: V, setSelectedId: S } = Oe(), { activeArtboardId: R } = rs(), f = U(l);
878
- f.current = l;
879
- const Y = U(V);
880
- Y.current = V;
881
- const [W, Q] = r(null), b = u ?? W, B = n ?? Q, O = ae(
882
- (P) => {
883
- var ce, ne;
884
- const g = f.current, y = Y.current;
885
- if (b) {
886
- const z = g.find((G) => G.id === b);
887
- if (z && ls(z)) {
888
- const G = z, o = z.clone(), q = ((ce = m.current) == null ? void 0 : ce.getZoom()) || 1;
889
- o.imageUrl = P, o.transformData.width = 300 / q, o.transformData.height = 300 / q, o.transformData.cropX = 0, o.transformData.cropY = 0, o.transformData.cropWidth = 1, o.transformData.cropHeight = 1, o.transformData.flipHorizontal = !1, o.transformData.flipVertical = !1, o.transformData.borderRadius = 0, o.imageLoaded = !1, o.imageElement = null, o.isCropping = !1, o.onLoadCallback = (X) => {
890
- const de = X;
891
- i((oe) => oe.map((le) => le.id === de.id ? de : le));
892
- }, o.loadImage(P), w(G, o), E && E(o);
893
- }
894
- B(null);
895
- return;
896
- }
897
- if (!R) {
898
- alert("Please create or select an artboard first");
899
- return;
900
- }
901
- const L = `element-${Date.now()}`, M = h.getActiveArtboard(), A = M ? M.x + M.width / 2 : window.innerWidth / 2, se = M ? M.y + M.height / 2 : window.innerHeight / 2, T = ((ne = m.current) == null ? void 0 : ne.getZoom()) || 1, $ = new os({
902
- id: L,
903
- x: A,
904
- y: se,
905
- imageUrl: P,
906
- transformData: {
907
- width: 300 / T,
908
- height: 300 / T
909
- },
910
- onLoadCallback: (z) => {
911
- const G = z;
912
- i((o) => o.map((q) => q.id === G.id ? G : q));
913
- }
914
- });
915
- h.addElementToArtboard(L, R), C($, R, y || void 0), S(L), N && N($);
916
- },
917
- [
918
- b,
919
- // Note: elements and selectedId are accessed via refs (elementsRef, selectedIdRef)
920
- // to prevent callback recreation on every context update
921
- h,
922
- C,
923
- w,
924
- R,
925
- m,
926
- i,
927
- S,
928
- B,
929
- N,
930
- E
931
- ]
932
- ), ee = ae(
933
- (P) => {
934
- t(P), P || B(null);
935
- },
936
- [t, B]
937
- ), D = b ? (j = l.find((P) => P.id === b)) == null ? void 0 : j.imageUrl : void 0, F = /* @__PURE__ */ e(
938
- fs,
939
- {
940
- isOpen: d,
941
- onToggle: ee,
942
- onImageSelect: O,
943
- currentImageUrl: D
944
- }
945
- );
946
- return x ? /* @__PURE__ */ e(as, { services: x, children: F }) : F;
947
- };
948
- export {
949
- ws as ImagePanel
950
- };
951
- //# sourceMappingURL=ImagePanel-Ckpc6QqR.js.map