@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,28 +1,28 @@
1
1
  import { isCanvasSlot as a, UNGROUPED_KEY as x, HEADER_GROUP_KEY as v } from "../../lib/layout-ops.js";
2
2
  import { titleCase as b } from "../../lib/utils.js";
3
3
  import { normalizedBundle as A, fieldZones as R, zoneItems as w } from "./field-zones.js";
4
- import { pinLocked as $, pinnedZone as E } from "./pin.js";
4
+ import { pinLocked as $, pinnedZone as E, isPlacementPinned as I } from "./pin.js";
5
5
  const Z = {
6
6
  ArrowUp: "up",
7
7
  ArrowDown: "down",
8
8
  ArrowLeft: "left",
9
9
  ArrowRight: "right"
10
10
  }, u = (r) => r === "up" || r === "left" ? -1 : 1;
11
- function I(r, e) {
11
+ function D(r, e) {
12
12
  return [
13
13
  ...r.groups.filter((n) => n.parent_key === e).map((n) => ({ key: n.key, sort: n.sort })),
14
14
  ...e === null ? r.placements.filter((n) => a(n)).map((n) => ({ key: n.field, sort: n.sort })) : []
15
15
  ].sort((n, l) => n.sort - l.sort).map((n) => n.key);
16
16
  }
17
- function D(r, e) {
17
+ function M(r, e) {
18
18
  if (e === x) return "ungrouped fields";
19
19
  const o = r.groups.find((n) => n.key === e);
20
20
  return o ? `${o.type === "tab" ? "tab" : "section"} "${o.label || b(o.key)}"` : "panel";
21
21
  }
22
22
  function _(r, e, o, n) {
23
- const l = w(r, o), p = l.findIndex((d) => d.field === e.field), i = p + u(n);
24
- return p < 0 || i < 0 || i >= l.length ? null : {
25
- ops: [{ op: "move", from: { field: e.field, group_key: o }, to_group_key: o, index: i }],
23
+ const l = w(r, o), p = l.findIndex((d) => d.field === e.field), t = p + u(n);
24
+ return p < 0 || t < 0 || t >= l.length || I(l[t]) ? null : {
25
+ ops: [{ op: "move", from: { field: e.field, group_key: o }, to_group_key: o, index: t }],
26
26
  label: `Move ${e.kind === "header" ? "header tile" : "field"} ${u(n) < 0 ? "up" : "down"}`,
27
27
  next: e
28
28
  };
@@ -33,12 +33,12 @@ function C(r, e, o) {
33
33
  if (e.kind === "header") return _(n, e, v, o);
34
34
  if ((e.kind === "field" || e.kind === "slot") && !a(e)) {
35
35
  const s = e.group_key;
36
- if (!n.placements.some((t) => t.field === e.field && t.group_key === s)) return null;
36
+ if (!n.placements.some((i) => i.field === e.field && i.group_key === s)) return null;
37
37
  if (o === "up" || o === "down") return _(n, e, s, o);
38
- const c = R(n), g = c.findIndex((t) => t.key === s);
38
+ const c = R(n), g = c.findIndex((i) => i.key === s);
39
39
  if (g < 0) return null;
40
- for (let t = g + u(o); t >= 0 && t < c.length; t += u(o)) {
41
- const f = c[t];
40
+ for (let i = g + u(o); i >= 0 && i < c.length; i += u(o)) {
41
+ const f = c[i];
42
42
  if (n.placements.some((m) => m.field === e.field && m.group_key === f.key) || E(n, f.key) || a({ field: e.field, group_key: f.key })) continue;
43
43
  const h = o === "left" ? w(n, f.key).length : 0;
44
44
  return {
@@ -51,12 +51,12 @@ function C(r, e, o) {
51
51
  }
52
52
  return null;
53
53
  }
54
- const l = e.kind === "group" ? e.key : e.field, p = n.groups.find((s) => s.key === l), i = p ? p.parent_key : null;
55
- if ((o === "left" || o === "right") && i === null) return null;
56
- const d = I(n, i), y = d.indexOf(l), k = y + u(o);
54
+ const l = e.kind === "group" ? e.key : e.field, p = n.groups.find((s) => s.key === l), t = p ? p.parent_key : null;
55
+ if ((o === "left" || o === "right") && t === null) return null;
56
+ const d = D(n, t), y = d.indexOf(l), k = y + u(o);
57
57
  return y < 0 || k < 0 || k >= d.length ? null : {
58
- ops: [{ op: "group_move", key: l, parent_key: i, index: k }],
59
- label: `Move ${e.kind === "group" ? D(n, l) : "panel"} ${i === null ? u(o) < 0 ? "up" : "down" : u(o) < 0 ? "left" : "right"}`,
58
+ ops: [{ op: "group_move", key: l, parent_key: t, index: k }],
59
+ label: `Move ${e.kind === "group" ? M(n, l) : "panel"} ${t === null ? u(o) < 0 ? "up" : "down" : u(o) < 0 ? "left" : "right"}`,
60
60
  next: e
61
61
  };
62
62
  }
@@ -0,0 +1,201 @@
1
+ import { jsx as n, jsxs as r } from "react/jsx-runtime";
2
+ import { ChevronRight as F } from "lucide-react";
3
+ import { useMemo as R, useState as y, useId as w, useEffect as L } from "react";
4
+ import { toast as _ } from "sonner";
5
+ import { STYLE_RULES as C, DEFAULT_MAX_LABEL_LENGTH as A, MAX_LABEL_LENGTH_RANGE as u, DEFAULT_JARGON as D } from "../../../lib/layout-lint.js";
6
+ import { cn as f } from "../../../lib/utils.js";
7
+ import { groupTitle as G, effectText as m, labelText as b, inputBase as v } from "../panel-style.js";
8
+ import { Toggle as H } from "../settings/controls.js";
9
+ import { useLintStyle as M, useSaveLintStyle as B, EMPTY_LINT_STYLE as I } from "./lint-api.js";
10
+ const N = {
11
+ "label-sentence-case": {
12
+ label: "Sentence case",
13
+ effect: "Only the first word of a label starts with a capital."
14
+ },
15
+ "label-too-long": {
16
+ label: "Short labels",
17
+ effect: "Labels past the limit move detail into help."
18
+ },
19
+ "label-jargon": {
20
+ label: "No abbreviations",
21
+ effect: "Qty, Amt, Dept and the like are spelled out."
22
+ },
23
+ "help-repeats-label": {
24
+ label: "Help says something new",
25
+ effect: "Help text that only repeats the label is flagged."
26
+ },
27
+ "label-duplicate": {
28
+ label: "One label per field",
29
+ effect: "Two fields on one form never share a label."
30
+ }
31
+ };
32
+ function J(e) {
33
+ return C.includes(e);
34
+ }
35
+ function U(e) {
36
+ const a = [], s = /* @__PURE__ */ new Set();
37
+ for (const o of e.split(`
38
+ `)) {
39
+ const t = /^\s*(.+?)\s*(?:=|→|->)\s*(.+?)\s*$/.exec(o);
40
+ !t || s.has(t[1].toLowerCase()) || (s.add(t[1].toLowerCase()), a.push({ term: t[1], say: t[2] }));
41
+ }
42
+ return a;
43
+ }
44
+ function g(e) {
45
+ return e.map((a) => `${a.term} = ${a.say}`).join(`
46
+ `);
47
+ }
48
+ function le(e = !0) {
49
+ const { data: a } = M(e), { mutate: s } = B();
50
+ return R(
51
+ () => ({
52
+ onTurnOff: (o) => {
53
+ if (!J(o)) return;
54
+ const t = [.../* @__PURE__ */ new Set([...(a == null ? void 0 : a.off) ?? [], o])];
55
+ s(
56
+ { off: t },
57
+ {
58
+ onSuccess: () => _.success(`${N[o].label} is off for every form here`),
59
+ onError: () => _.error("That check could not be turned off")
60
+ }
61
+ );
62
+ },
63
+ settings: /* @__PURE__ */ n(Y, {})
64
+ }),
65
+ [a == null ? void 0 : a.off, s]
66
+ );
67
+ }
68
+ function Y() {
69
+ const [e, a] = y(!1), s = w(), { data: o = I, isLoading: t } = M(e), i = B(), h = (d) => i.mutate(d, { onError: () => _.error("The label style was not saved") });
70
+ return /* @__PURE__ */ r("section", { "aria-label": "Label style", "data-label-style": "", className: "space-y-2", children: [
71
+ /* @__PURE__ */ r(
72
+ "button",
73
+ {
74
+ type: "button",
75
+ "aria-expanded": e,
76
+ "aria-controls": s,
77
+ onClick: () => a(!e),
78
+ className: "flex w-full items-center gap-1 rounded-md text-left transition-colors hover:text-slate-900 dark:hover:text-foreground",
79
+ children: [
80
+ /* @__PURE__ */ n(
81
+ F,
82
+ {
83
+ className: f(
84
+ "h-3.5 w-3.5 text-slate-400 transition-transform motion-reduce:transition-none",
85
+ e && "rotate-90"
86
+ )
87
+ }
88
+ ),
89
+ /* @__PURE__ */ n("span", { className: G, children: "Label style" })
90
+ ]
91
+ }
92
+ ),
93
+ e && /* @__PURE__ */ r("div", { id: s, className: "space-y-3", children: [
94
+ /* @__PURE__ */ n("p", { className: m, children: "Checks every form on this instance against house style. Turning a check off here turns it off for everyone." }),
95
+ t ? /* @__PURE__ */ n("p", { className: m, children: "Loading…" }) : /* @__PURE__ */ n(P, { data: o, commit: h, busy: i.isPending })
96
+ ] })
97
+ ] });
98
+ }
99
+ function P({
100
+ data: e,
101
+ commit: a,
102
+ busy: s
103
+ }) {
104
+ const o = { max: w(), allow: w(), jargon: w() }, t = new Set(e.off), [i, h] = y(String(e.max_label_length ?? "")), [d, S] = y(e.allow_words.join(", ")), [j, E] = y(g(e.jargon));
105
+ L(() => h(String(e.max_label_length ?? "")), [e.max_label_length]), L(() => S(e.allow_words.join(", ")), [e.allow_words]), L(() => E(g(e.jargon)), [e.jargon]);
106
+ const c = i.trim() === "" ? null : Number(i), p = c != null && (!Number.isInteger(c) || c < u[0] || c > u[1]), T = () => {
107
+ p || c === e.max_label_length || a({ max_label_length: c });
108
+ }, k = () => {
109
+ const l = [
110
+ ...new Set(
111
+ d.split(",").map((x) => x.trim()).filter(Boolean)
112
+ )
113
+ ];
114
+ l.join("\0") !== e.allow_words.join("\0") && a({ allow_words: l });
115
+ }, O = () => {
116
+ const l = U(j);
117
+ g(l) !== g(e.jargon) && a({ jargon: l });
118
+ };
119
+ return /* @__PURE__ */ r("div", { className: "space-y-3", children: [
120
+ /* @__PURE__ */ n("ul", { className: "space-y-2.5", children: C.map((l) => /* @__PURE__ */ r("li", { "data-style-rule": l, className: "flex items-start justify-between gap-3", children: [
121
+ /* @__PURE__ */ r("span", { className: "min-w-0", children: [
122
+ /* @__PURE__ */ n("span", { className: f(b, "block"), children: N[l].label }),
123
+ /* @__PURE__ */ n("span", { className: f(m, "block"), children: N[l].effect })
124
+ ] }),
125
+ /* @__PURE__ */ n(
126
+ H,
127
+ {
128
+ label: N[l].label,
129
+ checked: !t.has(l),
130
+ disabled: s,
131
+ onChange: (x) => a({
132
+ off: x ? e.off.filter(($) => $ !== l) : [.../* @__PURE__ */ new Set([...e.off, l])]
133
+ })
134
+ }
135
+ )
136
+ ] }, l)) }),
137
+ /* @__PURE__ */ r("div", { className: "space-y-1", children: [
138
+ /* @__PURE__ */ n("label", { htmlFor: o.max, className: b, children: "Longest label" }),
139
+ /* @__PURE__ */ n(
140
+ "input",
141
+ {
142
+ id: o.max,
143
+ inputMode: "numeric",
144
+ value: i,
145
+ placeholder: String(A),
146
+ "aria-invalid": p || void 0,
147
+ onChange: (l) => h(l.target.value),
148
+ onBlur: T,
149
+ onKeyDown: (l) => l.key === "Enter" && T(),
150
+ className: f(v, "w-24", p && "border-red-400 dark:border-red-500")
151
+ }
152
+ ),
153
+ /* @__PURE__ */ n("p", { className: m, children: p ? `A whole number from ${u[0]} to ${u[1]}.` : `Characters. Empty = ${A}.` })
154
+ ] }),
155
+ /* @__PURE__ */ r("div", { className: "space-y-1", children: [
156
+ /* @__PURE__ */ n("label", { htmlFor: o.allow, className: b, children: "Words that keep their capital" }),
157
+ /* @__PURE__ */ n(
158
+ "input",
159
+ {
160
+ id: o.allow,
161
+ value: d,
162
+ placeholder: "Fusion, Oracle",
163
+ onChange: (l) => S(l.target.value),
164
+ onBlur: k,
165
+ onKeyDown: (l) => l.key === "Enter" && k(),
166
+ className: v
167
+ }
168
+ ),
169
+ /* @__PURE__ */ n("p", { className: m, children: "Names, comma between. They are never called jargon either." })
170
+ ] }),
171
+ /* @__PURE__ */ r("div", { className: "space-y-1", children: [
172
+ /* @__PURE__ */ n("label", { htmlFor: o.jargon, className: b, children: "More abbreviations" }),
173
+ /* @__PURE__ */ n(
174
+ "textarea",
175
+ {
176
+ id: o.jargon,
177
+ value: j,
178
+ rows: 3,
179
+ placeholder: "PM = project manager",
180
+ onChange: (l) => E(l.target.value),
181
+ onBlur: O,
182
+ className: f(v, "h-auto py-1.5 font-mono text-[12px]")
183
+ }
184
+ ),
185
+ /* @__PURE__ */ r("p", { className: m, children: [
186
+ "One per line, the word and what to say instead. Checked already:",
187
+ " ",
188
+ D.slice(0, 8).map((l) => l.term).join(", "),
189
+ "…"
190
+ ] })
191
+ ] })
192
+ ] });
193
+ }
194
+ export {
195
+ Y as LabelStyleSettings,
196
+ N as STYLE_RULE_NAMES,
197
+ J as isStyleRule,
198
+ g as jargonLines,
199
+ U as parseJargonLines,
200
+ le as useLabelStyleControls
201
+ };
@@ -1,68 +1,81 @@
1
1
  import { jsxs as a, jsx as r } from "react/jsx-runtime";
2
- import { CircleAlert as k, CheckCircle2 as h, Sparkles as w, Info as y, AlertTriangle as v, AlertCircle as C } from "lucide-react";
2
+ import { CircleAlert as C, CheckCircle2 as k, Sparkles as $, Info as B, AlertTriangle as T, AlertCircle as I } from "lucide-react";
3
3
  import { cn as c } from "../../../lib/utils.js";
4
- import { PanelHeader as T, PanelBody as $ } from "../panel-frame.js";
5
- import { groupTitle as b, effectText as x } from "../panel-style.js";
6
- import { barBtnOn as I, barBtn as P } from "../toolbar-kit.js";
7
- import { findingDesignTarget as B } from "./lint-api.js";
8
- const j = [
4
+ import { PanelHeader as P, PanelBody as S } from "../panel-frame.js";
5
+ import { groupTitle as N, effectText as p } from "../panel-style.js";
6
+ import { barBtnOn as j, barBtn as A } from "../toolbar-kit.js";
7
+ import { isStyleRule as H } from "./LabelStyle.js";
8
+ import { findingDesignTarget as E } from "./lint-api.js";
9
+ const q = [
9
10
  { severity: "error", title: "Errors" },
10
11
  { severity: "warn", title: "Warnings" },
11
12
  { severity: "info", title: "Tips" }
12
- ], A = {
13
- error: C,
14
- warn: v,
15
- info: y
16
- }, O = {
13
+ ], F = {
14
+ error: I,
15
+ warn: T,
16
+ info: B
17
+ }, L = {
17
18
  error: "text-red-600 dark:text-red-400",
18
19
  warn: "text-amber-600 dark:text-amber-400",
19
20
  info: "text-slate-500 dark:text-muted-foreground"
20
21
  };
21
- function S(e) {
22
+ function D(e) {
22
23
  return e >= 80 ? "bg-emerald-50 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-300" : e >= 60 ? "bg-amber-50 text-amber-700 dark:bg-amber-500/15 dark:text-amber-300" : "bg-red-50 text-red-700 dark:bg-red-500/15 dark:text-red-300";
23
24
  }
24
- function f(e) {
25
- const t = (n) => e.filter((s) => s.severity === n).length;
25
+ function w(e) {
26
+ const t = (s) => e.filter((l) => l.severity === s).length;
26
27
  return { error: t("error"), warn: t("warn"), info: t("info") };
27
28
  }
28
- function G({
29
+ function X({
29
30
  findings: e,
30
31
  active: t,
31
- onClick: n
32
+ onClick: s
32
33
  }) {
33
- const s = f(e), o = s.error + s.warn;
34
+ const l = w(e), n = l.error + l.warn;
34
35
  return /* @__PURE__ */ a(
35
36
  "button",
36
37
  {
37
38
  type: "button",
38
- onClick: n,
39
+ onClick: s,
39
40
  "aria-pressed": t,
40
- "aria-label": `Problems: ${s.error} errors, ${s.warn} warnings`,
41
+ "aria-label": `Problems: ${l.error} errors, ${l.warn} warnings`,
41
42
  "data-editor-checks": "",
42
- "data-tip": "Problems this form has: hidden required fields, missing cascade parents, empty steps, unreachable fields and accessibility",
43
- className: c(P, "gap-1 px-2", t && I),
43
+ "data-tip": "Problems this form has: hidden required fields, missing cascade parents, empty steps, unreachable fields, accessibility and label style",
44
+ className: c(A, "gap-1 px-2", t && j),
44
45
  children: [
45
46
  /* @__PURE__ */ r(
46
- k,
47
+ C,
47
48
  {
48
49
  className: c(
49
50
  "h-3.5 w-3.5",
50
- s.error > 0 ? "text-red-600 dark:text-red-400" : o > 0 ? "text-amber-600 dark:text-amber-400" : "text-slate-500 dark:text-muted-foreground"
51
+ l.error > 0 ? "text-red-600 dark:text-red-400" : n > 0 ? "text-amber-600 dark:text-amber-400" : "text-slate-500 dark:text-muted-foreground"
51
52
  )
52
53
  }
53
54
  ),
54
- o > 0 ? /* @__PURE__ */ r("span", { "data-checks-count": o, className: "tabular-nums", children: o }) : /* @__PURE__ */ r(h, { className: "h-3.5 w-3.5 text-emerald-600 dark:text-emerald-400" })
55
+ n > 0 ? /* @__PURE__ */ r("span", { "data-checks-count": n, className: "tabular-nums", children: n }) : /* @__PURE__ */ r(k, { className: "h-3.5 w-3.5 text-emerald-600 dark:text-emerald-400" })
55
56
  ]
56
57
  }
57
58
  );
58
59
  }
59
- function E({
60
+ const f = "inline-flex h-6 items-center rounded px-1.5 text-[12px] font-medium text-slate-700 transition-colors hover:bg-muted hover:text-slate-900 dark:text-foreground";
61
+ function M(e) {
62
+ const t = e.filter((s) => s.rule === "label-sentence-case" && s.fix);
63
+ return t.length < 2 ? null : {
64
+ ops: t.flatMap((s) => {
65
+ var l;
66
+ return ((l = s.fix) == null ? void 0 : l.ops) ?? [];
67
+ }),
68
+ count: t.length
69
+ };
70
+ }
71
+ function R({
60
72
  finding: e,
61
73
  onSelect: t,
62
- apply: n,
63
- readOnly: s
74
+ apply: s,
75
+ readOnly: l,
76
+ onTurnOff: n
64
77
  }) {
65
- const o = A[e.severity], i = B(e);
78
+ const m = !!n && H(e.rule), u = F[e.severity], d = E(e);
66
79
  return /* @__PURE__ */ a(
67
80
  "li",
68
81
  {
@@ -73,57 +86,75 @@ function E({
73
86
  "button",
74
87
  {
75
88
  type: "button",
76
- disabled: !i,
77
- onClick: () => i && t(i),
89
+ disabled: !d,
90
+ onClick: () => d && t(d),
78
91
  className: "flex w-full items-start gap-2 rounded-md px-2.5 py-2 text-left transition-colors hover:bg-muted disabled:cursor-default disabled:hover:bg-transparent",
79
- "data-tip": i ? "Select it on the form" : void 0,
92
+ "data-tip": d ? "Select it on the form" : void 0,
80
93
  children: [
81
- /* @__PURE__ */ r(o, { className: c("mt-0.5 h-3.5 w-3.5 shrink-0", O[e.severity]) }),
94
+ /* @__PURE__ */ r(u, { className: c("mt-0.5 h-3.5 w-3.5 shrink-0", L[e.severity]) }),
82
95
  /* @__PURE__ */ r("span", { className: "min-w-0 text-[12.5px] leading-snug text-slate-700 dark:text-foreground", children: e.message })
83
96
  ]
84
97
  }
85
98
  ),
86
- e.fix && !s && /* @__PURE__ */ r("div", { className: "border-t border-slate-100 px-2.5 py-1.5 dark:border-border", children: /* @__PURE__ */ r(
87
- "button",
88
- {
89
- type: "button",
90
- "data-lint-fix": "",
91
- onClick: () => e.fix && n(e.fix.ops, { label: e.fix.label }),
92
- className: "inline-flex h-6 items-center rounded px-1.5 text-[12px] font-medium text-slate-700 transition-colors hover:bg-muted hover:text-slate-900 dark:text-foreground",
93
- children: e.fix.label
94
- }
95
- ) })
99
+ (e.fix && !l || m) && /* @__PURE__ */ a("div", { className: "flex flex-wrap items-center gap-x-1 border-t border-slate-100 px-2.5 py-1.5 dark:border-border", children: [
100
+ e.fix && !l && /* @__PURE__ */ r(
101
+ "button",
102
+ {
103
+ type: "button",
104
+ "data-lint-fix": "",
105
+ onClick: () => e.fix && s(e.fix.ops, { label: e.fix.label }),
106
+ className: f,
107
+ children: e.fix.label
108
+ }
109
+ ),
110
+ m && /* @__PURE__ */ r(
111
+ "button",
112
+ {
113
+ type: "button",
114
+ "data-lint-turn-off": e.rule,
115
+ "data-tip": "House style for every form on this instance",
116
+ onClick: () => n == null ? void 0 : n(e.rule),
117
+ className: c(
118
+ f,
119
+ "ml-auto font-normal text-slate-500 dark:text-muted-foreground"
120
+ ),
121
+ children: "Turn off this check"
122
+ }
123
+ )
124
+ ] })
96
125
  ]
97
126
  }
98
127
  );
99
128
  }
100
- function J({
129
+ function Y({
101
130
  findings: e,
102
131
  health: t,
103
- ready: n,
104
- onSelect: s,
105
- apply: o,
106
- onOpenAiReview: i,
107
- readOnly: g = !1
132
+ ready: s,
133
+ onSelect: l,
134
+ apply: n,
135
+ onOpenAiReview: m,
136
+ readOnly: u = !1,
137
+ onTurnOff: d,
138
+ styleSettings: y
108
139
  }) {
109
- const l = f(e), N = e.length === 0 ? n ? "Nothing to fix" : "Checking…" : [
110
- l.error && `${l.error} ${l.error === 1 ? "problem" : "problems"}`,
111
- l.warn && `${l.warn} ${l.warn === 1 ? "warning" : "warnings"}`,
112
- l.info && `${l.info} ${l.info === 1 ? "suggestion" : "suggestions"}`
140
+ const o = w(e), b = u ? null : M(e), v = e.length === 0 ? s ? "Nothing to fix" : "Checking…" : [
141
+ o.error && `${o.error} ${o.error === 1 ? "problem" : "problems"}`,
142
+ o.warn && `${o.warn} ${o.warn === 1 ? "warning" : "warnings"}`,
143
+ o.info && `${o.info} ${o.info === 1 ? "suggestion" : "suggestions"}`
113
144
  ].filter(Boolean).join(" · ");
114
145
  return /* @__PURE__ */ a("div", { "data-lint-panel": "", className: "flex min-h-0 flex-1 flex-col", children: [
115
- /* @__PURE__ */ r(T, { eyebrow: "Form", title: "Problems", sub: N }),
116
- /* @__PURE__ */ a($, { children: [
146
+ /* @__PURE__ */ r(P, { eyebrow: "Form", title: "Problems", sub: v }),
147
+ /* @__PURE__ */ a(S, { children: [
117
148
  t && /* @__PURE__ */ a("section", { "aria-label": "Health", className: "space-y-1.5", children: [
118
149
  /* @__PURE__ */ a("div", { className: "flex items-center gap-2", children: [
119
- /* @__PURE__ */ r("h3", { className: b, children: "Health" }),
150
+ /* @__PURE__ */ r("h3", { className: N, children: "Health" }),
120
151
  /* @__PURE__ */ a(
121
152
  "span",
122
153
  {
123
154
  "data-health-score": t.score,
124
155
  className: c(
125
156
  "rounded-full px-2 py-px text-[11.5px] font-semibold tabular-nums",
126
- S(t.score)
157
+ D(t.score)
127
158
  ),
128
159
  children: [
129
160
  t.score,
@@ -132,48 +163,64 @@ function J({
132
163
  }
133
164
  )
134
165
  ] }),
135
- t.costs.length > 0 ? /* @__PURE__ */ r("ul", { className: "space-y-0.5", children: t.costs.map((d) => /* @__PURE__ */ a("li", { className: c(x, "flex justify-between gap-2"), children: [
136
- /* @__PURE__ */ r("span", { children: d.label }),
166
+ t.costs.length > 0 ? /* @__PURE__ */ r("ul", { className: "space-y-0.5", children: t.costs.map((i) => /* @__PURE__ */ a("li", { className: c(p, "flex justify-between gap-2"), children: [
167
+ /* @__PURE__ */ r("span", { children: i.label }),
137
168
  /* @__PURE__ */ a("span", { className: "tabular-nums", children: [
138
169
  "−",
139
- d.points
170
+ i.points
140
171
  ] })
141
- ] }, d.label)) }) : /* @__PURE__ */ r("p", { className: x, children: "Nothing costs this form points." })
172
+ ] }, i.label)) }) : /* @__PURE__ */ r("p", { className: p, children: "Nothing costs this form points." })
142
173
  ] }),
143
- e.length === 0 && n && /* @__PURE__ */ a("p", { className: c(x, "flex items-center gap-1.5"), children: [
144
- /* @__PURE__ */ r(h, { className: "h-3.5 w-3.5 text-emerald-600 dark:text-emerald-400" }),
174
+ e.length === 0 && s && /* @__PURE__ */ a("p", { className: c(p, "flex items-center gap-1.5"), children: [
175
+ /* @__PURE__ */ r(k, { className: "h-3.5 w-3.5 text-emerald-600 dark:text-emerald-400" }),
145
176
  "No problems found on this form."
146
177
  ] }),
147
- j.map(({ severity: d, title: p }) => {
148
- const u = e.filter((m) => m.severity === d);
149
- return u.length === 0 ? null : /* @__PURE__ */ a("section", { "aria-label": p, className: "space-y-1.5", children: [
150
- /* @__PURE__ */ a("h3", { className: b, children: [
151
- p,
178
+ q.map(({ severity: i, title: g }) => {
179
+ const h = e.filter((x) => x.severity === i);
180
+ return h.length === 0 ? null : /* @__PURE__ */ a("section", { "aria-label": g, className: "space-y-1.5", children: [
181
+ /* @__PURE__ */ a("h3", { className: N, children: [
182
+ g,
152
183
  " ",
153
- /* @__PURE__ */ r("span", { className: "font-normal text-slate-500 dark:text-muted-foreground", children: u.length })
184
+ /* @__PURE__ */ r("span", { className: "font-normal text-slate-500 dark:text-muted-foreground", children: h.length })
154
185
  ] }),
155
- /* @__PURE__ */ r("ul", { className: "space-y-1.5", children: u.map((m) => /* @__PURE__ */ r(
156
- E,
186
+ i === "info" && b && /* @__PURE__ */ a(
187
+ "button",
188
+ {
189
+ type: "button",
190
+ "data-lint-fix-all": "label-sentence-case",
191
+ onClick: () => n(b.ops, { label: `Change ${b.count} labels to sentence case` }),
192
+ className: c(f, "h-7 border border-slate-200 dark:border-border"),
193
+ children: [
194
+ "Change all ",
195
+ b.count,
196
+ " labels to sentence case"
197
+ ]
198
+ }
199
+ ),
200
+ /* @__PURE__ */ r("ul", { className: "space-y-1.5", children: h.map((x) => /* @__PURE__ */ r(
201
+ R,
157
202
  {
158
- finding: m,
159
- onSelect: s,
160
- apply: o,
161
- readOnly: g
203
+ finding: x,
204
+ onSelect: l,
205
+ apply: n,
206
+ readOnly: u,
207
+ onTurnOff: d
162
208
  },
163
- m.id
209
+ x.id
164
210
  )) })
165
- ] }, d);
211
+ ] }, i);
166
212
  }),
167
- i && /* @__PURE__ */ a("div", { className: "space-y-1", children: [
168
- /* @__PURE__ */ r("p", { className: x, children: "These checks are counted, not guessed. The AI review also reads labels and help text." }),
213
+ y,
214
+ m && /* @__PURE__ */ a("div", { className: "space-y-1", children: [
215
+ /* @__PURE__ */ r("p", { className: p, children: "These checks are counted, not guessed. The AI review also reads labels and help text." }),
169
216
  /* @__PURE__ */ a(
170
217
  "button",
171
218
  {
172
219
  type: "button",
173
- onClick: i,
220
+ onClick: m,
174
221
  className: "inline-flex h-7 items-center gap-1.5 rounded-md px-1.5 text-[12px] font-medium text-slate-700 transition-colors hover:bg-muted hover:text-slate-900 dark:text-foreground",
175
222
  children: [
176
- /* @__PURE__ */ r(w, { className: "h-3.5 w-3.5" }),
223
+ /* @__PURE__ */ r($, { className: "h-3.5 w-3.5" }),
177
224
  "Open the AI review"
178
225
  ]
179
226
  }
@@ -183,8 +230,9 @@ function J({
183
230
  ] });
184
231
  }
185
232
  export {
186
- G as LintButton,
187
- J as LintPanel,
188
- f as lintCounts,
189
- S as scoreTone
233
+ X as LintButton,
234
+ Y as LintPanel,
235
+ w as lintCounts,
236
+ D as scoreTone,
237
+ M as sentenceCaseBatch
190
238
  };