@nivaro/react 0.3.36 → 0.3.38

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 (102) hide show
  1. package/dist/components/slots/CommentsSlot.js +44 -36
  2. package/dist/full.css +1 -1
  3. package/dist/hooks/useSessionRecorder.js +1 -1
  4. package/dist/index.d.ts +9 -1
  5. package/dist/shared/components/AgentBadge.js +26 -0
  6. package/dist/shared/components/AgentQuestionsCard.js +198 -0
  7. package/dist/shared/components/ItemEditForm.js +3329 -3263
  8. package/dist/shared/components/McpConnectionScope.js +480 -0
  9. package/dist/shared/components/MyWorkView.js +223 -208
  10. package/dist/shared/components/RecordReadView.js +620 -575
  11. package/dist/shared/components/chat/ChatPanel.js +683 -671
  12. package/dist/shared/components/imports/DownloadSampleButton.js +69 -0
  13. package/dist/shared/components/imports/ImportConsole.js +106 -104
  14. package/dist/shared/components/imports/RunDetailSheet.js +34 -32
  15. package/dist/shared/components/item-edit/FieldAffordances.js +32 -32
  16. package/dist/shared/components/item-edit/FormTour.js +279 -0
  17. package/dist/shared/components/item-edit/GroupSection.js +377 -360
  18. package/dist/shared/components/item-edit/PersonalDefaultControl.js +28 -28
  19. package/dist/shared/components/item-edit/entry/EntryStrip.js +30 -26
  20. package/dist/shared/components/item-edit/form-density.js +36 -0
  21. package/dist/shared/components/item-edit/useFormUsageBeacon.js +59 -46
  22. package/dist/shared/components/item-edit/usePersonalDefaults.js +312 -296
  23. package/dist/shared/components/layout-editor/AddPanel.js +349 -192
  24. package/dist/shared/components/layout-editor/DesignNode.js +126 -112
  25. package/dist/shared/components/layout-editor/EditorTopBar.js +123 -103
  26. package/dist/shared/components/layout-editor/LayoutEditor.js +829 -751
  27. package/dist/shared/components/layout-editor/PlaceTools.js +334 -0
  28. package/dist/shared/components/layout-editor/SlashInsert.js +252 -0
  29. package/dist/shared/components/layout-editor/StructureMenu.js +285 -242
  30. package/dist/shared/components/layout-editor/add-target.js +54 -43
  31. package/dist/shared/components/layout-editor/ai-forms/AiComposer.js +238 -155
  32. package/dist/shared/components/layout-editor/ai-forms/AiFormsButton.js +1 -1
  33. package/dist/shared/components/layout-editor/ai-forms/ai-forms-api.js +15 -12
  34. package/dist/shared/components/layout-editor/dnd/LayoutDndProvider.js +347 -189
  35. package/dist/shared/components/layout-editor/dnd/TrashZone.js +60 -32
  36. package/dist/shared/components/layout-editor/dnd/UndoChip.js +76 -0
  37. package/dist/shared/components/layout-editor/dnd/merge-drop.js +33 -0
  38. package/dist/shared/components/layout-editor/dnd/multi-drop.js +87 -0
  39. package/dist/shared/components/layout-editor/dnd/node.js +115 -105
  40. package/dist/shared/components/layout-editor/dnd/sensors.js +23 -0
  41. package/dist/shared/components/layout-editor/dnd/trash-drop.js +34 -28
  42. package/dist/shared/components/layout-editor/dnd/trash-links.js +97 -0
  43. package/dist/shared/components/layout-editor/even-row.js +86 -0
  44. package/dist/shared/components/layout-editor/field-list.js +99 -0
  45. package/dist/shared/components/layout-editor/format-painter.js +102 -0
  46. package/dist/shared/components/layout-editor/grid-guides.js +15 -13
  47. package/dist/shared/components/layout-editor/inspector/BehaviourSettings.js +150 -132
  48. package/dist/shared/components/layout-editor/inspector/BulkInspector.js +57 -53
  49. package/dist/shared/components/layout-editor/inspector/EvenRowAction.js +31 -0
  50. package/dist/shared/components/layout-editor/inspector/GroupInspector.js +154 -141
  51. package/dist/shared/components/layout-editor/inspector/Inspector.js +209 -178
  52. package/dist/shared/components/layout-editor/inspector/LookTab.js +106 -98
  53. package/dist/shared/components/layout-editor/inspector/RulesTab.js +38 -37
  54. package/dist/shared/components/layout-editor/inspector/kit.js +280 -223
  55. package/dist/shared/components/layout-editor/keyboard-move.js +15 -15
  56. package/dist/shared/components/layout-editor/lint/LabelStyle.js +201 -0
  57. package/dist/shared/components/layout-editor/lint/LintPanel.js +132 -84
  58. package/dist/shared/components/layout-editor/lint/lint-api.js +65 -28
  59. package/dist/shared/components/layout-editor/nav/NavTools.js +14 -12
  60. package/dist/shared/components/layout-editor/nav/ZoomControls.js +145 -0
  61. package/dist/shared/components/layout-editor/nav/useEditorNav.js +34 -32
  62. package/dist/shared/components/layout-editor/nav/view-prefs.js +100 -15
  63. package/dist/shared/components/layout-editor/outputs/LayoutFile.js +89 -0
  64. package/dist/shared/components/layout-editor/outputs/OutputsButton.js +272 -195
  65. package/dist/shared/components/layout-editor/outputs/layout-file-plan.js +176 -0
  66. package/dist/shared/components/layout-editor/outputs/output-api.js +71 -37
  67. package/dist/shared/components/layout-editor/overview/describe-conditions.js +16 -11
  68. package/dist/shared/components/layout-editor/overview/purpose.js +5 -5
  69. package/dist/shared/components/layout-editor/parity-keys.json.js +1 -1
  70. package/dist/shared/components/layout-editor/pin.js +37 -19
  71. package/dist/shared/components/layout-editor/place-clip.js +257 -0
  72. package/dist/shared/components/layout-editor/preview/PreviewModes.js +27 -26
  73. package/dist/shared/components/layout-editor/preview/PreviewPanes.js +148 -117
  74. package/dist/shared/components/layout-editor/preview/SampleRecord.js +113 -0
  75. package/dist/shared/components/layout-editor/preview/preview-model.js +79 -60
  76. package/dist/shared/components/layout-editor/preview/sample-record.js +105 -0
  77. package/dist/shared/components/layout-editor/removed-log.js +151 -0
  78. package/dist/shared/components/layout-editor/reuse/LibraryRows.js +109 -78
  79. package/dist/shared/components/layout-editor/reuse/linked-sections.js +373 -0
  80. package/dist/shared/components/layout-editor/revert-element.js +140 -0
  81. package/dist/shared/components/layout-editor/section-structure.js +193 -170
  82. package/dist/shared/components/layout-editor/settings/EntrySection.js +63 -45
  83. package/dist/shared/components/layout-editor/settings/LayoutSection.js +63 -32
  84. package/dist/shared/components/layout-editor/settings/ResolveSettings.js +179 -137
  85. package/dist/shared/components/layout-editor/settings/WhoSection.js +18 -17
  86. package/dist/shared/components/layout-editor/settings/settings-registry.js +24 -0
  87. package/dist/shared/components/layout-editor/shortcuts.js +21 -16
  88. package/dist/shared/components/layout-editor/structure-ops.js +221 -195
  89. package/dist/shared/components/layout-editor/usage/UsagePanel.js +133 -85
  90. package/dist/shared/components/layout-editor/usage/refusal-lens.js +130 -0
  91. package/dist/shared/components/layout-editor/usage/usage-api.js +12 -11
  92. package/dist/shared/components/panels/CommentPanel.js +47 -45
  93. package/dist/shared/components/panels/RevisionsPanel.js +66 -64
  94. package/dist/shared/components/panels/TaskPanel.js +395 -332
  95. package/dist/shared/components/profile/AgentsPanel.js +196 -147
  96. package/dist/shared/components/profile/ConnectionRollback.js +329 -0
  97. package/dist/shared/components/profile/MyDefaultsCard.js +526 -520
  98. package/dist/shared/lib/entry-config.js +22 -22
  99. package/dist/shared/lib/form-usage-beacon.js +91 -55
  100. package/dist/shared/lib/layout-lint.js +530 -284
  101. package/dist/shared/lib/layout-resolve.js +58 -44
  102. package/package.json +1 -1
