@ai-matrx/records-ui 0.51.0 → 0.52.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -56,6 +56,7 @@ __export(src_exports, {
56
56
  DEFAULT_FIELDS: () => DEFAULT_FIELDS,
57
57
  DEFAULT_VIEW_NAME: () => DEFAULT_VIEW_NAME,
58
58
  DashboardCanvas: () => DashboardCanvas,
59
+ DigestScheduler: () => DigestScheduler,
59
60
  DocRender: () => DocRender,
60
61
  DocTemplate: () => DocTemplate,
61
62
  EMPTY_PRESENTATION: () => EMPTY_PRESENTATION,
@@ -9537,28 +9538,325 @@ function Invite({ card, onInvited }) {
9537
9538
  ] });
9538
9539
  }
9539
9540
 
9540
- // src/SubscriptionsPanel.tsx
9541
+ // src/DigestScheduler.tsx
9541
9542
  var import_react67 = require("react");
9542
9543
  var import_react68 = require("@ai-matrx/records/react");
9543
9544
  var import_design_system33 = require("@ai-matrx/design-system");
9544
9545
  var import_jsx_runtime36 = require("react/jsx-runtime");
9546
+ var WEEKDAYS = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"];
9547
+ var CADENCE_WORDS = {
9548
+ instant: "the moment something arrives",
9549
+ hourly: "every hour",
9550
+ daily: "every day",
9551
+ weekly: "every week"
9552
+ };
9553
+ var CHANNEL_WORDS = {
9554
+ in_app: "in the app",
9555
+ email: "by email \u2014 only if an address is on their account",
9556
+ sms: "by text \u2014 only if a number is on their account"
9557
+ };
9558
+ function DigestScheduler({
9559
+ tableId,
9560
+ savedViewId,
9561
+ subjectName,
9562
+ filters,
9563
+ onScheduled,
9564
+ onClose,
9565
+ className
9566
+ }) {
9567
+ const client = (0, import_react68.useRecordsClient)();
9568
+ const host = useRecordsUi();
9569
+ const [views, setViews] = (0, import_react67.useState)(null);
9570
+ const [cadences, setCadences] = (0, import_react67.useState)([]);
9571
+ const [members, setMembers] = (0, import_react67.useState)(null);
9572
+ const [error, setError] = (0, import_react67.useState)(null);
9573
+ const [viewId, setViewId] = (0, import_react67.useState)(savedViewId ?? "");
9574
+ const [name, setName] = (0, import_react67.useState)(subjectName?.trim() ? `${subjectName.trim()} summary` : "");
9575
+ const [cadence, setCadence] = (0, import_react67.useState)("weekly");
9576
+ const [weekday, setWeekday] = (0, import_react67.useState)("monday");
9577
+ const [time, setTime] = (0, import_react67.useState)("08:00");
9578
+ const [channel, setChannel] = (0, import_react67.useState)("in_app");
9579
+ const [quiet, setQuiet] = (0, import_react67.useState)(false);
9580
+ const [quietFrom, setQuietFrom] = (0, import_react67.useState)("22:00");
9581
+ const [quietTo, setQuietTo] = (0, import_react67.useState)("07:00");
9582
+ const [recipients, setRecipients] = (0, import_react67.useState)([]);
9583
+ const [saving, setSaving] = (0, import_react67.useState)(false);
9584
+ const [outcomes, setOutcomes] = (0, import_react67.useState)(null);
9585
+ const [preview, setPreview] = (0, import_react67.useState)(null);
9586
+ const [previewing, setPreviewing] = (0, import_react67.useState)(false);
9587
+ const load = (0, import_react67.useCallback)(async () => {
9588
+ const [saved, offered] = await Promise.all([
9589
+ // The store's own door onto `platform.saved_view`, narrowed in SQL to
9590
+ // Tables this person can already open — never a grant on the table behind it.
9591
+ client.views({ table_id: tableId }),
9592
+ // The cadences are ASKED, never typed into this file, so a picker can
9593
+ // never offer a cadence the digest runner does not honour.
9594
+ client.subscriptionCadences()
9595
+ ]);
9596
+ if (!saved.ok) setError(saved.error);
9597
+ else setViews(saved.data);
9598
+ if (offered.ok) setCadences(offered.data.filter((c) => c !== "instant"));
9599
+ if (host.members) {
9600
+ const who = await host.members();
9601
+ setMembers(who.map((m) => ({ userId: m.userId, name: m.name ?? m.email ?? m.userId })));
9602
+ } else {
9603
+ setMembers([]);
9604
+ }
9605
+ }, [client, tableId, host]);
9606
+ (0, import_react67.useEffect)(() => {
9607
+ void load();
9608
+ }, [load]);
9609
+ const schedule = (0, import_react67.useMemo)(() => {
9610
+ if (cadence === "weekly") return `${weekday} ${time}`;
9611
+ if (cadence === "daily") return time;
9612
+ return null;
9613
+ }, [cadence, weekday, time]);
9614
+ const quietHours = (0, import_react67.useMemo)(
9615
+ () => quiet ? { start: quietFrom, end: quietTo } : null,
9616
+ [quiet, quietFrom, quietTo]
9617
+ );
9618
+ async function scheduleIt() {
9619
+ setSaving(true);
9620
+ setError(null);
9621
+ setOutcomes(null);
9622
+ let subject = viewId;
9623
+ if (subject === "" || subject === "new") {
9624
+ const declared = await client.viewDeclare({
9625
+ table_id: tableId,
9626
+ spec: {
9627
+ name: subjectName?.trim() ? subjectName.trim() : name.trim() || "Weekly summary",
9628
+ filters: filters ?? {}
9629
+ }
9630
+ });
9631
+ if (!declared.ok) {
9632
+ setSaving(false);
9633
+ setError(declared.error);
9634
+ return;
9635
+ }
9636
+ subject = declared.data;
9637
+ setViewId(declared.data);
9638
+ }
9639
+ const who = recipients.length > 0 ? recipients : [""];
9640
+ const done = [];
9641
+ for (const userId of who) {
9642
+ const label = members?.find((m) => m.userId === userId)?.name ?? (userId === "" ? "you" : userId);
9643
+ const written = await client.subscriptionDeclare({
9644
+ table_id: tableId,
9645
+ spec: {
9646
+ name: name.trim() === "" ? "Weekly summary" : name.trim(),
9647
+ saved_view_id: subject,
9648
+ cadence,
9649
+ schedule,
9650
+ channel,
9651
+ quiet_hours: quietHours,
9652
+ ...userId === "" ? {} : { recipient_user_id: userId }
9653
+ }
9654
+ });
9655
+ if (written.ok) done.push({ userId, who: label, ruleId: written.data });
9656
+ else done.push({ userId, who: label, refused: written.error });
9657
+ }
9658
+ setSaving(false);
9659
+ setOutcomes(done);
9660
+ if (done.some((d) => d.ruleId)) onScheduled?.();
9661
+ }
9662
+ async function showOne(ruleId) {
9663
+ setPreviewing(true);
9664
+ const answered = await client.subscriptionPreview({ rule_id: ruleId });
9665
+ setPreviewing(false);
9666
+ if (!answered.ok) {
9667
+ setError(answered.error);
9668
+ return;
9669
+ }
9670
+ setPreview(answered.data);
9671
+ }
9672
+ if (views === null && !error) return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Skeleton, { className: (0, import_design_system33.cn)("h-56 w-full", className) });
9673
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("section", { className: (0, import_design_system33.cn)("flex flex-col gap-3", className), children: [
9674
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("header", { className: "flex items-center gap-2", children: [
9675
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h3", { className: "text-sm font-medium", children: "Send this on a schedule" }),
9676
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex-1" }),
9677
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Button, { size: "sm", disabled: saving, onClick: () => void scheduleIt(), children: saving ? "Scheduling\u2026" : "Schedule it" }),
9678
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Button, { size: "sm", variant: "ghost", onClick: onClose, children: "Close" }) : null
9679
+ ] }),
9680
+ error ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(RefusalNotice, { error }) : null,
9681
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex flex-col gap-1", children: [
9682
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Label, { className: "text-xs font-medium", children: "What to call it" }),
9683
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9684
+ import_design_system33.BasicInput,
9685
+ {
9686
+ value: name,
9687
+ placeholder: "Monday donor summary",
9688
+ onChange: (e) => setName(e.target.value)
9689
+ }
9690
+ )
9691
+ ] }),
9692
+ savedViewId ? null : /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex flex-col gap-1", children: [
9693
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Label, { className: "text-xs font-medium", children: "What it summarises" }),
9694
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
9695
+ "select",
9696
+ {
9697
+ className: "h-9 rounded border bg-background px-2 text-sm",
9698
+ value: viewId,
9699
+ onChange: (e) => setViewId(e.target.value),
9700
+ children: [
9701
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("option", { value: "new", children: subjectName?.trim() ? `What I am looking at now (${subjectName.trim()})` : "What I am looking at now" }),
9702
+ (views ?? []).map((v) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("option", { value: v.view_id, children: v.name }, v.view_id))
9703
+ ]
9704
+ }
9705
+ ),
9706
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "text-xs text-muted-foreground", children: "The first choice saves what is on screen as a view, so the summary and the screen stay the same thing." })
9707
+ ] }),
9708
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
9709
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex flex-col gap-1", children: [
9710
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Label, { className: "text-xs font-medium", children: "How often" }),
9711
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9712
+ "select",
9713
+ {
9714
+ className: "h-9 rounded border bg-background px-2 text-sm",
9715
+ value: cadence,
9716
+ onChange: (e) => setCadence(e.target.value),
9717
+ children: (cadences.length > 0 ? cadences : ["hourly", "daily", "weekly"]).map((c) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("option", { value: c, children: CADENCE_WORDS[c] ?? c }, c))
9718
+ }
9719
+ )
9720
+ ] }),
9721
+ cadence === "weekly" ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex flex-col gap-1", children: [
9722
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Label, { className: "text-xs font-medium", children: "Which day" }),
9723
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9724
+ "select",
9725
+ {
9726
+ className: "h-9 rounded border bg-background px-2 text-sm",
9727
+ value: weekday,
9728
+ onChange: (e) => setWeekday(e.target.value),
9729
+ children: WEEKDAYS.map((d) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("option", { value: d, children: d[0].toUpperCase() + d.slice(1) }, d))
9730
+ }
9731
+ )
9732
+ ] }) : null,
9733
+ cadence === "weekly" || cadence === "daily" ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex flex-col gap-1", children: [
9734
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Label, { className: "text-xs font-medium", children: "At" }),
9735
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.BasicInput, { type: "time", value: time, onChange: (e) => setTime(e.target.value) })
9736
+ ] }) : null,
9737
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex flex-col gap-1", children: [
9738
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Label, { className: "text-xs font-medium", children: "Where it arrives" }),
9739
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9740
+ "select",
9741
+ {
9742
+ className: "h-9 rounded border bg-background px-2 text-sm",
9743
+ value: channel,
9744
+ onChange: (e) => setChannel(e.target.value),
9745
+ children: Object.entries(CHANNEL_WORDS).map(([key, words]) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("option", { value: key, children: words }, key))
9746
+ }
9747
+ )
9748
+ ] })
9749
+ ] }),
9750
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
9751
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Label, { className: "text-xs font-medium", children: "Who to send it to" }),
9752
+ members === null ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Skeleton, { className: "h-8 w-full" }) : members.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "text-xs text-muted-foreground", children: "Nobody else is offered here, so this will be addressed to you. Who the people are is the platform's answer and this screen reaches it through its host's `members` port, which is not bound here." }) : /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
9753
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex flex-wrap gap-x-4 gap-y-1.5", children: members.map((m) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex items-center gap-1.5 text-xs", children: [
9754
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9755
+ import_design_system33.Checkbox,
9756
+ {
9757
+ checked: recipients.includes(m.userId),
9758
+ onCheckedChange: (on) => setRecipients(
9759
+ (prev) => on ? [...prev, m.userId] : prev.filter((u) => u !== m.userId)
9760
+ )
9761
+ }
9762
+ ),
9763
+ m.name
9764
+ ] }, m.userId)) }),
9765
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "text-xs text-muted-foreground", children: recipients.length === 0 ? "Nobody picked \u2014 it will be addressed to you." : `${recipients.length} ${recipients.length === 1 ? "person" : "people"}, and each one's summary holds only what that person may see.` })
9766
+ ] })
9767
+ ] }),
9768
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex items-center gap-1.5 text-xs", children: [
9769
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Checkbox, { checked: quiet, onCheckedChange: (on) => setQuiet(Boolean(on)) }),
9770
+ "Not between certain hours"
9771
+ ] }),
9772
+ quiet ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-2", children: [
9773
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9774
+ import_design_system33.BasicInput,
9775
+ {
9776
+ type: "time",
9777
+ className: "h-8 w-28",
9778
+ value: quietFrom,
9779
+ onChange: (e) => setQuietFrom(e.target.value)
9780
+ }
9781
+ ),
9782
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "text-xs text-muted-foreground", children: "and" }),
9783
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9784
+ import_design_system33.BasicInput,
9785
+ {
9786
+ type: "time",
9787
+ className: "h-8 w-28",
9788
+ value: quietTo,
9789
+ onChange: (e) => setQuietTo(e.target.value)
9790
+ }
9791
+ ),
9792
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "text-xs text-muted-foreground", children: "A send inside these hours waits until they end \u2014 it is never dropped." })
9793
+ ] }) : null,
9794
+ outcomes ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
9795
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Separator, {}),
9796
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex flex-col gap-1.5", children: outcomes.map((o) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "text-xs", children: o.ruleId ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { children: [
9797
+ o.who,
9798
+ " will get it ",
9799
+ CADENCE_WORDS[cadence] ?? cadence,
9800
+ schedule ? `, ${schedule}` : "",
9801
+ ".",
9802
+ " ",
9803
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9804
+ import_design_system33.Button,
9805
+ {
9806
+ size: "sm",
9807
+ variant: "ghost",
9808
+ disabled: previewing,
9809
+ onClick: () => void showOne(o.ruleId),
9810
+ children: "Send me one now"
9811
+ }
9812
+ )
9813
+ ] }) : o.refused ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(RefusalNotice, { error: o.refused }) : null }, o.userId || "me")) })
9814
+ ] }) : null,
9815
+ preview ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "rounded-md border bg-muted/40 p-2.5 text-xs", children: [
9816
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "font-medium", children: preview.subject }),
9817
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "mt-1 text-muted-foreground", children: preview.body }),
9818
+ preview.incomplete ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "mt-1 text-destructive", children: preview.incomplete }) : null,
9819
+ preview.entered.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("p", { className: "mt-1", children: [
9820
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "font-medium", children: "Arrived:" }),
9821
+ " ",
9822
+ preview.entered.map((e) => e.name).join(", ")
9823
+ ] }) : null,
9824
+ preview.changed.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("p", { className: "mt-1", children: [
9825
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "font-medium", children: "Changed:" }),
9826
+ " ",
9827
+ preview.changed.map((e) => e.name).join(", ")
9828
+ ] }) : null,
9829
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "mt-1.5 text-muted-foreground", children: "Nothing was sent and nothing was recorded \u2014 this is what the next one would say." }),
9830
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Button, { size: "sm", variant: "ghost", className: "mt-1", onClick: () => setPreview(null), children: "Close" })
9831
+ ] }) : null
9832
+ ] });
9833
+ }
9834
+
9835
+ // src/SubscriptionsPanel.tsx
9836
+ var import_react69 = require("react");
9837
+ var import_react70 = require("@ai-matrx/records/react");
9838
+ var import_design_system34 = require("@ai-matrx/design-system");
9839
+ var import_jsx_runtime37 = require("react/jsx-runtime");
9545
9840
  function whenItFires(subscription) {
9546
9841
  if (subscription.cadence === "instant") return "as it happens";
9547
9842
  const every = subscription.cadence === "hourly" ? "an hourly summary" : subscription.cadence === "weekly" ? "a weekly summary" : "a daily summary";
9548
9843
  return subscription.schedule ? `${every}, ${subscription.schedule}` : every;
9549
9844
  }
9550
- var CHANNEL_WORDS = {
9845
+ var CHANNEL_WORDS2 = {
9551
9846
  in_app: "in the app",
9552
9847
  email: "by email \u2014 only if an address is on the account",
9553
9848
  sms: "by text \u2014 only if a number is on the account"
9554
9849
  };
9850
+ var DIGEST_SUGGESTION = "Email me a summary of this every Monday at 8 in the morning.";
9555
9851
  function SubscriptionsPanel({ tableId, className }) {
9556
- const client = (0, import_react68.useRecordsClient)();
9557
- const [rows, setRows] = (0, import_react67.useState)(null);
9558
- const [error, setError] = (0, import_react67.useState)(null);
9559
- const [busy, setBusy] = (0, import_react67.useState)(null);
9560
- const [preview, setPreview] = (0, import_react67.useState)(null);
9561
- const load = (0, import_react67.useCallback)(async () => {
9852
+ const client = (0, import_react70.useRecordsClient)();
9853
+ const [rows, setRows] = (0, import_react69.useState)(null);
9854
+ const [error, setError] = (0, import_react69.useState)(null);
9855
+ const [busy, setBusy] = (0, import_react69.useState)(null);
9856
+ const [preview, setPreview] = (0, import_react69.useState)(null);
9857
+ const [scheduling, setScheduling] = (0, import_react69.useState)(false);
9858
+ const host = useRecordsUi();
9859
+ const load = (0, import_react69.useCallback)(async () => {
9562
9860
  const answered = await client.subscriptions({ table_id: tableId });
9563
9861
  if (!answered.ok) {
9564
9862
  setError(answered.error);
@@ -9568,10 +9866,10 @@ function SubscriptionsPanel({ tableId, className }) {
9568
9866
  setError(null);
9569
9867
  setRows(answered.data);
9570
9868
  }, [client, tableId]);
9571
- (0, import_react67.useEffect)(() => {
9869
+ (0, import_react69.useEffect)(() => {
9572
9870
  void load();
9573
9871
  }, [load]);
9574
- const flip = (0, import_react67.useCallback)(
9872
+ const flip = (0, import_react69.useCallback)(
9575
9873
  async (subscription, on) => {
9576
9874
  setBusy(subscription.rule_id);
9577
9875
  const answered = await client.subscriptionMute({
@@ -9587,7 +9885,7 @@ function SubscriptionsPanel({ tableId, className }) {
9587
9885
  },
9588
9886
  [client, load]
9589
9887
  );
9590
- const showOne = (0, import_react67.useCallback)(
9888
+ const showOne = (0, import_react69.useCallback)(
9591
9889
  async (subscription) => {
9592
9890
  setBusy(subscription.rule_id);
9593
9891
  const answered = await client.subscriptionPreview({ rule_id: subscription.rule_id });
@@ -9601,53 +9899,85 @@ function SubscriptionsPanel({ tableId, className }) {
9601
9899
  },
9602
9900
  [client]
9603
9901
  );
9604
- if (rows === null) return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Skeleton, { className: (0, import_design_system33.cn)("h-32 w-full", className) });
9605
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("section", { className: (0, import_design_system33.cn)("flex flex-col gap-3", className), children: [
9606
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("header", { className: "flex items-center gap-2", children: [
9607
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h3", { className: "text-sm font-medium", children: "Notifications" }),
9608
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "text-xs text-muted-foreground", children: rows.length === 0 ? "none" : `${rows.filter((r) => !r.muted).length} on` })
9902
+ if (rows === null) return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_design_system34.Skeleton, { className: (0, import_design_system34.cn)("h-32 w-full", className) });
9903
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("section", { className: (0, import_design_system34.cn)("flex flex-col gap-3", className), children: [
9904
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("header", { className: "flex items-center gap-2", children: [
9905
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("h3", { className: "text-sm font-medium", children: "Notifications" }),
9906
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "text-xs text-muted-foreground", children: rows.length === 0 ? "none" : `${rows.filter((r) => !r.muted).length} on` }),
9907
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "flex-1" }),
9908
+ rows.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
9909
+ import_design_system34.Button,
9910
+ {
9911
+ size: "sm",
9912
+ variant: scheduling ? "secondary" : "ghost",
9913
+ onClick: () => setScheduling((s) => !s),
9914
+ children: scheduling ? "Done" : "Schedule a summary"
9915
+ }
9916
+ ) : null
9609
9917
  ] }),
9610
- error ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(RefusalNotice, { error }) : null,
9611
- rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "text-xs text-muted-foreground", children: 'Nothing is telling you about this table. A form that says "tell me when somebody answers" makes one, and it appears here the moment it does.' }) : null,
9612
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("ul", { className: "flex flex-col gap-2", children: rows.map((subscription) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("li", { className: "rounded-md border p-2.5", children: [
9613
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-start gap-2", children: [
9614
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "min-w-0 flex-1", children: [
9615
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "truncate text-sm font-medium", children: subscription.name }),
9616
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("p", { className: "mt-0.5 text-xs text-muted-foreground", children: [
9617
- CHANNEL_WORDS[subscription.channel] ?? `on the ${subscription.channel} channel`,
9918
+ error ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(RefusalNotice, { error }) : null,
9919
+ scheduling ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
9920
+ DigestScheduler,
9921
+ {
9922
+ tableId,
9923
+ onScheduled: () => {
9924
+ void load();
9925
+ },
9926
+ onClose: () => setScheduling(false)
9927
+ }
9928
+ ) : null,
9929
+ rows.length === 0 && !scheduling ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
9930
+ BuildOrAsk,
9931
+ {
9932
+ mayBuild: true,
9933
+ onBuild: () => setScheduling(true),
9934
+ ...host.onAskForOne ? {
9935
+ onAsk: () => host.onAskForOne?.({ kind: "digest", tableId, suggestion: DIGEST_SUGGESTION })
9936
+ } : {},
9937
+ suggestion: DIGEST_SUGGESTION,
9938
+ buildLabel: "Schedule a summary",
9939
+ children: "Nothing is telling you about this table. A summary arrives on a schedule you set and names what arrived, what left and what changed since the last one."
9940
+ }
9941
+ ) : null,
9942
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("ul", { className: "flex flex-col gap-2", children: rows.map((subscription) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("li", { className: "rounded-md border p-2.5", children: [
9943
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex items-start gap-2", children: [
9944
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "min-w-0 flex-1", children: [
9945
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "truncate text-sm font-medium", children: subscription.name }),
9946
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("p", { className: "mt-0.5 text-xs text-muted-foreground", children: [
9947
+ CHANNEL_WORDS2[subscription.channel] ?? `on the ${subscription.channel} channel`,
9618
9948
  " \xB7 ",
9619
9949
  whenItFires(subscription)
9620
9950
  ] })
9621
9951
  ] }),
9622
- subscription.i_may_mute ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9623
- import_design_system33.Switch,
9952
+ subscription.i_may_mute ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
9953
+ import_design_system34.Switch,
9624
9954
  {
9625
9955
  checked: !subscription.muted,
9626
9956
  disabled: busy === subscription.rule_id,
9627
9957
  "aria-label": `Tell me about ${subscription.name}`,
9628
9958
  onCheckedChange: (on) => void flip(subscription, on)
9629
9959
  }
9630
- ) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Badge, { variant: "secondary", children: "someone else's" })
9960
+ ) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_design_system34.Badge, { variant: "secondary", children: "someone else's" })
9631
9961
  ] }),
9632
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "mt-1.5 text-xs text-muted-foreground", children: subscription.muted ? "Off \u2014 it stays here and tells nobody until you switch it back on." : subscription.mine ? "On, and addressed to you." : "On, and addressed to somebody else in this organization." }),
9633
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "mt-1.5 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
9634
- subscription.next_digest_at ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { children: [
9962
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "mt-1.5 text-xs text-muted-foreground", children: subscription.muted ? "Off \u2014 it stays here and tells nobody until you switch it back on." : subscription.mine ? "On, and addressed to you." : "On, and addressed to somebody else in this organization." }),
9963
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "mt-1.5 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
9964
+ subscription.next_digest_at ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { children: [
9635
9965
  "Next summary ",
9636
9966
  new Date(subscription.next_digest_at).toLocaleString()
9637
- ] }) : subscription.cadence === "instant" ? null : subscription.muted ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { children: "No next summary while it is off." }) : null,
9638
- subscription.last_sent_at ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { children: [
9967
+ ] }) : subscription.cadence === "instant" ? null : subscription.muted ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { children: "No next summary while it is off." }) : null,
9968
+ subscription.last_sent_at ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { children: [
9639
9969
  "Last told you ",
9640
9970
  new Date(subscription.last_sent_at).toLocaleString()
9641
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { children: "It has not told you anything yet." }),
9642
- subscription.quiet_hours ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { children: [
9971
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { children: "It has not told you anything yet." }),
9972
+ subscription.quiet_hours ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { children: [
9643
9973
  "Not between ",
9644
9974
  subscription.quiet_hours.start,
9645
9975
  " and ",
9646
9976
  subscription.quiet_hours.end,
9647
9977
  " \u2014 a send inside those hours waits until they end."
9648
9978
  ] }) : null,
9649
- subscription.cadence === "instant" ? null : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9650
- import_design_system33.Button,
9979
+ subscription.cadence === "instant" ? null : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
9980
+ import_design_system34.Button,
9651
9981
  {
9652
9982
  size: "sm",
9653
9983
  variant: "ghost",
@@ -9657,58 +9987,58 @@ function SubscriptionsPanel({ tableId, className }) {
9657
9987
  }
9658
9988
  )
9659
9989
  ] }),
9660
- preview && preview.rule_id === subscription.rule_id ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "mt-2 rounded-md border bg-muted/40 p-2.5 text-xs", children: [
9661
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "font-medium", children: preview.subject }),
9662
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "mt-1 text-muted-foreground", children: preview.body }),
9990
+ preview && preview.rule_id === subscription.rule_id ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "mt-2 rounded-md border bg-muted/40 p-2.5 text-xs", children: [
9991
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "font-medium", children: preview.subject }),
9992
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "mt-1 text-muted-foreground", children: preview.body }),
9663
9993
  preview.incomplete ? (
9664
9994
  // Absent or honest: a subscription that cannot produce a summary
9665
9995
  // says which piece is missing instead of showing an empty one.
9666
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "mt-1 text-destructive", children: preview.incomplete })
9996
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "mt-1 text-destructive", children: preview.incomplete })
9667
9997
  ) : null,
9668
- preview.entered.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("p", { className: "mt-1", children: [
9669
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "font-medium", children: "Arrived:" }),
9998
+ preview.entered.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("p", { className: "mt-1", children: [
9999
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "font-medium", children: "Arrived:" }),
9670
10000
  " ",
9671
10001
  preview.entered.map((e) => e.name).join(", ")
9672
10002
  ] }) : null,
9673
- preview.left.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("p", { className: "mt-1", children: [
9674
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "font-medium", children: "Left:" }),
10003
+ preview.left.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("p", { className: "mt-1", children: [
10004
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "font-medium", children: "Left:" }),
9675
10005
  " ",
9676
10006
  preview.left.map((e) => e.name).join(", ")
9677
10007
  ] }) : null,
9678
- preview.changed.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("p", { className: "mt-1", children: [
9679
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "font-medium", children: "Changed:" }),
10008
+ preview.changed.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("p", { className: "mt-1", children: [
10009
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "font-medium", children: "Changed:" }),
9680
10010
  " ",
9681
10011
  preview.changed.map((e) => e.name).join(", ")
9682
10012
  ] }) : null,
9683
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "mt-1.5 text-muted-foreground", children: "Nothing was sent and nothing was recorded \u2014 this is what the next one would say." }),
9684
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Button, { size: "sm", variant: "ghost", className: "mt-1", onClick: () => setPreview(null), children: "Close" })
10013
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "mt-1.5 text-muted-foreground", children: "Nothing was sent and nothing was recorded \u2014 this is what the next one would say." }),
10014
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_design_system34.Button, { size: "sm", variant: "ghost", className: "mt-1", onClick: () => setPreview(null), children: "Close" })
9685
10015
  ] }) : null
9686
10016
  ] }, subscription.rule_id)) })
9687
10017
  ] });
9688
10018
  }
9689
10019
 
9690
10020
  // src/FormBuilder.tsx
9691
- var import_react71 = require("react");
9692
- var import_react72 = require("@ai-matrx/records/react");
10021
+ var import_react73 = require("react");
10022
+ var import_react74 = require("@ai-matrx/records/react");
9693
10023
  var import_records6 = require("@ai-matrx/records");
9694
- var import_design_system35 = require("@ai-matrx/design-system");
10024
+ var import_design_system36 = require("@ai-matrx/design-system");
9695
10025
 
9696
10026
  // src/FormRunner.tsx
9697
- var import_react69 = require("react");
9698
- var import_react70 = require("@ai-matrx/records/react");
9699
- var import_design_system34 = require("@ai-matrx/design-system");
9700
- var import_jsx_runtime37 = require("react/jsx-runtime");
10027
+ var import_react71 = require("react");
10028
+ var import_react72 = require("@ai-matrx/records/react");
10029
+ var import_design_system35 = require("@ai-matrx/design-system");
10030
+ var import_jsx_runtime38 = require("react/jsx-runtime");
9701
10031
  function FormRunner(props) {
9702
10032
  if (props.fields && props.onSubmit) {
9703
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(FormStage, { ...props, fields: props.fields, onSubmit: props.onSubmit });
10033
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(FormStage, { ...props, fields: props.fields, onSubmit: props.onSubmit });
9704
10034
  }
9705
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ConnectedFormRunner, { ...props });
10035
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ConnectedFormRunner, { ...props });
9706
10036
  }
