@nivaro/react 0.3.40 → 0.3.42

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 (99) hide show
  1. package/dist/components/LayoutForm.js +100 -98
  2. package/dist/full.css +1 -1
  3. package/dist/hooks/useSessionRecorder.js +1 -1
  4. package/dist/index.d.ts +645 -16
  5. package/dist/index.js +814 -775
  6. package/dist/shared/components/ActivityEntry.js +154 -0
  7. package/dist/shared/components/AudienceConfirmPanel.js +98 -0
  8. package/dist/shared/components/BackgroundRunOffer.js +43 -31
  9. package/dist/shared/components/BroadcastView.js +225 -204
  10. package/dist/shared/components/CollectionBrowserView.js +3924 -3584
  11. package/dist/shared/components/ConfigHistory.js +153 -0
  12. package/dist/shared/components/ConfigReadBack.js +65 -0
  13. package/dist/shared/components/DataTable.js +379 -346
  14. package/dist/shared/components/ForceReloadBanner.js +47 -40
  15. package/dist/shared/components/IdleReloadWatcher.js +69 -0
  16. package/dist/shared/components/ItemEditForm.js +4041 -3853
  17. package/dist/shared/components/MyWorkView.js +278 -213
  18. package/dist/shared/components/NotificationBell.js +130 -121
  19. package/dist/shared/components/PickerExcludedRows.js +3 -3
  20. package/dist/shared/components/ProfileView.js +776 -1003
  21. package/dist/shared/components/RecentRecordsRail.js +34 -16
  22. package/dist/shared/components/RecordReadView.js +500 -477
  23. package/dist/shared/components/Skeletons.js +199 -0
  24. package/dist/shared/components/SlowNotice.js +63 -0
  25. package/dist/shared/components/Term.js +23 -0
  26. package/dist/shared/components/WidgetSlot.js +350 -353
  27. package/dist/shared/components/access/PermissionSummary.js +106 -0
  28. package/dist/shared/components/bulk/BulkActionButtons.js +76 -73
  29. package/dist/shared/components/chat/ChatPanel.js +902 -886
  30. package/dist/shared/components/chat/MemberPaging.js +70 -0
  31. package/dist/shared/components/chat/RoomParts.js +147 -117
  32. package/dist/shared/components/chat/ScreenClip.js +73 -69
  33. package/dist/shared/components/chat/chat-core.js +449 -396
  34. package/dist/shared/components/chat/huddle/huddle-store.js +48 -43
  35. package/dist/shared/components/help-videos/api.js +2 -5
  36. package/dist/shared/components/help-videos/viewer/HelpVideoMatchChip.js +79 -0
  37. package/dist/shared/components/help-videos/viewer/matchChip.js +50 -0
  38. package/dist/shared/components/imports/CollectionImportPanel.js +139 -133
  39. package/dist/shared/components/imports/RunDetailSheet.js +222 -227
  40. package/dist/shared/components/integrations/console/ErrorExplanation.js +121 -0
  41. package/dist/shared/components/integrations/console/PartnerDetail.js +175 -174
  42. package/dist/shared/components/integrations/console/SubmissionRow.js +36 -34
  43. package/dist/shared/components/integrations/console/drill/SubmissionDrill.js +50 -48
  44. package/dist/shared/components/item-edit/FieldComments.js +212 -0
  45. package/dist/shared/components/item-edit/FieldRow.js +340 -336
  46. package/dist/shared/components/item-edit/RecordGrantTools.js +28 -28
  47. package/dist/shared/components/item-edit/RecordHeaderActions.js +23 -22
  48. package/dist/shared/components/item-edit/RelationCombobox.js +231 -222
  49. package/dist/shared/components/item-edit/RuleHiddenNotes.js +55 -0
  50. package/dist/shared/components/item-edit/field-comments-context.js +6 -0
  51. package/dist/shared/components/item-edit/field-sources.js +33 -0
  52. package/dist/shared/components/item-edit/rule-hidden.js +30 -0
  53. package/dist/shared/components/layout-editor/HistoryPanel.js +113 -96
  54. package/dist/shared/components/layout-editor/editors/cascade-filters.js +170 -145
  55. package/dist/shared/components/layout-editor/inspector/Breadcrumb.js +22 -18
  56. package/dist/shared/components/layout-editor/inspector/GroupInspector.js +177 -159
  57. package/dist/shared/components/layout-editor/inspector/PickerTab.js +35 -34
  58. package/dist/shared/components/layout-editor/inspector/RulesTab.js +124 -111
  59. package/dist/shared/components/layout-editor/inspector/kit.js +292 -277
  60. package/dist/shared/components/layout-editor/parity-keys.json.js +1 -1
  61. package/dist/shared/components/layout-editor/settings/settings-registry.js +1 -1
  62. package/dist/shared/components/list/CopyListLinkButton.js +41 -0
  63. package/dist/shared/components/list/InlineEdit.js +363 -0
  64. package/dist/shared/components/notifications/NotificationCenterView.js +213 -181
  65. package/dist/shared/components/notifications/NotificationDetailBits.js +205 -82
  66. package/dist/shared/components/notifications/NotificationRulesEditor.js +515 -0
  67. package/dist/shared/components/notifications/TestMyRules.js +137 -0
  68. package/dist/shared/components/notifications/changes-lines.js +24 -0
  69. package/dist/shared/components/notifications/why-lines.js +64 -0
  70. package/dist/shared/components/panels/CommentPanel.js +316 -281
  71. package/dist/shared/components/panels/LegalHoldBanner.js +38 -0
  72. package/dist/shared/components/panels/PipelinePanel.js +201 -196
  73. package/dist/shared/components/panels/RevisionsPanel.js +496 -479
  74. package/dist/shared/components/pipeline/PipelineEditorView.js +1587 -1560
  75. package/dist/shared/components/pipeline/PipelineStateOwners.js +116 -103
  76. package/dist/shared/components/profile/PersonDidPanel.js +188 -0
  77. package/dist/shared/components/profile/PersonProfile.js +57 -52
  78. package/dist/shared/components/queue/QueueWorklist.js +1526 -1365
  79. package/dist/shared/hooks/useSlowReason.js +39 -0
  80. package/dist/shared/lib/activity-sentence.js +670 -0
  81. package/dist/shared/lib/config-sentences.js +418 -0
  82. package/dist/shared/lib/core-glossary.js +229 -0
  83. package/dist/shared/lib/error-hints.js +159 -0
  84. package/dist/shared/lib/error-message.js +105 -0
  85. package/dist/shared/lib/error-toast.js +22 -0
  86. package/dist/shared/lib/field-comments.js +25 -0
  87. package/dist/shared/lib/filter-sentence.js +261 -0
  88. package/dist/shared/lib/glossary.js +55 -48
  89. package/dist/shared/lib/idle-reload.js +138 -0
  90. package/dist/shared/lib/layout-resolve.js +42 -29
  91. package/dist/shared/lib/list-inline-edit.js +190 -0
  92. package/dist/shared/lib/list-link.js +147 -0
  93. package/dist/shared/lib/prefetch.js +259 -106
  94. package/dist/shared/lib/record-ref.js +72 -0
  95. package/dist/shared/lib/reload-holds.js +25 -0
  96. package/dist/shared/lib/safe-error.js +52 -24
  97. package/dist/shared/lib/skeleton-shapes.js +72 -0
  98. package/dist/shared/lib/slow-reason.js +63 -0
  99. package/package.json +1 -1
