@ai-matrx/records-ui 0.51.0 → 0.53.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,
@@ -6403,6 +6404,7 @@ function Card({
6403
6404
 
6404
6405
  // src/ViewSwitcher.tsx
6405
6406
  var import_jsx_runtime25 = require("react/jsx-runtime");
6407
+ var NO_FIELDS = [];
6406
6408
  function useViewRecords(view, pageSize = 200) {
6407
6409
  const client = (0, import_react46.useRecordsClient)();
6408
6410
  const table = (0, import_react46.useRecords)(view.ruleId ? null : view.subject, { pageSize });
@@ -6772,7 +6774,12 @@ function Card2({
6772
6774
  onOpenRecord
6773
6775
  }) {
6774
6776
  const host = useRecordsUi();
6775
- const label = field ? scalarText(field, (record.document ?? {})[field.key]) : rowName(record, null, "Untitled");
6777
+ const wanted = (0, import_react45.useMemo)(
6778
+ () => field && pointsAtRecords(field) ? [field] : NO_FIELDS,
6779
+ [field]
6780
+ );
6781
+ const labels = useRecordLabels(wanted);
6782
+ const label = field ? scalarText(field, (record.document ?? {})[field.key], labels) : rowName(record, null, "Untitled");
6776
6783
  return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6777
6784
  "button",
6778
6785
  {
@@ -9537,28 +9544,325 @@ function Invite({ card, onInvited }) {
9537
9544
  ] });
9538
9545
  }
9539
9546
 
9540
- // src/SubscriptionsPanel.tsx
9547
+ // src/DigestScheduler.tsx
9541
9548
  var import_react67 = require("react");
9542
9549
  var import_react68 = require("@ai-matrx/records/react");
9543
9550
  var import_design_system33 = require("@ai-matrx/design-system");
9544
9551
  var import_jsx_runtime36 = require("react/jsx-runtime");
9552
+ var WEEKDAYS = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"];
9553
+ var CADENCE_WORDS = {
9554
+ instant: "the moment something arrives",
9555
+ hourly: "every hour",
9556
+ daily: "every day",
9557
+ weekly: "every week"
9558
+ };
9559
+ var CHANNEL_WORDS = {
9560
+ in_app: "in the app",
9561
+ email: "by email \u2014 only if an address is on their account",
9562
+ sms: "by text \u2014 only if a number is on their account"
9563
+ };
9564
+ function DigestScheduler({
9565
+ tableId,
9566
+ savedViewId,
9567
+ subjectName,
9568
+ filters,
9569
+ onScheduled,
9570
+ onClose,
9571
+ className
9572
+ }) {
9573
+ const client = (0, import_react68.useRecordsClient)();
9574
+ const host = useRecordsUi();
9575
+ const [views, setViews] = (0, import_react67.useState)(null);
9576
+ const [cadences, setCadences] = (0, import_react67.useState)([]);
9577
+ const [members, setMembers] = (0, import_react67.useState)(null);
9578
+ const [error, setError] = (0, import_react67.useState)(null);
9579
+ const [viewId, setViewId] = (0, import_react67.useState)(savedViewId ?? "");
9580
+ const [name, setName] = (0, import_react67.useState)(subjectName?.trim() ? `${subjectName.trim()} summary` : "");
9581
+ const [cadence, setCadence] = (0, import_react67.useState)("weekly");
9582
+ const [weekday, setWeekday] = (0, import_react67.useState)("monday");
9583
+ const [time, setTime] = (0, import_react67.useState)("08:00");
9584
+ const [channel, setChannel] = (0, import_react67.useState)("in_app");
9585
+ const [quiet, setQuiet] = (0, import_react67.useState)(false);
9586
+ const [quietFrom, setQuietFrom] = (0, import_react67.useState)("22:00");
9587
+ const [quietTo, setQuietTo] = (0, import_react67.useState)("07:00");
9588
+ const [recipients, setRecipients] = (0, import_react67.useState)([]);
9589
+ const [saving, setSaving] = (0, import_react67.useState)(false);
9590
+ const [outcomes, setOutcomes] = (0, import_react67.useState)(null);
9591
+ const [preview, setPreview] = (0, import_react67.useState)(null);
9592
+ const [previewing, setPreviewing] = (0, import_react67.useState)(false);
9593
+ const load = (0, import_react67.useCallback)(async () => {
9594
+ const [saved, offered] = await Promise.all([
9595
+ // The store's own door onto `platform.saved_view`, narrowed in SQL to
9596
+ // Tables this person can already open — never a grant on the table behind it.
9597
+ client.views({ table_id: tableId }),
9598
+ // The cadences are ASKED, never typed into this file, so a picker can
9599
+ // never offer a cadence the digest runner does not honour.
9600
+ client.subscriptionCadences()
9601
+ ]);
9602
+ if (!saved.ok) setError(saved.error);
9603
+ else setViews(saved.data);
9604
+ if (offered.ok) setCadences(offered.data.filter((c) => c !== "instant"));
9605
+ if (host.members) {
9606
+ const who = await host.members();
9607
+ setMembers(who.map((m) => ({ userId: m.userId, name: m.name ?? m.email ?? m.userId })));
9608
+ } else {
9609
+ setMembers([]);
9610
+ }
9611
+ }, [client, tableId, host]);
9612
+ (0, import_react67.useEffect)(() => {
9613
+ void load();
9614
+ }, [load]);
9615
+ const schedule = (0, import_react67.useMemo)(() => {
9616
+ if (cadence === "weekly") return `${weekday} ${time}`;
9617
+ if (cadence === "daily") return time;
9618
+ return null;
9619
+ }, [cadence, weekday, time]);
9620
+ const quietHours = (0, import_react67.useMemo)(
9621
+ () => quiet ? { start: quietFrom, end: quietTo } : null,
9622
+ [quiet, quietFrom, quietTo]
9623
+ );
9624
+ async function scheduleIt() {
9625
+ setSaving(true);
9626
+ setError(null);
9627
+ setOutcomes(null);
9628
+ let subject = viewId;
9629
+ if (subject === "" || subject === "new") {
9630
+ const declared = await client.viewDeclare({
9631
+ table_id: tableId,
9632
+ spec: {
9633
+ name: subjectName?.trim() ? subjectName.trim() : name.trim() || "Weekly summary",
9634
+ filters: filters ?? {}
9635
+ }
9636
+ });
9637
+ if (!declared.ok) {
9638
+ setSaving(false);
9639
+ setError(declared.error);
9640
+ return;
9641
+ }
9642
+ subject = declared.data;
9643
+ setViewId(declared.data);
9644
+ }
9645
+ const who = recipients.length > 0 ? recipients : [""];
9646
+ const done = [];
9647
+ for (const userId of who) {
9648
+ const label = members?.find((m) => m.userId === userId)?.name ?? (userId === "" ? "you" : userId);
9649
+ const written = await client.subscriptionDeclare({
9650
+ table_id: tableId,
9651
+ spec: {
9652
+ name: name.trim() === "" ? "Weekly summary" : name.trim(),
9653
+ saved_view_id: subject,
9654
+ cadence,
9655
+ schedule,
9656
+ channel,
9657
+ quiet_hours: quietHours,
9658
+ ...userId === "" ? {} : { recipient_user_id: userId }
9659
+ }
9660
+ });
9661
+ if (written.ok) done.push({ userId, who: label, ruleId: written.data });
9662
+ else done.push({ userId, who: label, refused: written.error });
9663
+ }
9664
+ setSaving(false);
9665
+ setOutcomes(done);
9666
+ if (done.some((d) => d.ruleId)) onScheduled?.();
9667
+ }
9668
+ async function showOne(ruleId) {
9669
+ setPreviewing(true);
9670
+ const answered = await client.subscriptionPreview({ rule_id: ruleId });
9671
+ setPreviewing(false);
9672
+ if (!answered.ok) {
9673
+ setError(answered.error);
9674
+ return;
9675
+ }
9676
+ setPreview(answered.data);
9677
+ }
9678
+ 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) });
9679
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("section", { className: (0, import_design_system33.cn)("flex flex-col gap-3", className), children: [
9680
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("header", { className: "flex items-center gap-2", children: [
9681
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h3", { className: "text-sm font-medium", children: "Send this on a schedule" }),
9682
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex-1" }),
9683
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Button, { size: "sm", disabled: saving, onClick: () => void scheduleIt(), children: saving ? "Scheduling\u2026" : "Schedule it" }),
9684
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Button, { size: "sm", variant: "ghost", onClick: onClose, children: "Close" }) : null
9685
+ ] }),
9686
+ error ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(RefusalNotice, { error }) : null,
9687
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex flex-col gap-1", children: [
9688
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Label, { className: "text-xs font-medium", children: "What to call it" }),
9689
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9690
+ import_design_system33.BasicInput,
9691
+ {
9692
+ value: name,
9693
+ placeholder: "Monday donor summary",
9694
+ onChange: (e) => setName(e.target.value)
9695
+ }
9696
+ )
9697
+ ] }),
9698
+ savedViewId ? null : /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex flex-col gap-1", children: [
9699
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Label, { className: "text-xs font-medium", children: "What it summarises" }),
9700
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
9701
+ "select",
9702
+ {
9703
+ className: "h-9 rounded border bg-background px-2 text-sm",
9704
+ value: viewId,
9705
+ onChange: (e) => setViewId(e.target.value),
9706
+ children: [
9707
+ /* @__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" }),
9708
+ (views ?? []).map((v) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("option", { value: v.view_id, children: v.name }, v.view_id))
9709
+ ]
9710
+ }
9711
+ ),
9712
+ /* @__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." })
9713
+ ] }),
9714
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
9715
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex flex-col gap-1", children: [
9716
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Label, { className: "text-xs font-medium", children: "How often" }),
9717
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9718
+ "select",
9719
+ {
9720
+ className: "h-9 rounded border bg-background px-2 text-sm",
9721
+ value: cadence,
9722
+ onChange: (e) => setCadence(e.target.value),
9723
+ 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))
9724
+ }
9725
+ )
9726
+ ] }),
9727
+ cadence === "weekly" ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex flex-col gap-1", children: [
9728
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Label, { className: "text-xs font-medium", children: "Which day" }),
9729
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9730
+ "select",
9731
+ {
9732
+ className: "h-9 rounded border bg-background px-2 text-sm",
9733
+ value: weekday,
9734
+ onChange: (e) => setWeekday(e.target.value),
9735
+ children: WEEKDAYS.map((d) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("option", { value: d, children: d[0].toUpperCase() + d.slice(1) }, d))
9736
+ }
9737
+ )
9738
+ ] }) : null,
9739
+ cadence === "weekly" || cadence === "daily" ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex flex-col gap-1", children: [
9740
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Label, { className: "text-xs font-medium", children: "At" }),
9741
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.BasicInput, { type: "time", value: time, onChange: (e) => setTime(e.target.value) })
9742
+ ] }) : null,
9743
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex flex-col gap-1", children: [
9744
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Label, { className: "text-xs font-medium", children: "Where it arrives" }),
9745
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9746
+ "select",
9747
+ {
9748
+ className: "h-9 rounded border bg-background px-2 text-sm",
9749
+ value: channel,
9750
+ onChange: (e) => setChannel(e.target.value),
9751
+ children: Object.entries(CHANNEL_WORDS).map(([key, words]) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("option", { value: key, children: words }, key))
9752
+ }
9753
+ )
9754
+ ] })
9755
+ ] }),
9756
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
9757
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Label, { className: "text-xs font-medium", children: "Who to send it to" }),
9758
+ 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: [
9759
+ /* @__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: [
9760
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9761
+ import_design_system33.Checkbox,
9762
+ {
9763
+ checked: recipients.includes(m.userId),
9764
+ onCheckedChange: (on) => setRecipients(
9765
+ (prev) => on ? [...prev, m.userId] : prev.filter((u) => u !== m.userId)
9766
+ )
9767
+ }
9768
+ ),
9769
+ m.name
9770
+ ] }, m.userId)) }),
9771
+ /* @__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.` })
9772
+ ] })
9773
+ ] }),
9774
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "flex items-center gap-1.5 text-xs", children: [
9775
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Checkbox, { checked: quiet, onCheckedChange: (on) => setQuiet(Boolean(on)) }),
9776
+ "Not between certain hours"
9777
+ ] }),
9778
+ quiet ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-2", children: [
9779
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9780
+ import_design_system33.BasicInput,
9781
+ {
9782
+ type: "time",
9783
+ className: "h-8 w-28",
9784
+ value: quietFrom,
9785
+ onChange: (e) => setQuietFrom(e.target.value)
9786
+ }
9787
+ ),
9788
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "text-xs text-muted-foreground", children: "and" }),
9789
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9790
+ import_design_system33.BasicInput,
9791
+ {
9792
+ type: "time",
9793
+ className: "h-8 w-28",
9794
+ value: quietTo,
9795
+ onChange: (e) => setQuietTo(e.target.value)
9796
+ }
9797
+ ),
9798
+ /* @__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." })
9799
+ ] }) : null,
9800
+ outcomes ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
9801
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Separator, {}),
9802
+ /* @__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: [
9803
+ o.who,
9804
+ " will get it ",
9805
+ CADENCE_WORDS[cadence] ?? cadence,
9806
+ schedule ? `, ${schedule}` : "",
9807
+ ".",
9808
+ " ",
9809
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9810
+ import_design_system33.Button,
9811
+ {
9812
+ size: "sm",
9813
+ variant: "ghost",
9814
+ disabled: previewing,
9815
+ onClick: () => void showOne(o.ruleId),
9816
+ children: "Send me one now"
9817
+ }
9818
+ )
9819
+ ] }) : o.refused ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(RefusalNotice, { error: o.refused }) : null }, o.userId || "me")) })
9820
+ ] }) : null,
9821
+ preview ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "rounded-md border bg-muted/40 p-2.5 text-xs", children: [
9822
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "font-medium", children: preview.subject }),
9823
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "mt-1 text-muted-foreground", children: preview.body }),
9824
+ preview.incomplete ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "mt-1 text-destructive", children: preview.incomplete }) : null,
9825
+ preview.entered.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("p", { className: "mt-1", children: [
9826
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "font-medium", children: "Arrived:" }),
9827
+ " ",
9828
+ preview.entered.map((e) => e.name).join(", ")
9829
+ ] }) : null,
9830
+ preview.changed.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("p", { className: "mt-1", children: [
9831
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "font-medium", children: "Changed:" }),
9832
+ " ",
9833
+ preview.changed.map((e) => e.name).join(", ")
9834
+ ] }) : null,
9835
+ /* @__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." }),
9836
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Button, { size: "sm", variant: "ghost", className: "mt-1", onClick: () => setPreview(null), children: "Close" })
9837
+ ] }) : null
9838
+ ] });
9839
+ }
9840
+
9841
+ // src/SubscriptionsPanel.tsx
9842
+ var import_react69 = require("react");
9843
+ var import_react70 = require("@ai-matrx/records/react");
9844
+ var import_design_system34 = require("@ai-matrx/design-system");
9845
+ var import_jsx_runtime37 = require("react/jsx-runtime");
9545
9846
  function whenItFires(subscription) {
9546
9847
  if (subscription.cadence === "instant") return "as it happens";
9547
9848
  const every = subscription.cadence === "hourly" ? "an hourly summary" : subscription.cadence === "weekly" ? "a weekly summary" : "a daily summary";
9548
9849
  return subscription.schedule ? `${every}, ${subscription.schedule}` : every;
9549
9850
  }
9550
- var CHANNEL_WORDS = {
9851
+ var CHANNEL_WORDS2 = {
9551
9852
  in_app: "in the app",
9552
9853
  email: "by email \u2014 only if an address is on the account",
9553
9854
  sms: "by text \u2014 only if a number is on the account"
9554
9855
  };
9856
+ var DIGEST_SUGGESTION = "Email me a summary of this every Monday at 8 in the morning.";
9555
9857
  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 () => {
9858
+ const client = (0, import_react70.useRecordsClient)();
9859
+ const [rows, setRows] = (0, import_react69.useState)(null);
9860
+ const [error, setError] = (0, import_react69.useState)(null);
9861
+ const [busy, setBusy] = (0, import_react69.useState)(null);
9862
+ const [preview, setPreview] = (0, import_react69.useState)(null);
9863
+ const [scheduling, setScheduling] = (0, import_react69.useState)(false);
9864
+ const host = useRecordsUi();
9865
+ const load = (0, import_react69.useCallback)(async () => {
9562
9866
  const answered = await client.subscriptions({ table_id: tableId });
9563
9867
  if (!answered.ok) {
9564
9868
  setError(answered.error);
@@ -9568,10 +9872,10 @@ function SubscriptionsPanel({ tableId, className }) {
9568
9872
  setError(null);
9569
9873
  setRows(answered.data);
9570
9874
  }, [client, tableId]);
9571
- (0, import_react67.useEffect)(() => {
9875
+ (0, import_react69.useEffect)(() => {
9572
9876
  void load();
9573
9877
  }, [load]);
9574
- const flip = (0, import_react67.useCallback)(
9878
+ const flip = (0, import_react69.useCallback)(
9575
9879
  async (subscription, on) => {
9576
9880
  setBusy(subscription.rule_id);
9577
9881
  const answered = await client.subscriptionMute({
@@ -9587,7 +9891,7 @@ function SubscriptionsPanel({ tableId, className }) {
9587
9891
  },
9588
9892
  [client, load]
9589
9893
  );
9590
- const showOne = (0, import_react67.useCallback)(
9894
+ const showOne = (0, import_react69.useCallback)(
9591
9895
  async (subscription) => {
9592
9896
  setBusy(subscription.rule_id);
9593
9897
  const answered = await client.subscriptionPreview({ rule_id: subscription.rule_id });
@@ -9601,53 +9905,85 @@ function SubscriptionsPanel({ tableId, className }) {
9601
9905
  },
9602
9906
  [client]
9603
9907
  );
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` })
9908
+ 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) });
9909
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("section", { className: (0, import_design_system34.cn)("flex flex-col gap-3", className), children: [
9910
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("header", { className: "flex items-center gap-2", children: [
9911
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("h3", { className: "text-sm font-medium", children: "Notifications" }),
9912
+ /* @__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` }),
9913
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "flex-1" }),
9914
+ rows.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
9915
+ import_design_system34.Button,
9916
+ {
9917
+ size: "sm",
9918
+ variant: scheduling ? "secondary" : "ghost",
9919
+ onClick: () => setScheduling((s) => !s),
9920
+ children: scheduling ? "Done" : "Schedule a summary"
9921
+ }
9922
+ ) : null
9609
9923
  ] }),
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`,
9924
+ error ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(RefusalNotice, { error }) : null,
9925
+ scheduling ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
9926
+ DigestScheduler,
9927
+ {
9928
+ tableId,
9929
+ onScheduled: () => {
9930
+ void load();
9931
+ },
9932
+ onClose: () => setScheduling(false)
9933
+ }
9934
+ ) : null,
9935
+ rows.length === 0 && !scheduling ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
9936
+ BuildOrAsk,
9937
+ {
9938
+ mayBuild: true,
9939
+ onBuild: () => setScheduling(true),
9940
+ ...host.onAskForOne ? {
9941
+ onAsk: () => host.onAskForOne?.({ kind: "digest", tableId, suggestion: DIGEST_SUGGESTION })
9942
+ } : {},
9943
+ suggestion: DIGEST_SUGGESTION,
9944
+ buildLabel: "Schedule a summary",
9945
+ 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."
9946
+ }
9947
+ ) : null,
9948
+ /* @__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: [
9949
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex items-start gap-2", children: [
9950
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "min-w-0 flex-1", children: [
9951
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "truncate text-sm font-medium", children: subscription.name }),
9952
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("p", { className: "mt-0.5 text-xs text-muted-foreground", children: [
9953
+ CHANNEL_WORDS2[subscription.channel] ?? `on the ${subscription.channel} channel`,
9618
9954
  " \xB7 ",
9619
9955
  whenItFires(subscription)
9620
9956
  ] })
9621
9957
  ] }),
9622
- subscription.i_may_mute ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9623
- import_design_system33.Switch,
9958
+ subscription.i_may_mute ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
9959
+ import_design_system34.Switch,
9624
9960
  {
9625
9961
  checked: !subscription.muted,
9626
9962
  disabled: busy === subscription.rule_id,
9627
9963
  "aria-label": `Tell me about ${subscription.name}`,
9628
9964
  onCheckedChange: (on) => void flip(subscription, on)
9629
9965
  }
9630
- ) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system33.Badge, { variant: "secondary", children: "someone else's" })
9966
+ ) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_design_system34.Badge, { variant: "secondary", children: "someone else's" })
9631
9967
  ] }),
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: [
9968
+ /* @__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." }),
9969
+ /* @__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: [
9970
+ subscription.next_digest_at ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { children: [
9635
9971
  "Next summary ",
9636
9972
  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: [
9973
+ ] }) : subscription.cadence === "instant" ? null : subscription.muted ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { children: "No next summary while it is off." }) : null,
9974
+ subscription.last_sent_at ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { children: [
9639
9975
  "Last told you ",
9640
9976
  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: [
9977
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { children: "It has not told you anything yet." }),
9978
+ subscription.quiet_hours ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { children: [
9643
9979
  "Not between ",
9644
9980
  subscription.quiet_hours.start,
9645
9981
  " and ",
9646
9982
  subscription.quiet_hours.end,
9647
9983
  " \u2014 a send inside those hours waits until they end."
9648
9984
  ] }) : null,
9649
- subscription.cadence === "instant" ? null : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
9650
- import_design_system33.Button,
9985
+ subscription.cadence === "instant" ? null : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
9986
+ import_design_system34.Button,
9651
9987
  {
9652
9988
  size: "sm",
9653
9989
  variant: "ghost",
@@ -9657,58 +9993,58 @@ function SubscriptionsPanel({ tableId, className }) {
9657
9993
  }
9658
9994
  )
9659
9995
  ] }),
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 }),
9996
+ 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: [
9997
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "font-medium", children: preview.subject }),
9998
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "mt-1 text-muted-foreground", children: preview.body }),
9663
9999
  preview.incomplete ? (
9664
10000
  // Absent or honest: a subscription that cannot produce a summary
9665
10001
  // 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 })
10002
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "mt-1 text-destructive", children: preview.incomplete })
9667
10003
  ) : 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:" }),
10004
+ preview.entered.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("p", { className: "mt-1", children: [
10005
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "font-medium", children: "Arrived:" }),
9670
10006
  " ",
9671
10007
  preview.entered.map((e) => e.name).join(", ")
9672
10008
  ] }) : 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:" }),
10009
+ preview.left.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("p", { className: "mt-1", children: [
10010
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "font-medium", children: "Left:" }),
9675
10011
  " ",
9676
10012
  preview.left.map((e) => e.name).join(", ")
9677
10013
  ] }) : 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:" }),
10014
+ preview.changed.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("p", { className: "mt-1", children: [
10015
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "font-medium", children: "Changed:" }),
9680
10016
  " ",
9681
10017
  preview.changed.map((e) => e.name).join(", ")
9682
10018
  ] }) : 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" })
10019
+ /* @__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." }),
10020
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_design_system34.Button, { size: "sm", variant: "ghost", className: "mt-1", onClick: () => setPreview(null), children: "Close" })
9685
10021
  ] }) : null
9686
10022
  ] }, subscription.rule_id)) })
9687
10023
  ] });
9688
10024
  }
9689
10025
 
9690
10026
  // src/FormBuilder.tsx
9691
- var import_react71 = require("react");
9692
- var import_react72 = require("@ai-matrx/records/react");
10027
+ var import_react73 = require("react");
10028
+ var import_react74 = require("@ai-matrx/records/react");
9693
10029
  var import_records6 = require("@ai-matrx/records");
9694
- var import_design_system35 = require("@ai-matrx/design-system");
10030
+ var import_design_system36 = require("@ai-matrx/design-system");
9695
10031
 
9696
10032
  // 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");
10033
+ var import_react71 = require("react");
10034
+ var import_react72 = require("@ai-matrx/records/react");
10035
+ var import_design_system35 = require("@ai-matrx/design-system");
10036
+ var import_jsx_runtime38 = require("react/jsx-runtime");
9701
10037
  function FormRunner(props) {
9702
10038
  if (props.fields && props.onSubmit) {
9703
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(FormStage, { ...props, fields: props.fields, onSubmit: props.onSubmit });
10039
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(FormStage, { ...props, fields: props.fields, onSubmit: props.onSubmit });
9704
10040
  }
9705
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ConnectedFormRunner, { ...props });
10041
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ConnectedFormRunner, { ...props });
9706
10042
  }
9707
10043
  function ConnectedFormRunner(props) {
9708
- const client = (0, import_react70.useOptionalRecordsClient)();
9709
- const fields = (0, import_react70.useFields)(props.form.subject);
10044
+ const client = (0, import_react72.useOptionalRecordsClient)();
10045
+ const fields = (0, import_react72.useFields)(props.form.subject);
9710
10046
  const { form, className } = props;
9711
- const submit = (0, import_react69.useCallback)(
10047
+ const submit = (0, import_react71.useCallback)(
9712
10048
  async (values) => {
9713
10049
  if (!client) {
9714
10050
  return {
@@ -9731,7 +10067,7 @@ function ConnectedFormRunner(props) {
9731
10067
  },
9732
10068
  [client, form]
9733
10069
  );
9734
- const evaluate = (0, import_react69.useCallback)(
10070
+ const evaluate = (0, import_react71.useCallback)(
9735
10071
  async (expr, values) => {
9736
10072
  if (!client) return null;
9737
10073
  const answered = await client.ruleEval({ expr, values });
@@ -9740,9 +10076,9 @@ function ConnectedFormRunner(props) {
9740
10076
  },
9741
10077
  [client]
9742
10078
  );
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)(
10079
+ if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(RefusalNotice, { error: fields.error, className });
10080
+ 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) });
10081
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
9746
10082
  FormStage,
9747
10083
  {
9748
10084
  ...props,
@@ -9765,16 +10101,16 @@ function FormStage({
9765
10101
  connected = false
9766
10102
  }) {
9767
10103
  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)(() => {
10104
+ const [answers, setAnswers] = (0, import_react71.useState)({});
10105
+ const [at, setAt] = (0, import_react71.useState)(0);
10106
+ const [error, setError] = (0, import_react71.useState)(null);
10107
+ const [refusal, setRefusal] = (0, import_react71.useState)(null);
10108
+ const [writing, setWriting] = (0, import_react71.useState)(false);
10109
+ const [done, setDone] = (0, import_react71.useState)(null);
10110
+ const [hidden, setHidden] = (0, import_react71.useState)({});
10111
+ const decoy = (0, import_react71.useRef)("");
10112
+ const stage = (0, import_react71.useRef)(null);
10113
+ const questions = (0, import_react71.useMemo)(() => {
9778
10114
  const byKey = new Map((fields ?? []).map((f) => [f.key, f]));
9779
10115
  return (form.questions ?? []).map((q) => {
9780
10116
  const field = byKey.get(q.field) ?? null;
@@ -9788,7 +10124,7 @@ function FormStage({
9788
10124
  };
9789
10125
  });
9790
10126
  }, [fields, form.questions]);
9791
- (0, import_react69.useEffect)(() => {
10127
+ (0, import_react71.useEffect)(() => {
9792
10128
  let cancelled = false;
9793
10129
  const conditional = questions.filter((q) => q.showIf);
9794
10130
  if (conditional.length === 0 || !evaluate) return;
@@ -9822,7 +10158,7 @@ function FormStage({
9822
10158
  const v = answers[q.key];
9823
10159
  return q.required && (v === void 0 || v === null || v === "");
9824
10160
  });
9825
- const submit = (0, import_react69.useCallback)(async () => {
10161
+ const submit = (0, import_react71.useCallback)(async () => {
9826
10162
  if (preview) {
9827
10163
  setDone("preview");
9828
10164
  return;
@@ -9859,51 +10195,51 @@ function FormStage({
9859
10195
  if (event.shiftKey) retreat();
9860
10196
  else advance();
9861
10197
  }
9862
- (0, import_react69.useEffect)(() => {
10198
+ (0, import_react71.useEffect)(() => {
9863
10199
  const input = stage.current?.querySelector(
9864
10200
  "input:not([tabindex='-1']), textarea, select, [role='combobox']"
9865
10201
  );
9866
10202
  input?.focus();
9867
10203
  }, [index, done]);
9868
10204
  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 })
10205
+ 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: [
10206
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("h2", { className: "text-lg font-medium", children: form.thankYou?.title ?? "Thank you" }),
10207
+ form.thankYou?.body ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "mt-1 text-sm text-muted-foreground", children: form.thankYou.body }) : null,
10208
+ /* @__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
10209
  ] });
9874
10210
  }
9875
10211
  const unresolved = questions.filter((q) => !q.field);
9876
10212
  const unanswerable = !evaluate && questions.some((q) => q.showIf);
9877
10213
  const signedInPublic = connected && form.isPublic === true;
9878
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
10214
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
9879
10215
  "section",
9880
10216
  {
9881
- className: (0, import_design_system34.cn)("mx-auto flex max-w-xl flex-col gap-3 py-4", centred && "text-center", className),
10217
+ className: (0, import_design_system35.cn)("mx-auto flex max-w-xl flex-col gap-3 py-4", centred && "text-center", className),
9882
10218
  onKeyDown,
9883
10219
  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,
10220
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("header", { className: "flex items-center gap-3 text-xs text-muted-foreground", children: [
10221
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10222
+ import_design_system35.Progress,
9887
10223
  {
9888
10224
  value: live.length === 0 ? 0 : (oneAtATime ? index + 1 : answered) / live.length * 100,
9889
10225
  className: "h-1 flex-1"
9890
10226
  }
9891
10227
  ),
9892
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "tabular-nums", children: oneAtATime ? `${index + 1} of ${live.length}` : `${answered} of ${live.length}` })
10228
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "tabular-nums", children: oneAtATime ? `${index + 1} of ${live.length}` : `${answered} of ${live.length}` })
9893
10229
  ] }),
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: [
10230
+ 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,
10231
+ 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,
10232
+ 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
10233
  unresolved.map((q) => q.key).join(", "),
9898
10234
  " ",
9899
10235
  unresolved.length === 1 ? "is a question" : "are questions",
9900
10236
  " 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
10237
  ] }) : 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)(
10238
+ form.intro && index === 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "text-sm text-muted-foreground", children: form.intro }) : null,
10239
+ error ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(RefusalNotice, { error, className: "text-left" }) : null,
10240
+ 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,
10241
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { ref: stage, className: "flex flex-col gap-4 text-left", children: [
10242
+ (oneAtATime ? current ? [current] : [] : live).map((q) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
9907
10243
  Question,
9908
10244
  {
9909
10245
  question: q,
@@ -9913,11 +10249,11 @@ function FormStage({
9913
10249
  },
9914
10250
  q.key
9915
10251
  )),
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
10252
+ 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
10253
  ] }),
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)(
10254
+ 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: [
10255
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("label", { htmlFor: `hp-${honeypotKey}`, children: "Leave this field empty" }),
10256
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
9921
10257
  "input",
9922
10258
  {
9923
10259
  id: `hp-${honeypotKey}`,
@@ -9932,16 +10268,16 @@ function FormStage({
9932
10268
  }
9933
10269
  )
9934
10270
  ] }) : 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: [
10271
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("footer", { className: (0, import_design_system35.cn)("flex flex-wrap items-center gap-2", centred && "justify-center"), children: [
10272
+ oneAtATime && index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system35.Button, { size: "sm", variant: "ghost", onClick: retreat, children: "Back" }) : null,
10273
+ 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" }),
10274
+ missing.length > 0 && (!oneAtATime || index === live.length - 1) ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
9939
10275
  missing.map((q) => q.ask).join(", "),
9940
10276
  " still ",
9941
10277
  missing.length === 1 ? "needs" : "need",
9942
10278
  " an answer."
9943
10279
  ] }) : null,
9944
- preview ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "text-xs text-muted-foreground", children: "Preview \u2014 nothing is written." }) : null
10280
+ preview ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "text-xs text-muted-foreground", children: "Preview \u2014 nothing is written." }) : null
9945
10281
  ] })
9946
10282
  ]
9947
10283
  }
@@ -9953,16 +10289,16 @@ function Question({
9953
10289
  onChange,
9954
10290
  upload
9955
10291
  }) {
9956
- const [uploadError, setUploadError] = (0, import_react69.useState)(null);
10292
+ const [uploadError, setUploadError] = (0, import_react71.useState)(null);
9957
10293
  const field = question.field;
9958
10294
  if (!field) return null;
9959
10295
  const id = `form-${field.key}`;
9960
10296
  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)(
10297
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
10298
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(FieldLabel, { field: { ...field, label: question.ask, required: question.required }, htmlFor: id }),
10299
+ question.help ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "text-xs text-muted-foreground", children: question.help }) : null,
10300
+ 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: [
10301
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
9966
10302
  "input",
9967
10303
  {
9968
10304
  id,
@@ -9980,31 +10316,31 @@ function Question({
9980
10316
  }
9981
10317
  }
9982
10318
  ),
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 })
10319
+ uploadError ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "text-xs text-destructive", children: uploadError }) : null
10320
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(FieldControl, { field, value, onChange, id })
9985
10321
  ] });
9986
10322
  }
9987
10323
 
9988
10324
  // src/FormBuilder.tsx
9989
- var import_jsx_runtime38 = require("react/jsx-runtime");
10325
+ var import_jsx_runtime39 = require("react/jsx-runtime");
9990
10326
  function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
9991
- const client = (0, import_react72.useRecordsClient)();
10327
+ const client = (0, import_react74.useRecordsClient)();
9992
10328
  const host = useRecordsUi();
9993
10329
  const claimSeed = useSeedGuard();
9994
- const table = (0, import_react72.useTable)(tableId);
10330
+ const table = (0, import_react74.useTable)(tableId);
9995
10331
  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);
10332
+ const fields = (0, import_react74.useFields)(tableId);
10333
+ const [forms, setForms] = (0, import_react73.useState)(null);
10334
+ const [error, setError] = (0, import_react73.useState)(null);
10335
+ const [activeId, setActiveId] = (0, import_react73.useState)(activeFormId ?? null);
10336
+ const [draft, setDraft] = (0, import_react73.useState)(null);
10337
+ const [saving, setSaving] = (0, import_react73.useState)(false);
10338
+ const [saved, setSaved] = (0, import_react73.useState)(null);
10339
+ const [publishing, setPublishing] = (0, import_react73.useState)(false);
10340
+ const [copied, setCopied] = (0, import_react73.useState)(false);
10341
+ const [shownUrl, setShownUrl] = (0, import_react73.useState)(null);
10006
10342
  const publicOrigin = host.publicOrigin ?? (typeof window === "undefined" ? "" : window.location.origin);
10007
- const load = (0, import_react71.useCallback)(async () => {
10343
+ const load = (0, import_react73.useCallback)(async () => {
10008
10344
  const answered = await client.forms({ table_id: tableId });
10009
10345
  if (!answered.ok) {
10010
10346
  setError(answered.error);
@@ -10031,17 +10367,17 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10031
10367
  setError(null);
10032
10368
  setForms(mine);
10033
10369
  }, [client, tableId, seed, claimSeed]);
10034
- (0, import_react71.useEffect)(() => {
10370
+ (0, import_react73.useEffect)(() => {
10035
10371
  void load();
10036
10372
  }, [load]);
10037
- (0, import_react71.useEffect)(() => {
10373
+ (0, import_react73.useEffect)(() => {
10038
10374
  if (!forms || forms.length === 0) return;
10039
10375
  const chosen = forms.find((f) => f.id === (activeFormId ?? activeId)) ?? forms[0];
10040
10376
  if (chosen.id !== activeId) setActiveId(chosen.id);
10041
10377
  setDraft(chosen);
10042
10378
  onActiveForm?.(chosen);
10043
10379
  }, [forms, activeFormId]);
10044
- const byKey = (0, import_react71.useMemo)(() => new Map((fields.data ?? []).map((f) => [f.key, f])), [fields.data]);
10380
+ const byKey = (0, import_react73.useMemo)(() => new Map((fields.data ?? []).map((f) => [f.key, f])), [fields.data]);
10045
10381
  function patch(change) {
10046
10382
  setDraft((prev) => prev ? { ...prev, ...change } : prev);
10047
10383
  setSaved(null);
@@ -10101,26 +10437,26 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10101
10437
  setActiveId(written.data);
10102
10438
  await load();
10103
10439
  }
10104
- if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(RefusalNotice, { error: fields.error, className });
10440
+ if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(RefusalNotice, { error: fields.error, className });
10105
10441
  if (error) {
10106
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10442
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10107
10443
  RefusalNotice,
10108
10444
  {
10109
10445
  error,
10110
10446
  className,
10111
- actions: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system35.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
10447
+ actions: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
10112
10448
  }
10113
10449
  );
10114
10450
  }
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) });
10451
+ 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
10452
  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") });
10453
+ 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
10454
  }
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,
10455
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: (0, import_design_system36.cn)("flex min-h-0 gap-3", className), children: [
10456
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col gap-2 overflow-auto", children: [
10457
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex items-center gap-1 overflow-x-auto", role: "group", "aria-label": "Forms", children: [
10458
+ forms.map((form) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10459
+ import_design_system36.Button,
10124
10460
  {
10125
10461
  size: "sm",
10126
10462
  variant: form.id === activeId ? "secondary" : "ghost",
@@ -10133,14 +10469,14 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10133
10469
  },
10134
10470
  form.id
10135
10471
  )),
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" })
10472
+ (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,
10473
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "ml-auto flex items-center gap-2", children: [
10474
+ saved ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-xs text-muted-foreground", children: saved }) : null,
10475
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.Button, { size: "sm", disabled: saving || !draft, onClick: () => void save(), children: saving ? "Saving\u2026" : "Save" })
10140
10476
  ] })
10141
10477
  ] }),
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)(
10478
+ !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: [
10479
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10144
10480
  PublishRow,
10145
10481
  {
10146
10482
  url: `${publicOrigin}${(0, import_records6.publicFormPath)(draft.id)}`,
@@ -10154,27 +10490,27 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10154
10490
  onCopy: (url) => void copyLink(url)
10155
10491
  }
10156
10492
  ),
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 }) })
10493
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
10494
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("label", { className: "flex flex-col gap-1", children: [
10495
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.Label, { className: "text-xs font-medium", children: "Name" }),
10496
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.BasicInput, { value: draft.name, onChange: (e) => patch({ name: e.target.value }) })
10161
10497
  ] }),
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)(
10498
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("label", { className: "flex flex-col gap-1", children: [
10499
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.Label, { className: "text-xs font-medium", children: "Flow" }),
10500
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10165
10501
  "select",
10166
10502
  {
10167
10503
  className: "h-9 rounded border bg-background px-2 text-sm",
10168
10504
  value: draft.flow ?? "one-at-a-time",
10169
10505
  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))
10506
+ 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
10507
  }
10172
10508
  )
10173
10509
  ] }),
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,
10510
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("label", { className: "col-span-2 flex flex-col gap-1", children: [
10511
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.Label, { className: "text-xs font-medium", children: "Intro" }),
10512
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10513
+ import_design_system36.BasicTextarea,
10178
10514
  {
10179
10515
  rows: 2,
10180
10516
  value: draft.intro ?? "",
@@ -10182,10 +10518,10 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10182
10518
  }
10183
10519
  )
10184
10520
  ] }),
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,
10521
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("label", { className: "flex flex-col gap-1", children: [
10522
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.Label, { className: "text-xs font-medium", children: "Submit button" }),
10523
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10524
+ import_design_system36.BasicInput,
10189
10525
  {
10190
10526
  value: draft.submitLabel ?? "",
10191
10527
  placeholder: "Submit",
@@ -10193,10 +10529,10 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10193
10529
  }
10194
10530
  )
10195
10531
  ] }),
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,
10532
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("label", { className: "flex flex-col gap-1", children: [
10533
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.Label, { className: "text-xs font-medium", children: "Thank-you title" }),
10534
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10535
+ import_design_system36.BasicInput,
10200
10536
  {
10201
10537
  value: draft.thankYou?.title ?? "",
10202
10538
  placeholder: "Thank you",
@@ -10207,10 +10543,10 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10207
10543
  )
10208
10544
  ] })
10209
10545
  ] }),
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: [
10546
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-col gap-1", children: [
10547
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
10548
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "font-medium text-foreground", children: "Questions" }),
10549
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { children: [
10214
10550
  draft.questions.length,
10215
10551
  " of this table's ",
10216
10552
  fields.data?.length ?? 0,
@@ -10221,10 +10557,10 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10221
10557
  const index = draft.questions.findIndex((q) => q.field === field.key);
10222
10558
  const asked = index >= 0;
10223
10559
  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,
10560
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "rounded border px-2 py-1.5", children: [
10561
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex items-center gap-2", children: [
10562
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10563
+ import_design_system36.Checkbox,
10228
10564
  {
10229
10565
  checked: asked,
10230
10566
  "aria-label": `Ask for ${fieldName(field)}`,
@@ -10233,13 +10569,13 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10233
10569
  })
10234
10570
  }
10235
10571
  ),
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
10572
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-xs font-medium", children: fieldName(field) }),
10573
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-xs text-muted-foreground", children: field.key }),
10574
+ field.required ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-xs text-destructive", children: "required" }) : null
10239
10575
  ] }),
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,
10576
+ asked && question ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "mt-1.5 grid grid-cols-2 gap-2 pl-6", children: [
10577
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10578
+ import_design_system36.BasicInput,
10243
10579
  {
10244
10580
  className: "h-8 text-xs",
10245
10581
  placeholder: fieldName(field),
@@ -10248,8 +10584,8 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10248
10584
  onChange: (e) => patchQuestion(index, { ask: e.target.value || null })
10249
10585
  }
10250
10586
  ),
10251
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10252
- import_design_system35.BasicInput,
10587
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10588
+ import_design_system36.BasicInput,
10253
10589
  {
10254
10590
  className: "h-8 text-xs",
10255
10591
  placeholder: "Help text",
@@ -10258,7 +10594,7 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10258
10594
  onChange: (e) => patchQuestion(index, { help: e.target.value || null })
10259
10595
  }
10260
10596
  ),
10261
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10597
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10262
10598
  Condition,
10263
10599
  {
10264
10600
  question,
@@ -10269,7 +10605,7 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10269
10605
  ] }) : null
10270
10606
  ] }, field.id);
10271
10607
  }),
10272
- draft.questions.filter((q) => !byKey.has(q.field)).map((q) => /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("p", { className: "text-xs text-destructive", children: [
10608
+ draft.questions.filter((q) => !byKey.has(q.field)).map((q) => /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("p", { className: "text-xs text-destructive", children: [
10273
10609
  'This form asks for "',
10274
10610
  q.field,
10275
10611
  '" and this table has no such Field. It is shown here rather than quietly dropped.'
@@ -10277,9 +10613,9 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10277
10613
  ] })
10278
10614
  ] })
10279
10615
  ] }),
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 })
10616
+ draft ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("aside", { className: "w-96 shrink-0 overflow-auto rounded border p-2", children: [
10617
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("h4", { className: "px-1 text-sm font-medium", children: draft.name }),
10618
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(FormRunner, { form: draft, preview: true })
10283
10619
  ] }) : null
10284
10620
  ] });
10285
10621
  }
@@ -10295,10 +10631,10 @@ function PublishRow({
10295
10631
  onCopy
10296
10632
  }) {
10297
10633
  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,
10634
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-col gap-1.5 rounded border px-2.5 py-2", children: [
10635
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
10636
+ mayPublish ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10637
+ import_design_system36.Button,
10302
10638
  {
10303
10639
  size: "sm",
10304
10640
  variant: open ? "ghost" : "default",
@@ -10307,8 +10643,8 @@ function PublishRow({
10307
10643
  children: busy ? "\u2026" : open ? "Unpublish" : "Publish"
10308
10644
  }
10309
10645
  ) : null,
10310
- state !== "draft" ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_jsx_runtime38.Fragment, { children: [
10311
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10646
+ state !== "draft" ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
10647
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10312
10648
  "a",
10313
10649
  {
10314
10650
  href: url,
@@ -10318,12 +10654,12 @@ function PublishRow({
10318
10654
  children: url
10319
10655
  }
10320
10656
  ),
10321
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system35.Button, { size: "sm", variant: "outline", onClick: () => onCopy(url), children: copied ? "Copied" : "Copy link" })
10657
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system36.Button, { size: "sm", variant: "outline", onClick: () => onCopy(url), children: copied ? "Copied" : "Copy link" })
10322
10658
  ] }) : null
10323
10659
  ] }),
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: [
10660
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-xs text-muted-foreground", children: FORM_STATE_WORDS[state] }),
10661
+ !mayPublish ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-xs text-muted-foreground", children: why }) : null,
10662
+ shownUrl ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("p", { className: "break-all rounded border border-dashed px-2 py-1 text-xs", children: [
10327
10663
  "This browser would not let the page copy for you, so here it is to copy by hand: ",
10328
10664
  shownUrl
10329
10665
  ] }) : null
@@ -10334,7 +10670,7 @@ function Condition({
10334
10670
  fieldKeys,
10335
10671
  onChange
10336
10672
  }) {
10337
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
10673
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10338
10674
  ConditionRow,
10339
10675
  {
10340
10676
  lead: "Ask only when",
@@ -10431,13 +10767,13 @@ function groupLabel(groups) {
10431
10767
  }
10432
10768
 
10433
10769
  // 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");
10770
+ var import_react75 = require("react");
10771
+ var import_design_system37 = require("@ai-matrx/design-system");
10772
+ var import_jsx_runtime40 = require("react/jsx-runtime");
10437
10773
  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)(() => {
10774
+ const ref = (0, import_react75.useRef)(null);
10775
+ const [width, setWidth] = (0, import_react75.useState)(fallback);
10776
+ (0, import_react75.useEffect)(() => {
10441
10777
  const node = ref.current;
10442
10778
  if (!node) return;
10443
10779
  const apply = () => {
@@ -10467,14 +10803,14 @@ function ChartFrame({
10467
10803
  children
10468
10804
  }) {
10469
10805
  const [ref, width] = useMeasuredWidth();
10470
- const chartId = `records-chart-${(0, import_react73.useId)().replace(/:/g, "")}`;
10471
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
10806
+ const chartId = `records-chart-${(0, import_react75.useId)().replace(/:/g, "")}`;
10807
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
10472
10808
  "div",
10473
10809
  {
10474
10810
  ref,
10475
10811
  "data-chart": chartId,
10476
10812
  style: { height, ...chartVariables(config) },
10477
- className: (0, import_design_system36.cn)(
10813
+ className: (0, import_design_system37.cn)(
10478
10814
  "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
10815
  className
10480
10816
  ),
@@ -10490,27 +10826,27 @@ function ChartTooltipContent({
10490
10826
  className
10491
10827
  }) {
10492
10828
  if (!active || !payload || payload.length === 0) return null;
10493
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
10829
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
10494
10830
  "div",
10495
10831
  {
10496
- className: (0, import_design_system36.cn)(
10832
+ className: (0, import_design_system37.cn)(
10497
10833
  "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
10834
  className
10499
10835
  ),
10500
10836
  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) => {
10837
+ label ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "font-medium", children: label }) : null,
10838
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "grid gap-1.5", children: payload.map((entry, index) => {
10503
10839
  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)(
10840
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
10841
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
10506
10842
  "span",
10507
10843
  {
10508
10844
  className: "h-2.5 w-2.5 shrink-0 rounded-[2px] bg-[--color-swatch]",
10509
10845
  style: { "--color-swatch": entry.color }
10510
10846
  }
10511
10847
  ),
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 })
10848
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "text-muted-foreground", children: config[key]?.label ?? key }),
10849
+ /* @__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
10850
  ] }, key);
10515
10851
  }) })
10516
10852
  ]
@@ -10523,10 +10859,10 @@ function ChartLegendContent({
10523
10859
  className
10524
10860
  }) {
10525
10861
  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) => {
10862
+ 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
10863
  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)(
10864
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
10865
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
10530
10866
  "span",
10531
10867
  {
10532
10868
  className: "h-2 w-2 shrink-0 rounded-[2px] bg-[--color-swatch]",
@@ -10561,24 +10897,24 @@ function isSignatureField(field) {
10561
10897
  }
10562
10898
 
10563
10899
  // 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");
10900
+ var import_react76 = require("react");
10901
+ var import_react77 = require("@ai-matrx/records/react");
10902
+ var import_design_system38 = require("@ai-matrx/design-system");
10903
+ var import_jsx_runtime41 = require("react/jsx-runtime");
10568
10904
  function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, className }) {
10569
- const client = (0, import_react75.useRecordsClient)();
10905
+ const client = (0, import_react77.useRecordsClient)();
10570
10906
  const claimSeed = useSeedGuard();
10571
- const table = (0, import_react75.useTable)(tableId);
10907
+ const table = (0, import_react77.useTable)(tableId);
10572
10908
  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 () => {
10909
+ const fields = (0, import_react77.useFields)(tableId);
10910
+ const [templates, setTemplates] = (0, import_react76.useState)(null);
10911
+ const [error, setError] = (0, import_react76.useState)(null);
10912
+ const [activeId, setActiveId] = (0, import_react76.useState)(activeTemplateId ?? null);
10913
+ const [draftName, setDraftName] = (0, import_react76.useState)("");
10914
+ const [draftBody, setDraftBody] = (0, import_react76.useState)("");
10915
+ const [unresolved, setUnresolved] = (0, import_react76.useState)([]);
10916
+ const [saving, setSaving] = (0, import_react76.useState)(false);
10917
+ const load = (0, import_react76.useCallback)(async () => {
10582
10918
  const held = await client.docTemplates({ table_id: tableId });
10583
10919
  if (!held.ok) {
10584
10920
  setError(held.error);
@@ -10609,10 +10945,10 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10609
10945
  setError(null);
10610
10946
  setTemplates(rows);
10611
10947
  }, [client, tableId, seed, fields.data]);
10612
- (0, import_react74.useEffect)(() => {
10948
+ (0, import_react76.useEffect)(() => {
10613
10949
  void load();
10614
10950
  }, [load]);
10615
- (0, import_react74.useEffect)(() => {
10951
+ (0, import_react76.useEffect)(() => {
10616
10952
  if (!templates || templates.length === 0) return;
10617
10953
  const chosen = templates.find((t) => t.id === (activeTemplateId ?? activeId)) ?? templates[0];
10618
10954
  if (chosen.id !== activeId) setActiveId(chosen.id);
@@ -10620,7 +10956,7 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10620
10956
  setDraftBody(chosen.body);
10621
10957
  onActiveTemplate?.(chosen);
10622
10958
  }, [templates, activeTemplateId]);
10623
- (0, import_react74.useEffect)(() => {
10959
+ (0, import_react76.useEffect)(() => {
10624
10960
  let cancelled = false;
10625
10961
  if (draftBody.trim() === "") {
10626
10962
  setUnresolved([]);
@@ -10650,25 +10986,25 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10650
10986
  setActiveId(saved.data);
10651
10987
  await load();
10652
10988
  }
10653
- if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(RefusalNotice, { error: fields.error, className });
10989
+ if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(RefusalNotice, { error: fields.error, className });
10654
10990
  if (error) {
10655
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
10991
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10656
10992
  RefusalNotice,
10657
10993
  {
10658
10994
  error,
10659
10995
  className,
10660
- actions: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system37.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
10996
+ actions: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
10661
10997
  }
10662
10998
  );
10663
10999
  }
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) });
11000
+ 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
11001
  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") });
11002
+ 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
11003
  }
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,
11004
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: (0, import_design_system38.cn)("flex flex-col gap-2", className), children: [
11005
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex items-center gap-1 overflow-x-auto", role: "group", "aria-label": "Templates", children: [
11006
+ templates.map((t) => /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
11007
+ import_design_system38.Button,
10672
11008
  {
10673
11009
  size: "sm",
10674
11010
  variant: t.id === activeId ? "secondary" : "ghost",
@@ -10680,7 +11016,7 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10680
11016
  },
10681
11017
  children: [
10682
11018
  t.name,
10683
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "ml-1 text-[10px] text-muted-foreground", children: [
11019
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "ml-1 text-[10px] text-muted-foreground", children: [
10684
11020
  "v",
10685
11021
  t.template_version
10686
11022
  ] })
@@ -10688,8 +11024,8 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10688
11024
  },
10689
11025
  t.id
10690
11026
  )),
10691
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
10692
- import_design_system37.Button,
11027
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
11028
+ import_design_system38.Button,
10693
11029
  {
10694
11030
  size: "sm",
10695
11031
  variant: "ghost",
@@ -10701,16 +11037,16 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10701
11037
  children: "New template"
10702
11038
  }
10703
11039
  ),
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" })
11040
+ /* @__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
11041
  ] }),
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" })
11042
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { className: "flex flex-col gap-1", children: [
11043
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_design_system38.Label, { className: "text-xs font-medium", children: "Name" }),
11044
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_design_system38.BasicInput, { value: draftName, onChange: (e) => setDraftName(e.target.value), placeholder: "Agreement" })
10709
11045
  ] }),
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,
11046
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
11047
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "text-xs text-muted-foreground", children: "Insert" }),
11048
+ (fields.data ?? []).map((field) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
11049
+ import_design_system38.Button,
10714
11050
  {
10715
11051
  size: "sm",
10716
11052
  variant: "ghost",
@@ -10721,8 +11057,8 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10721
11057
  field.id
10722
11058
  ))
10723
11059
  ] }),
10724
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
10725
- import_design_system37.BasicTextarea,
11060
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
11061
+ import_design_system38.BasicTextarea,
10726
11062
  {
10727
11063
  rows: 10,
10728
11064
  "aria-label": "Template body",
@@ -10731,28 +11067,28 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10731
11067
  onChange: (e) => setDraftBody(e.target.value)
10732
11068
  }
10733
11069
  ),
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 }),
11070
+ 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: [
11071
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("code", { children: token.raw }),
10736
11072
  " \u2014 ",
10737
11073
  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
11074
+ ] }, 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
11075
  ] });
10740
11076
  }
10741
11077
 
10742
11078
  // 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");
11079
+ var import_react78 = require("react");
11080
+ var import_react79 = require("@ai-matrx/records/react");
11081
+ var import_design_system39 = require("@ai-matrx/design-system");
11082
+ var import_jsx_runtime42 = require("react/jsx-runtime");
10747
11083
  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 () => {
11084
+ const client = (0, import_react79.useRecordsClient)();
11085
+ const [preview, setPreview] = (0, import_react78.useState)(null);
11086
+ const [renders, setRenders] = (0, import_react78.useState)(null);
11087
+ const [showing, setShowing] = (0, import_react78.useState)(null);
11088
+ const [error, setError] = (0, import_react78.useState)(null);
11089
+ const [busy, setBusy] = (0, import_react78.useState)(null);
11090
+ const paper = (0, import_react78.useRef)(null);
11091
+ const load = (0, import_react78.useCallback)(async () => {
10756
11092
  const [body, held] = await Promise.all([
10757
11093
  client.docRenderBody({ template_id: templateId, record_id: recordId }),
10758
11094
  client.docRenders({ record_id: recordId })
@@ -10769,7 +11105,7 @@ function DocRender({ templateId, recordId, filename, onRendered, className }) {
10769
11105
  setPreview(body.data);
10770
11106
  setRenders(held.data.filter((r) => r.template_id === templateId));
10771
11107
  }, [client, templateId, recordId]);
10772
- (0, import_react76.useEffect)(() => {
11108
+ (0, import_react78.useEffect)(() => {
10773
11109
  void load();
10774
11110
  }, [load]);
10775
11111
  async function freeze() {
@@ -10806,22 +11142,22 @@ function DocRender({ templateId, recordId, filename, onRendered, className }) {
10806
11142
  }
10807
11143
  }
10808
11144
  if (error) {
10809
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
11145
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
10810
11146
  RefusalNotice,
10811
11147
  {
10812
11148
  error,
10813
11149
  className,
10814
- actions: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
11150
+ actions: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_design_system39.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
10815
11151
  }
10816
11152
  );
10817
11153
  }
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) });
11154
+ 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
11155
  const frozen = showing ? renders.find((r) => r.id === showing) ?? null : null;
10820
11156
  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,
11157
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: (0, import_design_system39.cn)("flex flex-col gap-2", className), children: [
11158
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center gap-1 text-xs", children: [
11159
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11160
+ import_design_system39.Button,
10825
11161
  {
10826
11162
  size: "sm",
10827
11163
  variant: frozen ? "ghost" : "secondary",
@@ -10830,8 +11166,8 @@ function DocRender({ templateId, recordId, filename, onRendered, className }) {
10830
11166
  children: "As it reads now"
10831
11167
  }
10832
11168
  ),
10833
- renders.map((render) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10834
- import_design_system38.Button,
11169
+ renders.map((render) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11170
+ import_design_system39.Button,
10835
11171
  {
10836
11172
  size: "sm",
10837
11173
  variant: render.id === showing ? "secondary" : "ghost",
@@ -10842,33 +11178,33 @@ function DocRender({ templateId, recordId, filename, onRendered, className }) {
10842
11178
  },
10843
11179
  render.id
10844
11180
  )),
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" })
11181
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "ml-auto flex items-center gap-1", children: [
11182
+ /* @__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" }),
11183
+ /* @__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
11184
  ] })
10849
11185
  ] }),
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." })
11186
+ /* @__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 }),
11187
+ /* @__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
11188
  ] });
10853
11189
  }
10854
11190
 
10855
11191
  // 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");
11192
+ var import_react80 = require("react");
11193
+ var import_react81 = require("@ai-matrx/records/react");
11194
+ var import_design_system40 = require("@ai-matrx/design-system");
11195
+ var import_react82 = require("@ai-matrx/records/react");
11196
+ var import_jsx_runtime43 = require("react/jsx-runtime");
10861
11197
  function SignBlock({ tableId, recordId, render, className }) {
10862
- const client = (0, import_react79.useRecordsClient)();
10863
- const table = (0, import_react80.useTable)(tableId);
11198
+ const client = (0, import_react81.useRecordsClient)();
11199
+ const table = (0, import_react82.useTable)(tableId);
10864
11200
  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 () => {
11201
+ const fields = (0, import_react81.useFields)(tableId);
11202
+ const [signatures, setSignatures] = (0, import_react80.useState)(null);
11203
+ const [verdicts, setVerdicts] = (0, import_react80.useState)({});
11204
+ const [error, setError] = (0, import_react80.useState)(null);
11205
+ const [name, setName] = (0, import_react80.useState)("");
11206
+ const [busy, setBusy] = (0, import_react80.useState)(false);
11207
+ const load = (0, import_react80.useCallback)(async () => {
10872
11208
  const held = await client.docSignatures({ record_id: recordId });
10873
11209
  if (!held.ok) {
10874
11210
  setError(held.error);
@@ -10883,7 +11219,7 @@ function SignBlock({ tableId, recordId, render, className }) {
10883
11219
  }
10884
11220
  setVerdicts(answers);
10885
11221
  }, [client, recordId]);
10886
- (0, import_react78.useEffect)(() => {
11222
+ (0, import_react80.useEffect)(() => {
10887
11223
  void load();
10888
11224
  }, [load]);
10889
11225
  async function sign(field) {
@@ -10903,58 +11239,58 @@ function SignBlock({ tableId, recordId, render, className }) {
10903
11239
  setName("");
10904
11240
  await load();
10905
11241
  }
10906
- if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(RefusalNotice, { error: fields.error, className });
11242
+ if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(RefusalNotice, { error: fields.error, className });
10907
11243
  if (error) {
10908
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11244
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
10909
11245
  RefusalNotice,
10910
11246
  {
10911
11247
  error,
10912
11248
  className,
10913
- actions: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_design_system39.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
11249
+ actions: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system40.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
10914
11250
  }
10915
11251
  );
10916
11252
  }
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) });
11253
+ 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
11254
  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: [
11255
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: (0, import_design_system40.cn)("flex flex-col gap-2", className), children: [
11256
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
11257
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "font-medium text-foreground", children: "Signatures" }),
11258
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { children: [
10923
11259
  signatures.length,
10924
11260
  " on this record"
10925
11261
  ] })
10926
11262
  ] }),
10927
- signatures.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("ul", { className: "flex flex-col gap-1", children: signatures.map((signature) => {
11263
+ signatures.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("ul", { className: "flex flex-col gap-1", children: signatures.map((signature) => {
10928
11264
  const verdict = verdicts[signature.id];
10929
11265
  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: [
11266
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("li", { className: "rounded border px-2 py-1.5 text-xs", children: [
11267
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-center gap-2", children: [
11268
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "font-medium", children: signature.signer_name }),
11269
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-muted-foreground", children: signature.field_key }),
11270
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-muted-foreground", children: new Date(signature.signed_at).toLocaleString() }),
11271
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "ml-auto font-mono text-[10px] text-muted-foreground", children: [
10936
11272
  "v",
10937
11273
  signature.document_version,
10938
11274
  " \xB7 ",
10939
11275
  signature.document_hash.slice(0, 12)
10940
11276
  ] })
10941
11277
  ] }),
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 ?? "") })
11278
+ /* @__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
11279
  ] }, signature.id);
10944
11280
  }) }) : 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: [
11281
+ !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
11282
  "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" }),
11283
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("code", { children: "signature" }),
10948
11284
  " \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) => {
11285
+ ] }) : !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
11286
  const already = signatures.find((s) => s.field_key === field.key);
10951
11287
  if (already) {
10952
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("p", { className: "text-xs text-muted-foreground", children: [
11288
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("p", { className: "text-xs text-muted-foreground", children: [
10953
11289
  fieldName(field),
10954
11290
  " 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
11291
  ] }, field.id);
10956
11292
  }
10957
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
11293
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
10958
11294
  "form",
10959
11295
  {
10960
11296
  className: "flex items-center gap-1",
@@ -10963,8 +11299,8 @@ function SignBlock({ tableId, recordId, render, className }) {
10963
11299
  if (name.trim() !== "") void sign(field);
10964
11300
  },
10965
11301
  children: [
10966
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
10967
- import_design_system39.BasicInput,
11302
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
11303
+ import_design_system40.BasicInput,
10968
11304
  {
10969
11305
  className: "h-8 w-56 text-xs",
10970
11306
  "aria-label": `Sign ${fieldName(field)}`,
@@ -10973,8 +11309,8 @@ function SignBlock({ tableId, recordId, render, className }) {
10973
11309
  onChange: (e) => setName(e.target.value)
10974
11310
  }
10975
11311
  ),
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: [
11312
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system40.Button, { size: "sm", type: "submit", disabled: busy || name.trim() === "", children: "Sign" }),
11313
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
10978
11314
  "seals version ",
10979
11315
  render.template_version,
10980
11316
  " \xB7 ",
@@ -10990,32 +11326,32 @@ function SignBlock({ tableId, recordId, render, className }) {
10990
11326
  }
10991
11327
 
10992
11328
  // 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 = {
11329
+ var import_react83 = require("react");
11330
+ var import_react84 = require("@ai-matrx/records/react");
11331
+ var import_design_system41 = require("@ai-matrx/design-system");
11332
+ var import_jsx_runtime44 = require("react/jsx-runtime");
11333
+ var CADENCE_WORDS2 = {
10998
11334
  instant: "as it happens",
10999
11335
  hourly: "hourly summary",
11000
11336
  daily: "daily summary",
11001
11337
  weekly: "weekly summary"
11002
11338
  };
11003
- var CHANNEL_WORDS2 = {
11339
+ var CHANNEL_WORDS3 = {
11004
11340
  in_app: "in the app",
11005
11341
  email: "by email",
11006
11342
  sms: "by text"
11007
11343
  };
11008
11344
  function NotifyRuleEditor({ tableId, seed, className }) {
11009
- const client = (0, import_react82.useRecordsClient)();
11345
+ const client = (0, import_react84.useRecordsClient)();
11010
11346
  const host = useRecordsUi();
11011
- const table = (0, import_react82.useTable)(tableId);
11347
+ const table = (0, import_react84.useTable)(tableId);
11012
11348
  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 () => {
11349
+ const [subscriptions, setSubscriptions] = (0, import_react83.useState)(null);
11350
+ const [cadences, setCadences] = (0, import_react83.useState)([]);
11351
+ const [views, setViews] = (0, import_react83.useState)(null);
11352
+ const [error, setError] = (0, import_react83.useState)(null);
11353
+ const [busy, setBusy] = (0, import_react83.useState)(false);
11354
+ const load = (0, import_react83.useCallback)(async () => {
11019
11355
  const [held, offered] = await Promise.all([
11020
11356
  // THE PERSON'S OWN DOOR, not the notifier's. It answers what is addressed
11021
11357
  // to them plus — only where they hold admin on this Table — anyone's over
@@ -11035,10 +11371,10 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11035
11371
  if (host.savedViews) setViews(await host.savedViews());
11036
11372
  else setViews(null);
11037
11373
  }, [client, host, tableId]);
11038
- (0, import_react81.useEffect)(() => {
11374
+ (0, import_react83.useEffect)(() => {
11039
11375
  void load();
11040
11376
  }, [load]);
11041
- const write = (0, import_react81.useCallback)(
11377
+ const write = (0, import_react83.useCallback)(
11042
11378
  async (spec) => {
11043
11379
  const declared = await client.subscriptionDeclare({
11044
11380
  table_id: tableId,
@@ -11063,7 +11399,7 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11063
11399
  },
11064
11400
  [client, tableId]
11065
11401
  );
11066
- (0, import_react81.useEffect)(() => {
11402
+ (0, import_react83.useEffect)(() => {
11067
11403
  if (!subscriptions || !seed || seed.length === 0) return;
11068
11404
  const missing = seed.filter((s) => !subscriptions.some((held) => held.name === s.name));
11069
11405
  if (missing.length === 0) return;
@@ -11077,7 +11413,7 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11077
11413
  async function subscribe(viewId, viewName, cadence, channel, schedule, quiet) {
11078
11414
  setBusy(true);
11079
11415
  const ok = await write({
11080
- name: `${viewName} \u2014 ${CADENCE_WORDS[cadence] ?? cadence}`,
11416
+ name: `${viewName} \u2014 ${CADENCE_WORDS2[cadence] ?? cadence}`,
11081
11417
  savedViewId: viewId,
11082
11418
  cadence,
11083
11419
  channel,
@@ -11098,45 +11434,45 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11098
11434
  await load();
11099
11435
  }
11100
11436
  if (error) {
11101
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
11437
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11102
11438
  RefusalNotice,
11103
11439
  {
11104
11440
  error,
11105
11441
  className,
11106
- actions: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system40.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
11442
+ actions: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_design_system41.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
11107
11443
  }
11108
11444
  );
11109
11445
  }
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: [
11446
+ 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) });
11447
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: (0, import_design_system41.cn)("flex flex-col gap-2", className), children: [
11448
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
11449
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "font-medium text-foreground", children: "Tell me when" }),
11450
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { children: [
11115
11451
  subscriptions.length,
11116
11452
  " subscription",
11117
11453
  subscriptions.length === 1 ? "" : "s"
11118
11454
  ] })
11119
11455
  ] }),
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: [
11456
+ 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: [
11457
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "truncate font-medium", children: held.name }),
11458
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-muted-foreground", children: CADENCE_WORDS2[held.cadence] ?? held.cadence }),
11459
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-muted-foreground", children: CHANNEL_WORDS3[held.channel] ?? held.channel }),
11460
+ held.schedule ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-muted-foreground", children: held.schedule }) : null,
11461
+ held.next_digest_at ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "text-muted-foreground", children: [
11126
11462
  "next ",
11127
11463
  new Date(held.next_digest_at).toLocaleString()
11128
11464
  ] }) : null,
11129
- held.quiet_hours ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "text-muted-foreground", children: [
11465
+ held.quiet_hours ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "text-muted-foreground", children: [
11130
11466
  "quiet ",
11131
11467
  held.quiet_hours.start,
11132
11468
  "\u2013",
11133
11469
  held.quiet_hours.end
11134
11470
  ] }) : 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,
11471
+ 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,
11472
+ 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,
11473
+ 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,
11474
+ rights.write ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11475
+ import_design_system41.Button,
11140
11476
  {
11141
11477
  size: "sm",
11142
11478
  variant: "ghost",
@@ -11147,7 +11483,7 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11147
11483
  }
11148
11484
  ) : null
11149
11485
  ] }, 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)(
11486
+ 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
11487
  "form",
11152
11488
  {
11153
11489
  className: "flex flex-wrap items-center gap-1",
@@ -11165,10 +11501,10 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11165
11501
  if (view) void subscribe(view, name, cadence, channel, schedule, quiet);
11166
11502
  },
11167
11503
  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)(
11504
+ /* @__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)) }),
11505
+ /* @__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)) }),
11506
+ /* @__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)) }),
11507
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11172
11508
  "input",
11173
11509
  {
11174
11510
  name: "schedule",
@@ -11177,8 +11513,8 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11177
11513
  className: "h-7 w-28 rounded border bg-background px-1 text-xs"
11178
11514
  }
11179
11515
  ),
11180
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-xs text-muted-foreground", children: "not between" }),
11181
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
11516
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-xs text-muted-foreground", children: "not between" }),
11517
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11182
11518
  "input",
11183
11519
  {
11184
11520
  name: "quiet_start",
@@ -11187,8 +11523,8 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11187
11523
  className: "h-7 rounded border bg-background px-1 text-xs"
11188
11524
  }
11189
11525
  ),
11190
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-xs text-muted-foreground", children: "and" }),
11191
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
11526
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-xs text-muted-foreground", children: "and" }),
11527
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11192
11528
  "input",
11193
11529
  {
11194
11530
  name: "quiet_end",
@@ -11197,21 +11533,21 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11197
11533
  className: "h-7 rounded border bg-background px-1 text-xs"
11198
11534
  }
11199
11535
  ),
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." })
11536
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_design_system41.Button, { size: "sm", type: "submit", disabled: busy, children: "Tell me" }),
11537
+ /* @__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
11538
  ]
11203
11539
  }
11204
- ) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-xs text-muted-foreground", children: rights.why("write") })
11540
+ ) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "text-xs text-muted-foreground", children: rights.why("write") })
11205
11541
  ] });
11206
11542
  }
11207
11543
 
11208
11544
  // src/ChartBlock.tsx
11209
- var import_react83 = require("react");
11545
+ var import_react85 = require("react");
11210
11546
  var import_recharts = require("recharts");
11211
11547
  var import_records7 = require("@ai-matrx/records");
11212
11548
  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");
11549
+ var import_design_system42 = require("@ai-matrx/design-system");
11550
+ var import_jsx_runtime45 = require("react/jsx-runtime");
11215
11551
  function pretty(n) {
11216
11552
  return Number.isInteger(n) ? n.toLocaleString() : n.toLocaleString(void 0, { maximumFractionDigits: 2 });
11217
11553
  }
@@ -11231,7 +11567,7 @@ function ChartBlock({ block, subject, className }) {
11231
11567
  const measures = block.measures && block.measures.length > 0 ? block.measures : [{ op: "count" }];
11232
11568
  const primary = (0, import_records7.measureKey)(measures[0]);
11233
11569
  const series = [primary];
11234
- const points = (0, import_react83.useMemo)(() => {
11570
+ const points = (0, import_react85.useMemo)(() => {
11235
11571
  if (kind === "stuck") return [];
11236
11572
  const rows = block.rows ?? [];
11237
11573
  return rows.map((row) => ({
@@ -11243,7 +11579,7 @@ function ChartBlock({ block, subject, className }) {
11243
11579
  n: row.row_count
11244
11580
  }));
11245
11581
  }, [block.rows, kind, series.join("|")]);
11246
- const config = (0, import_react83.useMemo)(() => {
11582
+ const config = (0, import_react85.useMemo)(() => {
11247
11583
  const out = {};
11248
11584
  series.forEach((key, index) => {
11249
11585
  out[key] = {
@@ -11267,18 +11603,18 @@ function ChartBlock({ block, subject, className }) {
11267
11603
  label: point.label === "All records" ? block.title : `${block.title} \xB7 ${point.label}`
11268
11604
  });
11269
11605
  } : 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: [
11606
+ 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: [
11607
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("figcaption", { className: "flex items-baseline gap-2 text-xs", children: [
11608
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "truncate font-medium", children: block.title || CHART_KIND_LABEL[kind] }),
11609
+ /* @__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 ") }),
11610
+ 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
11611
  pretty(block.ms),
11276
11612
  " ms"
11277
11613
  ] }) : null
11278
11614
  ] }),
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 })
11615
+ 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: [
11616
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Drawing, { kind, points, series, config, onDrill: drill }),
11617
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Values, { points, measure: primary, config, onDrill: drill })
11282
11618
  ] }) })
11283
11619
  ] });
11284
11620
  }
@@ -11289,16 +11625,16 @@ function BigNumber({
11289
11625
  }) {
11290
11626
  const total = points.reduce((sum, p) => sum + (p.values[measure] ?? 0), 0);
11291
11627
  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: [
11628
+ const body = /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
11629
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "text-2xl font-semibold tabular-nums", children: pretty(total) }),
11630
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
11295
11631
  "from ",
11296
11632
  records.toLocaleString(),
11297
11633
  " records"
11298
11634
  ] })
11299
11635
  ] });
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)(
11636
+ if (!onDrill || !points[0]) return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "flex items-baseline gap-2 px-1 py-2", children: body });
11637
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11302
11638
  "button",
11303
11639
  {
11304
11640
  type: "button",
@@ -11314,19 +11650,19 @@ function Values({
11314
11650
  config,
11315
11651
  onDrill
11316
11652
  }) {
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)(
11653
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("ul", { className: "flex flex-wrap gap-x-2 gap-y-0.5", children: points.map((point) => {
11654
+ const text = /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
11655
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11320
11656
  "span",
11321
11657
  {
11322
11658
  className: "h-2 w-2 shrink-0 rounded-[2px]",
11323
11659
  style: { background: String(config[point.label]?.color ?? SERIES_COLORS[0]) }
11324
11660
  }
11325
11661
  ),
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) })
11662
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "truncate", children: point.label }),
11663
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "tabular-nums text-muted-foreground", children: pretty(point.values[measure] ?? 0) })
11328
11664
  ] });
11329
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("li", { className: "min-w-0", children: onDrill ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11665
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("li", { className: "min-w-0", children: onDrill ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11330
11666
  "button",
11331
11667
  {
11332
11668
  type: "button",
@@ -11334,7 +11670,7 @@ function Values({
11334
11670
  onClick: () => onDrill(point),
11335
11671
  children: text
11336
11672
  }
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);
11673
+ ) : /* @__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
11674
  }) });
11339
11675
  }
11340
11676
  function GroupTable({
@@ -11342,8 +11678,8 @@ function GroupTable({
11342
11678
  series,
11343
11679
  onDrill
11344
11680
  }) {
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)(
11681
+ 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: [
11682
+ /* @__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
11683
  "button",
11348
11684
  {
11349
11685
  type: "button",
@@ -11352,29 +11688,29 @@ function GroupTable({
11352
11688
  children: point.label
11353
11689
  }
11354
11690
  ) : 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 })
11691
+ 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)),
11692
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("td", { className: "py-0.5 pl-2 text-right tabular-nums text-muted-foreground", children: point.n })
11357
11693
  ] }, point.label)) }) });
11358
11694
  }
11359
11695
  function StuckList({ rows }) {
11360
11696
  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." });
11697
+ 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
11698
  }
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%]" })
11699
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("table", { className: "w-full table-fixed text-xs", children: [
11700
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("colgroup", { children: [
11701
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("col", { className: "w-[45%]" }),
11702
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("col", { className: "w-[33%]" }),
11703
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("col", { className: "w-[22%]" })
11368
11704
  ] }),
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" })
11705
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("thead", { className: "sr-only", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("tr", { children: [
11706
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("th", { children: "Record" }),
11707
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("th", { children: "Where it is" }),
11708
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("th", { children: "Days unchanged" })
11373
11709
  ] }) }),
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)(
11710
+ /* @__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: [
11711
+ /* @__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) }),
11712
+ /* @__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" }),
11713
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
11378
11714
  "td",
11379
11715
  {
11380
11716
  className: "whitespace-nowrap py-0.5 text-right tabular-nums",
@@ -11424,12 +11760,12 @@ function Drawing({
11424
11760
  axisLine: false,
11425
11761
  tickFormatter: compactTick
11426
11762
  };
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;
11763
+ const tooltip = /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.Tooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ChartTooltipContent, { config }), cursor: false });
11764
+ 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
11765
  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: [
11766
+ 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
11767
  tooltip,
11432
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11768
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11433
11769
  import_recharts.Pie,
11434
11770
  {
11435
11771
  data,
@@ -11439,19 +11775,19 @@ function Drawing({
11439
11775
  outerRadius: 58,
11440
11776
  isAnimationActive: false,
11441
11777
  ...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))
11778
+ 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
11779
  }
11444
11780
  )
11445
11781
  ] }) });
11446
11782
  }
11447
11783
  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 }),
11784
+ 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: [
11785
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.CartesianGrid, { vertical: false }),
11786
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.XAxis, { dataKey: "label", ...axis }),
11787
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.YAxis, { width: 44, ...axis }),
11452
11788
  tooltip,
11453
11789
  legend,
11454
- series.map((key) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11790
+ series.map((key) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11455
11791
  import_recharts.Line,
11456
11792
  {
11457
11793
  type: "monotone",
@@ -11467,7 +11803,7 @@ function Drawing({
11467
11803
  ] }) });
11468
11804
  }
11469
11805
  const horizontal = kind === "bar";
11470
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartFrame, { config, height: HEIGHT, children: (width) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
11806
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ChartFrame, { config, height: HEIGHT, children: (width) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
11471
11807
  import_recharts.BarChart,
11472
11808
  {
11473
11809
  width,
@@ -11476,17 +11812,17 @@ function Drawing({
11476
11812
  layout: horizontal ? "vertical" : "horizontal",
11477
11813
  margin: { top: 6, right: 6, bottom: 0, left: 0 },
11478
11814
  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 })
11815
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.CartesianGrid, { vertical: horizontal, horizontal: !horizontal }),
11816
+ horizontal ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
11817
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.XAxis, { type: "number", ...axis }),
11818
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.YAxis, { type: "category", dataKey: "label", width: 88, ...axis })
11819
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
11820
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.XAxis, { dataKey: "label", ...axis }),
11821
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_recharts.YAxis, { width: 44, ...axis })
11486
11822
  ] }),
11487
11823
  tooltip,
11488
11824
  legend,
11489
- series.map((key, index) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
11825
+ series.map((key, index) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11490
11826
  import_recharts.Bar,
11491
11827
  {
11492
11828
  dataKey: key,
@@ -11494,7 +11830,7 @@ function Drawing({
11494
11830
  isAnimationActive: false,
11495
11831
  fill: `var(--color-${key})`,
11496
11832
  ...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
11833
+ 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
11834
  },
11499
11835
  key
11500
11836
  ))
@@ -11504,24 +11840,25 @@ function Drawing({
11504
11840
  }
11505
11841
 
11506
11842
  // 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");
11843
+ var import_react86 = require("react");
11844
+ var import_react87 = require("@ai-matrx/records/react");
11845
+ var import_design_system43 = require("@ai-matrx/design-system");
11846
+ var import_jsx_runtime46 = require("react/jsx-runtime");
11511
11847
  function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11512
- const client = (0, import_react85.useRecordsClient)();
11848
+ const client = (0, import_react87.useRecordsClient)();
11513
11849
  const host = useRecordsUi();
11514
- const table = (0, import_react85.useTable)(tableId);
11850
+ const table = (0, import_react87.useTable)(tableId);
11515
11851
  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 () => {
11852
+ const fields = (0, import_react87.useFields)(tableId);
11853
+ const [boards, setBoards] = (0, import_react86.useState)(null);
11854
+ const [error, setError] = (0, import_react86.useState)(null);
11855
+ const [activeId, setActiveId] = (0, import_react86.useState)(activeDashboardId ?? null);
11856
+ const [run, setRun] = (0, import_react86.useState)(null);
11857
+ const [running, setRunning] = (0, import_react86.useState)(false);
11858
+ const [question, setQuestion] = (0, import_react86.useState)("");
11859
+ const [asking, setAsking] = (0, import_react86.useState)(false);
11860
+ const [scheduling, setScheduling] = (0, import_react86.useState)(false);
11861
+ const load = (0, import_react86.useCallback)(async () => {
11525
11862
  const answered = await client.dashboards({ table_id: tableId });
11526
11863
  if (!answered.ok) {
11527
11864
  setError(answered.error);
@@ -11530,17 +11867,17 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11530
11867
  setError(null);
11531
11868
  setBoards(answered.data.map(dashboardFromSummary));
11532
11869
  }, [client, tableId]);
11533
- (0, import_react84.useEffect)(() => {
11870
+ (0, import_react86.useEffect)(() => {
11534
11871
  void load();
11535
11872
  }, [load]);
11536
- (0, import_react84.useEffect)(() => {
11873
+ (0, import_react86.useEffect)(() => {
11537
11874
  if (!boards || boards.length === 0) return;
11538
11875
  const chosen = boards.find((d) => d.id === (activeDashboardId ?? activeId)) ?? boards[0];
11539
11876
  if (chosen.id !== activeId) setActiveId(chosen.id);
11540
11877
  }, [boards, activeDashboardId]);
11541
- const board = (0, import_react84.useMemo)(() => boards?.find((d) => d.id === activeId) ?? null, [boards, activeId]);
11878
+ const board = (0, import_react86.useMemo)(() => boards?.find((d) => d.id === activeId) ?? null, [boards, activeId]);
11542
11879
  const filterKey = JSON.stringify(filter ?? {});
11543
- (0, import_react84.useEffect)(() => {
11880
+ (0, import_react86.useEffect)(() => {
11544
11881
  if (!activeId) {
11545
11882
  setRun(null);
11546
11883
  return;
@@ -11558,7 +11895,7 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11558
11895
  cancelled = true;
11559
11896
  };
11560
11897
  }, [client, activeId, filterKey]);
11561
- const declare2 = (0, import_react84.useCallback)(
11898
+ const declare2 = (0, import_react86.useCallback)(
11562
11899
  async (next, blocks) => {
11563
11900
  const written = await client.dashboardDeclare(
11564
11901
  dashboardDeclareArgs({ ...next, blocks }, tableId)
@@ -11604,7 +11941,7 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11604
11941
  ]
11605
11942
  );
11606
11943
  }
11607
- const refresh = (0, import_react84.useCallback)(async () => {
11944
+ const refresh = (0, import_react86.useCallback)(async () => {
11608
11945
  if (!activeId) return;
11609
11946
  setRunning(true);
11610
11947
  const again = await client.dashboardRun({
@@ -11645,20 +11982,20 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11645
11982
  }
11646
11983
  }
11647
11984
  if (error) {
11648
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11985
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
11649
11986
  RefusalNotice,
11650
11987
  {
11651
11988
  error,
11652
11989
  className,
11653
- actions: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_design_system42.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
11990
+ actions: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_design_system43.Button, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
11654
11991
  }
11655
11992
  );
11656
11993
  }
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,
11994
+ 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) });
11995
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: (0, import_design_system43.cn)("flex min-h-0 flex-col gap-2", className), children: [
11996
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Dashboards", children: [
11997
+ boards.map((d) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
11998
+ import_design_system43.Button,
11662
11999
  {
11663
12000
  size: "sm",
11664
12001
  variant: d.id === activeId ? "secondary" : "ghost",
@@ -11668,10 +12005,10 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11668
12005
  },
11669
12006
  d.id
11670
12007
  )),
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,
12008
+ rights.admin ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_design_system43.Button, { size: "sm", variant: "ghost", onClick: () => void create(), children: "New dashboard" }) : null,
12009
+ board ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "ml-auto flex items-center gap-1", children: [
12010
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
12011
+ import_design_system43.Button,
11675
12012
  {
11676
12013
  size: "sm",
11677
12014
  variant: "ghost",
@@ -11680,13 +12017,31 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11680
12017
  children: running ? "Asking" : "Refresh"
11681
12018
  }
11682
12019
  ),
11683
- rights.admin ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_design_system42.Button, { size: "sm", variant: "ghost", onClick: () => void remove(board), children: "Delete" }) : null
12020
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
12021
+ import_design_system43.Button,
12022
+ {
12023
+ size: "sm",
12024
+ variant: scheduling ? "secondary" : "ghost",
12025
+ onClick: () => setScheduling((v) => !v),
12026
+ children: scheduling ? "Done" : "Send on a schedule"
12027
+ }
12028
+ ),
12029
+ rights.admin ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_design_system43.Button, { size: "sm", variant: "ghost", onClick: () => void remove(board), children: "Delete" }) : null
11684
12030
  ] }) : null
11685
12031
  ] }),
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,
12032
+ board && scheduling ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
12033
+ DigestScheduler,
12034
+ {
12035
+ tableId,
12036
+ subjectName: board.name,
12037
+ ...filter ? { filters: filter } : {},
12038
+ onClose: () => setScheduling(false)
12039
+ }
12040
+ ) : null,
12041
+ board ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex flex-col gap-1", children: [
12042
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-1", children: [
12043
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
12044
+ import_design_system43.BasicInput,
11690
12045
  {
11691
12046
  value: question,
11692
12047
  "aria-label": "Ask for a change to this dashboard",
@@ -11699,15 +12054,15 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11699
12054
  className: "h-8 min-w-0 flex-1 text-xs"
11700
12055
  }
11701
12056
  ),
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" })
12057
+ /* @__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
12058
  ] }),
11704
- !host.onReask ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: "text-xs text-muted-foreground", children: NO_REASK_REASON }) : null
12059
+ !host.onReask ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "text-xs text-muted-foreground", children: NO_REASK_REASON }) : null
11705
12060
  ] }) : 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)(
12061
+ !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: [
12062
+ /* @__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: [
12063
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ChartBlock, { block, subject: tableId }),
12064
+ rights.admin && board.blocks[index] ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-1 text-xs", children: [
12065
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
11711
12066
  "select",
11712
12067
  {
11713
12068
  "aria-label": `Shape of ${block.title}`,
@@ -11719,11 +12074,11 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11719
12074
  (b, i) => i === index ? { ...b, kind: e.target.value } : b
11720
12075
  )
11721
12076
  ),
11722
- children: CHART_KINDS.map((kind) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("option", { value: kind, children: CHART_KIND_LABEL[kind] }, kind))
12077
+ children: CHART_KINDS.map((kind) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: kind, children: CHART_KIND_LABEL[kind] }, kind))
11723
12078
  }
11724
12079
  ),
11725
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
11726
- import_design_system42.Button,
12080
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
12081
+ import_design_system43.Button,
11727
12082
  {
11728
12083
  size: "sm",
11729
12084
  variant: "ghost",
@@ -11736,17 +12091,17 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11736
12091
  )
11737
12092
  ] }) : null
11738
12093
  ] }, `${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
12094
+ !host.openRecords ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "text-xs text-muted-foreground", children: NO_OPEN_RECORDS_REASON }) : null
11740
12095
  ] })
11741
12096
  ] });
11742
12097
  }
11743
12098
 
11744
12099
  // src/FormsPanel.tsx
11745
- var import_react86 = require("react");
11746
- var import_react87 = require("@ai-matrx/records/react");
12100
+ var import_react88 = require("react");
12101
+ var import_react89 = require("@ai-matrx/records/react");
11747
12102
  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");
12103
+ var import_design_system44 = require("@ai-matrx/design-system");
12104
+ var import_jsx_runtime47 = require("react/jsx-runtime");
11750
12105
  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
12106
  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
12107
  function formSuggestion(tableName2) {
@@ -11754,16 +12109,16 @@ function formSuggestion(tableName2) {
11754
12109
  return `Make me a form that collects new ${subject} entries and tells me when somebody answers.`;
11755
12110
  }
11756
12111
  function FormsPanel({ tableId, className }) {
11757
- const client = (0, import_react87.useRecordsClient)();
12112
+ const client = (0, import_react89.useRecordsClient)();
11758
12113
  const host = useRecordsUi();
11759
- const table = (0, import_react87.useTable)(tableId);
12114
+ const table = (0, import_react89.useTable)(tableId);
11760
12115
  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 () => {
12116
+ const [forms, setForms] = (0, import_react88.useState)(null);
12117
+ const [error, setError] = (0, import_react88.useState)(null);
12118
+ const [busy, setBusy] = (0, import_react88.useState)(null);
12119
+ const [copied, setCopied] = (0, import_react88.useState)(null);
12120
+ const [building, setBuilding] = (0, import_react88.useState)(false);
12121
+ const load = (0, import_react88.useCallback)(async () => {
11767
12122
  const answered = await client.forms({ table_id: tableId });
11768
12123
  if (!answered.ok) {
11769
12124
  setError(answered.error);
@@ -11773,10 +12128,10 @@ function FormsPanel({ tableId, className }) {
11773
12128
  setError(null);
11774
12129
  setForms(answered.data);
11775
12130
  }, [client, tableId]);
11776
- (0, import_react86.useEffect)(() => {
12131
+ (0, import_react88.useEffect)(() => {
11777
12132
  void load();
11778
12133
  }, [load]);
11779
- const toggle = (0, import_react86.useCallback)(
12134
+ const toggle = (0, import_react88.useCallback)(
11780
12135
  async (form) => {
11781
12136
  setBusy(form.form_id);
11782
12137
  const wanted = form.published_at === null || form.closed_at !== null;
@@ -11790,8 +12145,8 @@ function FormsPanel({ tableId, className }) {
11790
12145
  },
11791
12146
  [client, load]
11792
12147
  );
11793
- const [shown, setShown] = (0, import_react86.useState)(null);
11794
- const copy = (0, import_react86.useCallback)(async (url, formId) => {
12148
+ const [shown, setShown] = (0, import_react88.useState)(null);
12149
+ const copy = (0, import_react88.useCallback)(async (url, formId) => {
11795
12150
  try {
11796
12151
  await navigator.clipboard.writeText(url);
11797
12152
  setCopied(formId);
@@ -11801,17 +12156,17 @@ function FormsPanel({ tableId, className }) {
11801
12156
  setShown(url);
11802
12157
  }
11803
12158
  }, []);
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) });
12159
+ 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
12160
  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
12161
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("section", { className: (0, import_design_system44.cn)("flex flex-col gap-3", className), children: [
12162
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("header", { className: "flex items-center gap-2", children: [
12163
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("h3", { className: "text-sm font-medium", children: "Forms" }),
12164
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "text-xs text-muted-foreground", children: forms.length === 0 ? "none yet" : `${forms.length}` }),
12165
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "flex-1" }),
12166
+ 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
12167
  ] }),
11813
- error ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(RefusalNotice, { error }) : null,
11814
- building ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
12168
+ error ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(RefusalNotice, { error }) : null,
12169
+ building ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
11815
12170
  FormBuilder,
11816
12171
  {
11817
12172
  tableId,
@@ -11820,7 +12175,7 @@ function FormsPanel({ tableId, className }) {
11820
12175
  }
11821
12176
  }
11822
12177
  ) : null,
11823
- forms.length === 0 && !building ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
12178
+ forms.length === 0 && !building ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
11824
12179
  BuildOrAsk,
11825
12180
  {
11826
12181
  mayBuild: rights.structure,
@@ -11838,36 +12193,36 @@ function FormsPanel({ tableId, className }) {
11838
12193
  children: WHAT_A_FORM_IS
11839
12194
  }
11840
12195
  ) : null,
11841
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("ul", { className: "flex flex-col gap-2", children: forms.map((form) => {
12196
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("ul", { className: "flex flex-col gap-2", children: forms.map((form) => {
11842
12197
  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 })
12198
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("li", { className: "rounded-md border p-2.5", children: [
12199
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-2", children: [
12200
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: form.title ?? form.slug }),
12201
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_design_system44.Badge, { variant: form.state === "open" ? "default" : "secondary", children: form.state })
11847
12202
  ] }),
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 }),
12203
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "mt-0.5 text-xs text-muted-foreground", children: FORM_STATE_WORDS[form.state] }),
12204
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("p", { className: "mt-1.5 text-xs", children: [
12205
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "font-medium", children: form.in_table }),
11851
12206
  " in the table",
11852
- form.held > 0 ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
12207
+ form.held > 0 ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
11853
12208
  " \xB7 ",
11854
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "font-medium", children: form.held }),
12209
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "font-medium", children: form.held }),
11855
12210
  " waiting for someone"
11856
12211
  ] }) : null,
11857
- form.rejected > 0 ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
12212
+ form.rejected > 0 ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
11858
12213
  " \xB7 ",
11859
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "font-medium", children: form.rejected }),
12214
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "font-medium", children: form.rejected }),
11860
12215
  " turned away"
11861
12216
  ] }) : null,
11862
- form.submission_cap !== null ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "text-muted-foreground", children: [
12217
+ form.submission_cap !== null ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "text-muted-foreground", children: [
11863
12218
  " \xB7 stops at ",
11864
12219
  form.submission_cap
11865
12220
  ] }) : null
11866
12221
  ] }),
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,
12222
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "mt-2 flex flex-wrap items-center gap-1.5", children: [
12223
+ 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,
12224
+ rights.structure ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
12225
+ import_design_system44.Button,
11871
12226
  {
11872
12227
  size: "sm",
11873
12228
  variant: "ghost",
@@ -11877,23 +12232,23 @@ function FormsPanel({ tableId, className }) {
11877
12232
  }
11878
12233
  ) : null
11879
12234
  ] }),
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: [
12235
+ 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
12236
  "This browser would not let the page copy for you, so here it is to copy by hand:",
11882
12237
  " ",
11883
12238
  url
11884
12239
  ] }) : null
11885
12240
  ] }, form.form_id);
11886
12241
  }) }),
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
12242
+ !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
12243
  ] });
11889
12244
  }
11890
12245
 
11891
12246
  // src/BookingBuilder.tsx
11892
- var import_react88 = require("react");
11893
- var import_react89 = require("@ai-matrx/records/react");
12247
+ var import_react90 = require("react");
12248
+ var import_react91 = require("@ai-matrx/records/react");
11894
12249
  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");
12250
+ var import_design_system45 = require("@ai-matrx/design-system");
12251
+ var import_jsx_runtime48 = require("react/jsx-runtime");
11897
12252
  var STORE_ANSWERS_THESE = ["slot", "status", "booked_with"];
11898
12253
  var DAYS = [
11899
12254
  { weekday: 1, label: "Mon" },
@@ -11917,36 +12272,36 @@ function draftWindows(availability) {
11917
12272
  });
11918
12273
  }
11919
12274
  function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
11920
- const client = (0, import_react89.useRecordsClient)();
12275
+ const client = (0, import_react91.useRecordsClient)();
11921
12276
  const host = useRecordsUi();
11922
- const table = (0, import_react89.useTable)(tableId);
12277
+ const table = (0, import_react91.useTable)(tableId);
11923
12278
  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);
12279
+ const fields = (0, import_react91.useFields)(tableId);
12280
+ const [existing, setExisting] = (0, import_react90.useState)(null);
12281
+ const [loaded, setLoaded] = (0, import_react90.useState)(false);
12282
+ const [error, setError] = (0, import_react90.useState)(null);
12283
+ const [saving, setSaving] = (0, import_react90.useState)(false);
12284
+ const [publishing, setPublishing] = (0, import_react90.useState)(false);
12285
+ const [copied, setCopied] = (0, import_react90.useState)(false);
12286
+ const [title, setTitle] = (0, import_react90.useState)("");
12287
+ const [minutes, setMinutes] = (0, import_react90.useState)(30);
12288
+ const [buffer, setBuffer] = (0, import_react90.useState)(0);
12289
+ const [lead, setLead] = (0, import_react90.useState)(120);
12290
+ const [perDay, setPerDay] = (0, import_react90.useState)(8);
12291
+ const [days, setDays] = (0, import_react90.useState)(30);
12292
+ const [windows, setWindows] = (0, import_react90.useState)(() => draftWindows(null));
12293
+ const [asked, setAsked] = (0, import_react90.useState)([]);
12294
+ const [confirmation, setConfirmation] = (0, import_react90.useState)("");
12295
+ const [offer, setOffer] = (0, import_react90.useState)(null);
12296
+ const [formId, setFormId] = (0, import_react90.useState)(bookingId ?? null);
11942
12297
  const publicOrigin = host.publicOrigin ?? (typeof window === "undefined" ? "" : window.location.origin);
11943
- const askable = (0, import_react88.useMemo)(
12298
+ const askable = (0, import_react90.useMemo)(
11944
12299
  () => (fields.data ?? []).filter(
11945
12300
  (f) => !STORE_ANSWERS_THESE.includes(f.key)
11946
12301
  ),
11947
12302
  [fields.data]
11948
12303
  );
11949
- const load = (0, import_react88.useCallback)(async () => {
12304
+ const load = (0, import_react90.useCallback)(async () => {
11950
12305
  const answered = await client.bookings({ table_id: tableId });
11951
12306
  if (!answered.ok) {
11952
12307
  setError(answered.error);
@@ -11958,18 +12313,18 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
11958
12313
  setLoaded(true);
11959
12314
  if (mine) setFormId(mine.form_id);
11960
12315
  }, [client, tableId, bookingId]);
11961
- (0, import_react88.useEffect)(() => {
12316
+ (0, import_react90.useEffect)(() => {
11962
12317
  void load();
11963
12318
  }, [load]);
11964
- (0, import_react88.useEffect)(() => {
12319
+ (0, import_react90.useEffect)(() => {
11965
12320
  if (title !== "" || !table.data) return;
11966
12321
  setTitle(existing?.title ?? `Book a ${minutes}-minute ${table.data.name} appointment`);
11967
12322
  }, [table.data, existing]);
11968
- (0, import_react88.useEffect)(() => {
12323
+ (0, import_react90.useEffect)(() => {
11969
12324
  if (!existing) return;
11970
12325
  setMinutes(existing.slot_minutes);
11971
12326
  }, [existing]);
11972
- const availability = (0, import_react88.useCallback)(
12327
+ const availability = (0, import_react90.useCallback)(
11973
12328
  () => ({
11974
12329
  slot_minutes: minutes,
11975
12330
  buffer_minutes: buffer,
@@ -12018,68 +12373,68 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12018
12373
  await load();
12019
12374
  onSaved?.({ form_id: formId });
12020
12375
  }
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) });
12376
+ 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
12377
  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." });
12378
+ 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
12379
  }
12025
12380
  const url = formId ? `${publicOrigin}${(0, import_records9.bookingPath)(formId)}` : null;
12026
12381
  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
12382
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("section", { className: (0, import_design_system45.cn)("flex flex-col gap-3", className), children: [
12383
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("header", { className: "flex items-center gap-2", children: [
12384
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("h3", { className: "text-sm font-medium", children: existing ? "Booking page" : "New booking page" }),
12385
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "flex-1" }),
12386
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Button, { size: "sm", disabled: saving, onClick: () => void save(), children: saving ? "Saving\u2026" : "Save" }),
12387
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Button, { size: "sm", variant: "ghost", onClick: onClose, children: "Close" }) : null
12033
12388
  ] }),
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) })
12389
+ error ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(RefusalNotice, { error }) : null,
12390
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "flex flex-col gap-1", children: [
12391
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Label, { className: "text-xs font-medium", children: "What it is called" }),
12392
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.BasicInput, { value: title, onChange: (e) => setTitle(e.target.value) })
12038
12393
  ] }),
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)(
12394
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
12395
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "flex flex-col gap-1", children: [
12396
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Label, { className: "text-xs font-medium", children: "How long one appointment is" }),
12397
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12043
12398
  "select",
12044
12399
  {
12045
12400
  className: "h-9 rounded border bg-background px-2 text-sm",
12046
12401
  value: minutes,
12047
12402
  onChange: (e) => setMinutes(Number(e.target.value)),
12048
- children: LENGTHS.map((n) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("option", { value: n, children: [
12403
+ children: LENGTHS.map((n) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("option", { value: n, children: [
12049
12404
  n,
12050
12405
  " minutes"
12051
12406
  ] }, n))
12052
12407
  }
12053
12408
  )
12054
12409
  ] }),
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)(
12410
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "flex flex-col gap-1", children: [
12411
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Label, { className: "text-xs font-medium", children: "Gap kept after each one" }),
12412
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12058
12413
  "select",
12059
12414
  {
12060
12415
  className: "h-9 rounded border bg-background px-2 text-sm",
12061
12416
  value: buffer,
12062
12417
  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))
12418
+ 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
12419
  }
12065
12420
  )
12066
12421
  ] }),
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)(
12422
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "flex flex-col gap-1", children: [
12423
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Label, { className: "text-xs font-medium", children: "Earliest somebody may book" }),
12424
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12070
12425
  "select",
12071
12426
  {
12072
12427
  className: "h-9 rounded border bg-background px-2 text-sm",
12073
12428
  value: lead,
12074
12429
  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))
12430
+ 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
12431
  }
12077
12432
  )
12078
12433
  ] }),
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,
12434
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "flex flex-col gap-1", children: [
12435
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Label, { className: "text-xs font-medium", children: "Most in one day" }),
12436
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12437
+ import_design_system45.BasicInput,
12083
12438
  {
12084
12439
  type: "number",
12085
12440
  min: 1,
@@ -12088,15 +12443,15 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12088
12443
  }
12089
12444
  )
12090
12445
  ] }),
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)(
12446
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "flex flex-col gap-1", children: [
12447
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Label, { className: "text-xs font-medium", children: "How far ahead the page offers" }),
12448
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12094
12449
  "select",
12095
12450
  {
12096
12451
  className: "h-9 rounded border bg-background px-2 text-sm",
12097
12452
  value: days,
12098
12453
  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: [
12454
+ children: [7, 14, 30, 60, 90].map((n) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("option", { value: n, children: [
12100
12455
  n,
12101
12456
  " days"
12102
12457
  ] }, n))
@@ -12104,12 +12459,12 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12104
12459
  )
12105
12460
  ] })
12106
12461
  ] }),
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,
12462
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
12463
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Label, { className: "text-xs font-medium", children: "Hours you are free" }),
12464
+ windows.map((w, i) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex items-center gap-2", children: [
12465
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "flex w-20 items-center gap-1.5 text-xs", children: [
12466
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12467
+ import_design_system45.Checkbox,
12113
12468
  {
12114
12469
  checked: w.on,
12115
12470
  onCheckedChange: (on) => setWindows((prev) => prev.map((x, j) => i === j ? { ...x, on: Boolean(on) } : x))
@@ -12117,9 +12472,9 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12117
12472
  ),
12118
12473
  DAYS[i]?.label
12119
12474
  ] }),
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,
12475
+ w.on ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_jsx_runtime48.Fragment, { children: [
12476
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12477
+ import_design_system45.BasicInput,
12123
12478
  {
12124
12479
  type: "time",
12125
12480
  className: "h-8 w-28",
@@ -12127,9 +12482,9 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12127
12482
  onChange: (e) => setWindows((prev) => prev.map((x, j) => i === j ? { ...x, from: e.target.value } : x))
12128
12483
  }
12129
12484
  ),
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,
12485
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "text-xs text-muted-foreground", children: "to" }),
12486
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12487
+ import_design_system45.BasicInput,
12133
12488
  {
12134
12489
  type: "time",
12135
12490
  className: "h-8 w-28",
@@ -12137,14 +12492,14 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12137
12492
  onChange: (e) => setWindows((prev) => prev.map((x, j) => i === j ? { ...x, to: e.target.value } : x))
12138
12493
  }
12139
12494
  )
12140
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "text-xs text-muted-foreground", children: "not taking bookings" })
12495
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "text-xs text-muted-foreground", children: "not taking bookings" })
12141
12496
  ] }, w.weekday))
12142
12497
  ] }),
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,
12498
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
12499
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Label, { className: "text-xs font-medium", children: "What to ask the person booking" }),
12500
+ 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: [
12501
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12502
+ import_design_system45.Checkbox,
12148
12503
  {
12149
12504
  checked: asked.includes(f.key),
12150
12505
  onCheckedChange: (on) => setAsked((prev) => on ? [...prev, f.key] : prev.filter((k) => k !== f.key))
@@ -12152,12 +12507,12 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12152
12507
  ),
12153
12508
  fieldName(f)
12154
12509
  ] }, 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." })
12510
+ /* @__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
12511
  ] }),
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,
12512
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "flex flex-col gap-1", children: [
12513
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system45.Label, { className: "text-xs font-medium", children: "What they see after booking" }),
12514
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12515
+ import_design_system45.BasicTextarea,
12161
12516
  {
12162
12517
  rows: 2,
12163
12518
  value: confirmation,
@@ -12166,7 +12521,7 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12166
12521
  }
12167
12522
  )
12168
12523
  ] }),
12169
- shown ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("p", { className: "rounded-md border bg-muted/40 p-2.5 text-xs", children: [
12524
+ shown ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("p", { className: "rounded-md border bg-muted/40 p-2.5 text-xs", children: [
12170
12525
  "Saved. The page offers ",
12171
12526
  shown.slot_minutes,
12172
12527
  "-minute appointments in ",
@@ -12185,10 +12540,10 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12185
12540
  ).join(", "),
12186
12541
  "."
12187
12542
  ] }) : 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,
12543
+ url ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex flex-wrap items-center gap-2 rounded-md border p-2.5", children: [
12544
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "min-w-0 flex-1 break-all text-xs", children: url }),
12545
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12546
+ import_design_system45.Button,
12192
12547
  {
12193
12548
  size: "sm",
12194
12549
  variant: "outline",
@@ -12201,8 +12556,8 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12201
12556
  children: copied ? "Copied" : "Copy link"
12202
12557
  }
12203
12558
  ),
12204
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
12205
- import_design_system44.Button,
12559
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12560
+ import_design_system45.Button,
12206
12561
  {
12207
12562
  size: "sm",
12208
12563
  disabled: publishing,
@@ -12210,17 +12565,17 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12210
12565
  children: publishing ? "\u2026" : existing?.published_at && !existing.closed_at ? "Unpublish" : "Publish"
12211
12566
  }
12212
12567
  ),
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." })
12568
+ /* @__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
12569
  ] }) : null
12215
12570
  ] });
12216
12571
  }
12217
12572
 
12218
12573
  // src/BookingSlots.tsx
12219
- var import_react90 = require("react");
12220
- var import_react91 = require("@ai-matrx/records/react");
12574
+ var import_react92 = require("react");
12575
+ var import_react93 = require("@ai-matrx/records/react");
12221
12576
  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");
12577
+ var import_design_system46 = require("@ai-matrx/design-system");
12578
+ var import_jsx_runtime49 = require("react/jsx-runtime");
12224
12579
  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
12580
  function bookingSuggestion(tableName2) {
12226
12581
  const subject = tableName2?.trim() ? tableName2.trim() : "appointments";
@@ -12234,15 +12589,15 @@ var STATE_WORDS = {
12234
12589
  full: "Every time you offered is taken."
12235
12590
  };
12236
12591
  function BookingSlots({ tableId, className }) {
12237
- const client = (0, import_react91.useRecordsClient)();
12592
+ const client = (0, import_react93.useRecordsClient)();
12238
12593
  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 () => {
12594
+ const [pages, setPages] = (0, import_react92.useState)(null);
12595
+ const [error, setError] = (0, import_react92.useState)(null);
12596
+ const [busy, setBusy] = (0, import_react92.useState)(null);
12597
+ const [copied, setCopied] = (0, import_react92.useState)(null);
12598
+ const [shown, setShown] = (0, import_react92.useState)(null);
12599
+ const [building, setBuilding] = (0, import_react92.useState)(false);
12600
+ const load = (0, import_react92.useCallback)(async () => {
12246
12601
  const answered = await client.bookings(tableId ? { table_id: tableId } : {});
12247
12602
  if (!answered.ok) {
12248
12603
  setError(answered.error);
@@ -12252,15 +12607,15 @@ function BookingSlots({ tableId, className }) {
12252
12607
  setError(null);
12253
12608
  setPages(answered.data);
12254
12609
  }, [client, tableId]);
12255
- (0, import_react90.useEffect)(() => {
12610
+ (0, import_react92.useEffect)(() => {
12256
12611
  void load();
12257
12612
  }, [load]);
12258
- const subjectIds = (0, import_react90.useMemo)(
12613
+ const subjectIds = (0, import_react92.useMemo)(
12259
12614
  () => Array.from(new Set((pages ?? []).map((p) => p.table_id))),
12260
12615
  [pages]
12261
12616
  );
12262
- const levels = (0, import_react91.useMyLevels)(subjectIds);
12263
- const toggle = (0, import_react90.useCallback)(
12617
+ const levels = (0, import_react93.useMyLevels)(subjectIds);
12618
+ const toggle = (0, import_react92.useCallback)(
12264
12619
  async (page) => {
12265
12620
  setBusy(page.form_id);
12266
12621
  const wanted = page.published_at === null || page.closed_at !== null;
@@ -12274,7 +12629,7 @@ function BookingSlots({ tableId, className }) {
12274
12629
  },
12275
12630
  [client, load]
12276
12631
  );
12277
- const copy = (0, import_react90.useCallback)(async (url, formId) => {
12632
+ const copy = (0, import_react92.useCallback)(async (url, formId) => {
12278
12633
  try {
12279
12634
  await navigator.clipboard.writeText(url);
12280
12635
  setCopied(formId);
@@ -12284,18 +12639,18 @@ function BookingSlots({ tableId, className }) {
12284
12639
  setShown(url);
12285
12640
  }
12286
12641
  }, []);
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) });
12642
+ 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
12643
  if (pages.length === 0 && !tableId && !error && !building) return null;
12289
12644
  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
12645
+ 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: [
12646
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("header", { className: "flex items-center gap-2", children: [
12647
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("h3", { className: "text-sm font-medium", children: "Bookings" }),
12648
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "text-xs text-muted-foreground", children: pages.length === 0 ? "none yet" : `${pages.length}` }),
12649
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "flex-1" }),
12650
+ 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
12651
  ] }),
12297
- error ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(RefusalNotice, { error }) : null,
12298
- building && tableId ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12652
+ error ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(RefusalNotice, { error }) : null,
12653
+ building && tableId ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
12299
12654
  BookingBuilder,
12300
12655
  {
12301
12656
  tableId,
@@ -12305,7 +12660,7 @@ function BookingSlots({ tableId, className }) {
12305
12660
  onClose: () => setBuilding(false)
12306
12661
  }
12307
12662
  ) : null,
12308
- pages.length === 0 && !building ? tableId ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
12663
+ pages.length === 0 && !building ? tableId ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
12309
12664
  BuildOrAsk,
12310
12665
  {
12311
12666
  mayBuild: true,
@@ -12321,47 +12676,47 @@ function BookingSlots({ tableId, className }) {
12321
12676
  buildLabel: "Build the booking page",
12322
12677
  children: WHAT_A_BOOKING_PAGE_IS
12323
12678
  }
12324
- ) : /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("p", { className: "text-xs text-muted-foreground", children: [
12679
+ ) : /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("p", { className: "text-xs text-muted-foreground", children: [
12325
12680
  WHAT_A_BOOKING_PAGE_IS,
12326
12681
  " Open the table the appointments should land in to make one."
12327
12682
  ] }) : null,
12328
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("ul", { className: "flex flex-col gap-2", children: pages.map((page) => {
12683
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("ul", { className: "flex flex-col gap-2", children: pages.map((page) => {
12329
12684
  const url = `${origin}${(0, import_records10.bookingPath)(page.form_id)}`;
12330
12685
  const mayOpen = levels.data?.[page.table_id] === "admin";
12331
12686
  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 })
12687
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("li", { className: "rounded-md border p-2.5", "data-testid": "booking-page", children: [
12688
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex items-center gap-2", children: [
12689
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: page.title ?? page.slug }),
12690
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_design_system46.Badge, { variant: page.state === "open" ? "default" : "secondary", children: page.state })
12336
12691
  ] }),
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 }),
12692
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "mt-0.5 text-xs text-muted-foreground", children: STATE_WORDS[page.state] ?? page.state }),
12693
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("p", { className: "mt-1.5 text-xs", children: [
12694
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "font-medium", children: page.upcoming }),
12340
12695
  " coming up",
12341
12696
  " \xB7 ",
12342
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "font-medium", children: page.booked }),
12697
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "font-medium", children: page.booked }),
12343
12698
  " booked in all",
12344
- page.held > 0 ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_jsx_runtime48.Fragment, { children: [
12699
+ page.held > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_jsx_runtime49.Fragment, { children: [
12345
12700
  " \xB7 ",
12346
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "font-medium", children: page.held }),
12701
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "font-medium", children: page.held }),
12347
12702
  " being held right now"
12348
12703
  ] }) : null,
12349
- page.cancelled > 0 ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_jsx_runtime48.Fragment, { children: [
12704
+ page.cancelled > 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_jsx_runtime49.Fragment, { children: [
12350
12705
  " \xB7 ",
12351
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "font-medium", children: page.cancelled }),
12706
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "font-medium", children: page.cancelled }),
12352
12707
  " cancelled"
12353
12708
  ] }) : null,
12354
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "text-muted-foreground", children: [
12709
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "text-muted-foreground", children: [
12355
12710
  " \xB7 ",
12356
12711
  page.slot_minutes,
12357
12712
  " minutes each"
12358
12713
  ] })
12359
12714
  ] }),
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,
12715
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "mt-1 text-xs text-muted-foreground", children: nextInWords(page) }),
12716
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "mt-2 flex flex-wrap items-center gap-1.5", children: [
12717
+ /* @__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" }),
12718
+ mayOpen ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
12719
+ import_design_system46.Button,
12365
12720
  {
12366
12721
  size: "sm",
12367
12722
  variant: "ghost",
@@ -12371,13 +12726,13 @@ function BookingSlots({ tableId, className }) {
12371
12726
  }
12372
12727
  ) : null
12373
12728
  ] }),
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: [
12729
+ 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
12730
  "This browser would not let the page copy for you, so here it is to copy by hand: ",
12376
12731
  url
12377
12732
  ] }) : null
12378
12733
  ] }, page.form_id);
12379
12734
  }) }),
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
12735
+ 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
12736
  ] });
12382
12737
  }
12383
12738
  function nextInWords(page) {
@@ -12409,16 +12764,16 @@ function nextInWords(page) {
12409
12764
  }
12410
12765
 
12411
12766
  // 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");
12767
+ var import_react96 = require("react");
12768
+ var import_react97 = require("@ai-matrx/records/react");
12769
+ var import_design_system48 = require("@ai-matrx/design-system");
12415
12770
 
12416
12771
  // src/CaptureRun.tsx
12417
- var import_react92 = require("react");
12772
+ var import_react94 = require("react");
12418
12773
  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");
12774
+ var import_react95 = require("@ai-matrx/records/react");
12775
+ var import_design_system47 = require("@ai-matrx/design-system");
12776
+ var import_jsx_runtime50 = require("react/jsx-runtime");
12422
12777
  function controlFor(field) {
12423
12778
  if (!field) return "text";
12424
12779
  const label = `${field.key} ${field.label ?? ""}`.toLowerCase();
@@ -12455,21 +12810,21 @@ function whereWeAre(timeoutMs = 4e3) {
12455
12810
  });
12456
12811
  }
12457
12812
  function CaptureRun({ sheetId, face: given, className }) {
12458
- const client = (0, import_react93.useRecordsClient)();
12813
+ const client = (0, import_react95.useRecordsClient)();
12459
12814
  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)(() => {
12815
+ const [face, setFace] = (0, import_react94.useState)(given);
12816
+ const [loadFailed, setLoadFailed] = (0, import_react94.useState)(null);
12817
+ const [at, setAt] = (0, import_react94.useState)(0);
12818
+ const [answers, setAnswers] = (0, import_react94.useState)({});
12819
+ const [files, setFiles] = (0, import_react94.useState)({});
12820
+ const [missing, setMissing] = (0, import_react94.useState)(null);
12821
+ const [done, setDone] = (0, import_react94.useState)(null);
12822
+ const [counts, setCounts] = (0, import_react94.useState)({ waiting: 0, sending: 0, refused: 0, landed: 0 });
12823
+ const [items, setItems] = (0, import_react94.useState)([]);
12824
+ const [lastSynced, setLastSynced] = (0, import_react94.useState)(null);
12825
+ const [sending, setSending] = (0, import_react94.useState)(false);
12826
+ const queueRef = (0, import_react94.useRef)(null);
12827
+ (0, import_react94.useEffect)(() => {
12473
12828
  const q2 = (0, import_records11.openCaptureQueue)({
12474
12829
  onChange: (c, all) => {
12475
12830
  setCounts(c);
@@ -12507,7 +12862,7 @@ function CaptureRun({ sheetId, face: given, className }) {
12507
12862
  void q2.sync().then(() => void q2.lastSyncedAt().then(setLastSynced));
12508
12863
  return () => q2.dispose();
12509
12864
  }, [client, host]);
12510
- (0, import_react92.useEffect)(() => {
12865
+ (0, import_react94.useEffect)(() => {
12511
12866
  if (given !== void 0) return;
12512
12867
  let cancelled = false;
12513
12868
  void client.captureOpen({ sheet_id: sheetId }).then((res) => {
@@ -12519,7 +12874,7 @@ function CaptureRun({ sheetId, face: given, className }) {
12519
12874
  cancelled = true;
12520
12875
  };
12521
12876
  }, [client, given, sheetId]);
12522
- const questions = (0, import_react92.useMemo)(() => {
12877
+ const questions = (0, import_react94.useMemo)(() => {
12523
12878
  const asked = face?.presentation?.questions ?? [];
12524
12879
  if (asked.length > 0) return asked;
12525
12880
  return (face?.fields ?? []).map((f) => ({
@@ -12529,11 +12884,11 @@ function CaptureRun({ sheetId, face: given, className }) {
12529
12884
  required: f.required
12530
12885
  }));
12531
12886
  }, [face]);
12532
- const fieldOf = (0, import_react92.useCallback)(
12887
+ const fieldOf = (0, import_react94.useCallback)(
12533
12888
  (key) => (face?.fields ?? []).find((f) => f.key === key),
12534
12889
  [face]
12535
12890
  );
12536
- const sync = (0, import_react92.useCallback)(async () => {
12891
+ const sync = (0, import_react94.useCallback)(async () => {
12537
12892
  const q2 = queueRef.current;
12538
12893
  if (!q2) return;
12539
12894
  setSending(true);
@@ -12546,7 +12901,7 @@ function CaptureRun({ sheetId, face: given, className }) {
12546
12901
  setSending(false);
12547
12902
  }
12548
12903
  }, []);
12549
- const answered = (0, import_react92.useCallback)(
12904
+ const answered = (0, import_react94.useCallback)(
12550
12905
  (key) => {
12551
12906
  if (files[key]) return true;
12552
12907
  const v = answers[key];
@@ -12591,24 +12946,24 @@ function CaptureRun({ sheetId, face: given, className }) {
12591
12946
  if (online) await sync();
12592
12947
  }
12593
12948
  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 }) });
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 text-destructive", "data-testid": "capture-refusal", children: loadFailed }) });
12595
12950
  }
12596
12951
  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) });
12952
+ 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
12953
  }
12599
12954
  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." }) });
12955
+ 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
12956
  }
12602
12957
  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: [
12958
+ 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: [
12959
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "tabular-nums", "data-testid": "capture-waiting", children: waiting === 0 ? "Nothing waiting" : `${waiting} waiting` }),
12960
+ counts.refused > 0 ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "text-destructive tabular-nums", "data-testid": "capture-refused", children: [
12606
12961
  counts.refused,
12607
12962
  " to fix"
12608
12963
  ] }) : 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,
12964
+ /* @__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" }),
12965
+ waiting > 0 || counts.refused > 0 ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
12966
+ import_design_system47.Button,
12612
12967
  {
12613
12968
  size: "sm",
12614
12969
  variant: "ghost",
@@ -12620,11 +12975,11 @@ function CaptureRun({ sheetId, face: given, className }) {
12620
12975
  }
12621
12976
  ) : null
12622
12977
  ] });
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,
12978
+ 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: [
12979
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "tabular-nums text-muted-foreground", children: new Date(i.captured_at).toLocaleTimeString() }),
12980
+ /* @__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." }),
12981
+ i.state === "refused" ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
12982
+ import_design_system47.Button,
12628
12983
  {
12629
12984
  size: "sm",
12630
12985
  variant: "ghost",
@@ -12635,19 +12990,19 @@ function CaptureRun({ sheetId, face: given, className }) {
12635
12990
  ) : null
12636
12991
  ] }, i.client_key)) }) : null;
12637
12992
  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 }),
12993
+ 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: [
12994
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("h1", { className: "text-lg font-medium", children: face.title }),
12995
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-sm", "data-testid": "capture-refusal", children: face.message }),
12641
12996
  queueLine,
12642
12997
  queuePanel
12643
12998
  ] });
12644
12999
  }
12645
13000
  if (done) {
12646
13001
  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" }),
13002
+ 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: [
13003
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("h2", { className: "text-lg font-medium", "data-testid": "capture-thankyou", children: thanks.title ?? "Logged" }),
13004
+ /* @__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." }),
13005
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_design_system47.Button, { className: "h-12", onClick: () => setDone(null), "data-testid": "capture-next", children: "Next one" }),
12651
13006
  queueLine,
12652
13007
  queuePanel
12653
13008
  ] });
@@ -12656,14 +13011,14 @@ function CaptureRun({ sheetId, face: given, className }) {
12656
13011
  const field = fieldOf(q.field);
12657
13012
  const control = controlFor(field);
12658
13013
  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: [
13014
+ 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: [
13015
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex items-center gap-2 text-[11px] text-muted-foreground", children: [
13016
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "tabular-nums", "data-testid": "capture-progress", children: [
12662
13017
  at + 1,
12663
13018
  " of ",
12664
13019
  questions.length
12665
13020
  ] }),
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)(
13021
+ /* @__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
13022
  "div",
12668
13023
  {
12669
13024
  className: "h-full bg-primary transition-[width] duration-200",
@@ -12671,7 +13026,7 @@ function CaptureRun({ sheetId, face: given, className }) {
12671
13026
  }
12672
13027
  ) })
12673
13028
  ] }),
12674
- /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
13029
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
12675
13030
  "label",
12676
13031
  {
12677
13032
  className: "text-xl font-medium leading-snug",
@@ -12679,13 +13034,13 @@ function CaptureRun({ sheetId, face: given, className }) {
12679
13034
  "data-testid": "capture-ask",
12680
13035
  children: [
12681
13036
  q.ask ?? q.field,
12682
- q.required ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "text-muted-foreground", children: " *" }) : null
13037
+ q.required ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "text-muted-foreground", children: " *" }) : null
12683
13038
  ]
12684
13039
  }
12685
13040
  ),
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)(
13041
+ q.help ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "-mt-1 text-sm text-muted-foreground", children: q.help }) : null,
13042
+ 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: [
13043
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
12689
13044
  "input",
12690
13045
  {
12691
13046
  id: `capture-${q.field}`,
@@ -12703,12 +13058,12 @@ function CaptureRun({ sheetId, face: given, className }) {
12703
13058
  }
12704
13059
  }
12705
13060
  ),
12706
- files[q.field] ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("p", { className: "text-[11px] text-muted-foreground", "data-testid": `capture-have-${q.field}`, children: [
13061
+ files[q.field] ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("p", { className: "text-[11px] text-muted-foreground", "data-testid": `capture-have-${q.field}`, children: [
12707
13062
  files[q.field].name,
12708
13063
  " is on the phone. It goes up with the capture."
12709
13064
  ] }) : null
12710
- ] }) : control === "number" ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
12711
- import_design_system46.Input,
13065
+ ] }) : control === "number" ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
13066
+ import_design_system47.Input,
12712
13067
  {
12713
13068
  id: `capture-${q.field}`,
12714
13069
  "data-testid": `capture-input-${q.field}`,
@@ -12723,8 +13078,8 @@ function CaptureRun({ sheetId, face: given, className }) {
12723
13078
  setMissing(null);
12724
13079
  }
12725
13080
  }
12726
- ) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
12727
- import_design_system46.Textarea,
13081
+ ) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
13082
+ import_design_system47.Textarea,
12728
13083
  {
12729
13084
  id: `capture-${q.field}`,
12730
13085
  "data-testid": `capture-input-${q.field}`,
@@ -12738,10 +13093,10 @@ function CaptureRun({ sheetId, face: given, className }) {
12738
13093
  }
12739
13094
  }
12740
13095
  ),
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,
13096
+ missing ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-sm text-destructive", "data-testid": "capture-missing", children: missing }) : null,
13097
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex items-center gap-2", children: [
13098
+ at > 0 ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
13099
+ import_design_system47.Button,
12745
13100
  {
12746
13101
  variant: "ghost",
12747
13102
  className: "h-12 px-3",
@@ -12750,16 +13105,16 @@ function CaptureRun({ sheetId, face: given, className }) {
12750
13105
  children: "Back"
12751
13106
  }
12752
13107
  ) : null,
12753
- last ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
12754
- import_design_system46.Button,
13108
+ last ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
13109
+ import_design_system47.Button,
12755
13110
  {
12756
13111
  className: "h-12 flex-1 text-base",
12757
13112
  onClick: () => void capture(),
12758
13113
  "data-testid": "capture-submit",
12759
13114
  children: "Capture"
12760
13115
  }
12761
- ) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
12762
- import_design_system46.Button,
13116
+ ) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
13117
+ import_design_system47.Button,
12763
13118
  {
12764
13119
  className: "h-12 flex-1 text-base",
12765
13120
  onClick: () => setAt(at + 1),
@@ -12774,7 +13129,7 @@ function CaptureRun({ sheetId, face: given, className }) {
12774
13129
  }
12775
13130
 
12776
13131
  // src/CaptureSheet.tsx
12777
- var import_jsx_runtime50 = require("react/jsx-runtime");
13132
+ var import_jsx_runtime51 = require("react/jsx-runtime");
12778
13133
  var CAPTURE_MODES = ["reading", "photo", "voice"];
12779
13134
  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
13135
  function mintClientKey() {
@@ -12794,8 +13149,8 @@ function CaptureSheet({
12794
13149
  attachmentField,
12795
13150
  className
12796
13151
  }) {
12797
- if (sheetId) return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(CaptureRun, { sheetId, className });
12798
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
13152
+ if (sheetId) return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(CaptureRun, { sheetId, className });
13153
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
12799
13154
  AdHocCaptureSheet,
12800
13155
  {
12801
13156
  tableId,
@@ -12813,21 +13168,21 @@ function AdHocCaptureSheet({
12813
13168
  attachmentField,
12814
13169
  className
12815
13170
  }) {
12816
- const client = (0, import_react95.useRecordsClient)();
13171
+ const client = (0, import_react97.useRecordsClient)();
12817
13172
  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)(
13173
+ const table = (0, import_react97.useTable)(tableId);
13174
+ const fields = (0, import_react97.useFields)(tableId);
13175
+ const [mode, setMode] = (0, import_react96.useState)("reading");
13176
+ const [reading, setReading] = (0, import_react96.useState)("");
13177
+ const [note, setNote] = (0, import_react96.useState)("");
13178
+ const [fileId, setFileId] = (0, import_react96.useState)(null);
13179
+ const [pending, setPending] = (0, import_react96.useState)(null);
13180
+ const [saved, setSaved] = (0, import_react96.useState)([]);
13181
+ const [error, setError] = (0, import_react96.useState)(null);
13182
+ const [uploadError, setUploadError] = (0, import_react96.useState)(null);
13183
+ const [flushing, setFlushing] = (0, import_react96.useState)(false);
13184
+ const queue = (0, import_react96.useRef)([]);
13185
+ const keep = (0, import_react96.useCallback)(
12831
13186
  async (next) => {
12832
13187
  queue.current = next;
12833
13188
  setPending(next);
@@ -12835,7 +13190,7 @@ function AdHocCaptureSheet({
12835
13190
  },
12836
13191
  [host]
12837
13192
  );
12838
- (0, import_react94.useEffect)(() => {
13193
+ (0, import_react96.useEffect)(() => {
12839
13194
  let cancelled = false;
12840
13195
  void (async () => {
12841
13196
  const held = host.captureQueue ? await host.captureQueue.load() : [];
@@ -12847,7 +13202,7 @@ function AdHocCaptureSheet({
12847
13202
  cancelled = true;
12848
13203
  };
12849
13204
  }, [host]);
12850
- const resolved = (0, import_react94.useCallback)(() => {
13205
+ const resolved = (0, import_react96.useCallback)(() => {
12851
13206
  const all = fields.data ?? [];
12852
13207
  return {
12853
13208
  reading: readingField ?? all.find((f) => f.type === "range")?.key ?? null,
@@ -12855,7 +13210,7 @@ function AdHocCaptureSheet({
12855
13210
  attachment: attachmentField ?? all.find((f) => f.format === "file" || f.format === "image")?.key ?? null
12856
13211
  };
12857
13212
  }, [attachmentField, fields.data, noteField, readingField, table.data]);
12858
- const flush = (0, import_react94.useCallback)(async () => {
13213
+ const flush = (0, import_react96.useCallback)(async () => {
12859
13214
  if (flushing || queue.current.length === 0) return;
12860
13215
  setFlushing(true);
12861
13216
  const left = [];
@@ -12907,14 +13262,14 @@ function AdHocCaptureSheet({
12907
13262
  await keep([...queue.current, item]);
12908
13263
  await flush();
12909
13264
  }
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) });
13265
+ if (table.error) return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(RefusalNotice, { error: table.error, className });
13266
+ if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(RefusalNotice, { error: fields.error, className });
13267
+ 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
13268
  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,
13269
+ 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: [
13270
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("header", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
13271
+ CAPTURE_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
13272
+ import_design_system48.Button,
12918
13273
  {
12919
13274
  size: "sm",
12920
13275
  variant: m === mode ? "default" : "ghost",
@@ -12924,11 +13279,11 @@ function AdHocCaptureSheet({
12924
13279
  },
12925
13280
  m
12926
13281
  )),
12927
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "ml-auto tabular-nums", children: pending.length > 0 ? `${pending.length} waiting` : `${saved.length} saved` })
13282
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "ml-auto tabular-nums", children: pending.length > 0 ? `${pending.length} waiting` : `${saved.length} saved` })
12928
13283
  ] }),
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,
13284
+ error ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(RefusalNotice, { error }) : null,
13285
+ mode === "reading" ? keys.reading ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
13286
+ import_design_system48.Input,
12932
13287
  {
12933
13288
  "aria-label": "Reading",
12934
13289
  inputMode: "decimal",
@@ -12937,22 +13292,22 @@ function AdHocCaptureSheet({
12937
13292
  value: reading,
12938
13293
  onChange: (e) => setReading(e.target.value)
12939
13294
  }
12940
- ) : /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: [
13295
+ ) : /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: [
12941
13296
  table.data?.name ?? "This table",
12942
13297
  " 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" }),
13298
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("code", { children: "readingField" }),
12944
13299
  "."
12945
13300
  ] }) : 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: [
13301
+ 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
13302
  table.data?.name ?? "This table",
12948
13303
  " has no Field a file id can go in, so a ",
12949
13304
  mode,
12950
13305
  " capture would upload the bytes and then have nowhere to record them. Add one, or name it with",
12951
13306
  " ",
12952
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("code", { children: "attachmentField" }),
13307
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("code", { children: "attachmentField" }),
12953
13308
  "."
12954
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_jsx_runtime50.Fragment, { children: [
12955
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
13309
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_jsx_runtime51.Fragment, { children: [
13310
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
12956
13311
  "input",
12957
13312
  {
12958
13313
  "aria-label": mode === "photo" ? "Take a photo" : "Record a voice note",
@@ -12971,11 +13326,11 @@ function AdHocCaptureSheet({
12971
13326
  }
12972
13327
  }
12973
13328
  ),
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
13329
+ fileId ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Attached." }) : null,
13330
+ uploadError ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("p", { className: "text-xs text-destructive", children: uploadError }) : null
12976
13331
  ] }) : null,
12977
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
12978
- import_design_system47.Textarea,
13332
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
13333
+ import_design_system48.Textarea,
12979
13334
  {
12980
13335
  "aria-label": "Note",
12981
13336
  rows: 2,
@@ -12985,12 +13340,12 @@ function AdHocCaptureSheet({
12985
13340
  onChange: (e) => setNote(e.target.value)
12986
13341
  }
12987
13342
  ),
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,
13343
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_design_system48.Button, { className: "h-12", onClick: () => void capture(), children: "Capture" }),
13344
+ pending.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "flex flex-col gap-1 rounded border p-2", children: [
13345
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
13346
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "font-medium", children: "Waiting to send" }),
13347
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
13348
+ import_design_system48.Button,
12994
13349
  {
12995
13350
  size: "sm",
12996
13351
  variant: "ghost",
@@ -13001,7 +13356,7 @@ function AdHocCaptureSheet({
13001
13356
  }
13002
13357
  )
13003
13358
  ] }),
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: [
13359
+ /* @__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
13360
  new Date(item.capturedAt).toLocaleTimeString(),
13006
13361
  " \xB7 ",
13007
13362
  item.attempts,
@@ -13009,23 +13364,23 @@ function AdHocCaptureSheet({
13009
13364
  item.lastRefusal ? ` \xB7 ${item.lastRefusal}` : ""
13010
13365
  ] }, item.clientKey)) })
13011
13366
  ] }) : 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
13367
+ !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
13368
  ] });
13014
13369
  }
13015
13370
 
13016
13371
  // 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");
13372
+ var import_react98 = require("react");
13373
+ var import_react99 = require("@ai-matrx/records/react");
13374
+ var import_design_system49 = require("@ai-matrx/design-system");
13375
+ var import_jsx_runtime52 = require("react/jsx-runtime");
13021
13376
  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 () => {
13377
+ const client = (0, import_react99.useRecordsClient)();
13378
+ const [card, setCard] = (0, import_react98.useState)(null);
13379
+ const [reach, setReach] = (0, import_react98.useState)(null);
13380
+ const [error, setError] = (0, import_react98.useState)(null);
13381
+ const [open, setOpen] = (0, import_react98.useState)(null);
13382
+ const [sending, setSending] = (0, import_react98.useState)(false);
13383
+ const load = (0, import_react98.useCallback)(async () => {
13029
13384
  const who = await client.externalPrincipalCard();
13030
13385
  if (!who.ok) {
13031
13386
  setError(who.error);
@@ -13040,23 +13395,23 @@ function PortalShell({ tableId, form, resourceType = "record", className }) {
13040
13395
  }
13041
13396
  setReach(reached.data.map((row) => row.resource_id));
13042
13397
  }, [client, resourceType]);
13043
- (0, import_react96.useEffect)(() => {
13398
+ (0, import_react98.useEffect)(() => {
13044
13399
  void load();
13045
13400
  }, [load]);
13046
13401
  if (error) {
13047
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(RefusalNotice, { error, className });
13402
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(RefusalNotice, { error, className });
13048
13403
  }
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) });
13404
+ 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
13405
  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." });
13406
+ 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
13407
  }
13053
13408
  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" })
13409
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("section", { className: (0, import_design_system49.cn)("flex min-h-0 flex-col gap-2", className), children: [
13410
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("header", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
13411
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "font-medium text-foreground", children: form.name }),
13412
+ /* @__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
13413
  ] }),
13059
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
13414
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
13060
13415
  FormRunner,
13061
13416
  {
13062
13417
  form,
@@ -13069,38 +13424,38 @@ function PortalShell({ tableId, form, resourceType = "record", className }) {
13069
13424
  ] });
13070
13425
  }
13071
13426
  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) }) });
13427
+ 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
13428
  }
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
13429
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("section", { className: (0, import_design_system49.cn)("flex min-h-0 flex-col gap-2", className), children: [
13430
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("header", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
13431
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "font-medium text-foreground", children: "Shared with you" }),
13432
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "tabular-nums", children: reach.length }),
13433
+ 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
13434
  ] }),
13080
13435
  reach.length === 0 ? (
13081
13436
  // EMPTY, AND IT SAYS WHICH EMPTY. "Nobody has shared anything with you"
13082
13437
  // and "the store would not tell us" are different sentences, and a
13083
13438
  // 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: [
13439
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: [
13085
13440
  "Nothing has been shared with you yet. ",
13086
13441
  card.explanation,
13087
13442
  " 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
13443
  ] })
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)(
13444
+ ) : /* @__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
13445
  "button",
13091
13446
  {
13092
13447
  type: "button",
13093
13448
  className: "w-full truncate rounded border px-2 py-1.5 text-left text-xs hover:bg-muted",
13094
13449
  onClick: () => setOpen(id),
13095
- children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(PortalRow, { tableId, recordId: id })
13450
+ children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(PortalRow, { tableId, recordId: id })
13096
13451
  }
13097
13452
  ) }, id)) })
13098
13453
  ] });
13099
13454
  }
13100
13455
  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)(() => {
13456
+ const client = (0, import_react99.useRecordsClient)();
13457
+ const [title, setTitle] = (0, import_react98.useState)(null);
13458
+ (0, import_react98.useEffect)(() => {
13104
13459
  let cancelled = false;
13105
13460
  void client.recordRead({ record_id: recordId }).then((answered) => {
13106
13461
  if (cancelled) return;
@@ -13116,22 +13471,22 @@ function PortalRow({ tableId, recordId }) {
13116
13471
  cancelled = true;
13117
13472
  };
13118
13473
  }, [client, recordId, tableId]);
13119
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { children: title ?? "\u2026" });
13474
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { children: title ?? "\u2026" });
13120
13475
  }
13121
13476
 
13122
13477
  // 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");
13478
+ var import_react100 = require("react");
13479
+ var import_react101 = require("@ai-matrx/records/react");
13480
+ var import_design_system50 = require("@ai-matrx/design-system");
13481
+ var import_jsx_runtime53 = require("react/jsx-runtime");
13127
13482
  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 () => {
13483
+ const client = (0, import_react101.useRecordsClient)();
13484
+ const [binding, setBinding] = (0, import_react100.useState)(null);
13485
+ const [rows, setRows] = (0, import_react100.useState)(null);
13486
+ const [fields, setFields] = (0, import_react100.useState)(null);
13487
+ const [error, setError] = (0, import_react100.useState)(null);
13488
+ const [gap, setGap] = (0, import_react100.useState)(null);
13489
+ const load = (0, import_react100.useCallback)(async () => {
13135
13490
  const notice = await client.worldPublishGapNotice();
13136
13491
  if (notice.ok) setGap(notice.data);
13137
13492
  const resolved = await client.resolvePublishBinding({ slug });
@@ -13164,48 +13519,48 @@ function PublicViewPage({ slug, className }) {
13164
13519
  }
13165
13520
  setRows([{ id: found.resource_id, document: read.data.document, level: "viewer", hidden: read.data.hidden }]);
13166
13521
  }, [client, slug]);
13167
- (0, import_react98.useEffect)(() => {
13522
+ (0, import_react100.useEffect)(() => {
13168
13523
  void load();
13169
13524
  }, [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) });
13525
+ if (error) return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(RefusalNotice, { error, className });
13526
+ 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
13527
  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
13528
+ 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: [
13529
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("h1", { className: "text-lg font-medium", children: "Nothing here" }),
13530
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("p", { className: "mt-1 text-sm text-muted-foreground", children: "There is no public page at this address." }),
13531
+ gap ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("p", { className: "mt-6 text-xs text-muted-foreground", children: gap }) : null
13177
13532
  ] });
13178
13533
  }
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" })
13534
+ 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: [
13535
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("header", { className: "flex items-baseline gap-2 text-xs text-muted-foreground", children: [
13536
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "font-medium text-foreground", children: binding.namespace ?? "Published" }),
13537
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { children: binding.render_mode === "list" ? `${rows?.length ?? 0} items` : "Shared publicly" })
13183
13538
  ] }),
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." })
13539
+ 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)) }),
13540
+ /* @__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
13541
  ] });
13187
13542
  }
13188
13543
  function PublicRow({ row, fields }) {
13189
13544
  const document2 = row.document ?? {};
13190
13545
  if (!fields) {
13191
13546
  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 ?? "") })
13547
+ 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: [
13548
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("dt", { className: "text-xs text-muted-foreground", children: key }),
13549
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("dd", { className: "text-sm", children: String(value ?? "") })
13195
13550
  ] }, key)) });
13196
13551
  }
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 }) })
13552
+ 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: [
13553
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("dt", { className: "text-xs text-muted-foreground", children: field.label }),
13554
+ /* @__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
13555
  ] }, field.key)) });
13201
13556
  }
13202
13557
 
13203
13558
  // 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");
13559
+ var import_react102 = require("react");
13560
+ var import_react103 = require("@ai-matrx/records/react");
13561
+ var import_design_system51 = require("@ai-matrx/design-system");
13562
+ var import_react104 = require("@ai-matrx/records/react");
13563
+ var import_jsx_runtime54 = require("react/jsx-runtime");
13209
13564
  function EmbedFrame({
13210
13565
  tableId,
13211
13566
  formId,
@@ -13214,18 +13569,18 @@ function EmbedFrame({
13214
13569
  embedUrl,
13215
13570
  className
13216
13571
  }) {
13217
- const client = (0, import_react101.useRecordsClient)();
13572
+ const client = (0, import_react103.useRecordsClient)();
13218
13573
  const host = useRecordsUi();
13219
- const table = (0, import_react102.useTable)(tableId);
13574
+ const table = (0, import_react104.useTable)(tableId);
13220
13575
  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);
13576
+ const [origins, setOrigins] = (0, import_react102.useState)("");
13577
+ const [secret, setSecret] = (0, import_react102.useState)(null);
13578
+ const [tokenId, setTokenId] = (0, import_react102.useState)(null);
13579
+ const [error, setError] = (0, import_react102.useState)(null);
13580
+ const [busy, setBusy] = (0, import_react102.useState)(false);
13226
13581
  const mode = formId ? "write" : "read";
13227
13582
  const parsed = origins.split(/[\s,]+/).map((o) => o.trim()).filter((o) => o.length > 0);
13228
- const issue = (0, import_react100.useCallback)(async () => {
13583
+ const issue = (0, import_react102.useCallback)(async () => {
13229
13584
  setBusy(true);
13230
13585
  setError(null);
13231
13586
  const minted = await client.anonTokenIssue({
@@ -13244,7 +13599,7 @@ function EmbedFrame({
13244
13599
  setTokenId(minted.data.token_id);
13245
13600
  host.notify?.success("Embed token issued. Copy it now \u2014 it is never shown again.");
13246
13601
  }, [client, formId, host, mode, parsed, recordId, savedViewId]);
13247
- const revoke = (0, import_react100.useCallback)(async () => {
13602
+ const revoke = (0, import_react102.useCallback)(async () => {
13248
13603
  if (!tokenId) return;
13249
13604
  setBusy(true);
13250
13605
  const done = await client.anonTokenRevoke({ token_id: tokenId });
@@ -13256,25 +13611,25 @@ function EmbedFrame({
13256
13611
  setSecret(null);
13257
13612
  setTokenId(null);
13258
13613
  }, [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) });
13614
+ if (table.error) return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(RefusalNotice, { error: table.error, className });
13615
+ 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
13616
  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: [
13617
+ 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
13618
  rights.why("structure"),
13264
13619
  " 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
13620
  ] });
13266
13621
  }
13267
13622
  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" })
13623
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("section", { className: (0, import_design_system51.cn)("flex min-h-0 flex-col gap-2", className), children: [
13624
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("header", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
13625
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "font-medium text-foreground", children: "Embed" }),
13626
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { children: mode === "write" ? "a form people can send" : "a read-only view" })
13272
13627
  ] }),
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,
13628
+ error ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(RefusalNotice, { error }) : null,
13629
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("label", { className: "flex flex-col gap-1 text-xs", children: [
13630
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "text-muted-foreground", children: "Sites this embed works on" }),
13631
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
13632
+ import_design_system51.Input,
13278
13633
  {
13279
13634
  "aria-label": "Allowed origins",
13280
13635
  className: "h-8 text-xs",
@@ -13283,18 +13638,18 @@ function EmbedFrame({
13283
13638
  onChange: (e) => setOrigins(e.target.value)
13284
13639
  }
13285
13640
  ),
13286
- /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("span", { className: "text-[11px] text-muted-foreground", children: [
13641
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "text-[11px] text-muted-foreground", children: [
13287
13642
  `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" }),
13643
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("code", { children: "example.com.evil.test" }),
13289
13644
  " will not pass."
13290
13645
  ] })
13291
13646
  ] }),
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,
13647
+ !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: [
13648
+ /* @__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." }),
13649
+ /* @__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 ?? "" }),
13650
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "flex gap-2", children: [
13651
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
13652
+ import_design_system51.Button,
13298
13653
  {
13299
13654
  size: "sm",
13300
13655
  variant: "outline",
@@ -13302,19 +13657,19 @@ function EmbedFrame({
13302
13657
  children: "Copy"
13303
13658
  }
13304
13659
  ),
13305
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_design_system50.Button, { size: "sm", variant: "ghost", disabled: busy, onClick: () => void revoke(), children: "Revoke" })
13660
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_design_system51.Button, { size: "sm", variant: "ghost", disabled: busy, onClick: () => void revoke(), children: "Revoke" })
13306
13661
  ] })
13307
13662
  ] })
13308
13663
  ] });
13309
13664
  }
13310
13665
  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);
13666
+ const client = (0, import_react103.useRecordsClient)();
13667
+ const [binding, setBinding] = (0, import_react102.useState)(null);
13668
+ const [error, setError] = (0, import_react102.useState)(null);
13669
+ const [loading, setLoading] = (0, import_react102.useState)(true);
13315
13670
  const origin = args.origin ?? (typeof location === "undefined" ? "" : location.origin);
13316
13671
  const { secret, requiredMode } = args;
13317
- (0, import_react100.useEffect)(() => {
13672
+ (0, import_react102.useEffect)(() => {
13318
13673
  let cancelled = false;
13319
13674
  setLoading(true);
13320
13675
  setError(null);
@@ -13336,8 +13691,8 @@ function useEmbedHandshake(args) {
13336
13691
  }
13337
13692
 
13338
13693
  // src/RecordsMount.tsx
13339
- var import_react103 = require("@ai-matrx/records/react");
13340
- var import_jsx_runtime54 = require("react/jsx-runtime");
13694
+ var import_react105 = require("@ai-matrx/records/react");
13695
+ var import_jsx_runtime55 = require("react/jsx-runtime");
13341
13696
  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
13697
  function storeDecidesRights(_table) {
13343
13698
  return NO_RIGHTS;
@@ -13350,7 +13705,7 @@ function RecordsMount({
13350
13705
  }) {
13351
13706
  const bound = { ...host ?? {} };
13352
13707
  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 }) }) });
13708
+ 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
13709
  }
13355
13710
  function personActor(userId) {
13356
13711
  return userId ? { actor: "user", user_id: userId } : { actor: "user" };
@@ -13369,9 +13724,9 @@ function recordsDataSource(client, fallbackSchema = "custom") {
13369
13724
  }
13370
13725
 
13371
13726
  // 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");
13727
+ var import_react106 = require("react");
13728
+ var import_react107 = require("@ai-matrx/records/react");
13729
+ var import_design_system52 = require("@ai-matrx/design-system");
13375
13730
 
13376
13731
  // src/createTable.ts
13377
13732
  function tokenFor(name) {
@@ -13481,7 +13836,7 @@ function declaredType(field) {
13481
13836
  }
13482
13837
 
13483
13838
  // src/TablesHome.tsx
13484
- var import_jsx_runtime55 = require("react/jsx-runtime");
13839
+ var import_jsx_runtime56 = require("react/jsx-runtime");
13485
13840
  var TABLE_LANES = ["mine", "organization", "system", "community", "app"];
13486
13841
  var LANE_TITLE = {
13487
13842
  mine: "Mine",
@@ -13506,15 +13861,15 @@ function laneFor(table) {
13506
13861
  return "organization";
13507
13862
  }
13508
13863
  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)(() => {
13864
+ const client = (0, import_react107.useRecordsClient)();
13865
+ const tables = (0, import_react107.useTables)();
13866
+ const [creating, setCreating] = (0, import_react106.useState)(false);
13867
+ const [name, setName] = (0, import_react106.useState)("");
13868
+ const [busy, setBusy] = (0, import_react106.useState)(false);
13869
+ const [error, setError] = (0, import_react106.useState)(null);
13870
+ const [importInto, setImportInto] = (0, import_react106.useState)(null);
13871
+ const [boards, setBoards] = (0, import_react106.useState)(null);
13872
+ (0, import_react106.useEffect)(() => {
13518
13873
  let cancelled = false;
13519
13874
  void client.dashboards({}).then((result) => {
13520
13875
  if (cancelled) return;
@@ -13524,7 +13879,7 @@ function TablesHome({ onOpenTable, className }) {
13524
13879
  cancelled = true;
13525
13880
  };
13526
13881
  }, [client]);
13527
- const create = (0, import_react104.useCallback)(
13882
+ const create = (0, import_react106.useCallback)(
13528
13883
  async (mode) => {
13529
13884
  const trimmed = name.trim();
13530
13885
  if (!trimmed) return;
@@ -13544,10 +13899,10 @@ function TablesHome({ onOpenTable, className }) {
13544
13899
  },
13545
13900
  [client, name, onOpenTable, tables]
13546
13901
  );
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,
13902
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: (0, import_design_system52.cn)("flex min-h-0 flex-col gap-4", className), children: [
13903
+ /* @__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: [
13904
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13905
+ import_design_system52.BasicInput,
13551
13906
  {
13552
13907
  autoFocus: true,
13553
13908
  value: name,
@@ -13560,9 +13915,9 @@ function TablesHome({ onOpenTable, className }) {
13560
13915
  className: "h-8 max-w-xs"
13561
13916
  }
13562
13917
  ),
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,
13918
+ /* @__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" }),
13919
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13920
+ import_design_system52.Button,
13566
13921
  {
13567
13922
  size: "sm",
13568
13923
  variant: "outline",
@@ -13571,37 +13926,37 @@ function TablesHome({ onOpenTable, className }) {
13571
13926
  children: "Create and import a file"
13572
13927
  }
13573
13928
  ),
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" })
13929
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_design_system52.Button, { size: "sm", variant: "ghost", onClick: () => setCreating(false), children: "Cancel" })
13930
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_design_system52.Button, { size: "sm", onClick: () => setCreating(true), children: "New table" }) }),
13931
+ error ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(RefusalNotice, { error }) : null,
13932
+ importInto ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "rounded-md border p-3", children: [
13933
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(ImportWizard, { tableId: importInto, onDone: () => setImportInto(null) }),
13934
+ /* @__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
13935
  ] }) : 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" })
13936
+ tables.error ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(RefusalNotice, { error: tables.error }) : null,
13937
+ tables.loading && !tables.data ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "space-y-2", children: [
13938
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_design_system52.Skeleton, { className: "h-6 w-40" }),
13939
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_design_system52.Skeleton, { className: "h-16 w-full" })
13585
13940
  ] }) : 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 })
13941
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(BookingSlots, {}),
13942
+ boards && boards.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("section", { className: "space-y-1.5", children: [
13943
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "flex items-baseline gap-2", children: [
13944
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("h2", { className: "text-sm font-medium", children: "Dashboards" }),
13945
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "text-xs opacity-60", children: boards.length })
13591
13946
  ] }),
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)(
13947
+ /* @__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
13948
  "button",
13594
13949
  {
13595
13950
  type: "button",
13596
13951
  disabled: !board.table_id,
13597
13952
  onClick: () => board.table_id ? onOpenTable?.(board.table_id, board.dashboard_id) : void 0,
13598
- className: (0, import_design_system51.cn)(
13953
+ className: (0, import_design_system52.cn)(
13599
13954
  "w-full rounded-md border px-3 py-2 text-left transition-colors",
13600
13955
  onOpenTable && board.table_id ? "hover:bg-accent" : "cursor-default"
13601
13956
  ),
13602
13957
  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: [
13958
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "block truncate text-sm", children: board.name }),
13959
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "block truncate text-xs opacity-60", children: [
13605
13960
  board.block_count,
13606
13961
  " block",
13607
13962
  board.block_count === 1 ? "" : "s",
@@ -13617,23 +13972,23 @@ function TablesHome({ onOpenTable, className }) {
13617
13972
  ] }) : null,
13618
13973
  tables.data ? TABLE_LANES.map((lane) => {
13619
13974
  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 })
13975
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("section", { className: "space-y-1.5", children: [
13976
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "flex items-baseline gap-2", children: [
13977
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("h2", { className: "text-sm font-medium", children: LANE_TITLE[lane] }),
13978
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "text-xs opacity-60", children: rows.length })
13624
13979
  ] }),
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)(
13980
+ 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
13981
  "button",
13627
13982
  {
13628
13983
  type: "button",
13629
13984
  onClick: () => onOpenTable?.(table.id),
13630
- className: (0, import_design_system51.cn)(
13985
+ className: (0, import_design_system52.cn)(
13631
13986
  "w-full rounded-md border px-3 py-2 text-left transition-colors",
13632
13987
  onOpenTable ? "hover:bg-accent" : "cursor-default"
13633
13988
  ),
13634
13989
  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: [
13990
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "block truncate text-sm", children: tableName(table) }),
13991
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "block truncate text-xs opacity-60", children: [
13637
13992
  table.fields.length,
13638
13993
  " field",
13639
13994
  table.fields.length === 1 ? "" : "s",
@@ -13648,10 +14003,10 @@ function TablesHome({ onOpenTable, className }) {
13648
14003
  }
13649
14004
 
13650
14005
  // 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");
14006
+ var import_react108 = require("react");
14007
+ var import_react109 = require("@ai-matrx/records/react");
14008
+ var import_design_system53 = require("@ai-matrx/design-system");
14009
+ var import_jsx_runtime57 = require("react/jsx-runtime");
13655
14010
  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
14011
  var DEFAULT_VIEW_NAME = "All records";
13657
14012
  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 +14037,29 @@ function TablePage({
13682
14037
  activeRecordId,
13683
14038
  className
13684
14039
  }) {
13685
- const client = (0, import_react107.useRecordsClient)();
13686
- const table = (0, import_react107.useTable)(tableId);
14040
+ const client = (0, import_react109.useRecordsClient)();
14041
+ const table = (0, import_react109.useTable)(tableId);
13687
14042
  const rights = useTableRights(table.data);
13688
- const organizationId = (0, import_react107.useRecordsClient)().config.organizationId;
13689
- const [view, setView] = (0, import_react106.useState)(null);
14043
+ const organizationId = (0, import_react109.useRecordsClient)().config.organizationId;
14044
+ const [view, setView] = (0, import_react108.useState)(null);
13690
14045
  const opening = openingRail(activeRecordId);
13691
- const [asking, setAsking] = (0, import_react106.useState)(null);
13692
- const [surface, setSurface] = (0, import_react106.useState)({
14046
+ const [asking, setAsking] = (0, import_react108.useState)(null);
14047
+ const [surface, setSurface] = (0, import_react108.useState)({
13693
14048
  main: activeDashboardId ? "dashboards" : "records",
13694
14049
  rail: opening.rail
13695
14050
  });
13696
14051
  const { main, rail } = surface;
13697
14052
  const setRail = (next) => setSurface((now) => ({ ...now, rail: next }));
13698
- const [openRecord, setOpenRecord] = (0, import_react106.useState)(opening.record);
14053
+ const [openRecord, setOpenRecord] = (0, import_react108.useState)(opening.record);
13699
14054
  const viewVersion = useRecordVersion(view?.id ?? null);
13700
14055
  const press = (pressed) => setSurface((now) => chooseSurface(now, pressed));
13701
14056
  const show = (next) => press({ rail: next });
13702
- (0, import_react106.useEffect)(() => {
14057
+ (0, import_react108.useEffect)(() => {
13703
14058
  if (!activeRecordId) return;
13704
14059
  setOpenRecord(activeRecordId);
13705
14060
  setSurface((now) => ({ ...now, rail: "record" }));
13706
14061
  }, [activeRecordId]);
13707
- const patchView = (0, import_react106.useCallback)(
14062
+ const patchView = (0, import_react108.useCallback)(
13708
14063
  async (patch) => {
13709
14064
  const current = view;
13710
14065
  if (!current) return;
@@ -13720,19 +14075,19 @@ function TablePage({
13720
14075
  },
13721
14076
  [client, view, viewVersion]
13722
14077
  );
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" });
14078
+ if (table.error) return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(RefusalNotice, { error: table.error });
14079
+ if (table.loading) return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_design_system53.Skeleton, { className: "h-40 w-full" });
13725
14080
  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
14081
+ 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: [
14082
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "text-sm font-medium", children: "This table is not here" }),
14083
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "max-w-prose text-xs text-muted-foreground", children: TABLE_NOT_REACHABLE }),
14084
+ onLeave ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_design_system53.Button, { size: "sm", variant: "outline", onClick: onLeave, children: leaveLabel }) : null
13730
14085
  ] });
13731
14086
  }
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)(
14087
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: (0, import_design_system53.cn)("flex min-h-0 gap-4", className), children: [
14088
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col gap-2", children: [
14089
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5", children: [
14090
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13736
14091
  ViewBar,
13737
14092
  {
13738
14093
  tableId,
@@ -13741,10 +14096,10 @@ function TablePage({
13741
14096
  className: "min-w-0 flex-1"
13742
14097
  }
13743
14098
  ),
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,
14099
+ 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,
14100
+ rights.structure ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
14101
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14102
+ import_design_system53.Button,
13748
14103
  {
13749
14104
  size: "sm",
13750
14105
  variant: surfaceChosen(surface, { rail: "field" }) ? "secondary" : "outline",
@@ -13753,8 +14108,8 @@ function TablePage({
13753
14108
  children: "Add field"
13754
14109
  }
13755
14110
  ),
13756
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13757
- import_design_system52.Button,
14111
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14112
+ import_design_system53.Button,
13758
14113
  {
13759
14114
  size: "sm",
13760
14115
  variant: surfaceChosen(surface, { rail: "settings" }) ? "secondary" : "ghost",
@@ -13763,8 +14118,8 @@ function TablePage({
13763
14118
  children: "Settings"
13764
14119
  }
13765
14120
  ),
13766
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13767
- import_design_system52.Button,
14121
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14122
+ import_design_system53.Button,
13768
14123
  {
13769
14124
  size: "sm",
13770
14125
  variant: surfaceChosen(surface, { rail: "import" }) ? "secondary" : "ghost",
@@ -13774,8 +14129,8 @@ function TablePage({
13774
14129
  }
13775
14130
  )
13776
14131
  ] }) : null,
13777
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13778
- import_design_system52.Button,
14132
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14133
+ import_design_system53.Button,
13779
14134
  {
13780
14135
  size: "sm",
13781
14136
  variant: surfaceChosen(surface, { main: "dashboards" }) ? "secondary" : "ghost",
@@ -13784,8 +14139,8 @@ function TablePage({
13784
14139
  children: "Dashboards"
13785
14140
  }
13786
14141
  ),
13787
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13788
- import_design_system52.Button,
14142
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14143
+ import_design_system53.Button,
13789
14144
  {
13790
14145
  size: "sm",
13791
14146
  variant: surfaceChosen(surface, { rail: "forms" }) ? "secondary" : "ghost",
@@ -13794,8 +14149,8 @@ function TablePage({
13794
14149
  children: "Forms"
13795
14150
  }
13796
14151
  ),
13797
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13798
- import_design_system52.Button,
14152
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14153
+ import_design_system53.Button,
13799
14154
  {
13800
14155
  size: "sm",
13801
14156
  variant: surfaceChosen(surface, { rail: "bookings" }) ? "secondary" : "ghost",
@@ -13804,8 +14159,8 @@ function TablePage({
13804
14159
  children: "Bookings"
13805
14160
  }
13806
14161
  ),
13807
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13808
- import_design_system52.Button,
14162
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14163
+ import_design_system53.Button,
13809
14164
  {
13810
14165
  size: "sm",
13811
14166
  variant: surfaceChosen(surface, { rail: "checklists" }) ? "secondary" : "ghost",
@@ -13814,8 +14169,8 @@ function TablePage({
13814
14169
  children: "Checklists"
13815
14170
  }
13816
14171
  ),
13817
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13818
- import_design_system52.Button,
14172
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14173
+ import_design_system53.Button,
13819
14174
  {
13820
14175
  size: "sm",
13821
14176
  variant: surfaceChosen(surface, { rail: "notifications" }) ? "secondary" : "ghost",
@@ -13824,8 +14179,8 @@ function TablePage({
13824
14179
  children: "Notifications"
13825
14180
  }
13826
14181
  ),
13827
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13828
- import_design_system52.Button,
14182
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14183
+ import_design_system53.Button,
13829
14184
  {
13830
14185
  size: "sm",
13831
14186
  variant: surfaceChosen(surface, { rail: "portals" }) ? "secondary" : "ghost",
@@ -13834,8 +14189,8 @@ function TablePage({
13834
14189
  children: "Portals"
13835
14190
  }
13836
14191
  ),
13837
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
13838
- import_design_system52.Button,
14192
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14193
+ import_design_system53.Button,
13839
14194
  {
13840
14195
  size: "sm",
13841
14196
  variant: surfaceChosen(surface, { rail: "inbox" }) ? "secondary" : "ghost",
@@ -13844,7 +14199,7 @@ function TablePage({
13844
14199
  children: "Inbox"
13845
14200
  }
13846
14201
  ),
13847
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
14202
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13848
14203
  ShareControl,
13849
14204
  {
13850
14205
  kind: "table",
@@ -13854,10 +14209,10 @@ function TablePage({
13854
14209
  may: rights.share
13855
14210
  }
13856
14211
  ),
13857
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(ExportMenu, { tableId })
14212
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ExportMenu, { tableId })
13858
14213
  ] }),
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)(
14214
+ main === "dashboards" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(DashboardCanvas, { tableId, activeDashboardId: activeDashboardId ?? null }) : /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
14215
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13861
14216
  ViewSwitcher,
13862
14217
  {
13863
14218
  view: view ?? defaultView(tableId),
@@ -13874,18 +14229,18 @@ function TablePage({
13874
14229
  }
13875
14230
  }
13876
14231
  ),
13877
- view ? null : /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("p", { className: "text-xs text-muted-foreground", children: VIEW_NOT_SAVED_YET })
14232
+ view ? null : /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "text-xs text-muted-foreground", children: VIEW_NOT_SAVED_YET })
13878
14233
  ] })
13879
14234
  ] }),
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)(
14235
+ rail === "none" ? null : /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("aside", { className: "w-[26rem] shrink-0 overflow-y-auto rounded-md border p-3", children: [
14236
+ rail === "settings" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13882
14237
  TableSettings,
13883
14238
  {
13884
14239
  tableId,
13885
14240
  ...onLeave ? { onDeleted: onLeave } : {}
13886
14241
  }
13887
14242
  ) : null,
13888
- rail === "inbox" ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
14243
+ rail === "inbox" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13889
14244
  ActionInbox,
13890
14245
  {
13891
14246
  tableId,
@@ -13895,9 +14250,9 @@ function TablePage({
13895
14250
  }
13896
14251
  }
13897
14252
  ) : 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)(
14253
+ rail === "forms" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(FormsPanel, { tableId }) : null,
14254
+ rail === "bookings" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(BookingSlots, { tableId }) : null,
14255
+ rail === "checklists" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13901
14256
  ChecklistsPanel,
13902
14257
  {
13903
14258
  tableId,
@@ -13907,11 +14262,11 @@ function TablePage({
13907
14262
  }
13908
14263
  }
13909
14264
  ) : 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)(
14265
+ rail === "notifications" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(SubscriptionsPanel, { tableId }) : null,
14266
+ rail === "portals" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(PortalsPanel, { tableId }) : null,
14267
+ rail === "import" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ImportWizard, { tableId, onDone: () => setRail("none") }) : null,
14268
+ rail === "field" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(FieldEditor, { tableId, onSaved: () => setRail("none"), onCancel: () => setRail("none") }) : null,
14269
+ rail === "new-record" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13915
14270
  RecordForm,
13916
14271
  {
13917
14272
  tableId,
@@ -13922,7 +14277,7 @@ function TablePage({
13922
14277
  onCancel: () => setRail("none")
13923
14278
  }
13924
14279
  ) : null,
13925
- rail === "who-changed" && asking ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
14280
+ rail === "who-changed" && asking ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13926
14281
  FieldHistoryPanel,
13927
14282
  {
13928
14283
  tableId,
@@ -13935,10 +14290,10 @@ function TablePage({
13935
14290
  }
13936
14291
  }
13937
14292
  ) : 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)(
14293
+ rail === "record" && openRecord ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "space-y-3", children: [
14294
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Peek, { tableId, recordId: openRecord, onClose: () => setRail("none") }),
14295
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_design_system53.Separator, {}),
14296
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13942
14297
  HistoryPanel,
13943
14298
  {
13944
14299
  tableId,
@@ -13949,10 +14304,10 @@ function TablePage({
13949
14304
  }
13950
14305
  }
13951
14306
  ),
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 })
14307
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_design_system53.Separator, {}),
14308
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ChecklistRunner, { tableId, recordId: openRecord }),
14309
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_design_system53.Separator, {}),
14310
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(CommentThread, { tableId, recordId: openRecord })
13956
14311
  ] }) : null
13957
14312
  ] })
13958
14313
  ] });