@ai-matrx/records-ui 0.101.7 → 0.101.9

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog — @ai-matrx/records-ui
2
2
 
3
+ ## 0.101.9
4
+
5
+ Automatic changed-only republish (docs/metadata drift since the last tag — see
6
+ `git diff npm/records-ui/v0.101.8..npm/records-ui/v0.101.9 -- apps/shared/records-ui`).
7
+ No source changes intended and no consumer action required.
8
+
9
+ ## 0.101.8
10
+
11
+ Automatic changed-only republish (docs/metadata drift since the last tag — see
12
+ `git diff npm/records-ui/v0.101.7..npm/records-ui/v0.101.8 -- apps/shared/records-ui`).
13
+ No source changes intended and no consumer action required.
14
+
3
15
  ## 0.101.7
4
16
 
5
17
  Automatic changed-only republish (docs/metadata drift since the last tag — see
package/dist/index.cjs CHANGED
@@ -678,8 +678,16 @@ function RecordsUiProvider({ value, children }) {
678
678
  function useRecordsUi() {
679
679
  return (0, import_react.useContext)(HostContext) ?? {};
680
680
  }
681
+ function quiet(may, say2) {
682
+ if (say2 !== false) return may;
683
+ return { ...may, why: () => "", ..."reason" in may ? { reason: "" } : {} };
684
+ }
681
685
  function useTableRights(table) {
682
686
  const host = useRecordsUi();
687
+ const asked3 = useTableRightsAsked(table, host);
688
+ return (0, import_react.useMemo)(() => quiet(asked3, host.sayLevelNeeded), [asked3, host.sayLevelNeeded]);
689
+ }
690
+ function useTableRightsAsked(table, host) {
683
691
  const bound = Boolean(host.rights);
684
692
  const asked3 = (0, import_react2.useMyLevel)(bound || !table ? null : table.id);
685
693
  return (0, import_react.useMemo)(() => {
@@ -692,22 +700,24 @@ function useTableRights(table) {
692
700
  }
693
701
  function useRecordRights(recordId) {
694
702
  const asked3 = (0, import_react2.useMyLevel)(recordId);
703
+ const say2 = useRecordsUi().sayLevelNeeded;
695
704
  return (0, import_react.useMemo)(() => {
696
705
  if (!recordId) return NOT_ANSWERED_YET;
697
706
  if (asked3.loading) return NOT_ANSWERED_YET;
698
- if (asked3.error) return whatYouMayDo(null, true);
699
- return whatYouMayDo(asked3.data, true);
700
- }, [recordId, asked3.loading, asked3.error, asked3.data]);
707
+ if (asked3.error) return quiet(whatYouMayDo(null, true), say2);
708
+ return quiet(whatYouMayDo(asked3.data, true), say2);
709
+ }, [recordId, asked3.loading, asked3.error, asked3.data, say2]);
701
710
  }
702
711
  function useRowRights(rowIds, enabled) {
703
712
  const asked3 = (0, import_react2.useMyLevels)(enabled ? rowIds : []);
713
+ const say2 = useRecordsUi().sayLevelNeeded;
704
714
  return (0, import_react.useMemo)(() => {
705
715
  if (!enabled) return () => null;
706
716
  if (asked3.loading) return () => NOT_ANSWERED_YET;
707
- if (asked3.error) return () => whatYouMayDo(null, true);
717
+ if (asked3.error) return () => quiet(whatYouMayDo(null, true), say2);
708
718
  const held = asked3.data ?? {};
709
- return (rowId) => whatYouMayDo(held[rowId] ?? null, true);
710
- }, [enabled, asked3.loading, asked3.error, asked3.data]);
719
+ return (rowId) => quiet(whatYouMayDo(held[rowId] ?? null, true), say2);
720
+ }, [enabled, asked3.loading, asked3.error, asked3.data, say2]);
711
721
  }
712
722
 
713
723
  // src/plainWords.ts
@@ -26574,7 +26584,7 @@ function Peek({ tableId, recordId, onClose, className, onPage = false }) {
26574
26584
  ) : host.chat && !askOpenBelow ? /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(import_design_system80.Button, { size: "sm", variant: talking ? "ghost" : "outline", onClick: () => setTalking((t) => !t), children: talking ? "Close chat" : "Talk to this record" }) : null,
26575
26585
  organizationId ? /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(ShareControl, { kind: "record", organizationId, subjectId: recordId, name: title, may: may.share }) : null,
26576
26586
  /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(RowShownTo, { recordId }),
26577
- may.write ? /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(import_design_system80.Button, { size: "sm", variant: editing ? "ghost" : "outline", onClick: () => setEditing((e) => !e), children: editing ? "Stop editing" : "Edit" }) : may.known ? (
26587
+ may.write ? /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(import_design_system80.Button, { size: "sm", variant: editing ? "ghost" : "outline", onClick: () => setEditing((e) => !e), children: editing ? "Stop editing" : "Edit" }) : may.known && may.why("write") ? (
26578
26588
  // Absent AND explained: no Edit button, and one sentence saying what
26579
26589
  // it would take and who can give it.
26580
26590
  /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "max-w-[18rem] text-[11px] text-muted-foreground", children: may.why("write") })
@@ -35967,7 +35977,7 @@ function DigestScheduler({
35967
35977
  const [channel, setChannel] = (0, import_react197.useState)(
35968
35978
  existing?.channel === "email" || existing?.channel === "sms" ? existing.channel : "in_app"
35969
35979
  );
35970
- const [quiet, setQuiet] = (0, import_react197.useState)((0, import_records50.hasQuietHours)(existing?.quiet_hours));
35980
+ const [quiet2, setQuiet] = (0, import_react197.useState)((0, import_records50.hasQuietHours)(existing?.quiet_hours));
35971
35981
  const [quietFrom, setQuietFrom] = (0, import_react197.useState)(existing?.quiet_hours?.start ?? "22:00");
35972
35982
  const [quietTo, setQuietTo] = (0, import_react197.useState)(existing?.quiet_hours?.end ?? "07:00");
35973
35983
  const [recipients, setRecipients] = (0, import_react197.useState)(
@@ -36005,8 +36015,8 @@ function DigestScheduler({
36005
36015
  return null;
36006
36016
  }, [cadence, weekday, time]);
36007
36017
  const quietHours = (0, import_react197.useMemo)(
36008
- () => quiet ? { start: quietFrom, end: quietTo, tz: timezone } : { tz: timezone },
36009
- [quiet, quietFrom, quietTo, timezone]
36018
+ () => quiet2 ? { start: quietFrom, end: quietTo, tz: timezone } : { tz: timezone },
36019
+ [quiet2, quietFrom, quietTo, timezone]
36010
36020
  );
36011
36021
  const fallbackName = `${CADENCE_TITLE[cadence] ?? "Weekly"} ${tableName2 ?? "records"} summary`;
36012
36022
  async function scheduleIt() {
@@ -36174,10 +36184,10 @@ function DigestScheduler({
36174
36184
  ] })
36175
36185
  ] }),
36176
36186
  /* @__PURE__ */ (0, import_jsx_runtime117.jsxs)("label", { className: "flex items-center gap-1.5 text-xs", children: [
36177
- /* @__PURE__ */ (0, import_jsx_runtime117.jsx)(import_design_system104.Checkbox, { checked: quiet, onCheckedChange: (on) => setQuiet(Boolean(on)) }),
36187
+ /* @__PURE__ */ (0, import_jsx_runtime117.jsx)(import_design_system104.Checkbox, { checked: quiet2, onCheckedChange: (on) => setQuiet(Boolean(on)) }),
36178
36188
  "Not between certain hours"
36179
36189
  ] }),
36180
- quiet ? /* @__PURE__ */ (0, import_jsx_runtime117.jsxs)("div", { className: "flex items-center gap-2", children: [
36190
+ quiet2 ? /* @__PURE__ */ (0, import_jsx_runtime117.jsxs)("div", { className: "flex items-center gap-2", children: [
36181
36191
  /* @__PURE__ */ (0, import_jsx_runtime117.jsx)(
36182
36192
  import_design_system104.BasicInput,
36183
36193
  {
@@ -36951,7 +36961,7 @@ function FormStage({
36951
36961
  }
36952
36962
  const unresolved = questions.filter((q) => !q.field);
36953
36963
  const unanswerable = !whichAsked && questions.some((q) => q.showIf);
36954
- const signedInPublic = connected && form.isPublic === true;
36964
+ const signedInPublic = connected && form.isPublic === true && !preview;
36955
36965
  return /* @__PURE__ */ (0, import_jsx_runtime120.jsxs)(
36956
36966
  "section",
36957
36967
  {
@@ -37211,7 +37221,7 @@ function NotifyRuleEditor({ tableId, seed, chosenRuleId, onChoose, className })
37211
37221
  await load();
37212
37222
  })();
37213
37223
  }, [subscriptions, seed, write, load]);
37214
- async function subscribe(viewId, viewName, cadence, channel, schedule, quiet) {
37224
+ async function subscribe(viewId, viewName, cadence, channel, schedule, quiet2) {
37215
37225
  setBusy(true);
37216
37226
  const ok = await write({
37217
37227
  name: `${viewName} \u2014 ${CADENCE_WORDS2[cadence] ?? cadence}`,
@@ -37219,7 +37229,7 @@ function NotifyRuleEditor({ tableId, seed, chosenRuleId, onChoose, className })
37219
37229
  cadence,
37220
37230
  channel,
37221
37231
  schedule: schedule.trim() === "" ? null : schedule.trim(),
37222
- quietHours: quiet
37232
+ quietHours: quiet2
37223
37233
  });
37224
37234
  setBusy(false);
37225
37235
  if (!ok) return;
@@ -37336,8 +37346,8 @@ function NotifyRuleEditor({ tableId, seed, chosenRuleId, onChoose, className })
37336
37346
  const start = form.elements.namedItem("quiet_start").value;
37337
37347
  const end = form.elements.namedItem("quiet_end").value;
37338
37348
  const name = views.find((v) => v.id === view)?.name ?? "View";
37339
- const quiet = start && end ? { start, end, tz: Intl.DateTimeFormat().resolvedOptions().timeZone } : null;
37340
- if (view) void subscribe(view, name, cadence, channel, schedule, quiet);
37349
+ const quiet2 = start && end ? { start, end, tz: Intl.DateTimeFormat().resolvedOptions().timeZone } : null;
37350
+ if (view) void subscribe(view, name, cadence, channel, schedule, quiet2);
37341
37351
  },
37342
37352
  children: [
37343
37353
  /* @__PURE__ */ (0, import_jsx_runtime121.jsx)("select", { name: "view", "aria-label": "View to be told about", className: "h-7 rounded border bg-background px-1 text-xs", children: views.map((view) => /* @__PURE__ */ (0, import_jsx_runtime121.jsx)("option", { value: view.id, children: view.name }, view.id)) }),
@@ -46060,12 +46070,14 @@ function Decision({ approvalId, onDecided }) {
46060
46070
  // src/TemplatePreview.tsx
46061
46071
  var import_react263 = require("react");
46062
46072
  var import_memory = require("@ai-matrx/records/memory");
46073
+ var import_react264 = require("@ai-matrx/records/react");
46063
46074
  var import_jsx_runtime152 = require("react/jsx-runtime");
46064
46075
  function useTemplatePreview(spec, today) {
46065
46076
  return (0, import_react263.useMemo)(() => (0, import_memory.templatePreview)(spec, today ? { today } : {}), [spec, today]);
46066
46077
  }
46067
- function TemplatePreview({ spec, today, initialTable, host, aside, className }) {
46078
+ function TemplatePreview({ spec, today, initialTable, host, aside, booking, className }) {
46068
46079
  const preview = useTemplatePreview(spec, today);
46080
+ const bound = (0, import_react263.useMemo)(() => ({ ...host, sayLevelNeeded: false }), [host]);
46069
46081
  const first = preview.tables.find((t) => t.token === initialTable) ?? preview.tables[0];
46070
46082
  const [active, setActive] = (0, import_react263.useState)(first?.id ?? null);
46071
46083
  const table = preview.tables.find((t) => t.id === active) ?? first;
@@ -46093,7 +46105,49 @@ function TemplatePreview({ spec, today, initialTable, host, aside, className })
46093
46105
  )),
46094
46106
  aside ? /* @__PURE__ */ (0, import_jsx_runtime152.jsx)("div", { className: "ml-auto", children: aside }) : null
46095
46107
  ] }) : null,
46096
- /* @__PURE__ */ (0, import_jsx_runtime152.jsx)(RecordsMount, { config: preview.config, host, children: /* @__PURE__ */ (0, import_jsx_runtime152.jsx)("div", { className: "min-h-[32rem] min-w-0 overflow-hidden rounded-xl border border-border bg-card", children: /* @__PURE__ */ (0, import_jsx_runtime152.jsx)(TablePage, { tableId: table.id }, table.id) }) })
46108
+ /* @__PURE__ */ (0, import_jsx_runtime152.jsxs)(RecordsMount, { config: preview.config, host: bound, children: [
46109
+ /* @__PURE__ */ (0, import_jsx_runtime152.jsx)("div", { className: "min-h-[32rem] min-w-0 overflow-hidden rounded-xl border border-border bg-card", children: /* @__PURE__ */ (0, import_jsx_runtime152.jsx)(TablePage, { tableId: table.id }, table.id) }),
46110
+ /* @__PURE__ */ (0, import_jsx_runtime152.jsx)(PreviewForms, { preview, booking }),
46111
+ preview.dashboards.length ? /* @__PURE__ */ (0, import_jsx_runtime152.jsxs)("section", { className: "flex min-w-0 flex-col gap-3", "aria-label": "Dashboards", "data-template-preview-dashboards": preview.dashboards.length, children: [
46112
+ /* @__PURE__ */ (0, import_jsx_runtime152.jsx)("h2", { className: "text-lg font-semibold tracking-tight", children: "Dashboards" }),
46113
+ preview.dashboards.map((d) => /* @__PURE__ */ (0, import_jsx_runtime152.jsx)("div", { className: "min-w-0 overflow-hidden rounded-xl border border-border bg-card p-3", "data-template-preview-dashboard": d.token, children: /* @__PURE__ */ (0, import_jsx_runtime152.jsx)(DashboardCanvas, { tableId: d.tableId, activeDashboardId: d.id }) }, d.id))
46114
+ ] }) : null
46115
+ ] })
46116
+ ] });
46117
+ }
46118
+ function PreviewForms({ preview, booking }) {
46119
+ const client = (0, import_react264.useRecordsClient)();
46120
+ const [forms, setForms] = (0, import_react263.useState)(null);
46121
+ const [pages, setPages] = (0, import_react263.useState)([]);
46122
+ (0, import_react263.useEffect)(() => {
46123
+ let gone = false;
46124
+ void client.forms().then((answered) => {
46125
+ if (!gone) setForms(answered.ok ? answered.data.map(formFromSummary) : []);
46126
+ });
46127
+ const wanted = booking ? preview.forms.filter((f) => f.booking) : [];
46128
+ void Promise.all(
46129
+ wanted.map(async (f) => {
46130
+ const answered = await preview.config.dataSource.rpc("booking_public", { p_form_id: f.id });
46131
+ return answered.error ? null : { id: f.id, page: answered.data };
46132
+ })
46133
+ ).then((got) => {
46134
+ if (!gone) setPages(got.filter((g) => g !== null));
46135
+ });
46136
+ return () => {
46137
+ gone = true;
46138
+ };
46139
+ }, [client, preview, booking]);
46140
+ if (!forms?.length && !pages.length) return null;
46141
+ return /* @__PURE__ */ (0, import_jsx_runtime152.jsxs)("section", { className: "flex min-w-0 flex-col gap-3", "aria-label": "Forms and booking", "data-template-preview-forms": forms?.length ?? 0, children: [
46142
+ /* @__PURE__ */ (0, import_jsx_runtime152.jsx)("h2", { className: "text-lg font-semibold tracking-tight", children: "Forms and booking" }),
46143
+ /* @__PURE__ */ (0, import_jsx_runtime152.jsx)("div", { className: "grid min-w-0 gap-4 md:grid-cols-2", children: (forms ?? []).map((f) => /* @__PURE__ */ (0, import_jsx_runtime152.jsxs)("div", { className: "min-w-0 rounded-xl border border-border bg-card p-4", "data-template-preview-form": f.slug ?? f.id, children: [
46144
+ /* @__PURE__ */ (0, import_jsx_runtime152.jsx)("h3", { className: "mb-3 text-sm font-semibold", children: f.name }),
46145
+ /* @__PURE__ */ (0, import_jsx_runtime152.jsx)(FormRunner, { form: f, preview: true })
46146
+ ] }, f.id)) }),
46147
+ booking ? pages.map((p) => /* @__PURE__ */ (0, import_jsx_runtime152.jsxs)("div", { className: "min-w-0 rounded-xl border border-border bg-card p-4", "data-template-preview-booking": p.id, children: [
46148
+ /* @__PURE__ */ (0, import_jsx_runtime152.jsx)("h3", { className: "mb-3 text-sm font-semibold", children: String(p.page["title"] ?? "") }),
46149
+ booking(p.page)
46150
+ ] }, p.id)) : null
46097
46151
  ] });
46098
46152
  }
46099
46153
  //# sourceMappingURL=index.cjs.map