9707
10037
  function ConnectedFormRunner(props) {
9708
- const client = (0, import_react70.useOptionalRecordsClient)();
9709
- const fields = (0, import_react70.useFields)(props.form.subject);
10038
+ const client = (0, import_react72.useOptionalRecordsClient)();
10039
+ const fields = (0, import_react72.useFields)(props.form.subject);
9710
10040
  const { form, className } = props;
9711
- const submit = (0, import_react69.useCallback)(
10041
+ const submit = (0, import_react71.useCallback)(
9712
10042
  async (values) => {
9713
10043
  if (!client) {
9714
10044
  return {
@@ -9731,7 +10061,7 @@ function ConnectedFormRunner(props) {
9731
10061
  },
9732
10062
  [client, form]
9733
10063
  );
9734
- const evaluate = (0, import_react69.useCallback)(
10064
+ const evaluate = (0, import_react71.useCallback)(
9735
10065
  async (expr, values) => {
9736
10066
  if (!client) return null;
9737
10067
  const answered = await client.ruleEval({ expr, values });
@@ -9740,9 +10070,9 @@ function ConnectedFormRunner(props) {
9740
10070
  },
9741
10071
  [client]
9742
10072
  );
9743
- if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(RefusalNotice, { error: fields.error, className });
9744
- if (fields.loading) return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_design_system34.Skeleton, { className: (0, import_design_system34.cn)("h-40 w-full", className) });
9745
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
10073
+ if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(RefusalNotice, { error: fields.error, className });
10074
+ if (fields.loading) return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system35.Skeleton, { className: (0, import_design_system35.cn)("h-40 w-full", className) });
10075
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
9746
10076
  FormStage,
9747
10077
  {
9748
10078
  ...props,
@@ -9765,16 +10095,16 @@ function FormStage({
9765
10095
  connected = false
9766
10096
  }) {
9767
10097
  const host = useRecordsUi();
9768
- const [answers, setAnswers] = (0, import_react69.useState)({});
9769
- const [at, setAt] = (0, import_react69.useState)(0);
9770
- const [error, setError] = (0, import_react69.useState)(null);
9771
- const [refusal, setRefusal] = (0, import_react69.useState)(null);
9772
- const [writing, setWriting] = (0, import_react69.useState)(false);
9773
- const [done, setDone] = (0, import_react69.useState)(null);
9774
- const [hidden, setHidden] = (0, import_react69.useState)({});
9775
- const decoy = (0, import_react69.useRef)("");
9776
- const stage = (0, import_react69.useRef)(null);
9777
- const questions = (0, import_react69.useMemo)(() => {
10098
+ const [answers, setAnswers] = (0, import_react71.useState)({});
10099
+ const [at, setAt] = (0, import_react71.useState)(0);
10100
+ const [error, setError] = (0, import_react71.useState)(null);
10101
+ const [refusal, setRefusal] = (0, import_react71.useState)(null);
10102
+ const [writing, setWriting] = (0, import_react71.useState)(false);
10103
+ const [done, setDone] = (0, import_react71.useState)(null);
10104
+ const [hidden, setHidden] = (0, import_react71.useState)({});
10105
+ const decoy = (0, import_react71.useRef)("");
10106
+ const stage = (0, import_react71.useRef)(null);
10107
+ const questions = (0, import_react71.useMemo)(() => {
9778
10108
  const byKey = new Map((fields ?? []).map((f) => [f.key, f]));
9779
10109
  return (form.questions ?? []).map((q) => {
9780
10110
  const field = byKey.get(q.field) ?? null;
@@ -9788,7 +10118,7 @@ function FormStage({
9788
10118
  };
9789
10119
  });
9790
10120
  }, [fields, form.questions]);
9791
- (0, import_react69.useEffect)(() => {
10121
+ (0, import_react71.useEffect)(() => {
9792
10122
  let cancelled = false;
9793
10123
  const conditional = questions.filter((q) => q.showIf);
9794
10124
  if (conditional.length === 0 || !evaluate) return;
@@ -9822,7 +10152,7 @@ function FormStage({
9822
10152
  const v = answers[q.key];
9823
10153
  return q.required && (v === void 0 || v === null || v === "");
9824
10154
  });
9825
- const submit = (0, import_react69.useCallback)(async () => {
10155
+ const submit = (0, import_react71.useCallback)(async () => {
9826
10156
  if (preview) {
9827
10157
  setDone("preview");
9828
10158
  return;
@@ -9859,51 +10189,51 @@ function FormStage({
9859
10189
  if (event.shiftKey) retreat();
9860
10190
  else advance();
9861
10191
  }
9862
- (0, import_react69.useEffect)(() => {
10192
+ (0, import_react71.useEffect)(() => {
9863
10193
  const input = stage.current?.querySelector(
9864
10194
  "input:not([tabindex='-1']), textarea, select, [role='combobox']"
9865
10195
  );
9866
10196
  input?.focus();
9867
10197
  }, [index, done]);
9868
10198
  if (done) {
9869
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("section", { className: (0, import_design_system34.cn)("mx-auto max-w-xl py-10", centred && "text-center", className), children: [
9870
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("h2", { className: "text-lg font-medium", children: form.thankYou?.title ?? "Thank you" }),
9871
- form.thankYou?.body ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "mt-1 text-sm text-muted-foreground", children: form.thankYou.body }) : null,
9872
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "mt-3 text-xs text-muted-foreground", children: done === "preview" ? "This was a preview, so nothing was written." : done === "sent" ? `Saved to ${form.name}, with this form stamped on it.` : done })
10199
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("section", { className: (0, import_design_system35.cn)("mx-auto max-w-xl py-10", centred && "text-center", className), children: [
10200
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("h2", { className: "text-lg font-medium", children: form.thankYou?.title ?? "Thank you" }),
10201
+ form.thankYou?.body ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "mt-1 text-sm text-muted-foreground", children: form.thankYou.body }) : null,
10202
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "mt-3 text-xs text-muted-foreground", children: done === "preview" ? "This was a preview, so nothing was written." : done === "sent" ? `Saved to ${form.name}, with this form stamped on it.` : done })
9873
10203
  ] });
9874
10204
  }
9875
10205
  const unresolved = questions.filter((q) => !q.field);
9876
10206
  const unanswerable = !evaluate && questions.some((q) => q.showIf);
9877
10207
  const signedInPublic = connected && form.isPublic === true;
9878
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
10208
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
9879
10209
  "section",
9880
10210
  {
9881
- className: (0, import_design_system34.cn)("mx-auto flex max-w-xl flex-col gap-3 py-4", centred && "text-center", className),
10211
+ className: (0, import_design_system35.cn)("mx-auto flex max-w-xl flex-col gap-3 py-4", centred && "text-center", className),
9882
10212
  onKeyDown,
9883
10213
  children: [
9884
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("header", { className: "flex items-center gap-3 text-xs text-muted-foreground", children: [
9885
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
9886
- import_design_system34.Progress,
10214
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("header", { className: "flex items-center gap-3 text-xs text-muted-foreground", children: [
10215
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10216
+ import_design_system35.Progress,
9887
10217
  {
9888
10218
  value: live.length === 0 ? 0 : (oneAtATime ? index + 1 : answered) / live.length * 100,
9889
10219
  className: "h-1 flex-1"
9890
10220
  }
9891
10221
  ),
9892
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "tabular-nums", children: oneAtATime ? `${index + 1} of ${live.length}` : `${answered} of ${live.length}` })
10222
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "tabular-nums", children: oneAtATime ? `${index + 1} of ${live.length}` : `${answered} of ${live.length}` })
9893
10223
  ] }),
9894
- signedInPublic ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "rounded border border-dashed px-2 py-1 text-left text-xs text-muted-foreground", children: "You are answering this signed in, so the record will carry your name. A stranger answers the same form at its public link, where the answer arrives through the anonymous door instead." }) : null,
9895
- unanswerable ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "rounded border border-dashed px-2 py-1 text-left text-xs text-muted-foreground", children: "This form has questions that only appear in certain cases. Nothing here can work out which ones, so all of them are being shown rather than any being skipped." }) : null,
9896
- unresolved.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("p", { className: "rounded border border-dashed px-2 py-1 text-left text-xs text-destructive", children: [
10224
+ signedInPublic ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "rounded border border-dashed px-2 py-1 text-left text-xs text-muted-foreground", children: "You are answering this signed in, so the record will carry your name. A stranger answers the same form at its public link, where the answer arrives through the anonymous door instead." }) : null,
10225
+ unanswerable ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "rounded border border-dashed px-2 py-1 text-left text-xs text-muted-foreground", children: "This form has questions that only appear in certain cases. Nothing here can work out which ones, so all of them are being shown rather than any being skipped." }) : null,
10226
+ unresolved.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("p", { className: "rounded border border-dashed px-2 py-1 text-left text-xs text-destructive", children: [
9897
10227
  unresolved.map((q) => q.key).join(", "),
9898
10228
  " ",
9899
10229
  unresolved.length === 1 ? "is a question" : "are questions",
9900
10230
  " this form asks for and this table has no such Field. Add the Field, or take the question out \u2014 it is shown here rather than quietly dropped, because a dropped question is an answer nobody gave."
9901
10231
  ] }) : null,
9902
- form.intro && index === 0 ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "text-sm text-muted-foreground", children: form.intro }) : null,
9903
- error ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(RefusalNotice, { error, className: "text-left" }) : null,
9904
- refusal ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { role: "alert", className: "rounded border border-destructive/40 px-2 py-1 text-left text-xs text-destructive", children: refusal }) : null,
9905
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { ref: stage, className: "flex flex-col gap-4 text-left", children: [
9906
- (oneAtATime ? current ? [current] : [] : live).map((q) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
10232
+ form.intro && index === 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "text-sm text-muted-foreground", children: form.intro }) : null,
10233
+ error ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(RefusalNotice, { error, className: "text-left" }) : null,
10234
+ refusal ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { role: "alert", className: "rounded border border-destructive/40 px-2 py-1 text-left text-xs text-destructive", children: refusal }) : null,
10235
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { ref: stage, className: "flex flex-col gap-4 text-left", children: [
10236
+ (oneAtATime ? current ? [current] : [] : live).map((q) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
9907
10237
  Question,
9908
10238
  {
9909
10239
  question: q,
@@ -9913,11 +10243,11 @@ function FormStage({
9913
10243
  },
9914
10244
  q.key
9915
10245
  )),
9916
- live.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "text-xs text-muted-foreground", children: "Every question in this form is hidden by its own condition right now, so there is nothing to answer yet." }) : null
10246
+ live.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "text-xs text-muted-foreground", children: "Every question in this form is hidden by its own condition right now, so there is nothing to answer yet." }) : null
9917
10247
  ] }),
9918
- honeypotKey ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { "aria-hidden": true, className: "pointer-events-none absolute left-[-9999px] h-px w-px overflow-hidden", children: [
9919
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("label", { htmlFor: `hp-${honeypotKey}`, children: "Leave this field empty" }),
9920
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
10248
+ honeypotKey ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { "aria-hidden": true, className: "pointer-events-none absolute left-[-9999px] h-px w-px overflow-hidden", children: [
10249
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("label", { htmlFor: `hp-${honeypotKey}`, children: "Leave this field empty" }),
10250
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
9921
10251
  "input",
9922
10252
  {
9923
10253
  id: `hp-${honeypotKey}`,
@@ -9932,16 +10262,16 @@ function FormStage({
9932
10262
  }
9933
10263
  )
9934
10264
  ] }) : null,
9935
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("footer", { className: (0, import_design_system34.cn)("flex flex-wrap items-center gap-2", centred && "justify-center"), children: [
9936
- oneAtATime && index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_design_system34.Button, { size: "sm", variant: "ghost", onClick: retreat, children: "Back" }) : null,
9937
- oneAtATime && index < live.length - 1 ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_design_system34.Button, { size: "sm", onClick: advance, children: "Next" }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_design_system34.Button, { size: "sm", disabled: writing || missing.length > 0, onClick: () => void submit(), children: writing ? "Sending\u2026" : form.submitLabel ?? "Submit" }),
9938
- missing.length > 0 && (!oneAtATime || index === live.length - 1) ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
10265
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("footer", { className: (0, import_design_system35.cn)("flex flex-wrap items-center gap-2", centred && "justify-center"), children: [
10266
+ oneAtATime && index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system35.Button, { size: "sm", variant: "ghost", onClick: retreat, children: "Back" }) : null,
10267
+ oneAtATime && index < live.length - 1 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system35.Button, { size: "sm", onClick: advance, children: "Next" }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system35.Button, { size: "sm", disabled: writing || missing.length > 0, onClick: () => void submit(), children: writing ? "Sending\u2026" : form.submitLabel ?? "Submit" }),
10268
+ missing.length > 0 && (!oneAtATime || index === live.length - 1) ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
9939
10269
  missing.map((q) => q.ask).join(", "),
9940
10270
  " still ",
9941
10271
  missing.length === 1 ? "needs" : "need",
9942
10272
  " an answer."
9943
10273
  ] }) : null,
9944
- preview ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "text-xs text-muted-foreground", children: "Preview \u2014 nothing is written." }) : null
10274
+ preview ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "text-xs text-muted-foreground", children: "Preview \u2014 nothing is written." }) : null
9945
10275
  ] })
9946
10276
  ]
9947
10277
  }
@@ -9953,16 +10283,16 @@ function Question({
9953
10283
  onChange,
9954
10284
  upload
9955
10285
  }) {
9956
- const [uploadError, setUploadError] = (0, import_react69.useState)(null);
10286
+ const [uploadError, setUploadError] = (0, import_react71.useState)(null);
9957
10287
  const field = question.field;
9958
10288
  if (!field) return null;
9959
10289
  const id = `form-${field.key}`;
9960
10290
  const isAttachment = editorKindFor(field) === "attachment";
9961
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
9962
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(FieldLabel, { field: { ...field, label: question.ask, required: question.required }, htmlFor: id }),
9963
- question.help ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "text-xs text-muted-foreground", children: question.help }) : null,
9964
- isAttachment && !upload ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: NO_UPLOAD_REASON }) : isAttachment ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
9965
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
10291
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
10292
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(FieldLabel, { field: { ...field, label: question.ask, required: question.required }, htmlFor: id }),
10293
+ question.help ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "text-xs text-muted-foreground", children: question.help }) : null,
10294
+ isAttachment && !upload ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: NO_UPLOAD_REASON }) : isAttachment ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_jsx_runtime38.Fragment, { children: [
10295
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
9966
10296
  "input",
9967
10297
  {
9968
10298
  id,
@@ -9980,31 +10310,31 @@ function Question({
9980
10310
  }
9981
10311
  }
9982
10312
  ),
9983
- uploadError ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "text-xs text-destructive", children: uploadError }) : null
9984
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(FieldControl, { field, value, onChange, id })
10313
+ uploadError ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "text-xs text-destructive", children: uploadError }) : null
10314
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(FieldControl, { field, value, onChange, id })
9985
10315
  ] });
9986
10316
  }
9987
10317
 
9988
10318
  // src/FormBuilder.tsx
9989
- var import_jsx_runtime38 = require("react/jsx-runtime");
10319
+ var import_jsx_runtime39 = require("react/jsx-runtime");
9990
10320
  function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
9991
- const client = (0, import_react72.useRecordsClient)();
10321
+ const client = (0, import_react74.useRecordsClient)();
9992
10322
  const host = useRecordsUi();
9993
10323
  const claimSeed = useSeedGuard();
9994
- const table = (0, import_react72.useTable)(tableId);
10324
+ const table = (0, import_react74.useTable)(tableId);
9995
10325
  const rights = useTableRights(table.data);
9996
- const fields = (0, import_react72.useFields)(tableId);
9997
- const [forms, setForms] = (0, import_react71.useState)(null);
9998
- const [error, setError] = (0, import_react71.useState)(null);
9999
- const [activeId, setActiveId] = (0, import_react71.useState)(activeFormId ?? null);
10000
- const [draft, setDraft] = (0, import_react71.useState)(null);
10001
- const [saving, setSaving] = (0, import_react71.useState)(false);
10002
- const [saved, setSaved] = (0, import_react71.useState)(null);
10003
- const [publishing, setPublishing] = (0, import_react71.useState)(false);
10004
- const [copied, setCopied] = (0, import_react71.useState)(false);
10005
- const [shownUrl, setShownUrl] = (0, import_react71.useState)(null);
10326
+ const fields = (0, import_react74.useFields)(tableId);
10327
+ const [forms, setForms] = (0, import_react73.useState)(null);
10328
+ const [error, setError] = (0, import_react73.useState)(null);
10329
+ const [activeId, setActiveId] = (0, import_react73.useState)(activeFormId ?? null);
10330
+ const [draft, setDraft] = (0, import_react73.useState)(null);
10331
+ const [saving, setSaving] = (0, import_react73.useState)(false);
10332
+ const [saved, setSaved] = (0, import_react73.useState)(null);
10333
+ const [publishing, setPublishing] = (0, import_react73.useState)(false);
10334
+ const [copied, setCopied] = (0, import_react73.useState)(false);
10335
+ const [shownUrl, setShownUrl] = (0, import_react73.useState)(null);
10006
10336
  const publicOrigin = host.publicOrigin ?? (typeof window === "undefined" ? "" : window.location.origin);
10007
- const load = (0, import_react71.useCallback)(async () => {
10337
+ const load = (0, import_react73.useCallback)(async () => {
10008
10338
  const answered = await client.forms({ table_id: tableId });
10009
10339
  if (!answered.ok) {
10010
10340
  setError(answered.error);
@@ -10031,17 +10361,17 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10031
10361
  setError(null);
10032
10362
  setForms(mine);
10033
10363
  }, [client, tableId, seed, claimSeed]);
10034
- (0, import_react71.useEffect)(() => {
10364
+ (0, import_react73.useEffect)(() => {
10035
10365
  void load();
10036
10366
  }, [load]);
10037
- (0, import_react71.useEffect)(() => {
10367
+ (0, import_react73.useEffect)(() => {
10038
10368
  if (!forms || forms.length === 0) return;
10039
10369
  const chosen = forms.find((f) => f.id === (activeFormId ?? activeId)) ?? forms[0];
10040
10370
  if (chosen.id !== activeId) setActiveId(chosen.id);
10041
10371
  setDraft(chosen);
10042
10372
  onActiveForm?.(chosen);
10043
10373
  }, [forms, activeFormId]);
10044
- const byKey = (0, import_react71.useMemo)(() => new Map((fields.data ?? []).map((f) => [f.key, f])), [fields.data]);
10374
+ const byKey = (0, import_react73.useMemo)(() => new Map((fields.data ?? []).map((f) => [f.key, f])), [fields.data]);
10045
10375
  function patch(change) {
10046
10376
  setDraft((prev) => prev ? { ...prev, ...change } : prev);
10047
10377
  setSaved(null);
@@ -10101,26 +10431,26 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10101
10431
  setActiveId(written.data);
10102
10432
  await load();
10103
10433
  }
10104
- if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(RefusalNotice, { error: fields.error, className });
10434
+ if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(RefusalNotice, { error: fields.error, className });
10105
10435
  if (error) {
10106
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10436
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10107
10437
  RefusalNotice,
10108
10438
  {
10109
10439
  error,
10110
10440
  className,
10111
- actions: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system35.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
10441
+ actions: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
10112
10442
  }
10113
10443
  );
10114
10444
  }
10115
- if (fields.loading || forms === null) return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system35.Skeleton, { className: (0, import_design_system35.cn)("h-64 w-full", className) });
10445
+ if (fields.loading || forms === null) return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.Skeleton, { className: (0, import_design_system36.cn)("h-64 w-full", className) });
10116
10446
  if (!rights.admin) {
10117
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: (0, import_design_system35.cn)("text-xs text-muted-foreground", className), children: rights.why("structure") });
10447
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: (0, import_design_system36.cn)("text-xs text-muted-foreground", className), children: rights.why("structure") });
10118
10448
  }
10119
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: (0, import_design_system35.cn)("flex min-h-0 gap-3", className), children: [
10120
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col gap-2 overflow-auto", children: [
10121
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center gap-1 overflow-x-auto", role: "group", "aria-label": "Forms", children: [
10122
- forms.map((form) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10123
- import_design_system35.Button,
10449
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: (0, import_design_system36.cn)("flex min-h-0 gap-3", className), children: [
10450
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col gap-2 overflow-auto", children: [
10451
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex items-center gap-1 overflow-x-auto", role: "group", "aria-label": "Forms", children: [
10452
+ forms.map((form) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10453
+ import_design_system36.Button,
10124
10454
  {
10125
10455
  size: "sm",
10126
10456
  variant: form.id === activeId ? "secondary" : "ghost",
@@ -10133,14 +10463,14 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10133
10463
  },
10134
10464
  form.id
10135
10465
  )),
10136
- (fields.data ?? []).length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system35.Button, { size: "sm", variant: "ghost", onClick: () => void create(`Form ${forms.length + 1}`), children: "New form" }) : null,
10137
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "ml-auto flex items-center gap-2", children: [
10138
- saved ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "text-xs text-muted-foreground", children: saved }) : null,
10139
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system35.Button, { size: "sm", disabled: saving || !draft, onClick: () => void save(), children: saving ? "Saving\u2026" : "Save" })
10466
+ (fields.data ?? []).length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.Button, { size: "sm", variant: "ghost", onClick: () => void create(`Form ${forms.length + 1}`), children: "New form" }) : null,
10467
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "ml-auto flex items-center gap-2", children: [
10468
+ saved ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-xs text-muted-foreground", children: saved }) : null,
10469
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.Button, { size: "sm", disabled: saving || !draft, onClick: () => void save(), children: saving ? "Saving\u2026" : "Save" })
10140
10470
  ] })
10141
10471
  ] }),
10142
- !draft ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "text-xs text-muted-foreground", children: (fields.data ?? []).length === 0 ? "This table has no fields yet, so there is nothing a form could ask for. Add a field first \u2014 every question is one of this table's own fields." : 'No form collects into this table yet. "New form" makes one, or you ask an agent for the whole thing in a sentence.' }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_jsx_runtime38.Fragment, { children: [
10143
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10472
+ !draft ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-xs text-muted-foreground", children: (fields.data ?? []).length === 0 ? "This table has no fields yet, so there is nothing a form could ask for. Add a field first \u2014 every question is one of this table's own fields." : 'No form collects into this table yet. "New form" makes one, or you ask an agent for the whole thing in a sentence.' }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
10473
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10144
10474
  PublishRow,
10145
10475
  {
10146
10476
  url: `${publicOrigin}${(0, import_records6.publicFormPath)(draft.id)}`,
@@ -10154,27 +10484,27 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10154
10484
  onCopy: (url) => void copyLink(url)
10155
10485
  }
10156
10486
  ),
10157
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
10158
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("label", { className: "flex flex-col gap-1", children: [
10159
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system35.Label, { className: "text-xs font-medium", children: "Name" }),
10160
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system35.BasicInput, { value: draft.name, onChange: (e) => patch({ name: e.target.value }) })
10487
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
10488
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("label", { className: "flex flex-col gap-1", children: [
10489
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.Label, { className: "text-xs font-medium", children: "Name" }),
10490
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.BasicInput, { value: draft.name, onChange: (e) => patch({ name: e.target.value }) })
10161
10491
  ] }),
10162
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("label", { className: "flex flex-col gap-1", children: [
10163
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system35.Label, { className: "text-xs font-medium", children: "Flow" }),
10164
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10492
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("label", { className: "flex flex-col gap-1", children: [
10493
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.Label, { className: "text-xs font-medium", children: "Flow" }),
10494
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10165
10495
  "select",
10166
10496
  {
10167
10497
  className: "h-9 rounded border bg-background px-2 text-sm",
10168
10498
  value: draft.flow ?? "one-at-a-time",
10169
10499
  onChange: (e) => patch({ flow: e.target.value }),
10170
- children: FORM_FLOWS.map((flow) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("option", { value: flow, children: flow === "one-at-a-time" ? "One question at a time" : "All on one page" }, flow))
10500
+ children: FORM_FLOWS.map((flow) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("option", { value: flow, children: flow === "one-at-a-time" ? "One question at a time" : "All on one page" }, flow))
10171
10501
  }
10172
10502
  )
10173
10503
  ] }),
10174
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("label", { className: "col-span-2 flex flex-col gap-1", children: [
10175
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system35.Label, { className: "text-xs font-medium", children: "Intro" }),
10176
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10177
- import_design_system35.BasicTextarea,
10504
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("label", { className: "col-span-2 flex flex-col gap-1", children: [
10505
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.Label, { className: "text-xs font-medium", children: "Intro" }),
10506
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10507
+ import_design_system36.BasicTextarea,
10178
10508
  {
10179
10509
  rows: 2,
10180
10510
  value: draft.intro ?? "",
@@ -10182,10 +10512,10 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10182
10512
  }
10183
10513
  )
10184
10514
  ] }),
10185
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("label", { className: "flex flex-col gap-1", children: [
10186
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system35.Label, { className: "text-xs font-medium", children: "Submit button" }),
10187
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10188
- import_design_system35.BasicInput,
10515
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("label", { className: "flex flex-col gap-1", children: [
10516
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.Label, { className: "text-xs font-medium", children: "Submit button" }),
10517
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10518
+ import_design_system36.BasicInput,
10189
10519
  {
10190
10520
  value: draft.submitLabel ?? "",
10191
10521
  placeholder: "Submit",
@@ -10193,10 +10523,10 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10193
10523
  }
10194
10524
  )
10195
10525
  ] }),
10196
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("label", { className: "flex flex-col gap-1", children: [
10197
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system35.Label, { className: "text-xs font-medium", children: "Thank-you title" }),
10198
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10199
- import_design_system35.BasicInput,
10526
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("label", { className: "flex flex-col gap-1", children: [
10527
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.Label, { className: "text-xs font-medium", children: "Thank-you title" }),
10528
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10529
+ import_design_system36.BasicInput,
10200
10530
  {
10201
10531
  value: draft.thankYou?.title ?? "",
10202
10532
  placeholder: "Thank you",
@@ -10207,10 +10537,10 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10207
10537
  )
10208
10538
  ] })
10209
10539
  ] }),
10210
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex flex-col gap-1", children: [
10211
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
10212
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "font-medium text-foreground", children: "Questions" }),
10213
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { children: [
10540
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-col gap-1", children: [
10541
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
10542
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "font-medium text-foreground", children: "Questions" }),
10543
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { children: [
10214
10544
  draft.questions.length,
10215
10545
  " of this table's ",
10216
10546
  fields.data?.length ?? 0,
@@ -10221,10 +10551,10 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10221
10551
  const index = draft.questions.findIndex((q) => q.field === field.key);
10222
10552
  const asked = index >= 0;
10223
10553
  const question = asked ? draft.questions[index] : null;
10224
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "rounded border px-2 py-1.5", children: [
10225
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center gap-2", children: [
10226
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10227
- import_design_system35.Checkbox,
10554
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "rounded border px-2 py-1.5", children: [
10555
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex items-center gap-2", children: [
10556
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10557
+ import_design_system36.Checkbox,
10228
10558
  {
10229
10559
  checked: asked,
10230
10560
  "aria-label": `Ask for ${fieldName(field)}`,
@@ -10233,13 +10563,13 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10233
10563
  })
10234
10564
  }
10235
10565
  ),
10236
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "text-xs font-medium", children: fieldName(field) }),
10237
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "text-xs text-muted-foreground", children: field.key }),
10238
- field.required ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "text-xs text-destructive", children: "required" }) : null
10566
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-xs font-medium", children: fieldName(field) }),
10567
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-xs text-muted-foreground", children: field.key }),
10568
+ field.required ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-xs text-destructive", children: "required" }) : null
10239
10569
  ] }),
10240
- asked && question ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "mt-1.5 grid grid-cols-2 gap-2 pl-6", children: [
10241
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10242
- import_design_system35.BasicInput,
10570
+ asked && question ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "mt-1.5 grid grid-cols-2 gap-2 pl-6", children: [
10571
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10572
+ import_design_system36.BasicInput,
10243
10573
  {
10244
10574
  className: "h-8 text-xs",
10245
10575
  placeholder: fieldName(field),
@@ -10248,8 +10578,8 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10248
10578
  onChange: (e) => patchQuestion(index, { ask: e.target.value || null })
10249
10579
  }
10250
10580
  ),
10251
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10252
- import_design_system35.BasicInput,
10581
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10582
+ import_design_system36.BasicInput,
10253
10583
  {
10254
10584
  className: "h-8 text-xs",
10255
10585
  placeholder: "Help text",
@@ -10258,7 +10588,7 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10258
10588
  onChange: (e) => patchQuestion(index, { help: e.target.value || null })
10259
10589
  }
10260
10590
  ),
10261
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10591
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10262
10592
  Condition,
10263
10593
  {
10264
10594
  question,
@@ -10269,7 +10599,7 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10269
10599
  ] }) : null
10270
10600
  ] }, field.id);
10271
10601
  }),
10272
- draft.questions.filter((q) => !byKey.has(q.field)).map((q) => /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("p", { className: "text-xs text-destructive", children: [
10602
+ draft.questions.filter((q) => !byKey.has(q.field)).map((q) => /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("p", { className: "text-xs text-destructive", children: [
10273
10603
  'This form asks for "',
10274
10604
  q.field,
10275
10605
  '" and this table has no such Field. It is shown here rather than quietly dropped.'
@@ -10277,9 +10607,9 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10277
10607
  ] })
10278
10608
  ] })
10279
10609
  ] }),
10280
- draft ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("aside", { className: "w-96 shrink-0 overflow-auto rounded border p-2", children: [
10281
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("h4", { className: "px-1 text-sm font-medium", children: draft.name }),
10282
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(FormRunner, { form: draft, preview: true })
10610
+ draft ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("aside", { className: "w-96 shrink-0 overflow-auto rounded border p-2", children: [
10611
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("h4", { className: "px-1 text-sm font-medium", children: draft.name }),
10612
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(FormRunner, { form: draft, preview: true })
10283
10613
  ] }) : null
10284
10614
  ] });
10285
10615
  }
@@ -10295,10 +10625,10 @@ function PublishRow({
10295
10625
  onCopy
10296
10626
  }) {
10297
10627
  const open = state === "open";
10298
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex flex-col gap-1.5 rounded border px-2.5 py-2", children: [
10299
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
10300
- mayPublish ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10301
- import_design_system35.Button,
10628
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-col gap-1.5 rounded border px-2.5 py-2", children: [
10629
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
10630
+ mayPublish ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10631
+ import_design_system36.Button,
10302
10632
  {
10303
10633
  size: "sm",
10304
10634
  variant: open ? "ghost" : "default",
@@ -10307,8 +10637,8 @@ function PublishRow({
10307
10637
  children: busy ? "\u2026" : open ? "Unpublish" : "Publish"
10308
10638
  }
10309
10639
  ) : null,
10310
- state !== "draft" ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_jsx_runtime38.Fragment, { children: [
10311
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10640
+ state !== "draft" ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
10641
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10312
10642
  "a",
10313
10643
  {
10314
10644
  href: url,
@@ -10318,12 +10648,12 @@ function PublishRow({
10318
10648
  children: url
10319
10649
  }
10320
10650
  ),
10321
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system35.Button, { size: "sm", variant: "outline", onClick: () => onCopy(url), children: copied ? "Copied" : "Copy link" })
10651
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.Button, { size: "sm", variant: "outline", onClick: () => onCopy(url), children: copied ? "Copied" : "Copy link" })
10322
10652
  ] }) : null
10323
10653
  ] }),