@@ -1,129 +1,139 @@
1
- import { jsxs as a, jsx as t, Fragment as oe } from "react/jsx-runtime";
2
- import { useQueryClient as ie, useQuery as k, useMutation as C } from "@tanstack/react-query";
3
- import { useState as p, useMemo as z, useEffect as Ce } from "react";
4
- import { createPortal as $e } from "react-dom";
5
- import { useNivaroClient as O } from "../context.js";
6
- import { get as v, post as j, patch as Te, del as Ae } from "../lib/commands.js";
7
- import { useLiveOps as je } from "../lib/live-ops.js";
1
+ import { jsxs as a, jsx as t, Fragment as ce } from "react/jsx-runtime";
2
+ import { useQueryClient as me, useQuery as k, useMutation as $ } from "@tanstack/react-query";
3
+ import { useState as u, useMemo as Y, useEffect as Ae } from "react";
4
+ import { createPortal as Te } from "react-dom";
5
+ import { useNivaroClient as I } from "../context.js";
6
+ import { get as v, post as j, patch as Le, del as je } from "../lib/commands.js";
7
+ import { useLiveOps as Fe } from "../lib/live-ops.js";
8
8
  import { useLiveRefetchInterval as Ke } from "../lib/live-queries.js";
9
9
  import { cn as y } from "../lib/utils.js";