@@ -1,17 +1,23 @@
1
- const he = "__ungrouped__";
2
- function Oe(o, n) {
3
- if (!n) return o;
4
- const s = new Set(o.placements.map((g) => g.field)), a = new Set(o.groups.map((g) => g.key)), c = n.groups.filter((g) => g.key !== he && !a.has(g.key)), u = n.placements.filter((g) => !s.has(g.field));
1
+ const pe = [
2
+ "label-sentence-case",
3
+ "label-too-long",
4
+ "label-jargon",
5
+ "help-repeats-label",
6
+ "label-duplicate"
7
+ ], Ee = "__ungrouped__";
8
+ function it(t, n) {
9
+ if (!n) return t;
10
+ const s = new Set(t.placements.map((c) => c.field)), a = new Set(t.groups.map((c) => c.key)), u = n.groups.filter((c) => c.key !== Ee && !a.has(c.key)), r = n.placements.filter((c) => !s.has(c.field));
5
11
  return {
6
- ...o,
7
- groups: [...o.groups, ...c],
8
- placements: [...o.placements, ...u],
9
- inherited: { fields: u.map((g) => g.field), groups: c.map((g) => g.key) }
12
+ ...t,
13
+ groups: [...t.groups, ...u],
14
+ placements: [...t.placements, ...r],
15
+ inherited: { fields: r.map((c) => c.field), groups: u.map((c) => c.key) }
10
16
  };
11
17
  }
12
- const Ue = { fields: [], roles: [], requirements: [] }, ye = /^__.*__$/, Se = "__header__", Me = /^\{\{\s*[A-Za-z_][A-Za-z0-9_]*\s*\}\}/;
13
- function W(o) {
14
- let n = o;
18
+ const lt = { fields: [], roles: [], requirements: [] }, V = /^__.*__$/, Oe = "__header__", je = /^\{\{\s*[A-Za-z_][A-Za-z0-9_]*\s*\}\}/;
19
+ function ee(t) {
20
+ let n = t;
15
21
  for (let s = 0; s < 4 && typeof n == "string"; s++) {
16
22
  const a = n.trim();
17
23
  if (a === "") return null;
@@ -23,375 +29,496 @@ function W(o) {
23
29
  }
24
30
  return n;
25
31
  }
26
- function se(o) {
27
- const n = W(o);
32
+ function de(t) {
33
+ const n = ee(t);
28
34
  return n && typeof n == "object" && !Array.isArray(n) ? n : {};
29
35
  }
30
- function T(o) {
31
- const n = W(o);
36
+ function q(t) {
37
+ const n = ee(t);
32
38
  return Array.isArray(n) ? n : [];
33
39
  }
34
- const re = (o) => o === !0 || o === 1 || o === "1" || o === "true";
35
- function G(o) {
36
- return T(o).map((n) => String(n).toUpperCase());
40
+ const he = (t) => t === !0 || t === 1 || t === "1" || t === "true";
41
+ function K(t) {
42
+ return q(t).map((n) => String(n).toUpperCase());
37
43
  }
38
- function me(o) {
39
- return !ye.test(o.field) && o.widget_id == null;
44
+ function Ae(t) {
45
+ return !V.test(t.field) && t.widget_id == null;
40
46
  }
41
- function K(o, n) {
42
- const s = W(o.input_bindings);
47
+ function X(t, n) {
48
+ const s = ee(t.input_bindings);
43
49
  if (Array.isArray(s)) {
44
- const a = s.find((c) => c && typeof c == "object" && c.key === n);
50
+ const a = s.find((u) => u && typeof u == "object" && u.key === n);
45
51
  return a == null ? void 0 : a.binding_value;
46
52
  }
47
53
  if (s && typeof s == "object") return s[n];
48
54
  }
49
- function B(o) {
50
- return o.length <= 1 ? o[0] ?? "" : o.length === 2 ? `${o[0]} and ${o[1]}` : `${o.slice(0, -1).join(", ")} and ${o[o.length - 1]}`;
55
+ function G(t) {
56
+ return t.length <= 1 ? t[0] ?? "" : t.length === 2 ? `${t[0]} and ${t[1]}` : `${t.slice(0, -1).join(", ")} and ${t[t.length - 1]}`;
51
57
  }
52
- const ie = (o) => o.replace(/[_.]+/g, " ").trim().replace(/\b\w/g, (n) => n.toUpperCase());
53
- function _e(o) {
54
- return T(o).filter(
58
+ const ge = (t) => t.replace(/[_.]+/g, " ").trim().replace(/\b\w/g, (n) => n.toUpperCase());
59
+ function Re(t) {
60
+ return q(t).filter(
55
61
  (n) => !!n && typeof n == "object" && typeof n.field == "string" && !!n.op
56
62
  );
57
63
  }
58
- const O = (o) => {
59
- if (typeof o == "number") return Number.isFinite(o) ? o : null;
60
- if (typeof o == "string" && o.trim() !== "") {
61
- const n = Number(o);
64
+ const D = (t) => {
65
+ if (typeof t == "number") return Number.isFinite(t) ? t : null;
66
+ if (typeof t == "string" && t.trim() !== "") {
67
+ const n = Number(t);
62
68
  return Number.isNaN(n) ? null : n;
63
69
  }
64
70
  return null;
65
71
  };
66
- function le(o, n) {
67
- const s = O(o), a = O(n);
68
- return s !== null && a !== null ? s === a : String(o ?? "") === String(n ?? "");
72
+ function ye(t, n) {
73
+ const s = D(t), a = D(n);
74
+ return s !== null && a !== null ? s === a : String(t ?? "") === String(n ?? "");
69
75
  }
70
- function ue(o) {
76
+ function me(t) {
71
77
  const n = /* @__PURE__ */ new Map();
72
- for (const s of o)
73
- typeof s.value == "string" && Me.test(s.value.trim()) || n.set(s.field, [...n.get(s.field) ?? [], s]);
78
+ for (const s of t)
79
+ typeof s.value == "string" && je.test(s.value.trim()) || n.set(s.field, [...n.get(s.field) ?? [], s]);
74
80
  for (const s of n.values()) {
75
- const a = s.some((l) => l.op === "null"), c = s.some(
76
- (l) => l.op === "nnull" || l.op === "contains" || ["gt", "gte", "lt", "lte"].includes(l.op) || l.op === "eq" && l.value != null && l.value !== ""
81
+ const a = s.some((h) => h.op === "null"), u = s.some(
82
+ (h) => h.op === "nnull" || h.op === "contains" || ["gt", "gte", "lt", "lte"].includes(h.op) || h.op === "eq" && h.value != null && h.value !== ""
77
83
  );
78
- if (a && c) return !0;
79
- const u = s.filter((l) => l.op === "eq");
80
- for (let l = 1; l < u.length; l++) if (!le(u[0].value, u[l].value)) return !0;
81
- const g = u[0];
82
- if (g) {
83
- if (s.some((p) => p.op === "neq" && le(p.value, g.value)) || s.some((p) => p.op === "nnull") && (g.value == null || g.value === "")) return !0;
84
- const l = O(g.value);
85
- if (l !== null)
84
+ if (a && u) return !0;
85
+ const r = s.filter((h) => h.op === "eq");
86
+ for (let h = 1; h < r.length; h++) if (!ye(r[0].value, r[h].value)) return !0;
87
+ const c = r[0];
88
+ if (c) {
89
+ if (s.some((p) => p.op === "neq" && ye(p.value, c.value)) || s.some((p) => p.op === "nnull") && (c.value == null || c.value === "")) return !0;
90
+ const h = D(c.value);
91
+ if (h !== null)
86
92
  for (const p of s) {
87
- const m = O(p.value);
88
- if (m !== null && (p.op === "gt" && !(l > m) || p.op === "gte" && !(l >= m) || p.op === "lt" && !(l < m) || p.op === "lte" && !(l <= m)))
93
+ const k = D(p.value);
94
+ if (k !== null && (p.op === "gt" && !(h > k) || p.op === "gte" && !(h >= k) || p.op === "lt" && !(h < k) || p.op === "lte" && !(h <= k)))
89
95
  return !0;
90
96
  }
91
97
  }
92
- let y = -1 / 0, _ = !1, S = 1 / 0, q = !1;
93
- for (const l of s) {
94
- const p = O(l.value);
95
- p !== null && ((l.op === "gt" || l.op === "gte") && (p > y || p === y && l.op === "gt") && (y = p, _ = l.op === "gt"), (l.op === "lt" || l.op === "lte") && (p < S || p === S && l.op === "lt") && (S = p, q = l.op === "lt"));
98
+ let g = -1 / 0, w = !1, $ = 1 / 0, v = !1;
99
+ for (const h of s) {
100
+ const p = D(h.value);
101
+ p !== null && ((h.op === "gt" || h.op === "gte") && (p > g || p === g && h.op === "gt") && (g = p, w = h.op === "gt"), (h.op === "lt" || h.op === "lte") && (p < $ || p === $ && h.op === "lt") && ($ = p, v = h.op === "lt"));
96
102
  }
97
- if (y > S || y === S && (_ || q)) return !0;
103
+ if (g > $ || g === $ && (w || v)) return !0;
98
104
  }
99
105
  return !1;
100
106
  }
101
- function qe(o) {
107
+ function Ue(t) {
102
108
  const n = [];
103
- for (const s of _e(o.record_conditions))
109
+ for (const s of Re(t.record_conditions))
104
110
  s.op === "eq" ? n.push(s.value === "" || s.value == null ? { ...s, op: "null" } : s) : s.op === "neq" ? n.push(s.value === "" ? { field: s.field, op: "nnull" } : s) : s.op === "nnull" && n.push(s);
105
111
  return n;
106
112
  }
107
- const Ne = {
113
+ const De = {
108
114
  cyan: ["#00ceff", "#00ceff"],
109
115
  blue: ["#2563eb", "#60a5fa"],
110
116
  green: ["#059669", "#34d399"],
111
117
  amber: ["#d97706", "#fbbf24"],
112
118
  red: ["#dc2626", "#f87171"],
113
119
  purple: ["#9333ea", "#c084fc"]
114
- }, Ee = "#ffffff", Ie = "#0f172a", ae = 3;
115
- function V(o) {
116
- const n = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(o.trim());
120
+ }, Fe = "#ffffff", ze = "#0f172a", be = 3;
121
+ function Q(t) {
122
+ const n = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(t.trim());
117
123
  if (!n) return null;
118
124
  const s = n[1].length === 3 ? [...n[1]].map((a) => a + a).join("") : n[1];
119
125
  return [0, 2, 4].map((a) => Number.parseInt(s.slice(a, a + 2), 16));
120
126
  }
121
- function ce([o, n, s]) {
122
- const a = (c) => {
123
- const u = c / 255;
124
- return u <= 0.03928 ? u / 12.92 : ((u + 0.055) / 1.055) ** 2.4;
127
+ function _e([t, n, s]) {
128
+ const a = (u) => {
129
+ const r = u / 255;
130
+ return r <= 0.03928 ? r / 12.92 : ((r + 0.055) / 1.055) ** 2.4;
125
131
  };
126
- return 0.2126 * a(o) + 0.7152 * a(n) + 0.0722 * a(s);
132
+ return 0.2126 * a(t) + 0.7152 * a(n) + 0.0722 * a(s);
127
133
  }
128
- function fe(o, n) {
129
- const s = V(o), a = V(n);
134
+ function ke(t, n) {
135
+ const s = Q(t), a = Q(n);
130
136
  if (!s || !a) return null;
131
- const [c, u] = [ce(s), ce(a)].sort((g, y) => y - g);
132
- return (c + 0.05) / (u + 0.05);
137
+ const [u, r] = [_e(s), _e(a)].sort((c, g) => g - c);
138
+ return (u + 0.05) / (r + 0.05);
133
139
  }
134
- function Ce(o) {
135
- const n = o.trim().toLowerCase(), s = Ne[n] ?? (V(n) ? [n, n] : null);
140
+ function He(t) {
141
+ const n = t.trim().toLowerCase(), s = De[n] ?? (Q(n) ? [n, n] : null);
136
142
  if (!s) return null;
137
- const a = fe(s[0], Ee), c = fe(s[1], Ie);
138
- return a == null || c == null ? null : a <= c ? { ratio: a, mode: "light" } : { ratio: c, mode: "dark" };
143
+ const a = ke(s[0], Fe), u = ke(s[1], ze);
144
+ return a == null || u == null ? null : a <= u ? { ratio: a, mode: "light" } : { ratio: u, mode: "dark" };
139
145
  }
140
- const Re = /* @__PURE__ */ new Set(["grouped", "", "null", "undefined"]), Te = [3, 4, 6, 12], de = { error: 0, warn: 1, info: 2 };
141
- function Ae(o) {
142
- return Re.has(String(o.layout_type ?? ""));
146
+ const Pe = 40, $e = [10, 200], Ze = [
147
+ { term: "qty", say: "quantity" },
148
+ { term: "amt", say: "amount" },
149
+ { term: "num", say: "number" },
150
+ { term: "no.", say: "number" },
151
+ { term: "desc", say: "description" },
152
+ { term: "addr", say: "address" },
153
+ { term: "dept", say: "department" },
154
+ { term: "mgr", say: "manager" },
155
+ { term: "acct", say: "account" },
156
+ { term: "cust", say: "customer" },
157
+ { term: "est.", say: "estimated" },
158
+ { term: "approx", say: "approximate" },
159
+ { term: "misc", say: "other" },
160
+ { term: "pct", say: "percent" },
161
+ { term: "yr", say: "year" },
162
+ { term: "ref", say: "reference" },
163
+ { term: "tel", say: "phone" },
164
+ { term: "w/o", say: "without" },
165
+ { term: "w/", say: "with" },
166
+ { term: "utilize", say: "use" },
167
+ { term: "utilise", say: "use" }
168
+ ], xe = [
169
+ "i",
170
+ "monday",
171
+ "tuesday",
172
+ "wednesday",
173
+ "thursday",
174
+ "friday",
175
+ "saturday",
176
+ "sunday",
177
+ "january",
178
+ "february",
179
+ "march",
180
+ "april",
181
+ "june",
182
+ "july",
183
+ "august",
184
+ "september",
185
+ "october",
186
+ "november",
187
+ "december"
188
+ ], Ge = /([\s\-/()[\],&+]+)/, We = /^[A-Z][a-z'’]+$/, Ye = /^[a-z][a-z'’]*$/, Be = /[.:?!]\s*$/;
189
+ function Je(t, n = new Set(xe)) {
190
+ const s = t.split(Ge);
191
+ let a = !0, u = "";
192
+ return s.map((r, c) => {
193
+ if (c % 2 === 1 || r === "")
194
+ return u += r, r;
195
+ const g = /^([^A-Za-z]*)([A-Za-z][A-Za-z'’]*)(.*)$/.exec(r);
196
+ if (!g)
197
+ return u += r, r;
198
+ const [, w, $, v] = g, h = n.has($.toLowerCase()) || /\d/.test(r), p = a || Be.test(u);
199
+ return a = !1, u += r, h ? r : p ? Ye.test($) ? `${w}${$[0].toUpperCase()}${$.slice(1)}${v}` : r : We.test($) ? `${w}${$.toLowerCase()}${v}` : r;
200
+ }).join("");
143
201
  }
144
- function Fe(o, n) {
145
- var oe, ne;
146
- if (!Ae(o.layout)) return [];
147
- const s = { ...o, groups: o.groups.filter((e) => e.key !== he) }, a = [], c = (e) => {
148
- const t = e.target, r = t.kind === "field" ? `${t.group_key ?? ""}/${t.field}` : t.kind === "group" ? t.key : "";
149
- a.push({ id: `${e.rule}:${r}`, ...e });
150
- }, u = new Map(n.fields.map((e) => [e.field, e])), g = new Map(s.groups.map((e) => [e.key, e])), y = (e) => {
151
- const t = u.get(e);
152
- return (t == null ? void 0 : t.label) || ie(e.includes(".") && e.split(".").pop() || e);
153
- }, _ = (e) => e.label || ie(e.key), S = String(s.layout.tab_mode ?? "") === "steps", q = [...s.placements].sort((e, t) => e.sort - t.sort), l = q.filter(me), p = (e) => se(e.overrides), m = (e) => {
154
- var r;
202
+ function Ke(t) {
203
+ return t.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&");
204
+ }
205
+ function Xe(t, n, s = /* @__PURE__ */ new Set()) {
206
+ const a = [], u = [];
207
+ let r = t;
208
+ for (const c of n) {
209
+ const g = c.term.trim();
210
+ if (!g || s.has(g.toLowerCase())) continue;
211
+ const w = new RegExp(`(?<![A-Za-z0-9])${Ke(g)}(?![A-Za-z0-9])`, "gi");
212
+ for (const $ of t.matchAll(w)) {
213
+ const v = $.index ?? 0;
214
+ u.some(([h, p]) => v < p && v + $[0].length > h) || (u.push([v, v + $[0].length]), a.push({ text: $[0], say: c.say, at: v }));
215
+ }
216
+ r = r.replace(
217
+ w,
218
+ ($) => /^[A-Z]/.test($) ? `${c.say.charAt(0).toUpperCase()}${c.say.slice(1)}` : c.say
219
+ );
220
+ }
221
+ return a.sort((c, g) => c.at - g.at), { found: a.map(({ text: c, say: g }) => ({ text: c, say: g })), fixed: r };
222
+ }
223
+ const Ve = /* @__PURE__ */ new Set([
224
+ "a",
225
+ "an",
226
+ "the",
227
+ "enter",
228
+ "select",
229
+ "choose",
230
+ "pick",
231
+ "type",
232
+ "add",
233
+ "your",
234
+ "this",
235
+ "is",
236
+ "of",
237
+ "here",
238
+ "in",
239
+ "please"
240
+ ]);
241
+ function we(t) {
242
+ return t.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((n) => n && !Ve.has(n));
243
+ }
244
+ function Qe(t, n) {
245
+ const s = we(t);
246
+ if (s.length === 0) return !1;
247
+ const a = new Set(we(n));
248
+ return s.every((u) => a.has(u));
249
+ }
250
+ function et(t) {
251
+ const n = /* @__PURE__ */ new Set([
252
+ ...xe,
253
+ ...((t == null ? void 0 : t.allow_words) ?? []).map((r) => String(r).trim().toLowerCase()).filter(Boolean)
254
+ ]), s = ((t == null ? void 0 : t.jargon) ?? []).filter(
255
+ (r) => r && typeof r.term == "string" && typeof r.say == "string" && r.term.trim()
256
+ ), a = new Set(s.map((r) => r.term.trim().toLowerCase())), u = Number(t == null ? void 0 : t.max_label_length);
257
+ return {
258
+ off: new Set(((t == null ? void 0 : t.off) ?? []).map(String)),
259
+ max: Number.isInteger(u) && u >= $e[0] && u <= $e[1] ? u : Pe,
260
+ // Longer terms first, so "w/o" wins over "w/".
261
+ jargon: [...s, ...Ze.filter((r) => !a.has(r.term))].sort(
262
+ (r, c) => c.term.length - r.term.length
263
+ ),
264
+ allow: n
265
+ };
266
+ }
267
+ const tt = /* @__PURE__ */ new Set(["grouped", "", "null", "undefined"]), ot = [3, 4, 6, 12], ve = { error: 0, warn: 1, info: 2 };
268
+ function nt(t) {
269
+ return tt.has(String(t.layout_type ?? ""));
270
+ }
271
+ function at(t, n) {
272
+ var le, ae, ue, ce, fe;
273
+ if (!nt(t.layout)) return [];
274
+ const s = { ...t, groups: t.groups.filter((e) => e.key !== Ee) }, a = [], u = (e) => {
275
+ const o = e.target, l = o.kind === "field" ? `${o.group_key ?? ""}/${o.field}` : o.kind === "group" ? o.key : "";
276
+ a.push({ id: `${e.rule}:${l}`, ...e });
277
+ }, r = new Map(n.fields.map((e) => [e.field, e])), c = new Map(s.groups.map((e) => [e.key, e])), g = (e) => {
278
+ const o = r.get(e);
279
+ return (o == null ? void 0 : o.label) || ge(e.includes(".") && e.split(".").pop() || e);
280
+ }, w = (e) => e.label || ge(e.key), $ = String(s.layout.tab_mode ?? "") === "steps", v = [...s.placements].sort((e, o) => e.sort - o.sort), h = v.filter(Ae), p = (e) => de(e.overrides), k = (e) => {
281
+ var l;
155
282
  if (e.is_visible === !1 || e.is_visible === 0) return !1;
156
- const t = p(e);
157
- return !("hidden" in t ? re(t.hidden) : (r = u.get(e.field)) != null && r.hidden);
158
- }, U = (e) => {
159
- var r;
283
+ const o = p(e);
284
+ return !("hidden" in o ? he(o.hidden) : (l = r.get(e.field)) != null && l.hidden);
285
+ }, F = (e) => {
286
+ var l;
160
287
  if (e.field.includes(".")) return !1;
161
- const t = p(e);
162
- return "required" in t ? re(t.required) : !!((r = u.get(e.field)) != null && r.required);
163
- }, I = (e) => {
164
- const t = [], r = /* @__PURE__ */ new Set();
165
- let i = e ? g.get(e) : void 0;
166
- for (; i && !r.has(i.key); )
167
- r.add(i.key), t.push(i), i = i.parent_key ? g.get(i.parent_key) : void 0;
168
- return t;
169
- }, A = (e) => {
288
+ const o = p(e);
289
+ return "required" in o ? he(o.required) : !!((l = r.get(e.field)) != null && l.required);
290
+ }, z = (e) => {
291
+ const o = [], l = /* @__PURE__ */ new Set();
292
+ let i = e ? c.get(e) : void 0;
293
+ for (; i && !l.has(i.key); )
294
+ l.add(i.key), o.push(i), i = i.parent_key ? c.get(i.parent_key) : void 0;
295
+ return o;
296
+ }, T = (e) => {
170
297
  if (e.type !== "tab") return "section";
171
- const t = e.parent_key ? g.get(e.parent_key) : void 0;
172
- return (t ? String(t.tab_mode ?? "") === "steps" : S) ? "step" : "tab";
173
- }, J = qe(s.layout), F = n.roles.filter((e) => !e.admin), x = /* @__PURE__ */ new Map(), ke = (e) => {
174
- const t = _e(e.visible_when);
175
- if (t.length > 0) {
176
- if (ue(t)) return "its show-when rules can never all hold";
177
- if (J.length > 0 && ue([...J, ...t]))
298
+ const o = e.parent_key ? c.get(e.parent_key) : void 0;
299
+ return (o ? String(o.tab_mode ?? "") === "steps" : $) ? "step" : "tab";
300
+ }, M = Ue(s.layout), H = n.roles.filter((e) => !e.admin), O = /* @__PURE__ */ new Map(), Ce = (e) => {
301
+ const o = Re(e.visible_when);
302
+ if (o.length > 0) {
303
+ if (me(o)) return "its show-when rules can never all hold";
304
+ if (M.length > 0 && me([...M, ...o]))
178
305
  return "its show-when rules never hold for the records this form opens";
179
306
  }
180
- const r = new Set(G(e.hidden_for_roles));
181
- return F.length > 0 && F.every((i) => r.has(i.id.toUpperCase())) ? "it is hidden from every role but administrators" : null;
307
+ const l = new Set(K(e.hidden_for_roles));
308
+ return H.length > 0 && H.every((i) => l.has(i.id.toUpperCase())) ? "it is hidden from every role but administrators" : null;
182
309
  };
183
310
  for (const e of s.groups) {
184
- const t = I(e.key);
185
- for (const r of t) {
186
- const i = ke(r);
311
+ const o = z(e.key);
312
+ for (const l of o) {
313
+ const i = Ce(l);
187
314
  if (i) {
188
- x.set(e.key, r === e ? i : `it sits inside ${_(r)}, and ${i}`);
315
+ O.set(e.key, l === e ? i : `it sits inside ${w(l)}, and ${i}`);
189
316
  break;
190
317
  }
191
318
  }
192
319
  }
193
320
  for (const e of s.groups) {
194
- const t = x.get(e.key);
195
- !t || e.parent_key && x.has(e.parent_key) || c({
321
+ const o = O.get(e.key);
322
+ !o || e.parent_key && O.has(e.parent_key) || u({
196
323
  rule: "unreachable-step",
197
324
  severity: "warn",
198
325
  target: { kind: "group", key: e.key },
199
- message: `${_(e)} never shows: ${t}.`
326
+ message: `${w(e)} never shows: ${o}.`
200
327
  });
201
328
  }
202
329
  for (const e of s.groups) {
203
330
  if (e.type === "content") continue;
204
- const t = s.groups.filter((d) => d.parent_key === e.key);
205
- if (q.filter((d) => d.group_key === e.key).length > 0 || t.length > 0) continue;
206
- const i = e.type === "container" ? "tabs holder" : A(e);
207
- c({
331
+ const o = s.groups.filter((f) => f.parent_key === e.key);
332
+ if (v.filter((f) => f.group_key === e.key).length > 0 || o.length > 0) continue;
333
+ const i = e.type === "container" ? "tabs holder" : T(e);
334
+ u({
208
335
  rule: e.type === "tab" ? "empty-step" : "empty-section",
209
336
  severity: "warn",
210
337
  target: { kind: "group", key: e.key },
211
- message: e.type === "container" ? `${_(e)} is a tabs holder with no tabs.` : `The ${i} ${_(e)} holds nothing, so it shows as an empty ${i}.`,
338
+ message: e.type === "container" ? `${w(e)} is a tabs holder with no tabs.` : `The ${i} ${w(e)} holds nothing, so it shows as an empty ${i}.`,
212
339
  fix: {
213
- label: `Remove ${_(e)}`,
340
+ label: `Remove ${w(e)}`,
214
341
  ops: [{ op: "group_remove", key: e.key, placements: "ungroup" }]
215
342
  }
216
343
  });
217
344
  }
218
- const C = /* @__PURE__ */ new Map();
219
- for (const e of l) C.set(e.field, [...C.get(e.field) ?? [], e]);
220
- const Z = (e) => !(e.group_key && x.has(e.group_key)), be = (e) => (C.get(e) ?? []).some((t) => m(t) && Z(t)), H = /* @__PURE__ */ new Map(), X = (e, t, r) => {
221
- const i = H.get(e) ?? /* @__PURE__ */ new Map();
222
- i.has(t) || i.set(t, r), H.set(e, i);
223
- }, Q = (e, t) => e.can_write && (e.writable_fields == null || e.writable_fields.includes(t));
224
- for (const [e, t] of C)
225
- if (t.some(U))
226
- for (const r of F) Q(r, e) && X(e, r.id, "required");
345
+ const x = /* @__PURE__ */ new Map();
346
+ for (const e of h) x.set(e.field, [...x.get(e.field) ?? [], e]);
347
+ const W = (e) => !(e.group_key && O.has(e.group_key)), Te = (e) => (x.get(e) ?? []).some((o) => k(o) && W(o)), Y = /* @__PURE__ */ new Map(), te = (e, o, l) => {
348
+ const i = Y.get(e) ?? /* @__PURE__ */ new Map();
349
+ i.has(o) || i.set(o, l), Y.set(e, i);
350
+ }, oe = (e, o) => e.can_write && (e.writable_fields == null || e.writable_fields.includes(o));
351
+ for (const [e, o] of x)
352
+ if (o.some(F))
353
+ for (const l of H) oe(l, e) && te(e, l.id, "required");
227
354
  for (const e of n.requirements) {
228
- if (!C.has(e.field)) continue;
229
- const t = e.role_ids.length ? e.role_ids.map((r) => r.toUpperCase()) : null;
230
- for (const r of F)
231
- t && !t.includes(r.id.toUpperCase()) || Q(r, e.field) && X(e.field, r.id, `to ${e.transition}`);
355
+ if (!x.has(e.field)) continue;
356
+ const o = e.role_ids.length ? e.role_ids.map((l) => l.toUpperCase()) : null;
357
+ for (const l of H)
358
+ o && !o.includes(l.id.toUpperCase()) || oe(l, e.field) && te(e.field, l.id, `to ${e.transition}`);
232
359
  }
233
- const $e = new Map(n.roles.map((e) => [e.id.toUpperCase(), e.name]));
234
- for (const [e, t] of C) {
235
- const r = t[0], i = { kind: "field", field: e, group_key: r.group_key }, d = y(e), w = t.some(U);
236
- if (w && !t.some(m)) {
237
- const f = t.find((k) => k.is_visible === !1 || k.is_visible === 0);
238
- c({
360
+ const Me = new Map(n.roles.map((e) => [e.id.toUpperCase(), e.name]));
361
+ for (const [e, o] of x) {
362
+ const l = o[0], i = { kind: "field", field: e, group_key: l.group_key }, f = g(e), m = o.some(F);
363
+ if (m && !o.some(k)) {
364
+ const d = o.find((L) => L.is_visible === !1 || L.is_visible === 0);
365
+ u({
239
366
  rule: "required-hidden",
240
367
  severity: "error",
241
368
  target: i,
242
- message: `${d} is required, but this form hides it — nobody can fill it here.`,
243
- fix: f ? {
244
- label: `Show ${d}`,
369
+ message: `${f} is required, but this form hides it — nobody can fill it here.`,
370
+ fix: d ? {
371
+ label: `Show ${f}`,
245
372
  ops: [
246
373
  {
247
374
  op: "update_placement",
248
- at: { field: e, group_key: f.group_key },
375
+ at: { field: e, group_key: d.group_key },
249
376
  patch: { is_visible: !0 }
250
377
  }
251
378
  ]
252
379
  } : void 0
253
380
  });
254
381
  }
255
- const M = H.get(e);
256
- if (M && t.some(m)) {
257
- const f = /* @__PURE__ */ new Map();
258
- for (const h of M.keys()) {
259
- const b = h.toUpperCase();
260
- let v = null, E = !1;
261
- for (const L of t.filter(m)) {
262
- const D = I(L.group_key).find((ve) => G(ve.hidden_for_roles).includes(b)), R = L.group_key ? g.get(L.group_key) : void 0, $ = R && G(R.locked_for_roles).includes(b) ? R : void 0;
263
- if (D) v ?? (v = { group: D, how: "hidden" });
264
- else if ($) v ?? (v = { group: $, how: "locked" });
382
+ const _ = Y.get(e);
383
+ if (_ && o.some(k)) {
384
+ const d = /* @__PURE__ */ new Map();
385
+ for (const y of _.keys()) {
386
+ const b = y.toUpperCase();
387
+ let S = null, C = !1;
388
+ for (const U of o.filter(k)) {
389
+ const Z = z(U.group_key).find((qe) => K(qe.hidden_for_roles).includes(b)), I = U.group_key ? c.get(U.group_key) : void 0, A = I && K(I.locked_for_roles).includes(b) ? I : void 0;
390
+ if (Z) S ?? (S = { group: Z, how: "hidden" });
391
+ else if (A) S ?? (S = { group: A, how: "locked" });
265
392
  else {
266
- E = !0;
393
+ C = !0;
267
394
  break;
268
395
  }
269
396
  }
270
- !E && v && f.set(h, v);
397
+ !C && S && d.set(y, S);
271
398
  }
272
- const k = /* @__PURE__ */ new Map();
273
- for (const [h, b] of f) {
274
- const v = `${b.how}|${b.group.key}`, E = k.get(v) ?? { ...b, roles: [] };
275
- E.roles.push(h), k.set(v, E);
399
+ const L = /* @__PURE__ */ new Map();
400
+ for (const [y, b] of d) {
401
+ const S = `${b.how}|${b.group.key}`, C = L.get(S) ?? { ...b, roles: [] };
402
+ C.roles.push(y), L.set(S, C);
276
403
  }
277
- for (const h of k.values()) {
278
- const b = h.roles.map(($) => $e.get($.toUpperCase()) ?? $), E = [...new Set(h.roles.map(($) => M.get($) ?? "required"))].find(($) => $.startsWith("to ")), L = E ? `${B(b)} must fill ${d} ${E}` : `${d} is required and ${B(b)} can edit these records`, z = h.how === "hidden" ? "hidden_for_roles" : "locked_for_roles", D = new Set(h.roles.map(($) => $.toUpperCase())), R = T(h.group[z]).filter(
279
- ($) => !D.has(String($).toUpperCase())
404
+ for (const y of L.values()) {
405
+ const b = y.roles.map((A) => Me.get(A.toUpperCase()) ?? A), C = [...new Set(y.roles.map((A) => _.get(A) ?? "required"))].find((A) => A.startsWith("to ")), U = C ? `${G(b)} must fill ${f} ${C}` : `${f} is required and ${G(b)} can edit these records`, J = y.how === "hidden" ? "hidden_for_roles" : "locked_for_roles", Z = new Set(y.roles.map((A) => A.toUpperCase())), I = q(y.group[J]).filter(
406
+ (A) => !Z.has(String(A).toUpperCase())
280
407
  );
281
- c({
408
+ u({
282
409
  rule: "required-hidden-for-role",
283
410
  severity: "error",
284
- target: { kind: "field", field: e, group_key: r.group_key },
285
- message: `${L}, but ${_(h.group)} is ${h.how} for ${b.length === 1 ? "that role" : "those roles"}.`,
411
+ target: { kind: "field", field: e, group_key: l.group_key },
412
+ message: `${U}, but ${w(y.group)} is ${y.how} for ${b.length === 1 ? "that role" : "those roles"}.`,
286
413
  fix: {
287
- label: `${h.how === "hidden" ? "Show" : "Unlock"} ${_(h.group)} for ${B(b)}`,
414
+ label: `${y.how === "hidden" ? "Show" : "Unlock"} ${w(y.group)} for ${G(b)}`,
288
415
  ops: [
289
416
  {
290
417
  op: "group_update",
291
- key: h.group.key,
292
- patch: { [z]: R.length ? JSON.stringify(R) : null }
418
+ key: y.group.key,
419
+ patch: { [J]: I.length ? JSON.stringify(I) : null }
293
420
  }
294
421
  ]
295
422
  }
296
423
  });
297
424
  }
298
425
  }
299
- if (t.some(m))
300
- for (const f of ((oe = u.get(e)) == null ? void 0 : oe.cascade_parents) ?? []) {
301
- if (!f || f === e || be(f)) continue;
302
- const k = C.has(f), h = t.find(m) ?? r, b = q.filter((v) => v.group_key === h.group_key).findIndex((v) => v.field === e);
303
- c({
426
+ if (o.some(k))
427
+ for (const d of ((le = r.get(e)) == null ? void 0 : le.cascade_parents) ?? []) {
428
+ if (!d || d === e || Te(d)) continue;
429
+ const L = x.has(d), y = o.find(k) ?? l, b = v.filter((S) => S.group_key === y.group_key).findIndex((S) => S.field === e);
430
+ u({
304
431
  rule: "cascade-missing",
305
432
  severity: "warn",
306
- target: { kind: "field", field: e, group_key: h.group_key },
307
- message: k ? `${d} narrows its choices by ${y(f)}, which is hidden on this form.` : `${d} narrows its choices by ${y(f)}, which is not on this form.`,
308
- fix: k ? void 0 : {
309
- label: `Add ${y(f)} before ${d}`,
433
+ target: { kind: "field", field: e, group_key: y.group_key },
434
+ message: L ? `${f} narrows its choices by ${g(d)}, which is hidden on this form.` : `${f} narrows its choices by ${g(d)}, which is not on this form.`,
435
+ fix: L ? void 0 : {
436
+ label: `Add ${g(d)} before ${f}`,
310
437
  ops: [
311
438
  {
312
439
  op: "place",
313
- field: f,
314
- group_key: h.group_key,
440
+ field: d,
441
+ group_key: y.group_key,
315
442
  index: Math.max(0, b)
316
443
  }
317
444
  ]
318
445
  }
319
446
  });
320
447
  }
321
- if (!w) {
322
- if (!t.some(m))
323
- c({
448
+ if (!m) {
449
+ if (!o.some(k))
450
+ u({
324
451
  rule: "unreachable-field",
325
452
  severity: "info",
326
453
  target: i,
327
- message: `${d} is hidden everywhere it is placed, so nobody sees it on this form.`
454
+ message: `${f} is hidden everywhere it is placed, so nobody sees it on this form.`
328
455
  });
329
- else if (!t.some((f) => m(f) && Z(f))) {
330
- const f = g.get(((ne = t.find(m)) == null ? void 0 : ne.group_key) ?? "");
331
- c({
456
+ else if (!o.some((d) => k(d) && W(d))) {
457
+ const d = c.get(((ae = o.find(k)) == null ? void 0 : ae.group_key) ?? "");
458
+ u({
332
459
  rule: "unreachable-field",
333
460
  severity: "info",
334
461
  target: i,
335
- message: `${d} only sits in ${f ? _(f) : "a part of the form"}, which never shows.`
462
+ message: `${f} only sits in ${d ? w(d) : "a part of the form"}, which never shows.`
336
463
  });
337
464
  }
338
465
  }
339
- const N = t.filter(m), Y = (f) => {
340
- var k;
341
- return ((k = u.get(e)) == null ? void 0 : k.type) === "alias" || f.group_key != null && l.filter((h) => h.group_key === f.group_key).length === 1;
466
+ const E = o.filter(k), R = (d) => {
467
+ var L;
468
+ return ((L = r.get(e)) == null ? void 0 : L.type) === "alias" || d.group_key != null && h.filter((y) => y.group_key === d.group_key).length === 1;
342
469
  };
343
- if (N.length > 0 && N.every((f) => p(f).label === "") && !N.some(Y)) {
344
- const f = N[0], { label: k, ...h } = p(f);
345
- c({
346
- rule: w ? "a11y-required-no-marker" : "a11y-no-label",
470
+ if (E.length > 0 && E.every((d) => p(d).label === "") && !E.some(R)) {
471
+ const d = E[0], { label: L, ...y } = p(d);
472
+ u({
473
+ rule: m ? "a11y-required-no-marker" : "a11y-no-label",
347
474
  severity: "warn",
348
- target: { kind: "field", field: e, group_key: f.group_key },
349
- message: w ? `${d} is required, but its label is hidden — so is the required mark.` : `${d} shows no label; people and screen readers cannot tell what it asks for.`,
475
+ target: { kind: "field", field: e, group_key: d.group_key },
476
+ message: m ? `${f} is required, but its label is hidden — so is the required mark.` : `${f} shows no label; people and screen readers cannot tell what it asks for.`,
350
477
  fix: {
351
- label: `Show the label of ${d}`,
478
+ label: `Show the label of ${f}`,
352
479
  ops: [
353
480
  {
354
481
  op: "update_placement",
355
- at: { field: e, group_key: f.group_key },
356
- patch: { overrides: Object.keys(h).length ? h : null }
482
+ at: { field: e, group_key: d.group_key },
483
+ patch: { overrides: Object.keys(y).length ? y : null }
357
484
  }
358
485
  ]
359
486
  }
360
487
  });
361
488
  }
362
489
  }
363
- const ee = (e) => {
364
- var r;
365
- const t = e.col_span ?? ((r = u.get(e.field)) == null ? void 0 : r.col_span) ?? 12;
366
- return Te.includes(Number(t)) ? Number(t) : 12;
367
- }, P = /* @__PURE__ */ new Map();
368
- for (const e of l)
369
- e.group_key === Se || !m(e) || P.set(e.group_key, [...P.get(e.group_key) ?? [], e]);
370
- for (const [e, t] of P) {
371
- const r = [];
372
- for (const i of t) {
373
- const d = ee(i), w = r[r.length - 1];
374
- w && w.free >= d ? (w.items.push(i), w.free -= d) : r.push({ items: [i], free: 12 - d });
490
+ const ne = (e) => {
491
+ var l;
492
+ const o = e.col_span ?? ((l = r.get(e.field)) == null ? void 0 : l.col_span) ?? 12;
493
+ return ot.includes(Number(o)) ? Number(o) : 12;
494
+ }, B = /* @__PURE__ */ new Map();
495
+ for (const e of h)
496
+ e.group_key === Oe || !k(e) || B.set(e.group_key, [...B.get(e.group_key) ?? [], e]);
497
+ for (const [e, o] of B) {
498
+ const l = [];
499
+ for (const i of o) {
500
+ const f = ne(i), m = l[l.length - 1];
501
+ m && m.free >= f ? (m.items.push(i), m.free -= f) : l.push({ items: [i], free: 12 - f });
375
502
  }
376
- for (let i = 0; i + 1 < r.length; i++) {
377
- const d = r[i];
378
- if (d.free <= 0) continue;
379
- const w = r.slice(i + 1, i + 3).flatMap((f) => f.items), M = w.slice(1).find((f) => ee(f) <= d.free);
380
- if (!M) continue;
381
- const N = d.items[d.items.length - 1], Y = t.indexOf(N) + 1;
382
- c({
503
+ for (let i = 0; i + 1 < l.length; i++) {
504
+ const f = l[i];
505
+ if (f.free <= 0) continue;
506
+ const m = l.slice(i + 1, i + 3).flatMap((d) => d.items), _ = m.slice(1).find((d) => ne(d) <= f.free);
507
+ if (!_) continue;
508
+ const E = f.items[f.items.length - 1], R = o.indexOf(E) + 1;
509
+ u({
383
510
  rule: "a11y-tab-order",
384
511
  severity: "info",
385
- target: { kind: "field", field: M.field, group_key: e },
386
- message: `${y(M.field)} would fit beside ${y(N.field)}, but comes after ${y(w[0].field)} — the keyboard order runs down, then back up.`,
512
+ target: { kind: "field", field: _.field, group_key: e },
513
+ message: `${g(_.field)} would fit beside ${g(E.field)}, but comes after ${g(m[0].field)} — the keyboard order runs down, then back up.`,
387
514
  fix: {
388
- label: `Move ${y(M.field)} beside ${y(N.field)}`,
515
+ label: `Move ${g(_.field)} beside ${g(E.field)}`,
389
516
  ops: [
390
517
  {
391
518
  op: "move",
392
- from: { field: M.field, group_key: e },
519
+ from: { field: _.field, group_key: e },
393
520
  to_group_key: e,
394
- index: Y
521
+ index: R
395
522
  }
396
523
  ]
397
524
  }
@@ -399,92 +526,211 @@ function Fe(o, n) {
399
526
  break;
400
527
  }
401
528
  }
402
- const j = (e, t, r, i) => {
529
+ const P = (e, o, l, i) => {
403
530
  if (typeof e != "string" || !e) return;
404
- const d = Ce(e);
405
- !d || d.ratio >= ae || a.push({
531
+ const f = He(e);
532
+ !f || f.ratio >= be || a.push({
406
533
  id: `a11y-contrast:${i}:${e}`,
407
534
  rule: "a11y-contrast",
408
535
  severity: "warn",
409
- target: r,
410
- message: `${t} uses ${e}, which reads at ${d.ratio.toFixed(1)}:1 on the ${d.mode} background (${ae}:1 is the least).`
536
+ target: l,
537
+ message: `${o} uses ${e}, which reads at ${f.ratio.toFixed(1)}:1 on the ${f.mode} background (${be}:1 is the least).`
411
538
  });
412
539
  };
413
- for (const e of q) {
414
- const t = { kind: "field", field: e.field, group_key: e.group_key }, r = ye.test(e.field) ? "The subtitle" : y(e.field);
415
- j(K(e, "__color__"), r, t, `${e.group_key}/${e.field}`);
416
- for (const i of T(K(e, "__threshold__")))
417
- j(i == null ? void 0 : i.color, `A threshold on ${r}`, t, `${e.group_key}/${e.field}`);
418
- for (const i of T(se(K(e, "__subtitle_config__")).fields))
419
- j(
540
+ for (const e of v) {
541
+ const o = { kind: "field", field: e.field, group_key: e.group_key }, l = V.test(e.field) ? "The subtitle" : g(e.field);
542
+ P(X(e, "__color__"), l, o, `${e.group_key}/${e.field}`);
543
+ for (const i of q(X(e, "__threshold__")))
544
+ P(i == null ? void 0 : i.color, `A threshold on ${l}`, o, `${e.group_key}/${e.field}`);
545
+ for (const i of q(de(X(e, "__subtitle_config__")).fields))
546
+ P(
420
547
  i == null ? void 0 : i.color,
421
- `The subtitle part ${y(String((i == null ? void 0 : i.field) ?? ""))}`,
422
- t,
548
+ `The subtitle part ${g(String((i == null ? void 0 : i.field) ?? ""))}`,
549
+ o,
423
550
  `subtitle/${String((i == null ? void 0 : i.field) ?? "")}`
424
551
  );
425
552
  }
426
553
  for (const e of s.groups)
427
- for (const t of T(e.summary_fields))
428
- j(
429
- t == null ? void 0 : t.color,
430
- `The summary of ${_(e)}`,
554
+ for (const o of q(e.summary_fields))
555
+ P(
556
+ o == null ? void 0 : o.color,
557
+ `The summary of ${w(e)}`,
431
558
  { kind: "group", key: e.key },
432
559
  `summary/${e.key}`
433
560
  );
434
- const te = /* @__PURE__ */ new Set(), we = (e) => {
435
- var t, r;
436
- return e.kind === "field" && !!((t = o.inherited) != null && t.fields.includes(e.field)) || e.kind === "group" && !!((r = o.inherited) != null && r.groups.includes(e.key));
561
+ const N = et(n.style), j = (e) => !N.off.has(e), Ne = (e) => e.trim() !== "" && !e.includes("{{"), se = (e, o, l, i, f) => {
562
+ const m = e.text.trim();
563
+ if (Ne(m)) {
564
+ if (j("label-sentence-case")) {
565
+ const _ = Je(m, N.allow);
566
+ _ !== m && a.push({
567
+ id: `label-sentence-case:${l}`,
568
+ rule: "label-sentence-case",
569
+ severity: "info",
570
+ target: o,
571
+ message: `${i} “${m}” is not in sentence case — house style is “${_}”.`,
572
+ fix: { label: `Change ${f} to “${_}”`, ops: e.ops(_) }
573
+ });
574
+ }
575
+ if (j("label-too-long") && m.length > N.max && a.push({
576
+ id: `label-too-long:${l}`,
577
+ rule: "label-too-long",
578
+ severity: "info",
579
+ target: o,
580
+ message: `${i} “${m}” is ${m.length} characters; house style keeps labels to ${N.max}. Move the detail into help text.`
581
+ }), j("label-jargon")) {
582
+ const _ = Xe(m, N.jargon, N.allow);
583
+ if (_.found.length > 0) {
584
+ const E = _.found.map((R) => `“${R.text}” (say “${R.say}”)`);
585
+ a.push({
586
+ id: `label-jargon:${l}`,
587
+ rule: "label-jargon",
588
+ severity: "info",
589
+ target: o,
590
+ message: `${i} “${m}” uses ${G(E)}.`,
591
+ fix: _.fixed !== m ? { label: `Change ${f} to “${_.fixed}”`, ops: e.ops(_.fixed) } : void 0
592
+ });
593
+ }
594
+ }
595
+ }
596
+ }, re = /* @__PURE__ */ new Map();
597
+ for (const [e, o] of x) {
598
+ const i = o.filter((b) => k(b) && W(b))[0];
599
+ if (!i) continue;
600
+ const f = p(i), m = { kind: "field", field: e, group_key: i.group_key }, _ = { field: e, group_key: i.group_key }, E = typeof f.label == "string" && f.label !== "" ? f.label : null, R = f.label === "" ? null : E != null ? {
601
+ text: E,
602
+ ops: (b) => [
603
+ { op: "update_placement", at: _, patch: { overrides: { ...f, label: b } } }
604
+ ]
605
+ } : i.label_override ? {
606
+ text: i.label_override,
607
+ ops: (b) => [{ op: "update_placement", at: _, patch: { label_override: b } }]
608
+ } : (ue = r.get(e)) != null && ue.label ? {
609
+ text: String((ce = r.get(e)) == null ? void 0 : ce.label),
610
+ // The field's own label stays; this form shows the fixed one.
611
+ ops: (b) => [
612
+ { op: "update_placement", at: _, patch: { overrides: { ...f, label: b } } }
613
+ ]
614
+ } : null;
615
+ R && se(R, m, `${i.group_key ?? ""}/${e}`, "The label", "the label");
616
+ const d = f.label === "" ? null : ((R == null ? void 0 : R.text) ?? g(e)).trim(), L = typeof f.note == "string" && f.note.trim() !== "" ? f.note : null, y = L ?? (((fe = r.get(e)) == null ? void 0 : fe.note) || null);
617
+ if (j("help-repeats-label") && d && y && Qe(y, d)) {
618
+ const { note: b, ...S } = f;
619
+ a.push({
620
+ id: `help-repeats-label:${i.group_key ?? ""}/${e}`,
621
+ rule: "help-repeats-label",
622
+ severity: "info",
623
+ target: m,
624
+ message: `The help text of ${d} (“${y.trim()}”) only repeats the label. Say what to enter, or leave it out.`,
625
+ fix: L ? {
626
+ label: `Remove the help text of ${d}`,
627
+ ops: [
628
+ {
629
+ op: "update_placement",
630
+ at: _,
631
+ patch: { overrides: Object.keys(S).length ? S : null }
632
+ }
633
+ ]
634
+ } : void 0
635
+ });
636
+ }
637
+ if (d && j("label-duplicate")) {
638
+ const b = d.toLowerCase(), S = re.get(b);
639
+ S && S !== e ? a.push({
640
+ id: `label-duplicate:${i.group_key ?? ""}/${e}`,
641
+ rule: "label-duplicate",
642
+ severity: "warn",
643
+ target: m,
644
+ message: `${e} and ${S} both show the label “${d}” on this form — people cannot tell them apart.`
645
+ }) : re.set(b, e);
646
+ }
647
+ }
648
+ for (const e of s.groups) {
649
+ if (e.type === "content" || e.type === "container" || V.test(e.key) || O.has(e.key)) continue;
650
+ const o = T(e);
651
+ se(
652
+ {
653
+ text: e.label,
654
+ ops: (l) => [{ op: "group_update", key: e.key, patch: { label: l } }]
655
+ },
656
+ { kind: "group", key: e.key },
657
+ e.key,
658
+ `The ${o} title`,
659
+ `the ${o} title`
660
+ );
661
+ }
662
+ const ie = /* @__PURE__ */ new Set(), Ie = (e) => {
663
+ var o, l;
664
+ return e.kind === "field" && !!((o = t.inherited) != null && o.fields.includes(e.field)) || e.kind === "group" && !!((l = t.inherited) != null && l.groups.includes(e.key));
437
665
  };
438
- return a.filter((e) => te.has(e.id) ? !1 : (te.add(e.id), !0)).map((e) => e.fix && we(e.target) ? { ...e, fix: void 0 } : e).sort((e, t) => de[e.severity] - de[t.severity]);
666
+ return a.filter((e) => ie.has(e.id) ? !1 : (ie.add(e.id), !0)).map((e) => e.fix && Ie(e.target) ? { ...e, fix: void 0 } : e).sort((e, o) => ve[e.severity] - ve[o.severity]);
439
667
  }
440
- const pe = 30, ge = 7;
441
- function Le(o) {
668
+ const Se = 30, Le = 7, st = 5;
669
+ function rt(t) {
442
670
  const n = new Set(
443
- o.placements.filter((u) => me(u) && u.is_visible !== !1 && u.is_visible !== 0).map((u) => u.field)
444
- ).size, s = new Set(o.groups.map((u) => u.key)), a = o.groups.filter((u) => u.type === "container").map((u) => u.key), c = o.groups.filter(
445
- (u) => u.type === "tab" && (u.parent_key == null || !s.has(u.parent_key) || a.includes(u.parent_key))
671
+ t.placements.filter((r) => Ae(r) && r.is_visible !== !1 && r.is_visible !== 0).map((r) => r.field)
672
+ ).size, s = new Set(t.groups.map((r) => r.key)), a = t.groups.filter((r) => r.type === "container").map((r) => r.key), u = t.groups.filter(
673
+ (r) => r.type === "tab" && (r.parent_key == null || !s.has(r.parent_key) || a.includes(r.parent_key))
446
674
  ).length;
447
- return { fields: n, steps: c };
675
+ return { fields: n, steps: u };
448
676
  }
449
- function xe(o, n) {
450
- const { fields: s, steps: a } = Le(o), c = [];
451
- s > pe && c.push({
677
+ function ut(t, n) {
678
+ const { fields: s, steps: a } = rt(t), u = [];
679
+ s > Se && u.push({
452
680
  label: `${s} fields on one form`,
453
- points: Math.min(20, Math.ceil((s - pe) / 3))
454
- }), a > ge && c.push({
681
+ points: Math.min(20, Math.ceil((s - Se) / 3))
682
+ }), a > Le && u.push({
455
683
  label: `${a} steps or tabs`,
456
- points: Math.min(10, (a - ge) * 2)
684
+ points: Math.min(10, (a - Le) * 2)
457
685
  });
458
- const u = n.filter((l) => l.rule === "unreachable-field").length;
459
- u > 0 && c.push({
460
- label: `${u} ${u === 1 ? "field" : "fields"} nobody sees`,
461
- points: Math.min(20, u * 2)
686
+ const r = n.filter((p) => p.rule === "unreachable-field").length;
687
+ r > 0 && u.push({
688
+ label: `${r} ${r === 1 ? "field" : "fields"} nobody sees`,
689
+ points: Math.min(20, r * 2)
690
+ });
691
+ const c = n.filter(
692
+ (p) => p.rule !== "label-duplicate" && pe.includes(p.rule)
693
+ ).length;
694
+ c > 0 && u.push({
695
+ label: `${c} label style ${c === 1 ? "tip" : "tips"}`,
696
+ points: Math.min(st, c)
462
697
  });
463
- const g = n.filter((l) => l.rule !== "unreachable-field"), y = (l) => g.filter((p) => p.severity === l).length, _ = [
698
+ const g = n.filter(
699
+ (p) => p.rule !== "unreachable-field" && (p.rule === "label-duplicate" || !pe.includes(p.rule))
700
+ ), w = (p) => g.filter((k) => k.severity === p).length, $ = [
464
701
  ["error", 10, "problem", "problems"],
465
702
  ["warn", 4, "warning", "warnings"],
466
703
  ["info", 1, "suggestion", "suggestions"]
467
704
  ];
468
- let S = 0;
469
- for (const [l, p, m, U] of _) {
470
- const I = y(l);
471
- if (I === 0) continue;
472
- const A = Math.min(50 - S, I * p);
473
- A <= 0 || (S += A, c.push({ label: `${I} ${I === 1 ? m : U}`, points: A }));
705
+ let v = 0;
706
+ for (const [p, k, F, z] of $) {
707
+ const T = w(p);
708
+ if (T === 0) continue;
709
+ const M = Math.min(50 - v, T * k);
710
+ M <= 0 || (v += M, u.push({ label: `${T} ${T === 1 ? F : z}`, points: M }));
474
711
  }
475
- return { score: Math.max(0, 100 - c.reduce((l, p) => l + p.points, 0)), costs: c };
712
+ return { score: Math.max(0, 100 - u.reduce((p, k) => p + k.points, 0)), costs: u };
476
713
  }
477
714
  export {
478
- ae as CONTRAST_MIN,
479
- Ue as EMPTY_LINT_CONTEXT,
480
- pe as HEALTH_FIELD_LIMIT,
481
- ge as HEALTH_STEP_LIMIT,
482
- Ce as colourContrast,
483
- ue as conditionsContradict,
484
- fe as contrastRatio,
485
- Ae as isFormLayout,
486
- xe as layoutHealth,
487
- Le as layoutShape,
488
- Fe as lintLayout,
489
- Oe as mergeInherited
715
+ be as CONTRAST_MIN,
716
+ Ze as DEFAULT_JARGON,
717
+ Pe as DEFAULT_MAX_LABEL_LENGTH,
718
+ lt as EMPTY_LINT_CONTEXT,
719
+ Se as HEALTH_FIELD_LIMIT,
720
+ Le as HEALTH_STEP_LIMIT,
721
+ $e as MAX_LABEL_LENGTH_RANGE,
722
+ st as STYLE_POINTS_MAX,
723
+ pe as STYLE_RULES,
724
+ He as colourContrast,
725
+ me as conditionsContradict,
726
+ ke as contrastRatio,
727
+ Xe as findJargon,
728
+ Qe as helpRepeatsLabel,
729
+ nt as isFormLayout,
730
+ ut as layoutHealth,
731
+ rt as layoutShape,
732
+ at as lintLayout,
733
+ it as mergeInherited,
734
+ et as resolveStyle,
735
+ Je as toSentenceCase
490
736
  };