10324
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "text-xs text-muted-foreground", children: FORM_STATE_WORDS[state] }),
10325
- !mayPublish ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "text-xs text-muted-foreground", children: why }) : null,
10326
- shownUrl ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("p", { className: "break-all rounded border border-dashed px-2 py-1 text-xs", children: [
10654
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-xs text-muted-foreground", children: FORM_STATE_WORDS[state] }),
10655
+ !mayPublish ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-xs text-muted-foreground", children: why }) : null,
10656
+ shownUrl ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("p", { className: "break-all rounded border border-dashed px-2 py-1 text-xs", children: [
10327
10657
  "This browser would not let the page copy for you, so here it is to copy by hand: ",
10328
10658
  shownUrl
10329
10659
  ] }) : null
@@ -10334,7 +10664,7 @@ function Condition({
10334
10664
  fieldKeys,
10335
10665
  onChange
10336
10666
  }) {
10337
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10667
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10338
10668
  ConditionRow,
10339
10669
  {
10340
10670
  lead: "Ask only when",
@@ -10431,13 +10761,13 @@ function groupLabel(groups) {
10431
10761
  }
10432
10762
 
10433
10763
  // src/chartFrame.tsx
10434
- var import_react73 = require("react");
10435
- var import_design_system36 = require("@ai-matrx/design-system");
10436
- var import_jsx_runtime39 = require("react/jsx-runtime");
10764
+ var import_react75 = require("react");
10765
+ var import_design_system37 = require("@ai-matrx/design-system");
10766
+ var import_jsx_runtime40 = require("react/jsx-runtime");
10437
10767
  function useMeasuredWidth(fallback = 480) {
10438
- const ref = (0, import_react73.useRef)(null);
10439
- const [width, setWidth] = (0, import_react73.useState)(fallback);
10440
- (0, import_react73.useEffect)(() => {
10768
+ const ref = (0, import_react75.useRef)(null);
10769
+ const [width, setWidth] = (0, import_react75.useState)(fallback);
10770
+ (0, import_react75.useEffect)(() => {
10441
10771
  const node = ref.current;
10442
10772
  if (!node) return;
10443
10773
  const apply = () => {
@@ -10467,14 +10797,14 @@ function ChartFrame({
10467
10797
  children
10468
10798
  }) {
10469
10799
  const [ref, width] = useMeasuredWidth();
10470
- const chartId = `records-chart-${(0, import_react73.useId)().replace(/:/g, "")}`;
10471
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10800
+ const chartId = `records-chart-${(0, import_react75.useId)().replace(/:/g, "")}`;
10801
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
10472
10802
  "div",
10473
10803
  {
10474
10804
  ref,
10475
10805
  "data-chart": chartId,
10476
10806
  style: { height, ...chartVariables(config) },
10477
- className: (0, import_design_system36.cn)(
10807
+ className: (0, import_design_system37.cn)(
10478
10808
  "w-full min-w-0 overflow-hidden text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-layer]:outline-none [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
10479
10809
  className
10480
10810
  ),
@@ -10490,27 +10820,27 @@ function ChartTooltipContent({
10490
10820
  className
10491
10821
  }) {
10492
10822
  if (!active || !payload || payload.length === 0) return null;
10493
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
10823
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
10494
10824
  "div",
10495
10825
  {
10496
- className: (0, import_design_system36.cn)(
10826
+ className: (0, import_design_system37.cn)(
10497
10827
  "grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl",
10498
10828
  className
10499
10829
  ),
10500
10830
  children: [
10501
- label ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "font-medium", children: label }) : null,
10502
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "grid gap-1.5", children: payload.map((entry, index) => {
10831
+ label ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "font-medium", children: label }) : null,
10832
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "grid gap-1.5", children: payload.map((entry, index) => {
10503
10833
  const key = String(entry.dataKey ?? entry.name ?? index);
10504
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
10505
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10834
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
10835
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
10506
10836
  "span",
10507
10837
  {
10508
10838
  className: "h-2.5 w-2.5 shrink-0 rounded-[2px] bg-[--color-swatch]",
10509
10839
  style: { "--color-swatch": entry.color }
10510
10840
  }
10511
10841
  ),
10512
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-muted-foreground", children: config[key]?.label ?? key }),
10513
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "ml-auto font-mono font-medium tabular-nums text-foreground", children: typeof entry.value === "number" ? entry.value.toLocaleString() : entry.value })
10842
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "text-muted-foreground", children: config[key]?.label ?? key }),
10843
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "ml-auto font-mono font-medium tabular-nums text-foreground", children: typeof entry.value === "number" ? entry.value.toLocaleString() : entry.value })
10514
10844
  ] }, key);
10515
10845
  }) })
10516
10846
  ]
@@ -10523,10 +10853,10 @@ function ChartLegendContent({
10523
10853
  className
10524
10854
  }) {
10525
10855
  if (!payload || payload.length === 0) return null;
10526
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: (0, import_design_system36.cn)("flex flex-wrap items-center justify-center gap-3 pt-2", className), children: payload.map((entry, index) => {
10856
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: (0, import_design_system37.cn)("flex flex-wrap items-center justify-center gap-3 pt-2", className), children: payload.map((entry, index) => {
10527
10857
  const key = String(entry.dataKey ?? entry.value ?? index);
10528
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
10529
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10858
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
10859
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
10530
10860
  "span",
10531
10861
  {
10532
10862
  className: "h-2 w-2 shrink-0 rounded-[2px] bg-[--color-swatch]",
@@ -10561,24 +10891,24 @@ function isSignatureField(field) {
10561
10891
  }
10562
10892
 
10563
10893
  // src/DocTemplate.tsx
10564
- var import_react74 = require("react");
10565
- var import_react75 = require("@ai-matrx/records/react");
10566
- var import_design_system37 = require("@ai-matrx/design-system");
10567
- var import_jsx_runtime40 = require("react/jsx-runtime");
10894
+ var import_react76 = require("react");
10895
+ var import_react77 = require("@ai-matrx/records/react");
10896
+ var import_design_system38 = require("@ai-matrx/design-system");
10897
+ var import_jsx_runtime41 = require("react/jsx-runtime");
10568
10898
  function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, className }) {
10569
- const client = (0, import_react75.useRecordsClient)();
10899
+ const client = (0, import_react77.useRecordsClient)();
10570
10900
  const claimSeed = useSeedGuard();
10571
- const table = (0, import_react75.useTable)(tableId);
10901
+ const table = (0, import_react77.useTable)(tableId);
10572
10902
  const rights = useTableRights(table.data);
10573
- const fields = (0, import_react75.useFields)(tableId);
10574
- const [templates, setTemplates] = (0, import_react74.useState)(null);
10575
- const [error, setError] = (0, import_react74.useState)(null);
10576
- const [activeId, setActiveId] = (0, import_react74.useState)(activeTemplateId ?? null);
10577
- const [draftName, setDraftName] = (0, import_react74.useState)("");
10578
- const [draftBody, setDraftBody] = (0, import_react74.useState)("");
10579
- const [unresolved, setUnresolved] = (0, import_react74.useState)([]);
10580
- const [saving, setSaving] = (0, import_react74.useState)(false);
10581
- const load = (0, import_react74.useCallback)(async () => {
10903
+ const fields = (0, import_react77.useFields)(tableId);
10904
+ const [templates, setTemplates] = (0, import_react76.useState)(null);
10905
+ const [error, setError] = (0, import_react76.useState)(null);
10906
+ const [activeId, setActiveId] = (0, import_react76.useState)(activeTemplateId ?? null);
10907
+ const [draftName, setDraftName] = (0, import_react76.useState)("");
10908
+ const [draftBody, setDraftBody] = (0, import_react76.useState)("");
10909
+ const [unresolved, setUnresolved] = (0, import_react76.useState)([]);
10910
+ const [saving, setSaving] = (0, import_react76.useState)(false);
10911
+ const load = (0, import_react76.useCallback)(async () => {
10582
10912
  const held = await client.docTemplates({ table_id: tableId });
10583
10913
  if (!held.ok) {
10584
10914
  setError(held.error);
@@ -10609,10 +10939,10 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10609
10939
  setError(null);
10610
10940
  setTemplates(rows);
10611
10941
  }, [client, tableId, seed, fields.data]);
10612
- (0, import_react74.useEffect)(() => {
10942
+ (0, import_react76.useEffect)(() => {
10613
10943
  void load();
10614
10944
  }, [load]);
10615
- (0, import_react74.useEffect)(() => {
10945
+ (0, import_react76.useEffect)(() => {
10616
10946
  if (!templates || templates.length === 0) return;
10617
10947
  const chosen = templates.find((t) => t.id === (activeTemplateId ?? activeId)) ?? templates[0];
10618
10948
  if (chosen.id !== activeId) setActiveId(chosen.id);
@@ -10620,7 +10950,7 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10620
10950
  setDraftBody(chosen.body);
10621
10951
  onActiveTemplate?.(chosen);
10622
10952
  }, [templates, activeTemplateId]);
10623
- (0, import_react74.useEffect)(() => {
10953
+ (0, import_react76.useEffect)(() => {
10624
10954
  let cancelled = false;
10625
10955
  if (draftBody.trim() === "") {
10626
10956
  setUnresolved([]);
@@ -10650,25 +10980,25 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10650
10980
  setActiveId(saved.data);
10651
10981
  await load();
10652
10982
  }
10653
- if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(RefusalNotice, { error: fields.error, className });
10983
+ if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(RefusalNotice, { error: fields.error, className });
10654
10984
  if (error) {
10655
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
10985
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10656
10986
  RefusalNotice,
10657
10987
  {
10658
10988
  error,
10659
10989
  className,
10660
- actions: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system37.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
10990
+ actions: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
10661
10991
  }
10662
10992
  );
10663
10993
  }
10664
- if (templates === null || fields.loading) return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system37.Skeleton, { className: (0, import_design_system37.cn)("h-64 w-full", className) });
10994
+ if (templates === null || fields.loading) return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_design_system38.Skeleton, { className: (0, import_design_system38.cn)("h-64 w-full", className) });
10665
10995
  if (!rights.admin) {
10666
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: (0, import_design_system37.cn)("text-xs text-muted-foreground", className), children: rights.why("structure") });
10996
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: (0, import_design_system38.cn)("text-xs text-muted-foreground", className), children: rights.why("structure") });
10667
10997
  }
10668
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: (0, import_design_system37.cn)("flex flex-col gap-2", className), children: [
10669
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex items-center gap-1 overflow-x-auto", role: "group", "aria-label": "Templates", children: [
10670
- templates.map((t) => /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
10671
- import_design_system37.Button,
10998
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: (0, import_design_system38.cn)("flex flex-col gap-2", className), children: [
10999
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex items-center gap-1 overflow-x-auto", role: "group", "aria-label": "Templates", children: [
11000
+ templates.map((t) => /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
11001
+ import_design_system38.Button,
10672
11002
  {
10673
11003
  size: "sm",
10674
11004
  variant: t.id === activeId ? "secondary" : "ghost",
@@ -10680,7 +11010,7 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10680
11010
  },
10681
11011
  children: [
10682
11012
  t.name,
10683
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "ml-1 text-[10px] text-muted-foreground", children: [
11013
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "ml-1 text-[10px] text-muted-foreground", children: [
10684
11014
  "v",
10685
11015
  t.template_version
10686
11016
  ] })
@@ -10688,8 +11018,8 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10688
11018
  },
10689
11019
  t.id
10690
11020
  )),
10691
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
10692
- import_design_system37.Button,
11021
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
11022
+ import_design_system38.Button,
10693
11023
  {
10694
11024
  size: "sm",
10695
11025
  variant: "ghost",
@@ -10701,16 +11031,16 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10701
11031
  children: "New template"
10702
11032
  }
10703
11033
  ),
10704
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system37.Button, { size: "sm", className: "ml-auto", disabled: saving, onClick: () => void save(), children: saving ? "Saving\u2026" : "Save" })
11034
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_design_system38.Button, { size: "sm", className: "ml-auto", disabled: saving, onClick: () => void save(), children: saving ? "Saving\u2026" : "Save" })
10705
11035
  ] }),
10706
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("label", { className: "flex flex-col gap-1", children: [
10707
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system37.Label, { className: "text-xs font-medium", children: "Name" }),
10708
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system37.BasicInput, { value: draftName, onChange: (e) => setDraftName(e.target.value), placeholder: "Agreement" })
11036
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { className: "flex flex-col gap-1", children: [
11037
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_design_system38.Label, { className: "text-xs font-medium", children: "Name" }),
11038
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_design_system38.BasicInput, { value: draftName, onChange: (e) => setDraftName(e.target.value), placeholder: "Agreement" })
10709
11039
  ] }),
10710
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
10711
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "text-xs text-muted-foreground", children: "Insert" }),
10712
- (fields.data ?? []).map((field) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
10713
- import_design_system37.Button,
11040
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
11041
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "text-xs text-muted-foreground", children: "Insert" }),
11042
+ (fields.data ?? []).map((field) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
11043
+ import_design_system38.Button,
10714
11044
  {
10715
11045
  size: "sm",
10716
11046
  variant: "ghost",
@@ -10721,8 +11051,8 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10721
11051
  field.id
10722
11052
  ))
10723
11053
  ] }),
10724
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
10725
- import_design_system37.BasicTextarea,
11054
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
11055
+ import_design_system38.BasicTextarea,
10726
11056
  {
10727
11057
  rows: 10,
10728
11058
  "aria-label": "Template body",
@@ -10731,28 +11061,28 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10731
11061
  onChange: (e) => setDraftBody(e.target.value)
10732
11062
  }
10733
11063
  ),
10734
- unresolved.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("ul", { className: "flex flex-col gap-0.5 rounded border border-dashed px-2 py-1 text-xs", children: unresolved.map((token) => /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("li", { className: "text-destructive", children: [
10735
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("code", { children: token.raw }),
11064
+ unresolved.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("ul", { className: "flex flex-col gap-0.5 rounded border border-dashed px-2 py-1 text-xs", children: unresolved.map((token) => /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("li", { className: "text-destructive", children: [
11065
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("code", { children: token.raw }),
10736
11066
  " \u2014 ",
10737
11067
  token.why
10738
- ] }, token.raw)) }) : draftBody.trim() !== "" ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-xs text-muted-foreground", children: "Every token in this body points at a Field this table can answer." }) : null
11068
+ ] }, token.raw)) }) : draftBody.trim() !== "" ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "text-xs text-muted-foreground", children: "Every token in this body points at a Field this table can answer." }) : null
10739
11069
  ] });
10740
11070
  }
10741
11071
 
10742
11072
  // src/DocRender.tsx
10743
- var import_react76 = require("react");
10744
- var import_react77 = require("@ai-matrx/records/react");
10745
- var import_design_system38 = require("@ai-matrx/design-system");
10746
- var import_jsx_runtime41 = require("react/jsx-runtime");
11073
+ var import_react78 = require("react");
11074
+ var import_react79 = require("@ai-matrx/records/react");
11075
+ var import_design_system39 = require("@ai-matrx/design-system");
11076
+ var import_jsx_runtime42 = require("react/jsx-runtime");
10747
11077
  function DocRender({ templateId, recordId, filename, onRendered, className }) {
10748
- const client = (0, import_react77.useRecordsClient)();
10749
- const [preview, setPreview] = (0, import_react76.useState)(null);
10750
- const [renders, setRenders] = (0, import_react76.useState)(null);
10751
- const [showing, setShowing] = (0, import_react76.useState)(null);
10752
- const [error, setError] = (0, import_react76.useState)(null);
10753
- const [busy, setBusy] = (0, import_react76.useState)(null);
10754
- const paper = (0, import_react76.useRef)(null);
10755
- const load = (0, import_react76.useCallback)(async () => {
11078
+ const client = (0, import_react79.useRecordsClient)();
11079
+ const [preview, setPreview] = (0, import_react78.useState)(null);
11080
+ const [renders, setRenders] = (0, import_react78.useState)(null);
11081
+ const [showing, setShowing] = (0, import_react78.useState)(null);
11082
+ const [error, setError] = (0, import_react78.useState)(null);
11083
+ const [busy, setBusy] = (0, import_react78.useState)(null);
11084
+ const paper = (0, import_react78.useRef)(null);
11085
+ const load = (0, import_react78.useCallback)(async () => {
10756
11086
  const [body, held] = await Promise.all([
10757
11087
  client.docRenderBody({ template_id: templateId, record_id: recordId }),
10758
11088
  client.docRenders({ record_id: recordId })
@@ -10769,7 +11099,7 @@ function DocRender({ templateId, recordId, filename, onRendered, className }) {
10769
11099
  setPreview(body.data);
10770
11100
  setRenders(held.data.filter((r) => r.template_id === templateId));
10771
11101
  }, [client, templateId, recordId]);
10772
- (0, import_react76.useEffect)(() => {
11102
+ (0, import_react78.useEffect)(() => {
10773
11103
  void load();
10774
11104
  }, [load]);
10775
11105
  async function freeze() {
@@ -10806,22 +11136,22 @@ function DocRender({ templateId, recordId, filename, onRendered, className }) {
10806
11136
  }
10807
11137
  }
10808
11138
  if (error) {
10809
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
11139
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
10810
11140
  RefusalNotice,
10811
11141
  {
10812
11142
  error,
10813
11143
  className,
10814
- actions: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
11144
+ actions: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_design_system39.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
10815
11145
  }
10816
11146
  );
10817
11147
  }
10818
- if (preview === null || renders === null) return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_design_system38.Skeleton, { className: (0, import_design_system38.cn)("h-64 w-full", className) });
11148
+ if (preview === null || renders === null) return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_design_system39.Skeleton, { className: (0, import_design_system39.cn)("h-64 w-full", className) });
10819
11149
  const frozen = showing ? renders.find((r) => r.id === showing) ?? null : null;
10820
11150
  const text = frozen ? frozen.body : preview;
10821
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: (0, import_design_system38.cn)("flex flex-col gap-2", className), children: [
10822
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex items-center gap-1 text-xs", children: [
10823
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10824
- import_design_system38.Button,
11151
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: (0, import_design_system39.cn)("flex flex-col gap-2", className), children: [
11152
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center gap-1 text-xs", children: [
11153
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11154
+ import_design_system39.Button,
10825
11155
  {
10826
11156
  size: "sm",
10827
11157
  variant: frozen ? "ghost" : "secondary",
@@ -10830,8 +11160,8 @@ function DocRender({ templateId, recordId, filename, onRendered, className }) {
10830
11160
  children: "As it reads now"
10831
11161
  }
10832
11162
  ),
10833
- renders.map((render) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10834
- import_design_system38.Button,
11163
+ renders.map((render) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11164
+ import_design_system39.Button,
10835
11165
  {
10836
11166
  size: "sm",
10837
11167
  variant: render.id === showing ? "secondary" : "ghost",
@@ -10842,33 +11172,33 @@ function DocRender({ templateId, recordId, filename, onRendered, className }) {
10842
11172
  },
10843
11173
  render.id
10844
11174
  )),
10845
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "ml-auto flex items-center gap-1", children: [
10846
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_design_system38.Button, { size: "sm", disabled: busy !== null, onClick: () => void freeze(), children: busy === "freeze" ? "Freezing\u2026" : "Freeze this version" }),
10847
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", disabled: busy !== null, onClick: () => void toPdf(), children: busy === "pdf" ? "Making the PDF\u2026" : "PDF" })
11175
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "ml-auto flex items-center gap-1", children: [
11176
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_design_system39.Button, { size: "sm", disabled: busy !== null, onClick: () => void freeze(), children: busy === "freeze" ? "Freezing\u2026" : "Freeze this version" }),
11177
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_design_system39.Button, { size: "sm", variant: "ghost", disabled: busy !== null, onClick: () => void toPdf(), children: busy === "pdf" ? "Making the PDF\u2026" : "PDF" })
10848
11178
  ] })
10849
11179
  ] }),
10850
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { ref: paper, className: "whitespace-pre-wrap rounded border bg-background p-4 text-sm text-foreground", children: text }),
10851
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "text-xs text-muted-foreground", children: frozen ? `Frozen ${new Date(frozen.rendered_at).toLocaleString()} from template v${frozen.template_version}. Its text and its SHA-256 (${frozen.content_hash.slice(0, 12)}\u2026) are what any signature seals.` : "This is how the template reads against this record right now. Nothing has been frozen, so there is no version for anyone to sign yet." })
11180
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { ref: paper, className: "whitespace-pre-wrap rounded border bg-background p-4 text-sm text-foreground", children: text }),
11181
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-xs text-muted-foreground", children: frozen ? `Frozen ${new Date(frozen.rendered_at).toLocaleString()} from template v${frozen.template_version}. Its text and its SHA-256 (${frozen.content_hash.slice(0, 12)}\u2026) are what any signature seals.` : "This is how the template reads against this record right now. Nothing has been frozen, so there is no version for anyone to sign yet." })
10852
11182
  ] });
10853
11183
  }
10854
11184
 
10855
11185
  // src/SignBlock.tsx
10856
- var import_react78 = require("react");
10857
- var import_react79 = require("@ai-matrx/records/react");
10858
- var import_design_system39 = require("@ai-matrx/design-system");
10859
- var import_react80 = require("@ai-matrx/records/react");
10860
- var import_jsx_runtime42 = require("react/jsx-runtime");
11186
+ var import_react80 = require("react");
11187
+ var import_react81 = require("@ai-matrx/records/react");
11188
+ var import_design_system40 = require("@ai-matrx/design-system");
11189
+ var import_react82 = require("@ai-matrx/records/react");
11190
+ var import_jsx_runtime43 = require("react/jsx-runtime");
10861
11191
  function SignBlock({ tableId, recordId, render, className }) {
10862
- const client = (0, import_react79.useRecordsClient)();
10863
- const table = (0, import_react80.useTable)(tableId);
11192
+ const client = (0, import_react81.useRecordsClient)();
11193
+ const table = (0, import_react82.useTable)(tableId);
10864
11194
  const rights = useTableRights(table.data);
10865
- const fields = (0, import_react79.useFields)(tableId);
10866
- const [signatures, setSignatures] = (0, import_react78.useState)(null);
10867
- const [verdicts, setVerdicts] = (0, import_react78.useState)({});
10868
- const [error, setError] = (0, import_react78.useState)(null);
10869
- const [name, setName] = (0, import_react78.useState)("");
10870
- const [busy, setBusy] = (0, import_react78.useState)(false);
10871
- const load = (0, import_react78.useCallback)(async () => {
11195
+ const fields = (0, import_react81.useFields)(tableId);
11196
+ const [signatures, setSignatures] = (0, import_react80.useState)(null);
11197
+ const [verdicts, setVerdicts] = (0, import_react80.useState)({});
11198
+ const [error, setError] = (0, import_react80.useState)(null);
11199
+ const [name, setName] = (0, import_react80.useState)("");
11200
+ const [busy, setBusy] = (0, import_react80.useState)(false);
11201
+ const load = (0, import_react80.useCallback)(async () => {
10872
11202
  const held = await client.docSignatures({ record_id: recordId });
10873
11203
  if (!held.ok) {
10874
11204
  setError(held.error);
@@ -10883,7 +11213,7 @@ function SignBlock({ tableId, recordId, render, className }) {
10883
11213
  }
10884
11214
  setVerdicts(answers);
10885
11215
  }, [client, recordId]);
10886
- (0, import_react78.useEffect)(() => {
11216
+ (0, import_react80.useEffect)(() => {
10887
11217
  void load();
10888
11218
  }, [load]);
10889
11219
  async function sign(field) {
@@ -10903,58 +11233,58 @@ function SignBlock({ tableId, recordId, render, className }) {
10903
11233
  setName("");
10904
11234
  await load();
10905
11235
  }
10906
- if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(RefusalNotice, { error: fields.error, className });
11236
+ if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(RefusalNotice, { error: fields.error, className });
10907
11237
  if (error) {
10908
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11238
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
10909
11239
  RefusalNotice,
10910
11240
  {
10911
11241
  error,
10912
11242
  className,
10913
- actions: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_design_system39.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
11243
+ actions: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system40.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
10914
11244
  }
10915
11245
  );
10916
11246
  }
10917
- if (fields.loading || signatures === null) return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_design_system39.Skeleton, { className: (0, import_design_system39.cn)("h-32 w-full", className) });
11247
+ if (fields.loading || signatures === null) return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system40.Skeleton, { className: (0, import_design_system40.cn)("h-32 w-full", className) });
10918
11248
  const signable = (fields.data ?? []).filter(isSignatureField);
10919
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: (0, import_design_system39.cn)("flex flex-col gap-2", className), children: [
10920
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
10921
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "font-medium text-foreground", children: "Signatures" }),
10922
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { children: [
11249
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: (0, import_design_system40.cn)("flex flex-col gap-2", className), children: [
11250
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
11251
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "font-medium text-foreground", children: "Signatures" }),
11252
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { children: [
10923
11253
  signatures.length,
10924
11254
  " on this record"
10925
11255
  ] })
10926
11256
  ] }),
10927
- signatures.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("ul", { className: "flex flex-col gap-1", children: signatures.map((signature) => {
11257
+ signatures.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("ul", { className: "flex flex-col gap-1", children: signatures.map((signature) => {
10928
11258
  const verdict = verdicts[signature.id];
10929
11259
  const intact = typeof verdict === "object" && verdict !== null ? verdict.intact : void 0;
10930
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("li", { className: "rounded border px-2 py-1.5 text-xs", children: [
10931
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center gap-2", children: [
10932
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "font-medium", children: signature.signer_name }),
10933
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "text-muted-foreground", children: signature.field_key }),
10934
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "text-muted-foreground", children: new Date(signature.signed_at).toLocaleString() }),
10935
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "ml-auto font-mono text-[10px] text-muted-foreground", children: [
11260
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("li", { className: "rounded border px-2 py-1.5 text-xs", children: [
11261
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-center gap-2", children: [
11262
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "font-medium", children: signature.signer_name }),
11263
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-muted-foreground", children: signature.field_key }),
11264
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-muted-foreground", children: new Date(signature.signed_at).toLocaleString() }),
11265
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "ml-auto font-mono text-[10px] text-muted-foreground", children: [
10936
11266
  "v",
10937
11267
  signature.document_version,
10938
11268
  " \xB7 ",
10939
11269
  signature.document_hash.slice(0, 12)
10940
11270
  ] })
10941
11271
  ] }),
10942
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: (0, import_design_system39.cn)("mt-0.5", intact === false ? "text-destructive" : "text-muted-foreground"), children: intact === true ? "The store says what was signed is still exactly what is there." : intact === false ? typeof verdict === "object" && verdict !== null && "reason" in verdict ? String(verdict.reason) : "The store says what is there no longer matches what was signed." : String(verdict ?? "") })
11272
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: (0, import_design_system40.cn)("mt-0.5", intact === false ? "text-destructive" : "text-muted-foreground"), children: intact === true ? "The store says what was signed is still exactly what is there." : intact === false ? typeof verdict === "object" && verdict !== null && "reason" in verdict ? String(verdict.reason) : "The store says what is there no longer matches what was signed." : String(verdict ?? "") })
10943
11273
  ] }, signature.id);
10944
11274
  }) }) : null,
10945
- !render ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-xs text-muted-foreground", children: 'Nothing has been frozen yet, so there is no version to sign. A signature seals one exact document version and its hash \u2014 "the document as it reads today" is not something anyone can agree to.' }) : signable.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("p", { className: "text-xs text-muted-foreground", children: [
11275
+ !render ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-xs text-muted-foreground", children: 'Nothing has been frozen yet, so there is no version to sign. A signature seals one exact document version and its hash \u2014 "the document as it reads today" is not something anyone can agree to.' }) : signable.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("p", { className: "text-xs text-muted-foreground", children: [
10946
11276
  "This table has no signature Field, so there is nowhere to write a signature. A signature is a Value on a text Field whose format is ",
10947
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("code", { children: "signature" }),
11277
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("code", { children: "signature" }),
10948
11278
  " \u2014 add one and the signing appears."
10949
- ] }) : !rights.write ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-xs text-muted-foreground", children: rights.why("write") }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "flex flex-col gap-1", children: signable.map((field) => {
11279
+ ] }) : !rights.write ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-xs text-muted-foreground", children: rights.why("write") }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "flex flex-col gap-1", children: signable.map((field) => {
10950
11280
  const already = signatures.find((s) => s.field_key === field.key);
10951
11281
  if (already) {
10952
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("p", { className: "text-xs text-muted-foreground", children: [
11282
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("p", { className: "text-xs text-muted-foreground", children: [
10953
11283
  fieldName(field),
10954
11284
  " is signed, and a signature is immutable once made. A further agreement is a further Field with its own signature, or a further version with its own seal."
10955
11285
  ] }, field.id);
10956
11286
  }
10957
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
11287
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
10958
11288
  "form",
10959
11289
  {
10960
11290
  className: "flex items-center gap-1",
@@ -10963,8 +11293,8 @@ function SignBlock({ tableId, recordId, render, className }) {
10963
11293
  if (name.trim() !== "") void sign(field);
10964
11294
  },
10965
11295
  children: [
10966
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
10967
- import_design_system39.BasicInput,
11296
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
11297
+ import_design_system40.BasicInput,
10968
11298
  {
10969
11299
  className: "h-8 w-56 text-xs",
10970
11300
  "aria-label": `Sign ${fieldName(field)}`,
@@ -10973,8 +11303,8 @@ function SignBlock({ tableId, recordId, render, className }) {
10973
11303
  onChange: (e) => setName(e.target.value)
10974
11304
  }
10975
11305
  ),
10976
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_design_system39.Button, { size: "sm", type: "submit", disabled: busy || name.trim() === "", children: "Sign" }),
10977
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
11306
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system40.Button, { size: "sm", type: "submit", disabled: busy || name.trim() === "", children: "Sign" }),
11307
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
10978
11308
  "seals version ",
10979
11309
  render.template_version,
10980
11310
  " \xB7 ",
@@ -10990,32 +11320,32 @@ function SignBlock({ tableId, recordId, render, className }) {
10990
11320
  }
10991
11321
 
10992
11322
  // src/NotifyRuleEditor.tsx
10993
- var import_react81 = require("react");
10994
- var import_react82 = require("@ai-matrx/records/react");
10995
- var import_design_system40 = require("@ai-matrx/design-system");
10996
- var import_jsx_runtime43 = require("react/jsx-runtime");
10997
- var CADENCE_WORDS = {
11323
+ var import_react83 = require("react");
11324
+ var import_react84 = require("@ai-matrx/records/react");
11325
+ var import_design_system41 = require("@ai-matrx/design-system");
11326
+ var import_jsx_runtime44 = require("react/jsx-runtime");
11327
+ var CADENCE_WORDS2 = {
10998
11328
  instant: "as it happens",
10999
11329
  hourly: "hourly summary",
11000
11330
  daily: "daily summary",
11001
11331
  weekly: "weekly summary"
11002
11332
  };
11003
- var CHANNEL_WORDS2 = {
11333
+ var CHANNEL_WORDS3 = {
11004
11334
  in_app: "in the app",
11005
11335
  email: "by email",
11006
11336
  sms: "by text"
11007
11337
  };
11008
11338
  function NotifyRuleEditor({ tableId, seed, className }) {
11009
- const client = (0, import_react82.useRecordsClient)();
11339
+ const client = (0, import_react84.useRecordsClient)();
11010
11340
  const host = useRecordsUi();
11011
- const table = (0, import_react82.useTable)(tableId);
11341
+ const table = (0, import_react84.useTable)(tableId);
11012
11342
  const rights = useTableRights(table.data);
11013
- const [subscriptions, setSubscriptions] = (0, import_react81.useState)(null);
11014
- const [cadences, setCadences] = (0, import_react81.useState)([]);
11015
- const [views, setViews] = (0, import_react81.useState)(null);
11016
- const [error, setError] = (0, import_react81.useState)(null);
11017
- const [busy, setBusy] = (0, import_react81.useState)(false);
11018
- const load = (0, import_react81.useCallback)(async () => {
11343
+ const [subscriptions, setSubscriptions] = (0, import_react83.useState)(null);
11344
+ const [cadences, setCadences] = (0, import_react83.useState)([]);
11345
+ const [views, setViews] = (0, import_react83.useState)(null);
11346
+ const [error, setError] = (0, import_react83.useState)(null);
11347
+ const [busy, setBusy] = (0, import_react83.useState)(false);
11348
+ const load = (0, import_react83.useCallback)(async () => {
11019
11349
  const [held, offered] = await Promise.all([
11020
11350
  // THE PERSON'S OWN DOOR, not the notifier's. It answers what is addressed
11021
11351
  // to them plus — only where they hold admin on this Table — anyone's over
@@ -11035,10 +11365,10 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11035
11365
  if (host.savedViews) setViews(await host.savedViews());
11036
11366
  else setViews(null);
11037
11367
  }, [client, host, tableId]);
11038
- (0, import_react81.useEffect)(() => {
11368
+ (0, import_react83.useEffect)(() => {
11039
11369
  void load();
11040
11370
  }, [load]);
11041
- const write = (0, import_react81.useCallback)(
11371
+ const write = (0, import_react83.useCallback)(
11042
11372
  async (spec) => {
11043
11373
  const declared = await client.subscriptionDeclare({
11044
11374
  table_id: tableId,
@@ -11063,7 +11393,7 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11063
11393
  },
11064
11394
  [client, tableId]
11065
11395
  );
11066
- (0, import_react81.useEffect)(() => {
11396
+ (0, import_react83.useEffect)(() => {
11067
11397
  if (!subscriptions || !seed || seed.length === 0) return;
11068
11398
  const missing = seed.filter((s) => !subscriptions.some((held) => held.name === s.name));
11069
11399
  if (missing.length === 0) return;
@@ -11077,7 +11407,7 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11077
11407
  async function subscribe(viewId, viewName, cadence, channel, schedule, quiet) {
11078
11408
  setBusy(true);
11079
11409
  const ok = await write({
11080
- name: `${viewName} \u2014 ${CADENCE_WORDS[cadence] ?? cadence}`,
11410
+ name: `${viewName} \u2014 ${CADENCE_WORDS2[cadence] ?? cadence}`,
11081
11411
  savedViewId: viewId,
11082
11412
  cadence,
11083
11413
  channel,
@@ -11098,45 +11428,45 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11098
11428
  await load();
11099
11429
  }
11100
11430
  if (error) {
11101
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
11431
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11102
11432
  RefusalNotice,
11103
11433
  {
11104
11434
  error,
11105
11435
  className,
11106
- actions: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system40.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
11436
+ actions: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_design_system41.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
11107
11437
  }
11108
11438
  );
11109
11439
  }
11110
- if (subscriptions === null) return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system40.Skeleton, { className: (0, import_design_system40.cn)("h-40 w-full", className) });
11111
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: (0, import_design_system40.cn)("flex flex-col gap-2", className), children: [
11112
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
11113
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "font-medium text-foreground", children: "Tell me when" }),
11114
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { children: [
11440
+ if (subscriptions === null) return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_design_system41.Skeleton, { className: (0, import_design_system41.cn)("h-40 w-full", className) });
11441
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: (0, import_design_system41.cn)("flex flex-col gap-2", className), children: [
11442
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
11443
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "font-medium text-foreground", children: "Tell me when" }),
11444
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { children: [
11115
11445
  subscriptions.length,
11116
11446
  " subscription",
11117
11447
  subscriptions.length === 1 ? "" : "s"
11118
11448
  ] })
11119
11449
  ] }),
11120
- subscriptions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-xs text-muted-foreground", children: "Nothing is telling anyone about this yet. A subscription is a Rule over a saved view, so what you are told about is exactly what that view holds." }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("ul", { className: "flex flex-col gap-1", children: subscriptions.map((held) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("li", { className: "flex items-center gap-2 rounded border px-2 py-1.5 text-xs", children: [
11121
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "truncate font-medium", children: held.name }),
11122
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-muted-foreground", children: CADENCE_WORDS[held.cadence] ?? held.cadence }),
11123
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-muted-foreground", children: CHANNEL_WORDS2[held.channel] ?? held.channel }),
11124
- held.schedule ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-muted-foreground", children: held.schedule }) : null,
11125
- held.next_digest_at ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "text-muted-foreground", children: [
11450
+ subscriptions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "text-xs text-muted-foreground", children: "Nothing is telling anyone about this yet. A subscription is a Rule over a saved view, so what you are told about is exactly what that view holds." }) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("ul", { className: "flex flex-col gap-1", children: subscriptions.map((held) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("li", { className: "flex items-center gap-2 rounded border px-2 py-1.5 text-xs", children: [
11451
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "truncate font-medium", children: held.name }),
11452
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-muted-foreground", children: CADENCE_WORDS2[held.cadence] ?? held.cadence }),
11453
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-muted-foreground", children: CHANNEL_WORDS3[held.channel] ?? held.channel }),
11454
+ held.schedule ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-muted-foreground", children: held.schedule }) : null,
11455
+ held.next_digest_at ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "text-muted-foreground", children: [
11126
11456
  "next ",
11127
11457
  new Date(held.next_digest_at).toLocaleString()
11128
11458
  ] }) : null,
11129
- held.quiet_hours ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "text-muted-foreground", children: [
11459
+ held.quiet_hours ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "text-muted-foreground", children: [
11130
11460
  "quiet ",
11131
11461
  held.quiet_hours.start,
11132
11462
  "\u2013",
11133
11463
  held.quiet_hours.end
11134
11464
  ] }) : null,
11135
- held.recipient_user_id === null ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-destructive", children: "This one has nobody to tell, so it fires at nobody." }) : null,
11136
- held.saved_view_id === null ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-destructive", children: "This one names no view, so the store never admits a record to it." }) : null,
11137
- held.muted ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-muted-foreground", children: "Switched off \u2014 it tells nobody until somebody switches it back on." }) : null,
11138
- rights.write ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
11139
- import_design_system40.Button,
11465
+ held.recipient_user_id === null ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-destructive", children: "This one has nobody to tell, so it fires at nobody." }) : null,
11466
+ held.saved_view_id === null ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-destructive", children: "This one names no view, so the store never admits a record to it." }) : null,
11467
+ held.muted ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-muted-foreground", children: "Switched off \u2014 it tells nobody until somebody switches it back on." }) : null,
11468
+ rights.write ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11469
+ import_design_system41.Button,
11140
11470
  {
11141
11471
  size: "sm",
11142
11472
  variant: "ghost",
@@ -11147,7 +11477,7 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11147
11477
  }
11148
11478
  ) : null
11149
11479
  ] }, held.rule_id)) }),
11150
- views === null ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: NO_SAVED_VIEWS_REASON }) : views.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-xs text-muted-foreground", children: "This organization has no saved views yet, so there is nothing to subscribe to. Save a view first." }) : rights.write ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
11480
+ views === null ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: NO_SAVED_VIEWS_REASON }) : views.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "text-xs text-muted-foreground", children: "This organization has no saved views yet, so there is nothing to subscribe to. Save a view first." }) : rights.write ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
11151
11481
  "form",
