@nivaro/react 0.3.35 → 0.3.37

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 (106) 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 +13 -4
  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 -572
  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 +11 -10
  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 +80 -63
  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 +146 -131
  25. package/dist/shared/components/layout-editor/EditorCanvas.js +25 -17
  26. package/dist/shared/components/layout-editor/EditorTopBar.js +268 -206
  27. package/dist/shared/components/layout-editor/LayoutEditor.js +810 -731
  28. package/dist/shared/components/layout-editor/PlaceTools.js +334 -0
  29. package/dist/shared/components/layout-editor/SlashInsert.js +252 -0
  30. package/dist/shared/components/layout-editor/StructureMenu.js +285 -242
  31. package/dist/shared/components/layout-editor/add-target.js +54 -43
  32. package/dist/shared/components/layout-editor/ai-forms/AiComposer.js +238 -155
  33. package/dist/shared/components/layout-editor/ai-forms/AiFormsButton.js +1 -1
  34. package/dist/shared/components/layout-editor/ai-forms/ai-forms-api.js +15 -12
  35. package/dist/shared/components/layout-editor/dnd/LayoutDndProvider.js +379 -185
  36. package/dist/shared/components/layout-editor/dnd/TrashZone.js +96 -0
  37. package/dist/shared/components/layout-editor/dnd/UndoChip.js +76 -0
  38. package/dist/shared/components/layout-editor/dnd/merge-drop.js +33 -0
  39. package/dist/shared/components/layout-editor/dnd/multi-drop.js +87 -0
  40. package/dist/shared/components/layout-editor/dnd/node.js +115 -105
  41. package/dist/shared/components/layout-editor/dnd/rail-drop.js +4 -4
  42. package/dist/shared/components/layout-editor/dnd/sensors.js +23 -0
  43. package/dist/shared/components/layout-editor/dnd/trash-drop.js +58 -0
  44. package/dist/shared/components/layout-editor/dnd/trash-links.js +97 -0
  45. package/dist/shared/components/layout-editor/even-row.js +86 -0
  46. package/dist/shared/components/layout-editor/field-list.js +99 -0
  47. package/dist/shared/components/layout-editor/format-painter.js +102 -0
  48. package/dist/shared/components/layout-editor/grid-guides.js +15 -13
  49. package/dist/shared/components/layout-editor/inspector/BehaviourSettings.js +150 -132
  50. package/dist/shared/components/layout-editor/inspector/BulkInspector.js +57 -53
  51. package/dist/shared/components/layout-editor/inspector/EvenRowAction.js +31 -0
  52. package/dist/shared/components/layout-editor/inspector/GroupInspector.js +154 -141
  53. package/dist/shared/components/layout-editor/inspector/Inspector.js +209 -178
  54. package/dist/shared/components/layout-editor/inspector/LookTab.js +106 -98
  55. package/dist/shared/components/layout-editor/inspector/RulesTab.js +38 -37
  56. package/dist/shared/components/layout-editor/inspector/kit.js +280 -223
  57. package/dist/shared/components/layout-editor/keyboard-move.js +15 -15
  58. package/dist/shared/components/layout-editor/lint/LabelStyle.js +201 -0
  59. package/dist/shared/components/layout-editor/lint/LintPanel.js +132 -84
  60. package/dist/shared/components/layout-editor/lint/lint-api.js +65 -28
  61. package/dist/shared/components/layout-editor/nav/NavTools.js +14 -12
  62. package/dist/shared/components/layout-editor/nav/ZoomControls.js +145 -0
  63. package/dist/shared/components/layout-editor/nav/useEditorNav.js +34 -32
  64. package/dist/shared/components/layout-editor/nav/view-prefs.js +100 -15
  65. package/dist/shared/components/layout-editor/outputs/LayoutFile.js +89 -0
  66. package/dist/shared/components/layout-editor/outputs/OutputsButton.js +272 -195
  67. package/dist/shared/components/layout-editor/outputs/layout-file-plan.js +176 -0
  68. package/dist/shared/components/layout-editor/outputs/output-api.js +71 -37
  69. package/dist/shared/components/layout-editor/overview/describe-conditions.js +16 -11
  70. package/dist/shared/components/layout-editor/overview/purpose.js +5 -5
  71. package/dist/shared/components/layout-editor/panel-frame.js +1 -1
  72. package/dist/shared/components/layout-editor/parity-keys.json.js +1 -1
  73. package/dist/shared/components/layout-editor/personal-default-marks.js +40 -0
  74. package/dist/shared/components/layout-editor/pin.js +37 -19
  75. package/dist/shared/components/layout-editor/place-clip.js +257 -0
  76. package/dist/shared/components/layout-editor/preview/PreviewModes.js +27 -26
  77. package/dist/shared/components/layout-editor/preview/PreviewPanes.js +149 -118
  78. package/dist/shared/components/layout-editor/preview/SampleRecord.js +113 -0
  79. package/dist/shared/components/layout-editor/preview/preview-model.js +79 -60
  80. package/dist/shared/components/layout-editor/preview/sample-record.js +105 -0
  81. package/dist/shared/components/layout-editor/removed-log.js +151 -0
  82. package/dist/shared/components/layout-editor/reuse/LibraryRows.js +109 -78
  83. package/dist/shared/components/layout-editor/reuse/linked-sections.js +373 -0
  84. package/dist/shared/components/layout-editor/revert-element.js +140 -0
  85. package/dist/shared/components/layout-editor/section-structure.js +193 -170
  86. package/dist/shared/components/layout-editor/settings/EntrySection.js +63 -45
  87. package/dist/shared/components/layout-editor/settings/LayoutSection.js +63 -32
  88. package/dist/shared/components/layout-editor/settings/ResolveSettings.js +179 -137
  89. package/dist/shared/components/layout-editor/settings/WhoSection.js +18 -17
  90. package/dist/shared/components/layout-editor/settings/settings-registry.js +24 -0
  91. package/dist/shared/components/layout-editor/shortcuts.js +21 -16
  92. package/dist/shared/components/layout-editor/structure-ops.js +221 -195
  93. package/dist/shared/components/layout-editor/usage/UsagePanel.js +133 -85
  94. package/dist/shared/components/layout-editor/usage/refusal-lens.js +130 -0
  95. package/dist/shared/components/layout-editor/usage/usage-api.js +12 -11
  96. package/dist/shared/components/panels/CommentPanel.js +47 -45
  97. package/dist/shared/components/panels/RevisionsPanel.js +66 -64
  98. package/dist/shared/components/panels/TaskPanel.js +395 -332
  99. package/dist/shared/components/profile/AgentsPanel.js +196 -147
  100. package/dist/shared/components/profile/ConnectionRollback.js +329 -0
  101. package/dist/shared/components/profile/MyDefaultsCard.js +526 -520
  102. package/dist/shared/lib/entry-config.js +22 -22
  103. package/dist/shared/lib/form-usage-beacon.js +91 -55
  104. package/dist/shared/lib/layout-lint.js +530 -284
  105. package/dist/shared/lib/layout-resolve.js +58 -44
  106. package/package.json +1 -1
