@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.js CHANGED
@@ -6250,6 +6250,7 @@ function Card({
6250
6250
 
6251
6251
  // src/ViewSwitcher.tsx
6252
6252
  import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
6253
+ var NO_FIELDS = [];
6253
6254
  function useViewRecords(view, pageSize = 200) {
6254
6255
  const client = useRecordsClient16();
6255
6256
  const table = useRecords4(view.ruleId ? null : view.subject, { pageSize });
@@ -6619,7 +6620,12 @@ function Card2({
6619
6620
  onOpenRecord
6620
6621
  }) {
6621
6622
  const host = useRecordsUi();
6622
- const label = field ? scalarText(field, (record.document ?? {})[field.key]) : rowName(record, null, "Untitled");
6623
+ const wanted = useMemo17(
6624
+ () => field && pointsAtRecords(field) ? [field] : NO_FIELDS,
6625
+ [field]
6626
+ );
6627
+ const labels = useRecordLabels(wanted);
6628
+ const label = field ? scalarText(field, (record.document ?? {})[field.key], labels) : rowName(record, null, "Untitled");
6623
6629
  return /* @__PURE__ */ jsx25(
6624
6630
  "button",
6625
6631
  {
@@ -9398,28 +9404,325 @@ function Invite({ card, onInvited }) {
9398
9404
  ] });
9399
9405
  }
9400
9406
 
9401
- // src/SubscriptionsPanel.tsx
9402
- import { useCallback as useCallback19, useEffect as useEffect22, useState as useState32 } from "react";
9407
+ // src/DigestScheduler.tsx
9408
+ import { useCallback as useCallback19, useEffect as useEffect22, useMemo as useMemo23, useState as useState32 } from "react";
9403
9409
  import { useRecordsClient as useRecordsClient26 } from "@ai-matrx/records/react";
9404
- import { Badge as Badge14, Button as Button29, Skeleton as Skeleton16, Switch as Switch2, cn as cn30 } from "@ai-matrx/design-system";
9405
- import { jsx as jsx36, jsxs as jsxs32 } from "react/jsx-runtime";
9410
+ import { BasicInput as BasicInput10, Button as Button29, Checkbox as Checkbox5, Label as Label5, Separator as Separator11, Skeleton as Skeleton16, cn as cn30 } from "@ai-matrx/design-system";
9411
+ import { Fragment as Fragment16, jsx as jsx36, jsxs as jsxs32 } from "react/jsx-runtime";
9412
+ var WEEKDAYS = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"];
9413
+ var CADENCE_WORDS = {
9414
+ instant: "the moment something arrives",
9415
+ hourly: "every hour",
9416
+ daily: "every day",
9417
+ weekly: "every week"
9418
+ };
9419
+ var CHANNEL_WORDS = {
9420
+ in_app: "in the app",
9421
+ email: "by email \u2014 only if an address is on their account",
9422
+ sms: "by text \u2014 only if a number is on their account"
9423
+ };
9424
+ function DigestScheduler({
9425
+ tableId,
9426
+ savedViewId,
9427
+ subjectName,
9428
+ filters,
9429
+ onScheduled,
9430
+ onClose,
9431
+ className
9432
+ }) {
9433
+ const client = useRecordsClient26();
9434
+ const host = useRecordsUi();
9435
+ const [views, setViews] = useState32(null);
9436
+ const [cadences, setCadences] = useState32([]);
9437
+ const [members, setMembers] = useState32(null);
9438
+ const [error, setError] = useState32(null);
9439
+ const [viewId, setViewId] = useState32(savedViewId ?? "");
9440
+ const [name, setName] = useState32(subjectName?.trim() ? `${subjectName.trim()} summary` : "");
9441
+ const [cadence, setCadence] = useState32("weekly");
9442
+ const [weekday, setWeekday] = useState32("monday");
9443
+ const [time, setTime] = useState32("08:00");
9444
+ const [channel, setChannel] = useState32("in_app");
9445
+ const [quiet, setQuiet] = useState32(false);
9446
+ const [quietFrom, setQuietFrom] = useState32("22:00");
9447
+ const [quietTo, setQuietTo] = useState32("07:00");
9448
+ const [recipients, setRecipients] = useState32([]);
9449
+ const [saving, setSaving] = useState32(false);
9450
+ const [outcomes, setOutcomes] = useState32(null);
9451
+ const [preview, setPreview] = useState32(null);
9452
+ const [previewing, setPreviewing] = useState32(false);
9453
+ const load = useCallback19(async () => {
9454
+ const [saved, offered] = await Promise.all([
9455
+ // The store's own door onto `platform.saved_view`, narrowed in SQL to
9456
+ // Tables this person can already open — never a grant on the table behind it.
9457
+ client.views({ table_id: tableId }),
9458
+ // The cadences are ASKED, never typed into this file, so a picker can
9459
+ // never offer a cadence the digest runner does not honour.
9460
+ client.subscriptionCadences()
9461
+ ]);
9462
+ if (!saved.ok) setError(saved.error);
9463
+ else setViews(saved.data);
9464
+ if (offered.ok) setCadences(offered.data.filter((c) => c !== "instant"));
9465
+ if (host.members) {
9466
+ const who = await host.members();
9467
+ setMembers(who.map((m) => ({ userId: m.userId, name: m.name ?? m.email ?? m.userId })));
9468
+ } else {
9469
+ setMembers([]);
9470
+ }
9471
+ }, [client, tableId, host]);
9472
+ useEffect22(() => {
9473
+ void load();
9474
+ }, [load]);
9475
+ const schedule = useMemo23(() => {
9476
+ if (cadence === "weekly") return `${weekday} ${time}`;
9477
+ if (cadence === "daily") return time;
9478
+ return null;
9479
+ }, [cadence, weekday, time]);
9480
+ const quietHours = useMemo23(
9481
+ () => quiet ? { start: quietFrom, end: quietTo } : null,
9482
+ [quiet, quietFrom, quietTo]
9483
+ );
9484
+ async function scheduleIt() {
9485
+ setSaving(true);
9486
+ setError(null);
9487
+ setOutcomes(null);
9488
+ let subject = viewId;
9489
+ if (subject === "" || subject === "new") {
9490
+ const declared = await client.viewDeclare({
9491
+ table_id: tableId,
9492
+ spec: {
9493
+ name: subjectName?.trim() ? subjectName.trim() : name.trim() || "Weekly summary",
9494
+ filters: filters ?? {}
9495
+ }
9496
+ });
9497
+ if (!declared.ok) {
9498
+ setSaving(false);
9499
+ setError(declared.error);
9500
+ return;
9501
+ }
9502
+ subject = declared.data;
9503
+ setViewId(declared.data);
9504
+ }
9505
+ const who = recipients.length > 0 ? recipients : [""];
9506
+ const done = [];
9507
+ for (const userId of who) {
9508
+ const label = members?.find((m) => m.userId === userId)?.name ?? (userId === "" ? "you" : userId);
9509
+ const written = await client.subscriptionDeclare({
9510
+ table_id: tableId,
9511
+ spec: {
9512
+ name: name.trim() === "" ? "Weekly summary" : name.trim(),
9513
+ saved_view_id: subject,
9514
+ cadence,
9515
+ schedule,
9516
+ channel,
9517
+ quiet_hours: quietHours,
9518
+ ...userId === "" ? {} : { recipient_user_id: userId }
9519
+ }
9520
+ });
9521
+ if (written.ok) done.push({ userId, who: label, ruleId: written.data });
9522
+ else done.push({ userId, who: label, refused: written.error });
9523
+ }
9524
+ setSaving(false);
9525
+ setOutcomes(done);
9526
+ if (done.some((d) => d.ruleId)) onScheduled?.();
9527
+ }
9528
+ async function showOne(ruleId) {
9529
+ setPreviewing(true);
9530
+ const answered = await client.subscriptionPreview({ rule_id: ruleId });
9531
+ setPreviewing(false);
9532
+ if (!answered.ok) {
9533
+ setError(answered.error);
9534
+ return;
9535
+ }
9536
+ setPreview(answered.data);
9537
+ }
9538
+ if (views === null && !error) return /* @__PURE__ */ jsx36(Skeleton16, { className: cn30("h-56 w-full", className) });
9539
+ return /* @__PURE__ */ jsxs32("section", { className: cn30("flex flex-col gap-3", className), children: [
9540
+ /* @__PURE__ */ jsxs32("header", { className: "flex items-center gap-2", children: [
9541
+ /* @__PURE__ */ jsx36("h3", { className: "text-sm font-medium", children: "Send this on a schedule" }),
9542
+ /* @__PURE__ */ jsx36("div", { className: "flex-1" }),
9543
+ /* @__PURE__ */ jsx36(Button29, { size: "sm", disabled: saving, onClick: () => void scheduleIt(), children: saving ? "Scheduling\u2026" : "Schedule it" }),
9544
+ onClose ? /* @__PURE__ */ jsx36(Button29, { size: "sm", variant: "ghost", onClick: onClose, children: "Close" }) : null
9545
+ ] }),
9546
+ error ? /* @__PURE__ */ jsx36(RefusalNotice, { error }) : null,
9547
+ /* @__PURE__ */ jsxs32("label", { className: "flex flex-col gap-1", children: [
9548
+ /* @__PURE__ */ jsx36(Label5, { className: "text-xs font-medium", children: "What to call it" }),
9549
+ /* @__PURE__ */ jsx36(
9550
+ BasicInput10,
9551
+ {
9552
+ value: name,
9553
+ placeholder: "Monday donor summary",
9554
+ onChange: (e) => setName(e.target.value)
9555
+ }
9556
+ )
9557
+ ] }),
9558
+ savedViewId ? null : /* @__PURE__ */ jsxs32("label", { className: "flex flex-col gap-1", children: [
9559
+ /* @__PURE__ */ jsx36(Label5, { className: "text-xs font-medium", children: "What it summarises" }),
9560
+ /* @__PURE__ */ jsxs32(
9561
+ "select",
9562
+ {
9563
+ className: "h-9 rounded border bg-background px-2 text-sm",
9564
+ value: viewId,
9565
+ onChange: (e) => setViewId(e.target.value),
9566
+ children: [
9567
+ /* @__PURE__ */ jsx36("option", { value: "new", children: subjectName?.trim() ? `What I am looking at now (${subjectName.trim()})` : "What I am looking at now" }),
9568
+ (views ?? []).map((v) => /* @__PURE__ */ jsx36("option", { value: v.view_id, children: v.name }, v.view_id))
9569
+ ]
9570
+ }
9571
+ ),
9572
+ /* @__PURE__ */ jsx36("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." })
9573
+ ] }),
9574
+ /* @__PURE__ */ jsxs32("div", { className: "grid grid-cols-2 gap-2", children: [
9575
+ /* @__PURE__ */ jsxs32("label", { className: "flex flex-col gap-1", children: [
9576
+ /* @__PURE__ */ jsx36(Label5, { className: "text-xs font-medium", children: "How often" }),
9577
+ /* @__PURE__ */ jsx36(
9578
+ "select",
9579
+ {
9580
+ className: "h-9 rounded border bg-background px-2 text-sm",
9581
+ value: cadence,
9582
+ onChange: (e) => setCadence(e.target.value),
9583
+ children: (cadences.length > 0 ? cadences : ["hourly", "daily", "weekly"]).map((c) => /* @__PURE__ */ jsx36("option", { value: c, children: CADENCE_WORDS[c] ?? c }, c))
9584
+ }
9585
+ )
9586
+ ] }),
9587
+ cadence === "weekly" ? /* @__PURE__ */ jsxs32("label", { className: "flex flex-col gap-1", children: [
9588
+ /* @__PURE__ */ jsx36(Label5, { className: "text-xs font-medium", children: "Which day" }),
9589
+ /* @__PURE__ */ jsx36(
9590
+ "select",
9591
+ {
9592
+ className: "h-9 rounded border bg-background px-2 text-sm",
9593
+ value: weekday,
9594
+ onChange: (e) => setWeekday(e.target.value),
9595
+ children: WEEKDAYS.map((d) => /* @__PURE__ */ jsx36("option", { value: d, children: d[0].toUpperCase() + d.slice(1) }, d))
9596
+ }
9597
+ )
9598
+ ] }) : null,
9599
+ cadence === "weekly" || cadence === "daily" ? /* @__PURE__ */ jsxs32("label", { className: "flex flex-col gap-1", children: [
9600
+ /* @__PURE__ */ jsx36(Label5, { className: "text-xs font-medium", children: "At" }),
9601
+ /* @__PURE__ */ jsx36(BasicInput10, { type: "time", value: time, onChange: (e) => setTime(e.target.value) })
9602
+ ] }) : null,
9603
+ /* @__PURE__ */ jsxs32("label", { className: "flex flex-col gap-1", children: [
9604
+ /* @__PURE__ */ jsx36(Label5, { className: "text-xs font-medium", children: "Where it arrives" }),
9605
+ /* @__PURE__ */ jsx36(
9606
+ "select",
9607
+ {
9608
+ className: "h-9 rounded border bg-background px-2 text-sm",
9609
+ value: channel,
9610
+ onChange: (e) => setChannel(e.target.value),
9611
+ children: Object.entries(CHANNEL_WORDS).map(([key, words]) => /* @__PURE__ */ jsx36("option", { value: key, children: words }, key))
9612
+ }
9613
+ )
9614
+ ] })
9615
+ ] }),
9616
+ /* @__PURE__ */ jsxs32("div", { className: "flex flex-col gap-1.5", children: [
9617
+ /* @__PURE__ */ jsx36(Label5, { className: "text-xs font-medium", children: "Who to send it to" }),
9618
+ members === null ? /* @__PURE__ */ jsx36(Skeleton16, { className: "h-8 w-full" }) : members.length === 0 ? /* @__PURE__ */ jsx36("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__ */ jsxs32(Fragment16, { children: [
9619
+ /* @__PURE__ */ jsx36("div", { className: "flex flex-wrap gap-x-4 gap-y-1.5", children: members.map((m) => /* @__PURE__ */ jsxs32("label", { className: "flex items-center gap-1.5 text-xs", children: [
9620
+ /* @__PURE__ */ jsx36(
9621
+ Checkbox5,
9622
+ {
9623
+ checked: recipients.includes(m.userId),
9624
+ onCheckedChange: (on) => setRecipients(
9625
+ (prev) => on ? [...prev, m.userId] : prev.filter((u) => u !== m.userId)
9626
+ )
9627
+ }
9628
+ ),
9629
+ m.name
9630
+ ] }, m.userId)) }),
9631
+ /* @__PURE__ */ jsx36("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.` })
9632
+ ] })
9633
+ ] }),
9634
+ /* @__PURE__ */ jsxs32("label", { className: "flex items-center gap-1.5 text-xs", children: [
9635
+ /* @__PURE__ */ jsx36(Checkbox5, { checked: quiet, onCheckedChange: (on) => setQuiet(Boolean(on)) }),
9636
+ "Not between certain hours"
9637
+ ] }),
9638
+ quiet ? /* @__PURE__ */ jsxs32("div", { className: "flex items-center gap-2", children: [
9639
+ /* @__PURE__ */ jsx36(
9640
+ BasicInput10,
9641
+ {
9642
+ type: "time",
9643
+ className: "h-8 w-28",
9644
+ value: quietFrom,
9645
+ onChange: (e) => setQuietFrom(e.target.value)
9646
+ }
9647
+ ),
9648
+ /* @__PURE__ */ jsx36("span", { className: "text-xs text-muted-foreground", children: "and" }),
9649
+ /* @__PURE__ */ jsx36(
9650
+ BasicInput10,
9651
+ {
9652
+ type: "time",
9653
+ className: "h-8 w-28",
9654
+ value: quietTo,
9655
+ onChange: (e) => setQuietTo(e.target.value)
9656
+ }
9657
+ ),
9658
+ /* @__PURE__ */ jsx36("span", { className: "text-xs text-muted-foreground", children: "A send inside these hours waits until they end \u2014 it is never dropped." })
9659
+ ] }) : null,
9660
+ outcomes ? /* @__PURE__ */ jsxs32(Fragment16, { children: [
9661
+ /* @__PURE__ */ jsx36(Separator11, {}),
9662
+ /* @__PURE__ */ jsx36("div", { className: "flex flex-col gap-1.5", children: outcomes.map((o) => /* @__PURE__ */ jsx36("div", { className: "text-xs", children: o.ruleId ? /* @__PURE__ */ jsxs32("span", { children: [
9663
+ o.who,
9664
+ " will get it ",
9665
+ CADENCE_WORDS[cadence] ?? cadence,
9666
+ schedule ? `, ${schedule}` : "",
9667
+ ".",
9668
+ " ",
9669
+ /* @__PURE__ */ jsx36(
9670
+ Button29,
9671
+ {
9672
+ size: "sm",
9673
+ variant: "ghost",
9674
+ disabled: previewing,
9675
+ onClick: () => void showOne(o.ruleId),
9676
+ children: "Send me one now"
9677
+ }
9678
+ )
9679
+ ] }) : o.refused ? /* @__PURE__ */ jsx36(RefusalNotice, { error: o.refused }) : null }, o.userId || "me")) })
9680
+ ] }) : null,
9681
+ preview ? /* @__PURE__ */ jsxs32("div", { className: "rounded-md border bg-muted/40 p-2.5 text-xs", children: [
9682
+ /* @__PURE__ */ jsx36("p", { className: "font-medium", children: preview.subject }),
9683
+ /* @__PURE__ */ jsx36("p", { className: "mt-1 text-muted-foreground", children: preview.body }),
9684
+ preview.incomplete ? /* @__PURE__ */ jsx36("p", { className: "mt-1 text-destructive", children: preview.incomplete }) : null,
9685
+ preview.entered.length > 0 ? /* @__PURE__ */ jsxs32("p", { className: "mt-1", children: [
9686
+ /* @__PURE__ */ jsx36("span", { className: "font-medium", children: "Arrived:" }),
9687
+ " ",
9688
+ preview.entered.map((e) => e.name).join(", ")
9689
+ ] }) : null,
9690
+ preview.changed.length > 0 ? /* @__PURE__ */ jsxs32("p", { className: "mt-1", children: [
9691
+ /* @__PURE__ */ jsx36("span", { className: "font-medium", children: "Changed:" }),
9692
+ " ",
9693
+ preview.changed.map((e) => e.name).join(", ")
9694
+ ] }) : null,
9695
+ /* @__PURE__ */ jsx36("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." }),
9696
+ /* @__PURE__ */ jsx36(Button29, { size: "sm", variant: "ghost", className: "mt-1", onClick: () => setPreview(null), children: "Close" })
9697
+ ] }) : null
9698
+ ] });
9699
+ }
9700
+
9701
+ // src/SubscriptionsPanel.tsx
9702
+ import { useCallback as useCallback20, useEffect as useEffect23, useState as useState33 } from "react";
9703
+ import { useRecordsClient as useRecordsClient27 } from "@ai-matrx/records/react";
9704
+ import { Badge as Badge14, Button as Button30, Skeleton as Skeleton17, Switch as Switch2, cn as cn31 } from "@ai-matrx/design-system";
9705
+ import { jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
9406
9706
  function whenItFires(subscription) {
9407
9707
  if (subscription.cadence === "instant") return "as it happens";
9408
9708
  const every = subscription.cadence === "hourly" ? "an hourly summary" : subscription.cadence === "weekly" ? "a weekly summary" : "a daily summary";
9409
9709
  return subscription.schedule ? `${every}, ${subscription.schedule}` : every;
9410
9710
  }
9411
- var CHANNEL_WORDS = {
9711
+ var CHANNEL_WORDS2 = {
9412
9712
  in_app: "in the app",
9413
9713
  email: "by email \u2014 only if an address is on the account",
9414
9714
  sms: "by text \u2014 only if a number is on the account"
9415
9715
  };
9716
+ var DIGEST_SUGGESTION = "Email me a summary of this every Monday at 8 in the morning.";
9416
9717
  function SubscriptionsPanel({ tableId, className }) {
9417
- const client = useRecordsClient26();
9418
- const [rows, setRows] = useState32(null);
9419
- const [error, setError] = useState32(null);
9420
- const [busy, setBusy] = useState32(null);
9421
- const [preview, setPreview] = useState32(null);
9422
- const load = useCallback19(async () => {
9718
+ const client = useRecordsClient27();
9719
+ const [rows, setRows] = useState33(null);
9720
+ const [error, setError] = useState33(null);
9721
+ const [busy, setBusy] = useState33(null);
9722
+ const [preview, setPreview] = useState33(null);
9723
+ const [scheduling, setScheduling] = useState33(false);
9724
+ const host = useRecordsUi();
9725
+ const load = useCallback20(async () => {
9423
9726
  const answered = await client.subscriptions({ table_id: tableId });
9424
9727
  if (!answered.ok) {
9425
9728
  setError(answered.error);
@@ -9429,10 +9732,10 @@ function SubscriptionsPanel({ tableId, className }) {
9429
9732
  setError(null);
9430
9733
  setRows(answered.data);
9431
9734
  }, [client, tableId]);
9432
- useEffect22(() => {
9735
+ useEffect23(() => {
9433
9736
  void load();
9434
9737
  }, [load]);
9435
- const flip = useCallback19(
9738
+ const flip = useCallback20(
9436
9739
  async (subscription, on) => {
9437
9740
  setBusy(subscription.rule_id);
9438
9741
  const answered = await client.subscriptionMute({
@@ -9448,7 +9751,7 @@ function SubscriptionsPanel({ tableId, className }) {
9448
9751
  },
9449
9752
  [client, load]
9450
9753
  );
9451
- const showOne = useCallback19(
9754
+ const showOne = useCallback20(
9452
9755
  async (subscription) => {
9453
9756
  setBusy(subscription.rule_id);
9454
9757
  const answered = await client.subscriptionPreview({ rule_id: subscription.rule_id });
@@ -9462,25 +9765,57 @@ function SubscriptionsPanel({ tableId, className }) {
9462
9765
  },
9463
9766
  [client]
9464
9767
  );
9465
- if (rows === null) return /* @__PURE__ */ jsx36(Skeleton16, { className: cn30("h-32 w-full", className) });
9466
- return /* @__PURE__ */ jsxs32("section", { className: cn30("flex flex-col gap-3", className), children: [
9467
- /* @__PURE__ */ jsxs32("header", { className: "flex items-center gap-2", children: [
9468
- /* @__PURE__ */ jsx36("h3", { className: "text-sm font-medium", children: "Notifications" }),
9469
- /* @__PURE__ */ jsx36("span", { className: "text-xs text-muted-foreground", children: rows.length === 0 ? "none" : `${rows.filter((r) => !r.muted).length} on` })
9768
+ if (rows === null) return /* @__PURE__ */ jsx37(Skeleton17, { className: cn31("h-32 w-full", className) });
9769
+ return /* @__PURE__ */ jsxs33("section", { className: cn31("flex flex-col gap-3", className), children: [
9770
+ /* @__PURE__ */ jsxs33("header", { className: "flex items-center gap-2", children: [
9771
+ /* @__PURE__ */ jsx37("h3", { className: "text-sm font-medium", children: "Notifications" }),
9772
+ /* @__PURE__ */ jsx37("span", { className: "text-xs text-muted-foreground", children: rows.length === 0 ? "none" : `${rows.filter((r) => !r.muted).length} on` }),
9773
+ /* @__PURE__ */ jsx37("div", { className: "flex-1" }),
9774
+ rows.length > 0 ? /* @__PURE__ */ jsx37(
9775
+ Button30,
9776
+ {
9777
+ size: "sm",
9778
+ variant: scheduling ? "secondary" : "ghost",
9779
+ onClick: () => setScheduling((s) => !s),
9780
+ children: scheduling ? "Done" : "Schedule a summary"
9781
+ }
9782
+ ) : null
9470
9783
  ] }),
9471
- error ? /* @__PURE__ */ jsx36(RefusalNotice, { error }) : null,
9472
- rows.length === 0 ? /* @__PURE__ */ jsx36("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,
9473
- /* @__PURE__ */ jsx36("ul", { className: "flex flex-col gap-2", children: rows.map((subscription) => /* @__PURE__ */ jsxs32("li", { className: "rounded-md border p-2.5", children: [
9474
- /* @__PURE__ */ jsxs32("div", { className: "flex items-start gap-2", children: [
9475
- /* @__PURE__ */ jsxs32("div", { className: "min-w-0 flex-1", children: [
9476
- /* @__PURE__ */ jsx36("p", { className: "truncate text-sm font-medium", children: subscription.name }),
9477
- /* @__PURE__ */ jsxs32("p", { className: "mt-0.5 text-xs text-muted-foreground", children: [
9478
- CHANNEL_WORDS[subscription.channel] ?? `on the ${subscription.channel} channel`,
9784
+ error ? /* @__PURE__ */ jsx37(RefusalNotice, { error }) : null,
9785
+ scheduling ? /* @__PURE__ */ jsx37(
9786
+ DigestScheduler,
9787
+ {
9788
+ tableId,
9789
+ onScheduled: () => {
9790
+ void load();
9791
+ },
9792
+ onClose: () => setScheduling(false)
9793
+ }
9794
+ ) : null,
9795
+ rows.length === 0 && !scheduling ? /* @__PURE__ */ jsx37(
9796
+ BuildOrAsk,
9797
+ {
9798
+ mayBuild: true,
9799
+ onBuild: () => setScheduling(true),
9800
+ ...host.onAskForOne ? {
9801
+ onAsk: () => host.onAskForOne?.({ kind: "digest", tableId, suggestion: DIGEST_SUGGESTION })
9802
+ } : {},
9803
+ suggestion: DIGEST_SUGGESTION,
9804
+ buildLabel: "Schedule a summary",
9805
+ 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."
9806
+ }
9807
+ ) : null,
9808
+ /* @__PURE__ */ jsx37("ul", { className: "flex flex-col gap-2", children: rows.map((subscription) => /* @__PURE__ */ jsxs33("li", { className: "rounded-md border p-2.5", children: [
9809
+ /* @__PURE__ */ jsxs33("div", { className: "flex items-start gap-2", children: [
9810
+ /* @__PURE__ */ jsxs33("div", { className: "min-w-0 flex-1", children: [
9811
+ /* @__PURE__ */ jsx37("p", { className: "truncate text-sm font-medium", children: subscription.name }),
9812
+ /* @__PURE__ */ jsxs33("p", { className: "mt-0.5 text-xs text-muted-foreground", children: [
9813
+ CHANNEL_WORDS2[subscription.channel] ?? `on the ${subscription.channel} channel`,
9479
9814
  " \xB7 ",
9480
9815
  whenItFires(subscription)
9481
9816
  ] })
9482
9817
  ] }),
9483
- subscription.i_may_mute ? /* @__PURE__ */ jsx36(
9818
+ subscription.i_may_mute ? /* @__PURE__ */ jsx37(
9484
9819
  Switch2,
9485
9820
  {
9486
9821
  checked: !subscription.muted,
@@ -9488,27 +9823,27 @@ function SubscriptionsPanel({ tableId, className }) {
9488
9823
  "aria-label": `Tell me about ${subscription.name}`,
9489
9824
  onCheckedChange: (on) => void flip(subscription, on)
9490
9825
  }
9491
- ) : /* @__PURE__ */ jsx36(Badge14, { variant: "secondary", children: "someone else's" })
9826
+ ) : /* @__PURE__ */ jsx37(Badge14, { variant: "secondary", children: "someone else's" })
9492
9827
  ] }),
9493
- /* @__PURE__ */ jsx36("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." }),
9494
- /* @__PURE__ */ jsxs32("div", { className: "mt-1.5 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
9495
- subscription.next_digest_at ? /* @__PURE__ */ jsxs32("span", { children: [
9828
+ /* @__PURE__ */ jsx37("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." }),
9829
+ /* @__PURE__ */ jsxs33("div", { className: "mt-1.5 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
9830
+ subscription.next_digest_at ? /* @__PURE__ */ jsxs33("span", { children: [
9496
9831
  "Next summary ",
9497
9832
  new Date(subscription.next_digest_at).toLocaleString()
9498
- ] }) : subscription.cadence === "instant" ? null : subscription.muted ? /* @__PURE__ */ jsx36("span", { children: "No next summary while it is off." }) : null,
9499
- subscription.last_sent_at ? /* @__PURE__ */ jsxs32("span", { children: [
9833
+ ] }) : subscription.cadence === "instant" ? null : subscription.muted ? /* @__PURE__ */ jsx37("span", { children: "No next summary while it is off." }) : null,
9834
+ subscription.last_sent_at ? /* @__PURE__ */ jsxs33("span", { children: [
9500
9835
  "Last told you ",
9501
9836
  new Date(subscription.last_sent_at).toLocaleString()
9502
- ] }) : /* @__PURE__ */ jsx36("span", { children: "It has not told you anything yet." }),
9503
- subscription.quiet_hours ? /* @__PURE__ */ jsxs32("span", { children: [
9837
+ ] }) : /* @__PURE__ */ jsx37("span", { children: "It has not told you anything yet." }),
9838
+ subscription.quiet_hours ? /* @__PURE__ */ jsxs33("span", { children: [
9504
9839
  "Not between ",
9505
9840
  subscription.quiet_hours.start,
9506
9841
  " and ",
9507
9842
  subscription.quiet_hours.end,
9508
9843
  " \u2014 a send inside those hours waits until they end."
9509
9844
  ] }) : null,
9510
- subscription.cadence === "instant" ? null : /* @__PURE__ */ jsx36(
9511
- Button29,
9845
+ subscription.cadence === "instant" ? null : /* @__PURE__ */ jsx37(
9846
+ Button30,
9512
9847
  {
9513
9848
  size: "sm",
9514
9849
  variant: "ghost",
@@ -9518,66 +9853,66 @@ function SubscriptionsPanel({ tableId, className }) {
9518
9853
  }
9519
9854
  )
9520
9855
  ] }),
9521
- preview && preview.rule_id === subscription.rule_id ? /* @__PURE__ */ jsxs32("div", { className: "mt-2 rounded-md border bg-muted/40 p-2.5 text-xs", children: [
9522
- /* @__PURE__ */ jsx36("p", { className: "font-medium", children: preview.subject }),
9523
- /* @__PURE__ */ jsx36("p", { className: "mt-1 text-muted-foreground", children: preview.body }),
9856
+ preview && preview.rule_id === subscription.rule_id ? /* @__PURE__ */ jsxs33("div", { className: "mt-2 rounded-md border bg-muted/40 p-2.5 text-xs", children: [
9857
+ /* @__PURE__ */ jsx37("p", { className: "font-medium", children: preview.subject }),
9858
+ /* @__PURE__ */ jsx37("p", { className: "mt-1 text-muted-foreground", children: preview.body }),
9524
9859
  preview.incomplete ? (
9525
9860
  // Absent or honest: a subscription that cannot produce a summary
9526
9861
  // says which piece is missing instead of showing an empty one.
9527
- /* @__PURE__ */ jsx36("p", { className: "mt-1 text-destructive", children: preview.incomplete })
9862
+ /* @__PURE__ */ jsx37("p", { className: "mt-1 text-destructive", children: preview.incomplete })
9528
9863
  ) : null,
9529
- preview.entered.length > 0 ? /* @__PURE__ */ jsxs32("p", { className: "mt-1", children: [
9530
- /* @__PURE__ */ jsx36("span", { className: "font-medium", children: "Arrived:" }),
9864
+ preview.entered.length > 0 ? /* @__PURE__ */ jsxs33("p", { className: "mt-1", children: [
9865
+ /* @__PURE__ */ jsx37("span", { className: "font-medium", children: "Arrived:" }),
9531
9866
  " ",
9532
9867
  preview.entered.map((e) => e.name).join(", ")
9533
9868
  ] }) : null,
9534
- preview.left.length > 0 ? /* @__PURE__ */ jsxs32("p", { className: "mt-1", children: [
9535
- /* @__PURE__ */ jsx36("span", { className: "font-medium", children: "Left:" }),
9869
+ preview.left.length > 0 ? /* @__PURE__ */ jsxs33("p", { className: "mt-1", children: [
9870
+ /* @__PURE__ */ jsx37("span", { className: "font-medium", children: "Left:" }),
9536
9871
  " ",
9537
9872
  preview.left.map((e) => e.name).join(", ")
9538
9873
  ] }) : null,
9539
- preview.changed.length > 0 ? /* @__PURE__ */ jsxs32("p", { className: "mt-1", children: [
9540
- /* @__PURE__ */ jsx36("span", { className: "font-medium", children: "Changed:" }),
9874
+ preview.changed.length > 0 ? /* @__PURE__ */ jsxs33("p", { className: "mt-1", children: [
9875
+ /* @__PURE__ */ jsx37("span", { className: "font-medium", children: "Changed:" }),
9541
9876
  " ",
9542
9877
  preview.changed.map((e) => e.name).join(", ")
9543
9878
  ] }) : null,
9544
- /* @__PURE__ */ jsx36("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." }),
9545
- /* @__PURE__ */ jsx36(Button29, { size: "sm", variant: "ghost", className: "mt-1", onClick: () => setPreview(null), children: "Close" })
9879
+ /* @__PURE__ */ jsx37("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." }),
9880
+ /* @__PURE__ */ jsx37(Button30, { size: "sm", variant: "ghost", className: "mt-1", onClick: () => setPreview(null), children: "Close" })
9546
9881
  ] }) : null
9547
9882
  ] }, subscription.rule_id)) })
9548
9883
  ] });
9549
9884
  }
9550
9885
 
9551
9886
  // src/FormBuilder.tsx
9552
- import { useCallback as useCallback21, useEffect as useEffect24, useMemo as useMemo24, useState as useState34 } from "react";
9553
- import { useFields as useFields16, useRecordsClient as useRecordsClient27, useTable as useTable13 } from "@ai-matrx/records/react";
9887
+ import { useCallback as useCallback22, useEffect as useEffect25, useMemo as useMemo25, useState as useState35 } from "react";
9888
+ import { useFields as useFields16, useRecordsClient as useRecordsClient28, useTable as useTable13 } from "@ai-matrx/records/react";
9554
9889
  import { publicFormPath } from "@ai-matrx/records";
9555
9890
  import {
9556
- BasicInput as BasicInput10,
9891
+ BasicInput as BasicInput11,
9557
9892
  BasicTextarea as BasicTextarea5,
9558
- Button as Button31,
9559
- Checkbox as Checkbox5,
9560
- Label as Label5,
9561
- Skeleton as Skeleton18,
9562
- cn as cn32
9893
+ Button as Button32,
9894
+ Checkbox as Checkbox6,
9895
+ Label as Label6,
9896
+ Skeleton as Skeleton19,
9897
+ cn as cn33
9563
9898
  } from "@ai-matrx/design-system";
9564
9899
 
9565
9900
  // src/FormRunner.tsx
9566
- import { useCallback as useCallback20, useEffect as useEffect23, useMemo as useMemo23, useRef as useRef9, useState as useState33 } from "react";
9901
+ import { useCallback as useCallback21, useEffect as useEffect24, useMemo as useMemo24, useRef as useRef9, useState as useState34 } from "react";
9567
9902
  import { useFields as useFields15, useOptionalRecordsClient } from "@ai-matrx/records/react";
9568
- import { Button as Button30, Progress, Skeleton as Skeleton17, cn as cn31 } from "@ai-matrx/design-system";
9569
- import { Fragment as Fragment16, jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
9903
+ import { Button as Button31, Progress, Skeleton as Skeleton18, cn as cn32 } from "@ai-matrx/design-system";
9904
+ import { Fragment as Fragment17, jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
9570
9905
  function FormRunner(props) {
9571
9906
  if (props.fields && props.onSubmit) {
9572
- return /* @__PURE__ */ jsx37(FormStage, { ...props, fields: props.fields, onSubmit: props.onSubmit });
9907
+ return /* @__PURE__ */ jsx38(FormStage, { ...props, fields: props.fields, onSubmit: props.onSubmit });
9573
9908
  }
9574
- return /* @__PURE__ */ jsx37(ConnectedFormRunner, { ...props });
9909
+ return /* @__PURE__ */ jsx38(ConnectedFormRunner, { ...props });
9575
9910
  }
9576
9911
  function ConnectedFormRunner(props) {
9577
9912
  const client = useOptionalRecordsClient();
9578
9913
  const fields = useFields15(props.form.subject);
9579
9914
  const { form, className } = props;
9580
- const submit = useCallback20(
9915
+ const submit = useCallback21(
9581
9916
  async (values) => {
9582
9917
  if (!client) {
9583
9918
  return {
@@ -9600,7 +9935,7 @@ function ConnectedFormRunner(props) {
9600
9935
  },
9601
9936
  [client, form]
9602
9937
  );
9603
- const evaluate = useCallback20(
9938
+ const evaluate = useCallback21(
9604
9939
  async (expr, values) => {
9605
9940
  if (!client) return null;
9606
9941
  const answered = await client.ruleEval({ expr, values });
@@ -9609,9 +9944,9 @@ function ConnectedFormRunner(props) {
9609
9944
  },
9610
9945
  [client]
9611
9946
  );
9612
- if (fields.error) return /* @__PURE__ */ jsx37(RefusalNotice, { error: fields.error, className });
9613
- if (fields.loading) return /* @__PURE__ */ jsx37(Skeleton17, { className: cn31("h-40 w-full", className) });
9614
- return /* @__PURE__ */ jsx37(
9947
+ if (fields.error) return /* @__PURE__ */ jsx38(RefusalNotice, { error: fields.error, className });
9948
+ if (fields.loading) return /* @__PURE__ */ jsx38(Skeleton18, { className: cn32("h-40 w-full", className) });
9949
+ return /* @__PURE__ */ jsx38(
9615
9950
  FormStage,
9616
9951
  {
9617
9952
  ...props,
@@ -9634,16 +9969,16 @@ function FormStage({
9634
9969
  connected = false
9635
9970
  }) {
9636
9971
  const host = useRecordsUi();
9637
- const [answers, setAnswers] = useState33({});
9638
- const [at, setAt] = useState33(0);
9639
- const [error, setError] = useState33(null);
9640
- const [refusal, setRefusal] = useState33(null);
9641
- const [writing, setWriting] = useState33(false);
9642
- const [done, setDone] = useState33(null);
9643
- const [hidden, setHidden] = useState33({});
9972
+ const [answers, setAnswers] = useState34({});
9973
+ const [at, setAt] = useState34(0);
9974
+ const [error, setError] = useState34(null);
9975
+ const [refusal, setRefusal] = useState34(null);
9976
+ const [writing, setWriting] = useState34(false);
9977
+ const [done, setDone] = useState34(null);
9978
+ const [hidden, setHidden] = useState34({});
9644
9979
  const decoy = useRef9("");
9645
9980
  const stage = useRef9(null);
9646
- const questions = useMemo23(() => {
9981
+ const questions = useMemo24(() => {
9647
9982
  const byKey = new Map((fields ?? []).map((f) => [f.key, f]));
9648
9983
  return (form.questions ?? []).map((q) => {
9649
9984
  const field = byKey.get(q.field) ?? null;
@@ -9657,7 +9992,7 @@ function FormStage({
9657
9992
  };
9658
9993
  });
9659
9994
  }, [fields, form.questions]);
9660
- useEffect23(() => {
9995
+ useEffect24(() => {
9661
9996
  let cancelled = false;
9662
9997
  const conditional = questions.filter((q) => q.showIf);
9663
9998
  if (conditional.length === 0 || !evaluate) return;
@@ -9691,7 +10026,7 @@ function FormStage({
9691
10026
  const v = answers[q.key];
9692
10027
  return q.required && (v === void 0 || v === null || v === "");
9693
10028
  });
9694
- const submit = useCallback20(async () => {
10029
+ const submit = useCallback21(async () => {
9695
10030
  if (preview) {
9696
10031
  setDone("preview");
9697
10032
  return;
@@ -9728,51 +10063,51 @@ function FormStage({
9728
10063
  if (event.shiftKey) retreat();
9729
10064
  else advance();
9730
10065
  }
9731
- useEffect23(() => {
10066
+ useEffect24(() => {
9732
10067
  const input = stage.current?.querySelector(
9733
10068
  "input:not([tabindex='-1']), textarea, select, [role='combobox']"
9734
10069
  );
9735
10070
  input?.focus();
9736
10071
  }, [index, done]);
9737
10072
  if (done) {
9738
- return /* @__PURE__ */ jsxs33("section", { className: cn31("mx-auto max-w-xl py-10", centred && "text-center", className), children: [
9739
- /* @__PURE__ */ jsx37("h2", { className: "text-lg font-medium", children: form.thankYou?.title ?? "Thank you" }),
9740
- form.thankYou?.body ? /* @__PURE__ */ jsx37("p", { className: "mt-1 text-sm text-muted-foreground", children: form.thankYou.body }) : null,
9741
- /* @__PURE__ */ jsx37("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 })
10073
+ return /* @__PURE__ */ jsxs34("section", { className: cn32("mx-auto max-w-xl py-10", centred && "text-center", className), children: [
10074
+ /* @__PURE__ */ jsx38("h2", { className: "text-lg font-medium", children: form.thankYou?.title ?? "Thank you" }),
10075
+ form.thankYou?.body ? /* @__PURE__ */ jsx38("p", { className: "mt-1 text-sm text-muted-foreground", children: form.thankYou.body }) : null,
10076
+ /* @__PURE__ */ jsx38("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 })
9742
10077
  ] });
9743
10078
  }
9744
10079
  const unresolved = questions.filter((q) => !q.field);
9745
10080
  const unanswerable = !evaluate && questions.some((q) => q.showIf);
9746
10081
  const signedInPublic = connected && form.isPublic === true;
9747
- return /* @__PURE__ */ jsxs33(
10082
+ return /* @__PURE__ */ jsxs34(
9748
10083
  "section",
9749
10084
  {
9750
- className: cn31("mx-auto flex max-w-xl flex-col gap-3 py-4", centred && "text-center", className),
10085
+ className: cn32("mx-auto flex max-w-xl flex-col gap-3 py-4", centred && "text-center", className),
9751
10086
  onKeyDown,
9752
10087
  children: [
9753
- /* @__PURE__ */ jsxs33("header", { className: "flex items-center gap-3 text-xs text-muted-foreground", children: [
9754
- /* @__PURE__ */ jsx37(
10088
+ /* @__PURE__ */ jsxs34("header", { className: "flex items-center gap-3 text-xs text-muted-foreground", children: [
10089
+ /* @__PURE__ */ jsx38(
9755
10090
  Progress,
9756
10091
  {
9757
10092
  value: live.length === 0 ? 0 : (oneAtATime ? index + 1 : answered) / live.length * 100,
9758
10093
  className: "h-1 flex-1"
9759
10094
  }
9760
10095
  ),
9761
- /* @__PURE__ */ jsx37("span", { className: "tabular-nums", children: oneAtATime ? `${index + 1} of ${live.length}` : `${answered} of ${live.length}` })
10096
+ /* @__PURE__ */ jsx38("span", { className: "tabular-nums", children: oneAtATime ? `${index + 1} of ${live.length}` : `${answered} of ${live.length}` })
9762
10097
  ] }),
9763
- signedInPublic ? /* @__PURE__ */ jsx37("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,
9764
- unanswerable ? /* @__PURE__ */ jsx37("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,
9765
- unresolved.length > 0 ? /* @__PURE__ */ jsxs33("p", { className: "rounded border border-dashed px-2 py-1 text-left text-xs text-destructive", children: [
10098
+ signedInPublic ? /* @__PURE__ */ jsx38("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,
10099
+ unanswerable ? /* @__PURE__ */ jsx38("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,
10100
+ unresolved.length > 0 ? /* @__PURE__ */ jsxs34("p", { className: "rounded border border-dashed px-2 py-1 text-left text-xs text-destructive", children: [
9766
10101
  unresolved.map((q) => q.key).join(", "),
9767
10102
  " ",
9768
10103
  unresolved.length === 1 ? "is a question" : "are questions",
9769
10104
  " 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."
9770
10105
  ] }) : null,
9771
- form.intro && index === 0 ? /* @__PURE__ */ jsx37("p", { className: "text-sm text-muted-foreground", children: form.intro }) : null,
9772
- error ? /* @__PURE__ */ jsx37(RefusalNotice, { error, className: "text-left" }) : null,
9773
- refusal ? /* @__PURE__ */ jsx37("p", { role: "alert", className: "rounded border border-destructive/40 px-2 py-1 text-left text-xs text-destructive", children: refusal }) : null,
9774
- /* @__PURE__ */ jsxs33("div", { ref: stage, className: "flex flex-col gap-4 text-left", children: [
9775
- (oneAtATime ? current ? [current] : [] : live).map((q) => /* @__PURE__ */ jsx37(
10106
+ form.intro && index === 0 ? /* @__PURE__ */ jsx38("p", { className: "text-sm text-muted-foreground", children: form.intro }) : null,
10107
+ error ? /* @__PURE__ */ jsx38(RefusalNotice, { error, className: "text-left" }) : null,
10108
+ refusal ? /* @__PURE__ */ jsx38("p", { role: "alert", className: "rounded border border-destructive/40 px-2 py-1 text-left text-xs text-destructive", children: refusal }) : null,
10109
+ /* @__PURE__ */ jsxs34("div", { ref: stage, className: "flex flex-col gap-4 text-left", children: [
10110
+ (oneAtATime ? current ? [current] : [] : live).map((q) => /* @__PURE__ */ jsx38(
9776
10111
  Question,
9777
10112
  {
9778
10113
  question: q,
@@ -9782,11 +10117,11 @@ function FormStage({
9782
10117
  },
9783
10118
  q.key
9784
10119
  )),
9785
- live.length === 0 ? /* @__PURE__ */ jsx37("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
10120
+ live.length === 0 ? /* @__PURE__ */ jsx38("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
9786
10121
  ] }),
9787
- honeypotKey ? /* @__PURE__ */ jsxs33("div", { "aria-hidden": true, className: "pointer-events-none absolute left-[-9999px] h-px w-px overflow-hidden", children: [
9788
- /* @__PURE__ */ jsx37("label", { htmlFor: `hp-${honeypotKey}`, children: "Leave this field empty" }),
9789
- /* @__PURE__ */ jsx37(
10122
+ honeypotKey ? /* @__PURE__ */ jsxs34("div", { "aria-hidden": true, className: "pointer-events-none absolute left-[-9999px] h-px w-px overflow-hidden", children: [
10123
+ /* @__PURE__ */ jsx38("label", { htmlFor: `hp-${honeypotKey}`, children: "Leave this field empty" }),
10124
+ /* @__PURE__ */ jsx38(
9790
10125
  "input",
9791
10126
  {
9792
10127
  id: `hp-${honeypotKey}`,
@@ -9801,16 +10136,16 @@ function FormStage({
9801
10136
  }
9802
10137
  )
9803
10138
  ] }) : null,
9804
- /* @__PURE__ */ jsxs33("footer", { className: cn31("flex flex-wrap items-center gap-2", centred && "justify-center"), children: [
9805
- oneAtATime && index > 0 ? /* @__PURE__ */ jsx37(Button30, { size: "sm", variant: "ghost", onClick: retreat, children: "Back" }) : null,
9806
- oneAtATime && index < live.length - 1 ? /* @__PURE__ */ jsx37(Button30, { size: "sm", onClick: advance, children: "Next" }) : /* @__PURE__ */ jsx37(Button30, { size: "sm", disabled: writing || missing.length > 0, onClick: () => void submit(), children: writing ? "Sending\u2026" : form.submitLabel ?? "Submit" }),
9807
- missing.length > 0 && (!oneAtATime || index === live.length - 1) ? /* @__PURE__ */ jsxs33("span", { className: "text-xs text-muted-foreground", children: [
10139
+ /* @__PURE__ */ jsxs34("footer", { className: cn32("flex flex-wrap items-center gap-2", centred && "justify-center"), children: [
10140
+ oneAtATime && index > 0 ? /* @__PURE__ */ jsx38(Button31, { size: "sm", variant: "ghost", onClick: retreat, children: "Back" }) : null,
10141
+ oneAtATime && index < live.length - 1 ? /* @__PURE__ */ jsx38(Button31, { size: "sm", onClick: advance, children: "Next" }) : /* @__PURE__ */ jsx38(Button31, { size: "sm", disabled: writing || missing.length > 0, onClick: () => void submit(), children: writing ? "Sending\u2026" : form.submitLabel ?? "Submit" }),
10142
+ missing.length > 0 && (!oneAtATime || index === live.length - 1) ? /* @__PURE__ */ jsxs34("span", { className: "text-xs text-muted-foreground", children: [
9808
10143
  missing.map((q) => q.ask).join(", "),
9809
10144
  " still ",
9810
10145
  missing.length === 1 ? "needs" : "need",
9811
10146
  " an answer."
9812
10147
  ] }) : null,
9813
- preview ? /* @__PURE__ */ jsx37("span", { className: "text-xs text-muted-foreground", children: "Preview \u2014 nothing is written." }) : null
10148
+ preview ? /* @__PURE__ */ jsx38("span", { className: "text-xs text-muted-foreground", children: "Preview \u2014 nothing is written." }) : null
9814
10149
  ] })
9815
10150
  ]
9816
10151
  }
@@ -9822,16 +10157,16 @@ function Question({
9822
10157
  onChange,
9823
10158
  upload
9824
10159
  }) {
9825
- const [uploadError, setUploadError] = useState33(null);
10160
+ const [uploadError, setUploadError] = useState34(null);
9826
10161
  const field = question.field;
9827
10162
  if (!field) return null;
9828
10163
  const id = `form-${field.key}`;
9829
10164
  const isAttachment = editorKindFor(field) === "attachment";
9830
- return /* @__PURE__ */ jsxs33("div", { className: "flex flex-col gap-1.5", children: [
9831
- /* @__PURE__ */ jsx37(FieldLabel, { field: { ...field, label: question.ask, required: question.required }, htmlFor: id }),
9832
- question.help ? /* @__PURE__ */ jsx37("p", { className: "text-xs text-muted-foreground", children: question.help }) : null,
9833
- isAttachment && !upload ? /* @__PURE__ */ jsx37("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: NO_UPLOAD_REASON }) : isAttachment ? /* @__PURE__ */ jsxs33(Fragment16, { children: [
9834
- /* @__PURE__ */ jsx37(
10165
+ return /* @__PURE__ */ jsxs34("div", { className: "flex flex-col gap-1.5", children: [
10166
+ /* @__PURE__ */ jsx38(FieldLabel, { field: { ...field, label: question.ask, required: question.required }, htmlFor: id }),
10167
+ question.help ? /* @__PURE__ */ jsx38("p", { className: "text-xs text-muted-foreground", children: question.help }) : null,
10168
+ isAttachment && !upload ? /* @__PURE__ */ jsx38("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: NO_UPLOAD_REASON }) : isAttachment ? /* @__PURE__ */ jsxs34(Fragment17, { children: [
10169
+ /* @__PURE__ */ jsx38(
9835
10170
  "input",
9836
10171
  {
9837
10172
  id,
@@ -9849,31 +10184,31 @@ function Question({
9849
10184
  }
9850
10185
  }
9851
10186
  ),
9852
- uploadError ? /* @__PURE__ */ jsx37("p", { className: "text-xs text-destructive", children: uploadError }) : null
9853
- ] }) : /* @__PURE__ */ jsx37(FieldControl, { field, value, onChange, id })
10187
+ uploadError ? /* @__PURE__ */ jsx38("p", { className: "text-xs text-destructive", children: uploadError }) : null
10188
+ ] }) : /* @__PURE__ */ jsx38(FieldControl, { field, value, onChange, id })
9854
10189
  ] });
9855
10190
  }
9856
10191
 
9857
10192
  // src/FormBuilder.tsx
9858
- import { Fragment as Fragment17, jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
10193
+ import { Fragment as Fragment18, jsx as jsx39, jsxs as jsxs35 } from "react/jsx-runtime";
9859
10194
  function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
9860
- const client = useRecordsClient27();
10195
+ const client = useRecordsClient28();
9861
10196
  const host = useRecordsUi();
9862
10197
  const claimSeed = useSeedGuard();
9863
10198
  const table = useTable13(tableId);
9864
10199
  const rights = useTableRights(table.data);
9865
10200
  const fields = useFields16(tableId);
9866
- const [forms, setForms] = useState34(null);
9867
- const [error, setError] = useState34(null);
9868
- const [activeId, setActiveId] = useState34(activeFormId ?? null);
9869
- const [draft, setDraft] = useState34(null);
9870
- const [saving, setSaving] = useState34(false);
9871
- const [saved, setSaved] = useState34(null);
9872
- const [publishing, setPublishing] = useState34(false);
9873
- const [copied, setCopied] = useState34(false);
9874
- const [shownUrl, setShownUrl] = useState34(null);
10201
+ const [forms, setForms] = useState35(null);
10202
+ const [error, setError] = useState35(null);
10203
+ const [activeId, setActiveId] = useState35(activeFormId ?? null);
10204
+ const [draft, setDraft] = useState35(null);
10205
+ const [saving, setSaving] = useState35(false);
10206
+ const [saved, setSaved] = useState35(null);
10207
+ const [publishing, setPublishing] = useState35(false);
10208
+ const [copied, setCopied] = useState35(false);
10209
+ const [shownUrl, setShownUrl] = useState35(null);
9875
10210
  const publicOrigin = host.publicOrigin ?? (typeof window === "undefined" ? "" : window.location.origin);
9876
- const load = useCallback21(async () => {
10211
+ const load = useCallback22(async () => {
9877
10212
  const answered = await client.forms({ table_id: tableId });
9878
10213
  if (!answered.ok) {
9879
10214
  setError(answered.error);
@@ -9900,17 +10235,17 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
9900
10235
  setError(null);
9901
10236
  setForms(mine);
9902
10237
  }, [client, tableId, seed, claimSeed]);
9903
- useEffect24(() => {
10238
+ useEffect25(() => {
9904
10239
  void load();
9905
10240
  }, [load]);
9906
- useEffect24(() => {
10241
+ useEffect25(() => {
9907
10242
  if (!forms || forms.length === 0) return;
9908
10243
  const chosen = forms.find((f) => f.id === (activeFormId ?? activeId)) ?? forms[0];
9909
10244
  if (chosen.id !== activeId) setActiveId(chosen.id);
9910
10245
  setDraft(chosen);
9911
10246
  onActiveForm?.(chosen);
9912
10247
  }, [forms, activeFormId]);
9913
- const byKey = useMemo24(() => new Map((fields.data ?? []).map((f) => [f.key, f])), [fields.data]);
10248
+ const byKey = useMemo25(() => new Map((fields.data ?? []).map((f) => [f.key, f])), [fields.data]);
9914
10249
  function patch(change) {
9915
10250
  setDraft((prev) => prev ? { ...prev, ...change } : prev);
9916
10251
  setSaved(null);
@@ -9970,26 +10305,26 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
9970
10305
  setActiveId(written.data);
9971
10306
  await load();
9972
10307
  }
9973
- if (fields.error) return /* @__PURE__ */ jsx38(RefusalNotice, { error: fields.error, className });
10308
+ if (fields.error) return /* @__PURE__ */ jsx39(RefusalNotice, { error: fields.error, className });
9974
10309
  if (error) {
9975
- return /* @__PURE__ */ jsx38(
10310
+ return /* @__PURE__ */ jsx39(
9976
10311
  RefusalNotice,
9977
10312
  {
9978
10313
  error,
9979
10314
  className,
9980
- actions: /* @__PURE__ */ jsx38(Button31, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
10315
+ actions: /* @__PURE__ */ jsx39(Button32, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
9981
10316
  }
9982
10317
  );
9983
10318
  }
9984
- if (fields.loading || forms === null) return /* @__PURE__ */ jsx38(Skeleton18, { className: cn32("h-64 w-full", className) });
10319
+ if (fields.loading || forms === null) return /* @__PURE__ */ jsx39(Skeleton19, { className: cn33("h-64 w-full", className) });
9985
10320
  if (!rights.admin) {
9986
- return /* @__PURE__ */ jsx38("p", { className: cn32("text-xs text-muted-foreground", className), children: rights.why("structure") });
10321
+ return /* @__PURE__ */ jsx39("p", { className: cn33("text-xs text-muted-foreground", className), children: rights.why("structure") });
9987
10322
  }
9988
- return /* @__PURE__ */ jsxs34("div", { className: cn32("flex min-h-0 gap-3", className), children: [
9989
- /* @__PURE__ */ jsxs34("div", { className: "flex min-w-0 flex-1 flex-col gap-2 overflow-auto", children: [
9990
- /* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-1 overflow-x-auto", role: "group", "aria-label": "Forms", children: [
9991
- forms.map((form) => /* @__PURE__ */ jsx38(
9992
- Button31,
10323
+ return /* @__PURE__ */ jsxs35("div", { className: cn33("flex min-h-0 gap-3", className), children: [
10324
+ /* @__PURE__ */ jsxs35("div", { className: "flex min-w-0 flex-1 flex-col gap-2 overflow-auto", children: [
10325
+ /* @__PURE__ */ jsxs35("div", { className: "flex items-center gap-1 overflow-x-auto", role: "group", "aria-label": "Forms", children: [
10326
+ forms.map((form) => /* @__PURE__ */ jsx39(
10327
+ Button32,
9993
10328
  {
9994
10329
  size: "sm",
9995
10330
  variant: form.id === activeId ? "secondary" : "ghost",
@@ -10002,14 +10337,14 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10002
10337
  },
10003
10338
  form.id
10004
10339
  )),
10005
- (fields.data ?? []).length > 0 ? /* @__PURE__ */ jsx38(Button31, { size: "sm", variant: "ghost", onClick: () => void create(`Form ${forms.length + 1}`), children: "New form" }) : null,
10006
- /* @__PURE__ */ jsxs34("span", { className: "ml-auto flex items-center gap-2", children: [
10007
- saved ? /* @__PURE__ */ jsx38("span", { className: "text-xs text-muted-foreground", children: saved }) : null,
10008
- /* @__PURE__ */ jsx38(Button31, { size: "sm", disabled: saving || !draft, onClick: () => void save(), children: saving ? "Saving\u2026" : "Save" })
10340
+ (fields.data ?? []).length > 0 ? /* @__PURE__ */ jsx39(Button32, { size: "sm", variant: "ghost", onClick: () => void create(`Form ${forms.length + 1}`), children: "New form" }) : null,
10341
+ /* @__PURE__ */ jsxs35("span", { className: "ml-auto flex items-center gap-2", children: [
10342
+ saved ? /* @__PURE__ */ jsx39("span", { className: "text-xs text-muted-foreground", children: saved }) : null,
10343
+ /* @__PURE__ */ jsx39(Button32, { size: "sm", disabled: saving || !draft, onClick: () => void save(), children: saving ? "Saving\u2026" : "Save" })
10009
10344
  ] })
10010
10345
  ] }),
10011
- !draft ? /* @__PURE__ */ jsx38("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__ */ jsxs34(Fragment17, { children: [
10012
- /* @__PURE__ */ jsx38(
10346
+ !draft ? /* @__PURE__ */ jsx39("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__ */ jsxs35(Fragment18, { children: [
10347
+ /* @__PURE__ */ jsx39(
10013
10348
  PublishRow,
10014
10349
  {
10015
10350
  url: `${publicOrigin}${publicFormPath(draft.id)}`,
@@ -10023,26 +10358,26 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10023
10358
  onCopy: (url) => void copyLink(url)
10024
10359
  }
10025
10360
  ),
10026
- /* @__PURE__ */ jsxs34("div", { className: "grid grid-cols-2 gap-2", children: [
10027
- /* @__PURE__ */ jsxs34("label", { className: "flex flex-col gap-1", children: [
10028
- /* @__PURE__ */ jsx38(Label5, { className: "text-xs font-medium", children: "Name" }),
10029
- /* @__PURE__ */ jsx38(BasicInput10, { value: draft.name, onChange: (e) => patch({ name: e.target.value }) })
10361
+ /* @__PURE__ */ jsxs35("div", { className: "grid grid-cols-2 gap-2", children: [
10362
+ /* @__PURE__ */ jsxs35("label", { className: "flex flex-col gap-1", children: [
10363
+ /* @__PURE__ */ jsx39(Label6, { className: "text-xs font-medium", children: "Name" }),
10364
+ /* @__PURE__ */ jsx39(BasicInput11, { value: draft.name, onChange: (e) => patch({ name: e.target.value }) })
10030
10365
  ] }),
10031
- /* @__PURE__ */ jsxs34("label", { className: "flex flex-col gap-1", children: [
10032
- /* @__PURE__ */ jsx38(Label5, { className: "text-xs font-medium", children: "Flow" }),
10033
- /* @__PURE__ */ jsx38(
10366
+ /* @__PURE__ */ jsxs35("label", { className: "flex flex-col gap-1", children: [
10367
+ /* @__PURE__ */ jsx39(Label6, { className: "text-xs font-medium", children: "Flow" }),
10368
+ /* @__PURE__ */ jsx39(
10034
10369
  "select",
10035
10370
  {
10036
10371
  className: "h-9 rounded border bg-background px-2 text-sm",
10037
10372
  value: draft.flow ?? "one-at-a-time",
10038
10373
  onChange: (e) => patch({ flow: e.target.value }),
10039
- children: FORM_FLOWS.map((flow) => /* @__PURE__ */ jsx38("option", { value: flow, children: flow === "one-at-a-time" ? "One question at a time" : "All on one page" }, flow))
10374
+ children: FORM_FLOWS.map((flow) => /* @__PURE__ */ jsx39("option", { value: flow, children: flow === "one-at-a-time" ? "One question at a time" : "All on one page" }, flow))
10040
10375
  }
10041
10376
  )
10042
10377
  ] }),
10043
- /* @__PURE__ */ jsxs34("label", { className: "col-span-2 flex flex-col gap-1", children: [
10044
- /* @__PURE__ */ jsx38(Label5, { className: "text-xs font-medium", children: "Intro" }),
10045
- /* @__PURE__ */ jsx38(
10378
+ /* @__PURE__ */ jsxs35("label", { className: "col-span-2 flex flex-col gap-1", children: [
10379
+ /* @__PURE__ */ jsx39(Label6, { className: "text-xs font-medium", children: "Intro" }),
10380
+ /* @__PURE__ */ jsx39(
10046
10381
  BasicTextarea5,
10047
10382
  {
10048
10383
  rows: 2,
@@ -10051,10 +10386,10 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10051
10386
  }
10052
10387
  )
10053
10388
  ] }),
10054
- /* @__PURE__ */ jsxs34("label", { className: "flex flex-col gap-1", children: [
10055
- /* @__PURE__ */ jsx38(Label5, { className: "text-xs font-medium", children: "Submit button" }),
10056
- /* @__PURE__ */ jsx38(
10057
- BasicInput10,
10389
+ /* @__PURE__ */ jsxs35("label", { className: "flex flex-col gap-1", children: [
10390
+ /* @__PURE__ */ jsx39(Label6, { className: "text-xs font-medium", children: "Submit button" }),
10391
+ /* @__PURE__ */ jsx39(
10392
+ BasicInput11,
10058
10393
  {
10059
10394
  value: draft.submitLabel ?? "",
10060
10395
  placeholder: "Submit",
@@ -10062,10 +10397,10 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10062
10397
  }
10063
10398
  )
10064
10399
  ] }),
10065
- /* @__PURE__ */ jsxs34("label", { className: "flex flex-col gap-1", children: [
10066
- /* @__PURE__ */ jsx38(Label5, { className: "text-xs font-medium", children: "Thank-you title" }),
10067
- /* @__PURE__ */ jsx38(
10068
- BasicInput10,
10400
+ /* @__PURE__ */ jsxs35("label", { className: "flex flex-col gap-1", children: [
10401
+ /* @__PURE__ */ jsx39(Label6, { className: "text-xs font-medium", children: "Thank-you title" }),
10402
+ /* @__PURE__ */ jsx39(
10403
+ BasicInput11,
10069
10404
  {
10070
10405
  value: draft.thankYou?.title ?? "",
10071
10406
  placeholder: "Thank you",
@@ -10076,10 +10411,10 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10076
10411
  )
10077
10412
  ] })
10078
10413
  ] }),
10079
- /* @__PURE__ */ jsxs34("div", { className: "flex flex-col gap-1", children: [
10080
- /* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
10081
- /* @__PURE__ */ jsx38("span", { className: "font-medium text-foreground", children: "Questions" }),
10082
- /* @__PURE__ */ jsxs34("span", { children: [
10414
+ /* @__PURE__ */ jsxs35("div", { className: "flex flex-col gap-1", children: [
10415
+ /* @__PURE__ */ jsxs35("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
10416
+ /* @__PURE__ */ jsx39("span", { className: "font-medium text-foreground", children: "Questions" }),
10417
+ /* @__PURE__ */ jsxs35("span", { children: [
10083
10418
  draft.questions.length,
10084
10419
  " of this table's ",
10085
10420
  fields.data?.length ?? 0,
@@ -10090,10 +10425,10 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10090
10425
  const index = draft.questions.findIndex((q) => q.field === field.key);
10091
10426
  const asked = index >= 0;
10092
10427
  const question = asked ? draft.questions[index] : null;
10093
- return /* @__PURE__ */ jsxs34("div", { className: "rounded border px-2 py-1.5", children: [
10094
- /* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-2", children: [
10095
- /* @__PURE__ */ jsx38(
10096
- Checkbox5,
10428
+ return /* @__PURE__ */ jsxs35("div", { className: "rounded border px-2 py-1.5", children: [
10429
+ /* @__PURE__ */ jsxs35("div", { className: "flex items-center gap-2", children: [
10430
+ /* @__PURE__ */ jsx39(
10431
+ Checkbox6,
10097
10432
  {
10098
10433
  checked: asked,
10099
10434
  "aria-label": `Ask for ${fieldName(field)}`,
@@ -10102,13 +10437,13 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10102
10437
  })
10103
10438
  }
10104
10439
  ),
10105
- /* @__PURE__ */ jsx38("span", { className: "text-xs font-medium", children: fieldName(field) }),
10106
- /* @__PURE__ */ jsx38("span", { className: "text-xs text-muted-foreground", children: field.key }),
10107
- field.required ? /* @__PURE__ */ jsx38("span", { className: "text-xs text-destructive", children: "required" }) : null
10440
+ /* @__PURE__ */ jsx39("span", { className: "text-xs font-medium", children: fieldName(field) }),
10441
+ /* @__PURE__ */ jsx39("span", { className: "text-xs text-muted-foreground", children: field.key }),
10442
+ field.required ? /* @__PURE__ */ jsx39("span", { className: "text-xs text-destructive", children: "required" }) : null
10108
10443
  ] }),
10109
- asked && question ? /* @__PURE__ */ jsxs34("div", { className: "mt-1.5 grid grid-cols-2 gap-2 pl-6", children: [
10110
- /* @__PURE__ */ jsx38(
10111
- BasicInput10,
10444
+ asked && question ? /* @__PURE__ */ jsxs35("div", { className: "mt-1.5 grid grid-cols-2 gap-2 pl-6", children: [
10445
+ /* @__PURE__ */ jsx39(
10446
+ BasicInput11,
10112
10447
  {
10113
10448
  className: "h-8 text-xs",
10114
10449
  placeholder: fieldName(field),
@@ -10117,8 +10452,8 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10117
10452
  onChange: (e) => patchQuestion(index, { ask: e.target.value || null })
10118
10453
  }
10119
10454
  ),
10120
- /* @__PURE__ */ jsx38(
10121
- BasicInput10,
10455
+ /* @__PURE__ */ jsx39(
10456
+ BasicInput11,
10122
10457
  {
10123
10458
  className: "h-8 text-xs",
10124
10459
  placeholder: "Help text",
@@ -10127,7 +10462,7 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10127
10462
  onChange: (e) => patchQuestion(index, { help: e.target.value || null })
10128
10463
  }
10129
10464
  ),
10130
- /* @__PURE__ */ jsx38(
10465
+ /* @__PURE__ */ jsx39(
10131
10466
  Condition,
10132
10467
  {
10133
10468
  question,
@@ -10138,7 +10473,7 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10138
10473
  ] }) : null
10139
10474
  ] }, field.id);
10140
10475
  }),
10141
- draft.questions.filter((q) => !byKey.has(q.field)).map((q) => /* @__PURE__ */ jsxs34("p", { className: "text-xs text-destructive", children: [
10476
+ draft.questions.filter((q) => !byKey.has(q.field)).map((q) => /* @__PURE__ */ jsxs35("p", { className: "text-xs text-destructive", children: [
10142
10477
  'This form asks for "',
10143
10478
  q.field,
10144
10479
  '" and this table has no such Field. It is shown here rather than quietly dropped.'
@@ -10146,9 +10481,9 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
10146
10481
  ] })
10147
10482
  ] })
10148
10483
  ] }),
10149
- draft ? /* @__PURE__ */ jsxs34("aside", { className: "w-96 shrink-0 overflow-auto rounded border p-2", children: [
10150
- /* @__PURE__ */ jsx38("h4", { className: "px-1 text-sm font-medium", children: draft.name }),
10151
- /* @__PURE__ */ jsx38(FormRunner, { form: draft, preview: true })
10484
+ draft ? /* @__PURE__ */ jsxs35("aside", { className: "w-96 shrink-0 overflow-auto rounded border p-2", children: [
10485
+ /* @__PURE__ */ jsx39("h4", { className: "px-1 text-sm font-medium", children: draft.name }),
10486
+ /* @__PURE__ */ jsx39(FormRunner, { form: draft, preview: true })
10152
10487
  ] }) : null
10153
10488
  ] });
10154
10489
  }
@@ -10164,10 +10499,10 @@ function PublishRow({
10164
10499
  onCopy
10165
10500
  }) {
10166
10501
  const open = state === "open";
10167
- return /* @__PURE__ */ jsxs34("div", { className: "flex flex-col gap-1.5 rounded border px-2.5 py-2", children: [
10168
- /* @__PURE__ */ jsxs34("div", { className: "flex flex-wrap items-center gap-2", children: [
10169
- mayPublish ? /* @__PURE__ */ jsx38(
10170
- Button31,
10502
+ return /* @__PURE__ */ jsxs35("div", { className: "flex flex-col gap-1.5 rounded border px-2.5 py-2", children: [
10503
+ /* @__PURE__ */ jsxs35("div", { className: "flex flex-wrap items-center gap-2", children: [
10504
+ mayPublish ? /* @__PURE__ */ jsx39(
10505
+ Button32,
10171
10506
  {
10172
10507
  size: "sm",
10173
10508
  variant: open ? "ghost" : "default",
@@ -10176,8 +10511,8 @@ function PublishRow({
10176
10511
  children: busy ? "\u2026" : open ? "Unpublish" : "Publish"
10177
10512
  }
10178
10513
  ) : null,
10179
- state !== "draft" ? /* @__PURE__ */ jsxs34(Fragment17, { children: [
10180
- /* @__PURE__ */ jsx38(
10514
+ state !== "draft" ? /* @__PURE__ */ jsxs35(Fragment18, { children: [
10515
+ /* @__PURE__ */ jsx39(
10181
10516
  "a",
10182
10517
  {
10183
10518
  href: url,
@@ -10187,12 +10522,12 @@ function PublishRow({
10187
10522
  children: url
10188
10523
  }
10189
10524
  ),
10190
- /* @__PURE__ */ jsx38(Button31, { size: "sm", variant: "outline", onClick: () => onCopy(url), children: copied ? "Copied" : "Copy link" })
10525
+ /* @__PURE__ */ jsx39(Button32, { size: "sm", variant: "outline", onClick: () => onCopy(url), children: copied ? "Copied" : "Copy link" })
10191
10526
  ] }) : null
10192
10527
  ] }),
10193
- /* @__PURE__ */ jsx38("p", { className: "text-xs text-muted-foreground", children: FORM_STATE_WORDS[state] }),
10194
- !mayPublish ? /* @__PURE__ */ jsx38("p", { className: "text-xs text-muted-foreground", children: why }) : null,
10195
- shownUrl ? /* @__PURE__ */ jsxs34("p", { className: "break-all rounded border border-dashed px-2 py-1 text-xs", children: [
10528
+ /* @__PURE__ */ jsx39("p", { className: "text-xs text-muted-foreground", children: FORM_STATE_WORDS[state] }),
10529
+ !mayPublish ? /* @__PURE__ */ jsx39("p", { className: "text-xs text-muted-foreground", children: why }) : null,
10530
+ shownUrl ? /* @__PURE__ */ jsxs35("p", { className: "break-all rounded border border-dashed px-2 py-1 text-xs", children: [
10196
10531
  "This browser would not let the page copy for you, so here it is to copy by hand: ",
10197
10532
  shownUrl
10198
10533
  ] }) : null
@@ -10203,7 +10538,7 @@ function Condition({
10203
10538
  fieldKeys,
10204
10539
  onChange
10205
10540
  }) {
10206
- return /* @__PURE__ */ jsx38(
10541
+ return /* @__PURE__ */ jsx39(
10207
10542
  ConditionRow,
10208
10543
  {
10209
10544
  lead: "Ask only when",
@@ -10301,17 +10636,17 @@ function groupLabel(groups) {
10301
10636
 
10302
10637
  // src/chartFrame.tsx
10303
10638
  import {
10304
- useEffect as useEffect25,
10639
+ useEffect as useEffect26,
10305
10640
  useId,
10306
10641
  useRef as useRef10,
10307
- useState as useState35
10642
+ useState as useState36
10308
10643
  } from "react";
10309
- import { cn as cn33 } from "@ai-matrx/design-system";
10310
- import { jsx as jsx39, jsxs as jsxs35 } from "react/jsx-runtime";
10644
+ import { cn as cn34 } from "@ai-matrx/design-system";
10645
+ import { jsx as jsx40, jsxs as jsxs36 } from "react/jsx-runtime";
10311
10646
  function useMeasuredWidth(fallback = 480) {
10312
10647
  const ref = useRef10(null);
10313
- const [width, setWidth] = useState35(fallback);
10314
- useEffect25(() => {
10648
+ const [width, setWidth] = useState36(fallback);
10649
+ useEffect26(() => {
10315
10650
  const node = ref.current;
10316
10651
  if (!node) return;
10317
10652
  const apply = () => {
@@ -10342,13 +10677,13 @@ function ChartFrame({
10342
10677
  }) {
10343
10678
  const [ref, width] = useMeasuredWidth();
10344
10679
  const chartId = `records-chart-${useId().replace(/:/g, "")}`;
10345
- return /* @__PURE__ */ jsx39(
10680
+ return /* @__PURE__ */ jsx40(
10346
10681
  "div",
10347
10682
  {
10348
10683
  ref,
10349
10684
  "data-chart": chartId,
10350
10685
  style: { height, ...chartVariables(config) },
10351
- className: cn33(
10686
+ className: cn34(
10352
10687
  "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",
10353
10688
  className
10354
10689
  ),
@@ -10364,27 +10699,27 @@ function ChartTooltipContent({
10364
10699
  className
10365
10700
  }) {
10366
10701
  if (!active || !payload || payload.length === 0) return null;
10367
- return /* @__PURE__ */ jsxs35(
10702
+ return /* @__PURE__ */ jsxs36(
10368
10703
  "div",
10369
10704
  {
10370
- className: cn33(
10705
+ className: cn34(
10371
10706
  "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",
10372
10707
  className
10373
10708
  ),
10374
10709
  children: [
10375
- label ? /* @__PURE__ */ jsx39("div", { className: "font-medium", children: label }) : null,
10376
- /* @__PURE__ */ jsx39("div", { className: "grid gap-1.5", children: payload.map((entry, index) => {
10710
+ label ? /* @__PURE__ */ jsx40("div", { className: "font-medium", children: label }) : null,
10711
+ /* @__PURE__ */ jsx40("div", { className: "grid gap-1.5", children: payload.map((entry, index) => {
10377
10712
  const key = String(entry.dataKey ?? entry.name ?? index);
10378
- return /* @__PURE__ */ jsxs35("div", { className: "flex w-full items-center gap-2", children: [
10379
- /* @__PURE__ */ jsx39(
10713
+ return /* @__PURE__ */ jsxs36("div", { className: "flex w-full items-center gap-2", children: [
10714
+ /* @__PURE__ */ jsx40(
10380
10715
  "span",
10381
10716
  {
10382
10717
  className: "h-2.5 w-2.5 shrink-0 rounded-[2px] bg-[--color-swatch]",
10383
10718
  style: { "--color-swatch": entry.color }
10384
10719
  }
10385
10720
  ),
10386
- /* @__PURE__ */ jsx39("span", { className: "text-muted-foreground", children: config[key]?.label ?? key }),
10387
- /* @__PURE__ */ jsx39("span", { className: "ml-auto font-mono font-medium tabular-nums text-foreground", children: typeof entry.value === "number" ? entry.value.toLocaleString() : entry.value })
10721
+ /* @__PURE__ */ jsx40("span", { className: "text-muted-foreground", children: config[key]?.label ?? key }),
10722
+ /* @__PURE__ */ jsx40("span", { className: "ml-auto font-mono font-medium tabular-nums text-foreground", children: typeof entry.value === "number" ? entry.value.toLocaleString() : entry.value })
10388
10723
  ] }, key);
10389
10724
  }) })
10390
10725
  ]
@@ -10397,10 +10732,10 @@ function ChartLegendContent({
10397
10732
  className
10398
10733
  }) {
10399
10734
  if (!payload || payload.length === 0) return null;
10400
- return /* @__PURE__ */ jsx39("div", { className: cn33("flex flex-wrap items-center justify-center gap-3 pt-2", className), children: payload.map((entry, index) => {
10735
+ return /* @__PURE__ */ jsx40("div", { className: cn34("flex flex-wrap items-center justify-center gap-3 pt-2", className), children: payload.map((entry, index) => {
10401
10736
  const key = String(entry.dataKey ?? entry.value ?? index);
10402
- return /* @__PURE__ */ jsxs35("span", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
10403
- /* @__PURE__ */ jsx39(
10737
+ return /* @__PURE__ */ jsxs36("span", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
10738
+ /* @__PURE__ */ jsx40(
10404
10739
  "span",
10405
10740
  {
10406
10741
  className: "h-2 w-2 shrink-0 rounded-[2px] bg-[--color-swatch]",
@@ -10435,24 +10770,24 @@ function isSignatureField(field) {
10435
10770
  }
10436
10771
 
10437
10772
  // src/DocTemplate.tsx
10438
- import { useCallback as useCallback22, useEffect as useEffect26, useState as useState36 } from "react";
10439
- import { useFields as useFields17, useRecordsClient as useRecordsClient28, useTable as useTable14 } from "@ai-matrx/records/react";
10440
- import { BasicInput as BasicInput11, BasicTextarea as BasicTextarea6, Button as Button32, Label as Label6, Skeleton as Skeleton19, cn as cn34 } from "@ai-matrx/design-system";
10441
- import { jsx as jsx40, jsxs as jsxs36 } from "react/jsx-runtime";
10773
+ import { useCallback as useCallback23, useEffect as useEffect27, useState as useState37 } from "react";
10774
+ import { useFields as useFields17, useRecordsClient as useRecordsClient29, useTable as useTable14 } from "@ai-matrx/records/react";
10775
+ import { BasicInput as BasicInput12, BasicTextarea as BasicTextarea6, Button as Button33, Label as Label7, Skeleton as Skeleton20, cn as cn35 } from "@ai-matrx/design-system";
10776
+ import { jsx as jsx41, jsxs as jsxs37 } from "react/jsx-runtime";
10442
10777
  function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, className }) {
10443
- const client = useRecordsClient28();
10778
+ const client = useRecordsClient29();
10444
10779
  const claimSeed = useSeedGuard();
10445
10780
  const table = useTable14(tableId);
10446
10781
  const rights = useTableRights(table.data);
10447
10782
  const fields = useFields17(tableId);
10448
- const [templates, setTemplates] = useState36(null);
10449
- const [error, setError] = useState36(null);
10450
- const [activeId, setActiveId] = useState36(activeTemplateId ?? null);
10451
- const [draftName, setDraftName] = useState36("");
10452
- const [draftBody, setDraftBody] = useState36("");
10453
- const [unresolved, setUnresolved] = useState36([]);
10454
- const [saving, setSaving] = useState36(false);
10455
- const load = useCallback22(async () => {
10783
+ const [templates, setTemplates] = useState37(null);
10784
+ const [error, setError] = useState37(null);
10785
+ const [activeId, setActiveId] = useState37(activeTemplateId ?? null);
10786
+ const [draftName, setDraftName] = useState37("");
10787
+ const [draftBody, setDraftBody] = useState37("");
10788
+ const [unresolved, setUnresolved] = useState37([]);
10789
+ const [saving, setSaving] = useState37(false);
10790
+ const load = useCallback23(async () => {
10456
10791
  const held = await client.docTemplates({ table_id: tableId });
10457
10792
  if (!held.ok) {
10458
10793
  setError(held.error);
@@ -10483,10 +10818,10 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10483
10818
  setError(null);
10484
10819
  setTemplates(rows);
10485
10820
  }, [client, tableId, seed, fields.data]);
10486
- useEffect26(() => {
10821
+ useEffect27(() => {
10487
10822
  void load();
10488
10823
  }, [load]);
10489
- useEffect26(() => {
10824
+ useEffect27(() => {
10490
10825
  if (!templates || templates.length === 0) return;
10491
10826
  const chosen = templates.find((t) => t.id === (activeTemplateId ?? activeId)) ?? templates[0];
10492
10827
  if (chosen.id !== activeId) setActiveId(chosen.id);
@@ -10494,7 +10829,7 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10494
10829
  setDraftBody(chosen.body);
10495
10830
  onActiveTemplate?.(chosen);
10496
10831
  }, [templates, activeTemplateId]);
10497
- useEffect26(() => {
10832
+ useEffect27(() => {
10498
10833
  let cancelled = false;
10499
10834
  if (draftBody.trim() === "") {
10500
10835
  setUnresolved([]);
@@ -10524,25 +10859,25 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10524
10859
  setActiveId(saved.data);
10525
10860
  await load();
10526
10861
  }
10527
- if (fields.error) return /* @__PURE__ */ jsx40(RefusalNotice, { error: fields.error, className });
10862
+ if (fields.error) return /* @__PURE__ */ jsx41(RefusalNotice, { error: fields.error, className });
10528
10863
  if (error) {
10529
- return /* @__PURE__ */ jsx40(
10864
+ return /* @__PURE__ */ jsx41(
10530
10865
  RefusalNotice,
10531
10866
  {
10532
10867
  error,
10533
10868
  className,
10534
- actions: /* @__PURE__ */ jsx40(Button32, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
10869
+ actions: /* @__PURE__ */ jsx41(Button33, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
10535
10870
  }
10536
10871
  );
10537
10872
  }
10538
- if (templates === null || fields.loading) return /* @__PURE__ */ jsx40(Skeleton19, { className: cn34("h-64 w-full", className) });
10873
+ if (templates === null || fields.loading) return /* @__PURE__ */ jsx41(Skeleton20, { className: cn35("h-64 w-full", className) });
10539
10874
  if (!rights.admin) {
10540
- return /* @__PURE__ */ jsx40("p", { className: cn34("text-xs text-muted-foreground", className), children: rights.why("structure") });
10875
+ return /* @__PURE__ */ jsx41("p", { className: cn35("text-xs text-muted-foreground", className), children: rights.why("structure") });
10541
10876
  }
10542
- return /* @__PURE__ */ jsxs36("div", { className: cn34("flex flex-col gap-2", className), children: [
10543
- /* @__PURE__ */ jsxs36("div", { className: "flex items-center gap-1 overflow-x-auto", role: "group", "aria-label": "Templates", children: [
10544
- templates.map((t) => /* @__PURE__ */ jsxs36(
10545
- Button32,
10877
+ return /* @__PURE__ */ jsxs37("div", { className: cn35("flex flex-col gap-2", className), children: [
10878
+ /* @__PURE__ */ jsxs37("div", { className: "flex items-center gap-1 overflow-x-auto", role: "group", "aria-label": "Templates", children: [
10879
+ templates.map((t) => /* @__PURE__ */ jsxs37(
10880
+ Button33,
10546
10881
  {
10547
10882
  size: "sm",
10548
10883
  variant: t.id === activeId ? "secondary" : "ghost",
@@ -10554,7 +10889,7 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10554
10889
  },
10555
10890
  children: [
10556
10891
  t.name,
10557
- /* @__PURE__ */ jsxs36("span", { className: "ml-1 text-[10px] text-muted-foreground", children: [
10892
+ /* @__PURE__ */ jsxs37("span", { className: "ml-1 text-[10px] text-muted-foreground", children: [
10558
10893
  "v",
10559
10894
  t.template_version
10560
10895
  ] })
@@ -10562,8 +10897,8 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10562
10897
  },
10563
10898
  t.id
10564
10899
  )),
10565
- /* @__PURE__ */ jsx40(
10566
- Button32,
10900
+ /* @__PURE__ */ jsx41(
10901
+ Button33,
10567
10902
  {
10568
10903
  size: "sm",
10569
10904
  variant: "ghost",
@@ -10575,16 +10910,16 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10575
10910
  children: "New template"
10576
10911
  }
10577
10912
  ),
10578
- /* @__PURE__ */ jsx40(Button32, { size: "sm", className: "ml-auto", disabled: saving, onClick: () => void save(), children: saving ? "Saving\u2026" : "Save" })
10913
+ /* @__PURE__ */ jsx41(Button33, { size: "sm", className: "ml-auto", disabled: saving, onClick: () => void save(), children: saving ? "Saving\u2026" : "Save" })
10579
10914
  ] }),
10580
- /* @__PURE__ */ jsxs36("label", { className: "flex flex-col gap-1", children: [
10581
- /* @__PURE__ */ jsx40(Label6, { className: "text-xs font-medium", children: "Name" }),
10582
- /* @__PURE__ */ jsx40(BasicInput11, { value: draftName, onChange: (e) => setDraftName(e.target.value), placeholder: "Agreement" })
10915
+ /* @__PURE__ */ jsxs37("label", { className: "flex flex-col gap-1", children: [
10916
+ /* @__PURE__ */ jsx41(Label7, { className: "text-xs font-medium", children: "Name" }),
10917
+ /* @__PURE__ */ jsx41(BasicInput12, { value: draftName, onChange: (e) => setDraftName(e.target.value), placeholder: "Agreement" })
10583
10918
  ] }),
10584
- /* @__PURE__ */ jsxs36("div", { className: "flex flex-wrap items-center gap-1", children: [
10585
- /* @__PURE__ */ jsx40("span", { className: "text-xs text-muted-foreground", children: "Insert" }),
10586
- (fields.data ?? []).map((field) => /* @__PURE__ */ jsx40(
10587
- Button32,
10919
+ /* @__PURE__ */ jsxs37("div", { className: "flex flex-wrap items-center gap-1", children: [
10920
+ /* @__PURE__ */ jsx41("span", { className: "text-xs text-muted-foreground", children: "Insert" }),
10921
+ (fields.data ?? []).map((field) => /* @__PURE__ */ jsx41(
10922
+ Button33,
10588
10923
  {
10589
10924
  size: "sm",
10590
10925
  variant: "ghost",
@@ -10595,7 +10930,7 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10595
10930
  field.id
10596
10931
  ))
10597
10932
  ] }),
10598
- /* @__PURE__ */ jsx40(
10933
+ /* @__PURE__ */ jsx41(
10599
10934
  BasicTextarea6,
10600
10935
  {
10601
10936
  rows: 10,
@@ -10605,28 +10940,28 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
10605
10940
  onChange: (e) => setDraftBody(e.target.value)
10606
10941
  }
10607
10942
  ),
10608
- unresolved.length > 0 ? /* @__PURE__ */ jsx40("ul", { className: "flex flex-col gap-0.5 rounded border border-dashed px-2 py-1 text-xs", children: unresolved.map((token) => /* @__PURE__ */ jsxs36("li", { className: "text-destructive", children: [
10609
- /* @__PURE__ */ jsx40("code", { children: token.raw }),
10943
+ unresolved.length > 0 ? /* @__PURE__ */ jsx41("ul", { className: "flex flex-col gap-0.5 rounded border border-dashed px-2 py-1 text-xs", children: unresolved.map((token) => /* @__PURE__ */ jsxs37("li", { className: "text-destructive", children: [
10944
+ /* @__PURE__ */ jsx41("code", { children: token.raw }),
10610
10945
  " \u2014 ",
10611
10946
  token.why
10612
- ] }, token.raw)) }) : draftBody.trim() !== "" ? /* @__PURE__ */ jsx40("p", { className: "text-xs text-muted-foreground", children: "Every token in this body points at a Field this table can answer." }) : null
10947
+ ] }, token.raw)) }) : draftBody.trim() !== "" ? /* @__PURE__ */ jsx41("p", { className: "text-xs text-muted-foreground", children: "Every token in this body points at a Field this table can answer." }) : null
10613
10948
  ] });
10614
10949
  }
10615
10950
 
10616
10951
  // src/DocRender.tsx
10617
- import { useCallback as useCallback23, useEffect as useEffect27, useRef as useRef11, useState as useState37 } from "react";
10618
- import { useRecordsClient as useRecordsClient29 } from "@ai-matrx/records/react";
10619
- import { Button as Button33, Skeleton as Skeleton20, cn as cn35 } from "@ai-matrx/design-system";
10620
- import { jsx as jsx41, jsxs as jsxs37 } from "react/jsx-runtime";
10952
+ import { useCallback as useCallback24, useEffect as useEffect28, useRef as useRef11, useState as useState38 } from "react";
10953
+ import { useRecordsClient as useRecordsClient30 } from "@ai-matrx/records/react";
10954
+ import { Button as Button34, Skeleton as Skeleton21, cn as cn36 } from "@ai-matrx/design-system";
10955
+ import { jsx as jsx42, jsxs as jsxs38 } from "react/jsx-runtime";
10621
10956
  function DocRender({ templateId, recordId, filename, onRendered, className }) {
10622
- const client = useRecordsClient29();
10623
- const [preview, setPreview] = useState37(null);
10624
- const [renders, setRenders] = useState37(null);
10625
- const [showing, setShowing] = useState37(null);
10626
- const [error, setError] = useState37(null);
10627
- const [busy, setBusy] = useState37(null);
10957
+ const client = useRecordsClient30();
10958
+ const [preview, setPreview] = useState38(null);
10959
+ const [renders, setRenders] = useState38(null);
10960
+ const [showing, setShowing] = useState38(null);
10961
+ const [error, setError] = useState38(null);
10962
+ const [busy, setBusy] = useState38(null);
10628
10963
  const paper = useRef11(null);
10629
- const load = useCallback23(async () => {
10964
+ const load = useCallback24(async () => {
10630
10965
  const [body, held] = await Promise.all([
10631
10966
  client.docRenderBody({ template_id: templateId, record_id: recordId }),
10632
10967
  client.docRenders({ record_id: recordId })
@@ -10643,7 +10978,7 @@ function DocRender({ templateId, recordId, filename, onRendered, className }) {
10643
10978
  setPreview(body.data);
10644
10979
  setRenders(held.data.filter((r) => r.template_id === templateId));
10645
10980
  }, [client, templateId, recordId]);
10646
- useEffect27(() => {
10981
+ useEffect28(() => {
10647
10982
  void load();
10648
10983
  }, [load]);
10649
10984
  async function freeze() {
@@ -10680,22 +11015,22 @@ function DocRender({ templateId, recordId, filename, onRendered, className }) {
10680
11015
  }
10681
11016
  }
10682
11017
  if (error) {
10683
- return /* @__PURE__ */ jsx41(
11018
+ return /* @__PURE__ */ jsx42(
10684
11019
  RefusalNotice,
10685
11020
  {
10686
11021
  error,
10687
11022
  className,
10688
- actions: /* @__PURE__ */ jsx41(Button33, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
11023
+ actions: /* @__PURE__ */ jsx42(Button34, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
10689
11024
  }
10690
11025
  );
10691
11026
  }
10692
- if (preview === null || renders === null) return /* @__PURE__ */ jsx41(Skeleton20, { className: cn35("h-64 w-full", className) });
11027
+ if (preview === null || renders === null) return /* @__PURE__ */ jsx42(Skeleton21, { className: cn36("h-64 w-full", className) });
10693
11028
  const frozen = showing ? renders.find((r) => r.id === showing) ?? null : null;
10694
11029
  const text = frozen ? frozen.body : preview;
10695
- return /* @__PURE__ */ jsxs37("div", { className: cn35("flex flex-col gap-2", className), children: [
10696
- /* @__PURE__ */ jsxs37("div", { className: "flex items-center gap-1 text-xs", children: [
10697
- /* @__PURE__ */ jsx41(
10698
- Button33,
11030
+ return /* @__PURE__ */ jsxs38("div", { className: cn36("flex flex-col gap-2", className), children: [
11031
+ /* @__PURE__ */ jsxs38("div", { className: "flex items-center gap-1 text-xs", children: [
11032
+ /* @__PURE__ */ jsx42(
11033
+ Button34,
10699
11034
  {
10700
11035
  size: "sm",
10701
11036
  variant: frozen ? "ghost" : "secondary",
@@ -10704,8 +11039,8 @@ function DocRender({ templateId, recordId, filename, onRendered, className }) {
10704
11039
  children: "As it reads now"
10705
11040
  }
10706
11041
  ),
10707
- renders.map((render) => /* @__PURE__ */ jsx41(
10708
- Button33,
11042
+ renders.map((render) => /* @__PURE__ */ jsx42(
11043
+ Button34,
10709
11044
  {
10710
11045
  size: "sm",
10711
11046
  variant: render.id === showing ? "secondary" : "ghost",
@@ -10716,33 +11051,33 @@ function DocRender({ templateId, recordId, filename, onRendered, className }) {
10716
11051
  },
10717
11052
  render.id
10718
11053
  )),
10719
- /* @__PURE__ */ jsxs37("span", { className: "ml-auto flex items-center gap-1", children: [
10720
- /* @__PURE__ */ jsx41(Button33, { size: "sm", disabled: busy !== null, onClick: () => void freeze(), children: busy === "freeze" ? "Freezing\u2026" : "Freeze this version" }),
10721
- /* @__PURE__ */ jsx41(Button33, { size: "sm", variant: "ghost", disabled: busy !== null, onClick: () => void toPdf(), children: busy === "pdf" ? "Making the PDF\u2026" : "PDF" })
11054
+ /* @__PURE__ */ jsxs38("span", { className: "ml-auto flex items-center gap-1", children: [
11055
+ /* @__PURE__ */ jsx42(Button34, { size: "sm", disabled: busy !== null, onClick: () => void freeze(), children: busy === "freeze" ? "Freezing\u2026" : "Freeze this version" }),
11056
+ /* @__PURE__ */ jsx42(Button34, { size: "sm", variant: "ghost", disabled: busy !== null, onClick: () => void toPdf(), children: busy === "pdf" ? "Making the PDF\u2026" : "PDF" })
10722
11057
  ] })
10723
11058
  ] }),
10724
- /* @__PURE__ */ jsx41("div", { ref: paper, className: "whitespace-pre-wrap rounded border bg-background p-4 text-sm text-foreground", children: text }),
10725
- /* @__PURE__ */ jsx41("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." })
11059
+ /* @__PURE__ */ jsx42("div", { ref: paper, className: "whitespace-pre-wrap rounded border bg-background p-4 text-sm text-foreground", children: text }),
11060
+ /* @__PURE__ */ jsx42("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." })
10726
11061
  ] });
10727
11062
  }
10728
11063
 
10729
11064
  // src/SignBlock.tsx
10730
- import { useCallback as useCallback24, useEffect as useEffect28, useState as useState38 } from "react";
10731
- import { useFields as useFields18, useRecordsClient as useRecordsClient30 } from "@ai-matrx/records/react";
10732
- import { BasicInput as BasicInput12, Button as Button34, Skeleton as Skeleton21, cn as cn36 } from "@ai-matrx/design-system";
11065
+ import { useCallback as useCallback25, useEffect as useEffect29, useState as useState39 } from "react";
11066
+ import { useFields as useFields18, useRecordsClient as useRecordsClient31 } from "@ai-matrx/records/react";
11067
+ import { BasicInput as BasicInput13, Button as Button35, Skeleton as Skeleton22, cn as cn37 } from "@ai-matrx/design-system";
10733
11068
  import { useTable as useTable15 } from "@ai-matrx/records/react";
10734
- import { jsx as jsx42, jsxs as jsxs38 } from "react/jsx-runtime";
11069
+ import { jsx as jsx43, jsxs as jsxs39 } from "react/jsx-runtime";
10735
11070
  function SignBlock({ tableId, recordId, render, className }) {
10736
- const client = useRecordsClient30();
11071
+ const client = useRecordsClient31();
10737
11072
  const table = useTable15(tableId);
10738
11073
  const rights = useTableRights(table.data);
10739
11074
  const fields = useFields18(tableId);
10740
- const [signatures, setSignatures] = useState38(null);
10741
- const [verdicts, setVerdicts] = useState38({});
10742
- const [error, setError] = useState38(null);
10743
- const [name, setName] = useState38("");
10744
- const [busy, setBusy] = useState38(false);
10745
- const load = useCallback24(async () => {
11075
+ const [signatures, setSignatures] = useState39(null);
11076
+ const [verdicts, setVerdicts] = useState39({});
11077
+ const [error, setError] = useState39(null);
11078
+ const [name, setName] = useState39("");
11079
+ const [busy, setBusy] = useState39(false);
11080
+ const load = useCallback25(async () => {
10746
11081
  const held = await client.docSignatures({ record_id: recordId });
10747
11082
  if (!held.ok) {
10748
11083
  setError(held.error);
@@ -10757,7 +11092,7 @@ function SignBlock({ tableId, recordId, render, className }) {
10757
11092
  }
10758
11093
  setVerdicts(answers);
10759
11094
  }, [client, recordId]);
10760
- useEffect28(() => {
11095
+ useEffect29(() => {
10761
11096
  void load();
10762
11097
  }, [load]);
10763
11098
  async function sign(field) {
@@ -10777,58 +11112,58 @@ function SignBlock({ tableId, recordId, render, className }) {
10777
11112
  setName("");
10778
11113
  await load();
10779
11114
  }
10780
- if (fields.error) return /* @__PURE__ */ jsx42(RefusalNotice, { error: fields.error, className });
11115
+ if (fields.error) return /* @__PURE__ */ jsx43(RefusalNotice, { error: fields.error, className });
10781
11116
  if (error) {
10782
- return /* @__PURE__ */ jsx42(
11117
+ return /* @__PURE__ */ jsx43(
10783
11118
  RefusalNotice,
10784
11119
  {
10785
11120
  error,
10786
11121
  className,
10787
- actions: /* @__PURE__ */ jsx42(Button34, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
11122
+ actions: /* @__PURE__ */ jsx43(Button35, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
10788
11123
  }
10789
11124
  );
10790
11125
  }
10791
- if (fields.loading || signatures === null) return /* @__PURE__ */ jsx42(Skeleton21, { className: cn36("h-32 w-full", className) });
11126
+ if (fields.loading || signatures === null) return /* @__PURE__ */ jsx43(Skeleton22, { className: cn37("h-32 w-full", className) });
10792
11127
  const signable = (fields.data ?? []).filter(isSignatureField);
10793
- return /* @__PURE__ */ jsxs38("div", { className: cn36("flex flex-col gap-2", className), children: [
10794
- /* @__PURE__ */ jsxs38("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
10795
- /* @__PURE__ */ jsx42("span", { className: "font-medium text-foreground", children: "Signatures" }),
10796
- /* @__PURE__ */ jsxs38("span", { children: [
11128
+ return /* @__PURE__ */ jsxs39("div", { className: cn37("flex flex-col gap-2", className), children: [
11129
+ /* @__PURE__ */ jsxs39("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
11130
+ /* @__PURE__ */ jsx43("span", { className: "font-medium text-foreground", children: "Signatures" }),
11131
+ /* @__PURE__ */ jsxs39("span", { children: [
10797
11132
  signatures.length,
10798
11133
  " on this record"
10799
11134
  ] })
10800
11135
  ] }),
10801
- signatures.length > 0 ? /* @__PURE__ */ jsx42("ul", { className: "flex flex-col gap-1", children: signatures.map((signature) => {
11136
+ signatures.length > 0 ? /* @__PURE__ */ jsx43("ul", { className: "flex flex-col gap-1", children: signatures.map((signature) => {
10802
11137
  const verdict = verdicts[signature.id];
10803
11138
  const intact = typeof verdict === "object" && verdict !== null ? verdict.intact : void 0;
10804
- return /* @__PURE__ */ jsxs38("li", { className: "rounded border px-2 py-1.5 text-xs", children: [
10805
- /* @__PURE__ */ jsxs38("div", { className: "flex items-center gap-2", children: [
10806
- /* @__PURE__ */ jsx42("span", { className: "font-medium", children: signature.signer_name }),
10807
- /* @__PURE__ */ jsx42("span", { className: "text-muted-foreground", children: signature.field_key }),
10808
- /* @__PURE__ */ jsx42("span", { className: "text-muted-foreground", children: new Date(signature.signed_at).toLocaleString() }),
10809
- /* @__PURE__ */ jsxs38("span", { className: "ml-auto font-mono text-[10px] text-muted-foreground", children: [
11139
+ return /* @__PURE__ */ jsxs39("li", { className: "rounded border px-2 py-1.5 text-xs", children: [
11140
+ /* @__PURE__ */ jsxs39("div", { className: "flex items-center gap-2", children: [
11141
+ /* @__PURE__ */ jsx43("span", { className: "font-medium", children: signature.signer_name }),
11142
+ /* @__PURE__ */ jsx43("span", { className: "text-muted-foreground", children: signature.field_key }),
11143
+ /* @__PURE__ */ jsx43("span", { className: "text-muted-foreground", children: new Date(signature.signed_at).toLocaleString() }),
11144
+ /* @__PURE__ */ jsxs39("span", { className: "ml-auto font-mono text-[10px] text-muted-foreground", children: [
10810
11145
  "v",
10811
11146
  signature.document_version,
10812
11147
  " \xB7 ",
10813
11148
  signature.document_hash.slice(0, 12)
10814
11149
  ] })
10815
11150
  ] }),
10816
- /* @__PURE__ */ jsx42("p", { className: cn36("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 ?? "") })
11151
+ /* @__PURE__ */ jsx43("p", { className: cn37("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 ?? "") })
10817
11152
  ] }, signature.id);
10818
11153
  }) }) : null,
10819
- !render ? /* @__PURE__ */ jsx42("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__ */ jsxs38("p", { className: "text-xs text-muted-foreground", children: [
11154
+ !render ? /* @__PURE__ */ jsx43("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__ */ jsxs39("p", { className: "text-xs text-muted-foreground", children: [
10820
11155
  "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 ",
10821
- /* @__PURE__ */ jsx42("code", { children: "signature" }),
11156
+ /* @__PURE__ */ jsx43("code", { children: "signature" }),
10822
11157
  " \u2014 add one and the signing appears."
10823
- ] }) : !rights.write ? /* @__PURE__ */ jsx42("p", { className: "text-xs text-muted-foreground", children: rights.why("write") }) : /* @__PURE__ */ jsx42("div", { className: "flex flex-col gap-1", children: signable.map((field) => {
11158
+ ] }) : !rights.write ? /* @__PURE__ */ jsx43("p", { className: "text-xs text-muted-foreground", children: rights.why("write") }) : /* @__PURE__ */ jsx43("div", { className: "flex flex-col gap-1", children: signable.map((field) => {
10824
11159
  const already = signatures.find((s) => s.field_key === field.key);
10825
11160
  if (already) {
10826
- return /* @__PURE__ */ jsxs38("p", { className: "text-xs text-muted-foreground", children: [
11161
+ return /* @__PURE__ */ jsxs39("p", { className: "text-xs text-muted-foreground", children: [
10827
11162
  fieldName(field),
10828
11163
  " 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."
10829
11164
  ] }, field.id);
10830
11165
  }
10831
- return /* @__PURE__ */ jsxs38(
11166
+ return /* @__PURE__ */ jsxs39(
10832
11167
  "form",
10833
11168
  {
10834
11169
  className: "flex items-center gap-1",
@@ -10837,8 +11172,8 @@ function SignBlock({ tableId, recordId, render, className }) {
10837
11172
  if (name.trim() !== "") void sign(field);
10838
11173
  },
10839
11174
  children: [
10840
- /* @__PURE__ */ jsx42(
10841
- BasicInput12,
11175
+ /* @__PURE__ */ jsx43(
11176
+ BasicInput13,
10842
11177
  {
10843
11178
  className: "h-8 w-56 text-xs",
10844
11179
  "aria-label": `Sign ${fieldName(field)}`,
@@ -10847,8 +11182,8 @@ function SignBlock({ tableId, recordId, render, className }) {
10847
11182
  onChange: (e) => setName(e.target.value)
10848
11183
  }
10849
11184
  ),
10850
- /* @__PURE__ */ jsx42(Button34, { size: "sm", type: "submit", disabled: busy || name.trim() === "", children: "Sign" }),
10851
- /* @__PURE__ */ jsxs38("span", { className: "text-xs text-muted-foreground", children: [
11185
+ /* @__PURE__ */ jsx43(Button35, { size: "sm", type: "submit", disabled: busy || name.trim() === "", children: "Sign" }),
11186
+ /* @__PURE__ */ jsxs39("span", { className: "text-xs text-muted-foreground", children: [
10852
11187
  "seals version ",
10853
11188
  render.template_version,
10854
11189
  " \xB7 ",
@@ -10864,32 +11199,32 @@ function SignBlock({ tableId, recordId, render, className }) {
10864
11199
  }
10865
11200
 
10866
11201
  // src/NotifyRuleEditor.tsx
10867
- import { useCallback as useCallback25, useEffect as useEffect29, useState as useState39 } from "react";
10868
- import { useRecordsClient as useRecordsClient31, useTable as useTable16 } from "@ai-matrx/records/react";
10869
- import { Button as Button35, Skeleton as Skeleton22, cn as cn37 } from "@ai-matrx/design-system";
10870
- import { jsx as jsx43, jsxs as jsxs39 } from "react/jsx-runtime";
10871
- var CADENCE_WORDS = {
11202
+ import { useCallback as useCallback26, useEffect as useEffect30, useState as useState40 } from "react";
11203
+ import { useRecordsClient as useRecordsClient32, useTable as useTable16 } from "@ai-matrx/records/react";
11204
+ import { Button as Button36, Skeleton as Skeleton23, cn as cn38 } from "@ai-matrx/design-system";
11205
+ import { jsx as jsx44, jsxs as jsxs40 } from "react/jsx-runtime";
11206
+ var CADENCE_WORDS2 = {
10872
11207
  instant: "as it happens",
10873
11208
  hourly: "hourly summary",
10874
11209
  daily: "daily summary",
10875
11210
  weekly: "weekly summary"
10876
11211
  };
10877
- var CHANNEL_WORDS2 = {
11212
+ var CHANNEL_WORDS3 = {
10878
11213
  in_app: "in the app",
10879
11214
  email: "by email",
10880
11215
  sms: "by text"
10881
11216
  };
10882
11217
  function NotifyRuleEditor({ tableId, seed, className }) {
10883
- const client = useRecordsClient31();
11218
+ const client = useRecordsClient32();
10884
11219
  const host = useRecordsUi();
10885
11220
  const table = useTable16(tableId);
10886
11221
  const rights = useTableRights(table.data);
10887
- const [subscriptions, setSubscriptions] = useState39(null);
10888
- const [cadences, setCadences] = useState39([]);
10889
- const [views, setViews] = useState39(null);
10890
- const [error, setError] = useState39(null);
10891
- const [busy, setBusy] = useState39(false);
10892
- const load = useCallback25(async () => {
11222
+ const [subscriptions, setSubscriptions] = useState40(null);
11223
+ const [cadences, setCadences] = useState40([]);
11224
+ const [views, setViews] = useState40(null);
11225
+ const [error, setError] = useState40(null);
11226
+ const [busy, setBusy] = useState40(false);
11227
+ const load = useCallback26(async () => {
10893
11228
  const [held, offered] = await Promise.all([
10894
11229
  // THE PERSON'S OWN DOOR, not the notifier's. It answers what is addressed
10895
11230
  // to them plus — only where they hold admin on this Table — anyone's over
@@ -10909,10 +11244,10 @@ function NotifyRuleEditor({ tableId, seed, className }) {
10909
11244
  if (host.savedViews) setViews(await host.savedViews());
10910
11245
  else setViews(null);
10911
11246
  }, [client, host, tableId]);
10912
- useEffect29(() => {
11247
+ useEffect30(() => {
10913
11248
  void load();
10914
11249
  }, [load]);
10915
- const write = useCallback25(
11250
+ const write = useCallback26(
10916
11251
  async (spec) => {
10917
11252
  const declared = await client.subscriptionDeclare({
10918
11253
  table_id: tableId,
@@ -10937,7 +11272,7 @@ function NotifyRuleEditor({ tableId, seed, className }) {
10937
11272
  },
10938
11273
  [client, tableId]
10939
11274
  );
10940
- useEffect29(() => {
11275
+ useEffect30(() => {
10941
11276
  if (!subscriptions || !seed || seed.length === 0) return;
10942
11277
  const missing = seed.filter((s) => !subscriptions.some((held) => held.name === s.name));
10943
11278
  if (missing.length === 0) return;
@@ -10951,7 +11286,7 @@ function NotifyRuleEditor({ tableId, seed, className }) {
10951
11286
  async function subscribe(viewId, viewName, cadence, channel, schedule, quiet) {
10952
11287
  setBusy(true);
10953
11288
  const ok = await write({
10954
- name: `${viewName} \u2014 ${CADENCE_WORDS[cadence] ?? cadence}`,
11289
+ name: `${viewName} \u2014 ${CADENCE_WORDS2[cadence] ?? cadence}`,
10955
11290
  savedViewId: viewId,
10956
11291
  cadence,
10957
11292
  channel,
@@ -10972,45 +11307,45 @@ function NotifyRuleEditor({ tableId, seed, className }) {
10972
11307
  await load();
10973
11308
  }
10974
11309
  if (error) {
10975
- return /* @__PURE__ */ jsx43(
11310
+ return /* @__PURE__ */ jsx44(
10976
11311
  RefusalNotice,
10977
11312
  {
10978
11313
  error,
10979
11314
  className,
10980
- actions: /* @__PURE__ */ jsx43(Button35, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
11315
+ actions: /* @__PURE__ */ jsx44(Button36, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
10981
11316
  }
10982
11317
  );
10983
11318
  }
10984
- if (subscriptions === null) return /* @__PURE__ */ jsx43(Skeleton22, { className: cn37("h-40 w-full", className) });
10985
- return /* @__PURE__ */ jsxs39("div", { className: cn37("flex flex-col gap-2", className), children: [
10986
- /* @__PURE__ */ jsxs39("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
10987
- /* @__PURE__ */ jsx43("span", { className: "font-medium text-foreground", children: "Tell me when" }),
10988
- /* @__PURE__ */ jsxs39("span", { children: [
11319
+ if (subscriptions === null) return /* @__PURE__ */ jsx44(Skeleton23, { className: cn38("h-40 w-full", className) });
11320
+ return /* @__PURE__ */ jsxs40("div", { className: cn38("flex flex-col gap-2", className), children: [
11321
+ /* @__PURE__ */ jsxs40("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
11322
+ /* @__PURE__ */ jsx44("span", { className: "font-medium text-foreground", children: "Tell me when" }),
11323
+ /* @__PURE__ */ jsxs40("span", { children: [
10989
11324
  subscriptions.length,
10990
11325
  " subscription",
10991
11326
  subscriptions.length === 1 ? "" : "s"
10992
11327
  ] })
10993
11328
  ] }),
10994
- subscriptions.length === 0 ? /* @__PURE__ */ jsx43("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__ */ jsx43("ul", { className: "flex flex-col gap-1", children: subscriptions.map((held) => /* @__PURE__ */ jsxs39("li", { className: "flex items-center gap-2 rounded border px-2 py-1.5 text-xs", children: [
10995
- /* @__PURE__ */ jsx43("span", { className: "truncate font-medium", children: held.name }),
10996
- /* @__PURE__ */ jsx43("span", { className: "text-muted-foreground", children: CADENCE_WORDS[held.cadence] ?? held.cadence }),
10997
- /* @__PURE__ */ jsx43("span", { className: "text-muted-foreground", children: CHANNEL_WORDS2[held.channel] ?? held.channel }),
10998
- held.schedule ? /* @__PURE__ */ jsx43("span", { className: "text-muted-foreground", children: held.schedule }) : null,
10999
- held.next_digest_at ? /* @__PURE__ */ jsxs39("span", { className: "text-muted-foreground", children: [
11329
+ subscriptions.length === 0 ? /* @__PURE__ */ jsx44("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__ */ jsx44("ul", { className: "flex flex-col gap-1", children: subscriptions.map((held) => /* @__PURE__ */ jsxs40("li", { className: "flex items-center gap-2 rounded border px-2 py-1.5 text-xs", children: [
11330
+ /* @__PURE__ */ jsx44("span", { className: "truncate font-medium", children: held.name }),
11331
+ /* @__PURE__ */ jsx44("span", { className: "text-muted-foreground", children: CADENCE_WORDS2[held.cadence] ?? held.cadence }),
11332
+ /* @__PURE__ */ jsx44("span", { className: "text-muted-foreground", children: CHANNEL_WORDS3[held.channel] ?? held.channel }),
11333
+ held.schedule ? /* @__PURE__ */ jsx44("span", { className: "text-muted-foreground", children: held.schedule }) : null,
11334
+ held.next_digest_at ? /* @__PURE__ */ jsxs40("span", { className: "text-muted-foreground", children: [
11000
11335
  "next ",
11001
11336
  new Date(held.next_digest_at).toLocaleString()
11002
11337
  ] }) : null,
11003
- held.quiet_hours ? /* @__PURE__ */ jsxs39("span", { className: "text-muted-foreground", children: [
11338
+ held.quiet_hours ? /* @__PURE__ */ jsxs40("span", { className: "text-muted-foreground", children: [
11004
11339
  "quiet ",
11005
11340
  held.quiet_hours.start,
11006
11341
  "\u2013",
11007
11342
  held.quiet_hours.end
11008
11343
  ] }) : null,
11009
- held.recipient_user_id === null ? /* @__PURE__ */ jsx43("span", { className: "text-destructive", children: "This one has nobody to tell, so it fires at nobody." }) : null,
11010
- held.saved_view_id === null ? /* @__PURE__ */ jsx43("span", { className: "text-destructive", children: "This one names no view, so the store never admits a record to it." }) : null,
11011
- held.muted ? /* @__PURE__ */ jsx43("span", { className: "text-muted-foreground", children: "Switched off \u2014 it tells nobody until somebody switches it back on." }) : null,
11012
- rights.write ? /* @__PURE__ */ jsx43(
11013
- Button35,
11344
+ held.recipient_user_id === null ? /* @__PURE__ */ jsx44("span", { className: "text-destructive", children: "This one has nobody to tell, so it fires at nobody." }) : null,
11345
+ held.saved_view_id === null ? /* @__PURE__ */ jsx44("span", { className: "text-destructive", children: "This one names no view, so the store never admits a record to it." }) : null,
11346
+ held.muted ? /* @__PURE__ */ jsx44("span", { className: "text-muted-foreground", children: "Switched off \u2014 it tells nobody until somebody switches it back on." }) : null,
11347
+ rights.write ? /* @__PURE__ */ jsx44(
11348
+ Button36,
11014
11349
  {
11015
11350
  size: "sm",
11016
11351
  variant: "ghost",
@@ -11021,7 +11356,7 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11021
11356
  }
11022
11357
  ) : null
11023
11358
  ] }, held.rule_id)) }),
11024
- views === null ? /* @__PURE__ */ jsx43("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: NO_SAVED_VIEWS_REASON }) : views.length === 0 ? /* @__PURE__ */ jsx43("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__ */ jsxs39(
11359
+ views === null ? /* @__PURE__ */ jsx44("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: NO_SAVED_VIEWS_REASON }) : views.length === 0 ? /* @__PURE__ */ jsx44("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__ */ jsxs40(
11025
11360
  "form",
11026
11361
  {
11027
11362
  className: "flex flex-wrap items-center gap-1",
@@ -11039,10 +11374,10 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11039
11374
  if (view) void subscribe(view, name, cadence, channel, schedule, quiet);
11040
11375
  },
11041
11376
  children: [
11042
- /* @__PURE__ */ jsx43("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__ */ jsx43("option", { value: view.id, children: view.name }, view.id)) }),
11043
- /* @__PURE__ */ jsx43("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__ */ jsx43("option", { value: cadence, children: CADENCE_WORDS[cadence] ?? cadence }, cadence)) }),
11044
- /* @__PURE__ */ jsx43("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__ */ jsx43("option", { value: channel, children: CHANNEL_WORDS2[channel] }, channel)) }),
11045
- /* @__PURE__ */ jsx43(
11377
+ /* @__PURE__ */ jsx44("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__ */ jsx44("option", { value: view.id, children: view.name }, view.id)) }),
11378
+ /* @__PURE__ */ jsx44("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__ */ jsx44("option", { value: cadence, children: CADENCE_WORDS2[cadence] ?? cadence }, cadence)) }),
11379
+ /* @__PURE__ */ jsx44("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__ */ jsx44("option", { value: channel, children: CHANNEL_WORDS3[channel] }, channel)) }),
11380
+ /* @__PURE__ */ jsx44(
11046
11381
  "input",
11047
11382
  {
11048
11383
  name: "schedule",
@@ -11051,8 +11386,8 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11051
11386
  className: "h-7 w-28 rounded border bg-background px-1 text-xs"
11052
11387
  }
11053
11388
  ),
11054
- /* @__PURE__ */ jsx43("span", { className: "text-xs text-muted-foreground", children: "not between" }),
11055
- /* @__PURE__ */ jsx43(
11389
+ /* @__PURE__ */ jsx44("span", { className: "text-xs text-muted-foreground", children: "not between" }),
11390
+ /* @__PURE__ */ jsx44(
11056
11391
  "input",
11057
11392
  {
11058
11393
  name: "quiet_start",
@@ -11061,8 +11396,8 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11061
11396
  className: "h-7 rounded border bg-background px-1 text-xs"
11062
11397
  }
11063
11398
  ),
11064
- /* @__PURE__ */ jsx43("span", { className: "text-xs text-muted-foreground", children: "and" }),
11065
- /* @__PURE__ */ jsx43(
11399
+ /* @__PURE__ */ jsx44("span", { className: "text-xs text-muted-foreground", children: "and" }),
11400
+ /* @__PURE__ */ jsx44(
11066
11401
  "input",
11067
11402
  {
11068
11403
  name: "quiet_end",
@@ -11071,16 +11406,16 @@ function NotifyRuleEditor({ tableId, seed, className }) {
11071
11406
  className: "h-7 rounded border bg-background px-1 text-xs"
11072
11407
  }
11073
11408
  ),
11074
- /* @__PURE__ */ jsx43(Button35, { size: "sm", type: "submit", disabled: busy, children: "Tell me" }),
11075
- /* @__PURE__ */ jsx43("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." })
11409
+ /* @__PURE__ */ jsx44(Button36, { size: "sm", type: "submit", disabled: busy, children: "Tell me" }),
11410
+ /* @__PURE__ */ jsx44("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." })
11076
11411
  ]
11077
11412
  }
11078
- ) : /* @__PURE__ */ jsx43("p", { className: "text-xs text-muted-foreground", children: rights.why("write") })
11413
+ ) : /* @__PURE__ */ jsx44("p", { className: "text-xs text-muted-foreground", children: rights.why("write") })
11079
11414
  ] });
11080
11415
  }
11081
11416
 
11082
11417
  // src/ChartBlock.tsx
11083
- import { useMemo as useMemo25 } from "react";
11418
+ import { useMemo as useMemo26 } from "react";
11084
11419
  import {
11085
11420
  Bar,
11086
11421
  BarChart,
@@ -11099,8 +11434,8 @@ import {
11099
11434
  measureKey
11100
11435
  } from "@ai-matrx/records";
11101
11436
  import { mapPgError } from "@ai-matrx/records/core";
11102
- import { cn as cn38 } from "@ai-matrx/design-system";
11103
- import { Fragment as Fragment18, jsx as jsx44, jsxs as jsxs40 } from "react/jsx-runtime";
11437
+ import { cn as cn39 } from "@ai-matrx/design-system";
11438
+ import { Fragment as Fragment19, jsx as jsx45, jsxs as jsxs41 } from "react/jsx-runtime";
11104
11439
  function pretty(n) {
11105
11440
  return Number.isInteger(n) ? n.toLocaleString() : n.toLocaleString(void 0, { maximumFractionDigits: 2 });
11106
11441
  }
@@ -11120,7 +11455,7 @@ function ChartBlock({ block, subject, className }) {
11120
11455
  const measures = block.measures && block.measures.length > 0 ? block.measures : [{ op: "count" }];
11121
11456
  const primary = measureKey(measures[0]);
11122
11457
  const series = [primary];
11123
- const points = useMemo25(() => {
11458
+ const points = useMemo26(() => {
11124
11459
  if (kind === "stuck") return [];
11125
11460
  const rows = block.rows ?? [];
11126
11461
  return rows.map((row) => ({
@@ -11132,7 +11467,7 @@ function ChartBlock({ block, subject, className }) {
11132
11467
  n: row.row_count
11133
11468
  }));
11134
11469
  }, [block.rows, kind, series.join("|")]);
11135
- const config = useMemo25(() => {
11470
+ const config = useMemo26(() => {
11136
11471
  const out = {};
11137
11472
  series.forEach((key, index) => {
11138
11473
  out[key] = {
@@ -11156,18 +11491,18 @@ function ChartBlock({ block, subject, className }) {
11156
11491
  label: point.label === "All records" ? block.title : `${block.title} \xB7 ${point.label}`
11157
11492
  });
11158
11493
  } : null;
11159
- return /* @__PURE__ */ jsxs40("figure", { className: cn38("flex min-w-0 flex-col gap-1.5 rounded border p-2", className), children: [
11160
- /* @__PURE__ */ jsxs40("figcaption", { className: "flex items-baseline gap-2 text-xs", children: [
11161
- /* @__PURE__ */ jsx44("span", { className: "truncate font-medium", children: block.title || CHART_KIND_LABEL[kind] }),
11162
- /* @__PURE__ */ jsx44("span", { className: "ml-auto shrink-0 text-muted-foreground", children: kind === "stuck" ? `${block.days ?? 14} days` : primary.replace("_", " of ") }),
11163
- typeof block.ms === "number" ? /* @__PURE__ */ jsxs40("span", { className: "shrink-0 tabular-nums text-muted-foreground/70", title: "how long the store took", children: [
11494
+ return /* @__PURE__ */ jsxs41("figure", { className: cn39("flex min-w-0 flex-col gap-1.5 rounded border p-2", className), children: [
11495
+ /* @__PURE__ */ jsxs41("figcaption", { className: "flex items-baseline gap-2 text-xs", children: [
11496
+ /* @__PURE__ */ jsx45("span", { className: "truncate font-medium", children: block.title || CHART_KIND_LABEL[kind] }),
11497
+ /* @__PURE__ */ jsx45("span", { className: "ml-auto shrink-0 text-muted-foreground", children: kind === "stuck" ? `${block.days ?? 14} days` : primary.replace("_", " of ") }),
11498
+ typeof block.ms === "number" ? /* @__PURE__ */ jsxs41("span", { className: "shrink-0 tabular-nums text-muted-foreground/70", title: "how long the store took", children: [
11164
11499
  pretty(block.ms),
11165
11500
  " ms"
11166
11501
  ] }) : null
11167
11502
  ] }),
11168
- block.refused ? /* @__PURE__ */ jsx44(RefusalNotice, { error: asRefusal(block) }) : needs ? /* @__PURE__ */ jsx44("p", { className: "px-1 py-3 text-xs text-muted-foreground", children: needs }) : kind === "stuck" ? /* @__PURE__ */ jsx44(StuckList, { rows: block.rows ?? [] }) : points.length === 0 ? /* @__PURE__ */ jsx44("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__ */ jsx44(Fragment18, { children: kind === "number" ? /* @__PURE__ */ jsx44(BigNumber, { points, measure: primary, onDrill: drill }) : kind === "table" ? /* @__PURE__ */ jsx44(GroupTable, { points, series, onDrill: drill }) : /* @__PURE__ */ jsxs40(Fragment18, { children: [
11169
- /* @__PURE__ */ jsx44(Drawing, { kind, points, series, config, onDrill: drill }),
11170
- /* @__PURE__ */ jsx44(Values, { points, measure: primary, config, onDrill: drill })
11503
+ block.refused ? /* @__PURE__ */ jsx45(RefusalNotice, { error: asRefusal(block) }) : needs ? /* @__PURE__ */ jsx45("p", { className: "px-1 py-3 text-xs text-muted-foreground", children: needs }) : kind === "stuck" ? /* @__PURE__ */ jsx45(StuckList, { rows: block.rows ?? [] }) : points.length === 0 ? /* @__PURE__ */ jsx45("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__ */ jsx45(Fragment19, { children: kind === "number" ? /* @__PURE__ */ jsx45(BigNumber, { points, measure: primary, onDrill: drill }) : kind === "table" ? /* @__PURE__ */ jsx45(GroupTable, { points, series, onDrill: drill }) : /* @__PURE__ */ jsxs41(Fragment19, { children: [
11504
+ /* @__PURE__ */ jsx45(Drawing, { kind, points, series, config, onDrill: drill }),
11505
+ /* @__PURE__ */ jsx45(Values, { points, measure: primary, config, onDrill: drill })
11171
11506
  ] }) })
11172
11507
  ] });
11173
11508
  }
@@ -11178,16 +11513,16 @@ function BigNumber({
11178
11513
  }) {
11179
11514
  const total = points.reduce((sum, p) => sum + (p.values[measure] ?? 0), 0);
11180
11515
  const records = points.reduce((sum, p) => sum + p.n, 0);
11181
- const body = /* @__PURE__ */ jsxs40(Fragment18, { children: [
11182
- /* @__PURE__ */ jsx44("span", { className: "text-2xl font-semibold tabular-nums", children: pretty(total) }),
11183
- /* @__PURE__ */ jsxs40("span", { className: "text-xs text-muted-foreground", children: [
11516
+ const body = /* @__PURE__ */ jsxs41(Fragment19, { children: [
11517
+ /* @__PURE__ */ jsx45("span", { className: "text-2xl font-semibold tabular-nums", children: pretty(total) }),
11518
+ /* @__PURE__ */ jsxs41("span", { className: "text-xs text-muted-foreground", children: [
11184
11519
  "from ",
11185
11520
  records.toLocaleString(),
11186
11521
  " records"
11187
11522
  ] })
11188
11523
  ] });
11189
- if (!onDrill || !points[0]) return /* @__PURE__ */ jsx44("div", { className: "flex items-baseline gap-2 px-1 py-2", children: body });
11190
- return /* @__PURE__ */ jsx44(
11524
+ if (!onDrill || !points[0]) return /* @__PURE__ */ jsx45("div", { className: "flex items-baseline gap-2 px-1 py-2", children: body });
11525
+ return /* @__PURE__ */ jsx45(
11191
11526
  "button",
11192
11527
  {
11193
11528
  type: "button",
@@ -11203,19 +11538,19 @@ function Values({
11203
11538
  config,
11204
11539
  onDrill
11205
11540
  }) {
11206
- return /* @__PURE__ */ jsx44("ul", { className: "flex flex-wrap gap-x-2 gap-y-0.5", children: points.map((point) => {
11207
- const text = /* @__PURE__ */ jsxs40(Fragment18, { children: [
11208
- /* @__PURE__ */ jsx44(
11541
+ return /* @__PURE__ */ jsx45("ul", { className: "flex flex-wrap gap-x-2 gap-y-0.5", children: points.map((point) => {
11542
+ const text = /* @__PURE__ */ jsxs41(Fragment19, { children: [
11543
+ /* @__PURE__ */ jsx45(
11209
11544
  "span",
11210
11545
  {
11211
11546
  className: "h-2 w-2 shrink-0 rounded-[2px]",
11212
11547
  style: { background: String(config[point.label]?.color ?? SERIES_COLORS[0]) }
11213
11548
  }
11214
11549
  ),
11215
- /* @__PURE__ */ jsx44("span", { className: "truncate", children: point.label }),
11216
- /* @__PURE__ */ jsx44("span", { className: "tabular-nums text-muted-foreground", children: pretty(point.values[measure] ?? 0) })
11550
+ /* @__PURE__ */ jsx45("span", { className: "truncate", children: point.label }),
11551
+ /* @__PURE__ */ jsx45("span", { className: "tabular-nums text-muted-foreground", children: pretty(point.values[measure] ?? 0) })
11217
11552
  ] });
11218
- return /* @__PURE__ */ jsx44("li", { className: "min-w-0", children: onDrill ? /* @__PURE__ */ jsx44(
11553
+ return /* @__PURE__ */ jsx45("li", { className: "min-w-0", children: onDrill ? /* @__PURE__ */ jsx45(
11219
11554
  "button",
11220
11555
  {
11221
11556
  type: "button",
@@ -11223,7 +11558,7 @@ function Values({
11223
11558
  onClick: () => onDrill(point),
11224
11559
  children: text
11225
11560
  }
11226
- ) : /* @__PURE__ */ jsx44("span", { className: "flex min-w-0 items-center gap-1.5 px-1 py-0.5 text-xs", children: text }) }, point.label);
11561
+ ) : /* @__PURE__ */ jsx45("span", { className: "flex min-w-0 items-center gap-1.5 px-1 py-0.5 text-xs", children: text }) }, point.label);
11227
11562
  }) });
11228
11563
  }
11229
11564
  function GroupTable({
@@ -11231,8 +11566,8 @@ function GroupTable({
11231
11566
  series,
11232
11567
  onDrill
11233
11568
  }) {
11234
- return /* @__PURE__ */ jsx44("table", { className: "w-full text-xs", children: /* @__PURE__ */ jsx44("tbody", { children: points.map((point) => /* @__PURE__ */ jsxs40("tr", { className: "border-t first:border-t-0", children: [
11235
- /* @__PURE__ */ jsx44("td", { className: "min-w-0 truncate py-0.5 pr-2", children: onDrill ? /* @__PURE__ */ jsx44(
11569
+ return /* @__PURE__ */ jsx45("table", { className: "w-full text-xs", children: /* @__PURE__ */ jsx45("tbody", { children: points.map((point) => /* @__PURE__ */ jsxs41("tr", { className: "border-t first:border-t-0", children: [
11570
+ /* @__PURE__ */ jsx45("td", { className: "min-w-0 truncate py-0.5 pr-2", children: onDrill ? /* @__PURE__ */ jsx45(
11236
11571
  "button",
11237
11572
  {
11238
11573
  type: "button",
@@ -11241,29 +11576,29 @@ function GroupTable({
11241
11576
  children: point.label
11242
11577
  }
11243
11578
  ) : point.label }),
11244
- series.map((key) => /* @__PURE__ */ jsx44("td", { className: "py-0.5 pl-2 text-right tabular-nums", children: pretty(point.values[key] ?? 0) }, key)),
11245
- /* @__PURE__ */ jsx44("td", { className: "py-0.5 pl-2 text-right tabular-nums text-muted-foreground", children: point.n })
11579
+ series.map((key) => /* @__PURE__ */ jsx45("td", { className: "py-0.5 pl-2 text-right tabular-nums", children: pretty(point.values[key] ?? 0) }, key)),
11580
+ /* @__PURE__ */ jsx45("td", { className: "py-0.5 pl-2 text-right tabular-nums text-muted-foreground", children: point.n })
11246
11581
  ] }, point.label)) }) });
11247
11582
  }
11248
11583
  function StuckList({ rows }) {
11249
11584
  if (rows.length === 0) {
11250
- return /* @__PURE__ */ jsx44("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." });
11585
+ return /* @__PURE__ */ jsx45("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." });
11251
11586
  }
11252
- return /* @__PURE__ */ jsxs40("table", { className: "w-full table-fixed text-xs", children: [
11253
- /* @__PURE__ */ jsxs40("colgroup", { children: [
11254
- /* @__PURE__ */ jsx44("col", { className: "w-[45%]" }),
11255
- /* @__PURE__ */ jsx44("col", { className: "w-[33%]" }),
11256
- /* @__PURE__ */ jsx44("col", { className: "w-[22%]" })
11587
+ return /* @__PURE__ */ jsxs41("table", { className: "w-full table-fixed text-xs", children: [
11588
+ /* @__PURE__ */ jsxs41("colgroup", { children: [
11589
+ /* @__PURE__ */ jsx45("col", { className: "w-[45%]" }),
11590
+ /* @__PURE__ */ jsx45("col", { className: "w-[33%]" }),
11591
+ /* @__PURE__ */ jsx45("col", { className: "w-[22%]" })
11257
11592
  ] }),
11258
- /* @__PURE__ */ jsx44("thead", { className: "sr-only", children: /* @__PURE__ */ jsxs40("tr", { children: [
11259
- /* @__PURE__ */ jsx44("th", { children: "Record" }),
11260
- /* @__PURE__ */ jsx44("th", { children: "Where it is" }),
11261
- /* @__PURE__ */ jsx44("th", { children: "Days unchanged" })
11593
+ /* @__PURE__ */ jsx45("thead", { className: "sr-only", children: /* @__PURE__ */ jsxs41("tr", { children: [
11594
+ /* @__PURE__ */ jsx45("th", { children: "Record" }),
11595
+ /* @__PURE__ */ jsx45("th", { children: "Where it is" }),
11596
+ /* @__PURE__ */ jsx45("th", { children: "Days unchanged" })
11262
11597
  ] }) }),
11263
- /* @__PURE__ */ jsx44("tbody", { children: rows.map((row) => /* @__PURE__ */ jsxs40("tr", { className: "border-t first:border-t-0", children: [
11264
- /* @__PURE__ */ jsx44("td", { className: "truncate py-0.5 pr-2", title: row.title ?? void 0, children: row.title ?? row.record_id.slice(0, 8) }),
11265
- /* @__PURE__ */ jsx44("td", { className: "truncate py-0.5 pr-2 text-muted-foreground", title: row.state ?? void 0, children: row.state ?? "\u2014" }),
11266
- /* @__PURE__ */ jsxs40(
11598
+ /* @__PURE__ */ jsx45("tbody", { children: rows.map((row) => /* @__PURE__ */ jsxs41("tr", { className: "border-t first:border-t-0", children: [
11599
+ /* @__PURE__ */ jsx45("td", { className: "truncate py-0.5 pr-2", title: row.title ?? void 0, children: row.title ?? row.record_id.slice(0, 8) }),
11600
+ /* @__PURE__ */ jsx45("td", { className: "truncate py-0.5 pr-2 text-muted-foreground", title: row.state ?? void 0, children: row.state ?? "\u2014" }),
11601
+ /* @__PURE__ */ jsxs41(
11267
11602
  "td",
11268
11603
  {
11269
11604
  className: "whitespace-nowrap py-0.5 text-right tabular-nums",
@@ -11313,12 +11648,12 @@ function Drawing({
11313
11648
  axisLine: false,
11314
11649
  tickFormatter: compactTick
11315
11650
  };
11316
- const tooltip = /* @__PURE__ */ jsx44(Tooltip, { content: /* @__PURE__ */ jsx44(ChartTooltipContent, { config }), cursor: false });
11317
- const legend = series.length > 1 ? /* @__PURE__ */ jsx44(Legend, { content: /* @__PURE__ */ jsx44(ChartLegendContent, { config }) }) : null;
11651
+ const tooltip = /* @__PURE__ */ jsx45(Tooltip, { content: /* @__PURE__ */ jsx45(ChartTooltipContent, { config }), cursor: false });
11652
+ const legend = series.length > 1 ? /* @__PURE__ */ jsx45(Legend, { content: /* @__PURE__ */ jsx45(ChartLegendContent, { config }) }) : null;
11318
11653
  if (kind === "donut") {
11319
- return /* @__PURE__ */ jsx44(ChartFrame, { config, height: HEIGHT, children: (width) => /* @__PURE__ */ jsxs40(PieChart, { width, height: HEIGHT, children: [
11654
+ return /* @__PURE__ */ jsx45(ChartFrame, { config, height: HEIGHT, children: (width) => /* @__PURE__ */ jsxs41(PieChart, { width, height: HEIGHT, children: [
11320
11655
  tooltip,
11321
- /* @__PURE__ */ jsx44(
11656
+ /* @__PURE__ */ jsx45(
11322
11657
  Pie,
11323
11658
  {
11324
11659
  data,
@@ -11328,19 +11663,19 @@ function Drawing({
11328
11663
  outerRadius: 58,
11329
11664
  isAnimationActive: false,
11330
11665
  ...click ? { onClick: click, className: "cursor-pointer" } : {},
11331
- children: points.map((point) => /* @__PURE__ */ jsx44(Cell, { fill: String(config[point.label]?.color ?? SERIES_COLORS[0]) }, point.label))
11666
+ children: points.map((point) => /* @__PURE__ */ jsx45(Cell, { fill: String(config[point.label]?.color ?? SERIES_COLORS[0]) }, point.label))
11332
11667
  }
11333
11668
  )
11334
11669
  ] }) });
11335
11670
  }
11336
11671
  if (kind === "line") {
11337
- return /* @__PURE__ */ jsx44(ChartFrame, { config, height: HEIGHT, children: (width) => /* @__PURE__ */ jsxs40(LineChart, { width, height: HEIGHT, data, margin: { top: 6, right: 6, bottom: 0, left: 0 }, children: [
11338
- /* @__PURE__ */ jsx44(CartesianGrid, { vertical: false }),
11339
- /* @__PURE__ */ jsx44(XAxis, { dataKey: "label", ...axis }),
11340
- /* @__PURE__ */ jsx44(YAxis, { width: 44, ...axis }),
11672
+ return /* @__PURE__ */ jsx45(ChartFrame, { config, height: HEIGHT, children: (width) => /* @__PURE__ */ jsxs41(LineChart, { width, height: HEIGHT, data, margin: { top: 6, right: 6, bottom: 0, left: 0 }, children: [
11673
+ /* @__PURE__ */ jsx45(CartesianGrid, { vertical: false }),
11674
+ /* @__PURE__ */ jsx45(XAxis, { dataKey: "label", ...axis }),
11675
+ /* @__PURE__ */ jsx45(YAxis, { width: 44, ...axis }),
11341
11676
  tooltip,
11342
11677
  legend,
11343
- series.map((key) => /* @__PURE__ */ jsx44(
11678
+ series.map((key) => /* @__PURE__ */ jsx45(
11344
11679
  Line2,
11345
11680
  {
11346
11681
  type: "monotone",
@@ -11356,7 +11691,7 @@ function Drawing({
11356
11691
  ] }) });
11357
11692
  }
11358
11693
  const horizontal = kind === "bar";
11359
- return /* @__PURE__ */ jsx44(ChartFrame, { config, height: HEIGHT, children: (width) => /* @__PURE__ */ jsxs40(
11694
+ return /* @__PURE__ */ jsx45(ChartFrame, { config, height: HEIGHT, children: (width) => /* @__PURE__ */ jsxs41(
11360
11695
  BarChart,
11361
11696
  {
11362
11697
  width,
@@ -11365,17 +11700,17 @@ function Drawing({
11365
11700
  layout: horizontal ? "vertical" : "horizontal",
11366
11701
  margin: { top: 6, right: 6, bottom: 0, left: 0 },
11367
11702
  children: [
11368
- /* @__PURE__ */ jsx44(CartesianGrid, { vertical: horizontal, horizontal: !horizontal }),
11369
- horizontal ? /* @__PURE__ */ jsxs40(Fragment18, { children: [
11370
- /* @__PURE__ */ jsx44(XAxis, { type: "number", ...axis }),
11371
- /* @__PURE__ */ jsx44(YAxis, { type: "category", dataKey: "label", width: 88, ...axis })
11372
- ] }) : /* @__PURE__ */ jsxs40(Fragment18, { children: [
11373
- /* @__PURE__ */ jsx44(XAxis, { dataKey: "label", ...axis }),
11374
- /* @__PURE__ */ jsx44(YAxis, { width: 44, ...axis })
11703
+ /* @__PURE__ */ jsx45(CartesianGrid, { vertical: horizontal, horizontal: !horizontal }),
11704
+ horizontal ? /* @__PURE__ */ jsxs41(Fragment19, { children: [
11705
+ /* @__PURE__ */ jsx45(XAxis, { type: "number", ...axis }),
11706
+ /* @__PURE__ */ jsx45(YAxis, { type: "category", dataKey: "label", width: 88, ...axis })
11707
+ ] }) : /* @__PURE__ */ jsxs41(Fragment19, { children: [
11708
+ /* @__PURE__ */ jsx45(XAxis, { dataKey: "label", ...axis }),
11709
+ /* @__PURE__ */ jsx45(YAxis, { width: 44, ...axis })
11375
11710
  ] }),
11376
11711
  tooltip,
11377
11712
  legend,
11378
- series.map((key, index) => /* @__PURE__ */ jsx44(
11713
+ series.map((key, index) => /* @__PURE__ */ jsx45(
11379
11714
  Bar,
11380
11715
  {
11381
11716
  dataKey: key,
@@ -11383,7 +11718,7 @@ function Drawing({
11383
11718
  isAnimationActive: false,
11384
11719
  fill: `var(--color-${key})`,
11385
11720
  ...click ? { onClick: click, className: "cursor-pointer" } : {},
11386
- children: series.length === 1 ? points.map((point) => /* @__PURE__ */ jsx44(Cell, { fill: String(config[point.label]?.color ?? SERIES_COLORS[index]) }, point.label)) : null
11721
+ children: series.length === 1 ? points.map((point) => /* @__PURE__ */ jsx45(Cell, { fill: String(config[point.label]?.color ?? SERIES_COLORS[index]) }, point.label)) : null
11387
11722
  },
11388
11723
  key
11389
11724
  ))
@@ -11393,24 +11728,25 @@ function Drawing({
11393
11728
  }
11394
11729
 
11395
11730
  // src/DashboardCanvas.tsx
11396
- import { useCallback as useCallback26, useEffect as useEffect30, useMemo as useMemo26, useState as useState40 } from "react";
11397
- import { useFields as useFields19, useRecordsClient as useRecordsClient32, useTable as useTable17 } from "@ai-matrx/records/react";
11398
- import { BasicInput as BasicInput13, Button as Button36, Skeleton as Skeleton23, cn as cn39 } from "@ai-matrx/design-system";
11399
- import { Fragment as Fragment19, jsx as jsx45, jsxs as jsxs41 } from "react/jsx-runtime";
11731
+ import { useCallback as useCallback27, useEffect as useEffect31, useMemo as useMemo27, useState as useState41 } from "react";
11732
+ import { useFields as useFields19, useRecordsClient as useRecordsClient33, useTable as useTable17 } from "@ai-matrx/records/react";
11733
+ import { BasicInput as BasicInput14, Button as Button37, Skeleton as Skeleton24, cn as cn40 } from "@ai-matrx/design-system";
11734
+ import { Fragment as Fragment20, jsx as jsx46, jsxs as jsxs42 } from "react/jsx-runtime";
11400
11735
  function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11401
- const client = useRecordsClient32();
11736
+ const client = useRecordsClient33();
11402
11737
  const host = useRecordsUi();
11403
11738
  const table = useTable17(tableId);
11404
11739
  const rights = useTableRights(table.data);
11405
11740
  const fields = useFields19(tableId);
11406
- const [boards, setBoards] = useState40(null);
11407
- const [error, setError] = useState40(null);
11408
- const [activeId, setActiveId] = useState40(activeDashboardId ?? null);
11409
- const [run, setRun] = useState40(null);
11410
- const [running, setRunning] = useState40(false);
11411
- const [question, setQuestion] = useState40("");
11412
- const [asking, setAsking] = useState40(false);
11413
- const load = useCallback26(async () => {
11741
+ const [boards, setBoards] = useState41(null);
11742
+ const [error, setError] = useState41(null);
11743
+ const [activeId, setActiveId] = useState41(activeDashboardId ?? null);
11744
+ const [run, setRun] = useState41(null);
11745
+ const [running, setRunning] = useState41(false);
11746
+ const [question, setQuestion] = useState41("");
11747
+ const [asking, setAsking] = useState41(false);
11748
+ const [scheduling, setScheduling] = useState41(false);
11749
+ const load = useCallback27(async () => {
11414
11750
  const answered = await client.dashboards({ table_id: tableId });
11415
11751
  if (!answered.ok) {
11416
11752
  setError(answered.error);
@@ -11419,17 +11755,17 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11419
11755
  setError(null);
11420
11756
  setBoards(answered.data.map(dashboardFromSummary));
11421
11757
  }, [client, tableId]);
11422
- useEffect30(() => {
11758
+ useEffect31(() => {
11423
11759
  void load();
11424
11760
  }, [load]);
11425
- useEffect30(() => {
11761
+ useEffect31(() => {
11426
11762
  if (!boards || boards.length === 0) return;
11427
11763
  const chosen = boards.find((d) => d.id === (activeDashboardId ?? activeId)) ?? boards[0];
11428
11764
  if (chosen.id !== activeId) setActiveId(chosen.id);
11429
11765
  }, [boards, activeDashboardId]);
11430
- const board = useMemo26(() => boards?.find((d) => d.id === activeId) ?? null, [boards, activeId]);
11766
+ const board = useMemo27(() => boards?.find((d) => d.id === activeId) ?? null, [boards, activeId]);
11431
11767
  const filterKey = JSON.stringify(filter ?? {});
11432
- useEffect30(() => {
11768
+ useEffect31(() => {
11433
11769
  if (!activeId) {
11434
11770
  setRun(null);
11435
11771
  return;
@@ -11447,7 +11783,7 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11447
11783
  cancelled = true;
11448
11784
  };
11449
11785
  }, [client, activeId, filterKey]);
11450
- const declare2 = useCallback26(
11786
+ const declare2 = useCallback27(
11451
11787
  async (next, blocks) => {
11452
11788
  const written = await client.dashboardDeclare(
11453
11789
  dashboardDeclareArgs({ ...next, blocks }, tableId)
@@ -11493,7 +11829,7 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11493
11829
  ]
11494
11830
  );
11495
11831
  }
11496
- const refresh = useCallback26(async () => {
11832
+ const refresh = useCallback27(async () => {
11497
11833
  if (!activeId) return;
11498
11834
  setRunning(true);
11499
11835
  const again = await client.dashboardRun({
@@ -11534,20 +11870,20 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11534
11870
  }
11535
11871
  }
11536
11872
  if (error) {
11537
- return /* @__PURE__ */ jsx45(
11873
+ return /* @__PURE__ */ jsx46(
11538
11874
  RefusalNotice,
11539
11875
  {
11540
11876
  error,
11541
11877
  className,
11542
- actions: /* @__PURE__ */ jsx45(Button36, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
11878
+ actions: /* @__PURE__ */ jsx46(Button37, { size: "sm", variant: "ghost", onClick: () => void load(), children: "Try again" })
11543
11879
  }
11544
11880
  );
11545
11881
  }
11546
- if (boards === null) return /* @__PURE__ */ jsx45(Skeleton23, { className: cn39("h-64 w-full", className) });
11547
- return /* @__PURE__ */ jsxs41("div", { className: cn39("flex min-h-0 flex-col gap-2", className), children: [
11548
- /* @__PURE__ */ jsxs41("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Dashboards", children: [
11549
- boards.map((d) => /* @__PURE__ */ jsx45(
11550
- Button36,
11882
+ if (boards === null) return /* @__PURE__ */ jsx46(Skeleton24, { className: cn40("h-64 w-full", className) });
11883
+ return /* @__PURE__ */ jsxs42("div", { className: cn40("flex min-h-0 flex-col gap-2", className), children: [
11884
+ /* @__PURE__ */ jsxs42("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Dashboards", children: [
11885
+ boards.map((d) => /* @__PURE__ */ jsx46(
11886
+ Button37,
11551
11887
  {
11552
11888
  size: "sm",
11553
11889
  variant: d.id === activeId ? "secondary" : "ghost",
@@ -11557,10 +11893,10 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11557
11893
  },
11558
11894
  d.id
11559
11895
  )),
11560
- rights.admin ? /* @__PURE__ */ jsx45(Button36, { size: "sm", variant: "ghost", onClick: () => void create(), children: "New dashboard" }) : null,
11561
- board ? /* @__PURE__ */ jsxs41("span", { className: "ml-auto flex items-center gap-1", children: [
11562
- /* @__PURE__ */ jsx45(
11563
- Button36,
11896
+ rights.admin ? /* @__PURE__ */ jsx46(Button37, { size: "sm", variant: "ghost", onClick: () => void create(), children: "New dashboard" }) : null,
11897
+ board ? /* @__PURE__ */ jsxs42("span", { className: "ml-auto flex items-center gap-1", children: [
11898
+ /* @__PURE__ */ jsx46(
11899
+ Button37,
11564
11900
  {
11565
11901
  size: "sm",
11566
11902
  variant: "ghost",
@@ -11569,13 +11905,31 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11569
11905
  children: running ? "Asking" : "Refresh"
11570
11906
  }
11571
11907
  ),
11572
- rights.admin ? /* @__PURE__ */ jsx45(Button36, { size: "sm", variant: "ghost", onClick: () => void remove(board), children: "Delete" }) : null
11908
+ /* @__PURE__ */ jsx46(
11909
+ Button37,
11910
+ {
11911
+ size: "sm",
11912
+ variant: scheduling ? "secondary" : "ghost",
11913
+ onClick: () => setScheduling((v) => !v),
11914
+ children: scheduling ? "Done" : "Send on a schedule"
11915
+ }
11916
+ ),
11917
+ rights.admin ? /* @__PURE__ */ jsx46(Button37, { size: "sm", variant: "ghost", onClick: () => void remove(board), children: "Delete" }) : null
11573
11918
  ] }) : null
11574
11919
  ] }),
11575
- board ? /* @__PURE__ */ jsxs41("div", { className: "flex flex-col gap-1", children: [
11576
- /* @__PURE__ */ jsxs41("div", { className: "flex items-center gap-1", children: [
11577
- /* @__PURE__ */ jsx45(
11578
- BasicInput13,
11920
+ board && scheduling ? /* @__PURE__ */ jsx46(
11921
+ DigestScheduler,
11922
+ {
11923
+ tableId,
11924
+ subjectName: board.name,
11925
+ ...filter ? { filters: filter } : {},
11926
+ onClose: () => setScheduling(false)
11927
+ }
11928
+ ) : null,
11929
+ board ? /* @__PURE__ */ jsxs42("div", { className: "flex flex-col gap-1", children: [
11930
+ /* @__PURE__ */ jsxs42("div", { className: "flex items-center gap-1", children: [
11931
+ /* @__PURE__ */ jsx46(
11932
+ BasicInput14,
11579
11933
  {
11580
11934
  value: question,
11581
11935
  "aria-label": "Ask for a change to this dashboard",
@@ -11588,15 +11942,15 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11588
11942
  className: "h-8 min-w-0 flex-1 text-xs"
11589
11943
  }
11590
11944
  ),
11591
- /* @__PURE__ */ jsx45(Button36, { size: "sm", disabled: !host.onReask || asking || question.trim() === "", onClick: () => void reask(), children: asking ? "Asking" : "Ask" })
11945
+ /* @__PURE__ */ jsx46(Button37, { size: "sm", disabled: !host.onReask || asking || question.trim() === "", onClick: () => void reask(), children: asking ? "Asking" : "Ask" })
11592
11946
  ] }),
11593
- !host.onReask ? /* @__PURE__ */ jsx45("p", { className: "text-xs text-muted-foreground", children: NO_REASK_REASON }) : null
11947
+ !host.onReask ? /* @__PURE__ */ jsx46("p", { className: "text-xs text-muted-foreground", children: NO_REASK_REASON }) : null
11594
11948
  ] }) : null,
11595
- !board ? /* @__PURE__ */ jsx45("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__ */ jsx45(Skeleton23, { className: "h-64 w-full" }) : run.blocks.length === 0 ? /* @__PURE__ */ jsx45("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__ */ jsxs41(Fragment19, { children: [
11596
- /* @__PURE__ */ jsx45("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-3", children: run.blocks.map((block, index) => /* @__PURE__ */ jsxs41("div", { className: "flex min-w-0 flex-col gap-1", children: [
11597
- /* @__PURE__ */ jsx45(ChartBlock, { block, subject: tableId }),
11598
- rights.admin && board.blocks[index] ? /* @__PURE__ */ jsxs41("div", { className: "flex items-center gap-1 text-xs", children: [
11599
- /* @__PURE__ */ jsx45(
11949
+ !board ? /* @__PURE__ */ jsx46("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__ */ jsx46(Skeleton24, { className: "h-64 w-full" }) : run.blocks.length === 0 ? /* @__PURE__ */ jsx46("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__ */ jsxs42(Fragment20, { children: [
11950
+ /* @__PURE__ */ jsx46("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-3", children: run.blocks.map((block, index) => /* @__PURE__ */ jsxs42("div", { className: "flex min-w-0 flex-col gap-1", children: [
11951
+ /* @__PURE__ */ jsx46(ChartBlock, { block, subject: tableId }),
11952
+ rights.admin && board.blocks[index] ? /* @__PURE__ */ jsxs42("div", { className: "flex items-center gap-1 text-xs", children: [
11953
+ /* @__PURE__ */ jsx46(
11600
11954
  "select",
11601
11955
  {
11602
11956
  "aria-label": `Shape of ${block.title}`,
@@ -11608,11 +11962,11 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11608
11962
  (b, i) => i === index ? { ...b, kind: e.target.value } : b
11609
11963
  )
11610
11964
  ),
11611
- children: CHART_KINDS.map((kind) => /* @__PURE__ */ jsx45("option", { value: kind, children: CHART_KIND_LABEL[kind] }, kind))
11965
+ children: CHART_KINDS.map((kind) => /* @__PURE__ */ jsx46("option", { value: kind, children: CHART_KIND_LABEL[kind] }, kind))
11612
11966
  }
11613
11967
  ),
11614
- /* @__PURE__ */ jsx45(
11615
- Button36,
11968
+ /* @__PURE__ */ jsx46(
11969
+ Button37,
11616
11970
  {
11617
11971
  size: "sm",
11618
11972
  variant: "ghost",
@@ -11625,17 +11979,17 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
11625
11979
  )
11626
11980
  ] }) : null
11627
11981
  ] }, `${block.title}-${index}`)) }),
11628
- !host.openRecords ? /* @__PURE__ */ jsx45("p", { className: "text-xs text-muted-foreground", children: NO_OPEN_RECORDS_REASON }) : null
11982
+ !host.openRecords ? /* @__PURE__ */ jsx46("p", { className: "text-xs text-muted-foreground", children: NO_OPEN_RECORDS_REASON }) : null
11629
11983
  ] })
11630
11984
  ] });
11631
11985
  }
11632
11986
 
11633
11987
  // src/FormsPanel.tsx
11634
- import { useCallback as useCallback27, useEffect as useEffect31, useState as useState41 } from "react";
11635
- import { useRecordsClient as useRecordsClient33, useTable as useTable18 } from "@ai-matrx/records/react";
11988
+ import { useCallback as useCallback28, useEffect as useEffect32, useState as useState42 } from "react";
11989
+ import { useRecordsClient as useRecordsClient34, useTable as useTable18 } from "@ai-matrx/records/react";
11636
11990
  import { publicFormPath as publicFormPath2 } from "@ai-matrx/records";
11637
- import { Badge as Badge15, Button as Button37, Skeleton as Skeleton24, cn as cn40 } from "@ai-matrx/design-system";
11638
- import { Fragment as Fragment20, jsx as jsx46, jsxs as jsxs42 } from "react/jsx-runtime";
11991
+ import { Badge as Badge15, Button as Button38, Skeleton as Skeleton25, cn as cn41 } from "@ai-matrx/design-system";
11992
+ import { Fragment as Fragment21, jsx as jsx47, jsxs as jsxs43 } from "react/jsx-runtime";
11639
11993
  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.";
11640
11994
  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.";
11641
11995
  function formSuggestion(tableName2) {
@@ -11643,16 +11997,16 @@ function formSuggestion(tableName2) {
11643
11997
  return `Make me a form that collects new ${subject} entries and tells me when somebody answers.`;
11644
11998
  }
11645
11999
  function FormsPanel({ tableId, className }) {
11646
- const client = useRecordsClient33();
12000
+ const client = useRecordsClient34();
11647
12001
  const host = useRecordsUi();
11648
12002
  const table = useTable18(tableId);
11649
12003
  const rights = useTableRights(table.data);
11650
- const [forms, setForms] = useState41(null);
11651
- const [error, setError] = useState41(null);
11652
- const [busy, setBusy] = useState41(null);
11653
- const [copied, setCopied] = useState41(null);
11654
- const [building, setBuilding] = useState41(false);
11655
- const load = useCallback27(async () => {
12004
+ const [forms, setForms] = useState42(null);
12005
+ const [error, setError] = useState42(null);
12006
+ const [busy, setBusy] = useState42(null);
12007
+ const [copied, setCopied] = useState42(null);
12008
+ const [building, setBuilding] = useState42(false);
12009
+ const load = useCallback28(async () => {
11656
12010
  const answered = await client.forms({ table_id: tableId });
11657
12011
  if (!answered.ok) {
11658
12012
  setError(answered.error);
@@ -11662,10 +12016,10 @@ function FormsPanel({ tableId, className }) {
11662
12016
  setError(null);
11663
12017
  setForms(answered.data);
11664
12018
  }, [client, tableId]);
11665
- useEffect31(() => {
12019
+ useEffect32(() => {
11666
12020
  void load();
11667
12021
  }, [load]);
11668
- const toggle = useCallback27(
12022
+ const toggle = useCallback28(
11669
12023
  async (form) => {
11670
12024
  setBusy(form.form_id);
11671
12025
  const wanted = form.published_at === null || form.closed_at !== null;
@@ -11679,8 +12033,8 @@ function FormsPanel({ tableId, className }) {
11679
12033
  },
11680
12034
  [client, load]
11681
12035
  );
11682
- const [shown, setShown] = useState41(null);
11683
- const copy = useCallback27(async (url, formId) => {
12036
+ const [shown, setShown] = useState42(null);
12037
+ const copy = useCallback28(async (url, formId) => {
11684
12038
  try {
11685
12039
  await navigator.clipboard.writeText(url);
11686
12040
  setCopied(formId);
@@ -11690,17 +12044,17 @@ function FormsPanel({ tableId, className }) {
11690
12044
  setShown(url);
11691
12045
  }
11692
12046
  }, []);
11693
- if (forms === null) return /* @__PURE__ */ jsx46(Skeleton24, { className: cn40("h-32 w-full", className) });
12047
+ if (forms === null) return /* @__PURE__ */ jsx47(Skeleton25, { className: cn41("h-32 w-full", className) });
11694
12048
  const origin = host.publicOrigin ?? (typeof window === "undefined" ? "" : window.location.origin);
11695
- return /* @__PURE__ */ jsxs42("section", { className: cn40("flex flex-col gap-3", className), children: [
11696
- /* @__PURE__ */ jsxs42("header", { className: "flex items-center gap-2", children: [
11697
- /* @__PURE__ */ jsx46("h3", { className: "text-sm font-medium", children: "Forms" }),
11698
- /* @__PURE__ */ jsx46("span", { className: "text-xs text-muted-foreground", children: forms.length === 0 ? "none yet" : `${forms.length}` }),
11699
- /* @__PURE__ */ jsx46("div", { className: "flex-1" }),
11700
- rights.structure && forms.length > 0 ? /* @__PURE__ */ jsx46(Button37, { size: "sm", variant: building ? "secondary" : "ghost", onClick: () => setBuilding((b) => !b), children: building ? "Done building" : "Build a form" }) : null
12049
+ return /* @__PURE__ */ jsxs43("section", { className: cn41("flex flex-col gap-3", className), children: [
12050
+ /* @__PURE__ */ jsxs43("header", { className: "flex items-center gap-2", children: [
12051
+ /* @__PURE__ */ jsx47("h3", { className: "text-sm font-medium", children: "Forms" }),
12052
+ /* @__PURE__ */ jsx47("span", { className: "text-xs text-muted-foreground", children: forms.length === 0 ? "none yet" : `${forms.length}` }),
12053
+ /* @__PURE__ */ jsx47("div", { className: "flex-1" }),
12054
+ rights.structure && forms.length > 0 ? /* @__PURE__ */ jsx47(Button38, { size: "sm", variant: building ? "secondary" : "ghost", onClick: () => setBuilding((b) => !b), children: building ? "Done building" : "Build a form" }) : null
11701
12055
  ] }),
11702
- error ? /* @__PURE__ */ jsx46(RefusalNotice, { error }) : null,
11703
- building ? /* @__PURE__ */ jsx46(
12056
+ error ? /* @__PURE__ */ jsx47(RefusalNotice, { error }) : null,
12057
+ building ? /* @__PURE__ */ jsx47(
11704
12058
  FormBuilder,
11705
12059
  {
11706
12060
  tableId,
@@ -11709,7 +12063,7 @@ function FormsPanel({ tableId, className }) {
11709
12063
  }
11710
12064
  }
11711
12065
  ) : null,
11712
- forms.length === 0 && !building ? /* @__PURE__ */ jsx46(
12066
+ forms.length === 0 && !building ? /* @__PURE__ */ jsx47(
11713
12067
  BuildOrAsk,
11714
12068
  {
11715
12069
  mayBuild: rights.structure,
@@ -11727,36 +12081,36 @@ function FormsPanel({ tableId, className }) {
11727
12081
  children: WHAT_A_FORM_IS
11728
12082
  }
11729
12083
  ) : null,
11730
- /* @__PURE__ */ jsx46("ul", { className: "flex flex-col gap-2", children: forms.map((form) => {
12084
+ /* @__PURE__ */ jsx47("ul", { className: "flex flex-col gap-2", children: forms.map((form) => {
11731
12085
  const url = `${origin}${publicFormPath2(form.form_id)}`;
11732
- return /* @__PURE__ */ jsxs42("li", { className: "rounded-md border p-2.5", children: [
11733
- /* @__PURE__ */ jsxs42("div", { className: "flex items-center gap-2", children: [
11734
- /* @__PURE__ */ jsx46("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: form.title ?? form.slug }),
11735
- /* @__PURE__ */ jsx46(Badge15, { variant: form.state === "open" ? "default" : "secondary", children: form.state })
12086
+ return /* @__PURE__ */ jsxs43("li", { className: "rounded-md border p-2.5", children: [
12087
+ /* @__PURE__ */ jsxs43("div", { className: "flex items-center gap-2", children: [
12088
+ /* @__PURE__ */ jsx47("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: form.title ?? form.slug }),
12089
+ /* @__PURE__ */ jsx47(Badge15, { variant: form.state === "open" ? "default" : "secondary", children: form.state })
11736
12090
  ] }),
11737
- /* @__PURE__ */ jsx46("p", { className: "mt-0.5 text-xs text-muted-foreground", children: FORM_STATE_WORDS[form.state] }),
11738
- /* @__PURE__ */ jsxs42("p", { className: "mt-1.5 text-xs", children: [
11739
- /* @__PURE__ */ jsx46("span", { className: "font-medium", children: form.in_table }),
12091
+ /* @__PURE__ */ jsx47("p", { className: "mt-0.5 text-xs text-muted-foreground", children: FORM_STATE_WORDS[form.state] }),
12092
+ /* @__PURE__ */ jsxs43("p", { className: "mt-1.5 text-xs", children: [
12093
+ /* @__PURE__ */ jsx47("span", { className: "font-medium", children: form.in_table }),
11740
12094
  " in the table",
11741
- form.held > 0 ? /* @__PURE__ */ jsxs42(Fragment20, { children: [
12095
+ form.held > 0 ? /* @__PURE__ */ jsxs43(Fragment21, { children: [
11742
12096
  " \xB7 ",
11743
- /* @__PURE__ */ jsx46("span", { className: "font-medium", children: form.held }),
12097
+ /* @__PURE__ */ jsx47("span", { className: "font-medium", children: form.held }),
11744
12098
  " waiting for someone"
11745
12099
  ] }) : null,
11746
- form.rejected > 0 ? /* @__PURE__ */ jsxs42(Fragment20, { children: [
12100
+ form.rejected > 0 ? /* @__PURE__ */ jsxs43(Fragment21, { children: [
11747
12101
  " \xB7 ",
11748
- /* @__PURE__ */ jsx46("span", { className: "font-medium", children: form.rejected }),
12102
+ /* @__PURE__ */ jsx47("span", { className: "font-medium", children: form.rejected }),
11749
12103
  " turned away"
11750
12104
  ] }) : null,
11751
- form.submission_cap !== null ? /* @__PURE__ */ jsxs42("span", { className: "text-muted-foreground", children: [
12105
+ form.submission_cap !== null ? /* @__PURE__ */ jsxs43("span", { className: "text-muted-foreground", children: [
11752
12106
  " \xB7 stops at ",
11753
12107
  form.submission_cap
11754
12108
  ] }) : null
11755
12109
  ] }),
11756
- /* @__PURE__ */ jsxs42("div", { className: "mt-2 flex flex-wrap items-center gap-1.5", children: [
11757
- form.published_at ? /* @__PURE__ */ jsx46(Button37, { size: "sm", variant: "outline", onClick: () => void copy(url, form.form_id), children: copied === form.form_id ? "Copied" : "Copy link" }) : null,
11758
- rights.structure ? /* @__PURE__ */ jsx46(
11759
- Button37,
12110
+ /* @__PURE__ */ jsxs43("div", { className: "mt-2 flex flex-wrap items-center gap-1.5", children: [
12111
+ form.published_at ? /* @__PURE__ */ jsx47(Button38, { size: "sm", variant: "outline", onClick: () => void copy(url, form.form_id), children: copied === form.form_id ? "Copied" : "Copy link" }) : null,
12112
+ rights.structure ? /* @__PURE__ */ jsx47(
12113
+ Button38,
11760
12114
  {
11761
12115
  size: "sm",
11762
12116
  variant: "ghost",
@@ -11766,25 +12120,25 @@ function FormsPanel({ tableId, className }) {
11766
12120
  }
11767
12121
  ) : null
11768
12122
  ] }),
11769
- shown && shown === url ? /* @__PURE__ */ jsxs42("p", { className: "mt-1.5 break-all rounded border border-dashed px-2 py-1 text-xs", children: [
12123
+ shown && shown === url ? /* @__PURE__ */ jsxs43("p", { className: "mt-1.5 break-all rounded border border-dashed px-2 py-1 text-xs", children: [
11770
12124
  "This browser would not let the page copy for you, so here it is to copy by hand:",
11771
12125
  " ",
11772
12126
  url
11773
12127
  ] }) : null
11774
12128
  ] }, form.form_id);
11775
12129
  }) }),
11776
- !rights.known ? /* @__PURE__ */ jsx46("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
12130
+ !rights.known ? /* @__PURE__ */ jsx47("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
11777
12131
  ] });
11778
12132
  }
11779
12133
 
11780
12134
  // src/BookingBuilder.tsx
11781
- import { useCallback as useCallback28, useEffect as useEffect32, useMemo as useMemo27, useState as useState42 } from "react";
11782
- import { useFields as useFields20, useRecordsClient as useRecordsClient34, useTable as useTable19 } from "@ai-matrx/records/react";
12135
+ import { useCallback as useCallback29, useEffect as useEffect33, useMemo as useMemo28, useState as useState43 } from "react";
12136
+ import { useFields as useFields20, useRecordsClient as useRecordsClient35, useTable as useTable19 } from "@ai-matrx/records/react";
11783
12137
  import {
11784
12138
  bookingPath
11785
12139
  } from "@ai-matrx/records";
11786
- import { BasicInput as BasicInput14, BasicTextarea as BasicTextarea7, Button as Button38, Checkbox as Checkbox6, Label as Label7, Skeleton as Skeleton25, cn as cn41 } from "@ai-matrx/design-system";
11787
- import { Fragment as Fragment21, jsx as jsx47, jsxs as jsxs43 } from "react/jsx-runtime";
12140
+ import { BasicInput as BasicInput15, BasicTextarea as BasicTextarea7, Button as Button39, Checkbox as Checkbox7, Label as Label8, Skeleton as Skeleton26, cn as cn42 } from "@ai-matrx/design-system";
12141
+ import { Fragment as Fragment22, jsx as jsx48, jsxs as jsxs44 } from "react/jsx-runtime";
11788
12142
  var STORE_ANSWERS_THESE = ["slot", "status", "booked_with"];
11789
12143
  var DAYS = [
11790
12144
  { weekday: 1, label: "Mon" },
@@ -11808,36 +12162,36 @@ function draftWindows(availability) {
11808
12162
  });
11809
12163
  }
11810
12164
  function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
11811
- const client = useRecordsClient34();
12165
+ const client = useRecordsClient35();
11812
12166
  const host = useRecordsUi();
11813
12167
  const table = useTable19(tableId);
11814
12168
  const rights = useTableRights(table.data);
11815
12169
  const fields = useFields20(tableId);
11816
- const [existing, setExisting] = useState42(null);
11817
- const [loaded, setLoaded] = useState42(false);
11818
- const [error, setError] = useState42(null);
11819
- const [saving, setSaving] = useState42(false);
11820
- const [publishing, setPublishing] = useState42(false);
11821
- const [copied, setCopied] = useState42(false);
11822
- const [title, setTitle] = useState42("");
11823
- const [minutes, setMinutes] = useState42(30);
11824
- const [buffer, setBuffer] = useState42(0);
11825
- const [lead, setLead] = useState42(120);
11826
- const [perDay, setPerDay] = useState42(8);
11827
- const [days, setDays] = useState42(30);
11828
- const [windows, setWindows] = useState42(() => draftWindows(null));
11829
- const [asked, setAsked] = useState42([]);
11830
- const [confirmation, setConfirmation] = useState42("");
11831
- const [offer, setOffer] = useState42(null);
11832
- const [formId, setFormId] = useState42(bookingId ?? null);
12170
+ const [existing, setExisting] = useState43(null);
12171
+ const [loaded, setLoaded] = useState43(false);
12172
+ const [error, setError] = useState43(null);
12173
+ const [saving, setSaving] = useState43(false);
12174
+ const [publishing, setPublishing] = useState43(false);
12175
+ const [copied, setCopied] = useState43(false);
12176
+ const [title, setTitle] = useState43("");
12177
+ const [minutes, setMinutes] = useState43(30);
12178
+ const [buffer, setBuffer] = useState43(0);
12179
+ const [lead, setLead] = useState43(120);
12180
+ const [perDay, setPerDay] = useState43(8);
12181
+ const [days, setDays] = useState43(30);
12182
+ const [windows, setWindows] = useState43(() => draftWindows(null));
12183
+ const [asked, setAsked] = useState43([]);
12184
+ const [confirmation, setConfirmation] = useState43("");
12185
+ const [offer, setOffer] = useState43(null);
12186
+ const [formId, setFormId] = useState43(bookingId ?? null);
11833
12187
  const publicOrigin = host.publicOrigin ?? (typeof window === "undefined" ? "" : window.location.origin);
11834
- const askable = useMemo27(
12188
+ const askable = useMemo28(
11835
12189
  () => (fields.data ?? []).filter(
11836
12190
  (f) => !STORE_ANSWERS_THESE.includes(f.key)
11837
12191
  ),
11838
12192
  [fields.data]
11839
12193
  );
11840
- const load = useCallback28(async () => {
12194
+ const load = useCallback29(async () => {
11841
12195
  const answered = await client.bookings({ table_id: tableId });
11842
12196
  if (!answered.ok) {
11843
12197
  setError(answered.error);
@@ -11849,18 +12203,18 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
11849
12203
  setLoaded(true);
11850
12204
  if (mine) setFormId(mine.form_id);
11851
12205
  }, [client, tableId, bookingId]);
11852
- useEffect32(() => {
12206
+ useEffect33(() => {
11853
12207
  void load();
11854
12208
  }, [load]);
11855
- useEffect32(() => {
12209
+ useEffect33(() => {
11856
12210
  if (title !== "" || !table.data) return;
11857
12211
  setTitle(existing?.title ?? `Book a ${minutes}-minute ${table.data.name} appointment`);
11858
12212
  }, [table.data, existing]);
11859
- useEffect32(() => {
12213
+ useEffect33(() => {
11860
12214
  if (!existing) return;
11861
12215
  setMinutes(existing.slot_minutes);
11862
12216
  }, [existing]);
11863
- const availability = useCallback28(
12217
+ const availability = useCallback29(
11864
12218
  () => ({
11865
12219
  slot_minutes: minutes,
11866
12220
  buffer_minutes: buffer,
@@ -11909,68 +12263,68 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
11909
12263
  await load();
11910
12264
  onSaved?.({ form_id: formId });
11911
12265
  }
11912
- if (!loaded || fields.loading) return /* @__PURE__ */ jsx47(Skeleton25, { className: cn41("h-64 w-full", className) });
12266
+ if (!loaded || fields.loading) return /* @__PURE__ */ jsx48(Skeleton26, { className: cn42("h-64 w-full", className) });
11913
12267
  if (!rights.structure) {
11914
- return /* @__PURE__ */ jsx47("p", { className: cn41("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." });
12268
+ return /* @__PURE__ */ jsx48("p", { className: cn42("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." });
11915
12269
  }
11916
12270
  const url = formId ? `${publicOrigin}${bookingPath(formId)}` : null;
11917
12271
  const shown = offer ?? null;
11918
- return /* @__PURE__ */ jsxs43("section", { className: cn41("flex flex-col gap-3", className), children: [
11919
- /* @__PURE__ */ jsxs43("header", { className: "flex items-center gap-2", children: [
11920
- /* @__PURE__ */ jsx47("h3", { className: "text-sm font-medium", children: existing ? "Booking page" : "New booking page" }),
11921
- /* @__PURE__ */ jsx47("div", { className: "flex-1" }),
11922
- /* @__PURE__ */ jsx47(Button38, { size: "sm", disabled: saving, onClick: () => void save(), children: saving ? "Saving\u2026" : "Save" }),
11923
- onClose ? /* @__PURE__ */ jsx47(Button38, { size: "sm", variant: "ghost", onClick: onClose, children: "Close" }) : null
12272
+ return /* @__PURE__ */ jsxs44("section", { className: cn42("flex flex-col gap-3", className), children: [
12273
+ /* @__PURE__ */ jsxs44("header", { className: "flex items-center gap-2", children: [
12274
+ /* @__PURE__ */ jsx48("h3", { className: "text-sm font-medium", children: existing ? "Booking page" : "New booking page" }),
12275
+ /* @__PURE__ */ jsx48("div", { className: "flex-1" }),
12276
+ /* @__PURE__ */ jsx48(Button39, { size: "sm", disabled: saving, onClick: () => void save(), children: saving ? "Saving\u2026" : "Save" }),
12277
+ onClose ? /* @__PURE__ */ jsx48(Button39, { size: "sm", variant: "ghost", onClick: onClose, children: "Close" }) : null
11924
12278
  ] }),
11925
- error ? /* @__PURE__ */ jsx47(RefusalNotice, { error }) : null,
11926
- /* @__PURE__ */ jsxs43("label", { className: "flex flex-col gap-1", children: [
11927
- /* @__PURE__ */ jsx47(Label7, { className: "text-xs font-medium", children: "What it is called" }),
11928
- /* @__PURE__ */ jsx47(BasicInput14, { value: title, onChange: (e) => setTitle(e.target.value) })
12279
+ error ? /* @__PURE__ */ jsx48(RefusalNotice, { error }) : null,
12280
+ /* @__PURE__ */ jsxs44("label", { className: "flex flex-col gap-1", children: [
12281
+ /* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "What it is called" }),
12282
+ /* @__PURE__ */ jsx48(BasicInput15, { value: title, onChange: (e) => setTitle(e.target.value) })
11929
12283
  ] }),
11930
- /* @__PURE__ */ jsxs43("div", { className: "grid grid-cols-2 gap-2", children: [
11931
- /* @__PURE__ */ jsxs43("label", { className: "flex flex-col gap-1", children: [
11932
- /* @__PURE__ */ jsx47(Label7, { className: "text-xs font-medium", children: "How long one appointment is" }),
11933
- /* @__PURE__ */ jsx47(
12284
+ /* @__PURE__ */ jsxs44("div", { className: "grid grid-cols-2 gap-2", children: [
12285
+ /* @__PURE__ */ jsxs44("label", { className: "flex flex-col gap-1", children: [
12286
+ /* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "How long one appointment is" }),
12287
+ /* @__PURE__ */ jsx48(
11934
12288
  "select",
11935
12289
  {
11936
12290
  className: "h-9 rounded border bg-background px-2 text-sm",
11937
12291
  value: minutes,
11938
12292
  onChange: (e) => setMinutes(Number(e.target.value)),
11939
- children: LENGTHS.map((n) => /* @__PURE__ */ jsxs43("option", { value: n, children: [
12293
+ children: LENGTHS.map((n) => /* @__PURE__ */ jsxs44("option", { value: n, children: [
11940
12294
  n,
11941
12295
  " minutes"
11942
12296
  ] }, n))
11943
12297
  }
11944
12298
  )
11945
12299
  ] }),
11946
- /* @__PURE__ */ jsxs43("label", { className: "flex flex-col gap-1", children: [
11947
- /* @__PURE__ */ jsx47(Label7, { className: "text-xs font-medium", children: "Gap kept after each one" }),
11948
- /* @__PURE__ */ jsx47(
12300
+ /* @__PURE__ */ jsxs44("label", { className: "flex flex-col gap-1", children: [
12301
+ /* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "Gap kept after each one" }),
12302
+ /* @__PURE__ */ jsx48(
11949
12303
  "select",
11950
12304
  {
11951
12305
  className: "h-9 rounded border bg-background px-2 text-sm",
11952
12306
  value: buffer,
11953
12307
  onChange: (e) => setBuffer(Number(e.target.value)),
11954
- children: [0, 5, 10, 15, 30].map((n) => /* @__PURE__ */ jsx47("option", { value: n, children: n === 0 ? "No gap \u2014 back to back" : `${n} minutes` }, n))
12308
+ children: [0, 5, 10, 15, 30].map((n) => /* @__PURE__ */ jsx48("option", { value: n, children: n === 0 ? "No gap \u2014 back to back" : `${n} minutes` }, n))
11955
12309
  }
11956
12310
  )
11957
12311
  ] }),
11958
- /* @__PURE__ */ jsxs43("label", { className: "flex flex-col gap-1", children: [
11959
- /* @__PURE__ */ jsx47(Label7, { className: "text-xs font-medium", children: "Earliest somebody may book" }),
11960
- /* @__PURE__ */ jsx47(
12312
+ /* @__PURE__ */ jsxs44("label", { className: "flex flex-col gap-1", children: [
12313
+ /* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "Earliest somebody may book" }),
12314
+ /* @__PURE__ */ jsx48(
11961
12315
  "select",
11962
12316
  {
11963
12317
  className: "h-9 rounded border bg-background px-2 text-sm",
11964
12318
  value: lead,
11965
12319
  onChange: (e) => setLead(Number(e.target.value)),
11966
- children: [0, 60, 120, 240, 1440].map((n) => /* @__PURE__ */ jsx47("option", { value: n, children: n === 0 ? "Right away" : n === 1440 ? "A day from now" : `${n / 60} hour${n === 60 ? "" : "s"} from now` }, n))
12320
+ children: [0, 60, 120, 240, 1440].map((n) => /* @__PURE__ */ jsx48("option", { value: n, children: n === 0 ? "Right away" : n === 1440 ? "A day from now" : `${n / 60} hour${n === 60 ? "" : "s"} from now` }, n))
11967
12321
  }
11968
12322
  )
11969
12323
  ] }),
11970
- /* @__PURE__ */ jsxs43("label", { className: "flex flex-col gap-1", children: [
11971
- /* @__PURE__ */ jsx47(Label7, { className: "text-xs font-medium", children: "Most in one day" }),
11972
- /* @__PURE__ */ jsx47(
11973
- BasicInput14,
12324
+ /* @__PURE__ */ jsxs44("label", { className: "flex flex-col gap-1", children: [
12325
+ /* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "Most in one day" }),
12326
+ /* @__PURE__ */ jsx48(
12327
+ BasicInput15,
11974
12328
  {
11975
12329
  type: "number",
11976
12330
  min: 1,
@@ -11979,15 +12333,15 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
11979
12333
  }
11980
12334
  )
11981
12335
  ] }),
11982
- /* @__PURE__ */ jsxs43("label", { className: "flex flex-col gap-1", children: [
11983
- /* @__PURE__ */ jsx47(Label7, { className: "text-xs font-medium", children: "How far ahead the page offers" }),
11984
- /* @__PURE__ */ jsx47(
12336
+ /* @__PURE__ */ jsxs44("label", { className: "flex flex-col gap-1", children: [
12337
+ /* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "How far ahead the page offers" }),
12338
+ /* @__PURE__ */ jsx48(
11985
12339
  "select",
11986
12340
  {
11987
12341
  className: "h-9 rounded border bg-background px-2 text-sm",
11988
12342
  value: days,
11989
12343
  onChange: (e) => setDays(Number(e.target.value)),
11990
- children: [7, 14, 30, 60, 90].map((n) => /* @__PURE__ */ jsxs43("option", { value: n, children: [
12344
+ children: [7, 14, 30, 60, 90].map((n) => /* @__PURE__ */ jsxs44("option", { value: n, children: [
11991
12345
  n,
11992
12346
  " days"
11993
12347
  ] }, n))
@@ -11995,12 +12349,12 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
11995
12349
  )
11996
12350
  ] })
11997
12351
  ] }),
11998
- /* @__PURE__ */ jsxs43("div", { className: "flex flex-col gap-1.5", children: [
11999
- /* @__PURE__ */ jsx47(Label7, { className: "text-xs font-medium", children: "Hours you are free" }),
12000
- windows.map((w, i) => /* @__PURE__ */ jsxs43("div", { className: "flex items-center gap-2", children: [
12001
- /* @__PURE__ */ jsxs43("label", { className: "flex w-20 items-center gap-1.5 text-xs", children: [
12002
- /* @__PURE__ */ jsx47(
12003
- Checkbox6,
12352
+ /* @__PURE__ */ jsxs44("div", { className: "flex flex-col gap-1.5", children: [
12353
+ /* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "Hours you are free" }),
12354
+ windows.map((w, i) => /* @__PURE__ */ jsxs44("div", { className: "flex items-center gap-2", children: [
12355
+ /* @__PURE__ */ jsxs44("label", { className: "flex w-20 items-center gap-1.5 text-xs", children: [
12356
+ /* @__PURE__ */ jsx48(
12357
+ Checkbox7,
12004
12358
  {
12005
12359
  checked: w.on,
12006
12360
  onCheckedChange: (on) => setWindows((prev) => prev.map((x, j) => i === j ? { ...x, on: Boolean(on) } : x))
@@ -12008,9 +12362,9 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12008
12362
  ),
12009
12363
  DAYS[i]?.label
12010
12364
  ] }),
12011
- w.on ? /* @__PURE__ */ jsxs43(Fragment21, { children: [
12012
- /* @__PURE__ */ jsx47(
12013
- BasicInput14,
12365
+ w.on ? /* @__PURE__ */ jsxs44(Fragment22, { children: [
12366
+ /* @__PURE__ */ jsx48(
12367
+ BasicInput15,
12014
12368
  {
12015
12369
  type: "time",
12016
12370
  className: "h-8 w-28",
@@ -12018,9 +12372,9 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12018
12372
  onChange: (e) => setWindows((prev) => prev.map((x, j) => i === j ? { ...x, from: e.target.value } : x))
12019
12373
  }
12020
12374
  ),
12021
- /* @__PURE__ */ jsx47("span", { className: "text-xs text-muted-foreground", children: "to" }),
12022
- /* @__PURE__ */ jsx47(
12023
- BasicInput14,
12375
+ /* @__PURE__ */ jsx48("span", { className: "text-xs text-muted-foreground", children: "to" }),
12376
+ /* @__PURE__ */ jsx48(
12377
+ BasicInput15,
12024
12378
  {
12025
12379
  type: "time",
12026
12380
  className: "h-8 w-28",
@@ -12028,14 +12382,14 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12028
12382
  onChange: (e) => setWindows((prev) => prev.map((x, j) => i === j ? { ...x, to: e.target.value } : x))
12029
12383
  }
12030
12384
  )
12031
- ] }) : /* @__PURE__ */ jsx47("span", { className: "text-xs text-muted-foreground", children: "not taking bookings" })
12385
+ ] }) : /* @__PURE__ */ jsx48("span", { className: "text-xs text-muted-foreground", children: "not taking bookings" })
12032
12386
  ] }, w.weekday))
12033
12387
  ] }),
12034
- /* @__PURE__ */ jsxs43("div", { className: "flex flex-col gap-1.5", children: [
12035
- /* @__PURE__ */ jsx47(Label7, { className: "text-xs font-medium", children: "What to ask the person booking" }),
12036
- askable.length === 0 ? /* @__PURE__ */ jsx47("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__ */ jsx47("div", { className: "flex flex-wrap gap-x-4 gap-y-1.5", children: askable.map((f) => /* @__PURE__ */ jsxs43("label", { className: "flex items-center gap-1.5 text-xs", children: [
12037
- /* @__PURE__ */ jsx47(
12038
- Checkbox6,
12388
+ /* @__PURE__ */ jsxs44("div", { className: "flex flex-col gap-1.5", children: [
12389
+ /* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "What to ask the person booking" }),
12390
+ askable.length === 0 ? /* @__PURE__ */ jsx48("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__ */ jsx48("div", { className: "flex flex-wrap gap-x-4 gap-y-1.5", children: askable.map((f) => /* @__PURE__ */ jsxs44("label", { className: "flex items-center gap-1.5 text-xs", children: [
12391
+ /* @__PURE__ */ jsx48(
12392
+ Checkbox7,
12039
12393
  {
12040
12394
  checked: asked.includes(f.key),
12041
12395
  onCheckedChange: (on) => setAsked((prev) => on ? [...prev, f.key] : prev.filter((k) => k !== f.key))
@@ -12043,11 +12397,11 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12043
12397
  ),
12044
12398
  fieldName(f)
12045
12399
  ] }, f.key)) }),
12046
- /* @__PURE__ */ jsx47("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." })
12400
+ /* @__PURE__ */ jsx48("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." })
12047
12401
  ] }),
12048
- /* @__PURE__ */ jsxs43("label", { className: "flex flex-col gap-1", children: [
12049
- /* @__PURE__ */ jsx47(Label7, { className: "text-xs font-medium", children: "What they see after booking" }),
12050
- /* @__PURE__ */ jsx47(
12402
+ /* @__PURE__ */ jsxs44("label", { className: "flex flex-col gap-1", children: [
12403
+ /* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "What they see after booking" }),
12404
+ /* @__PURE__ */ jsx48(
12051
12405
  BasicTextarea7,
12052
12406
  {
12053
12407
  rows: 2,
@@ -12057,7 +12411,7 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12057
12411
  }
12058
12412
  )
12059
12413
  ] }),
12060
- shown ? /* @__PURE__ */ jsxs43("p", { className: "rounded-md border bg-muted/40 p-2.5 text-xs", children: [
12414
+ shown ? /* @__PURE__ */ jsxs44("p", { className: "rounded-md border bg-muted/40 p-2.5 text-xs", children: [
12061
12415
  "Saved. The page offers ",
12062
12416
  shown.slot_minutes,
12063
12417
  "-minute appointments in ",
@@ -12076,10 +12430,10 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12076
12430
  ).join(", "),
12077
12431
  "."
12078
12432
  ] }) : null,
12079
- url ? /* @__PURE__ */ jsxs43("div", { className: "flex flex-wrap items-center gap-2 rounded-md border p-2.5", children: [
12080
- /* @__PURE__ */ jsx47("span", { className: "min-w-0 flex-1 break-all text-xs", children: url }),
12081
- /* @__PURE__ */ jsx47(
12082
- Button38,
12433
+ url ? /* @__PURE__ */ jsxs44("div", { className: "flex flex-wrap items-center gap-2 rounded-md border p-2.5", children: [
12434
+ /* @__PURE__ */ jsx48("span", { className: "min-w-0 flex-1 break-all text-xs", children: url }),
12435
+ /* @__PURE__ */ jsx48(
12436
+ Button39,
12083
12437
  {
12084
12438
  size: "sm",
12085
12439
  variant: "outline",
@@ -12092,8 +12446,8 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12092
12446
  children: copied ? "Copied" : "Copy link"
12093
12447
  }
12094
12448
  ),
12095
- /* @__PURE__ */ jsx47(
12096
- Button38,
12449
+ /* @__PURE__ */ jsx48(
12450
+ Button39,
12097
12451
  {
12098
12452
  size: "sm",
12099
12453
  disabled: publishing,
@@ -12101,17 +12455,17 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
12101
12455
  children: publishing ? "\u2026" : existing?.published_at && !existing.closed_at ? "Unpublish" : "Publish"
12102
12456
  }
12103
12457
  ),
12104
- /* @__PURE__ */ jsx47("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." })
12458
+ /* @__PURE__ */ jsx48("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." })
12105
12459
  ] }) : null
12106
12460
  ] });
12107
12461
  }
12108
12462
 
12109
12463
  // src/BookingSlots.tsx
12110
- import { useCallback as useCallback29, useEffect as useEffect33, useMemo as useMemo28, useState as useState43 } from "react";
12111
- import { useRecordsClient as useRecordsClient35, useMyLevels as useMyLevels2 } from "@ai-matrx/records/react";
12464
+ import { useCallback as useCallback30, useEffect as useEffect34, useMemo as useMemo29, useState as useState44 } from "react";
12465
+ import { useRecordsClient as useRecordsClient36, useMyLevels as useMyLevels2 } from "@ai-matrx/records/react";
12112
12466
  import { bookingPath as bookingPath2 } from "@ai-matrx/records";
12113
- import { Badge as Badge16, Button as Button39, Skeleton as Skeleton26, cn as cn42 } from "@ai-matrx/design-system";
12114
- import { Fragment as Fragment22, jsx as jsx48, jsxs as jsxs44 } from "react/jsx-runtime";
12467
+ import { Badge as Badge16, Button as Button40, Skeleton as Skeleton27, cn as cn43 } from "@ai-matrx/design-system";
12468
+ import { Fragment as Fragment23, jsx as jsx49, jsxs as jsxs45 } from "react/jsx-runtime";
12115
12469
  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.";
12116
12470
  function bookingSuggestion(tableName2) {
12117
12471
  const subject = tableName2?.trim() ? tableName2.trim() : "appointments";
@@ -12125,15 +12479,15 @@ var STATE_WORDS = {
12125
12479
  full: "Every time you offered is taken."
12126
12480
  };
12127
12481
  function BookingSlots({ tableId, className }) {
12128
- const client = useRecordsClient35();
12482
+ const client = useRecordsClient36();
12129
12483
  const host = useRecordsUi();
12130
- const [pages, setPages] = useState43(null);
12131
- const [error, setError] = useState43(null);
12132
- const [busy, setBusy] = useState43(null);
12133
- const [copied, setCopied] = useState43(null);
12134
- const [shown, setShown] = useState43(null);
12135
- const [building, setBuilding] = useState43(false);
12136
- const load = useCallback29(async () => {
12484
+ const [pages, setPages] = useState44(null);
12485
+ const [error, setError] = useState44(null);
12486
+ const [busy, setBusy] = useState44(null);
12487
+ const [copied, setCopied] = useState44(null);
12488
+ const [shown, setShown] = useState44(null);
12489
+ const [building, setBuilding] = useState44(false);
12490
+ const load = useCallback30(async () => {
12137
12491
  const answered = await client.bookings(tableId ? { table_id: tableId } : {});
12138
12492
  if (!answered.ok) {
12139
12493
  setError(answered.error);
@@ -12143,15 +12497,15 @@ function BookingSlots({ tableId, className }) {
12143
12497
  setError(null);
12144
12498
  setPages(answered.data);
12145
12499
  }, [client, tableId]);
12146
- useEffect33(() => {
12500
+ useEffect34(() => {
12147
12501
  void load();
12148
12502
  }, [load]);
12149
- const subjectIds = useMemo28(
12503
+ const subjectIds = useMemo29(
12150
12504
  () => Array.from(new Set((pages ?? []).map((p) => p.table_id))),
12151
12505
  [pages]
12152
12506
  );
12153
12507
  const levels = useMyLevels2(subjectIds);
12154
- const toggle = useCallback29(
12508
+ const toggle = useCallback30(
12155
12509
  async (page) => {
12156
12510
  setBusy(page.form_id);
12157
12511
  const wanted = page.published_at === null || page.closed_at !== null;
@@ -12165,7 +12519,7 @@ function BookingSlots({ tableId, className }) {
12165
12519
  },
12166
12520
  [client, load]
12167
12521
  );
12168
- const copy = useCallback29(async (url, formId) => {
12522
+ const copy = useCallback30(async (url, formId) => {
12169
12523
  try {
12170
12524
  await navigator.clipboard.writeText(url);
12171
12525
  setCopied(formId);
@@ -12175,18 +12529,18 @@ function BookingSlots({ tableId, className }) {
12175
12529
  setShown(url);
12176
12530
  }
12177
12531
  }, []);
12178
- if (pages === null) return /* @__PURE__ */ jsx48(Skeleton26, { className: cn42("h-32 w-full", className) });
12532
+ if (pages === null) return /* @__PURE__ */ jsx49(Skeleton27, { className: cn43("h-32 w-full", className) });
12179
12533
  if (pages.length === 0 && !tableId && !error && !building) return null;
12180
12534
  const origin = host.publicOrigin ?? (typeof window === "undefined" ? "" : window.location.origin);
12181
- return /* @__PURE__ */ jsxs44("section", { className: cn42("flex flex-col gap-3", className), "data-testid": "booking-slots", children: [
12182
- /* @__PURE__ */ jsxs44("header", { className: "flex items-center gap-2", children: [
12183
- /* @__PURE__ */ jsx48("h3", { className: "text-sm font-medium", children: "Bookings" }),
12184
- /* @__PURE__ */ jsx48("span", { className: "text-xs text-muted-foreground", children: pages.length === 0 ? "none yet" : `${pages.length}` }),
12185
- /* @__PURE__ */ jsx48("div", { className: "flex-1" }),
12186
- tableId && pages.length > 0 ? /* @__PURE__ */ jsx48(Button39, { size: "sm", variant: building ? "secondary" : "ghost", onClick: () => setBuilding((b) => !b), children: building ? "Done building" : "Build a booking page" }) : null
12535
+ return /* @__PURE__ */ jsxs45("section", { className: cn43("flex flex-col gap-3", className), "data-testid": "booking-slots", children: [
12536
+ /* @__PURE__ */ jsxs45("header", { className: "flex items-center gap-2", children: [
12537
+ /* @__PURE__ */ jsx49("h3", { className: "text-sm font-medium", children: "Bookings" }),
12538
+ /* @__PURE__ */ jsx49("span", { className: "text-xs text-muted-foreground", children: pages.length === 0 ? "none yet" : `${pages.length}` }),
12539
+ /* @__PURE__ */ jsx49("div", { className: "flex-1" }),
12540
+ tableId && pages.length > 0 ? /* @__PURE__ */ jsx49(Button40, { size: "sm", variant: building ? "secondary" : "ghost", onClick: () => setBuilding((b) => !b), children: building ? "Done building" : "Build a booking page" }) : null
12187
12541
  ] }),
12188
- error ? /* @__PURE__ */ jsx48(RefusalNotice, { error }) : null,
12189
- building && tableId ? /* @__PURE__ */ jsx48(
12542
+ error ? /* @__PURE__ */ jsx49(RefusalNotice, { error }) : null,
12543
+ building && tableId ? /* @__PURE__ */ jsx49(
12190
12544
  BookingBuilder,
12191
12545
  {
12192
12546
  tableId,
@@ -12196,7 +12550,7 @@ function BookingSlots({ tableId, className }) {
12196
12550
  onClose: () => setBuilding(false)
12197
12551
  }
12198
12552
  ) : null,
12199
- pages.length === 0 && !building ? tableId ? /* @__PURE__ */ jsx48(
12553
+ pages.length === 0 && !building ? tableId ? /* @__PURE__ */ jsx49(
12200
12554
  BuildOrAsk,
12201
12555
  {
12202
12556
  mayBuild: true,
@@ -12212,47 +12566,47 @@ function BookingSlots({ tableId, className }) {
12212
12566
  buildLabel: "Build the booking page",
12213
12567
  children: WHAT_A_BOOKING_PAGE_IS
12214
12568
  }
12215
- ) : /* @__PURE__ */ jsxs44("p", { className: "text-xs text-muted-foreground", children: [
12569
+ ) : /* @__PURE__ */ jsxs45("p", { className: "text-xs text-muted-foreground", children: [
12216
12570
  WHAT_A_BOOKING_PAGE_IS,
12217
12571
  " Open the table the appointments should land in to make one."
12218
12572
  ] }) : null,
12219
- /* @__PURE__ */ jsx48("ul", { className: "flex flex-col gap-2", children: pages.map((page) => {
12573
+ /* @__PURE__ */ jsx49("ul", { className: "flex flex-col gap-2", children: pages.map((page) => {
12220
12574
  const url = `${origin}${bookingPath2(page.form_id)}`;
12221
12575
  const mayOpen = levels.data?.[page.table_id] === "admin";
12222
12576
  const open = page.published_at !== null && page.closed_at === null;
12223
- return /* @__PURE__ */ jsxs44("li", { className: "rounded-md border p-2.5", "data-testid": "booking-page", children: [
12224
- /* @__PURE__ */ jsxs44("div", { className: "flex items-center gap-2", children: [
12225
- /* @__PURE__ */ jsx48("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: page.title ?? page.slug }),
12226
- /* @__PURE__ */ jsx48(Badge16, { variant: page.state === "open" ? "default" : "secondary", children: page.state })
12577
+ return /* @__PURE__ */ jsxs45("li", { className: "rounded-md border p-2.5", "data-testid": "booking-page", children: [
12578
+ /* @__PURE__ */ jsxs45("div", { className: "flex items-center gap-2", children: [
12579
+ /* @__PURE__ */ jsx49("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: page.title ?? page.slug }),
12580
+ /* @__PURE__ */ jsx49(Badge16, { variant: page.state === "open" ? "default" : "secondary", children: page.state })
12227
12581
  ] }),
12228
- /* @__PURE__ */ jsx48("p", { className: "mt-0.5 text-xs text-muted-foreground", children: STATE_WORDS[page.state] ?? page.state }),
12229
- /* @__PURE__ */ jsxs44("p", { className: "mt-1.5 text-xs", children: [
12230
- /* @__PURE__ */ jsx48("span", { className: "font-medium", children: page.upcoming }),
12582
+ /* @__PURE__ */ jsx49("p", { className: "mt-0.5 text-xs text-muted-foreground", children: STATE_WORDS[page.state] ?? page.state }),
12583
+ /* @__PURE__ */ jsxs45("p", { className: "mt-1.5 text-xs", children: [
12584
+ /* @__PURE__ */ jsx49("span", { className: "font-medium", children: page.upcoming }),
12231
12585
  " coming up",
12232
12586
  " \xB7 ",
12233
- /* @__PURE__ */ jsx48("span", { className: "font-medium", children: page.booked }),
12587
+ /* @__PURE__ */ jsx49("span", { className: "font-medium", children: page.booked }),
12234
12588
  " booked in all",
12235
- page.held > 0 ? /* @__PURE__ */ jsxs44(Fragment22, { children: [
12589
+ page.held > 0 ? /* @__PURE__ */ jsxs45(Fragment23, { children: [
12236
12590
  " \xB7 ",
12237
- /* @__PURE__ */ jsx48("span", { className: "font-medium", children: page.held }),
12591
+ /* @__PURE__ */ jsx49("span", { className: "font-medium", children: page.held }),
12238
12592
  " being held right now"
12239
12593
  ] }) : null,
12240
- page.cancelled > 0 ? /* @__PURE__ */ jsxs44(Fragment22, { children: [
12594
+ page.cancelled > 0 ? /* @__PURE__ */ jsxs45(Fragment23, { children: [
12241
12595
  " \xB7 ",
12242
- /* @__PURE__ */ jsx48("span", { className: "font-medium", children: page.cancelled }),
12596
+ /* @__PURE__ */ jsx49("span", { className: "font-medium", children: page.cancelled }),
12243
12597
  " cancelled"
12244
12598
  ] }) : null,
12245
- /* @__PURE__ */ jsxs44("span", { className: "text-muted-foreground", children: [
12599
+ /* @__PURE__ */ jsxs45("span", { className: "text-muted-foreground", children: [
12246
12600
  " \xB7 ",
12247
12601
  page.slot_minutes,
12248
12602
  " minutes each"
12249
12603
  ] })
12250
12604
  ] }),
12251
- /* @__PURE__ */ jsx48("p", { className: "mt-1 text-xs text-muted-foreground", children: nextInWords(page) }),
12252
- /* @__PURE__ */ jsxs44("div", { className: "mt-2 flex flex-wrap items-center gap-1.5", children: [
12253
- /* @__PURE__ */ jsx48(Button39, { size: "sm", variant: "outline", onClick: () => void copy(url, page.form_id), children: copied === page.form_id ? "Copied" : "Copy link" }),
12254
- mayOpen ? /* @__PURE__ */ jsx48(
12255
- Button39,
12605
+ /* @__PURE__ */ jsx49("p", { className: "mt-1 text-xs text-muted-foreground", children: nextInWords(page) }),
12606
+ /* @__PURE__ */ jsxs45("div", { className: "mt-2 flex flex-wrap items-center gap-1.5", children: [
12607
+ /* @__PURE__ */ jsx49(Button40, { size: "sm", variant: "outline", onClick: () => void copy(url, page.form_id), children: copied === page.form_id ? "Copied" : "Copy link" }),
12608
+ mayOpen ? /* @__PURE__ */ jsx49(
12609
+ Button40,
12256
12610
  {
12257
12611
  size: "sm",
12258
12612
  variant: "ghost",
@@ -12262,13 +12616,13 @@ function BookingSlots({ tableId, className }) {
12262
12616
  }
12263
12617
  ) : null
12264
12618
  ] }),
12265
- shown && shown === url ? /* @__PURE__ */ jsxs44("p", { className: "mt-1.5 break-all rounded border border-dashed px-2 py-1 text-xs", children: [
12619
+ shown && shown === url ? /* @__PURE__ */ jsxs45("p", { className: "mt-1.5 break-all rounded border border-dashed px-2 py-1 text-xs", children: [
12266
12620
  "This browser would not let the page copy for you, so here it is to copy by hand: ",
12267
12621
  url
12268
12622
  ] }) : null
12269
12623
  ] }, page.form_id);
12270
12624
  }) }),
12271
- pages.length > 0 && !levels.loading && levels.data && subjectIds.every((id) => levels.data?.[id] !== "admin") ? /* @__PURE__ */ jsx48("p", { className: "text-xs text-muted-foreground", children: NO_ADMIN2 }) : null
12625
+ pages.length > 0 && !levels.loading && levels.data && subjectIds.every((id) => levels.data?.[id] !== "admin") ? /* @__PURE__ */ jsx49("p", { className: "text-xs text-muted-foreground", children: NO_ADMIN2 }) : null
12272
12626
  ] });
12273
12627
  }
12274
12628
  function nextInWords(page) {
@@ -12300,18 +12654,18 @@ function nextInWords(page) {
12300
12654
  }
12301
12655
 
12302
12656
  // src/CaptureSheet.tsx
12303
- import { useCallback as useCallback31, useEffect as useEffect35, useRef as useRef13, useState as useState45 } from "react";
12304
- import { useFields as useFields21, useRecordsClient as useRecordsClient37, useTable as useTable20 } from "@ai-matrx/records/react";
12305
- import { Button as Button41, Input as Input4, Skeleton as Skeleton28, Textarea as Textarea3, cn as cn44 } from "@ai-matrx/design-system";
12657
+ import { useCallback as useCallback32, useEffect as useEffect36, useRef as useRef13, useState as useState46 } from "react";
12658
+ import { useFields as useFields21, useRecordsClient as useRecordsClient38, useTable as useTable20 } from "@ai-matrx/records/react";
12659
+ import { Button as Button42, Input as Input4, Skeleton as Skeleton29, Textarea as Textarea3, cn as cn45 } from "@ai-matrx/design-system";
12306
12660
 
12307
12661
  // src/CaptureRun.tsx
12308
- import { useCallback as useCallback30, useEffect as useEffect34, useMemo as useMemo29, useRef as useRef12, useState as useState44 } from "react";
12662
+ import { useCallback as useCallback31, useEffect as useEffect35, useMemo as useMemo30, useRef as useRef12, useState as useState45 } from "react";
12309
12663
  import {
12310
12664
  openCaptureQueue
12311
12665
  } from "@ai-matrx/records";
12312
- import { useRecordsClient as useRecordsClient36 } from "@ai-matrx/records/react";
12313
- import { Button as Button40, Input as Input3, Skeleton as Skeleton27, Textarea as Textarea2, cn as cn43 } from "@ai-matrx/design-system";
12314
- import { jsx as jsx49, jsxs as jsxs45 } from "react/jsx-runtime";
12666
+ import { useRecordsClient as useRecordsClient37 } from "@ai-matrx/records/react";
12667
+ import { Button as Button41, Input as Input3, Skeleton as Skeleton28, Textarea as Textarea2, cn as cn44 } from "@ai-matrx/design-system";
12668
+ import { jsx as jsx50, jsxs as jsxs46 } from "react/jsx-runtime";
12315
12669
  function controlFor(field) {
12316
12670
  if (!field) return "text";
12317
12671
  const label = `${field.key} ${field.label ?? ""}`.toLowerCase();
@@ -12348,21 +12702,21 @@ function whereWeAre(timeoutMs = 4e3) {
12348
12702
  });
12349
12703
  }
12350
12704
  function CaptureRun({ sheetId, face: given, className }) {
12351
- const client = useRecordsClient36();
12705
+ const client = useRecordsClient37();
12352
12706
  const host = useRecordsUi();
12353
- const [face, setFace] = useState44(given);
12354
- const [loadFailed, setLoadFailed] = useState44(null);
12355
- const [at, setAt] = useState44(0);
12356
- const [answers, setAnswers] = useState44({});
12357
- const [files, setFiles] = useState44({});
12358
- const [missing, setMissing] = useState44(null);
12359
- const [done, setDone] = useState44(null);
12360
- const [counts, setCounts] = useState44({ waiting: 0, sending: 0, refused: 0, landed: 0 });
12361
- const [items, setItems] = useState44([]);
12362
- const [lastSynced, setLastSynced] = useState44(null);
12363
- const [sending, setSending] = useState44(false);
12707
+ const [face, setFace] = useState45(given);
12708
+ const [loadFailed, setLoadFailed] = useState45(null);
12709
+ const [at, setAt] = useState45(0);
12710
+ const [answers, setAnswers] = useState45({});
12711
+ const [files, setFiles] = useState45({});
12712
+ const [missing, setMissing] = useState45(null);
12713
+ const [done, setDone] = useState45(null);
12714
+ const [counts, setCounts] = useState45({ waiting: 0, sending: 0, refused: 0, landed: 0 });
12715
+ const [items, setItems] = useState45([]);
12716
+ const [lastSynced, setLastSynced] = useState45(null);
12717
+ const [sending, setSending] = useState45(false);
12364
12718
  const queueRef = useRef12(null);
12365
- useEffect34(() => {
12719
+ useEffect35(() => {
12366
12720
  const q2 = openCaptureQueue({
12367
12721
  onChange: (c, all) => {
12368
12722
  setCounts(c);
@@ -12400,7 +12754,7 @@ function CaptureRun({ sheetId, face: given, className }) {
12400
12754
  void q2.sync().then(() => void q2.lastSyncedAt().then(setLastSynced));
12401
12755
  return () => q2.dispose();
12402
12756
  }, [client, host]);
12403
- useEffect34(() => {
12757
+ useEffect35(() => {
12404
12758
  if (given !== void 0) return;
12405
12759
  let cancelled = false;
12406
12760
  void client.captureOpen({ sheet_id: sheetId }).then((res) => {
@@ -12412,7 +12766,7 @@ function CaptureRun({ sheetId, face: given, className }) {
12412
12766
  cancelled = true;
12413
12767
  };
12414
12768
  }, [client, given, sheetId]);
12415
- const questions = useMemo29(() => {
12769
+ const questions = useMemo30(() => {
12416
12770
  const asked = face?.presentation?.questions ?? [];
12417
12771
  if (asked.length > 0) return asked;
12418
12772
  return (face?.fields ?? []).map((f) => ({
@@ -12422,11 +12776,11 @@ function CaptureRun({ sheetId, face: given, className }) {
12422
12776
  required: f.required
12423
12777
  }));
12424
12778
  }, [face]);
12425
- const fieldOf = useCallback30(
12779
+ const fieldOf = useCallback31(
12426
12780
  (key) => (face?.fields ?? []).find((f) => f.key === key),
12427
12781
  [face]
12428
12782
  );
12429
- const sync = useCallback30(async () => {
12783
+ const sync = useCallback31(async () => {
12430
12784
  const q2 = queueRef.current;
12431
12785
  if (!q2) return;
12432
12786
  setSending(true);
@@ -12439,7 +12793,7 @@ function CaptureRun({ sheetId, face: given, className }) {
12439
12793
  setSending(false);
12440
12794
  }
12441
12795
  }, []);
12442
- const answered = useCallback30(
12796
+ const answered = useCallback31(
12443
12797
  (key) => {
12444
12798
  if (files[key]) return true;
12445
12799
  const v = answers[key];
@@ -12484,24 +12838,24 @@ function CaptureRun({ sheetId, face: given, className }) {
12484
12838
  if (online) await sync();
12485
12839
  }
12486
12840
  if (loadFailed) {
12487
- return /* @__PURE__ */ jsx49("section", { className: cn43("mx-auto w-full max-w-sm p-4", className), children: /* @__PURE__ */ jsx49("p", { className: "text-sm text-destructive", "data-testid": "capture-refusal", children: loadFailed }) });
12841
+ return /* @__PURE__ */ jsx50("section", { className: cn44("mx-auto w-full max-w-sm p-4", className), children: /* @__PURE__ */ jsx50("p", { className: "text-sm text-destructive", "data-testid": "capture-refusal", children: loadFailed }) });
12488
12842
  }
12489
12843
  if (face === void 0) {
12490
- return /* @__PURE__ */ jsx49(Skeleton27, { className: cn43("mx-auto h-64 w-full max-w-sm", className) });
12844
+ return /* @__PURE__ */ jsx50(Skeleton28, { className: cn44("mx-auto h-64 w-full max-w-sm", className) });
12491
12845
  }
12492
12846
  if (face === null) {
12493
- return /* @__PURE__ */ jsx49("section", { className: cn43("mx-auto w-full max-w-sm p-4", className), children: /* @__PURE__ */ jsx49("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." }) });
12847
+ return /* @__PURE__ */ jsx50("section", { className: cn44("mx-auto w-full max-w-sm p-4", className), children: /* @__PURE__ */ jsx50("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." }) });
12494
12848
  }
12495
12849
  const waiting = counts.waiting + counts.sending;
12496
- const queueLine = /* @__PURE__ */ jsxs45("div", { className: "flex items-center gap-2 text-[11px] text-muted-foreground", "data-testid": "capture-queue-line", children: [
12497
- /* @__PURE__ */ jsx49("span", { className: "tabular-nums", "data-testid": "capture-waiting", children: waiting === 0 ? "Nothing waiting" : `${waiting} waiting` }),
12498
- counts.refused > 0 ? /* @__PURE__ */ jsxs45("span", { className: "text-destructive tabular-nums", "data-testid": "capture-refused", children: [
12850
+ const queueLine = /* @__PURE__ */ jsxs46("div", { className: "flex items-center gap-2 text-[11px] text-muted-foreground", "data-testid": "capture-queue-line", children: [
12851
+ /* @__PURE__ */ jsx50("span", { className: "tabular-nums", "data-testid": "capture-waiting", children: waiting === 0 ? "Nothing waiting" : `${waiting} waiting` }),
12852
+ counts.refused > 0 ? /* @__PURE__ */ jsxs46("span", { className: "text-destructive tabular-nums", "data-testid": "capture-refused", children: [
12499
12853
  counts.refused,
12500
12854
  " to fix"
12501
12855
  ] }) : null,
12502
- /* @__PURE__ */ jsx49("span", { className: "ml-auto", "data-testid": "capture-last-synced", children: lastSynced ? `Last synced ${new Date(lastSynced).toLocaleTimeString()}` : "Not synced yet" }),
12503
- waiting > 0 || counts.refused > 0 ? /* @__PURE__ */ jsx49(
12504
- Button40,
12856
+ /* @__PURE__ */ jsx50("span", { className: "ml-auto", "data-testid": "capture-last-synced", children: lastSynced ? `Last synced ${new Date(lastSynced).toLocaleTimeString()}` : "Not synced yet" }),
12857
+ waiting > 0 || counts.refused > 0 ? /* @__PURE__ */ jsx50(
12858
+ Button41,
12505
12859
  {
12506
12860
  size: "sm",
12507
12861
  variant: "ghost",
@@ -12513,11 +12867,11 @@ function CaptureRun({ sheetId, face: given, className }) {
12513
12867
  }
12514
12868
  ) : null
12515
12869
  ] });
12516
- const queuePanel = items.filter((i) => i.state !== "landed").length > 0 ? /* @__PURE__ */ jsx49("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__ */ jsxs45("li", { className: "flex items-start gap-2 text-[11px]", children: [
12517
- /* @__PURE__ */ jsx49("span", { className: "tabular-nums text-muted-foreground", children: new Date(i.captured_at).toLocaleTimeString() }),
12518
- /* @__PURE__ */ jsx49("span", { className: cn43("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." }),
12519
- i.state === "refused" ? /* @__PURE__ */ jsx49(
12520
- Button40,
12870
+ const queuePanel = items.filter((i) => i.state !== "landed").length > 0 ? /* @__PURE__ */ jsx50("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__ */ jsxs46("li", { className: "flex items-start gap-2 text-[11px]", children: [
12871
+ /* @__PURE__ */ jsx50("span", { className: "tabular-nums text-muted-foreground", children: new Date(i.captured_at).toLocaleTimeString() }),
12872
+ /* @__PURE__ */ jsx50("span", { className: cn44("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." }),
12873
+ i.state === "refused" ? /* @__PURE__ */ jsx50(
12874
+ Button41,
12521
12875
  {
12522
12876
  size: "sm",
12523
12877
  variant: "ghost",
@@ -12528,19 +12882,19 @@ function CaptureRun({ sheetId, face: given, className }) {
12528
12882
  ) : null
12529
12883
  ] }, i.client_key)) }) : null;
12530
12884
  if (!face.may_capture) {
12531
- return /* @__PURE__ */ jsxs45("section", { className: cn43("mx-auto flex w-full max-w-sm flex-col gap-3 p-4", className), children: [
12532
- /* @__PURE__ */ jsx49("h1", { className: "text-lg font-medium", children: face.title }),
12533
- /* @__PURE__ */ jsx49("p", { className: "text-sm", "data-testid": "capture-refusal", children: face.message }),
12885
+ return /* @__PURE__ */ jsxs46("section", { className: cn44("mx-auto flex w-full max-w-sm flex-col gap-3 p-4", className), children: [
12886
+ /* @__PURE__ */ jsx50("h1", { className: "text-lg font-medium", children: face.title }),
12887
+ /* @__PURE__ */ jsx50("p", { className: "text-sm", "data-testid": "capture-refusal", children: face.message }),
12534
12888
  queueLine,
12535
12889
  queuePanel
12536
12890
  ] });
12537
12891
  }
12538
12892
  if (done) {
12539
12893
  const thanks = face.presentation?.thank_you ?? {};
12540
- return /* @__PURE__ */ jsxs45("section", { className: cn43("mx-auto flex w-full max-w-sm flex-col gap-3 p-4", className), children: [
12541
- /* @__PURE__ */ jsx49("h2", { className: "text-lg font-medium", "data-testid": "capture-thankyou", children: thanks.title ?? "Logged" }),
12542
- /* @__PURE__ */ jsx49("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." }),
12543
- /* @__PURE__ */ jsx49(Button40, { className: "h-12", onClick: () => setDone(null), "data-testid": "capture-next", children: "Next one" }),
12894
+ return /* @__PURE__ */ jsxs46("section", { className: cn44("mx-auto flex w-full max-w-sm flex-col gap-3 p-4", className), children: [
12895
+ /* @__PURE__ */ jsx50("h2", { className: "text-lg font-medium", "data-testid": "capture-thankyou", children: thanks.title ?? "Logged" }),
12896
+ /* @__PURE__ */ jsx50("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." }),
12897
+ /* @__PURE__ */ jsx50(Button41, { className: "h-12", onClick: () => setDone(null), "data-testid": "capture-next", children: "Next one" }),
12544
12898
  queueLine,
12545
12899
  queuePanel
12546
12900
  ] });
@@ -12549,14 +12903,14 @@ function CaptureRun({ sheetId, face: given, className }) {
12549
12903
  const field = fieldOf(q.field);
12550
12904
  const control = controlFor(field);
12551
12905
  const last = at >= questions.length - 1;
12552
- return /* @__PURE__ */ jsxs45("section", { className: cn43("mx-auto flex w-full max-w-sm flex-col gap-3 p-4", className), children: [
12553
- /* @__PURE__ */ jsxs45("div", { className: "flex items-center gap-2 text-[11px] text-muted-foreground", children: [
12554
- /* @__PURE__ */ jsxs45("span", { className: "tabular-nums", "data-testid": "capture-progress", children: [
12906
+ return /* @__PURE__ */ jsxs46("section", { className: cn44("mx-auto flex w-full max-w-sm flex-col gap-3 p-4", className), children: [
12907
+ /* @__PURE__ */ jsxs46("div", { className: "flex items-center gap-2 text-[11px] text-muted-foreground", children: [
12908
+ /* @__PURE__ */ jsxs46("span", { className: "tabular-nums", "data-testid": "capture-progress", children: [
12555
12909
  at + 1,
12556
12910
  " of ",
12557
12911
  questions.length
12558
12912
  ] }),
12559
- /* @__PURE__ */ jsx49("div", { className: "h-1 flex-1 overflow-hidden rounded bg-muted", children: /* @__PURE__ */ jsx49(
12913
+ /* @__PURE__ */ jsx50("div", { className: "h-1 flex-1 overflow-hidden rounded bg-muted", children: /* @__PURE__ */ jsx50(
12560
12914
  "div",
12561
12915
  {
12562
12916
  className: "h-full bg-primary transition-[width] duration-200",
@@ -12564,7 +12918,7 @@ function CaptureRun({ sheetId, face: given, className }) {
12564
12918
  }
12565
12919
  ) })
12566
12920
  ] }),
12567
- /* @__PURE__ */ jsxs45(
12921
+ /* @__PURE__ */ jsxs46(
12568
12922
  "label",
12569
12923
  {
12570
12924
  className: "text-xl font-medium leading-snug",
@@ -12572,13 +12926,13 @@ function CaptureRun({ sheetId, face: given, className }) {
12572
12926
  "data-testid": "capture-ask",
12573
12927
  children: [
12574
12928
  q.ask ?? q.field,
12575
- q.required ? /* @__PURE__ */ jsx49("span", { className: "text-muted-foreground", children: " *" }) : null
12929
+ q.required ? /* @__PURE__ */ jsx50("span", { className: "text-muted-foreground", children: " *" }) : null
12576
12930
  ]
12577
12931
  }
12578
12932
  ),
12579
- q.help ? /* @__PURE__ */ jsx49("p", { className: "-mt-1 text-sm text-muted-foreground", children: q.help }) : null,
12580
- control === "photo" || control === "voice" ? !host.upload ? /* @__PURE__ */ jsx49("p", { className: "rounded border border-dashed px-2 py-2 text-xs text-muted-foreground", children: NO_UPLOAD_REASON }) : /* @__PURE__ */ jsxs45("div", { className: "flex flex-col gap-1", children: [
12581
- /* @__PURE__ */ jsx49(
12933
+ q.help ? /* @__PURE__ */ jsx50("p", { className: "-mt-1 text-sm text-muted-foreground", children: q.help }) : null,
12934
+ control === "photo" || control === "voice" ? !host.upload ? /* @__PURE__ */ jsx50("p", { className: "rounded border border-dashed px-2 py-2 text-xs text-muted-foreground", children: NO_UPLOAD_REASON }) : /* @__PURE__ */ jsxs46("div", { className: "flex flex-col gap-1", children: [
12935
+ /* @__PURE__ */ jsx50(
12582
12936
  "input",
12583
12937
  {
12584
12938
  id: `capture-${q.field}`,
@@ -12596,11 +12950,11 @@ function CaptureRun({ sheetId, face: given, className }) {
12596
12950
  }
12597
12951
  }
12598
12952
  ),
12599
- files[q.field] ? /* @__PURE__ */ jsxs45("p", { className: "text-[11px] text-muted-foreground", "data-testid": `capture-have-${q.field}`, children: [
12953
+ files[q.field] ? /* @__PURE__ */ jsxs46("p", { className: "text-[11px] text-muted-foreground", "data-testid": `capture-have-${q.field}`, children: [
12600
12954
  files[q.field].name,
12601
12955
  " is on the phone. It goes up with the capture."
12602
12956
  ] }) : null
12603
- ] }) : control === "number" ? /* @__PURE__ */ jsx49(
12957
+ ] }) : control === "number" ? /* @__PURE__ */ jsx50(
12604
12958
  Input3,
12605
12959
  {
12606
12960
  id: `capture-${q.field}`,
@@ -12616,7 +12970,7 @@ function CaptureRun({ sheetId, face: given, className }) {
12616
12970
  setMissing(null);
12617
12971
  }
12618
12972
  }
12619
- ) : /* @__PURE__ */ jsx49(
12973
+ ) : /* @__PURE__ */ jsx50(
12620
12974
  Textarea2,
12621
12975
  {
12622
12976
  id: `capture-${q.field}`,
@@ -12631,10 +12985,10 @@ function CaptureRun({ sheetId, face: given, className }) {
12631
12985
  }
12632
12986
  }
12633
12987
  ),
12634
- missing ? /* @__PURE__ */ jsx49("p", { className: "text-sm text-destructive", "data-testid": "capture-missing", children: missing }) : null,
12635
- /* @__PURE__ */ jsxs45("div", { className: "flex items-center gap-2", children: [
12636
- at > 0 ? /* @__PURE__ */ jsx49(
12637
- Button40,
12988
+ missing ? /* @__PURE__ */ jsx50("p", { className: "text-sm text-destructive", "data-testid": "capture-missing", children: missing }) : null,
12989
+ /* @__PURE__ */ jsxs46("div", { className: "flex items-center gap-2", children: [
12990
+ at > 0 ? /* @__PURE__ */ jsx50(
12991
+ Button41,
12638
12992
  {
12639
12993
  variant: "ghost",
12640
12994
  className: "h-12 px-3",
@@ -12643,16 +12997,16 @@ function CaptureRun({ sheetId, face: given, className }) {
12643
12997
  children: "Back"
12644
12998
  }
12645
12999
  ) : null,
12646
- last ? /* @__PURE__ */ jsx49(
12647
- Button40,
13000
+ last ? /* @__PURE__ */ jsx50(
13001
+ Button41,
12648
13002
  {
12649
13003
  className: "h-12 flex-1 text-base",
12650
13004
  onClick: () => void capture(),
12651
13005
  "data-testid": "capture-submit",
12652
13006
  children: "Capture"
12653
13007
  }
12654
- ) : /* @__PURE__ */ jsx49(
12655
- Button40,
13008
+ ) : /* @__PURE__ */ jsx50(
13009
+ Button41,
12656
13010
  {
12657
13011
  className: "h-12 flex-1 text-base",
12658
13012
  onClick: () => setAt(at + 1),
@@ -12667,7 +13021,7 @@ function CaptureRun({ sheetId, face: given, className }) {
12667
13021
  }
12668
13022
 
12669
13023
  // src/CaptureSheet.tsx
12670
- import { Fragment as Fragment23, jsx as jsx50, jsxs as jsxs46 } from "react/jsx-runtime";
13024
+ import { Fragment as Fragment24, jsx as jsx51, jsxs as jsxs47 } from "react/jsx-runtime";
12671
13025
  var CAPTURE_MODES = ["reading", "photo", "voice"];
12672
13026
  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.";
12673
13027
  function mintClientKey() {
@@ -12687,8 +13041,8 @@ function CaptureSheet({
12687
13041
  attachmentField,
12688
13042
  className
12689
13043
  }) {
12690
- if (sheetId) return /* @__PURE__ */ jsx50(CaptureRun, { sheetId, className });
12691
- return /* @__PURE__ */ jsx50(
13044
+ if (sheetId) return /* @__PURE__ */ jsx51(CaptureRun, { sheetId, className });
13045
+ return /* @__PURE__ */ jsx51(
12692
13046
  AdHocCaptureSheet,
12693
13047
  {
12694
13048
  tableId,
@@ -12706,21 +13060,21 @@ function AdHocCaptureSheet({
12706
13060
  attachmentField,
12707
13061
  className
12708
13062
  }) {
12709
- const client = useRecordsClient37();
13063
+ const client = useRecordsClient38();
12710
13064
  const host = useRecordsUi();
12711
13065
  const table = useTable20(tableId);
12712
13066
  const fields = useFields21(tableId);
12713
- const [mode, setMode] = useState45("reading");
12714
- const [reading, setReading] = useState45("");
12715
- const [note, setNote] = useState45("");
12716
- const [fileId, setFileId] = useState45(null);
12717
- const [pending, setPending] = useState45(null);
12718
- const [saved, setSaved] = useState45([]);
12719
- const [error, setError] = useState45(null);
12720
- const [uploadError, setUploadError] = useState45(null);
12721
- const [flushing, setFlushing] = useState45(false);
13067
+ const [mode, setMode] = useState46("reading");
13068
+ const [reading, setReading] = useState46("");
13069
+ const [note, setNote] = useState46("");
13070
+ const [fileId, setFileId] = useState46(null);
13071
+ const [pending, setPending] = useState46(null);
13072
+ const [saved, setSaved] = useState46([]);
13073
+ const [error, setError] = useState46(null);
13074
+ const [uploadError, setUploadError] = useState46(null);
13075
+ const [flushing, setFlushing] = useState46(false);
12722
13076
  const queue = useRef13([]);
12723
- const keep = useCallback31(
13077
+ const keep = useCallback32(
12724
13078
  async (next) => {
12725
13079
  queue.current = next;
12726
13080
  setPending(next);
@@ -12728,7 +13082,7 @@ function AdHocCaptureSheet({
12728
13082
  },
12729
13083
  [host]
12730
13084
  );
12731
- useEffect35(() => {
13085
+ useEffect36(() => {
12732
13086
  let cancelled = false;
12733
13087
  void (async () => {
12734
13088
  const held = host.captureQueue ? await host.captureQueue.load() : [];
@@ -12740,7 +13094,7 @@ function AdHocCaptureSheet({
12740
13094
  cancelled = true;
12741
13095
  };
12742
13096
  }, [host]);
12743
- const resolved = useCallback31(() => {
13097
+ const resolved = useCallback32(() => {
12744
13098
  const all = fields.data ?? [];
12745
13099
  return {
12746
13100
  reading: readingField ?? all.find((f) => f.type === "range")?.key ?? null,
@@ -12748,7 +13102,7 @@ function AdHocCaptureSheet({
12748
13102
  attachment: attachmentField ?? all.find((f) => f.format === "file" || f.format === "image")?.key ?? null
12749
13103
  };
12750
13104
  }, [attachmentField, fields.data, noteField, readingField, table.data]);
12751
- const flush = useCallback31(async () => {
13105
+ const flush = useCallback32(async () => {
12752
13106
  if (flushing || queue.current.length === 0) return;
12753
13107
  setFlushing(true);
12754
13108
  const left = [];
@@ -12800,14 +13154,14 @@ function AdHocCaptureSheet({
12800
13154
  await keep([...queue.current, item]);
12801
13155
  await flush();
12802
13156
  }
12803
- if (table.error) return /* @__PURE__ */ jsx50(RefusalNotice, { error: table.error, className });
12804
- if (fields.error) return /* @__PURE__ */ jsx50(RefusalNotice, { error: fields.error, className });
12805
- if (fields.loading || pending === null) return /* @__PURE__ */ jsx50(Skeleton28, { className: cn44("h-64 w-full", className) });
13157
+ if (table.error) return /* @__PURE__ */ jsx51(RefusalNotice, { error: table.error, className });
13158
+ if (fields.error) return /* @__PURE__ */ jsx51(RefusalNotice, { error: fields.error, className });
13159
+ if (fields.loading || pending === null) return /* @__PURE__ */ jsx51(Skeleton29, { className: cn45("h-64 w-full", className) });
12806
13160
  const keys = resolved();
12807
- return /* @__PURE__ */ jsxs46("section", { className: cn44("mx-auto flex w-full max-w-sm flex-col gap-2", className), children: [
12808
- /* @__PURE__ */ jsxs46("header", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
12809
- CAPTURE_MODES.map((m) => /* @__PURE__ */ jsx50(
12810
- Button41,
13161
+ return /* @__PURE__ */ jsxs47("section", { className: cn45("mx-auto flex w-full max-w-sm flex-col gap-2", className), children: [
13162
+ /* @__PURE__ */ jsxs47("header", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
13163
+ CAPTURE_MODES.map((m) => /* @__PURE__ */ jsx51(
13164
+ Button42,
12811
13165
  {
12812
13166
  size: "sm",
12813
13167
  variant: m === mode ? "default" : "ghost",
@@ -12817,10 +13171,10 @@ function AdHocCaptureSheet({
12817
13171
  },
12818
13172
  m
12819
13173
  )),
12820
- /* @__PURE__ */ jsx50("span", { className: "ml-auto tabular-nums", children: pending.length > 0 ? `${pending.length} waiting` : `${saved.length} saved` })
13174
+ /* @__PURE__ */ jsx51("span", { className: "ml-auto tabular-nums", children: pending.length > 0 ? `${pending.length} waiting` : `${saved.length} saved` })
12821
13175
  ] }),
12822
- error ? /* @__PURE__ */ jsx50(RefusalNotice, { error }) : null,
12823
- mode === "reading" ? keys.reading ? /* @__PURE__ */ jsx50(
13176
+ error ? /* @__PURE__ */ jsx51(RefusalNotice, { error }) : null,
13177
+ mode === "reading" ? keys.reading ? /* @__PURE__ */ jsx51(
12824
13178
  Input4,
12825
13179
  {
12826
13180
  "aria-label": "Reading",
@@ -12830,22 +13184,22 @@ function AdHocCaptureSheet({
12830
13184
  value: reading,
12831
13185
  onChange: (e) => setReading(e.target.value)
12832
13186
  }
12833
- ) : /* @__PURE__ */ jsxs46("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: [
13187
+ ) : /* @__PURE__ */ jsxs47("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: [
12834
13188
  table.data?.name ?? "This table",
12835
13189
  " 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 ",
12836
- /* @__PURE__ */ jsx50("code", { children: "readingField" }),
13190
+ /* @__PURE__ */ jsx51("code", { children: "readingField" }),
12837
13191
  "."
12838
13192
  ] }) : null,
12839
- mode !== "reading" ? !host.upload ? /* @__PURE__ */ jsx50("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: NO_UPLOAD_REASON }) : !keys.attachment ? /* @__PURE__ */ jsxs46("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: [
13193
+ mode !== "reading" ? !host.upload ? /* @__PURE__ */ jsx51("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: NO_UPLOAD_REASON }) : !keys.attachment ? /* @__PURE__ */ jsxs47("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: [
12840
13194
  table.data?.name ?? "This table",
12841
13195
  " has no Field a file id can go in, so a ",
12842
13196
  mode,
12843
13197
  " capture would upload the bytes and then have nowhere to record them. Add one, or name it with",
12844
13198
  " ",
12845
- /* @__PURE__ */ jsx50("code", { children: "attachmentField" }),
13199
+ /* @__PURE__ */ jsx51("code", { children: "attachmentField" }),
12846
13200
  "."
12847
- ] }) : /* @__PURE__ */ jsxs46(Fragment23, { children: [
12848
- /* @__PURE__ */ jsx50(
13201
+ ] }) : /* @__PURE__ */ jsxs47(Fragment24, { children: [
13202
+ /* @__PURE__ */ jsx51(
12849
13203
  "input",
12850
13204
  {
12851
13205
  "aria-label": mode === "photo" ? "Take a photo" : "Record a voice note",
@@ -12864,10 +13218,10 @@ function AdHocCaptureSheet({
12864
13218
  }
12865
13219
  }
12866
13220
  ),
12867
- fileId ? /* @__PURE__ */ jsx50("p", { className: "text-[11px] text-muted-foreground", children: "Attached." }) : null,
12868
- uploadError ? /* @__PURE__ */ jsx50("p", { className: "text-xs text-destructive", children: uploadError }) : null
13221
+ fileId ? /* @__PURE__ */ jsx51("p", { className: "text-[11px] text-muted-foreground", children: "Attached." }) : null,
13222
+ uploadError ? /* @__PURE__ */ jsx51("p", { className: "text-xs text-destructive", children: uploadError }) : null
12869
13223
  ] }) : null,
12870
- /* @__PURE__ */ jsx50(
13224
+ /* @__PURE__ */ jsx51(
12871
13225
  Textarea3,
12872
13226
  {
12873
13227
  "aria-label": "Note",
@@ -12878,12 +13232,12 @@ function AdHocCaptureSheet({
12878
13232
  onChange: (e) => setNote(e.target.value)
12879
13233
  }
12880
13234
  ),
12881
- /* @__PURE__ */ jsx50(Button41, { className: "h-12", onClick: () => void capture(), children: "Capture" }),
12882
- pending.length > 0 ? /* @__PURE__ */ jsxs46("div", { className: "flex flex-col gap-1 rounded border p-2", children: [
12883
- /* @__PURE__ */ jsxs46("div", { className: "flex items-center gap-2 text-xs", children: [
12884
- /* @__PURE__ */ jsx50("span", { className: "font-medium", children: "Waiting to send" }),
12885
- /* @__PURE__ */ jsx50(
12886
- Button41,
13235
+ /* @__PURE__ */ jsx51(Button42, { className: "h-12", onClick: () => void capture(), children: "Capture" }),
13236
+ pending.length > 0 ? /* @__PURE__ */ jsxs47("div", { className: "flex flex-col gap-1 rounded border p-2", children: [
13237
+ /* @__PURE__ */ jsxs47("div", { className: "flex items-center gap-2 text-xs", children: [
13238
+ /* @__PURE__ */ jsx51("span", { className: "font-medium", children: "Waiting to send" }),
13239
+ /* @__PURE__ */ jsx51(
13240
+ Button42,
12887
13241
  {
12888
13242
  size: "sm",
12889
13243
  variant: "ghost",
@@ -12894,7 +13248,7 @@ function AdHocCaptureSheet({
12894
13248
  }
12895
13249
  )
12896
13250
  ] }),
12897
- /* @__PURE__ */ jsx50("ul", { className: "flex flex-col gap-0.5", children: pending.map((item) => /* @__PURE__ */ jsxs46("li", { className: "text-[11px] text-muted-foreground", children: [
13251
+ /* @__PURE__ */ jsx51("ul", { className: "flex flex-col gap-0.5", children: pending.map((item) => /* @__PURE__ */ jsxs47("li", { className: "text-[11px] text-muted-foreground", children: [
12898
13252
  new Date(item.capturedAt).toLocaleTimeString(),
12899
13253
  " \xB7 ",
12900
13254
  item.attempts,
@@ -12902,23 +13256,23 @@ function AdHocCaptureSheet({
12902
13256
  item.lastRefusal ? ` \xB7 ${item.lastRefusal}` : ""
12903
13257
  ] }, item.clientKey)) })
12904
13258
  ] }) : null,
12905
- !host.captureQueue ? /* @__PURE__ */ jsx50("p", { className: "rounded border border-dashed px-2 py-1 text-[11px] text-muted-foreground", children: IN_MEMORY_QUEUE_REASON }) : null
13259
+ !host.captureQueue ? /* @__PURE__ */ jsx51("p", { className: "rounded border border-dashed px-2 py-1 text-[11px] text-muted-foreground", children: IN_MEMORY_QUEUE_REASON }) : null
12906
13260
  ] });
12907
13261
  }
12908
13262
 
12909
13263
  // src/PortalShell.tsx
12910
- import { useCallback as useCallback32, useEffect as useEffect36, useState as useState46 } from "react";
12911
- import { useRecordsClient as useRecordsClient38 } from "@ai-matrx/records/react";
12912
- import { Button as Button42, Skeleton as Skeleton29, cn as cn45 } from "@ai-matrx/design-system";
12913
- import { jsx as jsx51, jsxs as jsxs47 } from "react/jsx-runtime";
13264
+ import { useCallback as useCallback33, useEffect as useEffect37, useState as useState47 } from "react";
13265
+ import { useRecordsClient as useRecordsClient39 } from "@ai-matrx/records/react";
13266
+ import { Button as Button43, Skeleton as Skeleton30, cn as cn46 } from "@ai-matrx/design-system";
13267
+ import { jsx as jsx52, jsxs as jsxs48 } from "react/jsx-runtime";
12914
13268
  function PortalShell({ tableId, form, resourceType = "record", className }) {
12915
- const client = useRecordsClient38();
12916
- const [card, setCard] = useState46(null);
12917
- const [reach, setReach] = useState46(null);
12918
- const [error, setError] = useState46(null);
12919
- const [open, setOpen] = useState46(null);
12920
- const [sending, setSending] = useState46(false);
12921
- const load = useCallback32(async () => {
13269
+ const client = useRecordsClient39();
13270
+ const [card, setCard] = useState47(null);
13271
+ const [reach, setReach] = useState47(null);
13272
+ const [error, setError] = useState47(null);
13273
+ const [open, setOpen] = useState47(null);
13274
+ const [sending, setSending] = useState47(false);
13275
+ const load = useCallback33(async () => {
12922
13276
  const who = await client.externalPrincipalCard();
12923
13277
  if (!who.ok) {
12924
13278
  setError(who.error);
@@ -12933,23 +13287,23 @@ function PortalShell({ tableId, form, resourceType = "record", className }) {
12933
13287
  }
12934
13288
  setReach(reached.data.map((row) => row.resource_id));
12935
13289
  }, [client, resourceType]);
12936
- useEffect36(() => {
13290
+ useEffect37(() => {
12937
13291
  void load();
12938
13292
  }, [load]);
12939
13293
  if (error) {
12940
- return /* @__PURE__ */ jsx51(RefusalNotice, { error, className });
13294
+ return /* @__PURE__ */ jsx52(RefusalNotice, { error, className });
12941
13295
  }
12942
- if (!card || reach === null) return /* @__PURE__ */ jsx51(Skeleton29, { className: cn45("h-64 w-full", className) });
13296
+ if (!card || reach === null) return /* @__PURE__ */ jsx52(Skeleton30, { className: cn46("h-64 w-full", className) });
12943
13297
  if (!card.external) {
12944
- return /* @__PURE__ */ jsx51("p", { className: cn45("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." });
13298
+ return /* @__PURE__ */ jsx52("p", { className: cn46("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." });
12945
13299
  }
12946
13300
  if (sending && form) {
12947
- return /* @__PURE__ */ jsxs47("section", { className: cn45("flex min-h-0 flex-col gap-2", className), children: [
12948
- /* @__PURE__ */ jsxs47("header", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
12949
- /* @__PURE__ */ jsx51("span", { className: "font-medium text-foreground", children: form.name }),
12950
- /* @__PURE__ */ jsx51(Button42, { size: "sm", variant: "ghost", className: "ml-auto h-6 px-2 text-[11px]", onClick: () => setSending(false), children: "Back" })
13301
+ return /* @__PURE__ */ jsxs48("section", { className: cn46("flex min-h-0 flex-col gap-2", className), children: [
13302
+ /* @__PURE__ */ jsxs48("header", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
13303
+ /* @__PURE__ */ jsx52("span", { className: "font-medium text-foreground", children: form.name }),
13304
+ /* @__PURE__ */ jsx52(Button43, { size: "sm", variant: "ghost", className: "ml-auto h-6 px-2 text-[11px]", onClick: () => setSending(false), children: "Back" })
12951
13305
  ] }),
12952
- /* @__PURE__ */ jsx51(
13306
+ /* @__PURE__ */ jsx52(
12953
13307
  FormRunner,
12954
13308
  {
12955
13309
  form,
@@ -12962,38 +13316,38 @@ function PortalShell({ tableId, form, resourceType = "record", className }) {
12962
13316
  ] });
12963
13317
  }
12964
13318
  if (open) {
12965
- return /* @__PURE__ */ jsx51("section", { className: cn45("flex min-h-0 flex-col gap-2", className), children: /* @__PURE__ */ jsx51(Peek, { tableId, recordId: open, onClose: () => setOpen(null) }) });
13319
+ return /* @__PURE__ */ jsx52("section", { className: cn46("flex min-h-0 flex-col gap-2", className), children: /* @__PURE__ */ jsx52(Peek, { tableId, recordId: open, onClose: () => setOpen(null) }) });
12966
13320
  }
12967
- return /* @__PURE__ */ jsxs47("section", { className: cn45("flex min-h-0 flex-col gap-2", className), children: [
12968
- /* @__PURE__ */ jsxs47("header", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
12969
- /* @__PURE__ */ jsx51("span", { className: "font-medium text-foreground", children: "Shared with you" }),
12970
- /* @__PURE__ */ jsx51("span", { className: "tabular-nums", children: reach.length }),
12971
- form ? /* @__PURE__ */ jsx51(Button42, { size: "sm", className: "ml-auto h-7 px-2 text-[11px]", onClick: () => setSending(true), children: form.submitLabel ?? form.name }) : null
13321
+ return /* @__PURE__ */ jsxs48("section", { className: cn46("flex min-h-0 flex-col gap-2", className), children: [
13322
+ /* @__PURE__ */ jsxs48("header", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
13323
+ /* @__PURE__ */ jsx52("span", { className: "font-medium text-foreground", children: "Shared with you" }),
13324
+ /* @__PURE__ */ jsx52("span", { className: "tabular-nums", children: reach.length }),
13325
+ form ? /* @__PURE__ */ jsx52(Button43, { size: "sm", className: "ml-auto h-7 px-2 text-[11px]", onClick: () => setSending(true), children: form.submitLabel ?? form.name }) : null
12972
13326
  ] }),
12973
13327
  reach.length === 0 ? (
12974
13328
  // EMPTY, AND IT SAYS WHICH EMPTY. "Nobody has shared anything with you"
12975
13329
  // and "the store would not tell us" are different sentences, and a
12976
13330
  // person acts on them differently.
12977
- /* @__PURE__ */ jsxs47("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: [
13331
+ /* @__PURE__ */ jsxs48("p", { className: "rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", children: [
12978
13332
  "Nothing has been shared with you yet. ",
12979
13333
  card.explanation,
12980
13334
  " 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."
12981
13335
  ] })
12982
- ) : /* @__PURE__ */ jsx51("ul", { className: "flex min-h-0 flex-col gap-1 overflow-y-auto", children: reach.map((id) => /* @__PURE__ */ jsx51("li", { children: /* @__PURE__ */ jsx51(
13336
+ ) : /* @__PURE__ */ jsx52("ul", { className: "flex min-h-0 flex-col gap-1 overflow-y-auto", children: reach.map((id) => /* @__PURE__ */ jsx52("li", { children: /* @__PURE__ */ jsx52(
12983
13337
  "button",
12984
13338
  {
12985
13339
  type: "button",
12986
13340
  className: "w-full truncate rounded border px-2 py-1.5 text-left text-xs hover:bg-muted",
12987
13341
  onClick: () => setOpen(id),
12988
- children: /* @__PURE__ */ jsx51(PortalRow, { tableId, recordId: id })
13342
+ children: /* @__PURE__ */ jsx52(PortalRow, { tableId, recordId: id })
12989
13343
  }
12990
13344
  ) }, id)) })
12991
13345
  ] });
12992
13346
  }
12993
13347
  function PortalRow({ tableId, recordId }) {
12994
- const client = useRecordsClient38();
12995
- const [title, setTitle] = useState46(null);
12996
- useEffect36(() => {
13348
+ const client = useRecordsClient39();
13349
+ const [title, setTitle] = useState47(null);
13350
+ useEffect37(() => {
12997
13351
  let cancelled = false;
12998
13352
  void client.recordRead({ record_id: recordId }).then((answered) => {
12999
13353
  if (cancelled) return;
@@ -13009,22 +13363,22 @@ function PortalRow({ tableId, recordId }) {
13009
13363
  cancelled = true;
13010
13364
  };
13011
13365
  }, [client, recordId, tableId]);
13012
- return /* @__PURE__ */ jsx51("span", { children: title ?? "\u2026" });
13366
+ return /* @__PURE__ */ jsx52("span", { children: title ?? "\u2026" });
13013
13367
  }
13014
13368
 
13015
13369
  // src/PublicViewPage.tsx
13016
- import { useCallback as useCallback33, useEffect as useEffect37, useState as useState47 } from "react";
13017
- import { useRecordsClient as useRecordsClient39 } from "@ai-matrx/records/react";
13018
- import { Skeleton as Skeleton30, cn as cn46 } from "@ai-matrx/design-system";
13019
- import { jsx as jsx52, jsxs as jsxs48 } from "react/jsx-runtime";
13370
+ import { useCallback as useCallback34, useEffect as useEffect38, useState as useState48 } from "react";
13371
+ import { useRecordsClient as useRecordsClient40 } from "@ai-matrx/records/react";
13372
+ import { Skeleton as Skeleton31, cn as cn47 } from "@ai-matrx/design-system";
13373
+ import { jsx as jsx53, jsxs as jsxs49 } from "react/jsx-runtime";
13020
13374
  function PublicViewPage({ slug, className }) {
13021
- const client = useRecordsClient39();
13022
- const [binding, setBinding] = useState47(null);
13023
- const [rows, setRows] = useState47(null);
13024
- const [fields, setFields] = useState47(null);
13025
- const [error, setError] = useState47(null);
13026
- const [gap, setGap] = useState47(null);
13027
- const load = useCallback33(async () => {
13375
+ const client = useRecordsClient40();
13376
+ const [binding, setBinding] = useState48(null);
13377
+ const [rows, setRows] = useState48(null);
13378
+ const [fields, setFields] = useState48(null);
13379
+ const [error, setError] = useState48(null);
13380
+ const [gap, setGap] = useState48(null);
13381
+ const load = useCallback34(async () => {
13028
13382
  const notice = await client.worldPublishGapNotice();
13029
13383
  if (notice.ok) setGap(notice.data);
13030
13384
  const resolved = await client.resolvePublishBinding({ slug });
@@ -13057,48 +13411,48 @@ function PublicViewPage({ slug, className }) {
13057
13411
  }
13058
13412
  setRows([{ id: found.resource_id, document: read.data.document, level: "viewer", hidden: read.data.hidden }]);
13059
13413
  }, [client, slug]);
13060
- useEffect37(() => {
13414
+ useEffect38(() => {
13061
13415
  void load();
13062
13416
  }, [load]);
13063
- if (error) return /* @__PURE__ */ jsx52(RefusalNotice, { error, className });
13064
- if (binding === null) return /* @__PURE__ */ jsx52(Skeleton30, { className: cn46("h-64 w-full", className) });
13417
+ if (error) return /* @__PURE__ */ jsx53(RefusalNotice, { error, className });
13418
+ if (binding === null) return /* @__PURE__ */ jsx53(Skeleton31, { className: cn47("h-64 w-full", className) });
13065
13419
  if (binding === "none") {
13066
- return /* @__PURE__ */ jsxs48("main", { className: cn46("mx-auto max-w-2xl py-16 text-center", className), children: [
13067
- /* @__PURE__ */ jsx52("h1", { className: "text-lg font-medium", children: "Nothing here" }),
13068
- /* @__PURE__ */ jsx52("p", { className: "mt-1 text-sm text-muted-foreground", children: "There is no public page at this address." }),
13069
- gap ? /* @__PURE__ */ jsx52("p", { className: "mt-6 text-xs text-muted-foreground", children: gap }) : null
13420
+ return /* @__PURE__ */ jsxs49("main", { className: cn47("mx-auto max-w-2xl py-16 text-center", className), children: [
13421
+ /* @__PURE__ */ jsx53("h1", { className: "text-lg font-medium", children: "Nothing here" }),
13422
+ /* @__PURE__ */ jsx53("p", { className: "mt-1 text-sm text-muted-foreground", children: "There is no public page at this address." }),
13423
+ gap ? /* @__PURE__ */ jsx53("p", { className: "mt-6 text-xs text-muted-foreground", children: gap }) : null
13070
13424
  ] });
13071
13425
  }
13072
- return /* @__PURE__ */ jsxs48("main", { className: cn46("mx-auto flex max-w-2xl flex-col gap-3 py-8", className), children: [
13073
- /* @__PURE__ */ jsxs48("header", { className: "flex items-baseline gap-2 text-xs text-muted-foreground", children: [
13074
- /* @__PURE__ */ jsx52("span", { className: "font-medium text-foreground", children: binding.namespace ?? "Published" }),
13075
- /* @__PURE__ */ jsx52("span", { children: binding.render_mode === "list" ? `${rows?.length ?? 0} items` : "Shared publicly" })
13426
+ return /* @__PURE__ */ jsxs49("main", { className: cn47("mx-auto flex max-w-2xl flex-col gap-3 py-8", className), children: [
13427
+ /* @__PURE__ */ jsxs49("header", { className: "flex items-baseline gap-2 text-xs text-muted-foreground", children: [
13428
+ /* @__PURE__ */ jsx53("span", { className: "font-medium text-foreground", children: binding.namespace ?? "Published" }),
13429
+ /* @__PURE__ */ jsx53("span", { children: binding.render_mode === "list" ? `${rows?.length ?? 0} items` : "Shared publicly" })
13076
13430
  ] }),
13077
- rows === null ? /* @__PURE__ */ jsx52(Skeleton30, { className: "h-40 w-full" }) : rows.length === 0 ? /* @__PURE__ */ jsx52("p", { className: "text-sm text-muted-foreground", children: "This page has nothing on it yet." }) : /* @__PURE__ */ jsx52("ol", { className: "flex flex-col gap-2", children: rows.map((row) => /* @__PURE__ */ jsx52("li", { className: "rounded border p-3", children: /* @__PURE__ */ jsx52(PublicRow, { row, fields }) }, row.id)) }),
13078
- /* @__PURE__ */ jsx52("footer", { className: "mt-4 border-t pt-3 text-xs text-muted-foreground", children: binding.notice || gap || "Nothing was scanned before this was listed." })
13431
+ rows === null ? /* @__PURE__ */ jsx53(Skeleton31, { className: "h-40 w-full" }) : rows.length === 0 ? /* @__PURE__ */ jsx53("p", { className: "text-sm text-muted-foreground", children: "This page has nothing on it yet." }) : /* @__PURE__ */ jsx53("ol", { className: "flex flex-col gap-2", children: rows.map((row) => /* @__PURE__ */ jsx53("li", { className: "rounded border p-3", children: /* @__PURE__ */ jsx53(PublicRow, { row, fields }) }, row.id)) }),
13432
+ /* @__PURE__ */ jsx53("footer", { className: "mt-4 border-t pt-3 text-xs text-muted-foreground", children: binding.notice || gap || "Nothing was scanned before this was listed." })
13079
13433
  ] });
13080
13434
  }
13081
13435
  function PublicRow({ row, fields }) {
13082
13436
  const document2 = row.document ?? {};
13083
13437
  if (!fields) {
13084
13438
  const first = Object.entries(document2).filter(([key]) => !key.startsWith("_"));
13085
- return /* @__PURE__ */ jsx52("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 text-sm", children: first.map(([key, value]) => /* @__PURE__ */ jsxs48("div", { className: "contents", children: [
13086
- /* @__PURE__ */ jsx52("dt", { className: "text-xs text-muted-foreground", children: key }),
13087
- /* @__PURE__ */ jsx52("dd", { className: "text-sm", children: String(value ?? "") })
13439
+ return /* @__PURE__ */ jsx53("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 text-sm", children: first.map(([key, value]) => /* @__PURE__ */ jsxs49("div", { className: "contents", children: [
13440
+ /* @__PURE__ */ jsx53("dt", { className: "text-xs text-muted-foreground", children: key }),
13441
+ /* @__PURE__ */ jsx53("dd", { className: "text-sm", children: String(value ?? "") })
13088
13442
  ] }, key)) });
13089
13443
  }
13090
- return /* @__PURE__ */ jsx52("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1", children: fields.map((field) => /* @__PURE__ */ jsxs48("div", { className: "contents", children: [
13091
- /* @__PURE__ */ jsx52("dt", { className: "text-xs text-muted-foreground", children: field.label }),
13092
- /* @__PURE__ */ jsx52("dd", { className: "text-sm", children: /* @__PURE__ */ jsx52(RecordValue, { field, value: document2[field.key], document: row.document }) })
13444
+ return /* @__PURE__ */ jsx53("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1", children: fields.map((field) => /* @__PURE__ */ jsxs49("div", { className: "contents", children: [
13445
+ /* @__PURE__ */ jsx53("dt", { className: "text-xs text-muted-foreground", children: field.label }),
13446
+ /* @__PURE__ */ jsx53("dd", { className: "text-sm", children: /* @__PURE__ */ jsx53(RecordValue, { field, value: document2[field.key], document: row.document }) })
13093
13447
  ] }, field.key)) });
13094
13448
  }
13095
13449
 
13096
13450
  // src/EmbedFrame.tsx
13097
- import { useCallback as useCallback34, useEffect as useEffect38, useState as useState48 } from "react";
13098
- import { useRecordsClient as useRecordsClient40 } from "@ai-matrx/records/react";
13099
- import { Button as Button43, Input as Input5, Skeleton as Skeleton31, Textarea as Textarea4, cn as cn47 } from "@ai-matrx/design-system";
13451
+ import { useCallback as useCallback35, useEffect as useEffect39, useState as useState49 } from "react";
13452
+ import { useRecordsClient as useRecordsClient41 } from "@ai-matrx/records/react";
13453
+ import { Button as Button44, Input as Input5, Skeleton as Skeleton32, Textarea as Textarea4, cn as cn48 } from "@ai-matrx/design-system";
13100
13454
  import { useTable as useTable21 } from "@ai-matrx/records/react";
13101
- import { Fragment as Fragment24, jsx as jsx53, jsxs as jsxs49 } from "react/jsx-runtime";
13455
+ import { Fragment as Fragment25, jsx as jsx54, jsxs as jsxs50 } from "react/jsx-runtime";
13102
13456
  function EmbedFrame({
13103
13457
  tableId,
13104
13458
  formId,
@@ -13107,18 +13461,18 @@ function EmbedFrame({
13107
13461
  embedUrl,
13108
13462
  className
13109
13463
  }) {
13110
- const client = useRecordsClient40();
13464
+ const client = useRecordsClient41();
13111
13465
  const host = useRecordsUi();
13112
13466
  const table = useTable21(tableId);
13113
13467
  const rights = useTableRights(table.data);
13114
- const [origins, setOrigins] = useState48("");
13115
- const [secret, setSecret] = useState48(null);
13116
- const [tokenId, setTokenId] = useState48(null);
13117
- const [error, setError] = useState48(null);
13118
- const [busy, setBusy] = useState48(false);
13468
+ const [origins, setOrigins] = useState49("");
13469
+ const [secret, setSecret] = useState49(null);
13470
+ const [tokenId, setTokenId] = useState49(null);
13471
+ const [error, setError] = useState49(null);
13472
+ const [busy, setBusy] = useState49(false);
13119
13473
  const mode = formId ? "write" : "read";
13120
13474
  const parsed = origins.split(/[\s,]+/).map((o) => o.trim()).filter((o) => o.length > 0);
13121
- const issue = useCallback34(async () => {
13475
+ const issue = useCallback35(async () => {
13122
13476
  setBusy(true);
13123
13477
  setError(null);
13124
13478
  const minted = await client.anonTokenIssue({
@@ -13137,7 +13491,7 @@ function EmbedFrame({
13137
13491
  setTokenId(minted.data.token_id);
13138
13492
  host.notify?.success("Embed token issued. Copy it now \u2014 it is never shown again.");
13139
13493
  }, [client, formId, host, mode, parsed, recordId, savedViewId]);
13140
- const revoke = useCallback34(async () => {
13494
+ const revoke = useCallback35(async () => {
13141
13495
  if (!tokenId) return;
13142
13496
  setBusy(true);
13143
13497
  const done = await client.anonTokenRevoke({ token_id: tokenId });
@@ -13149,24 +13503,24 @@ function EmbedFrame({
13149
13503
  setSecret(null);
13150
13504
  setTokenId(null);
13151
13505
  }, [client, tokenId]);
13152
- if (table.error) return /* @__PURE__ */ jsx53(RefusalNotice, { error: table.error, className });
13153
- if (table.loading) return /* @__PURE__ */ jsx53(Skeleton31, { className: cn47("h-48 w-full", className) });
13506
+ if (table.error) return /* @__PURE__ */ jsx54(RefusalNotice, { error: table.error, className });
13507
+ if (table.loading) return /* @__PURE__ */ jsx54(Skeleton32, { className: cn48("h-48 w-full", className) });
13154
13508
  if (!rights.admin) {
13155
- return /* @__PURE__ */ jsxs49("p", { className: cn47("rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", className), children: [
13509
+ return /* @__PURE__ */ jsxs50("p", { className: cn48("rounded border border-dashed px-2 py-1 text-xs text-muted-foreground", className), children: [
13156
13510
  rights.why("structure"),
13157
13511
  " 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."
13158
13512
  ] });
13159
13513
  }
13160
13514
  const snippet = secret ? `<iframe src="${embedUrl}#t=${secret}" style="width:100%;height:640px;border:0" loading="lazy"></iframe>` : null;
13161
- return /* @__PURE__ */ jsxs49("section", { className: cn47("flex min-h-0 flex-col gap-2", className), children: [
13162
- /* @__PURE__ */ jsxs49("header", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
13163
- /* @__PURE__ */ jsx53("span", { className: "font-medium text-foreground", children: "Embed" }),
13164
- /* @__PURE__ */ jsx53("span", { children: mode === "write" ? "a form people can send" : "a read-only view" })
13515
+ return /* @__PURE__ */ jsxs50("section", { className: cn48("flex min-h-0 flex-col gap-2", className), children: [
13516
+ /* @__PURE__ */ jsxs50("header", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
13517
+ /* @__PURE__ */ jsx54("span", { className: "font-medium text-foreground", children: "Embed" }),
13518
+ /* @__PURE__ */ jsx54("span", { children: mode === "write" ? "a form people can send" : "a read-only view" })
13165
13519
  ] }),
13166
- error ? /* @__PURE__ */ jsx53(RefusalNotice, { error }) : null,
13167
- /* @__PURE__ */ jsxs49("label", { className: "flex flex-col gap-1 text-xs", children: [
13168
- /* @__PURE__ */ jsx53("span", { className: "text-muted-foreground", children: "Sites this embed works on" }),
13169
- /* @__PURE__ */ jsx53(
13520
+ error ? /* @__PURE__ */ jsx54(RefusalNotice, { error }) : null,
13521
+ /* @__PURE__ */ jsxs50("label", { className: "flex flex-col gap-1 text-xs", children: [
13522
+ /* @__PURE__ */ jsx54("span", { className: "text-muted-foreground", children: "Sites this embed works on" }),
13523
+ /* @__PURE__ */ jsx54(
13170
13524
  Input5,
13171
13525
  {
13172
13526
  "aria-label": "Allowed origins",
@@ -13176,18 +13530,18 @@ function EmbedFrame({
13176
13530
  onChange: (e) => setOrigins(e.target.value)
13177
13531
  }
13178
13532
  ),
13179
- /* @__PURE__ */ jsxs49("span", { className: "text-[11px] text-muted-foreground", children: [
13533
+ /* @__PURE__ */ jsxs50("span", { className: "text-[11px] text-muted-foreground", children: [
13180
13534
  `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 `,
13181
- /* @__PURE__ */ jsx53("code", { children: "example.com.evil.test" }),
13535
+ /* @__PURE__ */ jsx54("code", { children: "example.com.evil.test" }),
13182
13536
  " will not pass."
13183
13537
  ] })
13184
13538
  ] }),
13185
- !secret ? /* @__PURE__ */ jsx53(Button43, { size: "sm", className: "self-start", disabled: busy || parsed.length === 0, onClick: () => void issue(), children: busy ? "Issuing\u2026" : "Issue embed" }) : /* @__PURE__ */ jsxs49(Fragment24, { children: [
13186
- /* @__PURE__ */ jsx53("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." }),
13187
- /* @__PURE__ */ jsx53(Textarea4, { "aria-label": "Embed snippet", readOnly: true, rows: 3, className: "font-mono text-[11px]", value: snippet ?? "" }),
13188
- /* @__PURE__ */ jsxs49("div", { className: "flex gap-2", children: [
13189
- /* @__PURE__ */ jsx53(
13190
- Button43,
13539
+ !secret ? /* @__PURE__ */ jsx54(Button44, { size: "sm", className: "self-start", disabled: busy || parsed.length === 0, onClick: () => void issue(), children: busy ? "Issuing\u2026" : "Issue embed" }) : /* @__PURE__ */ jsxs50(Fragment25, { children: [
13540
+ /* @__PURE__ */ jsx54("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." }),
13541
+ /* @__PURE__ */ jsx54(Textarea4, { "aria-label": "Embed snippet", readOnly: true, rows: 3, className: "font-mono text-[11px]", value: snippet ?? "" }),
13542
+ /* @__PURE__ */ jsxs50("div", { className: "flex gap-2", children: [
13543
+ /* @__PURE__ */ jsx54(
13544
+ Button44,
13191
13545
  {
13192
13546
  size: "sm",
13193
13547
  variant: "outline",
@@ -13195,19 +13549,19 @@ function EmbedFrame({
13195
13549
  children: "Copy"
13196
13550
  }
13197
13551
  ),
13198
- /* @__PURE__ */ jsx53(Button43, { size: "sm", variant: "ghost", disabled: busy, onClick: () => void revoke(), children: "Revoke" })
13552
+ /* @__PURE__ */ jsx54(Button44, { size: "sm", variant: "ghost", disabled: busy, onClick: () => void revoke(), children: "Revoke" })
13199
13553
  ] })
13200
13554
  ] })
13201
13555
  ] });
13202
13556
  }
13203
13557
  function useEmbedHandshake(args) {
13204
- const client = useRecordsClient40();
13205
- const [binding, setBinding] = useState48(null);
13206
- const [error, setError] = useState48(null);
13207
- const [loading, setLoading] = useState48(true);
13558
+ const client = useRecordsClient41();
13559
+ const [binding, setBinding] = useState49(null);
13560
+ const [error, setError] = useState49(null);
13561
+ const [loading, setLoading] = useState49(true);
13208
13562
  const origin = args.origin ?? (typeof location === "undefined" ? "" : location.origin);
13209
13563
  const { secret, requiredMode } = args;
13210
- useEffect38(() => {
13564
+ useEffect39(() => {
13211
13565
  let cancelled = false;
13212
13566
  setLoading(true);
13213
13567
  setError(null);
@@ -13230,7 +13584,7 @@ function useEmbedHandshake(args) {
13230
13584
 
13231
13585
  // src/RecordsMount.tsx
13232
13586
  import { RecordsProvider } from "@ai-matrx/records/react";
13233
- import { jsx as jsx54 } from "react/jsx-runtime";
13587
+ import { jsx as jsx55 } from "react/jsx-runtime";
13234
13588
  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.";
13235
13589
  function storeDecidesRights(_table) {
13236
13590
  return NO_RIGHTS;
@@ -13243,7 +13597,7 @@ function RecordsMount({
13243
13597
  }) {
13244
13598
  const bound = { ...host ?? {} };
13245
13599
  void letTheStoreDecideRights;
13246
- return /* @__PURE__ */ jsx54(RecordsProvider, { config, children: /* @__PURE__ */ jsx54(RecordsUiProvider, { value: bound, children: /* @__PURE__ */ jsx54(RecordLabelProvider, { children }) }) });
13600
+ return /* @__PURE__ */ jsx55(RecordsProvider, { config, children: /* @__PURE__ */ jsx55(RecordsUiProvider, { value: bound, children: /* @__PURE__ */ jsx55(RecordLabelProvider, { children }) }) });
13247
13601
  }
13248
13602
  function personActor(userId) {
13249
13603
  return userId ? { actor: "user", user_id: userId } : { actor: "user" };
@@ -13262,9 +13616,9 @@ function recordsDataSource(client, fallbackSchema = "custom") {
13262
13616
  }
13263
13617
 
13264
13618
  // src/TablesHome.tsx
13265
- import { useCallback as useCallback35, useEffect as useEffect39, useState as useState49 } from "react";
13266
- import { useRecordsClient as useRecordsClient41, useTables as useTables3 } from "@ai-matrx/records/react";
13267
- import { BasicInput as BasicInput15, Button as Button44, Skeleton as Skeleton32, cn as cn48 } from "@ai-matrx/design-system";
13619
+ import { useCallback as useCallback36, useEffect as useEffect40, useState as useState50 } from "react";
13620
+ import { useRecordsClient as useRecordsClient42, useTables as useTables3 } from "@ai-matrx/records/react";
13621
+ import { BasicInput as BasicInput16, Button as Button45, Skeleton as Skeleton33, cn as cn49 } from "@ai-matrx/design-system";
13268
13622
 
13269
13623
  // src/createTable.ts
13270
13624
  function tokenFor(name) {
@@ -13374,7 +13728,7 @@ function declaredType(field) {
13374
13728
  }
13375
13729
 
13376
13730
  // src/TablesHome.tsx
13377
- import { Fragment as Fragment25, jsx as jsx55, jsxs as jsxs50 } from "react/jsx-runtime";
13731
+ import { Fragment as Fragment26, jsx as jsx56, jsxs as jsxs51 } from "react/jsx-runtime";
13378
13732
  var TABLE_LANES = ["mine", "organization", "system", "community", "app"];
13379
13733
  var LANE_TITLE = {
13380
13734
  mine: "Mine",
@@ -13399,15 +13753,15 @@ function laneFor(table) {
13399
13753
  return "organization";
13400
13754
  }
13401
13755
  function TablesHome({ onOpenTable, className }) {
13402
- const client = useRecordsClient41();
13756
+ const client = useRecordsClient42();
13403
13757
  const tables = useTables3();
13404
- const [creating, setCreating] = useState49(false);
13405
- const [name, setName] = useState49("");
13406
- const [busy, setBusy] = useState49(false);
13407
- const [error, setError] = useState49(null);
13408
- const [importInto, setImportInto] = useState49(null);
13409
- const [boards, setBoards] = useState49(null);
13410
- useEffect39(() => {
13758
+ const [creating, setCreating] = useState50(false);
13759
+ const [name, setName] = useState50("");
13760
+ const [busy, setBusy] = useState50(false);
13761
+ const [error, setError] = useState50(null);
13762
+ const [importInto, setImportInto] = useState50(null);
13763
+ const [boards, setBoards] = useState50(null);
13764
+ useEffect40(() => {
13411
13765
  let cancelled = false;
13412
13766
  void client.dashboards({}).then((result) => {
13413
13767
  if (cancelled) return;
@@ -13417,7 +13771,7 @@ function TablesHome({ onOpenTable, className }) {
13417
13771
  cancelled = true;
13418
13772
  };
13419
13773
  }, [client]);
13420
- const create = useCallback35(
13774
+ const create = useCallback36(
13421
13775
  async (mode) => {
13422
13776
  const trimmed = name.trim();
13423
13777
  if (!trimmed) return;
@@ -13437,10 +13791,10 @@ function TablesHome({ onOpenTable, className }) {
13437
13791
  },
13438
13792
  [client, name, onOpenTable, tables]
13439
13793
  );
13440
- return /* @__PURE__ */ jsxs50("div", { className: cn48("flex min-h-0 flex-col gap-4", className), children: [
13441
- /* @__PURE__ */ jsx55("div", { className: "flex items-center gap-2", children: creating ? /* @__PURE__ */ jsxs50(Fragment25, { children: [
13442
- /* @__PURE__ */ jsx55(
13443
- BasicInput15,
13794
+ return /* @__PURE__ */ jsxs51("div", { className: cn49("flex min-h-0 flex-col gap-4", className), children: [
13795
+ /* @__PURE__ */ jsx56("div", { className: "flex items-center gap-2", children: creating ? /* @__PURE__ */ jsxs51(Fragment26, { children: [
13796
+ /* @__PURE__ */ jsx56(
13797
+ BasicInput16,
13444
13798
  {
13445
13799
  autoFocus: true,
13446
13800
  value: name,
@@ -13453,9 +13807,9 @@ function TablesHome({ onOpenTable, className }) {
13453
13807
  className: "h-8 max-w-xs"
13454
13808
  }
13455
13809
  ),
13456
- /* @__PURE__ */ jsx55(Button44, { size: "sm", disabled: busy || name.trim().length === 0, onClick: () => void create("open"), children: busy ? "Declaring\u2026" : "Create" }),
13457
- /* @__PURE__ */ jsx55(
13458
- Button44,
13810
+ /* @__PURE__ */ jsx56(Button45, { size: "sm", disabled: busy || name.trim().length === 0, onClick: () => void create("open"), children: busy ? "Declaring\u2026" : "Create" }),
13811
+ /* @__PURE__ */ jsx56(
13812
+ Button45,
13459
13813
  {
13460
13814
  size: "sm",
13461
13815
  variant: "outline",
@@ -13464,37 +13818,37 @@ function TablesHome({ onOpenTable, className }) {
13464
13818
  children: "Create and import a file"
13465
13819
  }
13466
13820
  ),
13467
- /* @__PURE__ */ jsx55(Button44, { size: "sm", variant: "ghost", onClick: () => setCreating(false), children: "Cancel" })
13468
- ] }) : /* @__PURE__ */ jsx55(Button44, { size: "sm", onClick: () => setCreating(true), children: "New table" }) }),
13469
- error ? /* @__PURE__ */ jsx55(RefusalNotice, { error }) : null,
13470
- importInto ? /* @__PURE__ */ jsxs50("div", { className: "rounded-md border p-3", children: [
13471
- /* @__PURE__ */ jsx55(ImportWizard, { tableId: importInto, onDone: () => setImportInto(null) }),
13472
- /* @__PURE__ */ jsx55(Button44, { size: "sm", variant: "ghost", className: "mt-2", onClick: () => onOpenTable?.(importInto), children: "Open the table" })
13821
+ /* @__PURE__ */ jsx56(Button45, { size: "sm", variant: "ghost", onClick: () => setCreating(false), children: "Cancel" })
13822
+ ] }) : /* @__PURE__ */ jsx56(Button45, { size: "sm", onClick: () => setCreating(true), children: "New table" }) }),
13823
+ error ? /* @__PURE__ */ jsx56(RefusalNotice, { error }) : null,
13824
+ importInto ? /* @__PURE__ */ jsxs51("div", { className: "rounded-md border p-3", children: [
13825
+ /* @__PURE__ */ jsx56(ImportWizard, { tableId: importInto, onDone: () => setImportInto(null) }),
13826
+ /* @__PURE__ */ jsx56(Button45, { size: "sm", variant: "ghost", className: "mt-2", onClick: () => onOpenTable?.(importInto), children: "Open the table" })
13473
13827
  ] }) : null,
13474
- tables.error ? /* @__PURE__ */ jsx55(RefusalNotice, { error: tables.error }) : null,
13475
- tables.loading && !tables.data ? /* @__PURE__ */ jsxs50("div", { className: "space-y-2", children: [
13476
- /* @__PURE__ */ jsx55(Skeleton32, { className: "h-6 w-40" }),
13477
- /* @__PURE__ */ jsx55(Skeleton32, { className: "h-16 w-full" })
13828
+ tables.error ? /* @__PURE__ */ jsx56(RefusalNotice, { error: tables.error }) : null,
13829
+ tables.loading && !tables.data ? /* @__PURE__ */ jsxs51("div", { className: "space-y-2", children: [
13830
+ /* @__PURE__ */ jsx56(Skeleton33, { className: "h-6 w-40" }),
13831
+ /* @__PURE__ */ jsx56(Skeleton33, { className: "h-16 w-full" })
13478
13832
  ] }) : null,
13479
- /* @__PURE__ */ jsx55(BookingSlots, {}),
13480
- boards && boards.length > 0 ? /* @__PURE__ */ jsxs50("section", { className: "space-y-1.5", children: [
13481
- /* @__PURE__ */ jsxs50("div", { className: "flex items-baseline gap-2", children: [
13482
- /* @__PURE__ */ jsx55("h2", { className: "text-sm font-medium", children: "Dashboards" }),
13483
- /* @__PURE__ */ jsx55("span", { className: "text-xs opacity-60", children: boards.length })
13833
+ /* @__PURE__ */ jsx56(BookingSlots, {}),
13834
+ boards && boards.length > 0 ? /* @__PURE__ */ jsxs51("section", { className: "space-y-1.5", children: [
13835
+ /* @__PURE__ */ jsxs51("div", { className: "flex items-baseline gap-2", children: [
13836
+ /* @__PURE__ */ jsx56("h2", { className: "text-sm font-medium", children: "Dashboards" }),
13837
+ /* @__PURE__ */ jsx56("span", { className: "text-xs opacity-60", children: boards.length })
13484
13838
  ] }),
13485
- /* @__PURE__ */ jsx55("ul", { className: "grid gap-1.5 sm:grid-cols-2 lg:grid-cols-3", children: boards.map((board) => /* @__PURE__ */ jsx55("li", { children: /* @__PURE__ */ jsxs50(
13839
+ /* @__PURE__ */ jsx56("ul", { className: "grid gap-1.5 sm:grid-cols-2 lg:grid-cols-3", children: boards.map((board) => /* @__PURE__ */ jsx56("li", { children: /* @__PURE__ */ jsxs51(
13486
13840
  "button",
13487
13841
  {
13488
13842
  type: "button",
13489
13843
  disabled: !board.table_id,
13490
13844
  onClick: () => board.table_id ? onOpenTable?.(board.table_id, board.dashboard_id) : void 0,
13491
- className: cn48(
13845
+ className: cn49(
13492
13846
  "w-full rounded-md border px-3 py-2 text-left transition-colors",
13493
13847
  onOpenTable && board.table_id ? "hover:bg-accent" : "cursor-default"
13494
13848
  ),
13495
13849
  children: [
13496
- /* @__PURE__ */ jsx55("span", { className: "block truncate text-sm", children: board.name }),
13497
- /* @__PURE__ */ jsxs50("span", { className: "block truncate text-xs opacity-60", children: [
13850
+ /* @__PURE__ */ jsx56("span", { className: "block truncate text-sm", children: board.name }),
13851
+ /* @__PURE__ */ jsxs51("span", { className: "block truncate text-xs opacity-60", children: [
13498
13852
  board.block_count,
13499
13853
  " block",
13500
13854
  board.block_count === 1 ? "" : "s",
@@ -13510,23 +13864,23 @@ function TablesHome({ onOpenTable, className }) {
13510
13864
  ] }) : null,
13511
13865
  tables.data ? TABLE_LANES.map((lane) => {
13512
13866
  const rows = tables.data.filter((t) => laneFor(t) === lane);
13513
- return /* @__PURE__ */ jsxs50("section", { className: "space-y-1.5", children: [
13514
- /* @__PURE__ */ jsxs50("div", { className: "flex items-baseline gap-2", children: [
13515
- /* @__PURE__ */ jsx55("h2", { className: "text-sm font-medium", children: LANE_TITLE[lane] }),
13516
- /* @__PURE__ */ jsx55("span", { className: "text-xs opacity-60", children: rows.length })
13867
+ return /* @__PURE__ */ jsxs51("section", { className: "space-y-1.5", children: [
13868
+ /* @__PURE__ */ jsxs51("div", { className: "flex items-baseline gap-2", children: [
13869
+ /* @__PURE__ */ jsx56("h2", { className: "text-sm font-medium", children: LANE_TITLE[lane] }),
13870
+ /* @__PURE__ */ jsx56("span", { className: "text-xs opacity-60", children: rows.length })
13517
13871
  ] }),
13518
- rows.length === 0 ? /* @__PURE__ */ jsx55("p", { className: "text-xs opacity-70", children: LANE_EMPTY[lane] }) : /* @__PURE__ */ jsx55("ul", { className: "grid gap-1.5 sm:grid-cols-2 lg:grid-cols-3", children: rows.map((table) => /* @__PURE__ */ jsx55("li", { children: /* @__PURE__ */ jsxs50(
13872
+ rows.length === 0 ? /* @__PURE__ */ jsx56("p", { className: "text-xs opacity-70", children: LANE_EMPTY[lane] }) : /* @__PURE__ */ jsx56("ul", { className: "grid gap-1.5 sm:grid-cols-2 lg:grid-cols-3", children: rows.map((table) => /* @__PURE__ */ jsx56("li", { children: /* @__PURE__ */ jsxs51(
13519
13873
  "button",
13520
13874
  {
13521
13875
  type: "button",
13522
13876
  onClick: () => onOpenTable?.(table.id),
13523
- className: cn48(
13877
+ className: cn49(
13524
13878
  "w-full rounded-md border px-3 py-2 text-left transition-colors",
13525
13879
  onOpenTable ? "hover:bg-accent" : "cursor-default"
13526
13880
  ),
13527
13881
  children: [
13528
- /* @__PURE__ */ jsx55("span", { className: "block truncate text-sm", children: tableName(table) }),
13529
- /* @__PURE__ */ jsxs50("span", { className: "block truncate text-xs opacity-60", children: [
13882
+ /* @__PURE__ */ jsx56("span", { className: "block truncate text-sm", children: tableName(table) }),
13883
+ /* @__PURE__ */ jsxs51("span", { className: "block truncate text-xs opacity-60", children: [
13530
13884
  table.fields.length,
13531
13885
  " field",
13532
13886
  table.fields.length === 1 ? "" : "s",
@@ -13541,10 +13895,10 @@ function TablesHome({ onOpenTable, className }) {
13541
13895
  }
13542
13896
 
13543
13897
  // src/TablePage.tsx
13544
- import { useCallback as useCallback36, useEffect as useEffect40, useState as useState50 } from "react";
13545
- import { useRecordsClient as useRecordsClient42, useTable as useTable22 } from "@ai-matrx/records/react";
13546
- import { Button as Button45, Separator as Separator11, Skeleton as Skeleton33, cn as cn49 } from "@ai-matrx/design-system";
13547
- import { Fragment as Fragment26, jsx as jsx56, jsxs as jsxs51 } from "react/jsx-runtime";
13898
+ import { useCallback as useCallback37, useEffect as useEffect41, useState as useState51 } from "react";
13899
+ import { useRecordsClient as useRecordsClient43, useTable as useTable22 } from "@ai-matrx/records/react";
13900
+ import { Button as Button46, Separator as Separator12, Skeleton as Skeleton34, cn as cn50 } from "@ai-matrx/design-system";
13901
+ import { Fragment as Fragment27, jsx as jsx57, jsxs as jsxs52 } from "react/jsx-runtime";
13548
13902
  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.";
13549
13903
  var DEFAULT_VIEW_NAME = "All records";
13550
13904
  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.";
@@ -13575,29 +13929,29 @@ function TablePage({
13575
13929
  activeRecordId,
13576
13930
  className
13577
13931
  }) {
13578
- const client = useRecordsClient42();
13932
+ const client = useRecordsClient43();
13579
13933
  const table = useTable22(tableId);
13580
13934
  const rights = useTableRights(table.data);
13581
- const organizationId = useRecordsClient42().config.organizationId;
13582
- const [view, setView] = useState50(null);
13935
+ const organizationId = useRecordsClient43().config.organizationId;
13936
+ const [view, setView] = useState51(null);
13583
13937
  const opening = openingRail(activeRecordId);
13584
- const [asking, setAsking] = useState50(null);
13585
- const [surface, setSurface] = useState50({
13938
+ const [asking, setAsking] = useState51(null);
13939
+ const [surface, setSurface] = useState51({
13586
13940
  main: activeDashboardId ? "dashboards" : "records",
13587
13941
  rail: opening.rail
13588
13942
  });
13589
13943
  const { main, rail } = surface;
13590
13944
  const setRail = (next) => setSurface((now) => ({ ...now, rail: next }));
13591
- const [openRecord, setOpenRecord] = useState50(opening.record);
13945
+ const [openRecord, setOpenRecord] = useState51(opening.record);
13592
13946
  const viewVersion = useRecordVersion(view?.id ?? null);
13593
13947
  const press = (pressed) => setSurface((now) => chooseSurface(now, pressed));
13594
13948
  const show = (next) => press({ rail: next });
13595
- useEffect40(() => {
13949
+ useEffect41(() => {
13596
13950
  if (!activeRecordId) return;
13597
13951
  setOpenRecord(activeRecordId);
13598
13952
  setSurface((now) => ({ ...now, rail: "record" }));
13599
13953
  }, [activeRecordId]);
13600
- const patchView = useCallback36(
13954
+ const patchView = useCallback37(
13601
13955
  async (patch) => {
13602
13956
  const current = view;
13603
13957
  if (!current) return;
@@ -13613,19 +13967,19 @@ function TablePage({
13613
13967
  },
13614
13968
  [client, view, viewVersion]
13615
13969
  );
13616
- if (table.error) return /* @__PURE__ */ jsx56(RefusalNotice, { error: table.error });
13617
- if (table.loading) return /* @__PURE__ */ jsx56(Skeleton33, { className: "h-40 w-full" });
13970
+ if (table.error) return /* @__PURE__ */ jsx57(RefusalNotice, { error: table.error });
13971
+ if (table.loading) return /* @__PURE__ */ jsx57(Skeleton34, { className: "h-40 w-full" });
13618
13972
  if (!table.data) {
13619
- return /* @__PURE__ */ jsxs51("div", { className: cn49("flex flex-col items-start gap-2 rounded-md border border-dashed p-6", className), children: [
13620
- /* @__PURE__ */ jsx56("p", { className: "text-sm font-medium", children: "This table is not here" }),
13621
- /* @__PURE__ */ jsx56("p", { className: "max-w-prose text-xs text-muted-foreground", children: TABLE_NOT_REACHABLE }),
13622
- onLeave ? /* @__PURE__ */ jsx56(Button45, { size: "sm", variant: "outline", onClick: onLeave, children: leaveLabel }) : null
13973
+ return /* @__PURE__ */ jsxs52("div", { className: cn50("flex flex-col items-start gap-2 rounded-md border border-dashed p-6", className), children: [
13974
+ /* @__PURE__ */ jsx57("p", { className: "text-sm font-medium", children: "This table is not here" }),
13975
+ /* @__PURE__ */ jsx57("p", { className: "max-w-prose text-xs text-muted-foreground", children: TABLE_NOT_REACHABLE }),
13976
+ onLeave ? /* @__PURE__ */ jsx57(Button46, { size: "sm", variant: "outline", onClick: onLeave, children: leaveLabel }) : null
13623
13977
  ] });
13624
13978
  }
13625
- return /* @__PURE__ */ jsxs51("div", { className: cn49("flex min-h-0 gap-4", className), children: [
13626
- /* @__PURE__ */ jsxs51("div", { className: "flex min-w-0 flex-1 flex-col gap-2", children: [
13627
- /* @__PURE__ */ jsxs51("div", { className: "flex flex-wrap items-center gap-1.5", children: [
13628
- /* @__PURE__ */ jsx56(
13979
+ return /* @__PURE__ */ jsxs52("div", { className: cn50("flex min-h-0 gap-4", className), children: [
13980
+ /* @__PURE__ */ jsxs52("div", { className: "flex min-w-0 flex-1 flex-col gap-2", children: [
13981
+ /* @__PURE__ */ jsxs52("div", { className: "flex flex-wrap items-center gap-1.5", children: [
13982
+ /* @__PURE__ */ jsx57(
13629
13983
  ViewBar,
13630
13984
  {
13631
13985
  tableId,
@@ -13634,10 +13988,10 @@ function TablePage({
13634
13988
  className: "min-w-0 flex-1"
13635
13989
  }
13636
13990
  ),
13637
- rights.write && view && view.layout !== "grid" ? /* @__PURE__ */ jsx56(Button45, { size: "sm", onClick: () => show("new-record"), children: "New record" }) : null,
13638
- rights.structure ? /* @__PURE__ */ jsxs51(Fragment26, { children: [
13639
- /* @__PURE__ */ jsx56(
13640
- Button45,
13991
+ rights.write && view && view.layout !== "grid" ? /* @__PURE__ */ jsx57(Button46, { size: "sm", onClick: () => show("new-record"), children: "New record" }) : null,
13992
+ rights.structure ? /* @__PURE__ */ jsxs52(Fragment27, { children: [
13993
+ /* @__PURE__ */ jsx57(
13994
+ Button46,
13641
13995
  {
13642
13996
  size: "sm",
13643
13997
  variant: surfaceChosen(surface, { rail: "field" }) ? "secondary" : "outline",
@@ -13646,8 +14000,8 @@ function TablePage({
13646
14000
  children: "Add field"
13647
14001
  }
13648
14002
  ),
13649
- /* @__PURE__ */ jsx56(
13650
- Button45,
14003
+ /* @__PURE__ */ jsx57(
14004
+ Button46,
13651
14005
  {
13652
14006
  size: "sm",
13653
14007
  variant: surfaceChosen(surface, { rail: "settings" }) ? "secondary" : "ghost",
@@ -13656,8 +14010,8 @@ function TablePage({
13656
14010
  children: "Settings"
13657
14011
  }
13658
14012
  ),
13659
- /* @__PURE__ */ jsx56(
13660
- Button45,
14013
+ /* @__PURE__ */ jsx57(
14014
+ Button46,
13661
14015
  {
13662
14016
  size: "sm",
13663
14017
  variant: surfaceChosen(surface, { rail: "import" }) ? "secondary" : "ghost",
@@ -13667,8 +14021,8 @@ function TablePage({
13667
14021
  }
13668
14022
  )
13669
14023
  ] }) : null,
13670
- /* @__PURE__ */ jsx56(
13671
- Button45,
14024
+ /* @__PURE__ */ jsx57(
14025
+ Button46,
13672
14026
  {
13673
14027
  size: "sm",
13674
14028
  variant: surfaceChosen(surface, { main: "dashboards" }) ? "secondary" : "ghost",
@@ -13677,8 +14031,8 @@ function TablePage({
13677
14031
  children: "Dashboards"
13678
14032
  }
13679
14033
  ),
13680
- /* @__PURE__ */ jsx56(
13681
- Button45,
14034
+ /* @__PURE__ */ jsx57(
14035
+ Button46,
13682
14036
  {
13683
14037
  size: "sm",
13684
14038
  variant: surfaceChosen(surface, { rail: "forms" }) ? "secondary" : "ghost",
@@ -13687,8 +14041,8 @@ function TablePage({
13687
14041
  children: "Forms"
13688
14042
  }
13689
14043
  ),
13690
- /* @__PURE__ */ jsx56(
13691
- Button45,
14044
+ /* @__PURE__ */ jsx57(
14045
+ Button46,
13692
14046
  {
13693
14047
  size: "sm",
13694
14048
  variant: surfaceChosen(surface, { rail: "bookings" }) ? "secondary" : "ghost",
@@ -13697,8 +14051,8 @@ function TablePage({
13697
14051
  children: "Bookings"
13698
14052
  }
13699
14053
  ),
13700
- /* @__PURE__ */ jsx56(
13701
- Button45,
14054
+ /* @__PURE__ */ jsx57(
14055
+ Button46,
13702
14056
  {
13703
14057
  size: "sm",
13704
14058
  variant: surfaceChosen(surface, { rail: "checklists" }) ? "secondary" : "ghost",
@@ -13707,8 +14061,8 @@ function TablePage({
13707
14061
  children: "Checklists"
13708
14062
  }
13709
14063
  ),
13710
- /* @__PURE__ */ jsx56(
13711
- Button45,
14064
+ /* @__PURE__ */ jsx57(
14065
+ Button46,
13712
14066
  {
13713
14067
  size: "sm",
13714
14068
  variant: surfaceChosen(surface, { rail: "notifications" }) ? "secondary" : "ghost",
@@ -13717,8 +14071,8 @@ function TablePage({
13717
14071
  children: "Notifications"
13718
14072
  }
13719
14073
  ),
13720
- /* @__PURE__ */ jsx56(
13721
- Button45,
14074
+ /* @__PURE__ */ jsx57(
14075
+ Button46,
13722
14076
  {
13723
14077
  size: "sm",
13724
14078
  variant: surfaceChosen(surface, { rail: "portals" }) ? "secondary" : "ghost",
@@ -13727,8 +14081,8 @@ function TablePage({
13727
14081
  children: "Portals"
13728
14082
  }
13729
14083
  ),
13730
- /* @__PURE__ */ jsx56(
13731
- Button45,
14084
+ /* @__PURE__ */ jsx57(
14085
+ Button46,
13732
14086
  {
13733
14087
  size: "sm",
13734
14088
  variant: surfaceChosen(surface, { rail: "inbox" }) ? "secondary" : "ghost",
@@ -13737,7 +14091,7 @@ function TablePage({
13737
14091
  children: "Inbox"
13738
14092
  }
13739
14093
  ),
13740
- /* @__PURE__ */ jsx56(
14094
+ /* @__PURE__ */ jsx57(
13741
14095
  ShareControl,
13742
14096
  {
13743
14097
  kind: "table",
@@ -13747,10 +14101,10 @@ function TablePage({
13747
14101
  may: rights.share
13748
14102
  }
13749
14103
  ),
13750
- /* @__PURE__ */ jsx56(ExportMenu, { tableId })
14104
+ /* @__PURE__ */ jsx57(ExportMenu, { tableId })
13751
14105
  ] }),
13752
- main === "dashboards" ? /* @__PURE__ */ jsx56(DashboardCanvas, { tableId, activeDashboardId: activeDashboardId ?? null }) : /* @__PURE__ */ jsxs51(Fragment26, { children: [
13753
- /* @__PURE__ */ jsx56(
14106
+ main === "dashboards" ? /* @__PURE__ */ jsx57(DashboardCanvas, { tableId, activeDashboardId: activeDashboardId ?? null }) : /* @__PURE__ */ jsxs52(Fragment27, { children: [
14107
+ /* @__PURE__ */ jsx57(
13754
14108
  ViewSwitcher,
13755
14109
  {
13756
14110
  view: view ?? defaultView(tableId),
@@ -13767,18 +14121,18 @@ function TablePage({
13767
14121
  }
13768
14122
  }
13769
14123
  ),
13770
- view ? null : /* @__PURE__ */ jsx56("p", { className: "text-xs text-muted-foreground", children: VIEW_NOT_SAVED_YET })
14124
+ view ? null : /* @__PURE__ */ jsx57("p", { className: "text-xs text-muted-foreground", children: VIEW_NOT_SAVED_YET })
13771
14125
  ] })
13772
14126
  ] }),
13773
- rail === "none" ? null : /* @__PURE__ */ jsxs51("aside", { className: "w-[26rem] shrink-0 overflow-y-auto rounded-md border p-3", children: [
13774
- rail === "settings" ? /* @__PURE__ */ jsx56(
14127
+ rail === "none" ? null : /* @__PURE__ */ jsxs52("aside", { className: "w-[26rem] shrink-0 overflow-y-auto rounded-md border p-3", children: [
14128
+ rail === "settings" ? /* @__PURE__ */ jsx57(
13775
14129
  TableSettings,
13776
14130
  {
13777
14131
  tableId,
13778
14132
  ...onLeave ? { onDeleted: onLeave } : {}
13779
14133
  }
13780
14134
  ) : null,
13781
- rail === "inbox" ? /* @__PURE__ */ jsx56(
14135
+ rail === "inbox" ? /* @__PURE__ */ jsx57(
13782
14136
  ActionInbox,
13783
14137
  {
13784
14138
  tableId,
@@ -13788,9 +14142,9 @@ function TablePage({
13788
14142
  }
13789
14143
  }
13790
14144
  ) : null,
13791
- rail === "forms" ? /* @__PURE__ */ jsx56(FormsPanel, { tableId }) : null,
13792
- rail === "bookings" ? /* @__PURE__ */ jsx56(BookingSlots, { tableId }) : null,
13793
- rail === "checklists" ? /* @__PURE__ */ jsx56(
14145
+ rail === "forms" ? /* @__PURE__ */ jsx57(FormsPanel, { tableId }) : null,
14146
+ rail === "bookings" ? /* @__PURE__ */ jsx57(BookingSlots, { tableId }) : null,
14147
+ rail === "checklists" ? /* @__PURE__ */ jsx57(
13794
14148
  ChecklistsPanel,
13795
14149
  {
13796
14150
  tableId,
@@ -13800,11 +14154,11 @@ function TablePage({
13800
14154
  }
13801
14155
  }
13802
14156
  ) : null,
13803
- rail === "notifications" ? /* @__PURE__ */ jsx56(SubscriptionsPanel, { tableId }) : null,
13804
- rail === "portals" ? /* @__PURE__ */ jsx56(PortalsPanel, { tableId }) : null,
13805
- rail === "import" ? /* @__PURE__ */ jsx56(ImportWizard, { tableId, onDone: () => setRail("none") }) : null,
13806
- rail === "field" ? /* @__PURE__ */ jsx56(FieldEditor, { tableId, onSaved: () => setRail("none"), onCancel: () => setRail("none") }) : null,
13807
- rail === "new-record" ? /* @__PURE__ */ jsx56(
14157
+ rail === "notifications" ? /* @__PURE__ */ jsx57(SubscriptionsPanel, { tableId }) : null,
14158
+ rail === "portals" ? /* @__PURE__ */ jsx57(PortalsPanel, { tableId }) : null,
14159
+ rail === "import" ? /* @__PURE__ */ jsx57(ImportWizard, { tableId, onDone: () => setRail("none") }) : null,
14160
+ rail === "field" ? /* @__PURE__ */ jsx57(FieldEditor, { tableId, onSaved: () => setRail("none"), onCancel: () => setRail("none") }) : null,
14161
+ rail === "new-record" ? /* @__PURE__ */ jsx57(
13808
14162
  RecordForm,
13809
14163
  {
13810
14164
  tableId,
@@ -13815,7 +14169,7 @@ function TablePage({
13815
14169
  onCancel: () => setRail("none")
13816
14170
  }
13817
14171
  ) : null,
13818
- rail === "who-changed" && asking ? /* @__PURE__ */ jsx56(
14172
+ rail === "who-changed" && asking ? /* @__PURE__ */ jsx57(
13819
14173
  FieldHistoryPanel,
13820
14174
  {
13821
14175
  tableId,
@@ -13828,10 +14182,10 @@ function TablePage({
13828
14182
  }
13829
14183
  }
13830
14184
  ) : null,
13831
- rail === "record" && openRecord ? /* @__PURE__ */ jsxs51("div", { className: "space-y-3", children: [
13832
- /* @__PURE__ */ jsx56(Peek, { tableId, recordId: openRecord, onClose: () => setRail("none") }),
13833
- /* @__PURE__ */ jsx56(Separator11, {}),
13834
- /* @__PURE__ */ jsx56(
14185
+ rail === "record" && openRecord ? /* @__PURE__ */ jsxs52("div", { className: "space-y-3", children: [
14186
+ /* @__PURE__ */ jsx57(Peek, { tableId, recordId: openRecord, onClose: () => setRail("none") }),
14187
+ /* @__PURE__ */ jsx57(Separator12, {}),
14188
+ /* @__PURE__ */ jsx57(
13835
14189
  HistoryPanel,
13836
14190
  {
13837
14191
  tableId,
@@ -13842,10 +14196,10 @@ function TablePage({
13842
14196
  }
13843
14197
  }
13844
14198
  ),
13845
- /* @__PURE__ */ jsx56(Separator11, {}),
13846
- /* @__PURE__ */ jsx56(ChecklistRunner, { tableId, recordId: openRecord }),
13847
- /* @__PURE__ */ jsx56(Separator11, {}),
13848
- /* @__PURE__ */ jsx56(CommentThread, { tableId, recordId: openRecord })
14199
+ /* @__PURE__ */ jsx57(Separator12, {}),
14200
+ /* @__PURE__ */ jsx57(ChecklistRunner, { tableId, recordId: openRecord }),
14201
+ /* @__PURE__ */ jsx57(Separator12, {}),
14202
+ /* @__PURE__ */ jsx57(CommentThread, { tableId, recordId: openRecord })
13849
14203
  ] }) : null
13850
14204
  ] })
13851
14205
  ] });
@@ -13876,6 +14230,7 @@ export {
13876
14230
  DEFAULT_FIELDS,
13877
14231
  DEFAULT_VIEW_NAME,
13878
14232
  DashboardCanvas,
14233
+ DigestScheduler,
13879
14234
  DocRender,
13880
14235
  DocTemplate,
13881
14236
  EMPTY_PRESENTATION,