11152
11482
  {
11153
11483
  className: "flex flex-wrap items-center gap-1",
@@ -11165,10 +11495,10 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11165
11495
  if (view) void subscribe(view, name, cadence, channel, schedule, quiet);
11166
11496
  },
11167
11497
  children: [
11168
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("select", { name: "view", "aria-label": "View to be told about", className: "h-7 rounded border bg-background px-1 text-xs", children: views.map((view) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("option", { value: view.id, children: view.name }, view.id)) }),
11169
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("select", { name: "cadence", "aria-label": "How often", className: "h-7 rounded border bg-background px-1 text-xs", children: (cadences.length > 0 ? cadences : ["instant"]).map((cadence) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("option", { value: cadence, children: CADENCE_WORDS[cadence] ?? cadence }, cadence)) }),
11170
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("select", { name: "channel", "aria-label": "Where it arrives", className: "h-7 rounded border bg-background px-1 text-xs", children: ["in_app", "email", "sms"].map((channel) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("option", { value: channel, children: CHANNEL_WORDS2[channel] }, channel)) }),
11171
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
11498
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("select", { name: "view", "aria-label": "View to be told about", className: "h-7 rounded border bg-background px-1 text-xs", children: views.map((view) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: view.id, children: view.name }, view.id)) }),
11499
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("select", { name: "cadence", "aria-label": "How often", className: "h-7 rounded border bg-background px-1 text-xs", children: (cadences.length > 0 ? cadences : ["instant"]).map((cadence) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: cadence, children: CADENCE_WORDS2[cadence] ?? cadence }, cadence)) }),
11500
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("select", { name: "channel", "aria-label": "Where it arrives", className: "h-7 rounded border bg-background px-1 text-xs", children: ["in_app", "email", "sms"].map((channel) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: channel, children: CHANNEL_WORDS3[channel] }, channel)) }),
11501
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11172
11502
  "input",
11173
11503
  {
11174
11504
  name: "schedule",
@@ -11177,8 +11507,8 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11177
11507
  className: "h-7 w-28 rounded border bg-background px-1 text-xs"
11178
11508
  }
11179
11509
  ),
11180
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-xs text-muted-foreground", children: "not between" }),
11181
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
11510
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-xs text-muted-foreground", children: "not between" }),
11511
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11182
11512
  "input",
11183
11513
  {
11184
11514
  name: "quiet_start",
@@ -11187,8 +11517,8 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11187
11517
  className: "h-7 rounded border bg-background px-1 text-xs"
11188
11518
  }
11189
11519
  ),
11190
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-xs text-muted-foreground", children: "and" }),
11191
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
11520
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-xs text-muted-foreground", children: "and" }),
11521
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11192
11522
  "input",
11193
11523
  {
11194
11524
  name: "quiet_end",
@@ -11197,21 +11527,21 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11197
11527
  className: "h-7 rounded border bg-background px-1 text-xs"
11198
11528
  }
11199
11529
  ),
11200
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system40.Button, { size: "sm", type: "submit", disabled: busy, children: "Tell me" }),
11201
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "w-full text-xs text-muted-foreground", children: "A send inside your quiet hours is held until they end \u2014 it is never dropped. Leave the schedule blank for the store's own default of 08:00." })
11530
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_design_system41.Button, { size: "sm", type: "submit", disabled: busy, children: "Tell me" }),
11531
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "w-full text-xs text-muted-foreground", children: "A send inside your quiet hours is held until they end \u2014 it is never dropped. Leave the schedule blank for the store's own default of 08:00." })
11202
11532
  ]
11203
11533
  }
11204
- ) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-xs text-muted-foreground", children: rights.why("write") })
11534
+ ) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "text-xs text-muted-foreground", children: rights.why("write") })
11205
11535
  ] });
11206
11536
  }
11207
11537
 
11208
11538
  // src/ChartBlock.tsx
11209
- var import_react83 = require("react");
11539
+ var import_react85 = require("react");
11210
11540
  var import_recharts = require("recharts");
11211
11541
  var import_records7 = require("@ai-matrx/records");
11212
11542
  var import_core6 = require("@ai-matrx/records/core");
11213
- var import_design_system41 = require("@ai-matrx/design-system");
11214
- var import_jsx_runtime44 = require("react/jsx-runtime");
11543
+ var import_design_system42 = require("@ai-matrx/design-system");
11544
+ var import_jsx_runtime45 = require("react/jsx-runtime");
11215
11545
  function pretty(n) {
11216
11546
  return Number.isInteger(n) ? n.toLocaleString() : n.toLocaleString(void 0, { maximumFractionDigits: 2 });
11217
11547
  }
@@ -11231,7 +11561,7 @@ function ChartBlock({ block, subject, className }) {
11231
11561
  const measures = block.measures && block.measures.length > 0 ? block.measures : [{ op: "count" }];
11232
11562
  const primary = (0, import_records7.measureKey)(measures[0]);
11233
11563
  const series = [primary];
11234
- const points = (0, import_react83.useMemo)(() => {
11564
+ const points = (0, import_react85.useMemo)(() => {
11235
11565
  if (kind === "stuck") return [];
11236
11566
  const rows = block.rows ?? [];
11237
11567
  return rows.map((row) => ({
@@ -11243,7 +11573,7 @@ function ChartBlock({ block, subject, className }) {
11243
11573
  n: row.row_count
11244
11574
  }));
11245
11575
  }, [block.rows, kind, series.join("|")]);
11246
- const config = (0, import_react83.useMemo)(() => {
11576
+ const config = (0, import_react85.useMemo)(() => {
11247
11577
  const out = {};
11248
11578
  series.forEach((key, index) => {
11249
11579
  out[key] = {
@@ -11267,18 +11597,18 @@ function ChartBlock({ block, subject, className }) {
11267
11597
  label: point.label === "All records" ? block.title : `${block.title} \xB7 ${point.label}`
11268
11598
  });
11269
11599
  } : null;
11270
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("figure", { className: (0, import_design_system41.cn)("flex min-w-0 flex-col gap-1.5 rounded border p-2", className), children: [
11271
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("figcaption", { className: "flex items-baseline gap-2 text-xs", children: [
11272
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "truncate font-medium", children: block.title || CHART_KIND_LABEL[kind] }),
11273
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "ml-auto shrink-0 text-muted-foreground", children: kind === "stuck" ? `${block.days ?? 14} days` : primary.replace("_", " of ") }),
11274
- typeof block.ms === "number" ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "shrink-0 tabular-nums text-muted-foreground/70", title: "how long the store took", children: [
11600
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("figure", { className: (0, import_design_system42.cn)("flex min-w-0 flex-col gap-1.5 rounded border p-2", className), children: [
11601
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("figcaption", { className: "flex items-baseline gap-2 text-xs", children: [
11602
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "truncate font-medium", children: block.title || CHART_KIND_LABEL[kind] }),
11603
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "ml-auto shrink-0 text-muted-foreground", children: kind === "stuck" ? `${block.days ?? 14} days` : primary.replace("_", " of ") }),
11604
+ typeof block.ms === "number" ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "shrink-0 tabular-nums text-muted-foreground/70", title: "how long the store took", children: [
11275
11605
  pretty(block.ms),
11276
11606
  " ms"
11277
11607
  ] }) : null
11278
11608
  ] }),
11279
- block.refused ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(RefusalNotice, { error: asRefusal(block) }) : needs ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "px-1 py-3 text-xs text-muted-foreground", children: needs }) : kind === "stuck" ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(StuckList, { rows: block.rows ?? [] }) : points.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "px-1 py-3 text-xs text-muted-foreground", children: "The store answered this question with no groups at all, so there is nothing to draw yet." }) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_jsx_runtime44.Fragment, { children: kind === "number" ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(BigNumber, { points, measure: primary, onDrill: drill }) : kind === "table" ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(GroupTable, { points, series, onDrill: drill }) : /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
11280
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Drawing, { kind, points, series, config, onDrill: drill }),
11281
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Values, { points, measure: primary, config, onDrill: drill })
11609
+ block.refused ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(RefusalNotice, { error: asRefusal(block) }) : needs ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: "px-1 py-3 text-xs text-muted-foreground", children: needs }) : kind === "stuck" ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(StuckList, { rows: block.rows ?? [] }) : points.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: "px-1 py-3 text-xs text-muted-foreground", children: "The store answered this question with no groups at all, so there is nothing to draw yet." }) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_jsx_runtime45.Fragment, { children: kind === "number" ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(BigNumber, { points, measure: primary, onDrill: drill }) : kind === "table" ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(GroupTable, { points, series, onDrill: drill }) : /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
11610
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Drawing, { kind, points, series, config, onDrill: drill }),
11611
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Values, { points, measure: primary, config, onDrill: drill })
11282
11612
  ] }) })
11283
11613
  ] });
11284
11614
  }
@@ -11289,16 +11619,16 @@ function BigNumber({
11289
11619
  }) {
11290
11620
  const total = points.reduce((sum, p) => sum + (p.values[measure] ?? 0), 0);
11291
11621
  const records = points.reduce((sum, p) => sum + p.n, 0);
11292
- const body = /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
11293
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-2xl font-semibold tabular-nums", children: pretty(total) }),
11294
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
11622
+ const body = /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
11623
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "text-2xl font-semibold tabular-nums", children: pretty(total) }),
11624
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
11295
11625
  "from ",
11296
11626
  records.toLocaleString(),
11297
11627
  " records"
11298
11628
  ] })
11299
11629
  ] });
11300
- if (!onDrill || !points[0]) return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "flex items-baseline gap-2 px-1 py-2", children: body });
11301
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11630
+ if (!onDrill || !points[0]) return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "flex items-baseline gap-2 px-1 py-2", children: body });
11631
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11302
11632
  "button",
11303
11633
  {
11304
11634
  type: "button",
@@ -11314,19 +11644,19 @@ function Values({
11314
11644
  config,
11315
11645
  onDrill
11316
11646
  }) {
11317
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("ul", { className: "flex flex-wrap gap-x-2 gap-y-0.5", children: points.map((point) => {
11318
- const text = /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
11319
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11647
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("ul", { className: "flex flex-wrap gap-x-2 gap-y-0.5", children: points.map((point) => {
11648
+ const text = /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
11649
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11320
11650
  "span",
11321
11651
  {
11322
11652
  className: "h-2 w-2 shrink-0 rounded-[2px]",
11323
11653
  style: { background: String(config[point.label]?.color ?? SERIES_COLORS[0]) }
11324
11654
  }
11325
11655
  ),
11326
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "truncate", children: point.label }),
11327
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "tabular-nums text-muted-foreground", children: pretty(point.values[measure] ?? 0) })
11656
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "truncate", children: point.label }),
11657
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "tabular-nums text-muted-foreground", children: pretty(point.values[measure] ?? 0) })
11328
11658
  ] });
11329
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("li", { className: "min-w-0", children: onDrill ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11659
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("li", { className: "min-w-0", children: onDrill ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11330
11660
  "button",
11331
11661
  {
11332
11662
  type: "button",
@@ -11334,7 +11664,7 @@ function Values({
11334
11664
  onClick: () => onDrill(point),
11335
11665
  children: text
11336
11666
  }
11337
- ) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "flex min-w-0 items-center gap-1.5 px-1 py-0.5 text-xs", children: text }) }, point.label);
11667
+ ) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "flex min-w-0 items-center gap-1.5 px-1 py-0.5 text-xs", children: text }) }, point.label);
11338
11668
  }) });
11339
11669
  }
11340
11670
  function GroupTable({
@@ -11342,8 +11672,8 @@ function GroupTable({
11342
11672
  series,
11343
11673
  onDrill
11344
11674
  }) {
11345
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("table", { className: "w-full text-xs", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("tbody", { children: points.map((point) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("tr", { className: "border-t first:border-t-0", children: [
11346
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: "min-w-0 truncate py-0.5 pr-2", children: onDrill ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11675
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("table", { className: "w-full text-xs", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("tbody", { children: points.map((point) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("tr", { className: "border-t first:border-t-0", children: [
11676
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("td", { className: "min-w-0 truncate py-0.5 pr-2", children: onDrill ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11347
11677
  "button",
11348
11678
  {
11349
11679
  type: "button",
@@ -11352,29 +11682,29 @@ function GroupTable({
11352
11682
  children: point.label
11353
11683
  }
11354
11684
  ) : point.label }),
11355
- series.map((key) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: "py-0.5 pl-2 text-right tabular-nums", children: pretty(point.values[key] ?? 0) }, key)),
11356
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: "py-0.5 pl-2 text-right tabular-nums text-muted-foreground", children: point.n })
11685
+ series.map((key) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("td", { className: "py-0.5 pl-2 text-right tabular-nums", children: pretty(point.values[key] ?? 0) }, key)),
11686
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("td", { className: "py-0.5 pl-2 text-right tabular-nums text-muted-foreground", children: point.n })
11357
11687
  ] }, point.label)) }) });
11358
11688
  }
11359
11689
  function StuckList({ rows }) {
11360
11690
  if (rows.length === 0) {
11361
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "px-1 py-3 text-xs text-muted-foreground", children: "Nothing has sat still this long. This block goes quiet when the work is moving." });
11691
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: "px-1 py-3 text-xs text-muted-foreground", children: "Nothing has sat still this long. This block goes quiet when the work is moving." });
11362
11692
  }
11363
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("table", { className: "w-full table-fixed text-xs", children: [
11364
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("colgroup", { children: [
11365
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("col", { className: "w-[45%]" }),
11366
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("col", { className: "w-[33%]" }),
11367
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("col", { className: "w-[22%]" })
11693
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("table", { className: "w-full table-fixed text-xs", children: [
11694
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("colgroup", { children: [
11695
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("col", { className: "w-[45%]" }),
11696
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("col", { className: "w-[33%]" }),
11697
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("col", { className: "w-[22%]" })
11368
11698
  ] }),
11369
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("thead", { className: "sr-only", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("tr", { children: [
11370
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("th", { children: "Record" }),
11371
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("th", { children: "Where it is" }),
11372
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("th", { children: "Days unchanged" })
11699
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("thead", { className: "sr-only", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("tr", { children: [
11700
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("th", { children: "Record" }),
11701
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("th", { children: "Where it is" }),
11702
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("th", { children: "Days unchanged" })
11373
11703
  ] }) }),
11374
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("tbody", { children: rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("tr", { className: "border-t first:border-t-0", children: [
11375
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: "truncate py-0.5 pr-2", title: row.title ?? void 0, children: row.title ?? row.record_id.slice(0, 8) }),
11376
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: "truncate py-0.5 pr-2 text-muted-foreground", title: row.state ?? void 0, children: row.state ?? "\u2014" }),
11377
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
11704
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("tbody", { children: rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("tr", { className: "border-t first:border-t-0", children: [
11705
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("td", { className: "truncate py-0.5 pr-2", title: row.title ?? void 0, children: row.title ?? row.record_id.slice(0, 8) }),
11706
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("td", { className: "truncate py-0.5 pr-2 text-muted-foreground", title: row.state ?? void 0, children: row.state ?? "\u2014" }),
11707
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
11378
11708
  "td",
11379
11709
  {
11380
11710
  className: "whitespace-nowrap py-0.5 text-right tabular-nums",
@@ -11424,12 +11754,12 @@ function Drawing({
11424
11754
  axisLine: false,
11425
11755
  tickFormatter: compactTick
11426
11756
  };
11427
- const tooltip = /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_recharts.Tooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartTooltipContent, { config }), cursor: false });
11428
- const legend = series.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_recharts.Legend, { content: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartLegendContent, { config }) }) : null;
11757
+ const tooltip = /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.Tooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ChartTooltipContent, { config }), cursor: false });
11758
+ const legend = series.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.Legend, { content: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ChartLegendContent, { config }) }) : null;
11429
11759
  if (kind === "donut") {
11430
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartFrame, { config, height: HEIGHT, children: (width) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_recharts.PieChart, { width, height: HEIGHT, children: [
11760
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ChartFrame, { config, height: HEIGHT, children: (width) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_recharts.PieChart, { width, height: HEIGHT, children: [
11431
11761
  tooltip,
11432
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11762
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11433
11763
  import_recharts.Pie,
11434
11764
  {
11435
11765
  data,
@@ -11439,19 +11769,19 @@ function Drawing({
11439
11769
  outerRadius: 58,
11440
11770
  isAnimationActive: false,
11441
11771
  ...click ? { onClick: click, className: "cursor-pointer" } : {},
11442
- children: points.map((point) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_recharts.Cell, { fill: String(config[point.label]?.color ?? SERIES_COLORS[0]) }, point.label))
11772
+ children: points.map((point) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.Cell, { fill: String(config[point.label]?.color ?? SERIES_COLORS[0]) }, point.label))
11443
11773
  }
11444
11774
  )
11445
11775
  ] }) });
11446
11776
  }
11447
11777
  if (kind === "line") {
11448
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartFrame, { config, height: HEIGHT, children: (width) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_recharts.LineChart, { width, height: HEIGHT, data, margin: { top: 6, right: 6, bottom: 0, left: 0 }, children: [
11449
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_recharts.CartesianGrid, { vertical: false }),
11450
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_recharts.XAxis, { dataKey: "label", ...axis }),
11451
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_recharts.YAxis, { width: 44, ...axis }),
11778
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ChartFrame, { config, height: HEIGHT, children: (width) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_recharts.LineChart, { width, height: HEIGHT, data, margin: { top: 6, right: 6, bottom: 0, left: 0 }, children: [
11779
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.CartesianGrid, { vertical: false }),
11780
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.XAxis, { dataKey: "label", ...axis }),
11781
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.YAxis, { width: 44, ...axis }),
11452
11782
  tooltip,
11453
11783
  legend,
11454
- series.map((key) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11784
+ series.map((key) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11455
11785
  import_recharts.Line,
11456
11786
  {
11457
11787
  type: "monotone",
@@ -11467,7 +11797,7 @@ function Drawing({
11467
11797
  ] }) });
11468
11798
  }
11469
11799
  const horizontal = kind === "bar";
11470
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartFrame, { config, height: HEIGHT, children: (width) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
11800
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ChartFrame, { config, height: HEIGHT, children: (width) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
11471
11801
  import_recharts.BarChart,
11472
11802
  {
11473
11803
  width,
@@ -11476,17 +11806,17 @@ function Drawing({
11476
11806
  layout: horizontal ? "vertical" : "horizontal",
11477
11807
  margin: { top: 6, right: 6, bottom: 0, left: 0 },
11478
11808
  children: [
11479
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_recharts.CartesianGrid, { vertical: horizontal, horizontal: !horizontal }),
11480
- horizontal ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
11481
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_recharts.XAxis, { type: "number", ...axis }),
11482
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_recharts.YAxis, { type: "category", dataKey: "label", width: 88, ...axis })
11483
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
11484
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_recharts.XAxis, { dataKey: "label", ...axis }),
11485
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_recharts.YAxis, { width: 44, ...axis })
11809
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.CartesianGrid, { vertical: horizontal, horizontal: !horizontal }),
11810
+ horizontal ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
11811
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.XAxis, { type: "number", ...axis }),
11812
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.YAxis, { type: "category", dataKey: "label", width: 88, ...axis })
11813
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
11814
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.XAxis, { dataKey: "label", ...axis }),
11815
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.YAxis, { width: 44, ...axis })
11486
11816
  ] }),
11487
11817
  tooltip,
11488
11818
  legend,
11489
- series.map((key, index) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11819
+ series.map((key, index) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11490
11820
  import_recharts.Bar,
11491
11821
  {
11492
11822
  dataKey: key,
@@ -11494,7 +11824,7 @@ function Drawing({
11494
11824
  isAnimationActive: false,
11495
11825
  fill: `var(--color-${key})`,
11496
11826
  ...click ? { onClick: click, className: "cursor-pointer" } : {},
11497
- children: series.length === 1 ? points.map((point) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_recharts.Cell, { fill: String(config[point.label]?.color ?? SERIES_COLORS[index]) }, point.label)) : null
11827
+ children: series.length === 1 ? points.map((point) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.Cell, { fill: String(config[point.label]?.color ?? SERIES_COLORS[index]) }, point.label)) : null
11498
11828
  },
11499
11829
  key
11500
11830
  ))
@@ -11504,24 +11834,25 @@ function Drawing({
11504
11834
  }
11505
11835
 
11506
11836
  // src/DashboardCanvas.tsx
11507
- var import_react84 = require("react");
11508
- var import_react85 = require("@ai-matrx/records/react");
11509
- var import_design_system42 = require("@ai-matrx/design-system");
11510
- var import_jsx_runtime45 = require("react/jsx-runtime");
11837
+ var import_react86 = require("react");
11838
+ var import_react87 = require("@ai-matrx/records/react");
11839
+ var import_design_system43 = require("@ai-matrx/design-system");
11840
+ var import_jsx_runtime46 = require("react/jsx-runtime");
11511
11841
  function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11512
- const client = (0, import_react85.useRecordsClient)();
11842
+ const client = (0, import_react87.useRecordsClient)();
11513
11843
  const host = useRecordsUi();
11514
- const table = (0, import_react85.useTable)(tableId);
11844
+ const table = (0, import_react87.useTable)(tableId);
11515
11845
  const rights = useTableRights(table.data);
11516
- const fields = (0, import_react85.useFields)(tableId);
11517
- const [boards, setBoards] = (0, import_react84.useState)(null);
11518
- const [error, setError] = (0, import_react84.useState)(null);
11519
- const [activeId, setActiveId] = (0, import_react84.useState)(activeDashboardId ?? null);
11520
- const [run, setRun] = (0, import_react84.useState)(null);
11521
- const [running, setRunning] = (0, import_react84.useState)(false);
11522
- const [question, setQuestion] = (0, import_react84.useState)("");
11523
- const [asking, setAsking] = (0, import_react84.useState)(false);
11524
- const load = (0, import_react84.useCallback)(async () => {
11846
+ const fields = (0, import_react87.useFields)(tableId);
11847
+ const [boards, setBoards] = (0, import_react86.useState)(null);
11848
+ const [error, setError] = (0, import_react86.useState)(null);
11849
+ const [activeId, setActiveId] = (0, import_react86.useState)(activeDashboardId ?? null);
11850
+ const [run, setRun] = (0, import_react86.useState)(null);
11851
+ const [running, setRunning] = (0, import_react86.useState)(false);
11852
+ const [question, setQuestion] = (0, import_react86.useState)("");
11853
+ const [asking, setAsking] = (0, import_react86.useState)(false);
11854
+ const [scheduling, setScheduling] = (0, import_react86.useState)(false);
11855
+ const load = (0, import_react86.useCallback)(async () => {
11525
11856
  const answered = await client.dashboards({ table_id: tableId });
11526
11857
  if (!answered.ok) {
11527
11858
  setError(answered.error);
@@ -11530,17 +11861,17 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11530
11861
  setError(null);
11531
11862
  setBoards(answered.data.map(dashboardFromSummary));
11532
11863
  }, [client, tableId]);
11533
- (0, import_react84.useEffect)(() => {
11864
+ (0, import_react86.useEffect)(() => {
11534
11865
  void load();
11535
11866
  }, [load]);
11536
- (0, import_react84.useEffect)(() => {
11867
+ (0, import_react86.useEffect)(() => {
11537
11868
  if (!boards || boards.length === 0) return;
11538
11869
  const chosen = boards.find((d) => d.id === (activeDashboardId ?? activeId)) ?? boards[0];
11539
11870
  if (chosen.id !== activeId) setActiveId(chosen.id);
11540
11871
  }, [boards, activeDashboardId]);
11541
- const board = (0, import_react84.useMemo)(() => boards?.find((d) => d.id === activeId) ?? null, [boards, activeId]);
11872
+ const board = (0, import_react86.useMemo)(() => boards?.find((d) => d.id === activeId) ?? null, [boards, activeId]);
11542
11873
  const filterKey = JSON.stringify(filter ?? {});
11543
- (0, import_react84.useEffect)(() => {
11874
+ (0, import_react86.useEffect)(() => {
11544
11875
  if (!activeId) {
11545
11876
  setRun(null);
11546
11877
  return;
@@ -11558,7 +11889,7 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11558
11889
  cancelled = true;
11559
11890
  };
11560
11891
  }, [client, activeId, filterKey]);
11561
- const declare2 = (0, import_react84.useCallback)(
11892
+ const declare2 = (0, import_react86.useCallback)(
11562
11893
  async (next, blocks) => {
11563
11894
  const written = await client.dashboardDeclare(
11564
11895
  dashboardDeclareArgs({ ...next, blocks }, tableId)
@@ -11604,7 +11935,7 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11604
11935
  ]
11605
11936
  );
11606
11937
  }
11607
- const refresh = (0, import_react84.useCallback)(async () => {
11938
+ const refresh = (0, import_react86.useCallback)(async () => {
11608
11939
  if (!activeId) return;
11609
11940
  setRunning(true);
11610
11941
  const again = await client.dashboardRun({
@@ -11645,20 +11976,20 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11645
11976
  }
11646
11977
  }
11647
11978
  if (error) {
11648
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11979
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
11649
11980
  RefusalNotice,
11650
11981
  {
11651
11982
  error,
11652
11983
  className,
11653
- actions: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_design_system42.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
11984
+ actions: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_design_system43.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
11654
11985
  }
11655
11986
  );
11656
11987
  }
11657
- if (boards === null) return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_design_system42.Skeleton, { className: (0, import_design_system42.cn)("h-64 w-full", className) });
11658
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: (0, import_design_system42.cn)("flex min-h-0 flex-col gap-2", className), children: [
11659
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Dashboards", children: [
11660
- boards.map((d) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11661
- import_design_system42.Button,
11988
+ if (boards === null) return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_design_system43.Skeleton, { className: (0, import_design_system43.cn)("h-64 w-full", className) });
11989
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: (0, import_design_system43.cn)("flex min-h-0 flex-col gap-2", className), children: [
11990
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Dashboards", children: [
11991
+ boards.map((d) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
11992
+ import_design_system43.Button,
11662
11993
  {
11663
11994
  size: "sm",
11664
11995
  variant: d.id === activeId ? "secondary" : "ghost",
@@ -11668,10 +11999,10 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11668
11999
  },
11669
12000
  d.id
11670
12001
  )),
11671
- rights.admin ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_design_system42.Button, { size: "sm", variant: "ghost", onClick: () => void create(), children: "New dashboard" }) : null,
11672
- board ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "ml-auto flex items-center gap-1", children: [
11673
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11674
- import_design_system42.Button,
12002
+ rights.admin ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_design_system43.Button, { size: "sm", variant: "ghost", onClick: () => void create(), children: "New dashboard" }) : null,
12003
+ board ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "ml-auto flex items-center gap-1", children: [
12004
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
12005
+ import_design_system43.Button,
11675
12006
  {
11676
12007
  size: "sm",
11677
12008
  variant: "ghost",
@@ -11680,13 +12011,31 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11680
12011
  children: running ? "Asking" : "Refresh"
11681
12012
  }
11682
12013
  ),
11683
- rights.admin ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_design_system42.Button, { size: "sm", variant: "ghost", onClick: () => void remove(board), children: "Delete" }) : null
12014
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
12015
+ import_design_system43.Button,
12016
+ {
12017
+ size: "sm",
12018
+ variant: scheduling ? "secondary" : "ghost",
12019
+ onClick: () => setScheduling((v) => !v),
12020
+ children: scheduling ? "Done" : "Send on a schedule"
12021
+ }
12022
+ ),
12023
+ rights.admin ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_design_system43.Button, { size: "sm", variant: "ghost", onClick: () => void remove(board), children: "Delete" }) : null
11684
12024
  ] }) : null
11685
12025
  ] }),
11686
- board ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex flex-col gap-1", children: [
11687
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex items-center gap-1", children: [
11688
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11689
- import_design_system42.BasicInput,
12026
+ board && scheduling ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
12027
+ DigestScheduler,
12028
+ {
12029
+ tableId,
12030
+ subjectName: board.name,
12031
+ ...filter ? { filters: filter } : {},
12032
+ onClose: () => setScheduling(false)
12033
+ }
12034
+ ) : null,
12035
+ board ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex flex-col gap-1", children: [
12036
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-1", children: [
12037
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
12038
+ import_design_system43.BasicInput,
11690
12039
  {
11691
12040
  value: question,
11692
12041
  "aria-label": "Ask for a change to this dashboard",
@@ -11699,15 +12048,15 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11699
12048
  className: "h-8 min-w-0 flex-1 text-xs"
11700
12049
  }
11701
12050
  ),
11702
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_design_system42.Button, { size: "sm", disabled: !host.onReask || asking || question.trim() === "", onClick: () => void reask(), children: asking ? "Asking" : "Ask" })
12051
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_design_system43.Button, { size: "sm", disabled: !host.onReask || asking || question.trim() === "", onClick: () => void reask(), children: asking ? "Asking" : "Ask" })
11703
12052
  ] }),
11704
- !host.onReask ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: "text-xs text-muted-foreground", children: NO_REASK_REASON }) : null
12053
+ !host.onReask ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "text-xs text-muted-foreground", children: NO_REASK_REASON }) : null
11705
12054
  ] }) : null,