@@ -1,75 +1,75 @@
1
- import { jsx as t, jsxs as r } from "react/jsx-runtime";
2
- import { useQueryClient as W } from "@tanstack/react-query";
3
- import { Lock as O, Smartphone as P } from "lucide-react";
4
- import { useState as x, useEffect as A } from "react";
5
- import { toast as q } from "sonner";
6
- import { useItemEditAuth as D, useNivaroClient as M } from "../../../context.js";
7
- import { post as R, patch as T } from "../../../lib/commands.js";
8
- import { freezeOf as U, activeFreeze as _, localDay as S, dayWords as k, freezePatch as E, activeWindowOf as j, windowState as B, windowWords as Q, phoneOf as L, phoneOfPatch as V, activeWindowPatch as G, conditionsWithKey as H } from "../../../lib/layout-resolve.js";
1
+ import { jsx as t, jsxs as l } from "react/jsx-runtime";
2
+ import { useQueryClient as D } from "@tanstack/react-query";
3
+ import { Lock as P, Smartphone as M, Tablet as U } from "lucide-react";
4
+ import { useState as x, useEffect as _ } from "react";
5
+ import { toast as E } from "sonner";
6
+ import { useItemEditAuth as j, useNivaroClient as B } from "../../../context.js";
7
+ import { post as Q, patch as G } from "../../../lib/commands.js";
8
+ import { freezeOf as H, activeFreeze as J, localDay as L, dayWords as k, freezePatch as I, activeWindowOf as X, windowState as Y, windowWords as Z, activeWindowPatch as ee, tabletOfPatch as te, tabletOf as ne, phoneOfPatch as oe, phoneOf as ae, screenVersionOf as ie, conditionsWithKey as le } from "../../../lib/layout-resolve.js";
9
9
  import { cn as g } from "../../../lib/utils.js";