10
- import { BroadcastDraftPanel as Le } from "./BroadcastDraft.js";
11
- import { useHelpVideoLibrary as Fe } from "./help-videos/api.js";
12
- import { formatDuration as Pe } from "./help-videos/viewer/format.js";
13
- import { PickList as De } from "./imports/ServiceConfigBuilder.js";
14
- const ce = {
10
+ import { audienceConfirmFromError as Pe, AudienceConfirmPanel as Ee } from "./AudienceConfirmPanel.js";
11
+ import { BroadcastDraftPanel as De } from "./BroadcastDraft.js";
12
+ import { useHelpVideoLibrary as Oe } from "./help-videos/api.js";
13
+ import { formatDuration as Ie } from "./help-videos/viewer/format.js";
14
+ import { PickList as Qe } from "./imports/ServiceConfigBuilder.js";
15
+ const ue = {
15
16
  info: "bg-sky-500",
16
17
  warn: "bg-amber-500",
17
18
  critical: "bg-red-500"
18
19
  };
19
- function et({ className: r }) {
20
- var le;
21
- const o = O(), c = ie(), [b, h] = p(""), [s, u] = p(""), [l, n] = p("info"), [m, x] = p(!1), [d, N] = p(!1), [g, ue] = p(!0), [I, pe] = p(!1), [_, xe] = p("banner"), [Q, he] = p(!1), [Y, be] = p(""), [R, M] = p(""), [Z, ge] = p(""), [K, H] = p([]), [$, fe] = p([]), [J, q] = p(null), [T, W] = p(""), [X, ee] = p(""), A = Fe({ status: "published" }), te = () => {
20
+ function st({ className: r }) {
21
+ var ie;
22
+ const i = I(), c = me(), [b, h] = u(""), [s, p] = u(""), [o, n] = u("info"), [m, x] = u(!1), [d, N] = u(!1), [g, xe] = u(!0), [Q, he] = u(!1), [_, be] = u("banner"), [R, ge] = u(!1), [Z, fe] = u(""), [M, H] = u(""), [J, ye] = u(""), [F, V] = u([]), [A, ke] = u([]), [W, q] = u(null), [T, X] = u(""), [ee, te] = u(""), L = Oe({ status: "published" }), ae = () => {
22
23
  if (!T) return {};
23
- const e = Number(X);
24
+ const e = Number(ee);
24
25
  return {
25
26
  help_video_id: T,
26
27
  help_video_t_ms: Number.isFinite(e) && e > 0 ? Math.round(e * 1e3) : null
27
28
  };
28
- }, { data: V } = k({
29
+ }, { data: U } = k({
29
30
  queryKey: ["broadcast-config"],
30
- queryFn: () => o.request(v("/announcements/config")).then((e) => e.data).catch(() => ({ sms_enabled: !1 })),
31
+ queryFn: () => i.request(v("/announcements/config")).then((e) => e.data).catch(() => ({ sms_enabled: !1 })),
31
32
  staleTime: 5 * 6e4
32
- }), { data: ye = [] } = k({
33
+ }), { data: ve = [] } = k({
33
34
  queryKey: ["broadcast-dimensions"],
34
- queryFn: () => o.request(v("/scope-dimensions")).then((e) => e.data ?? []).catch(() => []),
35
+ queryFn: () => i.request(v("/scope-dimensions")).then((e) => e.data ?? []).catch(() => []),
35
36
  staleTime: 5 * 6e4
36
- }), { data: ke = [] } = k({
37
+ }), { data: Ne = [] } = k({
37
38
  queryKey: ["broadcast-roles"],
38
- queryFn: () => o.request(v("/chat/roles")).then((e) => e.data ?? []).catch(() => []),
39
+ queryFn: () => i.request(v("/chat/roles")).then((e) => e.data ?? []).catch(() => []),
39
40
  staleTime: 5 * 6e4
40
- }), { data: ae = [] } = k({
41
+ }), { data: re = [] } = k({
41
42
  queryKey: ["broadcasts"],
42
- queryFn: () => o.request(v("/announcements")).then((e) => e.data ?? [])
43
+ queryFn: () => i.request(v("/announcements")).then((e) => e.data ?? [])
43
44
  });
44
- je("broadcasts", () => {
45
+ Fe("broadcasts", () => {
45
46
  c.invalidateQueries({ queryKey: ["broadcasts"] }), c.invalidateQueries({ queryKey: ["broadcast-receipt-summary"] }), c.invalidateQueries({ queryKey: ["broadcast-receipts"] });
46
47
  });
47
- const w = z(() => {
48
+ const w = Y(() => {
48
49
  const e = [];
49
- return g && e.push(_), m && e.push("email"), d && e.push("sms"), I && e.push("login"), e;
50
- }, [g, _, m, d, I]), L = z(
51
- () => K.map((e) => {
52
- const i = {};
53
- for (const [f, S] of Object.entries(e)) f && S.length > 0 && (i[f] = S);
54
- return i;
50
+ return g && e.push(_), m && e.push("email"), d && e.push("sms"), Q && e.push("login"), e;
51
+ }, [g, _, m, d, Q]), K = Y(
52
+ () => F.map((e) => {
53
+ const l = {};
54
+ for (const [f, S] of Object.entries(e)) f && S.length > 0 && (l[f] = S);
55
+ return l;
55
56
  }).filter((e) => Object.keys(e).length > 0),
56
- [K]
57
- ), F = z(
57
+ [F]
58
+ ), P = Y(
58
59
  () => ({
59
- ...L.length > 0 ? { groups: L } : {},
60
- ...$.length > 0 ? { roles: $ } : {}
60
+ ...K.length > 0 ? { groups: K } : {},
61
+ ...A.length > 0 ? { roles: A } : {}
61
62
  }),
62
- [L, $]
63
- ), P = C({
64
- mutationFn: () => o.request(
63
+ [K, A]
64
+ ), [ne, E] = u(null), C = $({
65
+ mutationFn: (e) => i.request(
65
66
  j("/announcements", {
67
+ ...e != null && e.confirm ? { confirm_audience: !0 } : {},
66
68
  subject: b.trim() || void 0,
67
69
  message: s.trim(),
68
- severity: l,
70
+ severity: o,
69
71
  channels: w,
70
- starts_at: Y || void 0,
71
- scheduled_send_at: R || void 0,
72
- ends_at: Z || void 0,
73
- require_ack: g && _ === "banner" ? Q : !1,
74
- audience: F,
75
- ...te()
72
+ starts_at: Z || void 0,
73
+ scheduled_send_at: M || void 0,
74
+ ends_at: J || void 0,
75
+ require_ack: g && _ === "banner" ? R : !1,
76
+ audience: P,
77
+ ...ae()
76
78
  })
77
79
  ),
78
80
  onSuccess: (e) => {
79
- const i = e.data.scheduled_for;
81
+ E(null);
82
+ const l = e.data.scheduled_for;
80
83
  q(
81
- i ? `Scheduled — delivers ${new Date(i).toLocaleString()}. Cancel from the history below.` : w.some((f) => f !== "banner") ? `Sent — reached ${e.data.delivered} recipient(s).` : "Banner published."
82
- ), u(""), h(""), M(""), W(""), ee(""), c.invalidateQueries({ queryKey: ["broadcasts"] }), c.invalidateQueries({ queryKey: ["announcements-active"] });
84
+ l ? `Scheduled — delivers ${new Date(l).toLocaleString()}. Cancel from the history below.` : w.some((f) => f !== "banner") ? `Sent — reached ${e.data.delivered} recipient(s).` : "Banner published."
85
+ ), p(""), h(""), H(""), X(""), te(""), c.invalidateQueries({ queryKey: ["broadcasts"] }), c.invalidateQueries({ queryKey: ["announcements-active"] });
83
86
  },
84
- onError: (e) => q(e.message)
85
- }), D = s.trim().length > 0 && w.length > 0 && !P.isPending, { data: re = [] } = k({
87
+ onError: (e) => {
88
+ const l = Pe(e);
89
+ if (l) {
90
+ E(l);
91
+ return;
92
+ }
93
+ q(e.message);
94
+ }
95
+ }), D = s.trim().length > 0 && w.length > 0 && !C.isPending, { data: se = [] } = k({
86
96
  queryKey: ["broadcast-templates"],
87
- queryFn: () => o.request(v("/announcements/templates")).then((e) => e.data ?? []).catch(() => []),
97
+ queryFn: () => i.request(v("/announcements/templates")).then((e) => e.data ?? []).catch(() => []),
88
98
  staleTime: 6e4
89
- }), ne = C({
90
- mutationFn: (e) => o.request(
99
+ }), de = $({
100
+ mutationFn: (e) => i.request(
91
101
  j("/announcements/templates", {
92
102
  name: e,
93
103
  snapshot: {
94
104
  subject: b,
95
105
  message: s,
96
- severity: l,
106
+ severity: o,
97
107
  channels: w,
98
- require_ack: Q,
99
- audience: F
108
+ require_ack: R,
109
+ audience: P
100
110
  }
101
111
  })
102
112
  ),
103
113
  onSuccess: () => void c.invalidateQueries({ queryKey: ["broadcast-templates"] })
104
- }), ve = (e) => {
105
- const i = e.snapshot ?? {};
106
- typeof i.subject == "string" && h(i.subject), typeof i.message == "string" && u(i.message);
107
- }, [U, se] = p(""), [Ne, de] = p(!1), B = C({
108
- mutationFn: () => o.request(
114
+ }), we = (e) => {
115
+ const l = e.snapshot ?? {};
116
+ typeof l.subject == "string" && h(l.subject), typeof l.message == "string" && p(l.message);
117
+ }, [B, le] = u(""), [Se, oe] = u(!1), G = $({
118
+ mutationFn: () => i.request(
109
119
  j("/announcements/test-send", {
110
120
  subject: b.trim() || void 0,
111
121
  message: s.trim(),
112
122
  channels: w.filter((e) => e !== "banner"),
113
- ...te()
123
+ ...ae()
114
124
  })
115
125
  ),
116
126
  onSuccess: (e) => q(
117
- `Test sent to you — ${Object.entries(e.data ?? {}).map(([i, f]) => `${i}: ${f}`).join(", ")}`
127
+ `Test sent to you — ${Object.entries(e.data ?? {}).map(([l, f]) => `${l}: ${f}`).join(", ")}`
118
128
  ),
119
129
  onError: (e) => q(e.message)
120
- }), E = (/* @__PURE__ */ new Date()).getHours(), we = !R && (E >= 21 || E < 7), Se = C({
121
- mutationFn: ({ id: e, body: i }) => o.request(Te(`/announcements/${e}`, i)),
130
+ }), O = (/* @__PURE__ */ new Date()).getHours(), _e = !M && (O >= 21 || O < 7), qe = $({
131
+ mutationFn: ({ id: e, body: l }) => i.request(Le(`/announcements/${e}`, l)),
122
132
  onSuccess: () => {
123
133
  c.invalidateQueries({ queryKey: ["broadcasts"] }), c.invalidateQueries({ queryKey: ["announcements-active"] });
124
134
  }
125
- }), _e = C({
126
- mutationFn: (e) => o.request(Ae(`/announcements/${e}`)),
135
+ }), Ce = $({
136
+ mutationFn: (e) => i.request(je(`/announcements/${e}`)),
127
137
  onSuccess: () => {
128
138
  c.invalidateQueries({ queryKey: ["broadcasts"] }), c.invalidateQueries({ queryKey: ["announcements-active"] });
129
139
  }
@@ -133,43 +143,43 @@ function et({ className: r }) {
133
143
  /* @__PURE__ */ t("p", { className: "text-[13px] font-semibold text-slate-800 dark:text-foreground", children: "Audience" }),
134
144
  /* @__PURE__ */ t("p", { className: "mt-0.5 text-[11.5px] text-slate-400", children: "No selection = everyone. Zone/role targeting narrows both send channels and who sees a banner." }),
135
145
  /* @__PURE__ */ a("div", { className: "mt-3 space-y-2", children: [
136
- K.map((e, i) => /* @__PURE__ */ t(
137
- Oe,
146
+ F.map((e, l) => /* @__PURE__ */ t(
147
+ Me,
138
148
  {
139
- index: i,
149
+ index: l,
140
150
  group: e,
141
- dimensions: ye,
142
- onChange: (f) => H((S) => S.map((G, qe) => qe === i ? f : G)),
143
- onRemove: () => H((f) => f.filter((S, G) => G !== i))
151
+ dimensions: ve,
152
+ onChange: (f) => V((S) => S.map((z, $e) => $e === l ? f : z)),
153
+ onRemove: () => V((f) => f.filter((S, z) => z !== l))
144
154
  },
145
- i
155
+ l
146
156
  )),
147
157
  /* @__PURE__ */ a(
148
158
  "button",
149
159
  {
150
160
  type: "button",
151
- onClick: () => H((e) => [...e, {}]),
161
+ onClick: () => V((e) => [...e, {}]),
152
162
  className: "rounded-md border border-dashed border-slate-300 px-3 py-1.5 text-[11.5px] text-slate-500 hover:border-slate-400 hover:text-slate-700 dark:border-border dark:text-muted-foreground",
153
163
  children: [
154
164
  "+",
155
165
  " ",
156
- K.length === 0 ? "Target by scope (e.g. Zone 2 + Node Splits)" : "Add another group (OR)"
166
+ F.length === 0 ? "Target by scope (e.g. Zone 2 + Node Splits)" : "Add another group (OR)"
157
167
  ]
158
168
  }
159
169
  )
160
170
  ] }),
161
171
  /* @__PURE__ */ a("div", { className: "mt-3", children: [
162
172
  /* @__PURE__ */ t("p", { className: "mb-1 text-[11.5px] font-medium text-slate-700 dark:text-foreground", children: "Limit to roles" }),
163
- /* @__PURE__ */ t("div", { className: "flex flex-wrap gap-1.5", children: ke.map((e) => {
164
- const i = $.includes(e.id);
173
+ /* @__PURE__ */ t("div", { className: "flex flex-wrap gap-1.5", children: Ne.map((e) => {
174
+ const l = A.includes(e.id);
165
175
  return /* @__PURE__ */ t(
166
176
  "button",
167
177
  {
168
178
  type: "button",
169
- onClick: () => fe((f) => i ? f.filter((S) => S !== e.id) : [...f, e.id]),
179
+ onClick: () => ke((f) => l ? f.filter((S) => S !== e.id) : [...f, e.id]),
170
180
  className: y(
171
181
  "rounded-full border px-2.5 py-0.5 text-[11.5px] transition-colors",
172
- i ? "border-nvr-cyan/50 bg-nvr-cyan/10 text-slate-800 dark:text-foreground" : "border-slate-200 text-slate-500 hover:text-slate-700 dark:border-border dark:text-muted-foreground"
182
+ l ? "border-nvr-cyan/50 bg-nvr-cyan/10 text-slate-800 dark:text-foreground" : "border-slate-200 text-slate-500 hover:text-slate-700 dark:border-border dark:text-muted-foreground"
173
183
  ),
174
184
  children: e.name
175
185
  },
@@ -178,10 +188,10 @@ function et({ className: r }) {
178
188
  }) })
179
189
  ] }),
180
190
  /* @__PURE__ */ t("div", { className: "mt-3 border-t border-slate-100 pt-2.5 dark:border-border", children: /* @__PURE__ */ t(
181
- me,
191
+ pe,
182
192
  {
183
- audience: F,
184
- everyone: L.length === 0 && $.length === 0,
193
+ audience: P,
194
+ everyone: K.length === 0 && A.length === 0,
185
195
  label: "Sending to"
186
196
  }
187
197
  ) })
@@ -189,13 +199,13 @@ function et({ className: r }) {
189
199
  /* @__PURE__ */ a("div", { className: "max-w-[760px] rounded-lg border border-slate-200 bg-white p-4 dark:border-border dark:bg-card", children: [
190
200
  /* @__PURE__ */ t("p", { className: "text-[13px] font-semibold text-slate-800 dark:text-foreground", children: "Message" }),
191
201
  /* @__PURE__ */ t(
192
- Le,
202
+ De,
193
203
  {
194
- audience: F,
204
+ audience: P,
195
205
  channels: w,
196
- severity: l,
206
+ severity: o,
197
207
  onUse: (e) => {
198
- e.subject !== void 0 && h(e.subject), u(e.message);
208
+ e.subject !== void 0 && h(e.subject), p(e.message);
199
209
  }
200
210
  }
201
211
  ),
@@ -212,7 +222,7 @@ function et({ className: r }) {
212
222
  "textarea",
213
223
  {
214
224
  value: s,
215
- onChange: (e) => u(e.target.value),
225
+ onChange: (e) => p(e.target.value),
216
226
  rows: 5,
217
227
  placeholder: "Compose your message… (plain text; line breaks are kept)",
218
228
  className: "mt-2 w-full rounded-md border border-slate-200 bg-background px-2.5 py-2 text-[12.5px] text-slate-800 dark:border-border dark:text-foreground"
@@ -224,7 +234,7 @@ function et({ className: r }) {
224
234
  "button",
225
235
  {
226
236
  type: "button",
227
- onClick: () => u((i) => i ? `${i} ${e}` : e),
237
+ onClick: () => p((l) => l ? `${l} ${e}` : e),
228
238
  className: "rounded bg-slate-100 px-1.5 py-0.5 font-mono text-[10.5px] text-slate-600 hover:bg-slate-200 dark:bg-muted dark:text-slate-300 dark:hover:bg-accent",
229
239
  title: `Insert ${e} — replaced with each recipient's ${e === "{{name}}" ? "full name" : "first name"} at send time`,
230
240
  children: e
@@ -245,15 +255,15 @@ function et({ className: r }) {
245
255
  "select",
246
256
  {
247
257
  value: T,
248
- onChange: (e) => W(e.target.value),
258
+ onChange: (e) => X(e.target.value),
249
259
  className: "h-7 max-w-[320px] rounded-md border border-slate-200 bg-background px-1.5 text-[12px] text-slate-800 dark:border-border dark:text-foreground",
250
260
  "aria-label": "Attach a video",
251
261
  "data-broadcast-video-id": !0,
252
262
  children: [
253
263
  /* @__PURE__ */ t("option", { value: "", children: "None" }),
254
- (((le = A.data) == null ? void 0 : le.data) ?? []).map((e) => /* @__PURE__ */ a("option", { value: e.id, children: [
264
+ (((ie = L.data) == null ? void 0 : ie.data) ?? []).map((e) => /* @__PURE__ */ a("option", { value: e.id, children: [
255
265
  e.title || "Untitled video",
256
- e.duration_ms != null ? ` (${Pe(e.duration_ms)})` : ""
266
+ e.duration_ms != null ? ` (${Ie(e.duration_ms)})` : ""
257
267
  ] }, e.id))
258
268
  ]
259
269
  }
@@ -267,8 +277,8 @@ function et({ className: r }) {
267
277
  type: "number",
268
278
  min: 0,
269
279
  step: 1,
270
- value: X,
271
- onChange: (e) => ee(e.target.value),
280
+ value: ee,
281
+ onChange: (e) => te(e.target.value),
272
282
  placeholder: "0",
273
283
  className: "h-7 w-20 rounded-md border border-slate-200 bg-background px-1.5 text-[12px] dark:border-border",
274
284
  "aria-label": "Start at (seconds)",
@@ -277,14 +287,14 @@ function et({ className: r }) {
277
287
  ),
278
288
  "seconds"
279
289
  ] }),
280
- A.hasNextPage && /* @__PURE__ */ t(
290
+ L.hasNextPage && /* @__PURE__ */ t(
281
291
  "button",
282
292
  {
283
293
  type: "button",
284
- onClick: () => void A.fetchNextPage(),
285
- disabled: A.isFetchingNextPage,
294
+ onClick: () => void L.fetchNextPage(),
295
+ disabled: L.isFetchingNextPage,
286
296
  className: "rounded border border-slate-200 px-1.5 py-0.5 text-[11px] hover:bg-slate-50 dark:border-border dark:hover:bg-muted",
287
- children: A.isFetchingNextPage ? "Loading…" : "More videos"
297
+ children: L.isFetchingNextPage ? "Loading…" : "More videos"
288
298
  }
289
299
  ),
290
300
  T && /* @__PURE__ */ t("span", { className: "text-slate-400 dark:text-slate-500", children: "Shown as a card with a link to that moment — only to people who can watch the video." })
@@ -298,7 +308,7 @@ function et({ className: r }) {
298
308
  {
299
309
  type: "checkbox",
300
310
  checked: g,
301
- onChange: (e) => ue(e.target.checked),
311
+ onChange: (e) => xe(e.target.checked),
302
312
  className: "h-3.5 w-3.5"
303
313
  }
304
314
  ),
@@ -311,7 +321,7 @@ function et({ className: r }) {
311
321
  "button",
312
322
  {
313
323
  type: "button",
314
- onClick: () => xe(e.value),
324
+ onClick: () => be(e.value),
315
325
  className: y(
316
326
  "rounded px-2 py-0.5 text-[11px] font-medium transition-colors",
317
327
  _ === e.value ? "bg-nvr-cyan/10 text-slate-800 dark:text-foreground" : "text-slate-400 hover:text-slate-600"
@@ -342,8 +352,8 @@ function et({ className: r }) {
342
352
  "input",
343
353
  {
344
354
  type: "checkbox",
345
- checked: I,
346
- onChange: (e) => pe(e.target.checked),
355
+ checked: Q,
356
+ onChange: (e) => he(e.target.checked),
347
357
  className: "h-3.5 w-3.5"
348
358
  }
349
359
  ),
@@ -351,7 +361,7 @@ function et({ className: r }) {
351
361
  ]
352
362
  }
353
363
  ),
354
- (V == null ? void 0 : V.sms_enabled) && /* @__PURE__ */ a("label", { className: "flex cursor-pointer items-center gap-1.5 text-[12px] text-slate-600 dark:text-muted-foreground", children: [
364
+ (U == null ? void 0 : U.sms_enabled) && /* @__PURE__ */ a("label", { className: "flex cursor-pointer items-center gap-1.5 text-[12px] text-slate-600 dark:text-muted-foreground", children: [
355
365
  /* @__PURE__ */ t(
356
366
  "input",
357
367
  {
@@ -363,14 +373,14 @@ function et({ className: r }) {
363
373
  ),
364
374
  "Text (SMS)"
365
375
  ] }),
366
- g && _ === "banner" && /* @__PURE__ */ a(oe, { children: [
376
+ g && _ === "banner" && /* @__PURE__ */ a(ce, { children: [
367
377
  /* @__PURE__ */ a("label", { className: "flex cursor-pointer items-center gap-1.5 text-[12px] text-slate-600 dark:text-slate-300", children: [
368
378
  /* @__PURE__ */ t(
369
379
  "input",
370
380
  {
371
381
  type: "checkbox",
372
- checked: Q,
373
- onChange: (e) => he(e.target.checked),
382
+ checked: R,
383
+ onChange: (e) => ge(e.target.checked),
374
384
  className: "h-3.5 w-3.5"
375
385
  }
376
386
  ),
@@ -383,10 +393,10 @@ function et({ className: r }) {
383
393
  onClick: () => n(e),
384
394
  className: y(
385
395
  "flex items-center gap-1.5 rounded px-2 py-0.5 text-[11px] font-medium capitalize transition-colors",
386
- l === e ? "bg-nvr-cyan/10 text-slate-800 dark:text-foreground" : "text-slate-400 hover:text-slate-600"
396
+ o === e ? "bg-nvr-cyan/10 text-slate-800 dark:text-foreground" : "text-slate-400 hover:text-slate-600"
387
397
  ),
388
398
  children: [
389
- /* @__PURE__ */ t("span", { className: y("h-1.5 w-1.5 rounded-full", ce[e]) }),
399
+ /* @__PURE__ */ t("span", { className: y("h-1.5 w-1.5 rounded-full", ue[e]) }),
390
400
  e
391
401
  ]
392
402
  },
@@ -398,8 +408,8 @@ function et({ className: r }) {
398
408
  "input",
399
409
  {
400
410
  type: "datetime-local",
401
- value: Y,
402
- onChange: (e) => be(e.target.value),
411
+ value: Z,
412
+ onChange: (e) => fe(e.target.value),
403
413
  className: "h-7 rounded-md border border-slate-200 bg-background px-1.5 text-[12px] dark:border-border"
404
414
  }
405
415
  )
@@ -410,8 +420,8 @@ function et({ className: r }) {
410
420
  "input",
411
421
  {
412
422
  type: "datetime-local",
413
- value: Z,
414
- onChange: (e) => ge(e.target.value),
423
+ value: J,
424
+ onChange: (e) => ye(e.target.value),
415
425
  className: "h-7 rounded-md border border-slate-200 bg-background px-1.5 text-[12px] dark:border-border"
416
426
  }
417
427
  )
@@ -426,8 +436,8 @@ function et({ className: r }) {
426
436
  "input",
427
437
  {
428
438
  type: "datetime-local",
429
- value: R,
430
- onChange: (e) => M(e.target.value),
439
+ value: M,
440
+ onChange: (e) => H(e.target.value),
431
441
  title: "Leave empty to send immediately. With a time set, every channel (banner included) waits until then.",
432
442
  className: "h-7 rounded-md border border-slate-200 bg-background px-1.5 text-[12px] dark:border-border"
433
443
  }
@@ -437,13 +447,13 @@ function et({ className: r }) {
437
447
  "button",
438
448
  {
439
449
  type: "button",
440
- disabled: !D || B.isPending,
450
+ disabled: !D || G.isPending,
441
451
  onClick: () => {
442
- q(null), B.mutate();
452
+ q(null), G.mutate();
443
453
  },
444
454
  "data-tip": "Send this compose to YOURSELF over the picked channels first (#429)",
445
455
  className: "h-8 rounded-md border border-slate-200 px-3 text-[12.5px] font-medium text-slate-600 hover:bg-muted disabled:opacity-50 dark:border-border dark:text-slate-300",
446
- children: B.isPending ? "Testing…" : "Test on me"
456
+ children: G.isPending ? "Testing…" : "Test on me"
447
457
  }
448
458
  ),
449
459
  /* @__PURE__ */ t(
@@ -452,18 +462,18 @@ function et({ className: r }) {
452
462
  type: "button",
453
463
  disabled: !D,
454
464
  onClick: () => {
455
- q(null), P.mutate();
465
+ q(null), E(null), C.mutate(void 0);
456
466
  },
457
467
  className: "h-8 rounded-md bg-nvr-cyan px-4 text-[12.5px] font-medium text-white disabled:opacity-50",
458
- children: P.isPending ? "Sending…" : "Send"
468
+ children: C.isPending ? "Sending…" : "Send"
459
469
  }
460
470
  ),
461
- Ne ? /* @__PURE__ */ a("span", { className: "flex items-center gap-1", children: [
471
+ Se ? /* @__PURE__ */ a("span", { className: "flex items-center gap-1", children: [
462
472
  /* @__PURE__ */ t(
463
473
  "input",
464
474
  {
465
- value: U,
466
- onChange: (e) => se(e.target.value),
475
+ value: B,
476
+ onChange: (e) => le(e.target.value),
467
477
  placeholder: "Template name…",
468
478
  className: "h-7 w-40 rounded-md border border-slate-200 bg-background px-1.5 text-[12px] dark:border-border"
469
479
  }
@@ -472,9 +482,9 @@ function et({ className: r }) {
472
482
  "button",
473
483
  {
474
484
  type: "button",
475
- disabled: !U.trim() || ne.isPending,
485
+ disabled: !B.trim() || de.isPending,
476
486
  onClick: () => {
477
- ne.mutate(U.trim()), de(!1), se("");
487
+ de.mutate(B.trim()), oe(!1), le("");
478
488
  },
479
489
  className: "h-7 rounded-md border border-slate-200 px-2 text-[11.5px] hover:bg-muted dark:border-border",
480
490
  children: "Save"
@@ -485,18 +495,29 @@ function et({ className: r }) {
485
495
  {
486
496
  type: "button",
487
497
  disabled: !s.trim(),
488
- onClick: () => de(!0),
498
+ onClick: () => oe(!0),
489
499
  "data-tip": "Save this compose (audience + channels + text) as a reusable template (#104)",
490
500
  className: "h-8 rounded-md border border-dashed border-slate-300 px-2.5 text-[11.5px] text-slate-500 hover:text-slate-700 disabled:opacity-40 dark:border-border",
491
501
  children: "☆ Save template"
492
502
  }
493
503
  ),
494
- !D && !P.isPending && /* @__PURE__ */ t("span", { className: "text-[11.5px] text-slate-400", children: "A message and at least one channel are required." }),
495
- J && /* @__PURE__ */ t("span", { className: "text-[12px] font-medium text-emerald-600 dark:text-emerald-400", children: J })
504
+ !D && !C.isPending && /* @__PURE__ */ t("span", { className: "text-[11.5px] text-slate-400", children: "A message and at least one channel are required." }),
505
+ W && /* @__PURE__ */ t("span", { className: "text-[12px] font-medium text-emerald-600 dark:text-emerald-400", children: W })
496
506
  ] }),
497
- we && D && /* @__PURE__ */ a("p", { className: "mt-2 rounded-md bg-amber-50 px-3 py-1.5 text-[12px] text-amber-700 dark:bg-amber-400/10 dark:text-amber-400", children: [
507
+ ne && /* @__PURE__ */ t(
508
+ Ee,
509
+ {
510
+ className: "mt-3",
511
+ preview: ne,
512
+ busy: C.isPending,
513
+ confirmLabel: "Confirm and send",
514
+ onConfirm: () => C.mutate({ confirm: !0 }),
515
+ onCancel: () => E(null)
516
+ }
517
+ ),
518
+ _e && D && /* @__PURE__ */ a("p", { className: "mt-2 rounded-md bg-amber-50 px-3 py-1.5 text-[12px] text-amber-700 dark:bg-amber-400/10 dark:text-amber-400", children: [
498
519
  "It's ",
499
- E >= 21 ? "late" : "early",
520
+ O >= 21 ? "late" : "early",
500
521
  " for most recipients — consider the schedule field so this lands in the morning instead of overnight.",
501
522
  " ",
502
523
  /* @__PURE__ */ t(
@@ -506,19 +527,19 @@ function et({ className: r }) {
506
527
  className: "font-medium underline underline-offset-2",
507
528
  onClick: () => {
508
529
  const e = /* @__PURE__ */ new Date();
509
- E >= 21 && e.setDate(e.getDate() + 1), e.setHours(8, 0, 0, 0);
510
- const i = (f) => String(f).padStart(2, "0");
511
- M(
512
- `${e.getFullYear()}-${i(e.getMonth() + 1)}-${i(e.getDate())}T${i(e.getHours())}:${i(e.getMinutes())}`
530
+ O >= 21 && e.setDate(e.getDate() + 1), e.setHours(8, 0, 0, 0);
531
+ const l = (f) => String(f).padStart(2, "0");
532
+ H(
533
+ `${e.getFullYear()}-${l(e.getMonth() + 1)}-${l(e.getDate())}T${l(e.getHours())}:${l(e.getMinutes())}`
513
534
  );
514
535
  },
515
536
  children: "Schedule for 8:00 AM"
516
537
  }
517
538
  )
518
539
  ] }),
519
- re.length > 0 && /* @__PURE__ */ a("div", { className: "mt-2 flex flex-wrap items-center gap-1.5", children: [
540
+ se.length > 0 && /* @__PURE__ */ a("div", { className: "mt-2 flex flex-wrap items-center gap-1.5", children: [
520
541
  /* @__PURE__ */ t("span", { className: "text-[11px] text-slate-400", children: "Templates:" }),
521
- re.map((e) => /* @__PURE__ */ t(
542
+ se.map((e) => /* @__PURE__ */ t(
522
543
  "span",
523
544
  {
524
545
  className: "inline-flex items-center overflow-hidden rounded-full border border-slate-200 dark:border-border",
@@ -526,7 +547,7 @@ function et({ className: r }) {
526
547
  "button",
527
548
  {
528
549
  type: "button",
529
- onClick: () => ve(e),
550
+ onClick: () => we(e),
530
551
  className: "px-2 py-0.5 text-[11.5px] text-slate-600 hover:bg-muted dark:text-slate-300",
531
552
  children: e.name
532
553
  }
@@ -538,30 +559,30 @@ function et({ className: r }) {
538
559
  ] }),
539
560
  /* @__PURE__ */ a("div", { className: "max-w-[760px] space-y-2", children: [
540
561
  /* @__PURE__ */ t("p", { className: "text-[11px] font-semibold uppercase tracking-wide text-slate-500 dark:text-muted-foreground", children: "History" }),
541
- ae.length === 0 && /* @__PURE__ */ t("p", { className: "text-[12px] text-slate-400", children: "Nothing sent yet." }),
542
- ae.map((e) => /* @__PURE__ */ t(
543
- Ee,
562
+ re.length === 0 && /* @__PURE__ */ t("p", { className: "text-[12px] text-slate-400", children: "Nothing sent yet." }),
563
+ re.map((e) => /* @__PURE__ */ t(
564
+ Re,
544
565
  {
545
566
  broadcast: e,
546
- onPatch: Se.mutate,
547
- onRemove: _e.mutate
567
+ onPatch: qe.mutate,
568
+ onRemove: Ce.mutate
548
569
  },
549
570
  e.id
550
571
  ))
551
572
  ] })
552
573
  ] });
553
574
  }
554
- function Ee({
575
+ function Re({
555
576
  broadcast: r,
556
- onPatch: o,
577
+ onPatch: i,
557
578
  onRemove: c
558
579
  }) {
559
- const b = O(), h = ie(), [s, u] = p(!1), { data: l } = k({
580
+ const b = I(), h = me(), [s, p] = u(!1), { data: o } = k({
560
581
  queryKey: ["broadcast-receipt-summary", r.id],
561
582
  queryFn: () => b.request(v(`/announcements/${r.id}/receipts/summary`)).then((d) => d.data),
562
583
  enabled: s,
563
584
  staleTime: 5e3
564
- }), n = C({
585
+ }), n = $({
565
586
  mutationFn: () => b.request(
566
587
  j(`/announcements/${r.id}/nudge`, {})
567
588
  ),
@@ -579,7 +600,7 @@ function Ee({
579
600
  });
580
601
  return /* @__PURE__ */ a("div", { className: "rounded-lg border border-slate-200 bg-white dark:border-border dark:bg-card", children: [
581
602
  /* @__PURE__ */ a("div", { className: "flex items-start gap-3 px-4 py-3", children: [
582
- /* @__PURE__ */ t("span", { className: y("mt-1.5 h-2 w-2 shrink-0 rounded-full", ce[r.severity]) }),
603
+ /* @__PURE__ */ t("span", { className: y("mt-1.5 h-2 w-2 shrink-0 rounded-full", ue[r.severity]) }),
583
604
  /* @__PURE__ */ a("div", { className: "min-w-0 flex-1", children: [
584
605
  r.subject && /* @__PURE__ */ t("p", { className: "text-[12.5px] font-medium text-slate-800 dark:text-foreground", children: r.subject }),
585
606
  /* @__PURE__ */ t("p", { className: "text-[12.5px] text-slate-600 dark:text-muted-foreground", children: r.message }),
@@ -612,7 +633,7 @@ function Ee({
612
633
  "button",
613
634
  {
614
635
  type: "button",
615
- onClick: () => u((d) => !d),
636
+ onClick: () => p((d) => !d),
616
637
  className: "underline decoration-dotted underline-offset-2 hover:text-slate-600 dark:hover:text-muted-foreground",
617
638
  children: [
618
639
  s ? "hide receipts" : "who saw this?",
@@ -630,7 +651,7 @@ function Ee({
630
651
  "button",
631
652
  {
632
653
  type: "button",
633
- onClick: () => o({ id: r.id, body: { is_active: !r.is_active } }),
654
+ onClick: () => i({ id: r.id, body: { is_active: !r.is_active } }),
634
655
  className: y(
635
656
  "shrink-0 rounded-full border px-2 py-0.5 text-[11px] font-medium",
636
657
  r.is_active ? "border-emerald-300 text-emerald-700 dark:border-emerald-500/40 dark:text-emerald-400" : "border-slate-200 text-slate-400 dark:border-border"
@@ -648,7 +669,7 @@ function Ee({
648
669
  }
649
670
  )
650
671
  ] }),
651
- s && l && (l.totals.delivered > 0 || l.totals.acked > 0) && /* @__PURE__ */ a(
672
+ s && o && (o.totals.delivered > 0 || o.totals.acked > 0) && /* @__PURE__ */ a(
652
673
  "div",
653
674
  {
654
675
  className: "border-t border-slate-100 px-4 py-3 dark:border-border",
@@ -658,17 +679,17 @@ function Ee({
658
679
  /* @__PURE__ */ t("p", { className: "text-[10.5px] font-semibold uppercase tracking-wide text-slate-400", children: "By audience" }),
659
680
  /* @__PURE__ */ a("span", { className: "text-[11.5px] text-slate-500 dark:text-muted-foreground", children: [
660
681
  "delivered ",
661
- /* @__PURE__ */ t("b", { children: l.totals.delivered }),
682
+ /* @__PURE__ */ t("b", { children: o.totals.delivered }),
662
683
  " · opened ",
663
- /* @__PURE__ */ t("b", { children: l.totals.opened }),
684
+ /* @__PURE__ */ t("b", { children: o.totals.opened }),
664
685
  " · acknowledged ",
665
- /* @__PURE__ */ t("b", { children: l.totals.acked }),
686
+ /* @__PURE__ */ t("b", { children: o.totals.acked }),
666
687
  " · still unread",
667
688
  " ",
668
- /* @__PURE__ */ t("b", { children: l.totals.unread })
689
+ /* @__PURE__ */ t("b", { children: o.totals.unread })
669
690
  ] }),
670
691
  /* @__PURE__ */ t("span", { className: "flex-1" }),
671
- l.totals.unread > 0 && /* @__PURE__ */ t(
692
+ o.totals.unread > 0 && /* @__PURE__ */ t(
672
693
  "button",
673
694
  {
674
695
  type: "button",
@@ -676,11 +697,11 @@ function Ee({
676
697
  onClick: () => n.mutate(),
677
698
  className: "rounded-md border border-amber-300 bg-amber-50 px-2.5 py-1 text-[11.5px] font-medium text-amber-800 hover:bg-amber-100 disabled:opacity-50 dark:border-amber-500/40 dark:bg-amber-500/10 dark:text-amber-300",
678
699
  "data-nvr-nudge": !0,
679
- children: n.isPending ? "Nudging…" : n.data ? `Nudged ${n.data.data.nudged}` : `Nudge ${l.totals.unread} unread`
700
+ children: n.isPending ? "Nudging…" : n.data ? `Nudged ${n.data.data.nudged}` : `Nudge ${o.totals.unread} unread`
680
701
  }
681
702
  )
682
703
  ] }),
683
- /* @__PURE__ */ t("div", { className: "mt-2 grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3", children: [["Role", l.by_role], ...Object.entries(l.by_dimension)].map(
704
+ /* @__PURE__ */ t("div", { className: "mt-2 grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3", children: [["Role", o.by_role], ...Object.entries(o.by_dimension)].map(
684
705
  ([d, N]) => /* @__PURE__ */ a("table", { className: "w-full text-[11.5px] tabular-nums", children: [
685
706
  /* @__PURE__ */ t("thead", { children: /* @__PURE__ */ a("tr", { className: "text-left text-[10px] uppercase tracking-wide text-slate-400", children: [
686
707
  /* @__PURE__ */ t("th", { className: "py-0.5 font-semibold", children: d }),
@@ -707,11 +728,11 @@ function Ee({
707
728
  ] }, g.label)) })
708
729
  ] }, d)
709
730
  ) }),
710
- l.unread_users.length > 0 && /* @__PURE__ */ a("p", { className: "mt-2 text-[11px] text-slate-400", children: [
731
+ o.unread_users.length > 0 && /* @__PURE__ */ a("p", { className: "mt-2 text-[11px] text-slate-400", children: [
711
732
  "Unread:",
712
733
  " ",
713
- l.unread_users.slice(0, 12).map((d) => d.name).join(", "),
714
- l.unread_users.length > 12 ? ` +${l.unread_users.length - 12} more` : ""
734
+ o.unread_users.slice(0, 12).map((d) => d.name).join(", "),
735
+ o.unread_users.length > 12 ? ` +${o.unread_users.length - 12} more` : ""
715
736
  ] })
716
737
  ]
717
738
  }
@@ -752,14 +773,14 @@ function Ee({
752
773
  ] })
753
774
  ] });
754
775
  }
755
- function Oe({
776
+ function Me({
756
777
  index: r,
757
- group: o,
778
+ group: i,
758
779
  dimensions: c,
759
780
  onChange: b,
760
781
  onRemove: h
761
782
  }) {
762
- const s = Object.keys(o), u = c.filter((n) => !s.includes(n.name)), l = s.length > 0 && s.every((n) => (o[n] ?? []).length > 0);
783
+ const s = Object.keys(i), p = c.filter((n) => !s.includes(n.name)), o = s.length > 0 && s.every((n) => (i[n] ?? []).length > 0);
763
784
  return /* @__PURE__ */ a("div", { className: "rounded-lg border border-slate-200 bg-slate-50/60 p-3 dark:border-border dark:bg-muted/30", children: [
764
785
  /* @__PURE__ */ a("div", { className: "flex items-center justify-between", children: [
765
786
  /* @__PURE__ */ a("p", { className: "text-[10.5px] font-semibold uppercase tracking-wide text-slate-400", children: [
@@ -768,10 +789,10 @@ function Oe({
768
789
  s.length > 1 && " · all conditions must match"
769
790
  ] }),
770
791
  /* @__PURE__ */ a("div", { className: "flex items-center gap-2.5", children: [
771
- l && /* @__PURE__ */ t(
772
- me,
792
+ o && /* @__PURE__ */ t(
793
+ pe,
773
794
  {
774
- audience: { groups: [o] },
795
+ audience: { groups: [i] },
775
796
  everyone: !1,
776
797
  label: "Matches",
777
798
  compact: !0
@@ -794,45 +815,45 @@ function Oe({
794
815
  return /* @__PURE__ */ a("div", { className: "flex flex-wrap items-start gap-2", children: [
795
816
  /* @__PURE__ */ t("span", { className: "mt-0.5 w-[110px] shrink-0 text-[11.5px] font-medium text-slate-600 dark:text-muted-foreground", children: (m == null ? void 0 : m.label) ?? n }),
796
817
  /* @__PURE__ */ t("div", { className: "min-w-0 flex-1", children: m ? /* @__PURE__ */ t(
797
- Ie,
818
+ He,
798
819
  {
799
820
  dim: m,
800
- selected: o[n] ?? [],
821
+ selected: i[n] ?? [],
801
822
  onChange: (x) => {
802
- const d = { ...o };
823
+ const d = { ...i };
803
824
  x.length === 0 ? delete d[n] : d[n] = x, b(d);
804
825
  }
805
826
  }
806
827
  ) : /* @__PURE__ */ t("span", { className: "text-[11.5px] text-slate-400", children: "Unknown scope" }) })
807
828
  ] }, n);
808
829
  }),
809
- u.length > 0 && /* @__PURE__ */ t("div", { className: "w-[200px]", children: /* @__PURE__ */ t(
810
- De,
830
+ p.length > 0 && /* @__PURE__ */ t("div", { className: "w-[200px]", children: /* @__PURE__ */ t(
831
+ Qe,
811
832
  {
812
833
  value: "",
813
834
  onChange: (n) => {
814
- n && b({ ...o, [n]: [] });
835
+ n && b({ ...i, [n]: [] });
815
836
  },
816
- options: u.map((n) => ({ value: n.name, label: n.label })),
837
+ options: p.map((n) => ({ value: n.name, label: n.label })),
817
838
  placeholder: s.length === 0 ? "Pick a scope…" : "+ And also…"
818
839
  }
819
840
  ) })
820
841
  ] })
821
842
  ] });
822
843
  }
823
- function Ie({
844
+ function He({
824
845
  dim: r,
825
- selected: o,
846
+ selected: i,
826
847
  onChange: c
827
848
  }) {
828
- const b = O(), { data: h = [] } = k({
849
+ const b = I(), { data: h = [] } = k({
829
850
  queryKey: ["broadcast-dim-options", r.target_collection],
830
851
  queryFn: () => b.request(
831
852
  v(`/items/${r.target_collection}`, { limit: 200 })
832
853
  ).then(
833
- (s) => (s.data ?? []).map((u) => ({
834
- id: u.id,
835
- label: String(u[r.display_field || "name"] ?? u.id)
854
+ (s) => (s.data ?? []).map((p) => ({
855
+ id: p.id,
856
+ label: String(p[r.display_field || "name"] ?? p.id)
836
857
  }))
837
858
  ),
838
859
  staleTime: 5 * 6e4
@@ -840,17 +861,17 @@ function Ie({
840
861
  return /* @__PURE__ */ a("div", { className: "flex flex-wrap gap-1.5", children: [
841
862
  h.length === 0 && /* @__PURE__ */ t("span", { className: "text-[11.5px] text-slate-400", children: "Loading…" }),
842
863
  h.map((s) => {
843
- const u = o.some((l) => String(l) === String(s.id));
864
+ const p = i.some((o) => String(o) === String(s.id));
844
865
  return /* @__PURE__ */ t(
845
866
  "button",
846
867
  {
847
868
  type: "button",
848
869
  onClick: () => c(
849
- u ? o.filter((l) => String(l) !== String(s.id)) : [...o, s.id]
870
+ p ? i.filter((o) => String(o) !== String(s.id)) : [...i, s.id]
850
871
  ),
851
872
  className: y(
852
873
  "rounded-full border px-2.5 py-0.5 text-[11.5px] transition-colors",
853
- u ? "border-nvr-cyan/50 bg-nvr-cyan/10 text-slate-800 dark:text-foreground" : "border-slate-200 bg-white text-slate-500 hover:text-slate-700 dark:border-border dark:bg-card dark:text-muted-foreground"
874
+ p ? "border-nvr-cyan/50 bg-nvr-cyan/10 text-slate-800 dark:text-foreground" : "border-slate-200 bg-white text-slate-500 hover:text-slate-700 dark:border-border dark:bg-card dark:text-muted-foreground"
854
875
  ),
855
876
  children: s.label
856
877
  },
@@ -859,28 +880,28 @@ function Ie({
859
880
  })
860
881
  ] });
861
882
  }
862
- function me({
883
+ function pe({
863
884
  audience: r,
864
- everyone: o,
885
+ everyone: i,
865
886
  label: c,
866
887
  compact: b
867
888
  }) {
868
- const h = O(), [s, u] = p(!1), l = JSON.stringify(r), { data: n } = k({
869
- queryKey: ["broadcast-audience-preview", l],
889
+ const h = I(), [s, p] = u(!1), o = JSON.stringify(r), { data: n } = k({
890
+ queryKey: ["broadcast-audience-preview", o],
870
891
  queryFn: () => h.request(j("/announcements/preview-audience", { audience: r })).then((m) => m.data),
871
- enabled: !o,
892
+ enabled: !i,
872
893
  staleTime: 3e4
873
894
  });
874
- return o ? /* @__PURE__ */ a("p", { className: "text-[11.5px] text-slate-500 dark:text-muted-foreground", children: [
895
+ return i ? /* @__PURE__ */ a("p", { className: "text-[11.5px] text-slate-500 dark:text-muted-foreground", children: [
875
896
  c,
876
897
  ": ",
877
898
  /* @__PURE__ */ t("span", { className: "font-medium", children: "Everyone" })
878
- ] }) : /* @__PURE__ */ a(oe, { children: [
899
+ ] }) : /* @__PURE__ */ a(ce, { children: [
879
900
  /* @__PURE__ */ a(
880
901
  "button",
881
902
  {
882
903
  type: "button",
883
- onClick: () => u(!0),
904
+ onClick: () => p(!0),
884
905
  className: "text-[11.5px] text-slate-500 underline decoration-dotted underline-offset-2 hover:text-slate-700 dark:text-muted-foreground",
885
906
  title: "Click to see who",
886
907
  children: [
@@ -893,35 +914,35 @@ function me({
893
914
  }
894
915
  ),
895
916
  s && n && /* @__PURE__ */ t(
896
- Qe,
917
+ Ve,
897
918
  {
898
919
  title: c === "Matches" ? "This group matches" : "Sending to",
899
920
  count: n.count,
900
921
  users: n.users,
901
922
  truncated: n.truncated,
902
- onClose: () => u(!1)
923
+ onClose: () => p(!1)
903
924
  }
904
925
  )
905
926
  ] });
906
927
  }
907
- function Qe({
928
+ function Ve({
908
929
  title: r,
909
- count: o,
930
+ count: i,
910
931
  users: c,
911
932
  truncated: b,
912
933
  onClose: h
913
934
  }) {
914
- const [s, u] = p("");
915
- Ce(() => {
935
+ const [s, p] = u("");
936
+ Ae(() => {
916
937
  const m = (x) => {
917
938
  x.key === "Escape" && h();
918
939
  };
919
940
  return window.addEventListener("keydown", m), () => window.removeEventListener("keydown", m);
920
941
  }, [h]);
921
- const l = s.trim().toLowerCase(), n = l ? c.filter(
922
- (m) => m.name.toLowerCase().includes(l) || (m.email ?? "").toLowerCase().includes(l)
942
+ const o = s.trim().toLowerCase(), n = o ? c.filter(
943
+ (m) => m.name.toLowerCase().includes(o) || (m.email ?? "").toLowerCase().includes(o)
923
944
  ) : c;
924
- return $e(
945
+ return Te(
925
946
  /* @__PURE__ */ a("div", { className: "fixed inset-0 z-[100]", children: [
926
947
  /* @__PURE__ */ t("div", { className: "absolute inset-0 bg-black/30", onClick: h }),
927
948
  /* @__PURE__ */ a("div", { className: "absolute right-0 top-0 flex h-full w-[380px] max-w-[92vw] flex-col border-l border-slate-200 bg-white shadow-xl dark:border-border dark:bg-card", children: [
@@ -930,9 +951,9 @@ function Qe({
930
951
  /* @__PURE__ */ a("p", { className: "text-[13px] font-semibold text-slate-800 dark:text-foreground", children: [
931
952
  r,
932
953
  /* @__PURE__ */ a("span", { className: "ml-1.5 font-normal text-slate-400", children: [
933
- o,
954
+ i,
934
955
  " user",
935
- o === 1 ? "" : "s"
956
+ i === 1 ? "" : "s"
936
957
  ] })
937
958
  ] }),
938
959
  /* @__PURE__ */ t(
@@ -950,7 +971,7 @@ function Qe({
950
971
  {
951
972
  autoFocus: !0,
952
973
  value: s,
953
- onChange: (m) => u(m.target.value),
974
+ onChange: (m) => p(m.target.value),
954
975
  placeholder: "Search name or email…",
955
976
  className: "mt-2 h-8 w-full rounded-md border border-slate-200 bg-background px-2.5 text-[12.5px] text-slate-800 dark:border-border dark:text-foreground"
956
977
  }
@@ -973,7 +994,7 @@ function Qe({
973
994
  "Showing the first ",
974
995
  c.length,
975
996
  " of ",
976
- o,
997
+ i,
977
998
  "."
978
999
  ] })
979
1000
  ] })
@@ -983,5 +1004,5 @@ function Qe({
983
1004
  );
984
1005
  }
985
1006
  export {
986
- et as BroadcastView
1007
+ st as BroadcastView
987
1008
  };