11706
- !board ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: "text-xs text-muted-foreground", children: rights.admin ? "No dashboard looks at this table yet. \u201CNew dashboard\u201D makes one, or ask an agent for the one you want and it writes the whole thing." : rights.why("structure") }) : run === null ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_design_system42.Skeleton, { className: "h-64 w-full" }) : run.blocks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: "text-xs text-muted-foreground", children: "This dashboard has no blocks yet. Each one is a single question the store answers \u2014 grouped, bucketed and measured inside the read door." }) : /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
11707
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-3", children: run.blocks.map((block, index) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex min-w-0 flex-col gap-1", children: [
11708
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ChartBlock, { block, subject: tableId }),
11709
- rights.admin && board.blocks[index] ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex items-center gap-1 text-xs", children: [
11710
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
12055
+ !board ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "text-xs text-muted-foreground", children: rights.admin ? "No dashboard looks at this table yet. \u201CNew dashboard\u201D makes one, or ask an agent for the one you want and it writes the whole thing." : rights.why("structure") }) : run === null ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_design_system43.Skeleton, { className: "h-64 w-full" }) : run.blocks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "text-xs text-muted-foreground", children: "This dashboard has no blocks yet. Each one is a single question the store answers \u2014 grouped, bucketed and measured inside the read door." }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
12056
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-3", children: run.blocks.map((block, index) => /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex min-w-0 flex-col gap-1", children: [
12057
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ChartBlock, { block, subject: tableId }),
12058
+ rights.admin && board.blocks[index] ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-1 text-xs", children: [
12059
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
11711
12060
  "select",
11712
12061
  {
11713
12062
  "aria-label": `Shape of ${block.title}`,
@@ -11719,11 +12068,11 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11719
12068
  (b, i) => i === index ? { ...b, kind: e.target.value } : b
11720
12069
  )
11721
12070
  ),
11722
- children: CHART_KINDS.map((kind) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("option", { value: kind, children: CHART_KIND_LABEL[kind] }, kind))
12071
+ children: CHART_KINDS.map((kind) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: kind, children: CHART_KIND_LABEL[kind] }, kind))
11723
12072
  }
11724
12073
  ),
11725
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11726
- import_design_system42.Button,
12074
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
12075
+ import_design_system43.Button,
11727
12076
  {
11728
12077
  size: "sm",
11729
12078
  variant: "ghost",
@@ -11736,17 +12085,17 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11736
12085
  )
11737
12086
  ] }) : null
11738
12087
  ] }, `${block.title}-${index}`)) }),
11739
- !host.openRecords ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: "text-xs text-muted-foreground", children: NO_OPEN_RECORDS_REASON }) : null
12088
+ !host.openRecords ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "text-xs text-muted-foreground", children: NO_OPEN_RECORDS_REASON }) : null
11740
12089
  ] })
11741
12090
  ] });
11742
12091
  }
11743
12092
 
11744
12093
  // src/FormsPanel.tsx
11745
- var import_react86 = require("react");
11746
- var import_react87 = require("@ai-matrx/records/react");
12094
+ var import_react88 = require("react");
12095
+ var import_react89 = require("@ai-matrx/records/react");
11747
12096
  var import_records8 = require("@ai-matrx/records");
11748
- var import_design_system43 = require("@ai-matrx/design-system");
11749
- var import_jsx_runtime46 = require("react/jsx-runtime");
12097
+ var import_design_system44 = require("@ai-matrx/design-system");
12098
+ var import_jsx_runtime47 = require("react/jsx-runtime");
11750
12099
  var WHAT_A_FORM_IS = "A form asks for this table's own fields, and its answers land here as ordinary records stamped with the form they came through.";
11751
12100
  var NO_ADMIN = "This table has no forms. Making one needs the admin level on it, because a form decides what people with no account may add here.";
11752
12101
  function formSuggestion(tableName2) {
@@ -11754,16 +12103,16 @@ function formSuggestion(tableName2) {
11754
12103
  return `Make me a form that collects new ${subject} entries and tells me when somebody answers.`;
11755
12104
  }
11756
12105
  function FormsPanel({ tableId, className }) {
11757
- const client = (0, import_react87.useRecordsClient)();
12106
+ const client = (0, import_react89.useRecordsClient)();
11758
12107
  const host = useRecordsUi();
11759
- const table = (0, import_react87.useTable)(tableId);
12108
+ const table = (0, import_react89.useTable)(tableId);
11760
12109
  const rights = useTableRights(table.data);
11761
- const [forms, setForms] = (0, import_react86.useState)(null);
11762
- const [error, setError] = (0, import_react86.useState)(null);
11763
- const [busy, setBusy] = (0, import_react86.useState)(null);
11764
- const [copied, setCopied] = (0, import_react86.useState)(null);
11765
- const [building, setBuilding] = (0, import_react86.useState)(false);
11766
- const load = (0, import_react86.useCallback)(async () => {
12110
+ const [forms, setForms] = (0, import_react88.useState)(null);
12111
+ const [error, setError] = (0, import_react88.useState)(null);
12112
+ const [busy, setBusy] = (0, import_react88.useState)(null);
12113
+ const [copied, setCopied] = (0, import_react88.useState)(null);
12114
+ const [building, setBuilding] = (0, import_react88.useState)(false);
12115
+ const load = (0, import_react88.useCallback)(async () => {
11767
12116
  const answered = await client.forms({ table_id: tableId });
11768
12117
  if (!answered.ok) {
11769
12118
  setError(answered.error);
@@ -11773,10 +12122,10 @@ function FormsPanel({ tableId, className }) {
11773
12122
  setError(null);
11774
12123
  setForms(answered.data);
11775
12124
  }, [client, tableId]);
11776
- (0, import_react86.useEffect)(() => {
12125
+ (0, import_react88.useEffect)(() => {
11777
12126
  void load();
11778
12127
  }, [load]);
11779
- const toggle = (0, import_react86.useCallback)(
12128
+ const toggle = (0, import_react88.useCallback)(
11780
12129
  async (form) => {
11781
12130
  setBusy(form.form_id);
11782
12131
  const wanted = form.published_at === null || form.closed_at !== null;
@@ -11790,8 +12139,8 @@ function FormsPanel({ tableId, className }) {
11790
12139
  },
11791
12140
  [client, load]
11792
12141
  );
11793
- const [shown, setShown] = (0, import_react86.useState)(null);
11794
- const copy = (0, import_react86.useCallback)(async (url, formId) => {
12142
+ const [shown, setShown] = (0, import_react88.useState)(null);
12143
+ const copy = (0, import_react88.useCallback)(async (url, formId) => {
11795
12144
  try {
11796
12145
  await navigator.clipboard.writeText(url);
11797
12146
  setCopied(formId);
@@ -11801,17 +12150,17 @@ function FormsPanel({ tableId, className }) {
11801
12150
  setShown(url);
11802
12151
  }
11803
12152
  }, []);
11804
- if (forms === null) return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_design_system43.Skeleton, { className: (0, import_design_system43.cn)("h-32 w-full", className) });
12153
+ if (forms === null) return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.Skeleton, { className: (0, import_design_system44.cn)("h-32 w-full", className) });
11805
12154
  const origin = host.publicOrigin ?? (typeof window === "undefined" ? "" : window.location.origin);
11806
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("section", { className: (0, import_design_system43.cn)("flex flex-col gap-3", className), children: [
11807
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("header", { className: "flex items-center gap-2", children: [
11808
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("h3", { className: "text-sm font-medium", children: "Forms" }),
11809
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "text-xs text-muted-foreground", children: forms.length === 0 ? "none yet" : `${forms.length}` }),
11810
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "flex-1" }),
11811
- rights.structure && forms.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_design_system43.Button, { size: "sm", variant: building ? "secondary" : "ghost", onClick: () => setBuilding((b) => !b), children: building ? "Done building" : "Build a form" }) : null
12155
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("section", { className: (0, import_design_system44.cn)("flex flex-col gap-3", className), children: [
12156
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("header", { className: "flex items-center gap-2", children: [
12157
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("h3", { className: "text-sm font-medium", children: "Forms" }),
12158
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "text-xs text-muted-foreground", children: forms.length === 0 ? "none yet" : `${forms.length}` }),
12159
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "flex-1" }),
12160
+ rights.structure && forms.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.Button, { size: "sm", variant: building ? "secondary" : "ghost", onClick: () => setBuilding((b) => !b), children: building ? "Done building" : "Build a form" }) : null
11812
12161
  ] }),
11813
- error ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(RefusalNotice, { error }) : null,
11814
- building ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
12162
+ error ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(RefusalNotice, { error }) : null,
12163
+ building ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
11815
12164
  FormBuilder,
11816
12165
  {
11817
12166
  tableId,
@@ -11820,7 +12169,7 @@ function FormsPanel({ tableId, className }) {
11820
12169
  }
11821
12170
  }
11822
12171
  ) : null,
11823
- forms.length === 0 && !building ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
12172
+ forms.length === 0 && !building ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
11824
12173
  BuildOrAsk,
11825
12174
  {
11826
12175
  mayBuild: rights.structure,
@@ -11838,36 +12187,36 @@ function FormsPanel({ tableId, className }) {
11838
12187
  children: WHAT_A_FORM_IS
11839
12188
  }
11840
12189
  ) : null,
11841
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("ul", { className: "flex flex-col gap-2", children: forms.map((form) => {
12190
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("ul", { className: "flex flex-col gap-2", children: forms.map((form) => {
11842
12191
  const url = `${origin}${(0, import_records8.publicFormPath)(form.form_id)}`;
11843
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("li", { className: "rounded-md border p-2.5", children: [
11844
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-2", children: [
11845
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: form.title ?? form.slug }),
11846
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_design_system43.Badge, { variant: form.state === "open" ? "default" : "secondary", children: form.state })
12192
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("li", { className: "rounded-md border p-2.5", children: [
12193
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-2", children: [
12194
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: form.title ?? form.slug }),
12195
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.Badge, { variant: form.state === "open" ? "default" : "secondary", children: form.state })
11847
12196
  ] }),
11848
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "mt-0.5 text-xs text-muted-foreground", children: FORM_STATE_WORDS[form.state] }),
11849
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("p", { className: "mt-1.5 text-xs", children: [
11850
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "font-medium", children: form.in_table }),
12197
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "mt-0.5 text-xs text-muted-foreground", children: FORM_STATE_WORDS[form.state] }),
12198
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("p", { className: "mt-1.5 text-xs", children: [
12199
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "font-medium", children: form.in_table }),
11851
12200
  " in the table",
11852
- form.held > 0 ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
12201
+ form.held > 0 ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
11853
12202
  " \xB7 ",
11854
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "font-medium", children: form.held }),
12203
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "font-medium", children: form.held }),
11855
12204
  " waiting for someone"
11856
12205
  ] }) : null,
11857
- form.rejected > 0 ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
12206
+ form.rejected > 0 ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
11858
12207
  " \xB7 ",
11859
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "font-medium", children: form.rejected }),
12208
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "font-medium", children: form.rejected }),
11860
12209
  " turned away"
11861
12210
  ] }) : null,
11862
- form.submission_cap !== null ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "text-muted-foreground", children: [
12211
+ form.submission_cap !== null ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "text-muted-foreground", children: [
11863
12212
  " \xB7 stops at ",
11864
12213
  form.submission_cap
11865
12214
  ] }) : null
11866
12215
  ] }),
11867
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "mt-2 flex flex-wrap items-center gap-1.5", children: [
11868
- form.published_at ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_design_system43.Button, { size: "sm", variant: "outline", onClick: () => void copy(url, form.form_id), children: copied === form.form_id ? "Copied" : "Copy link" }) : null,
11869
- rights.structure ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
11870
- import_design_system43.Button,
12216
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "mt-2 flex flex-wrap items-center gap-1.5", children: [
12217
+ form.published_at ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.Button, { size: "sm", variant: "outline", onClick: () => void copy(url, form.form_id), children: copied === form.form_id ? "Copied" : "Copy link" }) : null,
12218
+ rights.structure ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
12219
+ import_design_system44.Button,
11871
12220
  {
11872
12221
  size: "sm",
11873
12222
  variant: "ghost",
@@ -11877,23 +12226,23 @@ function FormsPanel({ tableId, className }) {
11877
12226
  }
11878
12227
  ) : null
11879
12228
  ] }),
11880
- shown && shown === url ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("p", { className: "mt-1.5 break-all rounded border border-dashed px-2 py-1 text-xs", children: [
12229
+ shown && shown === url ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("p", { className: "mt-1.5 break-all rounded border border-dashed px-2 py-1 text-xs", children: [
11881
12230
  "This browser would not let the page copy for you, so here it is to copy by hand:",
11882
12231
  " ",
11883
12232
  url
11884
12233
  ] }) : null
11885
12234
  ] }, form.form_id);
11886
12235
  }) }),
11887
- !rights.known ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "text-xs text-muted-foreground", children: "Still asking what you may do with this table \u2014 nothing is offered until it answers." }) : null
12236
+ !rights.known ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "text-xs text-muted-foreground", children: "Still asking what you may do with this table \u2014 nothing is offered until it answers." }) : null
11888
12237
  ] });
11889
12238
  }
11890
12239
 
11891
12240
  // src/BookingBuilder.tsx
11892
- var import_react88 = require("react");
11893
- var import_react89 = require("@ai-matrx/records/react");
12241
+ var import_react90 = require("react");
12242
+ var import_react91 = require("@ai-matrx/records/react");
11894
12243
  var import_records9 = require("@ai-matrx/records");
11895
- var import_design_system44 = require("@ai-matrx/design-system");
11896
- var import_jsx_runtime47 = require("react/jsx-runtime");
12244
+ var import_design_system45 = require("@ai-matrx/design-system");
12245
+ var import_jsx_runtime48 = require("react/jsx-runtime");
11897
12246
  var STORE_ANSWERS_THESE = ["slot", "status", "booked_with"];
11898
12247
  var DAYS = [
11899
12248
  { weekday: 1, label: "Mon" },
@@ -11917,36 +12266,36 @@ function draftWindows(availability) {
11917
12266
  });
11918
12267
  }
11919
12268
  function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
11920
- const client = (0, import_react89.useRecordsClient)();
12269
+ const client = (0, import_react91.useRecordsClient)();
11921
12270
  const host = useRecordsUi();
11922
- const table = (0, import_react89.useTable)(tableId);
12271
+ const table = (0, import_react91.useTable)(tableId);
11923
12272
  const rights = useTableRights(table.data);
11924
- const fields = (0, import_react89.useFields)(tableId);
11925
- const [existing, setExisting] = (0, import_react88.useState)(null);
11926
- const [loaded, setLoaded] = (0, import_react88.useState)(false);
11927
- const [error, setError] = (0, import_react88.useState)(null);
11928
- const [saving, setSaving] = (0, import_react88.useState)(false);
11929
- const [publishing, setPublishing] = (0, import_react88.useState)(false);
11930
- const [copied, setCopied] = (0, import_react88.useState)(false);
11931
- const [title, setTitle] = (0, import_react88.useState)("");
11932
- const [minutes, setMinutes] = (0, import_react88.useState)(30);
11933
- const [buffer, setBuffer] = (0, import_react88.useState)(0);
11934
- const [lead, setLead] = (0, import_react88.useState)(120);
11935
- const [perDay, setPerDay] = (0, import_react88.useState)(8);
11936
- const [days, setDays] = (0, import_react88.useState)(30);
11937
- const [windows, setWindows] = (0, import_react88.useState)(() => draftWindows(null));
11938
- const [asked, setAsked] = (0, import_react88.useState)([]);
11939
- const [confirmation, setConfirmation] = (0, import_react88.useState)("");
11940
- const [offer, setOffer] = (0, import_react88.useState)(null);
11941
- const [formId, setFormId] = (0, import_react88.useState)(bookingId ?? null);
12273
+ const fields = (0, import_react91.useFields)(tableId);
12274
+ const [existing, setExisting] = (0, import_react90.useState)(null);
12275
+ const [loaded, setLoaded] = (0, import_react90.useState)(false);
12276
+ const [error, setError] = (0, import_react90.useState)(null);
12277
+ const [saving, setSaving] = (0, import_react90.useState)(false);
12278
+ const [publishing, setPublishing] = (0, import_react90.useState)(false);
12279
+ const [copied, setCopied] = (0, import_react90.useState)(false);
12280
+ const [title, setTitle] = (0, import_react90.useState)("");
12281
+ const [minutes, setMinutes] = (0, import_react90.useState)(30);
12282
+ const [buffer, setBuffer] = (0, import_react90.useState)(0);
12283
+ const [lead, setLead] = (0, import_react90.useState)(120);
12284
+ const [perDay, setPerDay] = (0, import_react90.useState)(8);
12285
+ const [days, setDays] = (0, import_react90.useState)(30);
12286
+ const [windows, setWindows] = (0, import_react90.useState)(() => draftWindows(null));
12287
+ const [asked, setAsked] = (0, import_react90.useState)([]);
12288
+ const [confirmation, setConfirmation] = (0, import_react90.useState)("");
12289
+ const [offer, setOffer] = (0, import_react90.useState)(null);
12290
+ const [formId, setFormId] = (0, import_react90.useState)(bookingId ?? null);
11942
12291
  const publicOrigin = host.publicOrigin ?? (typeof window === "undefined" ? "" : window.location.origin);
11943
- const askable = (0, import_react88.useMemo)(
12292
+ const askable = (0, import_react90.useMemo)(
11944
12293
  () => (fields.data ?? []).filter(
11945
12294
  (f) => !STORE_ANSWERS_THESE.includes(f.key)
11946
12295
  ),
11947
12296
  [fields.data]
11948
12297
  );
11949
- const load = (0, import_react88.useCallback)(async () => {
12298
+ const load = (0, import_react90.useCallback)(async () => {
11950
12299
  const answered = await client.bookings({ table_id: tableId });
11951
12300
  if (!answered.ok) {
11952
12301
  setError(answered.error);
@@ -11958,18 +12307,18 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
11958
12307
  setLoaded(true);
11959
12308
  if (mine) setFormId(mine.form_id);
11960
12309
  }, [client, tableId, bookingId]);
11961
- (0, import_react88.useEffect)(() => {
12310
+ (0, import_react90.useEffect)(() => {
11962
12311
  void load();
11963
12312
  }, [load]);
11964
- (0, import_react88.useEffect)(() => {
12313
+ (0, import_react90.useEffect)(() => {
11965
12314
  if (title !== "" || !table.data) return;
11966
12315
  setTitle(existing?.title ?? `Book a ${minutes}-minute ${table.data.name} appointment`);
11967
12316
  }, [table.data, existing]);
11968
- (0, import_react88.useEffect)(() => {
12317
+ (0, import_react90.useEffect)(() => {
11969
12318
  if (!existing) return;
11970
12319
  setMinutes(existing.slot_minutes);
11971
12320
  }, [existing]);
11972
- const availability = (0, import_react88.useCallback)(
12321
+ const availability = (0, import_react90.useCallback)(
11973
12322
  () => ({
11974
12323
  slot_minutes: minutes,
11975
12324
  buffer_minutes: buffer,
@@ -12018,68 +12367,68 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12018
12367
  await load();
12019
12368
  onSaved?.({ form_id: formId });
12020
12369
  }
12021
- if (!loaded || fields.loading) return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.Skeleton, { className: (0, import_design_system44.cn)("h-64 w-full", className) });
12370
+ if (!loaded || fields.loading) return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Skeleton, { className: (0, import_design_system45.cn)("h-64 w-full", className) });
12022
12371
  if (!rights.structure) {
12023
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: (0, import_design_system44.cn)("text-xs text-muted-foreground", className), children: rights.why("structure") ?? "Making a booking page needs the admin level on this table, because it lets people with no account take time in your calendar." });
12372
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: (0, import_design_system45.cn)("text-xs text-muted-foreground", className), children: rights.why("structure") ?? "Making a booking page needs the admin level on this table, because it lets people with no account take time in your calendar." });
12024
12373
  }
12025
12374
  const url = formId ? `${publicOrigin}${(0, import_records9.bookingPath)(formId)}` : null;
12026
12375
  const shown = offer ?? null;
12027
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("section", { className: (0, import_design_system44.cn)("flex flex-col gap-3", className), children: [
12028
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("header", { className: "flex items-center gap-2", children: [
12029
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("h3", { className: "text-sm font-medium", children: existing ? "Booking page" : "New booking page" }),
12030
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "flex-1" }),
12031
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.Button, { size: "sm", disabled: saving, onClick: () => void save(), children: saving ? "Saving\u2026" : "Save" }),
12032
- onClose ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.Button, { size: "sm", variant: "ghost", onClick: onClose, children: "Close" }) : null
12376
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("section", { className: (0, import_design_system45.cn)("flex flex-col gap-3", className), children: [
12377
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("header", { className: "flex items-center gap-2", children: [
12378
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("h3", { className: "text-sm font-medium", children: existing ? "Booking page" : "New booking page" }),
12379
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "flex-1" }),
12380
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Button, { size: "sm", disabled: saving, onClick: () => void save(), children: saving ? "Saving\u2026" : "Save" }),
12381
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Button, { size: "sm", variant: "ghost", onClick: onClose, children: "Close" }) : null
12033
12382
  ] }),
12034
- error ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(RefusalNotice, { error }) : null,
12035
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: "flex flex-col gap-1", children: [
12036
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.Label, { className: "text-xs font-medium", children: "What it is called" }),
12037
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.BasicInput, { value: title, onChange: (e) => setTitle(e.target.value) })
12383
+ error ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(RefusalNotice, { error }) : null,
12384
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "flex flex-col gap-1", children: [
12385
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Label, { className: "text-xs font-medium", children: "What it is called" }),
12386
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.BasicInput, { value: title, onChange: (e) => setTitle(e.target.value) })
12038
12387
  ] }),
12039
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
12040
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: "flex flex-col gap-1", children: [
12041
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.Label, { className: "text-xs font-medium", children: "How long one appointment is" }),
12042
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
12388
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
12389
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "flex flex-col gap-1", children: [
12390
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Label, { className: "text-xs font-medium", children: "How long one appointment is" }),
12391
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12043
12392
  "select",
12044
12393
  {
12045
12394
  className: "h-9 rounded border bg-background px-2 text-sm",
12046
12395
  value: minutes,
12047
12396
  onChange: (e) => setMinutes(Number(e.target.value)),
12048
- children: LENGTHS.map((n) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("option", { value: n, children: [
12397
+ children: LENGTHS.map((n) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("option", { value: n, children: [
12049
12398
  n,
12050
12399
  " minutes"
12051
12400
  ] }, n))
12052
12401
  }
12053
12402
  )
12054
12403
  ] }),
12055
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: "flex flex-col gap-1", children: [
12056
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.Label, { className: "text-xs font-medium", children: "Gap kept after each one" }),
12057
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
12404
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "flex flex-col gap-1", children: [
12405
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Label, { className: "text-xs font-medium", children: "Gap kept after each one" }),
12406
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12058
12407
  "select",
12059
12408
  {
12060
12409
  className: "h-9 rounded border bg-background px-2 text-sm",
12061
12410
  value: buffer,
12062
12411
  onChange: (e) => setBuffer(Number(e.target.value)),
12063
- children: [0, 5, 10, 15, 30].map((n) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: n, children: n === 0 ? "No gap \u2014 back to back" : `${n} minutes` }, n))
12412
+ children: [0, 5, 10, 15, 30].map((n) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("option", { value: n, children: n === 0 ? "No gap \u2014 back to back" : `${n} minutes` }, n))
12064
12413
  }
12065
12414
  )
12066
12415
  ] }),
12067
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: "flex flex-col gap-1", children: [
12068
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.Label, { className: "text-xs font-medium", children: "Earliest somebody may book" }),
12069
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
12416
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "flex flex-col gap-1", children: [
12417
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Label, { className: "text-xs font-medium", children: "Earliest somebody may book" }),
12418
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12070
12419
  "select",
12071
12420
  {
12072
12421
  className: "h-9 rounded border bg-background px-2 text-sm",
12073
12422
  value: lead,
12074
12423
  onChange: (e) => setLead(Number(e.target.value)),
12075
- children: [0, 60, 120, 240, 1440].map((n) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: n, children: n === 0 ? "Right away" : n === 1440 ? "A day from now" : `${n / 60} hour${n === 60 ? "" : "s"} from now` }, n))
12424
+ children: [0, 60, 120, 240, 1440].map((n) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("option", { value: n, children: n === 0 ? "Right away" : n === 1440 ? "A day from now" : `${n / 60} hour${n === 60 ? "" : "s"} from now` }, n))
12076
12425
  }
12077
12426
  )
12078
12427
  ] }),
12079
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: "flex flex-col gap-1", children: [
12080
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.Label, { className: "text-xs font-medium", children: "Most in one day" }),
12081
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
12082
- import_design_system44.BasicInput,
12428
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "flex flex-col gap-1", children: [
12429
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Label, { className: "text-xs font-medium", children: "Most in one day" }),
12430
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12431
+ import_design_system45.BasicInput,
12083
12432
  {
12084
12433
  type: "number",
12085
12434
  min: 1,
@@ -12088,15 +12437,15 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12088
12437
  }
12089
12438
  )
12090
12439
  ] }),
12091
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: "flex flex-col gap-1", children: [
12092
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.Label, { className: "text-xs font-medium", children: "How far ahead the page offers" }),
12093
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
12440
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "flex flex-col gap-1", children: [
12441
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Label, { className: "text-xs font-medium", children: "How far ahead the page offers" }),
12442
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12094
12443
  "select",
12095
12444
  {
12096
12445
  className: "h-9 rounded border bg-background px-2 text-sm",
12097
12446
  value: days,
12098
12447
  onChange: (e) => setDays(Number(e.target.value)),
12099
- children: [7, 14, 30, 60, 90].map((n) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("option", { value: n, children: [
12448
+ children: [7, 14, 30, 60, 90].map((n) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("option", { value: n, children: [
12100
12449
  n,
12101
12450
  " days"
12102
12451
  ] }, n))
@@ -12104,12 +12453,12 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12104
12453
  )
12105
12454
  ] })
12106
12455
  ] }),
12107
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
12108
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.Label, { className: "text-xs font-medium", children: "Hours you are free" }),
12109
- windows.map((w, i) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-2", children: [
12110
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: "flex w-20 items-center gap-1.5 text-xs", children: [
12111
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
12112
- import_design_system44.Checkbox,
12456
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
12457
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Label, { className: "text-xs font-medium", children: "Hours you are free" }),
12458
+ windows.map((w, i) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex items-center gap-2", children: [
12459
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "flex w-20 items-center gap-1.5 text-xs", children: [
12460
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12461
+ import_design_system45.Checkbox,
12113
12462
  {
12114
12463
  checked: w.on,
12115
12464
  onCheckedChange: (on) => setWindows((prev) => prev.map((x, j) => i === j ? { ...x, on: Boolean(on) } : x))
@@ -12117,9 +12466,9 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12117
12466
  ),
12118
12467
  DAYS[i]?.label
12119
12468
  ] }),
12120
- w.on ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
12121
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
12122
- import_design_system44.BasicInput,
12469
+ w.on ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_jsx_runtime48.Fragment, { children: [
12470
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12471
+ import_design_system45.BasicInput,
12123
12472
  {
12124
12473
  type: "time",
12125
12474
  className: "h-8 w-28",
@@ -12127,9 +12476,9 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12127
12476
  onChange: (e) => setWindows((prev) => prev.map((x, j) => i === j ? { ...x, from: e.target.value } : x))
12128
12477
  }
12129
12478
  ),
12130
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "text-xs text-muted-foreground", children: "to" }),
12131
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
12132
- import_design_system44.BasicInput,
12479
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "text-xs text-muted-foreground", children: "to" }),
12480
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12481
+ import_design_system45.BasicInput,
12133
12482
  {
12134
12483
  type: "time",
12135
12484
  className: "h-8 w-28",
@@ -12137,14 +12486,14 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12137
12486
  onChange: (e) => setWindows((prev) => prev.map((x, j) => i === j ? { ...x, to: e.target.value } : x))
12138
12487
  }
12139
12488
  )
12140
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "text-xs text-muted-foreground", children: "not taking bookings" })
12489
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "text-xs text-muted-foreground", children: "not taking bookings" })
12141
12490
  ] }, w.weekday))
12142
12491
  ] }),
12143
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
12144
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.Label, { className: "text-xs font-medium", children: "What to ask the person booking" }),
12145
- askable.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "text-xs text-muted-foreground", children: "This table has no fields yet, so there is nothing a booking page could ask for. Add a field first \u2014 every question is one of this table's own fields." }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "flex flex-wrap gap-x-4 gap-y-1.5", children: askable.map((f) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: "flex items-center gap-1.5 text-xs", children: [
12146
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
12147
- import_design_system44.Checkbox,
12492
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
12493
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Label, { className: "text-xs font-medium", children: "What to ask the person booking" }),
12494
+ askable.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "text-xs text-muted-foreground", children: "This table has no fields yet, so there is nothing a booking page could ask for. Add a field first \u2014 every question is one of this table's own fields." }) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "flex flex-wrap gap-x-4 gap-y-1.5", children: askable.map((f) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "flex items-center gap-1.5 text-xs", children: [
12495
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12496
+ import_design_system45.Checkbox,
12148
12497
  {
12149
12498
  checked: asked.includes(f.key),
12150
12499
  onCheckedChange: (on) => setAsked((prev) => on ? [...prev, f.key] : prev.filter((k) => k !== f.key))
@@ -12152,12 +12501,12 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12152
12501
  ),
12153
12502
  fieldName(f)
12154
12503
  ] }, f.key)) }),
12155
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "text-xs text-muted-foreground", children: "The time, whether it is booked or cancelled, and who it is with are filled in by the store \u2014 a booking page cannot ask a visitor for any of the three." })
12504
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "text-xs text-muted-foreground", children: "The time, whether it is booked or cancelled, and who it is with are filled in by the store \u2014 a booking page cannot ask a visitor for any of the three." })
12156
12505
  ] }),
