@nldoc/validation 1.0.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.
package/dist/index.mjs ADDED
@@ -0,0 +1,922 @@
1
+ import { ValidationFinding as pe } from "@nldoc/types";
2
+ import ce, { useMemo as me, useState as H, useEffect as w, createContext as ge, useContext as Ee, useRef as de, useReducer as he, useCallback as Se, useLayoutEffect as Ie } from "react";
3
+ import { z as be } from "zod";
4
+ import { ContentType as ee, useConversion as ke } from "@nldoc/api";
5
+ import { useDebounce as Re } from "use-debounce";
6
+ import { TransactionMeta as ve } from "@nldoc/tiptap-extensions";
7
+ function xe(n, t = {}) {
8
+ const { debounceDelay: r = 500, debounceMaxWait: o = 5e3, includeAssets: s = !1 } = t, [i] = Re(n, r, { maxWait: o }), l = me(() => {
9
+ if (!i) return null;
10
+ const p = s ? i : {
11
+ ...i,
12
+ attrs: { ...i.attrs, assets: {} }
13
+ };
14
+ return new Blob([JSON.stringify(p)], { type: ee.Tiptap });
15
+ }, [i, s]);
16
+ return ke(l, ee.Validation);
17
+ }
18
+ const Te = new Error("An unknown error occurred"), _e = be.array(pe);
19
+ function Ne(n, t = {}) {
20
+ const r = xe(n, t), [o, s] = H(!1), [i, l] = H([]), [p, b] = H(null);
21
+ return w(() => {
22
+ if (r.status === "error") {
23
+ s(!1), b(r.error);
24
+ return;
25
+ }
26
+ if (r.status === "idle") {
27
+ s(!1);
28
+ return;
29
+ }
30
+ if (r.status !== "done") {
31
+ s(!0);
32
+ return;
33
+ }
34
+ try {
35
+ const E = _e.parse(JSON.parse(r.content));
36
+ l(E), b(null);
37
+ } catch (E) {
38
+ b(E instanceof Error ? E : Te);
39
+ } finally {
40
+ s(!1);
41
+ }
42
+ }, [r]), { isValidating: o, findings: i, error: p };
43
+ }
44
+ var V = { exports: {} }, G = {};
45
+ var ne;
46
+ function ye() {
47
+ if (ne) return G;
48
+ ne = 1;
49
+ var n = /* @__PURE__ */ Symbol.for("react.transitional.element"), t = /* @__PURE__ */ Symbol.for("react.fragment");
50
+ function r(o, s, i) {
51
+ var l = null;
52
+ if (i !== void 0 && (l = "" + i), s.key !== void 0 && (l = "" + s.key), "key" in s) {
53
+ i = {};
54
+ for (var p in s)
55
+ p !== "key" && (i[p] = s[p]);
56
+ } else i = s;
57
+ return s = i.ref, {
58
+ $$typeof: n,
59
+ type: o,
60
+ key: l,
61
+ ref: s !== void 0 ? s : null,
62
+ props: i
63
+ };
64
+ }
65
+ return G.Fragment = t, G.jsx = r, G.jsxs = r, G;
66
+ }
67
+ var U = {};
68
+ var te;
69
+ function Ae() {
70
+ return te || (te = 1, process.env.NODE_ENV !== "production" && (function() {
71
+ function n(e) {
72
+ if (e == null) return null;
73
+ if (typeof e == "function")
74
+ return e.$$typeof === q ? null : e.displayName || e.name || null;
75
+ if (typeof e == "string") return e;
76
+ switch (e) {
77
+ case y:
78
+ return "Fragment";
79
+ case h:
80
+ return "Profiler";
81
+ case c:
82
+ return "StrictMode";
83
+ case _:
84
+ return "Suspense";
85
+ case z:
86
+ return "SuspenseList";
87
+ case W:
88
+ return "Activity";
89
+ }
90
+ if (typeof e == "object")
91
+ switch (typeof e.tag == "number" && console.error(
92
+ "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
93
+ ), e.$$typeof) {
94
+ case m:
95
+ return "Portal";
96
+ case u:
97
+ return e.displayName || "Context";
98
+ case S:
99
+ return (e._context.displayName || "Context") + ".Consumer";
100
+ case L:
101
+ var f = e.render;
102
+ return e = e.displayName, e || (e = f.displayName || f.name || "", e = e !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e;
103
+ case M:
104
+ return f = e.displayName || null, f !== null ? f : n(e.type) || "Memo";
105
+ case P:
106
+ f = e._payload, e = e._init;
107
+ try {
108
+ return n(e(f));
109
+ } catch {
110
+ }
111
+ }
112
+ return null;
113
+ }
114
+ function t(e) {
115
+ return "" + e;
116
+ }
117
+ function r(e) {
118
+ try {
119
+ t(e);
120
+ var f = !1;
121
+ } catch {
122
+ f = !0;
123
+ }
124
+ if (f) {
125
+ f = console;
126
+ var I = f.error, v = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
127
+ return I.call(
128
+ f,
129
+ "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
130
+ v
131
+ ), t(e);
132
+ }
133
+ }
134
+ function o(e) {
135
+ if (e === y) return "<>";
136
+ if (typeof e == "object" && e !== null && e.$$typeof === P)
137
+ return "<...>";
138
+ try {
139
+ var f = n(e);
140
+ return f ? "<" + f + ">" : "<...>";
141
+ } catch {
142
+ return "<...>";
143
+ }
144
+ }
145
+ function s() {
146
+ var e = D.A;
147
+ return e === null ? null : e.getOwner();
148
+ }
149
+ function i() {
150
+ return Error("react-stack-top-frame");
151
+ }
152
+ function l(e) {
153
+ if (B.call(e, "key")) {
154
+ var f = Object.getOwnPropertyDescriptor(e, "key").get;
155
+ if (f && f.isReactWarning) return !1;
156
+ }
157
+ return e.key !== void 0;
158
+ }
159
+ function p(e, f) {
160
+ function I() {
161
+ j || (j = !0, console.error(
162
+ "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
163
+ f
164
+ ));
165
+ }
166
+ I.isReactWarning = !0, Object.defineProperty(e, "key", {
167
+ get: I,
168
+ configurable: !0
169
+ });
170
+ }
171
+ function b() {
172
+ var e = n(this.type);
173
+ return $[e] || ($[e] = !0, console.error(
174
+ "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
175
+ )), e = this.props.ref, e !== void 0 ? e : null;
176
+ }
177
+ function E(e, f, I, v, F, J) {
178
+ var x = I.ref;
179
+ return e = {
180
+ $$typeof: R,
181
+ type: e,
182
+ key: f,
183
+ props: I,
184
+ _owner: v
185
+ }, (x !== void 0 ? x : null) !== null ? Object.defineProperty(e, "ref", {
186
+ enumerable: !1,
187
+ get: b
188
+ }) : Object.defineProperty(e, "ref", { enumerable: !1, value: null }), e._store = {}, Object.defineProperty(e._store, "validated", {
189
+ configurable: !1,
190
+ enumerable: !1,
191
+ writable: !0,
192
+ value: 0
193
+ }), Object.defineProperty(e, "_debugInfo", {
194
+ configurable: !1,
195
+ enumerable: !1,
196
+ writable: !0,
197
+ value: null
198
+ }), Object.defineProperty(e, "_debugStack", {
199
+ configurable: !1,
200
+ enumerable: !1,
201
+ writable: !0,
202
+ value: F
203
+ }), Object.defineProperty(e, "_debugTask", {
204
+ configurable: !1,
205
+ enumerable: !1,
206
+ writable: !0,
207
+ value: J
208
+ }), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
209
+ }
210
+ function a(e, f, I, v, F, J) {
211
+ var x = f.children;
212
+ if (x !== void 0)
213
+ if (v)
214
+ if (Y(x)) {
215
+ for (v = 0; v < x.length; v++)
216
+ g(x[v]);
217
+ Object.freeze && Object.freeze(x);
218
+ } else
219
+ console.error(
220
+ "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
221
+ );
222
+ else g(x);
223
+ if (B.call(f, "key")) {
224
+ x = n(e);
225
+ var C = Object.keys(f).filter(function(fe) {
226
+ return fe !== "key";
227
+ });
228
+ v = 0 < C.length ? "{key: someKey, " + C.join(": ..., ") + ": ...}" : "{key: someKey}", Q[x + v] || (C = 0 < C.length ? "{" + C.join(": ..., ") + ": ...}" : "{}", console.error(
229
+ `A props object containing a "key" prop is being spread into JSX:
230
+ let props = %s;
231
+ <%s {...props} />
232
+ React keys must be passed directly to JSX without using spread:
233
+ let props = %s;
234
+ <%s key={someKey} {...props} />`,
235
+ v,
236
+ x,
237
+ C,
238
+ x
239
+ ), Q[x + v] = !0);
240
+ }
241
+ if (x = null, I !== void 0 && (r(I), x = "" + I), l(f) && (r(f.key), x = "" + f.key), "key" in f) {
242
+ I = {};
243
+ for (var K in f)
244
+ K !== "key" && (I[K] = f[K]);
245
+ } else I = f;
246
+ return x && p(
247
+ I,
248
+ typeof e == "function" ? e.displayName || e.name || "Unknown" : e
249
+ ), E(
250
+ e,
251
+ x,
252
+ I,
253
+ s(),
254
+ F,
255
+ J
256
+ );
257
+ }
258
+ function g(e) {
259
+ T(e) ? e._store && (e._store.validated = 1) : typeof e == "object" && e !== null && e.$$typeof === P && (e._payload.status === "fulfilled" ? T(e._payload.value) && e._payload.value._store && (e._payload.value._store.validated = 1) : e._store && (e._store.validated = 1));
260
+ }
261
+ function T(e) {
262
+ return typeof e == "object" && e !== null && e.$$typeof === R;
263
+ }
264
+ var k = ce, R = /* @__PURE__ */ Symbol.for("react.transitional.element"), m = /* @__PURE__ */ Symbol.for("react.portal"), y = /* @__PURE__ */ Symbol.for("react.fragment"), c = /* @__PURE__ */ Symbol.for("react.strict_mode"), h = /* @__PURE__ */ Symbol.for("react.profiler"), S = /* @__PURE__ */ Symbol.for("react.consumer"), u = /* @__PURE__ */ Symbol.for("react.context"), L = /* @__PURE__ */ Symbol.for("react.forward_ref"), _ = /* @__PURE__ */ Symbol.for("react.suspense"), z = /* @__PURE__ */ Symbol.for("react.suspense_list"), M = /* @__PURE__ */ Symbol.for("react.memo"), P = /* @__PURE__ */ Symbol.for("react.lazy"), W = /* @__PURE__ */ Symbol.for("react.activity"), q = /* @__PURE__ */ Symbol.for("react.client.reference"), D = k.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, B = Object.prototype.hasOwnProperty, Y = Array.isArray, A = console.createTask ? console.createTask : function() {
265
+ return null;
266
+ };
267
+ k = {
268
+ react_stack_bottom_frame: function(e) {
269
+ return e();
270
+ }
271
+ };
272
+ var j, $ = {}, X = k.react_stack_bottom_frame.bind(
273
+ k,
274
+ i
275
+ )(), Z = A(o(i)), Q = {};
276
+ U.Fragment = y, U.jsx = function(e, f, I) {
277
+ var v = 1e4 > D.recentlyCreatedOwnerStacks++;
278
+ return a(
279
+ e,
280
+ f,
281
+ I,
282
+ !1,
283
+ v ? Error("react-stack-top-frame") : X,
284
+ v ? A(o(e)) : Z
285
+ );
286
+ }, U.jsxs = function(e, f, I) {
287
+ var v = 1e4 > D.recentlyCreatedOwnerStacks++;
288
+ return a(
289
+ e,
290
+ f,
291
+ I,
292
+ !0,
293
+ v ? Error("react-stack-top-frame") : X,
294
+ v ? A(o(e)) : Z
295
+ );
296
+ };
297
+ })()), U;
298
+ }
299
+ var re;
300
+ function je() {
301
+ return re || (re = 1, process.env.NODE_ENV === "production" ? V.exports = ye() : V.exports = Ae()), V.exports;
302
+ }
303
+ var d = je();
304
+ const ue = ge({
305
+ findings: [],
306
+ isValidating: !1,
307
+ error: null
308
+ });
309
+ function Ze({
310
+ children: n,
311
+ editor: t,
312
+ editorJSON: r,
313
+ options: o,
314
+ autoApplyFindings: s = !0,
315
+ onApplyFindings: i
316
+ }) {
317
+ const [l, p] = H(
318
+ () => r !== void 0 ? null : t?.getJSON() ?? null
319
+ );
320
+ w(() => {
321
+ if (!t || r !== void 0) return;
322
+ const a = ({
323
+ editor: g,
324
+ transaction: T
325
+ }) => {
326
+ T.getMeta(ve.blockValidation) !== !0 && p(g.getJSON());
327
+ };
328
+ return t.on("update", a), () => {
329
+ t.off("update", a);
330
+ };
331
+ }, [t, r]);
332
+ const E = Ne(r ?? l, o);
333
+ return w(() => {
334
+ if (!(!t || !s))
335
+ if (i)
336
+ i(t, E.findings);
337
+ else {
338
+ const a = t.commands;
339
+ a.setValidationFindings && a.setValidationFindings(E.findings);
340
+ }
341
+ }, [t, E.findings, s, i]), /* @__PURE__ */ d.jsx(ue.Provider, { value: E, children: n });
342
+ }
343
+ function Qe() {
344
+ return Ee(ue);
345
+ }
346
+ const Le = ({
347
+ findings: n,
348
+ isBundle: t = !1,
349
+ variant: r = "default",
350
+ stackAmount: o,
351
+ stackIsExpanded: s,
352
+ stackOnToggle: i,
353
+ onResolve: l,
354
+ onRetrigger: p,
355
+ isExpanded: b,
356
+ onToggle: E,
357
+ labels: a = {},
358
+ renderIcon: g,
359
+ renderMessage: T,
360
+ renderResolution: k,
361
+ className: R = "",
362
+ styles: m = {}
363
+ }) => {
364
+ const y = de(null), [c, h] = ce.useState(!1), S = r === "stack";
365
+ if (S && (o === void 0 || s === void 0 || !i))
366
+ return console.error(
367
+ 'ValidationResult: stackAmount, stackIsExpanded, and stackOnToggle are required when variant="stack"'
368
+ ), null;
369
+ const u = S ? s : b ?? c, L = S ? i : E ?? (() => h(!c)), _ = n[0], M = g ?? ((A) => {
370
+ const j = {
371
+ error: "⚠️",
372
+ warning: "⚠️",
373
+ suggestion: "ℹ️",
374
+ close: "✕",
375
+ chevron: "▼"
376
+ };
377
+ return /* @__PURE__ */ d.jsx("span", { children: j[A] });
378
+ }), W = T ?? ((A, j, $) => $ ? `${j} ${A.rule} findings` : j > 1 ? `${j} ${A.rule} findings` : A.rule), D = k ?? ((A, j) => /* @__PURE__ */ d.jsx(
379
+ "button",
380
+ {
381
+ onClick: () => {
382
+ l && l(A), j();
383
+ },
384
+ children: "Resolve"
385
+ }
386
+ )), B = () => {
387
+ p && p();
388
+ }, Y = /* @__PURE__ */ d.jsxs(
389
+ "div",
390
+ {
391
+ className: `${m.outerWrapper ?? ""} ${R}`,
392
+ ref: S ? null : y,
393
+ children: [
394
+ /* @__PURE__ */ d.jsx(
395
+ "button",
396
+ {
397
+ className: `${m.toggleButton ?? ""} ${u ? m.toggleButtonSelected ?? "" : ""}`,
398
+ onClick: L,
399
+ "aria-controls": `comment-${t ? "" : "inner-"}${_.resourceId}`,
400
+ "aria-expanded": u,
401
+ "aria-label": a.toggleFinding ?? "Toggle finding details",
402
+ "data-testid": "toggle-button",
403
+ children: /* @__PURE__ */ d.jsx("div", { className: m.dropShadow ?? "", children: S ? /* @__PURE__ */ d.jsx("div", { className: m.amount ?? "", children: /* @__PURE__ */ d.jsx("strong", { children: o }) }) : M(u ? "close" : _.severity) })
404
+ }
405
+ ),
406
+ /* @__PURE__ */ d.jsxs(
407
+ "div",
408
+ {
409
+ className: `${m.result ?? ""} ${m.resultSeverity ? `${m.resultSeverity}-${_.severity}` : ""} ${u ? m.resultSelected ?? "" : ""}`,
410
+ id: `comment-${t ? "" : "inner-"}${_.resourceId}`,
411
+ tabIndex: -1,
412
+ "aria-live": "polite",
413
+ children: [
414
+ /* @__PURE__ */ d.jsxs("div", { className: m.messageWrapper ?? "", children: [
415
+ /* @__PURE__ */ d.jsxs("div", { className: m.label ?? "", children: [
416
+ M(_.severity),
417
+ /* @__PURE__ */ d.jsx("strong", { children: a.severity?.[_.severity] ?? _.severity })
418
+ ] }),
419
+ /* @__PURE__ */ d.jsx("div", { className: m.message ?? "", children: W(
420
+ _,
421
+ S ? o ?? 0 : n.length,
422
+ t
423
+ ) })
424
+ ] }),
425
+ S ? /* @__PURE__ */ d.jsx("div", { className: m.openValidations ?? "", children: /* @__PURE__ */ d.jsx("button", { onClick: i, children: a.toggleStackOpen ?? "Open validations" }) }) : /* @__PURE__ */ d.jsx("div", { className: m.resolution ?? "", children: D(
426
+ n.map((A) => A.resourceId),
427
+ B
428
+ ) })
429
+ ]
430
+ }
431
+ )
432
+ ]
433
+ }
434
+ );
435
+ return S ? /* @__PURE__ */ d.jsxs("div", { className: m.stack ?? "", children: [
436
+ Y,
437
+ o === 2 ? /* @__PURE__ */ d.jsx("div", { className: m.stackDecorationTwoItems ?? "" }) : /* @__PURE__ */ d.jsx("div", { className: m.stackDecorationManyItems ?? "", children: /* @__PURE__ */ d.jsx("div", { className: m.stackDecorationManyItems ?? "" }) })
438
+ ] }) : Y;
439
+ }, Oe = ["no-underline", "style-bold-in-header", "style-italic-in-header"];
440
+ function Ce(n, t) {
441
+ const r = /* @__PURE__ */ new Map();
442
+ for (const s of n) {
443
+ if (!Oe.includes(s.rule) || s.hidden) continue;
444
+ const i = t.get(s.resourceId);
445
+ if (!i) continue;
446
+ const l = r.get(i);
447
+ l ? l.push(s) : r.set(i, [s]);
448
+ }
449
+ const o = [];
450
+ for (const [s, i] of r) {
451
+ if (i.length < 2) continue;
452
+ const l = [...i].sort((p, b) => p.desiredYLocation - b.desiredYLocation);
453
+ o.push({
454
+ id: crypto.randomUUID(),
455
+ type: "bundle",
456
+ findings: l,
457
+ blockId: s,
458
+ rule: l[0].rule,
459
+ // All findings in bundle have same rule
460
+ desiredYLocation: l[0].desiredYLocation,
461
+ yLocation: l[0].desiredYLocation
462
+ });
463
+ }
464
+ return o;
465
+ }
466
+ function we(n) {
467
+ const t = /* @__PURE__ */ new Set();
468
+ for (const r of n)
469
+ for (const o of r.findings)
470
+ t.add(o.resourceId);
471
+ return t;
472
+ }
473
+ function Me(n, t = {}) {
474
+ const { editorSelector: r = "#tiptap" } = t, o = document.getElementById(n.resourceId);
475
+ if (!o)
476
+ return null;
477
+ const s = document.querySelector(r);
478
+ if (!s)
479
+ throw new Error(`Editor not found: ${r} element does not exist`);
480
+ const i = s.getBoundingClientRect().top;
481
+ return o.getBoundingClientRect().top - i;
482
+ }
483
+ function De(n, t) {
484
+ const o = Me(n, t) ?? 0;
485
+ return {
486
+ ...n,
487
+ desiredYLocation: o,
488
+ yLocation: o,
489
+ hidden: !1
490
+ };
491
+ }
492
+ function se(n, t) {
493
+ return n.map((r) => De(r, t)).sort(Ge);
494
+ }
495
+ function Ge(n, t) {
496
+ const r = n.desiredYLocation - t.desiredYLocation;
497
+ return Math.abs(r) > 0.01 ? r : n.resourceId.localeCompare(t.resourceId);
498
+ }
499
+ function le(n) {
500
+ return "type" in n && n.type === "bundle";
501
+ }
502
+ function oe(n) {
503
+ return le(n) ? `bundle:${n.blockId}` : n.resourceId;
504
+ }
505
+ function O(n) {
506
+ return n.desiredYLocation;
507
+ }
508
+ function Ue(n) {
509
+ return n.map((t) => ({
510
+ id: crypto.randomUUID(),
511
+ type: "stack",
512
+ items: [t],
513
+ rule: t.rule,
514
+ isExpandable: !1,
515
+ isExpanded: !1,
516
+ desiredYLocation: O(t),
517
+ yLocation: O(t)
518
+ }));
519
+ }
520
+ function Pe(n, t, r = /* @__PURE__ */ new Set(), o = []) {
521
+ if (n.length === 0) return [];
522
+ const s = [...n].sort((T, k) => T.desiredYLocation - k.desiredYLocation), i = [...o], l = [];
523
+ let p = [], b = null, E = 0, a = 0, g = 0;
524
+ for (const T of s) {
525
+ const k = T.items[0], R = k.rule, m = O(k), y = Be(k, t), c = Math.max(m, g);
526
+ if (p.length === 0) {
527
+ p = [k], b = R, E = c, a = y, g = c + y;
528
+ continue;
529
+ }
530
+ const h = R === b, S = c <= E + a;
531
+ h && S ? (p.push(k), g = E + a) : (l.push(ie(p, r, i)), p = [k], b = R, E = c, a = y, g = c + y);
532
+ }
533
+ return p.length > 0 && l.push(ie(p, r, i)), l;
534
+ }
535
+ function Be(n, t) {
536
+ return le(n) ? t.get(n.id) ?? 0 : t.get(n.resourceId) ?? 0;
537
+ }
538
+ function ie(n, t, r) {
539
+ const o = [...n].sort((l, p) => O(l) - O(p)), s = Ye(o, r), i = s ? s.id : crypto.randomUUID();
540
+ return {
541
+ id: i,
542
+ type: "stack",
543
+ items: o,
544
+ rule: o[0].rule,
545
+ isExpandable: o.length > 1,
546
+ isExpanded: t.has(i),
547
+ desiredYLocation: O(o[0]),
548
+ yLocation: O(o[0])
549
+ };
550
+ }
551
+ function Ye(n, t) {
552
+ if (t.length === 0) return null;
553
+ const r = new Set(n.map(oe));
554
+ let o = null, s = 0, i = -1;
555
+ for (let l = 0; l < t.length; l++) {
556
+ const p = t[l], b = new Set(p.items.map(oe));
557
+ let E = 0;
558
+ for (const g of r)
559
+ b.has(g) && E++;
560
+ const a = E / Math.max(r.size, b.size);
561
+ a > s && (s = a, o = p, i = l);
562
+ }
563
+ return s >= 0.5 && i >= 0 ? (t.splice(i, 1), o) : null;
564
+ }
565
+ function $e(n, t) {
566
+ const r = n.map((o) => ({ ...o }));
567
+ for (let o = 1; o < r.length; o++) {
568
+ const s = r[o - 1], i = r[o], l = t[s.id]?.offsetHeight ?? 0, p = s.yLocation + l;
569
+ i.yLocation = Math.max(i.desiredYLocation, p);
570
+ }
571
+ return r;
572
+ }
573
+ const N = {
574
+ IDLE: "idle",
575
+ MEASURING: "measuring",
576
+ // Render findings invisibly to measure heights
577
+ BUNDLING: "bundling",
578
+ // Group findings into bundles based on proximity
579
+ MEASURING_BUNDLES: "measuring-bundles",
580
+ // Render bundles invisibly to measure heights
581
+ STACKING: "stacking",
582
+ // Create initial vertical stacks
583
+ MERGING: "merging",
584
+ // Merge overlapping stacks
585
+ POSITIONING: "positioning"
586
+ // Final absolute positioning calculation
587
+ }, Fe = {
588
+ phase: N.IDLE,
589
+ bundles: [],
590
+ stacks: [],
591
+ previousStacks: [],
592
+ expandedStackIds: /* @__PURE__ */ new Set(),
593
+ itemHeights: /* @__PURE__ */ new Map(),
594
+ findingBlockMap: /* @__PURE__ */ new Map(),
595
+ findings: []
596
+ }, ae = (n, t) => ({
597
+ ...n,
598
+ phase: N.MEASURING,
599
+ findings: t,
600
+ previousStacks: n.stacks,
601
+ // Cache previous stacks to prevent layout jumping
602
+ stacks: [],
603
+ bundles: []
604
+ });
605
+ function Ve(n, t) {
606
+ switch (t.type) {
607
+ case "FINDINGS_UPDATED":
608
+ case "ANIMATION_FINISHED":
609
+ return n.findings === t.findings ? n : ae(n, t.findings);
610
+ case "RECALCULATE":
611
+ return ae(n, n.findings);
612
+ case "HEIGHTS_MEASURED":
613
+ return { ...n, phase: N.BUNDLING, itemHeights: t.heights };
614
+ case "BLOCK_MAP_BUILT":
615
+ return { ...n, findingBlockMap: t.blockMap };
616
+ case "BUNDLES_CREATED":
617
+ return { ...n, phase: N.MEASURING_BUNDLES, bundles: t.bundles };
618
+ case "BUNDLE_HEIGHTS_MEASURED":
619
+ return {
620
+ ...n,
621
+ phase: N.STACKING,
622
+ itemHeights: new Map([...n.itemHeights, ...t.heights])
623
+ };
624
+ case "STACKS_CREATED":
625
+ return { ...n, phase: N.MERGING, stacks: t.stacks };
626
+ case "STACKS_MERGED":
627
+ return { ...n, phase: N.POSITIONING, stacks: t.stacks };
628
+ case "STACKS_POSITIONED":
629
+ return { ...n, phase: N.IDLE, stacks: t.stacks };
630
+ case "TOGGLE_STACK": {
631
+ const r = new Set(n.expandedStackIds);
632
+ return r.has(t.stackId) ? r.delete(t.stackId) : r.add(t.stackId), {
633
+ ...n,
634
+ expandedStackIds: r,
635
+ phase: N.STACKING,
636
+ previousStacks: n.stacks
637
+ };
638
+ }
639
+ default:
640
+ return n;
641
+ }
642
+ }
643
+ function He(n, t) {
644
+ let r;
645
+ return () => {
646
+ clearTimeout(r), r = setTimeout(n, t);
647
+ };
648
+ }
649
+ const en = ({
650
+ findings: n,
651
+ isAnimating: t = !1,
652
+ positioningConfig: r,
653
+ buildFindingBlockMap: o,
654
+ validationResultProps: s = {},
655
+ resultComponent: i,
656
+ collapseButtonComponent: l,
657
+ resizeDebounceDelay: p = 100,
658
+ className: b = "",
659
+ styles: E = {}
660
+ }) => {
661
+ const [a, g] = he(Ve, Fe), T = i ?? Le, k = l, R = de({
662
+ findings: {},
663
+ bundles: {},
664
+ stacks: {}
665
+ }), m = Se(() => g({ type: "RECALCULATE" }), []);
666
+ w(() => {
667
+ t || g({ type: "ANIMATION_FINISHED", findings: n });
668
+ }, [t, n]), w(() => {
669
+ g({ type: "FINDINGS_UPDATED", findings: n }), g(o ? {
670
+ type: "BLOCK_MAP_BUILT",
671
+ blockMap: o(n)
672
+ } : { type: "BLOCK_MAP_BUILT", blockMap: /* @__PURE__ */ new Map() });
673
+ }, [n, o]), w(() => {
674
+ const c = He(m, p);
675
+ return window.addEventListener("resize", c), () => window.removeEventListener("resize", c);
676
+ }, [m, p]), Ie(() => {
677
+ const c = se(a.findings, r);
678
+ switch (a.phase) {
679
+ case N.MEASURING: {
680
+ const h = /* @__PURE__ */ new Map();
681
+ c.forEach((S) => {
682
+ const u = R.current.findings[S.resourceId];
683
+ u && h.set(S.resourceId, u.offsetHeight);
684
+ }), g({ type: "HEIGHTS_MEASURED", heights: h });
685
+ break;
686
+ }
687
+ case N.BUNDLING: {
688
+ const h = Ce(c, a.findingBlockMap);
689
+ g({ type: "BUNDLES_CREATED", bundles: h });
690
+ break;
691
+ }
692
+ case N.MEASURING_BUNDLES: {
693
+ const h = /* @__PURE__ */ new Map();
694
+ a.bundles.forEach((S) => {
695
+ const u = R.current.bundles[S.id];
696
+ u && h.set(S.id, u.offsetHeight);
697
+ }), g({ type: "BUNDLE_HEIGHTS_MEASURED", heights: h });
698
+ break;
699
+ }
700
+ case N.STACKING: {
701
+ const h = we(a.bundles), S = c.filter((L) => !h.has(L.resourceId)), u = Ue([...a.bundles, ...S]);
702
+ g({ type: "STACKS_CREATED", stacks: u });
703
+ break;
704
+ }
705
+ case N.MERGING: {
706
+ const h = Pe(
707
+ a.stacks,
708
+ a.itemHeights,
709
+ a.expandedStackIds,
710
+ a.previousStacks
711
+ );
712
+ g({ type: "STACKS_MERGED", stacks: h });
713
+ break;
714
+ }
715
+ case N.POSITIONING: {
716
+ const h = $e(a.stacks, R.current.stacks);
717
+ g({ type: "STACKS_POSITIONED", stacks: h });
718
+ break;
719
+ }
720
+ }
721
+ }, [
722
+ a.phase,
723
+ a.findings,
724
+ a.bundles,
725
+ a.stacks,
726
+ a.findingBlockMap,
727
+ a.itemHeights,
728
+ a.expandedStackIds,
729
+ a.previousStacks,
730
+ r
731
+ ]);
732
+ const y = {
733
+ position: "absolute",
734
+ visibility: "hidden",
735
+ pointerEvents: "none"
736
+ };
737
+ return /* @__PURE__ */ d.jsxs(
738
+ "section",
739
+ {
740
+ className: `${E.container ?? ""} ${b}`,
741
+ tabIndex: -1,
742
+ "data-testid": "validation-results-summary",
743
+ children: [
744
+ a.phase === N.MEASURING && se(a.findings, r).map((c) => /* @__PURE__ */ d.jsx(
745
+ "div",
746
+ {
747
+ ref: (h) => {
748
+ R.current.findings[c.resourceId] = h;
749
+ },
750
+ style: y,
751
+ children: /* @__PURE__ */ d.jsx(
752
+ T,
753
+ {
754
+ ...s,
755
+ findings: [c],
756
+ onRetrigger: m
757
+ }
758
+ )
759
+ },
760
+ c.resourceId
761
+ )),
762
+ a.phase === N.MEASURING_BUNDLES && a.bundles.map((c) => /* @__PURE__ */ d.jsx(
763
+ "div",
764
+ {
765
+ className: E.comment ?? "",
766
+ ref: (h) => {
767
+ R.current.bundles[c.id] = h;
768
+ },
769
+ style: y,
770
+ children: /* @__PURE__ */ d.jsx(
771
+ T,
772
+ {
773
+ ...s,
774
+ findings: c.findings,
775
+ onRetrigger: m,
776
+ isBundle: !0
777
+ }
778
+ )
779
+ },
780
+ c.id
781
+ )),
782
+ a.stacks.map((c) => {
783
+ const h = c.items.length > 1, S = c.items.flatMap(
784
+ (u) => "type" in u && u.type === "bundle" ? u.findings : [u]
785
+ );
786
+ return /* @__PURE__ */ d.jsx(
787
+ "div",
788
+ {
789
+ "data-testid": `comment-item-${c.id}`,
790
+ className: E.comment ?? "",
791
+ ref: (u) => {
792
+ R.current.stacks[c.id] = u;
793
+ },
794
+ style: { top: `${c.yLocation}px`, position: "absolute" },
795
+ children: h && !c.isExpanded ? (
796
+ // Collapsed stack: show count and render hidden items for measurement
797
+ /* @__PURE__ */ d.jsxs(d.Fragment, { children: [
798
+ c.items.map((u) => "type" in u && u.type === "bundle" ? /* @__PURE__ */ d.jsx(
799
+ "div",
800
+ {
801
+ ref: (_) => {
802
+ R.current.bundles[u.id] = _;
803
+ },
804
+ style: y,
805
+ children: /* @__PURE__ */ d.jsx(
806
+ T,
807
+ {
808
+ ...s,
809
+ findings: u.findings,
810
+ onRetrigger: m,
811
+ isBundle: !0
812
+ }
813
+ )
814
+ },
815
+ u.id
816
+ ) : /* @__PURE__ */ d.jsx(
817
+ "div",
818
+ {
819
+ ref: (_) => {
820
+ R.current.findings[u.resourceId] = _;
821
+ },
822
+ style: y,
823
+ children: /* @__PURE__ */ d.jsx(
824
+ T,
825
+ {
826
+ ...s,
827
+ findings: [u],
828
+ onRetrigger: m
829
+ }
830
+ )
831
+ },
832
+ u.resourceId
833
+ )),
834
+ /* @__PURE__ */ d.jsx(
835
+ T,
836
+ {
837
+ ...s,
838
+ variant: "stack",
839
+ findings: S,
840
+ stackAmount: c.items.length,
841
+ stackIsExpanded: !1,
842
+ stackOnToggle: () => g({ type: "TOGGLE_STACK", stackId: c.id }),
843
+ onRetrigger: m
844
+ }
845
+ )
846
+ ] })
847
+ ) : (
848
+ // Single item or expanded stack: show individual items
849
+ /* @__PURE__ */ d.jsxs(d.Fragment, { children: [
850
+ c.items.map((u) => "type" in u && u.type === "bundle" ? /* @__PURE__ */ d.jsx(
851
+ "div",
852
+ {
853
+ ref: (_) => {
854
+ R.current.bundles[u.id] = _;
855
+ },
856
+ className: c.isExpanded ? E.findingInExpandedStack : void 0,
857
+ children: /* @__PURE__ */ d.jsx(
858
+ T,
859
+ {
860
+ ...s,
861
+ findings: u.findings,
862
+ onRetrigger: m,
863
+ isBundle: !0
864
+ }
865
+ )
866
+ },
867
+ u.id
868
+ ) : /* @__PURE__ */ d.jsx(
869
+ "div",
870
+ {
871
+ ref: (_) => {
872
+ R.current.findings[u.resourceId] = _;
873
+ },
874
+ className: c.isExpanded ? E.findingInExpandedStack : void 0,
875
+ children: /* @__PURE__ */ d.jsx(
876
+ T,
877
+ {
878
+ ...s,
879
+ findings: [u],
880
+ onRetrigger: m
881
+ }
882
+ )
883
+ },
884
+ u.resourceId
885
+ )),
886
+ h && c.isExpanded && k && /* @__PURE__ */ d.jsx(
887
+ k,
888
+ {
889
+ onClick: () => g({ type: "TOGGLE_STACK", stackId: c.id })
890
+ }
891
+ ),
892
+ h && c.isExpanded && !k && /* @__PURE__ */ d.jsx("div", { children: /* @__PURE__ */ d.jsx("button", { onClick: () => g({ type: "TOGGLE_STACK", stackId: c.id }), children: s.labels?.toggleStackClosed ?? "Collapse" }) })
893
+ ] })
894
+ )
895
+ },
896
+ c.id
897
+ );
898
+ })
899
+ ]
900
+ }
901
+ );
902
+ };
903
+ export {
904
+ Oe as BUNDLEABLE_RULES,
905
+ ue as ValidationContext,
906
+ Ze as ValidationProvider,
907
+ Le as ValidationResult,
908
+ en as ValidationResultSummary,
909
+ Ge as byIncreasingDesiredYLocation,
910
+ Me as calculateDesiredYLocation,
911
+ Ce as computeBundles,
912
+ Ue as createInitialStacksFromItems,
913
+ we as getBundledFindingIds,
914
+ le as isBundle,
915
+ De as makePositionedFinding,
916
+ se as makePositionedFindings,
917
+ Pe as mergeOverlappingStacksWithBundles,
918
+ $e as positionStacksWithBundles,
919
+ xe as useTiptapValidation,
920
+ Ne as useValidation,
921
+ Qe as useValidationContext
922
+ };