10
- import { useLayoutEditorHost as J } from "../host.js";
11
- import { useInvalidateLayouts as X, apiFailure as Y } from "../overview/overview-api.js";
12
- import { amberStrip as Z } from "../panel-style.js";
13
- import { Setting as $, smallBtn as b, quietText as w, inputCls as I, PickList as ee } from "./controls.js";
14
- import { useCollectionLayoutList as te, settingsKeys as ne } from "./settings-api.js";
15
- import { layoutKindOf as ae } from "./settings-registry.js";
16
- const F = g(I, "h-8 w-[150px] font-mono dark:[color-scheme:dark]");
17
- function ge(m) {
18
- const { layout: c } = m, e = j(c.conditions), [a, l] = x((e == null ? void 0 : e.from) ?? ""), [s, u] = x((e == null ? void 0 : e.until) ?? "");
19
- A(() => {
20
- l((e == null ? void 0 : e.from) ?? ""), u((e == null ? void 0 : e.until) ?? "");
10
+ import { useLayoutEditorHost as re } from "../host.js";
11
+ import { useInvalidateLayouts as se, apiFailure as ce } from "../overview/overview-api.js";
12
+ import { amberStrip as de } from "../panel-style.js";
13
+ import { Setting as C, smallBtn as y, quietText as N, inputCls as K, PickList as me } from "./controls.js";
14
+ import { useCollectionLayoutList as ue, settingsKeys as fe } from "./settings-api.js";
15
+ import { layoutKindOf as he } from "./settings-registry.js";
16
+ const O = g(K, "h-8 w-[150px] font-mono dark:[color-scheme:dark]");
17
+ function Fe(s) {
18
+ const { layout: c } = s, e = X(c.conditions), [o, n] = x((e == null ? void 0 : e.from) ?? ""), [r, h] = x((e == null ? void 0 : e.until) ?? "");
19
+ _(() => {
20
+ n((e == null ? void 0 : e.from) ?? ""), h((e == null ? void 0 : e.until) ?? "");
21
21
  }, [e == null ? void 0 : e.from, e == null ? void 0 : e.until]);
22
- const p = !!a && !!s && a > s, f = (o, i) => {
23
- o && i && o > i || (o || null) === ((e == null ? void 0 : e.from) ?? null) && (i || null) === ((e == null ? void 0 : e.until) ?? null) || m.set(
24
- G(c.conditions, { from: o || null, until: i || null }),
25
- o || i ? "Set active dates" : "Clear active dates"
22
+ const u = !!o && !!r && o > r, m = (i, d) => {
23
+ i && d && i > d || (i || null) === ((e == null ? void 0 : e.from) ?? null) && (d || null) === ((e == null ? void 0 : e.until) ?? null) || s.set(
24
+ ee(c.conditions, { from: i || null, until: d || null }),
25
+ i || d ? "Set active dates" : "Clear active dates"
26
26
  );
27
- }, d = B(e, S());
27
+ }, f = Y(e, L());
28
28
  return /* @__PURE__ */ t(
29
- $,
29
+ C,
30
30
  {
31
31
  k: "layout.conditions.active_window",
32
- note: p ? /* @__PURE__ */ t("span", { className: "text-amber-700 dark:text-amber-300", children: "The end comes before the start." }) : e && d ? /* @__PURE__ */ t("span", { "data-active-window-state": d, children: d === "open" ? `In use now, ${Q(e)}.` : d === "before" ? `Not in use yet: starts ${k(e.from)}.` : `No longer in use: ended ${k(e.until)}.` }) : null,
33
- children: /* @__PURE__ */ r("div", { className: "flex flex-wrap items-end gap-2", children: [
34
- /* @__PURE__ */ r("label", { className: "flex flex-col gap-1", children: [
35
- /* @__PURE__ */ t("span", { className: w, children: "From" }),
32
+ note: u ? /* @__PURE__ */ t("span", { className: "text-amber-700 dark:text-amber-300", children: "The end comes before the start." }) : e && f ? /* @__PURE__ */ t("span", { "data-active-window-state": f, children: f === "open" ? `In use now, ${Z(e)}.` : f === "before" ? `Not in use yet: starts ${k(e.from)}.` : `No longer in use: ended ${k(e.until)}.` }) : null,
33
+ children: /* @__PURE__ */ l("div", { className: "flex flex-wrap items-end gap-2", children: [
34
+ /* @__PURE__ */ l("label", { className: "flex flex-col gap-1", children: [
35
+ /* @__PURE__ */ t("span", { className: N, children: "From" }),
36
36
  /* @__PURE__ */ t(
37
37
  "input",
38
38
  {
39
39
  type: "date",
40
40
  "aria-label": "Active from",
41
- value: a,
42
- max: s || void 0,
43
- onChange: (o) => {
44
- l(o.target.value), f(o.target.value, s);
41
+ value: o,
42
+ max: r || void 0,
43
+ onChange: (i) => {
44
+ n(i.target.value), m(i.target.value, r);
45
45
  },
46
- className: F
46
+ className: O
47
47
  }
48
48
  )
49
49
  ] }),
50
- /* @__PURE__ */ r("label", { className: "flex flex-col gap-1", children: [
51
- /* @__PURE__ */ t("span", { className: w, children: "Until" }),
50
+ /* @__PURE__ */ l("label", { className: "flex flex-col gap-1", children: [
51
+ /* @__PURE__ */ t("span", { className: N, children: "Until" }),
52
52
  /* @__PURE__ */ t(
53
53
  "input",
54
54
  {
55
55
  type: "date",
56
56
  "aria-label": "Active until",
57
- value: s,
58
- min: a || void 0,
59
- onChange: (o) => {
60
- u(o.target.value), f(a, o.target.value);
57
+ value: r,
58
+ min: o || void 0,
59
+ onChange: (i) => {
60
+ h(i.target.value), m(o, i.target.value);
61
61
  },
62
- className: F
62
+ className: O
63
63
  }
64
64
  )
65
65
  ] }),
66
- (a || s) && /* @__PURE__ */ t(
66
+ (o || r) && /* @__PURE__ */ t(
67
67
  "button",
68
68
  {
69
69
  type: "button",
70
- className: g(b, "mb-0.5"),
70
+ className: g(y, "mb-0.5"),
71
71
  onClick: () => {
72
- l(""), u(""), f("", "");
72
+ n(""), h(""), m("", "");
73
73
  },
74
74
  children: "Clear"
75
75
  }
@@ -78,170 +78,211 @@ function ge(m) {
78
78
  }
79
79
  );
80
80
  }
81
- function xe(m) {
82
- const { layout: c, collection: e } = m, a = Number(c.id), l = J(), s = M(), u = W(), p = X(e), f = te(e), [d, o] = x(!1), i = f.filter((n) => ae(n) === "grouped"), h = L(c.conditions), N = i.find((n) => n.id !== a && L(n.conditions) === a) ?? null, v = h != null ? i.find((n) => n.id === h) ?? null : null, C = (n) => {
83
- l.layoutLink && l.navigate(l.layoutLink(e, n));
84
- }, K = async () => {
85
- o(!0);
81
+ const q = {
82
+ phone: {
83
+ key: "phone_of",
84
+ of: ae,
85
+ patch: oe,
86
+ word: "phone",
87
+ where: "small screens"
88
+ },
89
+ tablet: {
90
+ key: "tablet_of",
91
+ of: ne,
92
+ patch: te,
93
+ word: "tablet",
94
+ where: "tablet-width screens"
95
+ }
96
+ };
97
+ function Te(s) {
98
+ return /* @__PURE__ */ t(R, { ...s, screen: "phone" });
99
+ }
100
+ function Pe(s) {
101
+ return /* @__PURE__ */ t(R, { ...s, screen: "tablet" });
102
+ }
103
+ function R(s) {
104
+ const { layout: c, collection: e, screen: o } = s, n = q[o], r = q[o === "phone" ? "tablet" : "phone"], h = o === "phone" ? M : U, u = Number(c.id), m = re(), f = B(), i = D(), d = se(e), V = ue(e), [F, T] = x(!1), S = V.filter((a) => he(a) === "grouped"), p = n.of(c.conditions), W = r.of(c.conditions), w = S.find((a) => a.id !== u && n.of(a.conditions) === u) ?? null, b = p != null ? S.find((a) => a.id === p) ?? null : null, $ = (a) => {
105
+ m.layoutLink && m.navigate(m.layoutLink(e, a));
106
+ }, A = async () => {
107
+ T(!0);
86
108
  try {
87
- const n = String(c.name || "Form"), z = await s.request(
88
- R(`/collection-layouts/${a}/clone`, { name: `${n} (phone)`.slice(0, 255) })
89
- ), y = z == null ? void 0 : z.data;
90
- if (!(y != null && y.id)) throw new Error("No id came back");
91
- await s.request(
92
- T(`/collection-layouts/${y.id}`, {
93
- conditions: H(y.conditions, "phone_of", a)
109
+ const a = String(c.name || "Form"), z = await f.request(
110
+ Q(`/collection-layouts/${u}/clone`, { name: `${a} (${n.word})`.slice(0, 255) })
111
+ ), v = z == null ? void 0 : z.data;
112
+ if (!(v != null && v.id)) throw new Error("No id came back");
113
+ await f.request(
114
+ G(`/collection-layouts/${v.id}`, {
115
+ conditions: le(v.conditions, n.key, u)
94
116
  })
95
- ), u.invalidateQueries({ queryKey: ne.layouts(e) }), p(), q.success("Phone version made: remove what a phone does not need"), C(Number(y.id));
96
- } catch (n) {
97
- q.error(Y(n, "Could not make the phone version").message);
117
+ ), i.invalidateQueries({ queryKey: fe.layouts(e) }), d(), E.success(
118
+ o === "phone" ? "Phone version made: remove what a phone does not need" : "Tablet version made: arrange it for a tablet-width screen"
119
+ ), $(Number(v.id));
120
+ } catch (a) {
121
+ E.error(ce(a, `Could not make the ${n.word} version`).message);
98
122
  } finally {
99
- o(!1);
123
+ T(!1);
100
124
  }
101
125
  };
102
- return /* @__PURE__ */ t(
103
- $,
126
+ return W != null ? /* @__PURE__ */ t(C, { k: `layout.conditions.${n.key}`, children: /* @__PURE__ */ l("p", { className: N, "data-screen-version-blocked": o, children: [
127
+ "This form is the ",
128
+ r.word,
129
+ " version of another form, so it cannot have a ",
130
+ n.word,
131
+ " ",
132
+ "version."
133
+ ] }) }) : /* @__PURE__ */ t(
134
+ C,
104
135
  {
105
- k: "layout.conditions.phone_of",
106
- note: h != null ? /* @__PURE__ */ r("span", { "data-phone-of": h, children: [
107
- "This form opens instead of",
108
- " ",
109
- /* @__PURE__ */ t("strong", { className: "font-medium text-slate-700 dark:text-foreground", children: (v == null ? void 0 : v.name) ?? `form ${h}` }),
110
- " ",
111
- "on small screens, for the records and roles that form gets."
112
- ] }) : null,
113
- children: N ? /* @__PURE__ */ r(
136
+ k: `layout.conditions.${n.key}`,
137
+ note: p != null ? /* @__PURE__ */ l(
138
+ "span",
139
+ {
140
+ "data-phone-of": o === "phone" ? p : void 0,
141
+ "data-tablet-of": o === "tablet" ? p : void 0,
142
+ children: [
143
+ "This form opens instead of",
144
+ " ",
145
+ /* @__PURE__ */ t("strong", { className: "font-medium text-slate-700 dark:text-foreground", children: (b == null ? void 0 : b.name) ?? `form ${p}` }),
146
+ " ",
147
+ "on ",
148
+ n.where,
149
+ ", for the records and roles that form gets."
150
+ ]
151
+ }
152
+ ) : null,
153
+ children: w ? /* @__PURE__ */ l(
114
154
  "div",
115
155
  {
116
- "data-phone-version": N.id,
156
+ "data-phone-version": o === "phone" ? w.id : void 0,
157
+ "data-tablet-version": o === "tablet" ? w.id : void 0,
117
158
  className: "flex flex-wrap items-center gap-2 text-[12.5px] text-slate-700 dark:text-foreground",
118
159
  children: [
119
- /* @__PURE__ */ t(P, { className: "h-3.5 w-3.5 shrink-0 text-slate-500 dark:text-muted-foreground" }),
120
- /* @__PURE__ */ t("span", { className: "min-w-0 truncate", children: N.name }),
121
- l.layoutLink && /* @__PURE__ */ t("button", { type: "button", className: b, onClick: () => C(N.id), children: "Open" })
160
+ /* @__PURE__ */ t(h, { className: "h-3.5 w-3.5 shrink-0 text-slate-500 dark:text-muted-foreground" }),
161
+ /* @__PURE__ */ t("span", { className: "min-w-0 truncate", children: w.name }),
162
+ m.layoutLink && /* @__PURE__ */ t("button", { type: "button", className: y, onClick: () => $(w.id), children: "Open" })
122
163
  ]
123
164
  }
124
- ) : /* @__PURE__ */ r("div", { className: "flex flex-wrap items-center gap-2", children: [
165
+ ) : /* @__PURE__ */ l("div", { className: "flex flex-wrap items-center gap-2", children: [
125
166
  /* @__PURE__ */ t(
126
- ee,
167
+ me,
127
168
  {
128
- ariaLabel: "Phone version of",
129
- value: h != null ? String(h) : null,
130
- placeholder: "Not a phone version",
131
- clearLabel: "Not a phone version",
132
- options: i.filter((n) => n.id !== a && L(n.conditions) == null).map((n) => ({ value: String(n.id), label: n.name })),
133
- onChange: (n) => m.set(
134
- V(c.conditions, n ? Number(n) : null),
135
- n ? "Make this a phone version" : "Stop being a phone version"
169
+ ariaLabel: o === "phone" ? "Phone version of" : "Tablet version of",
170
+ value: p != null ? String(p) : null,
171
+ placeholder: `Not a ${n.word} version`,
172
+ clearLabel: `Not a ${n.word} version`,
173
+ options: S.filter((a) => a.id !== u && ie(a.conditions) == null).map((a) => ({ value: String(a.id), label: a.name })),
174
+ onChange: (a) => s.set(
175
+ n.patch(c.conditions, a ? Number(a) : null),
176
+ a ? `Make this a ${n.word} version` : `Stop being a ${n.word} version`
136
177
  ),
137
178
  className: "w-[220px]"
138
179
  }
139
180
  ),
140
- h == null && /* @__PURE__ */ r(
181
+ p == null && /* @__PURE__ */ l(
141
182
  "button",
142
183
  {
143
184
  type: "button",
144
- className: b,
145
- disabled: d,
146
- "data-action": "make-phone-version",
147
- onClick: () => void K(),
185
+ className: y,
186
+ disabled: F,
187
+ "data-action": `make-${n.word}-version`,
188
+ onClick: () => void A(),
148
189
  children: [
149
- /* @__PURE__ */ t(P, { className: "h-3.5 w-3.5" }),
150
- d ? "Making…" : "Make a phone version"
190
+ /* @__PURE__ */ t(h, { className: "h-3.5 w-3.5" }),
191
+ F ? "Making…" : `Make a ${n.word} version`
151
192
  ]
152
193
  }
153
194
  ),
154
- v && l.layoutLink && /* @__PURE__ */ r("button", { type: "button", className: b, onClick: () => C(v.id), children: [
195
+ b && m.layoutLink && /* @__PURE__ */ l("button", { type: "button", className: y, onClick: () => $(b.id), children: [
155
196
  "Open ",
156
- v.name
197
+ b.name
157
198
  ] })
158
199
  ] })
159
200
  }
160
201
  );
161
202
  }
162
- function Ne(m) {
163
- const { layout: c } = m, { userId: e } = D(), a = U(c.conditions), l = _(c.conditions), [s, u] = x(""), [p, f] = x(""), d = s > S() && p.trim().length >= 3, o = () => {
164
- d && (m.set(
165
- E(c.conditions, {
166
- until: s,
167
- reason: p.trim().slice(0, 300),
203
+ function Ee(s) {
204
+ const { layout: c } = s, { userId: e } = j(), o = H(c.conditions), n = J(c.conditions), [r, h] = x(""), [u, m] = x(""), f = r > L() && u.trim().length >= 3, i = () => {
205
+ f && (s.set(
206
+ I(c.conditions, {
207
+ until: r,
208
+ reason: u.trim().slice(0, 300),
168
209
  by: e || null,
169
210
  at: (/* @__PURE__ */ new Date()).toISOString()
170
211
  }),
171
- `Freeze edits until ${k(s)}`
172
- ), u(""), f(""));
212
+ `Freeze edits until ${k(r)}`
213
+ ), h(""), m(""));
173
214
  };
174
- return /* @__PURE__ */ t($, { k: "layout.conditions.freeze", children: a ? /* @__PURE__ */ r(
215
+ return /* @__PURE__ */ t(C, { k: "layout.conditions.freeze", children: o ? /* @__PURE__ */ l(
175
216
  "div",
176
217
  {
177
- "data-layout-frozen": a.until,
218
+ "data-layout-frozen": o.until,
178
219
  className: g(
179
220
  "flex flex-wrap items-center gap-2 rounded-md border px-2.5 py-2 text-[12.5px]",
180
- l ? Z : "border-slate-200 text-slate-600 dark:border-border dark:text-muted-foreground"
221
+ n ? de : "border-slate-200 text-slate-600 dark:border-border dark:text-muted-foreground"
181
222
  ),
182
223
  children: [
183
- /* @__PURE__ */ t(O, { className: "h-3.5 w-3.5 shrink-0" }),
184
- /* @__PURE__ */ r("span", { className: "min-w-0 flex-1", children: [
185
- l ? "Frozen until " : "The freeze ended on ",
186
- k(a.until),
187
- a.reason ? `: ${a.reason}` : ""
224
+ /* @__PURE__ */ t(P, { className: "h-3.5 w-3.5 shrink-0" }),
225
+ /* @__PURE__ */ l("span", { className: "min-w-0 flex-1", children: [
226
+ n ? "Frozen until " : "The freeze ended on ",
227
+ k(o.until),
228
+ o.reason ? `: ${o.reason}` : ""
188
229
  ] }),
189
230
  /* @__PURE__ */ t(
190
231
  "button",
191
232
  {
192
233
  type: "button",
193
- className: b,
234
+ className: y,
194
235
  "data-action": "lift-freeze",
195
- onClick: () => m.set(
196
- E(c.conditions, null),
197
- l ? "Lift the edit freeze" : "Remove the ended freeze"
236
+ onClick: () => s.set(
237
+ I(c.conditions, null),
238
+ n ? "Lift the edit freeze" : "Remove the ended freeze"
198
239
  ),
199
- children: l ? "Lift" : "Remove"
240
+ children: n ? "Lift" : "Remove"
200
241
  }
201
242
  )
202
243
  ]
203
244
  }
204
- ) : /* @__PURE__ */ r("div", { className: "flex flex-wrap items-end gap-2", children: [
205
- /* @__PURE__ */ r("label", { className: "flex flex-col gap-1", children: [
206
- /* @__PURE__ */ t("span", { className: w, children: "Until" }),
245
+ ) : /* @__PURE__ */ l("div", { className: "flex flex-wrap items-end gap-2", children: [
246
+ /* @__PURE__ */ l("label", { className: "flex flex-col gap-1", children: [
247
+ /* @__PURE__ */ t("span", { className: N, children: "Until" }),
207
248
  /* @__PURE__ */ t(
208
249
  "input",
209
250
  {
210
251
  type: "date",
211
252
  "aria-label": "Frozen until",
212
- value: s,
213
- min: S(),
214
- onChange: (i) => u(i.target.value),
215
- className: F
253
+ value: r,
254
+ min: L(),
255
+ onChange: (d) => h(d.target.value),
256
+ className: O
216
257
  }
217
258
  )
218
259
  ] }),
219
- /* @__PURE__ */ r("label", { className: "flex min-w-[180px] flex-1 flex-col gap-1", children: [
220
- /* @__PURE__ */ t("span", { className: w, children: "Reason people see" }),
260
+ /* @__PURE__ */ l("label", { className: "flex min-w-[180px] flex-1 flex-col gap-1", children: [
261
+ /* @__PURE__ */ t("span", { className: N, children: "Reason people see" }),
221
262
  /* @__PURE__ */ t(
222
263
  "input",
223
264
  {
224
- value: p,
265
+ value: u,
225
266
  maxLength: 300,
226
267
  placeholder: "e.g. Go-live on Monday",
227
- onChange: (i) => f(i.target.value),
228
- onKeyDown: (i) => {
229
- i.key === "Enter" && o();
268
+ onChange: (d) => m(d.target.value),
269
+ onKeyDown: (d) => {
270
+ d.key === "Enter" && i();
230
271
  },
231
- className: g(I, "h-8")
272
+ className: g(K, "h-8")
232
273
  }
233
274
  )
234
275
  ] }),
235
- /* @__PURE__ */ r(
276
+ /* @__PURE__ */ l(
236
277
  "button",
237
278
  {
238
279
  type: "button",
239
- className: g(b, "mb-0.5"),
240
- disabled: !d,
280
+ className: g(y, "mb-0.5"),
281
+ disabled: !f,
241
282
  "data-action": "freeze",
242
- onClick: o,
283
+ onClick: i,
243
284
  children: [
244
- /* @__PURE__ */ t(O, { className: "h-3.5 w-3.5" }),
285
+ /* @__PURE__ */ t(P, { className: "h-3.5 w-3.5" }),
245
286
  "Freeze"
246
287
  ]
247
288
  }
@@ -249,7 +290,8 @@ function Ne(m) {
249
290
  ] }) });
250
291
  }
251
292
  export {
252
- ge as ActiveDatesSetting,
253
- Ne as FreezeSetting,
254
- xe as PhoneVersionSetting
293
+ Fe as ActiveDatesSetting,
294
+ Ee as FreezeSetting,
295
+ Te as PhoneVersionSetting,
296
+ Pe as TabletVersionSetting
255
297
  };
@@ -8,17 +8,17 @@ import { LAYOUT_TYPES as D } from "../overview/OverviewActions.js";
8
8
  import { useRoleNames as F } from "../overview/overview-api.js";
9
9
  import { roleIdsPatch as Y } from "../testing/testing-model.js";
10
10
  import { Setting as p, smallBtn as d, quietText as x, Segmented as j } from "./controls.js";
11
- import { ActiveDatesSetting as K, PhoneVersionSetting as M } from "./ResolveSettings.js";
11
+ import { ActiveDatesSetting as K, PhoneVersionSetting as M, TabletVersionSetting as U } from "./ResolveSettings.js";
12
12
  import { changeLabel as _, flag as C } from "./section-props.js";
13
- import { useFieldSources as U, useCollectionLayoutList as $ } from "./settings-api.js";
14
- import { layoutKindOf as B } from "./settings-registry.js";
13
+ import { useFieldSources as $, useCollectionLayoutList as B } from "./settings-api.js";
14
+ import { layoutKindOf as E } from "./settings-registry.js";
15
15
  import { TextSetting as S } from "./TextSetting.js";
16
- import { ToggleSetting as E } from "./ToggleSetting.js";
16
+ import { ToggleSetting as G } from "./ToggleSetting.js";
17
17
  const g = (t) => {
18
18
  var e;
19
19
  return ((e = D.find((o) => o.type === t)) == null ? void 0 : e.label) ?? t;
20
- }, G = (t) => t.toLowerCase().replace(/[^a-z0-9_]/g, "_"), v = (t) => t.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
21
- function J(t) {
20
+ }, J = (t) => t.toLowerCase().replace(/[^a-z0-9_]/g, "_"), v = (t) => t.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
21
+ function V(t) {
22
22
  let e = t;
23
23
  if (typeof e == "string")
24
24
  try {
@@ -29,10 +29,10 @@ function J(t) {
29
29
  const o = e == null ? void 0 : e.role_ids;
30
30
  return Array.isArray(o) ? o.map(String) : [];
31
31
  }
32
- function me(t) {
33
- const { layout: e, collection: o } = t, { fields: c, columns: l, relations: i } = U(o), { data: m = [] } = F(!0), f = J(e.conditions);
32
+ function fe(t) {
33
+ const { layout: e, collection: o } = t, { fields: c, columns: l, relations: i } = $(o), { data: m = [] } = F(!0), f = V(e.conditions);
34
34
  return /* @__PURE__ */ a(u, { children: [
35
- /* @__PURE__ */ n(V, { ...t }),
35
+ /* @__PURE__ */ n(W, { ...t }),
36
36
  /* @__PURE__ */ n(
37
37
  p,
38
38
  {
@@ -81,7 +81,7 @@ function me(t) {
81
81
  props: t,
82
82
  mono: !0,
83
83
  placeholder: "e.g. unit_order",
84
- sanitize: G,
84
+ sanitize: J,
85
85
  blurOnly: !0,
86
86
  extra: !e.slug && typeof e.name == "string" && v(e.name) ? /* @__PURE__ */ n(
87
87
  "button",
@@ -110,9 +110,10 @@ function me(t) {
110
110
  placeholder: typeof e.name == "string" ? e.name : ""
111
111
  }
112
112
  ),
113
- /* @__PURE__ */ n(E, { k: "layout.create_hidden", props: t }),
113
+ /* @__PURE__ */ n(G, { k: "layout.create_hidden", props: t }),
114
114
  /* @__PURE__ */ n(K, { ...t }),
115
- /* @__PURE__ */ n(M, { ...t })
115
+ /* @__PURE__ */ n(M, { ...t }),
116
+ /* @__PURE__ */ n(U, { ...t })
116
117
  ] });
117
118
  }
118
119
  function q({ layoutId: t }) {
@@ -137,9 +138,9 @@ function q({ layoutId: t }) {
137
138
  o && /* @__PURE__ */ n(w, { layoutId: t, change: "slug", compact: !0, className: "mt-2" })
138
139
  ] }) : null;
139
140
  }
140
- function V(t) {
141
- const { layout: e, kind: o, bundle: c } = t, [l, i] = y(null), { data: m } = L(Number(e.id)), f = ((m == null ? void 0 : m.nodes.length) ?? 0) > 0, s = c.placements.length + c.groups.length, h = (r) => t.set({ layout_type: r }, `Change kind to ${g(r)}`), T = C(e.is_active), [O, b] = y(!1), k = $(t.collection).find(
142
- (r) => r.id !== Number(e.id) && B(r) === o && C(r.is_active)
141
+ function W(t) {
142
+ const { layout: e, kind: o, bundle: c } = t, [l, i] = y(null), { data: m } = L(Number(e.id)), f = ((m == null ? void 0 : m.nodes.length) ?? 0) > 0, s = c.placements.length + c.groups.length, h = (r) => t.set({ layout_type: r }, `Change kind to ${g(r)}`), T = C(e.is_active), [O, b] = y(!1), k = B(t.collection).find(
143
+ (r) => r.id !== Number(e.id) && E(r) === o && C(r.is_active)
143
144
  ), N = o === "grouped" ? "form" : `${g(o).toLowerCase()} layout`, A = () => {
144
145
  t.set({ is_active: !0 }, "Make default", { undoable: !1 }), b(!1);
145
146
  }, R = o === "file" ? null : /* @__PURE__ */ n("div", { className: "flex flex-wrap items-center gap-2", children: T ? /* @__PURE__ */ a("span", { className: x, "data-default-layout": !0, children: [
@@ -247,6 +248,6 @@ function V(t) {
247
248
  ] });
248
249
  }
249
250
  export {
250
- me as WhoSection,
251
- G as sanitizeSlug
251
+ fe as WhoSection,
252
+ J as sanitizeSlug
252
253
  };
@@ -70,6 +70,14 @@ const y = [
70
70
  types: ["grouped"],
71
71
  keywords: "mobile small screen variant device lighter"
72
72
  },
73
+ {
74
+ key: "layout.conditions.tablet_of",
75
+ section: "who",
76
+ label: "Tablet version",
77
+ effect: "A copy of a form arranged for tablet-width screens that opens instead of it there (and on a phone without a phone version); it never opens on its own.",
78
+ types: ["grouped"],
79
+ keywords: "ipad tablet medium screen variant device touch"
80
+ },
73
81
  // ── How it's laid out ─────────────────────────────────────────────────────
74
82
  {
75
83
  key: "layout.tab_mode",
@@ -92,6 +100,14 @@ const y = [
92
100
  effect: "Opening a section closes the others.",
93
101
  types: t
94
102
  },
103
+ {
104
+ key: "layout.density",
105
+ section: "layout",
106
+ label: "Density",
107
+ effect: "How tightly the form is spaced for the people filling it in: comfortable, or compact to fit more on the screen.",
108
+ types: ["grouped"],
109
+ keywords: "compact comfortable spacing tight dense padding row gap height"
110
+ },
95
111
  {
96
112
  key: "layout.row_order_field",
97
113
  section: "layout",
@@ -403,6 +419,14 @@ const y = [
403
419
  effect: "How many records of their own a person makes before the form switches to tabs.",
404
420
  types: s
405
421
  },
422
+ {
423
+ key: "layout.tour",
424
+ section: "entry",
425
+ label: "First-use tour",
426
+ effect: "The first time someone opens this form, a short tour walks them through its sections; a Tour button brings it back.",
427
+ types: s,
428
+ keywords: "onboarding guide walkthrough introduction help first time new people"
429
+ },
406
430
  {
407
431
  key: "layout.badge",
408
432
  section: "entry",
@@ -1,4 +1,4 @@
1
- const l = ["Editing", "Moving", "Finding", "Saving", "View"], r = [
1
+ const r = ["Editing", "Moving", "Finding", "Saving", "View"], i = [
2
2
  { id: "undo", area: "Editing", keys: [["mod", "z"]], label: "Undo" },
3
3
  {
4
4
  id: "redo",
@@ -55,19 +55,23 @@ const l = ["Editing", "Moving", "Finding", "Saving", "View"], r = [
55
55
  label: "Close the editor (record page), or the open popover"
56
56
  }
57
57
  ];
58
- function d() {
59
- return l.map((e) => ({
58
+ function d(e) {
59
+ const t = i.findIndex((o) => o.id === e.id);
60
+ t >= 0 ? i[t] = e : i.push(e);
61
+ }
62
+ function c() {
63
+ return r.map((e) => ({
60
64
  area: e,
61
- items: r.filter((a) => a.area === e)
65
+ items: i.filter((t) => t.area === e)
62
66
  })).filter((e) => e.items.length > 0);
63
67
  }
64
- function s() {
65
- var a;
68
+ function n() {
69
+ var t;
66
70
  if (typeof navigator > "u") return !0;
67
- const e = ((a = navigator.userAgentData) == null ? void 0 : a.platform) ?? navigator.platform ?? navigator.userAgent;
71
+ const e = ((t = navigator.userAgentData) == null ? void 0 : t.platform) ?? navigator.platform ?? navigator.userAgent;
68
72
  return /mac|iphone|ipad|ipod/i.test(e ?? "");
69
73
  }
70
- const i = {
74
+ const l = {
71
75
  mod: "⌘",
72
76
  shift: "⇧",
73
77
  alt: "⌥",
@@ -75,14 +79,15 @@ const i = {
75
79
  esc: "Esc",
76
80
  space: "Space",
77
81
  click: "click"
78
- }, n = { ...i, mod: "Ctrl", shift: "Shift", alt: "Alt" };
79
- function c(e, a = s()) {
80
- const o = a ? i : n;
81
- return e.map((t) => o[t] ?? (t.length === 1 ? t.toUpperCase() : t));
82
+ }, s = { ...l, mod: "Ctrl", shift: "Shift", alt: "Alt" };
83
+ function p(e, t = n()) {
84
+ const o = t ? l : s;
85
+ return e.map((a) => o[a] ?? (a.length === 1 ? a.toUpperCase() : a));
82
86
  }
83
87
  export {
84
- l as SHORTCUT_AREAS,
85
- s as isMacLike,
86
- c as keyLabels,
87
- d as shortcutGroups
88
+ r as SHORTCUT_AREAS,
89
+ n as isMacLike,
90
+ p as keyLabels,
91
+ d as registerShortcut,
92
+ c as shortcutGroups
88
93
  };