12157
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: "flex flex-col gap-1", children: [
12158
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.Label, { className: "text-xs font-medium", children: "What they see after booking" }),
12159
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
12160
- import_design_system44.BasicTextarea,
12506
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "flex flex-col gap-1", children: [
12507
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Label, { className: "text-xs font-medium", children: "What they see after booking" }),
12508
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12509
+ import_design_system45.BasicTextarea,
12161
12510
  {
12162
12511
  rows: 2,
12163
12512
  value: confirmation,
@@ -12166,7 +12515,7 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12166
12515
  }
12167
12516
  )
12168
12517
  ] }),
12169
- shown ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("p", { className: "rounded-md border bg-muted/40 p-2.5 text-xs", children: [
12518
+ shown ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("p", { className: "rounded-md border bg-muted/40 p-2.5 text-xs", children: [
12170
12519
  "Saved. The page offers ",
12171
12520
  shown.slot_minutes,
12172
12521
  "-minute appointments in ",
@@ -12185,10 +12534,10 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12185
12534
  ).join(", "),
12186
12535
  "."
12187
12536
  ] }) : null,
12188
- url ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex flex-wrap items-center gap-2 rounded-md border p-2.5", children: [
12189
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "min-w-0 flex-1 break-all text-xs", children: url }),
12190
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
12191
- import_design_system44.Button,
12537
+ url ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex flex-wrap items-center gap-2 rounded-md border p-2.5", children: [
12538
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "min-w-0 flex-1 break-all text-xs", children: url }),
12539
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12540
+ import_design_system45.Button,
12192
12541
  {
12193
12542
  size: "sm",
12194
12543
  variant: "outline",
@@ -12201,8 +12550,8 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12201
12550
  children: copied ? "Copied" : "Copy link"
12202
12551
  }
12203
12552
  ),
12204
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
12205
- import_design_system44.Button,
12553
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12554
+ import_design_system45.Button,
12206
12555
  {
12207
12556
  size: "sm",
12208
12557
  disabled: publishing,
@@ -12210,17 +12559,17 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12210
12559
  children: publishing ? "\u2026" : existing?.published_at && !existing.closed_at ? "Unpublish" : "Publish"
12211
12560
  }
12212
12561
  ),
12213
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "w-full text-xs text-muted-foreground", children: existing?.published_at && !existing.closed_at ? "Open. Anyone with this link can book a time." : "Not open yet \u2014 the link does not take bookings until you publish it." })
12562
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "w-full text-xs text-muted-foreground", children: existing?.published_at && !existing.closed_at ? "Open. Anyone with this link can book a time." : "Not open yet \u2014 the link does not take bookings until you publish it." })
12214
12563
  ] }) : null
12215
12564
  ] });
12216
12565
  }
12217
12566
 
12218
12567
  // src/BookingSlots.tsx
12219
- var import_react90 = require("react");
12220
- var import_react91 = require("@ai-matrx/records/react");
12568
+ var import_react92 = require("react");
12569
+ var import_react93 = require("@ai-matrx/records/react");
12221
12570
  var import_records10 = require("@ai-matrx/records");
12222
- var import_design_system45 = require("@ai-matrx/design-system");
12223
- var import_jsx_runtime48 = require("react/jsx-runtime");
12571
+ var import_design_system46 = require("@ai-matrx/design-system");
12572
+ var import_jsx_runtime49 = require("react/jsx-runtime");
12224
12573
  var WHAT_A_BOOKING_PAGE_IS = "A booking page offers times you are free and writes each appointment into this table as an ordinary record.";
12225
12574
  function bookingSuggestion(tableName2) {
12226
12575
  const subject = tableName2?.trim() ? tableName2.trim() : "appointments";
@@ -12234,15 +12583,15 @@ var STATE_WORDS = {
12234
12583
  full: "Every time you offered is taken."
12235
12584
  };
12236
12585
  function BookingSlots({ tableId, className }) {
12237
- const client = (0, import_react91.useRecordsClient)();
12586
+ const client = (0, import_react93.useRecordsClient)();
12238
12587
  const host = useRecordsUi();
12239
- const [pages, setPages] = (0, import_react90.useState)(null);
12240
- const [error, setError] = (0, import_react90.useState)(null);
12241
- const [busy, setBusy] = (0, import_react90.useState)(null);
12242
- const [copied, setCopied] = (0, import_react90.useState)(null);
12243
- const [shown, setShown] = (0, import_react90.useState)(null);
12244
- const [building, setBuilding] = (0, import_react90.useState)(false);
12245
- const load = (0, import_react90.useCallback)(async () => {
12588
+ const [pages, setPages] = (0, import_react92.useState)(null);
12589
+ const [error, setError] = (0, import_react92.useState)(null);
12590
+ const [busy, setBusy] = (0, import_react92.useState)(null);
12591
+ const [copied, setCopied] = (0, import_react92.useState)(null);
12592
+ const [shown, setShown] = (0, import_react92.useState)(null);
12593
+ const [building, setBuilding] = (0, import_react92.useState)(false);
12594
+ const load = (0, import_react92.useCallback)(async () => {
12246
12595
  const answered = await client.bookings(tableId ? { table_id: tableId } : {});
12247
12596
  if (!answered.ok) {
12248
12597
  setError(answered.error);
@@ -12252,15 +12601,15 @@ function BookingSlots({ tableId, className }) {
12252
12601
  setError(null);
12253
12602
  setPages(answered.data);
12254
12603
  }, [client, tableId]);
12255
- (0, import_react90.useEffect)(() => {
12604
+ (0, import_react92.useEffect)(() => {
12256
12605
  void load();
12257
12606
  }, [load]);
12258
- const subjectIds = (0, import_react90.useMemo)(
12607
+ const subjectIds = (0, import_react92.useMemo)(
12259
12608
  () => Array.from(new Set((pages ?? []).map((p) => p.table_id))),
12260
12609
  [pages]
12261
12610
  );
12262
- const levels = (0, import_react91.useMyLevels)(subjectIds);
12263
- const toggle = (0, import_react90.useCallback)(
12611
+ const levels = (0, import_react93.useMyLevels)(subjectIds);
12612
+ const toggle = (0, import_react92.useCallback)(
12264
12613
  async (page) => {
12265
12614
  setBusy(page.form_id);
12266
12615
  const wanted = page.published_at === null || page.closed_at !== null;
@@ -12274,7 +12623,7 @@ function BookingSlots({ tableId, className }) {
12274
12623
  },
12275
12624
  [client, load]
12276
12625
  );
12277
- const copy = (0, import_react90.useCallback)(async (url, formId) => {
12626
+ const copy = (0, import_react92.useCallback)(async (url, formId) => {
12278
12627
  try {
12279
12628
  await navigator.clipboard.writeText(url);
12280
12629
  setCopied(formId);
@@ -12284,18 +12633,18 @@ function BookingSlots({ tableId, className }) {
12284
12633
  setShown(url);
12285
12634
  }
12286
12635
  }, []);
12287
- if (pages === null) return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Skeleton, { className: (0, import_design_system45.cn)("h-32 w-full", className) });
12636
+ if (pages === null) return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_design_system46.Skeleton, { className: (0, import_design_system46.cn)("h-32 w-full", className) });
12288
12637
  if (pages.length === 0 && !tableId && !error && !building) return null;
12289
12638
  const origin = host.publicOrigin ?? (typeof window === "undefined" ? "" : window.location.origin);
12290
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("section", { className: (0, import_design_system45.cn)("flex flex-col gap-3", className), "data-testid": "booking-slots", children: [
12291
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("header", { className: "flex items-center gap-2", children: [
12292
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("h3", { className: "text-sm font-medium", children: "Bookings" }),
12293
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "text-xs text-muted-foreground", children: pages.length === 0 ? "none yet" : `${pages.length}` }),
12294
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "flex-1" }),
12295
- tableId && pages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Button, { size: "sm", variant: building ? "secondary" : "ghost", onClick: () => setBuilding((b) => !b), children: building ? "Done building" : "Build a booking page" }) : null
12639
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("section", { className: (0, import_design_system46.cn)("flex flex-col gap-3", className), "data-testid": "booking-slots", children: [
12640
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("header", { className: "flex items-center gap-2", children: [
12641
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("h3", { className: "text-sm font-medium", children: "Bookings" }),
12642
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "text-xs text-muted-foreground", children: pages.length === 0 ? "none yet" : `${pages.length}` }),
12643
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "flex-1" }),
12644
+ tableId && pages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_design_system46.Button, { size: "sm", variant: building ? "secondary" : "ghost", onClick: () => setBuilding((b) => !b), children: building ? "Done building" : "Build a booking page" }) : null
12296
12645
  ] }),
12297
- error ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(RefusalNotice, { error }) : null,
12298
- building && tableId ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12646
+ error ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(RefusalNotice, { error }) : null,
12647
+ building && tableId ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
12299
12648
  BookingBuilder,
12300
12649
  {
12301
12650
  tableId,
@@ -12305,7 +12654,7 @@ function BookingSlots({ tableId, className }) {
12305
12654
  onClose: () => setBuilding(false)
12306
12655
  }
12307
12656
  ) : null,
12308
- pages.length === 0 && !building ? tableId ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12657
+ pages.length === 0 && !building ? tableId ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
12309
12658
  BuildOrAsk,
12310
12659
  {
12311
12660
  mayBuild: true,
@@ -12321,47 +12670,47 @@ function BookingSlots({ tableId, className }) {
12321
12670
  buildLabel: "Build the booking page",
12322
12671
  children: WHAT_A_BOOKING_PAGE_IS
12323
12672
  }
12324
- ) : /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("p", { className: "text-xs text-muted-foreground", children: [
12673
+ ) : /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("p", { className: "text-xs text-muted-foreground", children: [
12325
12674
  WHAT_A_BOOKING_PAGE_IS,
12326
12675
  " Open the table the appointments should land in to make one."
12327
12676
  ] }) : null,
12328
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("ul", { className: "flex flex-col gap-2", children: pages.map((page) => {
12677
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("ul", { className: "flex flex-col gap-2", children: pages.map((page) => {
12329
12678
  const url = `${origin}${(0, import_records10.bookingPath)(page.form_id)}`;
12330
12679
  const mayOpen = levels.data?.[page.table_id] === "admin";
12331
12680
  const open = page.published_at !== null && page.closed_at === null;
12332
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("li", { className: "rounded-md border p-2.5", "data-testid": "booking-page", children: [
12333
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex items-center gap-2", children: [
12334
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: page.title ?? page.slug }),
12335
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Badge, { variant: page.state === "open" ? "default" : "secondary", children: page.state })
12681
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("li", { className: "rounded-md border p-2.5", "data-testid": "booking-page", children: [
12682
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex items-center gap-2", children: [
12683
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: page.title ?? page.slug }),
12684
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_design_system46.Badge, { variant: page.state === "open" ? "default" : "secondary", children: page.state })
12336
12685
  ] }),
12337
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "mt-0.5 text-xs text-muted-foreground", children: STATE_WORDS[page.state] ?? page.state }),
12338
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("p", { className: "mt-1.5 text-xs", children: [
12339
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "font-medium", children: page.upcoming }),
12686
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "mt-0.5 text-xs text-muted-foreground", children: STATE_WORDS[page.state] ?? page.state }),
12687
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("p", { className: "mt-1.5 text-xs", children: [
12688
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "font-medium", children: page.upcoming }),
12340
12689
  " coming up",
12341
12690
  " \xB7 ",
12342
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "font-medium", children: page.booked }),
12691
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "font-medium", children: page.booked }),
12343
12692
  " booked in all",
12344
- page.held > 0 ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_jsx_runtime48.Fragment, { children: [
12693
+ page.held > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_jsx_runtime49.Fragment, { children: [
12345
12694
  " \xB7 ",
12346
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "font-medium", children: page.held }),
12695
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "font-medium", children: page.held }),
12347
12696
  " being held right now"
12348
12697
  ] }) : null,
12349
- page.cancelled > 0 ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_jsx_runtime48.Fragment, { children: [
12698
+ page.cancelled > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_jsx_runtime49.Fragment, { children: [
12350
12699
  " \xB7 ",
12351
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "font-medium", children: page.cancelled }),
12700
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "font-medium", children: page.cancelled }),
12352
12701
  " cancelled"
12353
12702
  ] }) : null,
12354
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "text-muted-foreground", children: [
12703
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "text-muted-foreground", children: [
12355
12704
  " \xB7 ",
12356
12705
  page.slot_minutes,
12357
12706
  " minutes each"
12358
12707
  ] })
12359
12708
  ] }),
12360
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "mt-1 text-xs text-muted-foreground", children: nextInWords(page) }),
12361
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "mt-2 flex flex-wrap items-center gap-1.5", children: [
12362
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Button, { size: "sm", variant: "outline", onClick: () => void copy(url, page.form_id), children: copied === page.form_id ? "Copied" : "Copy link" }),
12363
- mayOpen ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12364
- import_design_system45.Button,
12709
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "mt-1 text-xs text-muted-foreground", children: nextInWords(page) }),
12710
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "mt-2 flex flex-wrap items-center gap-1.5", children: [
12711
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_design_system46.Button, { size: "sm", variant: "outline", onClick: () => void copy(url, page.form_id), children: copied === page.form_id ? "Copied" : "Copy link" }),
12712
+ mayOpen ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
12713
+ import_design_system46.Button,
12365
12714
  {
12366
12715
  size: "sm",
12367
12716
  variant: "ghost",
@@ -12371,13 +12720,13 @@ function BookingSlots({ tableId, className }) {
12371
12720
  }
12372
12721
  ) : null
12373
12722
  ] }),
12374
- shown && shown === url ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("p", { className: "mt-1.5 break-all rounded border border-dashed px-2 py-1 text-xs", children: [
12723
+ shown && shown === url ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("p", { className: "mt-1.5 break-all rounded border border-dashed px-2 py-1 text-xs", children: [
12375
12724
  "This browser would not let the page copy for you, so here it is to copy by hand: ",
12376
12725
  url
12377
12726
  ] }) : null
12378
12727
  ] }, page.form_id);
12379
12728
  }) }),
12380
- pages.length > 0 && !levels.loading && levels.data && subjectIds.every((id) => levels.data?.[id] !== "admin") ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "text-xs text-muted-foreground", children: NO_ADMIN2 }) : null
12729
+ pages.length > 0 && !levels.loading && levels.data && subjectIds.every((id) => levels.data?.[id] !== "admin") ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-xs text-muted-foreground", children: NO_ADMIN2 }) : null
12381
12730
  ] });
12382
12731
  }
12383
12732
  function nextInWords(page) {
@@ -12409,16 +12758,16 @@ function nextInWords(page) {
12409
12758
  }
12410
12759
 
12411
12760
  // src/CaptureSheet.tsx
12412
- var import_react94 = require("react");
12413
- var import_react95 = require("@ai-matrx/records/react");
12414
- var import_design_system47 = require("@ai-matrx/design-system");
12761
+ var import_react96 = require("react");
12762
+ var import_react97 = require("@ai-matrx/records/react");
12763
+ var import_design_system48 = require("@ai-matrx/design-system");
12415
12764
 
12416
12765
  // src/CaptureRun.tsx
12417
- var import_react92 = require("react");
12766
+ var import_react94 = require("react");
12418
12767
  var import_records11 = require("@ai-matrx/records");
12419
- var import_react93 = require("@ai-matrx/records/react");
12420
- var import_design_system46 = require("@ai-matrx/design-system");
12421
- var import_jsx_runtime49 = require("react/jsx-runtime");
12768
+ var import_react95 = require("@ai-matrx/records/react");
12769
+ var import_design_system47 = require("@ai-matrx/design-system");
12770
+ var import_jsx_runtime50 = require("react/jsx-runtime");
12422
12771
  function controlFor(field) {
12423
12772
  if (!field) return "text";
12424
12773
  const label = `${field.key} ${field.label ?? ""}`.toLowerCase();
@@ -12455,21 +12804,21 @@ function whereWeAre(timeoutMs = 4e3) {
12455
12804
  });
12456
12805
  }
