@ai-matrx/records-ui 0.101.2 → 0.101.8
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 +36 -0
- package/dist/index.cjs +112 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -9
- package/dist/index.d.ts +34 -9
- package/dist/index.js +112 -16
- package/dist/index.js.map +1 -1
- package/dist/pickers.cjs.map +1 -1
- package/dist/pickers.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# Changelog — @ai-matrx/records-ui
|
|
2
2
|
|
|
3
|
+
## 0.101.8
|
|
4
|
+
|
|
5
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
6
|
+
`git diff npm/records-ui/v0.101.7..npm/records-ui/v0.101.8 -- apps/shared/records-ui`).
|
|
7
|
+
No source changes intended and no consumer action required.
|
|
8
|
+
|
|
9
|
+
## 0.101.7
|
|
10
|
+
|
|
11
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
12
|
+
`git diff npm/records-ui/v0.101.2..npm/records-ui/v0.101.7 -- apps/shared/records-ui`).
|
|
13
|
+
No source changes intended and no consumer action required.
|
|
14
|
+
|
|
15
|
+
## 0.101.6
|
|
16
|
+
|
|
17
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
18
|
+
`git diff npm/records-ui/v0.101.2..npm/records-ui/v0.101.6 -- apps/shared/records-ui`).
|
|
19
|
+
No source changes intended and no consumer action required.
|
|
20
|
+
|
|
21
|
+
## 0.101.5
|
|
22
|
+
|
|
23
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
24
|
+
`git diff npm/records-ui/v0.101.2..npm/records-ui/v0.101.5 -- apps/shared/records-ui`).
|
|
25
|
+
No source changes intended and no consumer action required.
|
|
26
|
+
|
|
27
|
+
## 0.101.4
|
|
28
|
+
|
|
29
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
30
|
+
`git diff npm/records-ui/v0.101.2..npm/records-ui/v0.101.4 -- apps/shared/records-ui`).
|
|
31
|
+
No source changes intended and no consumer action required.
|
|
32
|
+
|
|
33
|
+
## 0.101.3
|
|
34
|
+
|
|
35
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
36
|
+
`git diff npm/records-ui/v0.101.2..npm/records-ui/v0.101.3 -- apps/shared/records-ui`).
|
|
37
|
+
No source changes intended and no consumer action required.
|
|
38
|
+
|
|
3
39
|
## 0.101.2
|
|
4
40
|
|
|
5
41
|
`TablesHome`: "Start from a template" (`templatesHref`) also shows while a new table is being named, so a
|
package/dist/index.cjs
CHANGED
|
@@ -269,6 +269,7 @@ __export(src_exports, {
|
|
|
269
269
|
TableSettings: () => TableSettings,
|
|
270
270
|
TableToolbarSlotContext: () => TableToolbarSlotContext,
|
|
271
271
|
TablesHome: () => TablesHome,
|
|
272
|
+
TemplatePreview: () => TemplatePreview,
|
|
272
273
|
TimelineView: () => TimelineView,
|
|
273
274
|
UNREAD_RECORD_LABEL: () => UNREAD_RECORD_LABEL,
|
|
274
275
|
VIEW_ADDRESS_KEYS: () => VIEW_ADDRESS_KEYS,
|
|
@@ -550,6 +551,7 @@ __export(src_exports, {
|
|
|
550
551
|
useTableRights: () => useTableRights,
|
|
551
552
|
useTableToolbarSlot: () => useTableToolbarSlot,
|
|
552
553
|
useTablesAnywhere: () => useTablesAnywhere,
|
|
554
|
+
useTemplatePreview: () => useTemplatePreview,
|
|
553
555
|
useViewRecords: () => useViewRecords,
|
|
554
556
|
useWhoChanged: () => useWhoChanged,
|
|
555
557
|
viewActions: () => viewActions,
|
|
@@ -676,8 +678,16 @@ function RecordsUiProvider({ value, children }) {
|
|
|
676
678
|
function useRecordsUi() {
|
|
677
679
|
return (0, import_react.useContext)(HostContext) ?? {};
|
|
678
680
|
}
|
|
681
|
+
function quiet(may, say2) {
|
|
682
|
+
if (say2 !== false) return may;
|
|
683
|
+
return { ...may, why: () => "", ..."reason" in may ? { reason: "" } : {} };
|
|
684
|
+
}
|
|
679
685
|
function useTableRights(table) {
|
|
680
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) {
|
|
681
691
|
const bound = Boolean(host.rights);
|
|
682
692
|
const asked3 = (0, import_react2.useMyLevel)(bound || !table ? null : table.id);
|
|
683
693
|
return (0, import_react.useMemo)(() => {
|
|
@@ -690,22 +700,24 @@ function useTableRights(table) {
|
|
|
690
700
|
}
|
|
691
701
|
function useRecordRights(recordId) {
|
|
692
702
|
const asked3 = (0, import_react2.useMyLevel)(recordId);
|
|
703
|
+
const say2 = useRecordsUi().sayLevelNeeded;
|
|
693
704
|
return (0, import_react.useMemo)(() => {
|
|
694
705
|
if (!recordId) return NOT_ANSWERED_YET;
|
|
695
706
|
if (asked3.loading) return NOT_ANSWERED_YET;
|
|
696
|
-
if (asked3.error) return whatYouMayDo(null, true);
|
|
697
|
-
return whatYouMayDo(asked3.data, true);
|
|
698
|
-
}, [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]);
|
|
699
710
|
}
|
|
700
711
|
function useRowRights(rowIds, enabled) {
|
|
701
712
|
const asked3 = (0, import_react2.useMyLevels)(enabled ? rowIds : []);
|
|
713
|
+
const say2 = useRecordsUi().sayLevelNeeded;
|
|
702
714
|
return (0, import_react.useMemo)(() => {
|
|
703
715
|
if (!enabled) return () => null;
|
|
704
716
|
if (asked3.loading) return () => NOT_ANSWERED_YET;
|
|
705
|
-
if (asked3.error) return () => whatYouMayDo(null, true);
|
|
717
|
+
if (asked3.error) return () => quiet(whatYouMayDo(null, true), say2);
|
|
706
718
|
const held = asked3.data ?? {};
|
|
707
|
-
return (rowId) => whatYouMayDo(held[rowId] ?? null, true);
|
|
708
|
-
}, [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]);
|
|
709
721
|
}
|
|
710
722
|
|
|
711
723
|
// src/plainWords.ts
|
|
@@ -26572,7 +26584,7 @@ function Peek({ tableId, recordId, onClose, className, onPage = false }) {
|
|
|
26572
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,
|
|
26573
26585
|
organizationId ? /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(ShareControl, { kind: "record", organizationId, subjectId: recordId, name: title, may: may.share }) : null,
|
|
26574
26586
|
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)(RowShownTo, { recordId }),
|
|
26575
|
-
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") ? (
|
|
26576
26588
|
// Absent AND explained: no Edit button, and one sentence saying what
|
|
26577
26589
|
// it would take and who can give it.
|
|
26578
26590
|
/* @__PURE__ */ (0, import_jsx_runtime90.jsx)("span", { className: "max-w-[18rem] text-[11px] text-muted-foreground", children: may.why("write") })
|
|
@@ -35965,7 +35977,7 @@ function DigestScheduler({
|
|
|
35965
35977
|
const [channel, setChannel] = (0, import_react197.useState)(
|
|
35966
35978
|
existing?.channel === "email" || existing?.channel === "sms" ? existing.channel : "in_app"
|
|
35967
35979
|
);
|
|
35968
|
-
const [
|
|
35980
|
+
const [quiet2, setQuiet] = (0, import_react197.useState)((0, import_records50.hasQuietHours)(existing?.quiet_hours));
|
|
35969
35981
|
const [quietFrom, setQuietFrom] = (0, import_react197.useState)(existing?.quiet_hours?.start ?? "22:00");
|
|
35970
35982
|
const [quietTo, setQuietTo] = (0, import_react197.useState)(existing?.quiet_hours?.end ?? "07:00");
|
|
35971
35983
|
const [recipients, setRecipients] = (0, import_react197.useState)(
|
|
@@ -36003,8 +36015,8 @@ function DigestScheduler({
|
|
|
36003
36015
|
return null;
|
|
36004
36016
|
}, [cadence, weekday, time]);
|
|
36005
36017
|
const quietHours = (0, import_react197.useMemo)(
|
|
36006
|
-
() =>
|
|
36007
|
-
[
|
|
36018
|
+
() => quiet2 ? { start: quietFrom, end: quietTo, tz: timezone } : { tz: timezone },
|
|
36019
|
+
[quiet2, quietFrom, quietTo, timezone]
|
|
36008
36020
|
);
|
|
36009
36021
|
const fallbackName = `${CADENCE_TITLE[cadence] ?? "Weekly"} ${tableName2 ?? "records"} summary`;
|
|
36010
36022
|
async function scheduleIt() {
|
|
@@ -36172,10 +36184,10 @@ function DigestScheduler({
|
|
|
36172
36184
|
] })
|
|
36173
36185
|
] }),
|
|
36174
36186
|
/* @__PURE__ */ (0, import_jsx_runtime117.jsxs)("label", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
36175
|
-
/* @__PURE__ */ (0, import_jsx_runtime117.jsx)(import_design_system104.Checkbox, { checked:
|
|
36187
|
+
/* @__PURE__ */ (0, import_jsx_runtime117.jsx)(import_design_system104.Checkbox, { checked: quiet2, onCheckedChange: (on) => setQuiet(Boolean(on)) }),
|
|
36176
36188
|
"Not between certain hours"
|
|
36177
36189
|
] }),
|
|
36178
|
-
|
|
36190
|
+
quiet2 ? /* @__PURE__ */ (0, import_jsx_runtime117.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
36179
36191
|
/* @__PURE__ */ (0, import_jsx_runtime117.jsx)(
|
|
36180
36192
|
import_design_system104.BasicInput,
|
|
36181
36193
|
{
|
|
@@ -37209,7 +37221,7 @@ function NotifyRuleEditor({ tableId, seed, chosenRuleId, onChoose, className })
|
|
|
37209
37221
|
await load();
|
|
37210
37222
|
})();
|
|
37211
37223
|
}, [subscriptions, seed, write, load]);
|
|
37212
|
-
async function subscribe(viewId, viewName, cadence, channel, schedule,
|
|
37224
|
+
async function subscribe(viewId, viewName, cadence, channel, schedule, quiet2) {
|
|
37213
37225
|
setBusy(true);
|
|
37214
37226
|
const ok = await write({
|
|
37215
37227
|
name: `${viewName} \u2014 ${CADENCE_WORDS2[cadence] ?? cadence}`,
|
|
@@ -37217,7 +37229,7 @@ function NotifyRuleEditor({ tableId, seed, chosenRuleId, onChoose, className })
|
|
|
37217
37229
|
cadence,
|
|
37218
37230
|
channel,
|
|
37219
37231
|
schedule: schedule.trim() === "" ? null : schedule.trim(),
|
|
37220
|
-
quietHours:
|
|
37232
|
+
quietHours: quiet2
|
|
37221
37233
|
});
|
|
37222
37234
|
setBusy(false);
|
|
37223
37235
|
if (!ok) return;
|
|
@@ -37334,8 +37346,8 @@ function NotifyRuleEditor({ tableId, seed, chosenRuleId, onChoose, className })
|
|
|
37334
37346
|
const start = form.elements.namedItem("quiet_start").value;
|
|
37335
37347
|
const end = form.elements.namedItem("quiet_end").value;
|
|
37336
37348
|
const name = views.find((v) => v.id === view)?.name ?? "View";
|
|
37337
|
-
const
|
|
37338
|
-
if (view) void subscribe(view, name, cadence, channel, schedule,
|
|
37349
|
+
const quiet2 = start && end ? { start, end, tz: Intl.DateTimeFormat().resolvedOptions().timeZone } : null;
|
|
37350
|
+
if (view) void subscribe(view, name, cadence, channel, schedule, quiet2);
|
|
37339
37351
|
},
|
|
37340
37352
|
children: [
|
|
37341
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)) }),
|
|
@@ -46054,4 +46066,88 @@ function Decision({ approvalId, onDecided }) {
|
|
|
46054
46066
|
error ? /* @__PURE__ */ (0, import_jsx_runtime151.jsx)(RefusalLine, { error }) : null
|
|
46055
46067
|
] });
|
|
46056
46068
|
}
|
|
46069
|
+
|
|
46070
|
+
// src/TemplatePreview.tsx
|
|
46071
|
+
var import_react263 = require("react");
|
|
46072
|
+
var import_memory = require("@ai-matrx/records/memory");
|
|
46073
|
+
var import_react264 = require("@ai-matrx/records/react");
|
|
46074
|
+
var import_jsx_runtime152 = require("react/jsx-runtime");
|
|
46075
|
+
function useTemplatePreview(spec, today) {
|
|
46076
|
+
return (0, import_react263.useMemo)(() => (0, import_memory.templatePreview)(spec, today ? { today } : {}), [spec, today]);
|
|
46077
|
+
}
|
|
46078
|
+
function TemplatePreview({ spec, today, initialTable, host, aside, booking, className }) {
|
|
46079
|
+
const preview = useTemplatePreview(spec, today);
|
|
46080
|
+
const bound = (0, import_react263.useMemo)(() => ({ ...host, sayLevelNeeded: false }), [host]);
|
|
46081
|
+
const first = preview.tables.find((t) => t.token === initialTable) ?? preview.tables[0];
|
|
46082
|
+
const [active, setActive] = (0, import_react263.useState)(first?.id ?? null);
|
|
46083
|
+
const table = preview.tables.find((t) => t.id === active) ?? first;
|
|
46084
|
+
if (!table) return null;
|
|
46085
|
+
return /* @__PURE__ */ (0, import_jsx_runtime152.jsxs)("div", { className: ["flex min-w-0 flex-col gap-3", className].filter(Boolean).join(" "), "data-template-preview": preview.tables.length, children: [
|
|
46086
|
+
preview.tables.length > 1 || aside ? /* @__PURE__ */ (0, import_jsx_runtime152.jsxs)("div", { className: "flex min-w-0 flex-wrap items-center gap-1.5", role: "tablist", "aria-label": "Tables", children: [
|
|
46087
|
+
preview.tables.map((t) => /* @__PURE__ */ (0, import_jsx_runtime152.jsxs)(
|
|
46088
|
+
"button",
|
|
46089
|
+
{
|
|
46090
|
+
type: "button",
|
|
46091
|
+
role: "tab",
|
|
46092
|
+
"aria-selected": t.id === table.id,
|
|
46093
|
+
"data-template-preview-table": t.token,
|
|
46094
|
+
onClick: () => setActive(t.id),
|
|
46095
|
+
className: [
|
|
46096
|
+
"inline-flex h-8 items-center gap-1.5 rounded-md border px-3 text-sm",
|
|
46097
|
+
t.id === table.id ? "border-primary bg-primary/10 text-foreground" : "border-border text-muted-foreground hover:text-foreground"
|
|
46098
|
+
].join(" "),
|
|
46099
|
+
children: [
|
|
46100
|
+
t.name,
|
|
46101
|
+
/* @__PURE__ */ (0, import_jsx_runtime152.jsx)("span", { className: "text-xs tabular-nums text-muted-foreground", children: t.rows })
|
|
46102
|
+
]
|
|
46103
|
+
},
|
|
46104
|
+
t.id
|
|
46105
|
+
)),
|
|
46106
|
+
aside ? /* @__PURE__ */ (0, import_jsx_runtime152.jsx)("div", { className: "ml-auto", children: aside }) : null
|
|
46107
|
+
] }) : null,
|
|
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 })
|
|
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
|
|
46151
|
+
] });
|
|
46152
|
+
}
|
|
46057
46153
|
//# sourceMappingURL=index.cjs.map
|