@declarion/react 0.1.79 → 0.1.80

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.
@@ -0,0 +1,571 @@
1
+ import { createContext as e, useCallback as t, useContext as n, useMemo as r, useRef as i } from "react";
2
+ import { jsx as a } from "react/jsx-runtime";
3
+ //#region src/types/api.ts
4
+ var o = class extends Error {
5
+ status;
6
+ code;
7
+ index;
8
+ raw;
9
+ constructor(e, t, n, r, i) {
10
+ super(t), this.name = "ApiError", this.status = e, this.code = n, this.index = r, this.raw = i;
11
+ }
12
+ }, s = "/", c = "/login", l = "/signup", u = "https://declarion.local";
13
+ function d(e) {
14
+ let t = e.split(/[?#]/, 1)[0];
15
+ return t === c || t.startsWith(`${c}/`) || t === l || t.startsWith(`${l}/`);
16
+ }
17
+ function f(e) {
18
+ if (!e) return s;
19
+ let t = e.toLowerCase();
20
+ if (!e.startsWith("/") || e.startsWith("//") || e.includes("\\") || t.includes("%5c")) return s;
21
+ try {
22
+ let t = new URL(e, u);
23
+ if (t.origin !== u) return s;
24
+ let n = `${t.pathname}${t.search}${t.hash}`;
25
+ return !n.startsWith("/") || n.startsWith("//") || n.includes("\\") ? s : n || s;
26
+ } catch {
27
+ return s;
28
+ }
29
+ }
30
+ function p(e) {
31
+ let t = f(e);
32
+ return t === s || d(t) ? c : `${c}?next=${encodeURIComponent(t)}`;
33
+ }
34
+ function m() {
35
+ if (typeof window > "u") return c;
36
+ let { pathname: e, search: t, hash: n } = window.location;
37
+ return p(`${e}${t}${n}`);
38
+ }
39
+ //#endregion
40
+ //#region src/lib/versionTracker.ts
41
+ var h = "X-Declarion-Version", g = "declarion-version";
42
+ function _() {
43
+ if (typeof BroadcastChannel > "u") return null;
44
+ try {
45
+ return new BroadcastChannel(g);
46
+ } catch {
47
+ return null;
48
+ }
49
+ }
50
+ var v = {
51
+ firstSeen: null,
52
+ firstComponents: null,
53
+ hasReportedDrift: !1,
54
+ listeners: /* @__PURE__ */ new Set(),
55
+ channel: null
56
+ };
57
+ function y() {
58
+ v.channel || typeof BroadcastChannel > "u" || (v.channel = _(), v.channel && v.channel.addEventListener("message", (e) => {
59
+ let t = e.data;
60
+ if (!(!t || t.type !== "drift" || !t.delta) && !v.hasReportedDrift) {
61
+ v.hasReportedDrift = !0;
62
+ for (let e of v.listeners) e(t.delta);
63
+ }
64
+ }));
65
+ }
66
+ function b(e) {
67
+ if (y(), !e) return;
68
+ let t = e.get(h);
69
+ if (t) {
70
+ if (!v.firstSeen) {
71
+ v.firstSeen = t;
72
+ return;
73
+ }
74
+ t !== v.firstSeen && (v.hasReportedDrift || x().catch(() => {
75
+ C({
76
+ kind: "unknown",
77
+ observed: t
78
+ });
79
+ }));
80
+ }
81
+ }
82
+ async function x() {
83
+ y();
84
+ let e;
85
+ try {
86
+ let t = {};
87
+ v.firstSeen && (t["If-None-Match"] = `"${v.firstSeen}"`), e = await fetch("/api/version", {
88
+ method: "GET",
89
+ credentials: "include",
90
+ headers: t
91
+ });
92
+ } catch {
93
+ throw Error("version probe network error");
94
+ }
95
+ if (e.status === 304) return;
96
+ if (!e.ok) throw Error(`version probe ${e.status}`);
97
+ let t;
98
+ try {
99
+ t = await e.json();
100
+ } catch {
101
+ throw Error("version probe malformed body");
102
+ }
103
+ let n = t.fingerprint;
104
+ if (typeof n != "string" || n === "") throw Error("version probe missing fingerprint");
105
+ let r = typeof t.schema_fingerprint == "string" && typeof t.asset_fingerprint == "string" && typeof t.binary_fingerprint == "string" ? {
106
+ schema: t.schema_fingerprint,
107
+ asset: t.asset_fingerprint,
108
+ binary: t.binary_fingerprint
109
+ } : void 0;
110
+ v.firstSeen ||= n, !v.firstComponents && r && n === v.firstSeen && (v.firstComponents = r), n !== v.firstSeen && C({
111
+ kind: S(v.firstComponents, r),
112
+ observed: n,
113
+ components: r
114
+ });
115
+ }
116
+ function S(e, t) {
117
+ if (!e || !t) return "unknown";
118
+ let n = e.schema !== t.schema, r = e.asset !== t.asset, i = e.binary !== t.binary;
119
+ return n && !r && !i ? "schema-only" : r || i ? "asset-or-binary" : "unknown";
120
+ }
121
+ function C(e) {
122
+ if (!v.hasReportedDrift) {
123
+ v.hasReportedDrift = !0;
124
+ for (let t of v.listeners) t(e);
125
+ if (v.channel) try {
126
+ v.channel.postMessage({
127
+ type: "drift",
128
+ delta: e
129
+ });
130
+ } catch {}
131
+ }
132
+ }
133
+ function ee(e) {
134
+ return v.listeners.add(e), () => {
135
+ v.listeners.delete(e);
136
+ };
137
+ }
138
+ //#endregion
139
+ //#region src/api/client.ts
140
+ var w = (e) => JSON.stringify(e ?? {}), T = null, E = class extends Error {
141
+ constructor(e) {
142
+ super(`refresh failed terminally (${e})`), this.status = e, this.name = "RefreshDeadError";
143
+ }
144
+ };
145
+ async function te() {
146
+ let e = {
147
+ method: "POST",
148
+ credentials: "include",
149
+ headers: { "Content-Type": "application/json" },
150
+ body: w({})
151
+ }, t = await fetch("/api/actions/auth.refresh", e);
152
+ if (t.status === 429) {
153
+ let n = parseInt(t.headers.get("Retry-After") || "1", 10);
154
+ await new Promise((e) => setTimeout(e, n * 1e3));
155
+ let r = await fetch("/api/actions/auth.refresh", e);
156
+ if (!r.ok) throw new E(r.status);
157
+ return;
158
+ }
159
+ if (!t.ok) throw new E(t.status);
160
+ }
161
+ async function D() {
162
+ return T || (T = te().finally(() => {
163
+ T = null;
164
+ }), T);
165
+ }
166
+ var O = () => {
167
+ if (typeof window > "u") return;
168
+ let { pathname: e } = window.location;
169
+ e.startsWith("/login") || e.startsWith("/signup") || e === "/reset" || e === "/forgot" || (window.location.href = m());
170
+ };
171
+ function k() {
172
+ return O;
173
+ }
174
+ var A = ({ status: e, code: t, message: n }) => {
175
+ console.error(`[API ${e}] ${t}: ${n}`);
176
+ }, j = 3e4;
177
+ async function M(e, t = {}) {
178
+ let n = new Headers(t.headers);
179
+ !n.has("Content-Type") && t.body && n.set("Content-Type", "application/json");
180
+ let r = AbortSignal.timeout(j), i = t.signal ? AbortSignal.any([t.signal, r]) : r, a;
181
+ try {
182
+ a = await fetch(e, {
183
+ ...t,
184
+ headers: n,
185
+ credentials: "include",
186
+ signal: i
187
+ });
188
+ } catch (t) {
189
+ throw t instanceof DOMException && t.name === "TimeoutError" ? new o(0, `Request to ${e} timed out after ${j / 1e3}s. If you have many tabs open to the dev server, the HTTP/1.1 6-connection cap may be queueing requests in the browser. See docs/gotchas.md.`, "REQUEST_TIMEOUT") : t;
190
+ }
191
+ if (b(a.headers), a.status !== 204) {
192
+ if (a.status === 207) return a.json();
193
+ if (!a.ok) {
194
+ let n = "Request failed", r = "UNKNOWN", s, c;
195
+ try {
196
+ c = await a.json();
197
+ let e = c;
198
+ e && e.error && (n = e.error.message, r = e.error.code, e.index != null && (s = e.index));
199
+ } catch {}
200
+ if (a.status === 401 && (r === "TOKEN_REFRESH_NEEDED" || r === "UNAUTHORIZED")) try {
201
+ await D();
202
+ let n = new Headers(t.headers);
203
+ !n.has("Content-Type") && t.body && n.set("Content-Type", "application/json");
204
+ let r = await fetch(e, {
205
+ ...t,
206
+ headers: n,
207
+ credentials: "include",
208
+ signal: i
209
+ });
210
+ if (r.status === 204) return;
211
+ if (!r.ok) {
212
+ O();
213
+ let e = await r.json().catch(() => ({ error: {
214
+ message: "Request failed",
215
+ code: "UNKNOWN"
216
+ } }));
217
+ throw new o(r.status, e.error.message, e.error.code, e.index);
218
+ }
219
+ return r.json();
220
+ } catch (e) {
221
+ throw e instanceof o ? e : (O(), new o(401, n, r, s));
222
+ }
223
+ throw a.status === 401 && O(), A({
224
+ status: a.status,
225
+ code: r,
226
+ message: n
227
+ }), new o(a.status, n, r, s, c);
228
+ }
229
+ return a.json();
230
+ }
231
+ }
232
+ async function ne(e, t = {}) {
233
+ let n = new Headers(t.headers);
234
+ !n.has("Content-Type") && t.body && n.set("Content-Type", "application/json"), n.has("Accept") || n.set("Accept", "*/*");
235
+ let r = AbortSignal.timeout(j), i = t.signal ? AbortSignal.any([t.signal, r]) : r, a;
236
+ try {
237
+ a = await fetch(e, {
238
+ ...t,
239
+ headers: n,
240
+ credentials: "include",
241
+ signal: i
242
+ });
243
+ } catch (t) {
244
+ throw t instanceof DOMException && t.name === "TimeoutError" ? new o(0, `Request to ${e} timed out after ${j / 1e3}s.`, "REQUEST_TIMEOUT") : t;
245
+ }
246
+ if (b(a.headers), !a.ok) {
247
+ let n = "Request failed", r = "UNKNOWN", s, c;
248
+ try {
249
+ c = await a.json();
250
+ let e = c;
251
+ e && e.error && (n = e.error.message, r = e.error.code, e.index != null && (s = e.index));
252
+ } catch {}
253
+ if (a.status === 401 && (r === "TOKEN_REFRESH_NEEDED" || r === "UNAUTHORIZED")) try {
254
+ await D();
255
+ let n = new Headers(t.headers);
256
+ !n.has("Content-Type") && t.body && n.set("Content-Type", "application/json"), n.has("Accept") || n.set("Accept", "*/*");
257
+ let r = await fetch(e, {
258
+ ...t,
259
+ headers: n,
260
+ credentials: "include",
261
+ signal: i
262
+ });
263
+ if (!r.ok) {
264
+ O();
265
+ let e = await r.json().catch(() => ({ error: {
266
+ message: "Request failed",
267
+ code: "UNKNOWN"
268
+ } }));
269
+ throw new o(r.status, e.error.message, e.error.code, e.index);
270
+ }
271
+ return {
272
+ blob: await r.blob(),
273
+ filename: N(r.headers),
274
+ headers: r.headers
275
+ };
276
+ } catch (e) {
277
+ throw e instanceof o ? e : (O(), new o(401, n, r, s));
278
+ }
279
+ throw a.status === 401 && O(), A({
280
+ status: a.status,
281
+ code: r,
282
+ message: n
283
+ }), new o(a.status, n, r, s, c);
284
+ }
285
+ return {
286
+ blob: await a.blob(),
287
+ filename: N(a.headers),
288
+ headers: a.headers
289
+ };
290
+ }
291
+ function N(e) {
292
+ let t = e.get("Content-Disposition");
293
+ if (!t) return "";
294
+ let n = t.match(/filename\*\s*=\s*([^']*)'([^']*)'([^;]+)/i);
295
+ if (n) try {
296
+ return decodeURIComponent(n[3].trim());
297
+ } catch {}
298
+ let r = t.match(/filename\s*=\s*("([^"]+)"|([^;]+))/i);
299
+ return r ? (r[2] ?? r[3] ?? "").trim() : "";
300
+ }
301
+ async function P(e, t = {}) {
302
+ return (await M(`/api/actions/${encodeURIComponent(e)}`, {
303
+ method: "POST",
304
+ body: w(t)
305
+ })).result;
306
+ }
307
+ //#endregion
308
+ //#region src/components/file-widgets/upload.ts
309
+ var F = class extends Error {
310
+ code;
311
+ status;
312
+ constructor(e, t, n) {
313
+ super(n), this.code = t, this.status = e;
314
+ }
315
+ };
316
+ function I(e) {
317
+ let { file: t, entityCode: n, fieldCode: r, slotCode: i, onProgress: a, signal: o } = e;
318
+ return new Promise((e, s) => {
319
+ let c = new XMLHttpRequest();
320
+ if (c.open("POST", L(n, r, i)), c.withCredentials = !0, c.upload.onprogress = (e) => {
321
+ if (!a) return;
322
+ let n = e.lengthComputable ? e.total : t.size, r = n > 0 ? Math.min(100, Math.round(e.loaded / n * 100)) : 0;
323
+ a({
324
+ loaded: e.loaded,
325
+ total: n,
326
+ pct: r
327
+ });
328
+ }, c.onload = () => {
329
+ let t = c.responseText || "", n = null;
330
+ try {
331
+ n = t ? JSON.parse(t) : null;
332
+ } catch {}
333
+ if (c.status >= 200 && c.status < 300) {
334
+ let t = R(n);
335
+ if (!t || !t.id) {
336
+ s(new F(c.status, "BAD_RESPONSE", "Upload returned no file id"));
337
+ return;
338
+ }
339
+ e(t);
340
+ return;
341
+ }
342
+ let r = n, i = r?.error?.code ?? "UPLOAD_FAILED", a = r?.error?.message ?? `Upload failed (${c.status})`;
343
+ s(new F(c.status, i, a));
344
+ }, c.onerror = () => {
345
+ s(new F(0, "NETWORK_ERROR", "Network error during upload"));
346
+ }, c.onabort = () => {
347
+ s(new F(0, "ABORTED", "Upload aborted"));
348
+ }, o) {
349
+ if (o.aborted) {
350
+ c.abort(), s(new F(0, "ABORTED", "Upload aborted"));
351
+ return;
352
+ }
353
+ o.addEventListener("abort", () => c.abort(), { once: !0 });
354
+ }
355
+ let l = new FormData();
356
+ l.append("file", t, t.name), c.send(l);
357
+ });
358
+ }
359
+ function L(e, t, n) {
360
+ let r = new URLSearchParams();
361
+ e && t && (r.set("entity_code", e), r.set("field_code", t), n && r.set("slot_code", n));
362
+ let i = r.toString();
363
+ return i ? `/api/files/upload?${i}` : "/api/files/upload";
364
+ }
365
+ function R(e) {
366
+ return B(e) ? B(e.result) ? R(e.result) : B(e.file) ? z(e.file) : typeof e.id == "string" ? e : null : null;
367
+ }
368
+ function z(e) {
369
+ let t = V(e.file_id);
370
+ return t ? {
371
+ id: t,
372
+ filename: V(e.filename_original) ?? V(e.filename_normalized) ?? t,
373
+ content_type: V(e.content_type) ?? "application/octet-stream",
374
+ size_bytes: H(e.size_bytes) ?? 0,
375
+ sha256: V(e.sha256) ?? "",
376
+ dedup: U(e.dedup)
377
+ } : null;
378
+ }
379
+ function B(e) {
380
+ return typeof e == "object" && !!e;
381
+ }
382
+ function V(e) {
383
+ return typeof e == "string" ? e : void 0;
384
+ }
385
+ function H(e) {
386
+ return typeof e == "number" ? e : void 0;
387
+ }
388
+ function U(e) {
389
+ return typeof e == "boolean" ? e : void 0;
390
+ }
391
+ async function W(e) {
392
+ await P("files.discard", { file_id: e });
393
+ }
394
+ function G(e, t, n) {
395
+ if (n && e.size > n) return {
396
+ code: "FILE_TOO_LARGE",
397
+ message: `File is ${q(e.size)}, max ${q(n)}`
398
+ };
399
+ if (t && t.length > 0) {
400
+ let n = e.type || "application/octet-stream";
401
+ if (!t.some((e) => K(e, n))) return {
402
+ code: "MIME_NOT_ACCEPTED",
403
+ message: `File type ${n} is not accepted`
404
+ };
405
+ }
406
+ return null;
407
+ }
408
+ function K(e, t) {
409
+ if (e === "*/*" || e === "*") return !0;
410
+ if (e.endsWith("/*")) {
411
+ let n = e.slice(0, e.length - 1);
412
+ return t.startsWith(n);
413
+ }
414
+ return e === t;
415
+ }
416
+ function q(e) {
417
+ if (e < 1024) return `${e} B`;
418
+ let t = [
419
+ "KB",
420
+ "MB",
421
+ "GB"
422
+ ], n = e / 1024, r = 0;
423
+ for (; n >= 1024 && r < t.length - 1;) n /= 1024, r++;
424
+ return `${n.toFixed(n >= 10 ? 0 : 1)} ${t[r]}`;
425
+ }
426
+ //#endregion
427
+ //#region src/components/file-widgets/helpers.ts
428
+ function J() {
429
+ return typeof navigator > "u" ? ["en"] : (navigator.languages?.length ? navigator.languages : [navigator.language]).filter((e) => typeof e == "string" && e.length > 0);
430
+ }
431
+ function Y(e, t) {
432
+ for (let n of t) {
433
+ if (e[n]) return e[n];
434
+ let t = n.split("-")[0];
435
+ if (t && e[t]) return e[t];
436
+ }
437
+ for (let t of Object.values(e)) if (typeof t == "string" && t.length > 0) return t;
438
+ }
439
+ function re(e, t, n) {
440
+ if (t) return t;
441
+ let r = e?.metadata?.alt_text;
442
+ if (typeof r == "string" && r.length > 0) return r;
443
+ if (r && typeof r == "object" && !Array.isArray(r)) {
444
+ let e = Y(Object.fromEntries(Object.entries(r).filter((e) => e[0].length > 0 && typeof e[1] == "string")), J());
445
+ if (e) return e;
446
+ }
447
+ return n;
448
+ }
449
+ var X = new Set([
450
+ "image/png",
451
+ "image/jpeg",
452
+ "image/webp",
453
+ "image/gif",
454
+ "image/avif",
455
+ "application/pdf"
456
+ ]);
457
+ function ie(e) {
458
+ let t = e.content_type?.toLowerCase().split(";")[0]?.trim() ?? "";
459
+ return X.has(t);
460
+ }
461
+ function ae(e) {
462
+ return e.url ?? e.presigned_url;
463
+ }
464
+ function oe(e) {
465
+ return e.url ? ce(e.url, "attachment") : e.presigned_url;
466
+ }
467
+ function se(e, t) {
468
+ if (!e) return;
469
+ let n = e.derivations ?? {};
470
+ return t && n[t] ? n[t] : n.thumb_200 ?? n.thumb_300 ?? e.url ?? e.presigned_url;
471
+ }
472
+ function ce(e, t) {
473
+ try {
474
+ let n = new URL(e, typeof window < "u" ? window.location.origin : "http://localhost");
475
+ return n.searchParams.set("disposition", t), /^https?:\/\//i.test(e) ? n.toString() : `${n.pathname}${n.search}${n.hash}`;
476
+ } catch {
477
+ return `${e}${e.includes("?") ? "&" : "?"}disposition=${t}`;
478
+ }
479
+ }
480
+ function le(e) {
481
+ let t = e?.metadata?.focal_point;
482
+ if (!t || typeof t != "object" || Array.isArray(t)) return null;
483
+ let n = t, r = typeof n.x == "number" ? n.x : NaN, i = typeof n.y == "number" ? n.y : NaN;
484
+ return !Number.isFinite(r) || !Number.isFinite(i) || r < 0 || r > 1 || i < 0 || i > 1 ? null : {
485
+ x: r,
486
+ y: i
487
+ };
488
+ }
489
+ function ue(e) {
490
+ if (e) return `${e.x * 100}% ${e.y * 100}%`;
491
+ }
492
+ function de(e, t) {
493
+ return {
494
+ ...e,
495
+ metadata: {
496
+ ...e.metadata ?? {},
497
+ focal_point: t
498
+ }
499
+ };
500
+ }
501
+ //#endregion
502
+ //#region src/components/file-widgets/draft-scope.tsx
503
+ var Z = e({
504
+ registerDraft() {},
505
+ unregisterDraft() {},
506
+ hasDraft() {
507
+ return !1;
508
+ },
509
+ flushAllDrafts: async () => {},
510
+ markCommitted() {}
511
+ });
512
+ function fe({ children: e }) {
513
+ let t = i(/* @__PURE__ */ new Map()), n = r(() => ({
514
+ registerDraft(e) {
515
+ t.current.set(e.fileId, e);
516
+ },
517
+ unregisterDraft(e) {
518
+ t.current.delete(e);
519
+ },
520
+ hasDraft(e) {
521
+ return t.current.has(e);
522
+ },
523
+ markCommitted(e) {
524
+ t.current.delete(e);
525
+ },
526
+ async flushAllDrafts() {
527
+ let e = Array.from(t.current.values());
528
+ t.current.clear(), await Promise.allSettled(e.map((e) => Promise.resolve(e.discard())));
529
+ }
530
+ }), []);
531
+ return /* @__PURE__ */ a(Z.Provider, {
532
+ value: n,
533
+ children: e
534
+ });
535
+ }
536
+ function Q() {
537
+ return n(Z);
538
+ }
539
+ function pe() {
540
+ let e = Q();
541
+ return {
542
+ register: t((t, n) => {
543
+ e.registerDraft({
544
+ fileId: t,
545
+ discard: n
546
+ });
547
+ }, [e]),
548
+ unregister: t((t) => {
549
+ e.unregisterDraft(t);
550
+ }, [e]),
551
+ markCommitted: t((t) => {
552
+ e.markCommitted(t);
553
+ }, [e]),
554
+ isDraft: t((t) => e.hasDraft(t), [e])
555
+ };
556
+ }
557
+ //#endregion
558
+ //#region src/components/file-widgets/value.ts
559
+ function $(e) {
560
+ return typeof e == "object" && !!e && typeof e.id == "string";
561
+ }
562
+ function me(e) {
563
+ return e ? Array.isArray(e) ? e.find($) ?? null : $(e) ? e : null : null;
564
+ }
565
+ function he(e) {
566
+ return e ? Array.isArray(e) ? e.filter($) : $(e) ? [e] : [] : [];
567
+ }
568
+ //#endregion
569
+ export { D as C, p as D, ee as E, f as O, P as S, x as T, I as _, Q as a, M as b, ue as c, le as d, re as f, q as g, W as h, pe as i, o as k, se as l, F as m, me as n, ie as o, de as p, fe as r, oe as s, he as t, ae as u, G as v, k as w, ne as x, E as y };
570
+
571
+ //# sourceMappingURL=value-FIp50R1-.js.map