12457
12806
  function CaptureRun({ sheetId, face: given, className }) {
12458
- const client = (0, import_react93.useRecordsClient)();
12807
+ const client = (0, import_react95.useRecordsClient)();
12459
12808
  const host = useRecordsUi();
12460
- const [face, setFace] = (0, import_react92.useState)(given);
12461
- const [loadFailed, setLoadFailed] = (0, import_react92.useState)(null);
12462
- const [at, setAt] = (0, import_react92.useState)(0);
12463
- const [answers, setAnswers] = (0, import_react92.useState)({});
12464
- const [files, setFiles] = (0, import_react92.useState)({});
12465
- const [missing, setMissing] = (0, import_react92.useState)(null);
12466
- const [done, setDone] = (0, import_react92.useState)(null);
12467
- const [counts, setCounts] = (0, import_react92.useState)({ waiting: 0, sending: 0, refused: 0, landed: 0 });
12468
- const [items, setItems] = (0, import_react92.useState)([]);
12469
- const [lastSynced, setLastSynced] = (0, import_react92.useState)(null);
12470
- const [sending, setSending] = (0, import_react92.useState)(false);
12471
- const queueRef = (0, import_react92.useRef)(null);
12472
- (0, import_react92.useEffect)(() => {
12809
+ const [face, setFace] = (0, import_react94.useState)(given);
12810
+ const [loadFailed, setLoadFailed] = (0, import_react94.useState)(null);
12811
+ const [at, setAt] = (0, import_react94.useState)(0);
12812
+ const [answers, setAnswers] = (0, import_react94.useState)({});
12813
+ const [files, setFiles] = (0, import_react94.useState)({});
12814
+ const [missing, setMissing] = (0, import_react94.useState)(null);
12815
+ const [done, setDone] = (0, import_react94.useState)(null);
12816
+ const [counts, setCounts] = (0, import_react94.useState)({ waiting: 0, sending: 0, refused: 0, landed: 0 });
12817
+ const [items, setItems] = (0, import_react94.useState)([]);
12818
+ const [lastSynced, setLastSynced] = (0, import_react94.useState)(null);
12819
+ const [sending, setSending] = (0, import_react94.useState)(false);
12820
+ const queueRef = (0, import_react94.useRef)(null);
12821
+ (0, import_react94.useEffect)(() => {
12473
12822
  const q2 = (0, import_records11.openCaptureQueue)({
12474
12823
  onChange: (c, all) => {
12475
12824
  setCounts(c);
@@ -12507,7 +12856,7 @@ function CaptureRun({ sheetId, face: given, className }) {
12507
12856
  void q2.sync().then(() => void q2.lastSyncedAt().then(setLastSynced));
12508
12857
  return () => q2.dispose();
12509
12858
  }, [client, host]);
12510
- (0, import_react92.useEffect)(() => {
12859
+ (0, import_react94.useEffect)(() => {
12511
12860
  if (given !== void 0) return;
12512
12861
  let cancelled = false;
12513
12862
  void client.captureOpen({ sheet_id: sheetId }).then((res) => {
@@ -12519,7 +12868,7 @@ function CaptureRun({ sheetId, face: given, className }) {
12519
12868
  cancelled = true;
12520
12869
  };
12521
12870
  }, [client, given, sheetId]);
12522
- const questions = (0, import_react92.useMemo)(() => {
12871
+ const questions = (0, import_react94.useMemo)(() => {
12523
12872
  const asked = face?.presentation?.questions ?? [];
12524
12873
  if (asked.length > 0) return asked;
12525
12874
  return (face?.fields ?? []).map((f) => ({
@@ -12529,11 +12878,11 @@ function CaptureRun({ sheetId, face: given, className }) {
12529
12878
  required: f.required
12530
12879
  }));
12531
12880
  }, [face]);
12532
- const fieldOf = (0, import_react92.useCallback)(
12881
+ const fieldOf = (0, import_react94.useCallback)(
12533
12882
  (key) => (face?.fields ?? []).find((f) => f.key === key),
12534
12883
  [face]
12535
12884
  );
12536
- const sync = (0, import_react92.useCallback)(async () => {
12885
+ const sync = (0, import_react94.useCallback)(async () => {
12537
12886
  const q2 = queueRef.current;
12538
12887
  if (!q2) return;
12539
12888
  setSending(true);
@@ -12546,7 +12895,7 @@ function CaptureRun({ sheetId, face: given, className }) {
12546
12895
  setSending(false);
12547
12896
  }
12548
12897
  }, []);
12549
- const answered = (0, import_react92.useCallback)(
12898
+ const answered = (0, import_react94.useCallback)(
12550
12899
  (key) => {
12551
12900
  if (files[key]) return true;
12552
12901
  const v = answers[key];
@@ -12591,24 +12940,24 @@ function CaptureRun({ sheetId, face: given, className }) {
12591
12940
  if (online) await sync();
12592
12941
  }
12593
12942
  if (loadFailed) {
12594
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("section", { className: (0, import_design_system46.cn)("mx-auto w-full max-w-sm p-4", className), children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-sm text-destructive", "data-testid": "capture-refusal", children: loadFailed }) });
12943
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("section", { className: (0, import_design_system47.cn)("mx-auto w-full max-w-sm p-4", className), children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-sm text-destructive", "data-testid": "capture-refusal", children: loadFailed }) });
12595
12944
  }
12596
12945
  if (face === void 0) {
12597
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_design_system46.Skeleton, { className: (0, import_design_system46.cn)("mx-auto h-64 w-full max-w-sm", className) });
12946
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_design_system47.Skeleton, { className: (0, import_design_system47.cn)("mx-auto h-64 w-full max-w-sm", className) });
12598
12947
  }
12599
12948
  if (face === null) {
12600
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("section", { className: (0, import_design_system46.cn)("mx-auto w-full max-w-sm p-4", className), children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-sm", "data-testid": "capture-refusal", children: "This capture sheet is not here, or it is not yours to open. If somebody sent you this link, ask them to check it." }) });
12949
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("section", { className: (0, import_design_system47.cn)("mx-auto w-full max-w-sm p-4", className), children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-sm", "data-testid": "capture-refusal", children: "This capture sheet is not here, or it is not yours to open. If somebody sent you this link, ask them to check it." }) });
12601
12950
  }
12602
12951
  const waiting = counts.waiting + counts.sending;
12603
- const queueLine = /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex items-center gap-2 text-[11px] text-muted-foreground", "data-testid": "capture-queue-line", children: [
12604
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "tabular-nums", "data-testid": "capture-waiting", children: waiting === 0 ? "Nothing waiting" : `${waiting} waiting` }),
12605
- counts.refused > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "text-destructive tabular-nums", "data-testid": "capture-refused", children: [
12952
+ const queueLine = /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex items-center gap-2 text-[11px] text-muted-foreground", "data-testid": "capture-queue-line", children: [
12953
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "tabular-nums", "data-testid": "capture-waiting", children: waiting === 0 ? "Nothing waiting" : `${waiting} waiting` }),
12954
+ counts.refused > 0 ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "text-destructive tabular-nums", "data-testid": "capture-refused", children: [
12606
12955
  counts.refused,
12607
12956
  " to fix"
12608
12957
  ] }) : null,
12609
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "ml-auto", "data-testid": "capture-last-synced", children: lastSynced ? `Last synced ${new Date(lastSynced).toLocaleTimeString()}` : "Not synced yet" }),
12610
- waiting > 0 || counts.refused > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
12611
- import_design_system46.Button,
12958
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "ml-auto", "data-testid": "capture-last-synced", children: lastSynced ? `Last synced ${new Date(lastSynced).toLocaleTimeString()}` : "Not synced yet" }),
12959
+ waiting > 0 || counts.refused > 0 ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
12960
+ import_design_system47.Button,
12612
12961
  {
12613
12962
  size: "sm",
12614
12963
  variant: "ghost",
@@ -12620,11 +12969,11 @@ function CaptureRun({ sheetId, face: given, className }) {
12620
12969
  }
12621
12970
  ) : null
12622
12971
  ] });
12623
- const queuePanel = items.filter((i) => i.state !== "landed").length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("ul", { className: "flex flex-col gap-1 rounded border p-2", "data-testid": "capture-queue", children: items.filter((i) => i.state !== "landed").map((i) => /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("li", { className: "flex items-start gap-2 text-[11px]", children: [
12624
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "tabular-nums text-muted-foreground", children: new Date(i.captured_at).toLocaleTimeString() }),
12625
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: (0, import_design_system46.cn)("flex-1", i.state === "refused" && "text-destructive"), children: i.state === "refused" ? i.last_error ?? "This one was refused." : i.last_error ?? "Waiting for a signal." }),
12626
- i.state === "refused" ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
12627
- import_design_system46.Button,
12972
+ const queuePanel = items.filter((i) => i.state !== "landed").length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("ul", { className: "flex flex-col gap-1 rounded border p-2", "data-testid": "capture-queue", children: items.filter((i) => i.state !== "landed").map((i) => /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("li", { className: "flex items-start gap-2 text-[11px]", children: [
12973
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "tabular-nums text-muted-foreground", children: new Date(i.captured_at).toLocaleTimeString() }),
12974
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: (0, import_design_system47.cn)("flex-1", i.state === "refused" && "text-destructive"), children: i.state === "refused" ? i.last_error ?? "This one was refused." : i.last_error ?? "Waiting for a signal." }),
12975
+ i.state === "refused" ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
12976
+ import_design_system47.Button,
12628
12977
  {
12629
12978
  size: "sm",
12630
12979
  variant: "ghost",
@@ -12635,19 +12984,19 @@ function CaptureRun({ sheetId, face: given, className }) {
12635
12984
  ) : null
12636
12985
  ] }, i.client_key)) }) : null;
12637
12986
  if (!face.may_capture) {
12638
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("section", { className: (0, import_design_system46.cn)("mx-auto flex w-full max-w-sm flex-col gap-3 p-4", className), children: [
12639
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("h1", { className: "text-lg font-medium", children: face.title }),
12640
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-sm", "data-testid": "capture-refusal", children: face.message }),
12987
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("section", { className: (0, import_design_system47.cn)("mx-auto flex w-full max-w-sm flex-col gap-3 p-4", className), children: [
12988
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("h1", { className: "text-lg font-medium", children: face.title }),
12989
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-sm", "data-testid": "capture-refusal", children: face.message }),
12641
12990
  queueLine,
12642
12991
  queuePanel
12643
12992
  ] });
12644
12993
  }
12645
12994
  if (done) {
12646
12995
  const thanks = face.presentation?.thank_you ?? {};
12647
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("section", { className: (0, import_design_system46.cn)("mx-auto flex w-full max-w-sm flex-col gap-3 p-4", className), children: [
12648
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("h2", { className: "text-lg font-medium", "data-testid": "capture-thankyou", children: thanks.title ?? "Logged" }),
12649
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-sm text-muted-foreground", children: done.queued ? "There is no signal, so this one is on the phone and goes up the moment there is. Nothing is lost." : thanks.body ?? "Ready for the next one." }),
12650
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_design_system46.Button, { className: "h-12", onClick: () => setDone(null), "data-testid": "capture-next", children: "Next one" }),
12996
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("section", { className: (0, import_design_system47.cn)("mx-auto flex w-full max-w-sm flex-col gap-3 p-4", className), children: [
12997
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("h2", { className: "text-lg font-medium", "data-testid": "capture-thankyou", children: thanks.title ?? "Logged" }),
12998
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-sm text-muted-foreground", children: done.queued ? "There is no signal, so this one is on the phone and goes up the moment there is. Nothing is lost." : thanks.body ?? "Ready for the next one." }),
12999
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_design_system47.Button, { className: "h-12", onClick: () => setDone(null), "data-testid": "capture-next", children: "Next one" }),
12651
13000
  queueLine,
12652
13001
  queuePanel
12653
13002
  ] });
@@ -12656,14 +13005,14 @@ function CaptureRun({ sheetId, face: given, className }) {
12656
13005
  const field = fieldOf(q.field);
12657
13006
  const control = controlFor(field);
12658
13007
  const last = at >= questions.length - 1;
12659
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("section", { className: (0, import_design_system46.cn)("mx-auto flex w-full max-w-sm flex-col gap-3 p-4", className), children: [
12660
- /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex items-center gap-2 text-[11px] text-muted-foreground", children: [
12661
- /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "tabular-nums", "data-testid": "capture-progress", children: [
13008
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("section", { className: (0, import_design_system47.cn)("mx-auto flex w-full max-w-sm flex-col gap-3 p-4", className), children: [
13009
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex items-center gap-2 text-[11px] text-muted-foreground", children: [
13010
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "tabular-nums", "data-testid": "capture-progress", children: [
12662
13011
  at + 1,
12663
13012
  " of ",
12664
13013
  questions.length
12665
13014
  ] }),
12666
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "h-1 flex-1 overflow-hidden rounded bg-muted", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
13015
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "h-1 flex-1 overflow-hidden rounded bg-muted", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
12667
13016
  "div",
12668
13017
  {
12669
13018
  className: "h-full bg-primary transition-[width] duration-200",
@@ -12671,7 +13020,7 @@ function CaptureRun({ sheetId, face: given, className }) {
12671
13020
  }
12672
13021
  ) })
12673
13022
  ] }),
12674
- /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
13023
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
12675
13024
  "label",
12676
13025
  {
12677
13026
  className: "text-xl font-medium leading-snug",
@@ -12679,13 +13028,13 @@ function CaptureRun({ sheetId, face: given, className }) {
12679
13028
  "data-testid": "capture-ask",
12680
13029
  children: [
12681
13030
  q.ask ?? q.field,
12682
- q.required ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "text-muted-foreground", children: " *" }) : null
13031
+ q.required ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "text-muted-foreground", children: " *" }) : null
12683
13032
  ]
12684
13033
  }
12685
13034
  ),
12686
- q.help ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "-mt-1 text-sm text-muted-foreground", children: q.help }) : null,
12687
- control === "photo" || control === "voice" ? !host.upload ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "rounded border border-dashed px-2 py-2 text-xs text-muted-foreground", children: NO_UPLOAD_REASON }) : /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex flex-col gap-1", children: [
12688
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
13035
+ q.help ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "-mt-1 text-sm text-muted-foreground", children: q.help }) : null,
13036
+ control === "photo" || control === "voice" ? !host.upload ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "rounded border border-dashed px-2 py-2 text-xs text-muted-foreground", children: NO_UPLOAD_REASON }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex flex-col gap-1", children: [
13037
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
12689
13038
  "input",
12690
13039
  {
12691
13040
  id: `capture-${q.field}`,
@@ -12703,12 +13052,12 @@ function CaptureRun({ sheetId, face: given, className }) {
12703
13052
  }
12704
13053
  }
12705
13054
  ),
12706
- files[q.field] ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("p", { className: "text-[11px] text-muted-foreground", "data-testid": `capture-have-${q.field}`, children: [
13055
+ files[q.field] ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("p", { className: "text-[11px] text-muted-foreground", "data-testid": `capture-have-${q.field}`, children: [
12707
13056
  files[q.field].name,
12708
13057
  " is on the phone. It goes up with the capture."
12709
13058
  ] }) : null
12710
- ] }) : control === "number" ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
12711
- import_design_system46.Input,
13059
+ ] }) : control === "number" ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
13060
+ import_design_system47.Input,
12712
13061
  {
12713
13062
  id: `capture-${q.field}`,
12714
13063
  "data-testid": `capture-input-${q.field}`,
@@ -12723,8 +13072,8 @@ function CaptureRun({ sheetId, face: given, className }) {
12723
13072
  setMissing(null);
12724
13073
  }
12725
13074
  }
12726
- ) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
12727
- import_design_system46.Textarea,
13075
+ ) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
13076
+ import_design_system47.Textarea,
12728
13077
  {
12729
13078
  id: `capture-${q.field}`,
12730
13079
  "data-testid": `capture-input-${q.field}`,
@@ -12738,10 +13087,10 @@ function CaptureRun({ sheetId, face: given, className }) {
12738
13087
  }
12739
13088
  }
12740
13089
  ),
12741
- missing ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-sm text-destructive", "data-testid": "capture-missing", children: missing }) : null,
12742
- /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex items-center gap-2", children: [
12743
- at > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
12744
- import_design_system46.Button,
13090
+ missing ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-sm text-destructive", "data-testid": "capture-missing", children: missing }) : null,
13091
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex items-center gap-2", children: [
13092
+ at > 0 ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
13093
+ import_design_system47.Button,
12745
13094
  {
12746
13095
  variant: "ghost",
12747
13096
  className: "h-12 px-3",
@@ -12750,16 +13099,16 @@ function CaptureRun({ sheetId, face: given, className }) {
12750
13099
  children: "Back"
12751
13100
  }
12752
13101
  ) : null,
12753
- last ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
12754
- import_design_system46.Button,
13102
+ last ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
13103
+ import_design_system47.Button,
12755
13104
  {
12756
13105
  className: "h-12 flex-1 text-base",
12757
13106
  onClick: () => void capture(),
12758
13107
  "data-testid": "capture-submit",
12759
13108
  children: "Capture"
12760
13109
  }
12761
- ) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
12762
- import_design_system46.Button,
13110
+ ) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
13111
+ import_design_system47.Button,
12763
13112
  {
12764
13113
  className: "h-12 flex-1 text-base",
12765
13114
  onClick: () => setAt(at + 1),
@@ -12774,7 +13123,7 @@ function CaptureRun({ sheetId, face: given, className }) {
12774
13123
  }
12775
13124
 
12776
13125
  // src/CaptureSheet.tsx
12777
- var import_jsx_runtime50 = require("react/jsx-runtime");
13126
+ var import_jsx_runtime51 = require("react/jsx-runtime");
12778
13127
  var CAPTURE_MODES = ["reading", "photo", "voice"];
12779
13128
  var IN_MEMORY_QUEUE_REASON = "No capture queue is bound, so anything that cannot be sent right now is held in this page's memory and is lost if the page closes. Bind `captureQueue` on <RecordsUiProvider> with your host's own durable store (IndexedDB in a browser) and a queued capture survives the tab, the reload and the flight. It is said here rather than discovered later.";
12780
13129
  function mintClientKey() {
@@ -12794,8 +13143,8 @@ function CaptureSheet({
12794
13143
  attachmentField,
12795
13144
  className
12796
13145
  }) {
12797
- if (sheetId) return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(CaptureRun, { sheetId, className });
12798
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
13146
+ if (sheetId) return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(CaptureRun, { sheetId, className });
13147
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
12799
13148
  AdHocCaptureSheet,
12800
13149
  {
12801
13150
  tableId,
@@ -12813,21 +13162,21 @@ function AdHocCaptureSheet({
12813
13162
  attachmentField,
12814
13163
  className
12815
13164
  }) {
12816
- const client = (0, import_react95.useRecordsClient)();
13165
+ const client = (0, import_react97.useRecordsClient)();
12817
13166
  const host = useRecordsUi();
12818
- const table = (0, import_react95.useTable)(tableId);
12819
- const fields = (0, import_react95.useFields)(tableId);
12820
- const [mode, setMode] = (0, import_react94.useState)("reading");
12821
- const [reading, setReading] = (0, import_react94.useState)("");
12822
- const [note, setNote] = (0, import_react94.useState)("");
12823
- const [fileId, setFileId] = (0, import_react94.useState)(null);
12824
- const [pending, setPending] = (0, import_react94.useState)(null);
12825
- const [saved, setSaved] = (0, import_react94.useState)([]);
12826
- const [error, setError] = (0, import_react94.useState)(null);
12827
- const [uploadError, setUploadError] = (0, import_react94.useState)(null);
12828
- const [flushing, setFlushing] = (0, import_react94.useState)(false);
12829
- const queue = (0, import_react94.useRef)([]);
12830
- const keep = (0, import_react94.useCallback)(
13167
+ const table = (0, import_react97.useTable)(tableId);
13168
+ const fields = (0, import_react97.useFields)(tableId);
13169
+ const [mode, setMode] = (0, import_react96.useState)("reading");
13170
+ const [reading, setReading] = (0, import_react96.useState)("");
13171
+ const [note, setNote] = (0, import_react96.useState)("");
13172
+ const [fileId, setFileId] = (0, import_react96.useState)(null);
13173
+ const [pending, setPending] = (0, import_react96.useState)(null);
13174
+ const [saved, setSaved] = (0, import_react96.useState)([]);
13175
+ const [error, setError] = (0, import_react96.useState)(null);
13176
+ const [uploadError, setUploadError] = (0, import_react96.useState)(null);
13177
+ const [flushing, setFlushing] = (0, import_react96.useState)(false);
13178
+ const queue = (0, import_react96.useRef)([]);
13179
+ const keep = (0, import_react96.useCallback)(
12831
13180
  async (next) => {
12832
13181
  queue.current = next;
12833
13182
  setPending(next);
@@ -12835,7 +13184,7 @@ function AdHocCaptureSheet({
12835
13184
  },
12836
13185
  [host]
12837
13186
  );
12838
- (0, import_react94.useEffect)(() => {
13187
+ (0, import_react96.useEffect)(() => {
12839
13188
  let cancelled = false;
12840
13189
  void (async () => {
12841
13190
  const held = host.captureQueue ? await host.captureQueue.load() : [];
@@ -12847,7 +13196,7 @@ function AdHocCaptureSheet({
12847
13196
  cancelled = true;
12848
13197
  };
12849
13198
  }, [host]);
12850
- const resolved = (0, import_react94.useCallback)(() => {
13199
+ const resolved = (0, import_react96.useCallback)(() => {
12851
13200
  const all = fields.data ?? [];
12852
13201
  return {
12853
13202
  reading: readingField ?? all.find((f) => f.type === "range")?.key ?? null,
@@ -12855,7 +13204,7 @@ function AdHocCaptureSheet({
12855
13204
  attachment: attachmentField ?? all.find((f) => f.format === "file" || f.format === "image")?.key ?? null
12856
13205
  };
12857
13206
  }, [attachmentField, fields.data, noteField, readingField, table.data]);
12858
- const flush = (0, import_react94.useCallback)(async () => {
13207
+ const flush = (0, import_react96.useCallback)(async () => {
12859
13208
  if (flushing || queue.current.length === 0) return;
12860
13209
  setFlushing(true);
12861
13210
  const left = [];
@@ -12907,14 +13256,14 @@ function AdHocCaptureSheet({
12907
13256
  await keep([...queue.current, item]);
12908
13257
  await flush();
12909
13258
  }
12910
- if (table.error) return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(RefusalNotice, { error: table.error, className });
12911
- if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(RefusalNotice, { error: fields.error, className });
12912
- if (fields.loading || pending === null) return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_design_system47.Skeleton, { className: (0, import_design_system47.cn)("h-64 w-full", className) });
13259
+ if (table.error) return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(RefusalNotice, { error: table.error, className });
13260
+ if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(RefusalNotice, { error: fields.error, className });
13261
+ if (fields.loading || pending === null) return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_design_system48.Skeleton, { className: (0, import_design_system48.cn)("h-64 w-full", className) });
12913
13262
  const keys = resolved();
12914
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("section", { className: (0, import_design_system47.cn)("mx-auto flex w-full max-w-sm flex-col gap-2", className), children: [
12915
- /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("header", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
12916
- CAPTURE_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
12917
- import_design_system47.Button,
13263
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("section", { className: (0, import_design_system48.cn)("mx-auto flex w-full max-w-sm flex-col gap-2", className), children: [
13264
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("header", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
13265
+ CAPTURE_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
13266
+ import_design_system48.Button,
12918
13267
  {
12919
13268
  size: "sm",
12920
13269
  variant: m === mode ? "default" : "ghost",
@@ -12924,11 +13273,11 @@ function AdHocCaptureSheet({
12924
13273
  },
12925
13274
  m
12926
13275
  )),
12927
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "ml-auto tabular-nums", children: pending.length > 0 ? `${pending.length} waiting` : `${saved.length} saved` })
13276
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "ml-auto tabular-nums", children: pending.length > 0 ? `${pending.length} waiting` : `${saved.length} saved` })
12928
13277
  ] }),
12929
- error ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(RefusalNotice, { error }) : null,
12930
- mode === "reading" ? keys.reading ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
12931
- import_design_system47.Input,
13278
+ error ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(RefusalNotice, { error }) : null,
13279
+ mode === "reading" ? keys.reading ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
13280
+ import_design_system48.Input,
12932
13281
  {
12933
13282
  "aria-label": "Reading",
12934
13283
  inputMode: "decimal",
@@ -12937,22 +13286,22 @@ function AdHocCaptureSheet({
12937
13286
  value: reading,
12938
13287
  onChange: (e) => setReading(e.target.value)
12939
13288
  }
12940
- ) : /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: [
13289
+ ) : /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: [
12941
13290
  table.data?.name ?? "This table",
12942
13291
  " has no number Field for a reading to go in, so this mode would have nowhere to put what you typed. Add one, or name it with ",
12943
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("code", { children: "readingField" }),
13292
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("code", { children: "readingField" }),
12944
13293
  "."
12945
13294
  ] }) : null,
12946
- mode !== "reading" ? !host.upload ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: NO_UPLOAD_REASON }) : !keys.attachment ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: [
13295
+ mode !== "reading" ? !host.upload ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: NO_UPLOAD_REASON }) : !keys.attachment ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: [
12947
13296
  table.data?.name ?? "This table",
12948
13297
  " has no Field a file id can go in, so a ",
12949
13298
  mode,
12950
13299
  " capture would upload the bytes and then have nowhere to record them. Add one, or name it with",
12951
13300
  " ",
12952
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("code", { children: "attachmentField" }),
13301
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("code", { children: "attachmentField" }),
12953
13302
  "."
12954
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_jsx_runtime50.Fragment, { children: [
12955
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
13303
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_jsx_runtime51.Fragment, { children: [
13304
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
12956
13305
  "input",
12957
13306
  {
12958
13307
  "aria-label": mode === "photo" ? "Take a photo" : "Record a voice note",
@@ -12971,11 +13320,11 @@ function AdHocCaptureSheet({
12971
13320
  }
12972
13321
  }
12973
13322
  ),
12974
- fileId ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Attached." }) : null,
12975
- uploadError ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-xs text-destructive", children: uploadError }) : null
13323
+ fileId ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Attached." }) : null,
13324
+ uploadError ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("p", { className: "text-xs text-destructive", children: uploadError }) : null
12976
13325
  ] }) : null,
12977
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
12978
- import_design_system47.Textarea,
13326
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
13327
+ import_design_system48.Textarea,
12979
13328
  {
12980
13329
  "aria-label": "Note",
12981
13330
  rows: 2,
@@ -12985,12 +13334,12 @@ function AdHocCaptureSheet({
12985
13334
  onChange: (e) => setNote(e.target.value)
12986
13335
  }
12987
13336
  ),
12988
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_design_system47.Button, { className: "h-12", onClick: () => void capture(), children: "Capture" }),
12989
- pending.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex flex-col gap-1 rounded border p-2", children: [
12990
- /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
12991
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "font-medium", children: "Waiting to send" }),
12992
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
12993
- import_design_system47.Button,
13337
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_design_system48.Button, { className: "h-12", onClick: () => void capture(), children: "Capture" }),
13338
+ pending.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "flex flex-col gap-1 rounded border p-2", children: [
13339
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
13340
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "font-medium", children: "Waiting to send" }),
13341
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
13342
+ import_design_system48.Button,
12994
13343
  {
12995
13344
  size: "sm",
12996
13345
  variant: "ghost",
@@ -13001,7 +13350,7 @@ function AdHocCaptureSheet({
13001
13350
  }
13002
13351
  )
13003
13352
  ] }),
13004
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("ul", { className: "flex flex-col gap-0.5", children: pending.map((item) => /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("li", { className: "text-[11px] text-muted-foreground", children: [
13353
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("ul", { className: "flex flex-col gap-0.5", children: pending.map((item) => /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("li", { className: "text-[11px] text-muted-foreground", children: [
13005
13354
  new Date(item.capturedAt).toLocaleTimeString(),
13006
13355
  " \xB7 ",
13007
13356
  item.attempts,
@@ -13009,23 +13358,23 @@ function AdHocCaptureSheet({
13009
13358
  item.lastRefusal ? ` \xB7 ${item.lastRefusal}` : ""
13010
13359
  ] }, item.clientKey)) })
13011
13360
  ] }) : null,
13012
- !host.captureQueue ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "rounded border border-dashed px-2 py-1 text-[11px] text-muted-foreground", children: IN_MEMORY_QUEUE_REASON }) : null
13361
+ !host.captureQueue ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("p", { className: "rounded border border-dashed px-2 py-1 text-[11px] text-muted-foreground", children: IN_MEMORY_QUEUE_REASON }) : null
13013
13362
  ] });
13014
13363
  }
13015
13364
 
13016
13365
  // src/PortalShell.tsx
13017
- var import_react96 = require("react");
13018
- var import_react97 = require("@ai-matrx/records/react");
13019
- var import_design_system48 = require("@ai-matrx/design-system");
13020
- var import_jsx_runtime51 = require("react/jsx-runtime");
13366
+ var import_react98 = require("react");
13367
+ var import_react99 = require("@ai-matrx/records/react");
13368
+ var import_design_system49 = require("@ai-matrx/design-system");
13369
+ var import_jsx_runtime52 = require("react/jsx-runtime");
13021
13370
  function PortalShell({ tableId, form, resourceType = "record", className }) {
13022
- const client = (0, import_react97.useRecordsClient)();
13023
- const [card, setCard] = (0, import_react96.useState)(null);
13024
- const [reach, setReach] = (0, import_react96.useState)(null);
13025
- const [error, setError] = (0, import_react96.useState)(null);
13026
- const [open, setOpen] = (0, import_react96.useState)(null);
13027
- const [sending, setSending] = (0, import_react96.useState)(false);
13028
- const load = (0, import_react96.useCallback)(async () => {
13371
+ const client = (0, import_react99.useRecordsClient)();
13372
+ const [card, setCard] = (0, import_react98.useState)(null);
13373
+ const [reach, setReach] = (0, import_react98.useState)(null);
13374
+ const [error, setError] = (0, import_react98.useState)(null);
13375
+ const [open, setOpen] = (0, import_react98.useState)(null);
13376
+ const [sending, setSending] = (0, import_react98.useState)(false);
13377
+ const load = (0, import_react98.useCallback)(async () => {
13029
13378
  const who = await client.externalPrincipalCard();
13030
13379
  if (!who.ok) {
13031
13380
  setError(who.error);
@@ -13040,23 +13389,23 @@ function PortalShell({ tableId, form, resourceType = "record", className }) {
13040
13389
  }
13041
13390
  setReach(reached.data.map((row) => row.resource_id));
13042
13391
  }, [client, resourceType]);
13043
- (0, import_react96.useEffect)(() => {
13392
+ (0, import_react98.useEffect)(() => {
13044
13393
  void load();
13045
13394
  }, [load]);
13046
13395
  if (error) {
13047
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(RefusalNotice, { error, className });
13396
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(RefusalNotice, { error, className });
13048
13397
  }
13049
- if (!card || reach === null) return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_design_system48.Skeleton, { className: (0, import_design_system48.cn)("h-64 w-full", className) });
13398
+ if (!card || reach === null) return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_design_system49.Skeleton, { className: (0, import_design_system49.cn)("h-64 w-full", className) });
13050
13399
  if (!card.external) {
13051
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("p", { className: (0, import_design_system48.cn)("rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", className), children: card.explanation || "You are a member of an organization here, so this portal is not yours \u2014 a portal is the scoped view an OUTSIDER gets. You have the full application instead." });
13400
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("p", { className: (0, import_design_system49.cn)("rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", className), children: card.explanation || "You are a member of an organization here, so this portal is not yours \u2014 a portal is the scoped view an OUTSIDER gets. You have the full application instead." });
13052
13401
  }
13053
13402
  if (sending && form) {
13054
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("section", { className: (0, import_design_system48.cn)("flex min-h-0 flex-col gap-2", className), children: [
13055
- /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("header", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
13056
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "font-medium text-foreground", children: form.name }),
13057
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_design_system48.Button, { size: "sm", variant: "ghost", className: "ml-auto h-6 px-2 text-[11px]", onClick: () => setSending(false), children: "Back" })
13403
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("section", { className: (0, import_design_system49.cn)("flex min-h-0 flex-col gap-2", className), children: [
13404
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("header", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
13405
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "font-medium text-foreground", children: form.name }),
13406
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_design_system49.Button, { size: "sm", variant: "ghost", className: "ml-auto h-6 px-2 text-[11px]", onClick: () => setSending(false), children: "Back" })
13058
13407
  ] }),
13059
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
13408
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
13060
13409
  FormRunner,
13061
13410
  {
13062
13411
  form,
@@ -13069,38 +13418,38 @@ function PortalShell({ tableId, form, resourceType = "record", className }) {
13069
13418
  ] });
13070
13419
  }
13071
13420
  if (open) {
13072
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("section", { className: (0, import_design_system48.cn)("flex min-h-0 flex-col gap-2", className), children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Peek, { tableId, recordId: open, onClose: () => setOpen(null) }) });
13421
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("section", { className: (0, import_design_system49.cn)("flex min-h-0 flex-col gap-2", className), children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(Peek, { tableId, recordId: open, onClose: () => setOpen(null) }) });
13073
13422
  }
13074
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("section", { className: (0, import_design_system48.cn)("flex min-h-0 flex-col gap-2", className), children: [
13075
- /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("header", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
13076
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "font-medium text-foreground", children: "Shared with you" }),
13077
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "tabular-nums", children: reach.length }),
13078
- form ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_design_system48.Button, { size: "sm", className: "ml-auto h-7 px-2 text-[11px]", onClick: () => setSending(true), children: form.submitLabel ?? form.name }) : null
13423
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("section", { className: (0, import_design_system49.cn)("flex min-h-0 flex-col gap-2", className), children: [
13424
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("header", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
13425
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "font-medium text-foreground", children: "Shared with you" }),
13426
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "tabular-nums", children: reach.length }),
13427
+ form ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_design_system49.Button, { size: "sm", className: "ml-auto h-7 px-2 text-[11px]", onClick: () => setSending(true), children: form.submitLabel ?? form.name }) : null
13079
13428
  ] }),
13080
13429
  reach.length === 0 ? (
13081
13430
  // EMPTY, AND IT SAYS WHICH EMPTY. "Nobody has shared anything with you"
13082
13431
  // and "the store would not tell us" are different sentences, and a
13083
13432
  // person acts on them differently.
13084
- /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: [
13433
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: [
13085
13434
  "Nothing has been shared with you yet. ",
13086
13435
  card.explanation,
13087
13436
  " When somebody shares a record with you it appears here \u2014 this list is exactly what Visibility gave you, one record at a time, never an organization's list."
13088
13437
  ] })
13089
- ) : /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("ul", { className: "flex min-h-0 flex-col gap-1 overflow-y-auto", children: reach.map((id) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
13438
+ ) : /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("ul", { className: "flex min-h-0 flex-col gap-1 overflow-y-auto", children: reach.map((id) => /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
13090
13439
  "button",
13091
13440
  {
13092
13441
  type: "button",
13093
13442
  className: "w-full truncate rounded border px-2 py-1.5 text-left text-xs hover:bg-muted",
13094
13443
  onClick: () => setOpen(id),
13095
- children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(PortalRow, { tableId, recordId: id })
13444
+ children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(PortalRow, { tableId, recordId: id })
13096
13445
  }
13097
13446
  ) }, id)) })
13098
13447
  ] });
13099
13448
  }
13100
13449
  function PortalRow({ tableId, recordId }) {
13101
- const client = (0, import_react97.useRecordsClient)();
13102
- const [title, setTitle] = (0, import_react96.useState)(null);
13103
- (0, import_react96.useEffect)(() => {
13450
+ const client = (0, import_react99.useRecordsClient)();
13451
+ const [title, setTitle] = (0, import_react98.useState)(null);
13452
+ (0, import_react98.useEffect)(() => {
13104
13453
  let cancelled = false;
13105
13454
  void client.recordRead({ record_id: recordId }).then((answered) => {
13106
13455
  if (cancelled) return;
@@ -13116,22 +13465,22 @@ function PortalRow({ tableId, recordId }) {
13116
13465
  cancelled = true;
13117
13466
  };
13118
13467
  }, [client, recordId, tableId]);
13119
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { children: title ?? "\u2026" });
13468
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { children: title ?? "\u2026" });
13120
13469
  }
13121
13470
 
13122
13471
  // src/PublicViewPage.tsx
13123
- var import_react98 = require("react");
13124
- var import_react99 = require("@ai-matrx/records/react");
13125
- var import_design_system49 = require("@ai-matrx/design-system");
13126
- var import_jsx_runtime52 = require("react/jsx-runtime");
13472
+ var import_react100 = require("react");
13473
+ var import_react101 = require("@ai-matrx/records/react");
13474
+ var import_design_system50 = require("@ai-matrx/design-system");
13475
+ var import_jsx_runtime53 = require("react/jsx-runtime");
13127
13476
  function PublicViewPage({ slug, className }) {
13128
- const client = (0, import_react99.useRecordsClient)();
13129
- const [binding, setBinding] = (0, import_react98.useState)(null);
13130
- const [rows, setRows] = (0, import_react98.useState)(null);
13131
- const [fields, setFields] = (0, import_react98.useState)(null);
13132
- const [error, setError] = (0, import_react98.useState)(null);
13133
- const [gap, setGap] = (0, import_react98.useState)(null);
13134
- const load = (0, import_react98.useCallback)(async () => {
13477
+ const client = (0, import_react101.useRecordsClient)();
13478
+ const [binding, setBinding] = (0, import_react100.useState)(null);
13479
+ const [rows, setRows] = (0, import_react100.useState)(null);
13480
+ const [fields, setFields] = (0, import_react100.useState)(null);
13481
+ const [error, setError] = (0, import_react100.useState)(null);
13482
+ const [gap, setGap] = (0, import_react100.useState)(null);
13483
+ const load = (0, import_react100.useCallback)(async () => {
13135
13484
  const notice = await client.worldPublishGapNotice();
13136
13485
  if (notice.ok) setGap(notice.data);
13137
13486
  const resolved = await client.resolvePublishBinding({ slug });
@@ -13164,48 +13513,48 @@ function PublicViewPage({ slug, className }) {
13164
13513
  }
13165
13514
  setRows([{ id: found.resource_id, document: read.data.document, level: "viewer", hidden: read.data.hidden }]);
13166
13515
  }, [client, slug]);
13167
- (0, import_react98.useEffect)(() => {
13516
+ (0, import_react100.useEffect)(() => {
13168
13517
  void load();
13169
13518
  }, [load]);
13170
- if (error) return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(RefusalNotice, { error, className });
13171
- if (binding === null) return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_design_system49.Skeleton, { className: (0, import_design_system49.cn)("h-64 w-full", className) });
13519
+ if (error) return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(RefusalNotice, { error, className });
13520
+ if (binding === null) return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_design_system50.Skeleton, { className: (0, import_design_system50.cn)("h-64 w-full", className) });
13172
13521
  if (binding === "none") {
13173
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("main", { className: (0, import_design_system49.cn)("mx-auto max-w-2xl py-16 text-center", className), children: [
13174
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("h1", { className: "text-lg font-medium", children: "Nothing here" }),
13175
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("p", { className: "mt-1 text-sm text-muted-foreground", children: "There is no public page at this address." }),
13176
- gap ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("p", { className: "mt-6 text-xs text-muted-foreground", children: gap }) : null
13522
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("main", { className: (0, import_design_system50.cn)("mx-auto max-w-2xl py-16 text-center", className), children: [
13523
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("h1", { className: "text-lg font-medium", children: "Nothing here" }),
13524
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("p", { className: "mt-1 text-sm text-muted-foreground", children: "There is no public page at this address." }),
13525
+ gap ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("p", { className: "mt-6 text-xs text-muted-foreground", children: gap }) : null
13177
13526
  ] });
13178
13527
  }
13179
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("main", { className: (0, import_design_system49.cn)("mx-auto flex max-w-2xl flex-col gap-3 py-8", className), children: [
13180
- /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("header", { className: "flex items-baseline gap-2 text-xs text-muted-foreground", children: [
13181
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "font-medium text-foreground", children: binding.namespace ?? "Published" }),
13182
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { children: binding.render_mode === "list" ? `${rows?.length ?? 0} items` : "Shared publicly" })
13528
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("main", { className: (0, import_design_system50.cn)("mx-auto flex max-w-2xl flex-col gap-3 py-8", className), children: [
13529
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("header", { className: "flex items-baseline gap-2 text-xs text-muted-foreground", children: [
13530
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "font-medium text-foreground", children: binding.namespace ?? "Published" }),
13531
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { children: binding.render_mode === "list" ? `${rows?.length ?? 0} items` : "Shared publicly" })
13183
13532
  ] }),
13184
- rows === null ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_design_system49.Skeleton, { className: "h-40 w-full" }) : rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("p", { className: "text-sm text-muted-foreground", children: "This page has nothing on it yet." }) : /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("ol", { className: "flex flex-col gap-2", children: rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("li", { className: "rounded border p-3", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(PublicRow, { row, fields }) }, row.id)) }),
13185
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("footer", { className: "mt-4 border-t pt-3 text-xs text-muted-foreground", children: binding.notice || gap || "Nothing was scanned before this was listed." })
13533
+ rows === null ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_design_system50.Skeleton, { className: "h-40 w-full" }) : rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("p", { className: "text-sm text-muted-foreground", children: "This page has nothing on it yet." }) : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("ol", { className: "flex flex-col gap-2", children: rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("li", { className: "rounded border p-3", children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(PublicRow, { row, fields }) }, row.id)) }),
13534
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("footer", { className: "mt-4 border-t pt-3 text-xs text-muted-foreground", children: binding.notice || gap || "Nothing was scanned before this was listed." })
13186
13535
  ] });
13187
13536
  }
13188
13537
  function PublicRow({ row, fields }) {
13189
13538
  const document2 = row.document ?? {};
13190
13539
  if (!fields) {
13191
13540
  const first = Object.entries(document2).filter(([key]) => !key.startsWith("_"));
13192
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 text-sm", children: first.map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "contents", children: [
13193
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("dt", { className: "text-xs text-muted-foreground", children: key }),
13194
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("dd", { className: "text-sm", children: String(value ?? "") })
13541
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 text-sm", children: first.map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "contents", children: [
13542
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("dt", { className: "text-xs text-muted-foreground", children: key }),
13543
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("dd", { className: "text-sm", children: String(value ?? "") })
13195
13544
  ] }, key)) });
13196
13545
  }
13197
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1", children: fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "contents", children: [
13198
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("dt", { className: "text-xs text-muted-foreground", children: field.label }),
13199
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("dd", { className: "text-sm", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(RecordValue, { field, value: document2[field.key], document: row.document }) })
13546
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1", children: fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "contents", children: [
13547
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("dt", { className: "text-xs text-muted-foreground", children: field.label }),
13548
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("dd", { className: "text-sm", children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(RecordValue, { field, value: document2[field.key], document: row.document }) })
13200
13549
  ] }, field.key)) });
13201
13550
  }
13202
13551
 
13203
13552
  // src/EmbedFrame.tsx
13204
- var import_react100 = require("react");
13205
- var import_react101 = require("@ai-matrx/records/react");
13206
- var import_design_system50 = require("@ai-matrx/design-system");
13207
- var import_react102 = require("@ai-matrx/records/react");
13208
- var import_jsx_runtime53 = require("react/jsx-runtime");
13553
+ var import_react102 = require("react");
13554
+ var import_react103 = require("@ai-matrx/records/react");
13555
+ var import_design_system51 = require("@ai-matrx/design-system");
13556
+ var import_react104 = require("@ai-matrx/records/react");
13557
+ var import_jsx_runtime54 = require("react/jsx-runtime");
13209
13558
  function EmbedFrame({
13210
13559
  tableId,
13211
13560
  formId,
@@ -13214,18 +13563,18 @@ function EmbedFrame({
13214
13563
  embedUrl,
13215
13564
  className
13216
13565
  }) {
13217
- const client = (0, import_react101.useRecordsClient)();
13566
+ const client = (0, import_react103.useRecordsClient)();
13218
13567
  const host = useRecordsUi();
13219
- const table = (0, import_react102.useTable)(tableId);
13568
+ const table = (0, import_react104.useTable)(tableId);
13220
13569
  const rights = useTableRights(table.data);
13221
- const [origins, setOrigins] = (0, import_react100.useState)("");
13222
- const [secret, setSecret] = (0, import_react100.useState)(null);
13223
- const [tokenId, setTokenId] = (0, import_react100.useState)(null);
13224
- const [error, setError] = (0, import_react100.useState)(null);
13225
- const [busy, setBusy] = (0, import_react100.useState)(false);
13570
+ const [origins, setOrigins] = (0, import_react102.useState)("");
13571
+ const [secret, setSecret] = (0, import_react102.useState)(null);
13572
+ const [tokenId, setTokenId] = (0, import_react102.useState)(null);
13573
+ const [error, setError] = (0, import_react102.useState)(null);
13574
+ const [busy, setBusy] = (0, import_react102.useState)(false);
13226
13575
  const mode = formId ? "write" : "read";
13227
13576
  const parsed = origins.split(/[\s,]+/).map((o) => o.trim()).filter((o) => o.length > 0);
13228
- const issue = (0, import_react100.useCallback)(async () => {
13577
+ const issue = (0, import_react102.useCallback)(async () => {
13229
13578
  setBusy(true);
13230
13579
  setError(null);
13231
13580
  const minted = await client.anonTokenIssue({
@@ -13244,7 +13593,7 @@ function EmbedFrame({
13244
13593
  setTokenId(minted.data.token_id);
13245
13594
  host.notify?.success("Embed token issued. Copy it now \u2014 it is never shown again.");
13246
13595
  }, [client, formId, host, mode, parsed, recordId, savedViewId]);
13247
- const revoke = (0, import_react100.useCallback)(async () => {
13596
+ const revoke = (0, import_react102.useCallback)(async () => {
13248
13597
  if (!tokenId) return;
13249
13598
  setBusy(true);
13250
13599
  const done = await client.anonTokenRevoke({ token_id: tokenId });
@@ -13256,25 +13605,25 @@ function EmbedFrame({
13256
13605
  setSecret(null);
13257
13606
  setTokenId(null);
13258
13607
  }, [client, tokenId]);
13259
- if (table.error) return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(RefusalNotice, { error: table.error, className });
13260
- if (table.loading) return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_design_system50.Skeleton, { className: (0, import_design_system50.cn)("h-48 w-full", className) });
13608
+ if (table.error) return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(RefusalNotice, { error: table.error, className });
13609
+ if (table.loading) return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_design_system51.Skeleton, { className: (0, import_design_system51.cn)("h-48 w-full", className) });
13261
13610
  if (!rights.admin) {
13262
- return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("p", { className: (0, import_design_system50.cn)("rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", className), children: [
13611
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("p", { className: (0, import_design_system51.cn)("rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", className), children: [
13263
13612
  rights.why("structure"),
13264
13613
  " Issuing an embed opens a way in from somebody else's website, so the store asks for the admin level on this table before it will mint one."
13265
13614
  ] });
13266
13615
  }
13267
13616
  const snippet = secret ? `<iframe src="${embedUrl}#t=${secret}" style="width:100%;height:640px;border:0" loading="lazy"></iframe>` : null;
13268
- return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("section", { className: (0, import_design_system50.cn)("flex min-h-0 flex-col gap-2", className), children: [
13269
- /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("header", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
13270
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "font-medium text-foreground", children: "Embed" }),
13271
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { children: mode === "write" ? "a form people can send" : "a read-only view" })
13617
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("section", { className: (0, import_design_system51.cn)("flex min-h-0 flex-col gap-2", className), children: [
13618
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("header", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
13619
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "font-medium text-foreground", children: "Embed" }),
13620
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { children: mode === "write" ? "a form people can send" : "a read-only view" })
13272
13621
  ] }),
13273
- error ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(RefusalNotice, { error }) : null,
13274
- /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("label", { className: "flex flex-col gap-1 text-xs", children: [
13275
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "text-muted-foreground", children: "Sites this embed works on" }),
13276
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
13277
- import_design_system50.Input,
13622
+ error ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(RefusalNotice, { error }) : null,
13623
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("label", { className: "flex flex-col gap-1 text-xs", children: [
13624
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "text-muted-foreground", children: "Sites this embed works on" }),
13625
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
13626
+ import_design_system51.Input,
13278
13627
  {
13279
13628
  "aria-label": "Allowed origins",
13280
13629
  className: "h-8 text-xs",
@@ -13283,18 +13632,18 @@ function EmbedFrame({
13283
13632
  onChange: (e) => setOrigins(e.target.value)
13284
13633
  }
13285
13634
  ),
13286
- /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("span", { className: "text-[11px] text-muted-foreground", children: [
13635
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "text-[11px] text-muted-foreground", children: [
13287
13636
  `Name every site, scheme and host and port. An empty list is refused rather than quietly meaning "anywhere": a token that works from any page on the internet includes an attacker's. The match is exact, so `,
13288
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("code", { children: "example.com.evil.test" }),
13637
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("code", { children: "example.com.evil.test" }),
13289
13638
  " will not pass."
13290
13639
  ] })
13291
13640
  ] }),
13292
- !secret ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_design_system50.Button, { size: "sm", className: "self-start", disabled: busy || parsed.length === 0, onClick: () => void issue(), children: busy ? "Issuing\u2026" : "Issue embed" }) : /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_jsx_runtime53.Fragment, { children: [
13293
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("p", { className: "rounded border px-2 py-1 text-xs text-muted-foreground", children: "Copy this now. Only its digest is stored, so nobody \u2014 including us \u2014 can show it to you again; if it is lost, issue a new one and replace the old." }),
13294
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_design_system50.Textarea, { "aria-label": "Embed snippet", readOnly: true, rows: 3, className: "font-mono text-[11px]", value: snippet ?? "" }),
13295
- /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "flex gap-2", children: [
13296
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
13297
- import_design_system50.Button,
13641
+ !secret ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_design_system51.Button, { size: "sm", className: "self-start", disabled: busy || parsed.length === 0, onClick: () => void issue(), children: busy ? "Issuing\u2026" : "Issue embed" }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_jsx_runtime54.Fragment, { children: [
13642
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("p", { className: "rounded border px-2 py-1 text-xs text-muted-foreground", children: "Copy this now. Only its digest is stored, so nobody \u2014 including us \u2014 can show it to you again; if it is lost, issue a new one and replace the old." }),
13643
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_design_system51.Textarea, { "aria-label": "Embed snippet", readOnly: true, rows: 3, className: "font-mono text-[11px]", value: snippet ?? "" }),
13644
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "flex gap-2", children: [
13645
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
13646
+ import_design_system51.Button,
13298
13647
  {
13299
13648
  size: "sm",
13300
13649
  variant: "outline",
@@ -13302,19 +13651,19 @@ function EmbedFrame({
13302
13651
  children: "Copy"
13303
13652
  }
13304
13653
  ),
13305
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_design_system50.Button, { size: "sm", variant: "ghost", disabled: busy, onClick: () => void revoke(), children: "Revoke" })
13654
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_design_system51.Button, { size: "sm", variant: "ghost", disabled: busy, onClick: () => void revoke(), children: "Revoke" })
13306
13655
  ] })
13307
13656
  ] })
13308
13657
  ] });
13309
13658
  }
13310
13659
  function useEmbedHandshake(args) {
13311
- const client = (0, import_react101.useRecordsClient)();
13312
- const [binding, setBinding] = (0, import_react100.useState)(null);
13313
- const [error, setError] = (0, import_react100.useState)(null);
13314
- const [loading, setLoading] = (0, import_react100.useState)(true);
13660
+ const client = (0, import_react103.useRecordsClient)();
13661
+ const [binding, setBinding] = (0, import_react102.useState)(null);
13662
+ const [error, setError] = (0, import_react102.useState)(null);
13663
+ const [loading, setLoading] = (0, import_react102.useState)(true);
13315
13664
  const origin = args.origin ?? (typeof location === "undefined" ? "" : location.origin);
13316
13665
  const { secret, requiredMode } = args;
13317
- (0, import_react100.useEffect)(() => {
13666
+ (0, import_react102.useEffect)(() => {
13318
13667
  let cancelled = false;
13319
13668
  setLoading(true);
13320
13669
  setError(null);
@@ -13336,8 +13685,8 @@ function useEmbedHandshake(args) {
13336
13685
  }
13337
13686
 
13338
13687
  // src/RecordsMount.tsx
13339
- var import_react103 = require("@ai-matrx/records/react");
13340
- var import_jsx_runtime54 = require("react/jsx-runtime");
13688
+ var import_react105 = require("@ai-matrx/records/react");
13689
+ var import_jsx_runtime55 = require("react/jsx-runtime");
13341
13690
  var STORE_DECIDES_REASON = "This host offers exactly what the record store says this person may do: the level comes back with the table on the read door, so a control they cannot use is never drawn in the first place.";
13342
13691
  function storeDecidesRights(_table) {
13343
13692
  return NO_RIGHTS;
@@ -13350,7 +13699,7 @@ function RecordsMount({
13350
13699
  }) {
13351
13700
  const bound = { ...host ?? {} };
13352
13701
  void letTheStoreDecideRights;
13353
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react103.RecordsProvider, { config, children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(RecordsUiProvider, { value: bound, children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(RecordLabelProvider, { children }) }) });
13702
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_react105.RecordsProvider, { config, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(RecordsUiProvider, { value: bound, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(RecordLabelProvider, { children }) }) });
13354
13703
  }
13355
13704
  function personActor(userId) {
13356
13705
  return userId ? { actor: "user", user_id: userId } : { actor: "user" };
@@ -13369,9 +13718,9 @@ function recordsDataSource(client, fallbackSchema = "custom") {
13369
13718
  }
13370
13719
 
13371
13720
  // src/TablesHome.tsx
13372
- var import_react104 = require("react");
13373
- var import_react105 = require("@ai-matrx/records/react");
13374
- var import_design_system51 = require("@ai-matrx/design-system");
13721
+ var import_react106 = require("react");
13722
+ var import_react107 = require("@ai-matrx/records/react");
13723
+ var import_design_system52 = require("@ai-matrx/design-system");
13375
13724
 
13376
13725
  // src/createTable.ts
13377
13726
  function tokenFor(name) {
@@ -13481,7 +13830,7 @@ function declaredType(field) {
13481
13830
  }
13482
13831
 
13483
13832
  // src/TablesHome.tsx
13484
- var import_jsx_runtime55 = require("react/jsx-runtime");
13833
+ var import_jsx_runtime56 = require("react/jsx-runtime");
13485
13834
  var TABLE_LANES = ["mine", "organization", "system", "community", "app"];
13486
13835
  var LANE_TITLE = {
13487
13836
  mine: "Mine",
@@ -13506,15 +13855,15 @@ function laneFor(table) {
13506
13855
  return "organization";
13507
13856
  }
13508
13857
  function TablesHome({ onOpenTable, className }) {
13509
- const client = (0, import_react105.useRecordsClient)();
13510
- const tables = (0, import_react105.useTables)();
13511
- const [creating, setCreating] = (0, import_react104.useState)(false);
13512
- const [name, setName] = (0, import_react104.useState)("");
13513
- const [busy, setBusy] = (0, import_react104.useState)(false);
13514
- const [error, setError] = (0, import_react104.useState)(null);
13515
- const [importInto, setImportInto] = (0, import_react104.useState)(null);
13516
- const [boards, setBoards] = (0, import_react104.useState)(null);
13517
- (0, import_react104.useEffect)(() => {
13858
+ const client = (0, import_react107.useRecordsClient)();
13859
+ const tables = (0, import_react107.useTables)();
13860
+ const [creating, setCreating] = (0, import_react106.useState)(false);
13861
+ const [name, setName] = (0, import_react106.useState)("");
13862
+ const [busy, setBusy] = (0, import_react106.useState)(false);
13863
+ const [error, setError] = (0, import_react106.useState)(null);
13864
+ const [importInto, setImportInto] = (0, import_react106.useState)(null);
13865
+ const [boards, setBoards] = (0, import_react106.useState)(null);
13866
+ (0, import_react106.useEffect)(() => {
13518
13867
  let cancelled = false;
13519
13868
  void client.dashboards({}).then((result) => {
13520
13869
  if (cancelled) return;
@@ -13524,7 +13873,7 @@ function TablesHome({ onOpenTable, className }) {
13524
13873
  cancelled = true;
13525
13874
  };
13526
13875
  }, [client]);
13527
- const create = (0, import_react104.useCallback)(
13876
+ const create = (0, import_react106.useCallback)(
13528
13877
  async (mode) => {
13529
13878
  const trimmed = name.trim();
13530
13879
  if (!trimmed) return;
@@ -13544,10 +13893,10 @@ function TablesHome({ onOpenTable, className }) {
13544
13893
  },
13545
13894
  [client, name, onOpenTable, tables]
13546
13895
  );
13547
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: (0, import_design_system51.cn)("flex min-h-0 flex-col gap-4", className), children: [
13548
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "flex items-center gap-2", children: creating ? /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_jsx_runtime55.Fragment, { children: [
13549
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
13550
- import_design_system51.BasicInput,
13896
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: (0, import_design_system52.cn)("flex min-h-0 flex-col gap-4", className), children: [
13897
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "flex items-center gap-2", children: creating ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
13898
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13899
+ import_design_system52.BasicInput,
13551
13900
  {
13552
13901
  autoFocus: true,
13553
13902
  value: name,
@@ -13560,9 +13909,9 @@ function TablesHome({ onOpenTable, className }) {
13560
13909
  className: "h-8 max-w-xs"
13561
13910
  }
13562
13911
  ),
13563
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_design_system51.Button, { size: "sm", disabled: busy || name.trim().length === 0, onClick: () => void create("open"), children: busy ? "Declaring\u2026" : "Create" }),
13564
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
13565
- import_design_system51.Button,
13912
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_design_system52.Button, { size: "sm", disabled: busy || name.trim().length === 0, onClick: () => void create("open"), children: busy ? "Declaring\u2026" : "Create" }),
13913
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13914
+ import_design_system52.Button,
13566
13915
  {
13567
13916
  size: "sm",
13568
13917
  variant: "outline",
@@ -13571,37 +13920,37 @@ function TablesHome({ onOpenTable, className }) {
13571
13920
  children: "Create and import a file"
13572
13921
  }
13573
13922
  ),
13574
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_design_system51.Button, { size: "sm", variant: "ghost", onClick: () => setCreating(false), children: "Cancel" })
13575
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_design_system51.Button, { size: "sm", onClick: () => setCreating(true), children: "New table" }) }),
13576
- error ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(RefusalNotice, { error }) : null,
13577
- importInto ? /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "rounded-md border p-3", children: [
13578
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(ImportWizard, { tableId: importInto, onDone: () => setImportInto(null) }),
13579
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_design_system51.Button, { size: "sm", variant: "ghost", className: "mt-2", onClick: () => onOpenTable?.(importInto), children: "Open the table" })
13923
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_design_system52.Button, { size: "sm", variant: "ghost", onClick: () => setCreating(false), children: "Cancel" })
13924
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_design_system52.Button, { size: "sm", onClick: () => setCreating(true), children: "New table" }) }),
13925
+ error ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(RefusalNotice, { error }) : null,
13926
+ importInto ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "rounded-md border p-3", children: [
13927
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(ImportWizard, { tableId: importInto, onDone: () => setImportInto(null) }),
13928
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_design_system52.Button, { size: "sm", variant: "ghost", className: "mt-2", onClick: () => onOpenTable?.(importInto), children: "Open the table" })
13580
13929
  ] }) : null,
13581
- tables.error ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(RefusalNotice, { error: tables.error }) : null,
13582
- tables.loading && !tables.data ? /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "space-y-2", children: [
13583
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_design_system51.Skeleton, { className: "h-6 w-40" }),
13584
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_design_system51.Skeleton, { className: "h-16 w-full" })
13930
+ tables.error ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(RefusalNotice, { error: tables.error }) : null,
13931
+ tables.loading && !tables.data ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "space-y-2", children: [
13932
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_design_system52.Skeleton, { className: "h-6 w-40" }),
13933
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_design_system52.Skeleton, { className: "h-16 w-full" })
13585
13934
  ] }) : null,
13586
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(BookingSlots, {}),
13587
- boards && boards.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("section", { className: "space-y-1.5", children: [
13588
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "flex items-baseline gap-2", children: [
13589
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("h2", { className: "text-sm font-medium", children: "Dashboards" }),
13590
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "text-xs opacity-60", children: boards.length })
13935
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(BookingSlots, {}),
13936
+ boards && boards.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("section", { className: "space-y-1.5", children: [
13937
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "flex items-baseline gap-2", children: [
13938
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("h2", { className: "text-sm font-medium", children: "Dashboards" }),
13939
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "text-xs opacity-60", children: boards.length })
13591
13940
  ] }),
13592
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("ul", { className: "grid gap-1.5 sm:grid-cols-2 lg:grid-cols-3", children: boards.map((board) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
13941
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("ul", { className: "grid gap-1.5 sm:grid-cols-2 lg:grid-cols-3", children: boards.map((board) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
13593
13942
  "button",
13594
13943
  {
13595
13944
  type: "button",
13596
13945
  disabled: !board.table_id,
13597
13946
  onClick: () => board.table_id ? onOpenTable?.(board.table_id, board.dashboard_id) : void 0,
13598
- className: (0, import_design_system51.cn)(
13947
+ className: (0, import_design_system52.cn)(
13599
13948
  "w-full rounded-md border px-3 py-2 text-left transition-colors",
13600
13949
  onOpenTable && board.table_id ? "hover:bg-accent" : "cursor-default"
13601
13950
  ),
13602
13951
  children: [
13603
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "block truncate text-sm", children: board.name }),
13604
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "block truncate text-xs opacity-60", children: [
13952
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "block truncate text-sm", children: board.name }),
13953
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "block truncate text-xs opacity-60", children: [
13605
13954
  board.block_count,
13606
13955
  " block",
13607
13956
  board.block_count === 1 ? "" : "s",
@@ -13617,23 +13966,23 @@ function TablesHome({ onOpenTable, className }) {
13617
13966
  ] }) : null,
13618
13967
  tables.data ? TABLE_LANES.map((lane) => {
13619
13968
  const rows = tables.data.filter((t) => laneFor(t) === lane);
13620
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("section", { className: "space-y-1.5", children: [
13621
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "flex items-baseline gap-2", children: [
13622
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("h2", { className: "text-sm font-medium", children: LANE_TITLE[lane] }),
13623
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "text-xs opacity-60", children: rows.length })
13969
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("section", { className: "space-y-1.5", children: [
13970
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "flex items-baseline gap-2", children: [
13971
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("h2", { className: "text-sm font-medium", children: LANE_TITLE[lane] }),
13972
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "text-xs opacity-60", children: rows.length })
13624
13973
  ] }),
13625
- rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "text-xs opacity-70", children: LANE_EMPTY[lane] }) : /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("ul", { className: "grid gap-1.5 sm:grid-cols-2 lg:grid-cols-3", children: rows.map((table) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
13974
+ rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("p", { className: "text-xs opacity-70", children: LANE_EMPTY[lane] }) : /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("ul", { className: "grid gap-1.5 sm:grid-cols-2 lg:grid-cols-3", children: rows.map((table) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
13626
13975
  "button",
13627
13976
  {
13628
13977
  type: "button",
13629
13978
  onClick: () => onOpenTable?.(table.id),
13630
- className: (0, import_design_system51.cn)(
13979
+ className: (0, import_design_system52.cn)(
13631
13980
  "w-full rounded-md border px-3 py-2 text-left transition-colors",
13632
13981
  onOpenTable ? "hover:bg-accent" : "cursor-default"
13633
13982
  ),
13634
13983
  children: [
13635
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "block truncate text-sm", children: tableName(table) }),
13636
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "block truncate text-xs opacity-60", children: [
13984
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "block truncate text-sm", children: tableName(table) }),
13985
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "block truncate text-xs opacity-60", children: [
13637
13986
  table.fields.length,
13638
13987
  " field",
13639
13988
  table.fields.length === 1 ? "" : "s",
@@ -13648,10 +13997,10 @@ function TablesHome({ onOpenTable, className }) {
13648
13997
  }
13649
13998
 
13650
13999
  // src/TablePage.tsx
13651
- var import_react106 = require("react");
13652
- var import_react107 = require("@ai-matrx/records/react");
13653
- var import_design_system52 = require("@ai-matrx/design-system");
13654
- var import_jsx_runtime56 = require("react/jsx-runtime");
14000
+ var import_react108 = require("react");
14001
+ var import_react109 = require("@ai-matrx/records/react");
14002
+ var import_design_system53 = require("@ai-matrx/design-system");
14003
+ var import_jsx_runtime57 = require("react/jsx-runtime");
13655
14004
  var TABLE_NOT_REACHABLE = "This table is not in the organization you are working in, so there is nothing here to show. Switch to the organization that owns it and open it again \u2014 or it may have been deleted.";
13656
14005
  var DEFAULT_VIEW_NAME = "All records";
13657
14006
  var VIEW_NOT_SAVED_YET = "This table has no saved view yet, so the layout you pick here is not being kept. Save one from the bar above and it is remembered.";
@@ -13682,29 +14031,29 @@ function TablePage({
13682
14031
  activeRecordId,
13683
14032
  className
13684
14033
  }) {
13685
- const client = (0, import_react107.useRecordsClient)();
13686
- const table = (0, import_react107.useTable)(tableId);
14034
+ const client = (0, import_react109.useRecordsClient)();
14035
+ const table = (0, import_react109.useTable)(tableId);
13687
14036
  const rights = useTableRights(table.data);
13688
- const organizationId = (0, import_react107.useRecordsClient)().config.organizationId;
13689
- const [view, setView] = (0, import_react106.useState)(null);
14037
+ const organizationId = (0, import_react109.useRecordsClient)().config.organizationId;
14038
+ const [view, setView] = (0, import_react108.useState)(null);
13690
14039
  const opening = openingRail(activeRecordId);
13691
- const [asking, setAsking] = (0, import_react106.useState)(null);
13692
- const [surface, setSurface] = (0, import_react106.useState)({
14040
+ const [asking, setAsking] = (0, import_react108.useState)(null);
14041
+ const [surface, setSurface] = (0, import_react108.useState)({
13693
14042
  main: activeDashboardId ? "dashboards" : "records",
13694
14043
  rail: opening.rail
13695
14044
  });
13696
14045
  const { main, rail } = surface;
13697
14046
  const setRail = (next) => setSurface((now) => ({ ...now, rail: next }));
13698
- const [openRecord, setOpenRecord] = (0, import_react106.useState)(opening.record);
14047
+ const [openRecord, setOpenRecord] = (0, import_react108.useState)(opening.record);
13699
14048
  const viewVersion = useRecordVersion(view?.id ?? null);
13700
14049
  const press = (pressed) => setSurface((now) => chooseSurface(now, pressed));
13701
14050
  const show = (next) => press({ rail: next });
13702
- (0, import_react106.useEffect)(() => {
14051
+ (0, import_react108.useEffect)(() => {
13703
14052
  if (!activeRecordId) return;
13704
14053
  setOpenRecord(activeRecordId);
13705
14054
  setSurface((now) => ({ ...now, rail: "record" }));
13706
14055
  }, [activeRecordId]);
13707
- const patchView = (0, import_react106.useCallback)(
14056
+ const patchView = (0, import_react108.useCallback)(
13708
14057
  async (patch) => {
13709
14058
  const current = view;
13710
14059
  if (!current) return;
@@ -13720,19 +14069,19 @@ function TablePage({
13720
14069
  },
13721
14070
  [client, view, viewVersion]
13722
14071
  );
13723
- if (table.error) return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(RefusalNotice, { error: table.error });
13724
- if (table.loading) return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_design_system52.Skeleton, { className: "h-40 w-full" });
14072
+ if (table.error) return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(RefusalNotice, { error: table.error });
14073
+ if (table.loading) return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_design_system53.Skeleton, { className: "h-40 w-full" });
13725
14074
  if (!table.data) {
13726
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: (0, import_design_system52.cn)("flex flex-col items-start gap-2 rounded-md border border-dashed p-6", className), children: [
13727
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("p", { className: "text-sm font-medium", children: "This table is not here" }),
13728
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("p", { className: "max-w-prose text-xs text-muted-foreground", children: TABLE_NOT_REACHABLE }),
13729
- onLeave ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_design_system52.Button, { size: "sm", variant: "outline", onClick: onLeave, children: leaveLabel }) : null
14075
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: (0, import_design_system53.cn)("flex flex-col items-start gap-2 rounded-md border border-dashed p-6", className), children: [
14076
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "text-sm font-medium", children: "This table is not here" }),
14077
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "max-w-prose text-xs text-muted-foreground", children: TABLE_NOT_REACHABLE }),
14078
+ onLeave ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_design_system53.Button, { size: "sm", variant: "outline", onClick: onLeave, children: leaveLabel }) : null
13730
14079
  ] });
13731
14080
  }
13732
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: (0, import_design_system52.cn)("flex min-h-0 gap-4", className), children: [
13733
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col gap-2", children: [
13734
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5", children: [
13735
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
14081
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: (0, import_design_system53.cn)("flex min-h-0 gap-4", className), children: [
14082
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col gap-2", children: [
14083
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5", children: [
14084
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13736
14085
  ViewBar,
13737
14086
  {
13738
14087
  tableId,
@@ -13741,10 +14090,10 @@ function TablePage({
13741
14090
  className: "min-w-0 flex-1"
13742
14091
  }
13743
14092
  ),
13744
- rights.write && view && view.layout !== "grid" ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_design_system52.Button, { size: "sm", onClick: () => show("new-record"), children: "New record" }) : null,
13745
- rights.structure ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
13746
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13747
- import_design_system52.Button,
14093
+ rights.write && view && view.layout !== "grid" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_design_system53.Button, { size: "sm", onClick: () => show("new-record"), children: "New record" }) : null,
14094
+ rights.structure ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
14095
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14096
+ import_design_system53.Button,
13748
14097
  {
13749
14098
  size: "sm",
13750
14099
  variant: surfaceChosen(surface, { rail: "field" }) ? "secondary" : "outline",
@@ -13753,8 +14102,8 @@ function TablePage({
13753
14102
  children: "Add field"
13754
14103
  }
13755
14104
  ),
13756
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13757
- import_design_system52.Button,
14105
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14106
+ import_design_system53.Button,
13758
14107
  {
13759
14108
  size: "sm",
13760
14109
  variant: surfaceChosen(surface, { rail: "settings" }) ? "secondary" : "ghost",
@@ -13763,8 +14112,8 @@ function TablePage({
13763
14112
  children: "Settings"
13764
14113
  }
13765
14114
  ),
13766
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13767
- import_design_system52.Button,
14115
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14116
+ import_design_system53.Button,
13768
14117
  {
13769
14118
  size: "sm",
13770
14119
  variant: surfaceChosen(surface, { rail: "import" }) ? "secondary" : "ghost",
@@ -13774,8 +14123,8 @@ function TablePage({
13774
14123
  }
13775
14124
  )
13776
14125
  ] }) : null,
13777
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13778
- import_design_system52.Button,
14126
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14127
+ import_design_system53.Button,
13779
14128
  {
13780
14129
  size: "sm",
13781
14130
  variant: surfaceChosen(surface, { main: "dashboards" }) ? "secondary" : "ghost",
@@ -13784,8 +14133,8 @@ function TablePage({
13784
14133
  children: "Dashboards"
13785
14134
  }
13786
14135
  ),
13787
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13788
- import_design_system52.Button,
14136
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14137
+ import_design_system53.Button,
13789
14138
  {
13790
14139
  size: "sm",
13791
14140
  variant: surfaceChosen(surface, { rail: "forms" }) ? "secondary" : "ghost",
@@ -13794,8 +14143,8 @@ function TablePage({
13794
14143
  children: "Forms"
13795
14144
  }
13796
14145
  ),
13797
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13798
- import_design_system52.Button,
14146
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14147
+ import_design_system53.Button,
13799
14148
  {
13800
14149
  size: "sm",
13801
14150
  variant: surfaceChosen(surface, { rail: "bookings" }) ? "secondary" : "ghost",
@@ -13804,8 +14153,8 @@ function TablePage({
13804
14153
  children: "Bookings"
13805
14154
  }
13806
14155
  ),
13807
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13808
- import_design_system52.Button,
14156
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14157
+ import_design_system53.Button,
13809
14158
  {
13810
14159
  size: "sm",
13811
14160
  variant: surfaceChosen(surface, { rail: "checklists" }) ? "secondary" : "ghost",
@@ -13814,8 +14163,8 @@ function TablePage({
13814
14163
  children: "Checklists"
13815
14164
  }
13816
14165
  ),
13817
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13818
- import_design_system52.Button,
14166
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14167
+ import_design_system53.Button,
13819
14168
  {
13820
14169
  size: "sm",
13821
14170
  variant: surfaceChosen(surface, { rail: "notifications" }) ? "secondary" : "ghost",
@@ -13824,8 +14173,8 @@ function TablePage({
13824
14173
  children: "Notifications"
13825
14174
  }
13826
14175
  ),
13827
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13828
- import_design_system52.Button,
14176
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14177
+ import_design_system53.Button,
13829
14178
  {
13830
14179
  size: "sm",
13831
14180
  variant: surfaceChosen(surface, { rail: "portals" }) ? "secondary" : "ghost",
@@ -13834,8 +14183,8 @@ function TablePage({
13834
14183
  children: "Portals"
13835
14184
  }
13836
14185
  ),
13837
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13838
- import_design_system52.Button,
14186
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14187
+ import_design_system53.Button,
13839
14188
  {
13840
14189
  size: "sm",
13841
14190
  variant: surfaceChosen(surface, { rail: "inbox" }) ? "secondary" : "ghost",
@@ -13844,7 +14193,7 @@ function TablePage({
13844
14193
  children: "Inbox"
13845
14194
  }
13846
14195
  ),
13847
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
14196
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13848
14197
  ShareControl,
13849
14198
  {
13850
14199
  kind: "table",
@@ -13854,10 +14203,10 @@ function TablePage({
13854
14203
  may: rights.share
13855
14204
  }
13856
14205
  ),
13857
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(ExportMenu, { tableId })
14206
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ExportMenu, { tableId })
13858
14207
  ] }),
13859
- main === "dashboards" ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(DashboardCanvas, { tableId, activeDashboardId: activeDashboardId ?? null }) : /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
13860
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
14208
+ main === "dashboards" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(DashboardCanvas, { tableId, activeDashboardId: activeDashboardId ?? null }) : /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
14209
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13861
14210
  ViewSwitcher,
13862
14211
  {
13863
14212
  view: view ?? defaultView(tableId),
@@ -13874,18 +14223,18 @@ function TablePage({
13874
14223
  }
13875
14224
  }
13876
14225
  ),
13877
- view ? null : /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("p", { className: "text-xs text-muted-foreground", children: VIEW_NOT_SAVED_YET })
14226
+ view ? null : /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "text-xs text-muted-foreground", children: VIEW_NOT_SAVED_YET })
13878
14227
  ] })
13879
14228
  ] }),
13880
- rail === "none" ? null : /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("aside", { className: "w-[26rem] shrink-0 overflow-y-auto rounded-md border p-3", children: [
13881
- rail === "settings" ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
14229
+ rail === "none" ? null : /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("aside", { className: "w-[26rem] shrink-0 overflow-y-auto rounded-md border p-3", children: [
14230
+ rail === "settings" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13882
14231
  TableSettings,
13883
14232
  {
13884
14233
  tableId,
13885
14234
  ...onLeave ? { onDeleted: onLeave } : {}
13886
14235
  }
13887
14236
  ) : null,
13888
- rail === "inbox" ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
14237
+ rail === "inbox" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13889
14238
  ActionInbox,
13890
14239
  {
13891
14240
  tableId,
@@ -13895,9 +14244,9 @@ function TablePage({
13895
14244
  }
13896
14245
  }
13897
14246
  ) : null,
13898
- rail === "forms" ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(FormsPanel, { tableId }) : null,
13899
- rail === "bookings" ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(BookingSlots, { tableId }) : null,
13900
- rail === "checklists" ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
14247
+ rail === "forms" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(FormsPanel, { tableId }) : null,
14248
+ rail === "bookings" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(BookingSlots, { tableId }) : null,
14249
+ rail === "checklists" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13901
14250
  ChecklistsPanel,
13902
14251
  {
13903
14252
  tableId,
@@ -13907,11 +14256,11 @@ function TablePage({
13907
14256
  }
13908
14257
  }
13909
14258
  ) : null,
13910
- rail === "notifications" ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(SubscriptionsPanel, { tableId }) : null,
13911
- rail === "portals" ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(PortalsPanel, { tableId }) : null,
13912
- rail === "import" ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(ImportWizard, { tableId, onDone: () => setRail("none") }) : null,
13913
- rail === "field" ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(FieldEditor, { tableId, onSaved: () => setRail("none"), onCancel: () => setRail("none") }) : null,
13914
- rail === "new-record" ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
14259
+ rail === "notifications" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(SubscriptionsPanel, { tableId }) : null,
14260
+ rail === "portals" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(PortalsPanel, { tableId }) : null,
14261
+ rail === "import" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ImportWizard, { tableId, onDone: () => setRail("none") }) : null,
14262
+ rail === "field" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(FieldEditor, { tableId, onSaved: () => setRail("none"), onCancel: () => setRail("none") }) : null,
14263
+ rail === "new-record" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13915
14264
  RecordForm,
13916
14265
  {
13917
14266
  tableId,
@@ -13922,7 +14271,7 @@ function TablePage({
13922
14271
  onCancel: () => setRail("none")
13923
14272
  }
13924
14273
  ) : null,
13925
- rail === "who-changed" && asking ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
14274
+ rail === "who-changed" && asking ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13926
14275
  FieldHistoryPanel,
13927
14276
  {
13928
14277
  tableId,
@@ -13935,10 +14284,10 @@ function TablePage({
13935
14284
  }
13936
14285
  }
13937
14286
  ) : null,
13938
- rail === "record" && openRecord ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "space-y-3", children: [
13939
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Peek, { tableId, recordId: openRecord, onClose: () => setRail("none") }),
13940
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_design_system52.Separator, {}),
13941
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
14287
+ rail === "record" && openRecord ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "space-y-3", children: [
14288
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Peek, { tableId, recordId: openRecord, onClose: () => setRail("none") }),
14289
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_design_system53.Separator, {}),
14290
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13942
14291
  HistoryPanel,
13943
14292
  {
13944
14293
  tableId,
@@ -13949,10 +14298,10 @@ function TablePage({
13949
14298
  }
13950
14299
  }
13951
14300
  ),
13952
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_design_system52.Separator, {}),
13953
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(ChecklistRunner, { tableId, recordId: openRecord }),
13954
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_design_system52.Separator, {}),
13955
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(CommentThread, { tableId, recordId: openRecord })
14301
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_design_system53.Separator, {}),
14302
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ChecklistRunner, { tableId, recordId: openRecord }),
14303
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_design_system53.Separator, {}),
14304
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(CommentThread, { tableId, recordId: openRecord })
13956
14305
  ] }) : null
13957
14306
  ] })
13958
14307
  ] });