@ai-matrx/records-ui 0.113.39 → 0.114.1

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,20 @@
1
1
  # Changelog — @ai-matrx/records-ui
2
2
 
3
+ ## 0.114.1
4
+
5
+ Automatic changed-only republish (docs/metadata drift since the last tag — see
6
+ `git diff npm/records-ui/v0.114.0..npm/records-ui/v0.114.1 -- apps/shared/records-ui`).
7
+ No source changes intended and no consumer action required.
8
+
9
+ ## 0.114.0 — a view exports as Markdown (lane FORMULA-2)
10
+
11
+ - **The table page's action list** gains "Download Markdown" (a `.md` file named after the table) and "Copy as Markdown": the rows
12
+ THIS VIEW shows (its filter and sort, to the 5,000-row ceiling, "First N rows only" when cut) in its visible columns, as a pipe table.
13
+ - **The Export rail (`ExportMenu`)** gains "Markdown" and "Copy Markdown" beside CSV and XLSX.
14
+ - Needs `@ai-matrx/records` 0.95.0 (`exportMarkdown`).
15
+ - Tests: `a-view-exports-as-a-markdown-table.test.tsx`.
16
+ - **Consumer action:** none; the host's copy door is `@ai-matrx/kit/clipboard`.
17
+
3
18
  ## 0.113.39
4
19
 
5
20
  Automatic changed-only republish (docs/metadata drift since the last tag — see
package/dist/index.cjs CHANGED
@@ -15920,7 +15920,7 @@ function useMergedGridControls(args) {
15920
15920
  },
15921
15921
  [enabled, fieldOf2, choiceOptions, rows, choiceCounts]
15922
15922
  );
15923
- const copyText14 = (0, import_react90.useCallback)(
15923
+ const copyText16 = (0, import_react90.useCallback)(
15924
15924
  (text, what) => {
15925
15925
  void (0, import_clipboard.copyText)(text).then(
15926
15926
  (landed) => landed ? notify?.success(`${what} ${what.endsWith("cells") ? "are" : "is"} copied.`) : notify?.error("The clipboard refused the copy. Select the cells and press Cmd-C.")
@@ -16040,7 +16040,7 @@ function useMergedGridControls(args) {
16040
16040
  },
16041
16041
  sortedBy: query.sort ? { id: query.sort.id, direction: query.sort.direction } : null,
16042
16042
  actions: {
16043
- copyText: copyText14,
16043
+ copyText: copyText16,
16044
16044
  pasteInto: (rowId, columnId2) => {
16045
16045
  const field2 = fields.find((f) => f.key === columnId2);
16046
16046
  if (!field2) return;
@@ -16109,7 +16109,7 @@ function useMergedGridControls(args) {
16109
16109
  ...hrefForRecord && table ? {
16110
16110
  copyRecordLink: (rowId) => {
16111
16111
  const href = hrefForRecord({ table, recordId: rowId });
16112
- if (href) copyText14(new URL(href, window.location.origin).toString(), "The link");
16112
+ if (href) copyText16(new URL(href, window.location.origin).toString(), "The link");
16113
16113
  }
16114
16114
  } : {},
16115
16115
  ...editable && rights.structure ? {
@@ -16209,7 +16209,7 @@ function useMergedGridControls(args) {
16209
16209
  fieldKeys,
16210
16210
  canWrite,
16211
16211
  client,
16212
- copyText14,
16212
+ copyText16,
16213
16213
  editable,
16214
16214
  editing,
16215
16215
  fields,
@@ -25975,6 +25975,7 @@ function ConnectedRecordsTableCard({
25975
25975
  }
25976
25976
 
25977
25977
  // src/ExportMenu.tsx
25978
+ var import_clipboard3 = require("@ai-matrx/kit/clipboard");
25978
25979
  var import_download2 = require("@ai-matrx/kit/download");
25979
25980
  var import_react133 = require("react");
25980
25981
  var import_react134 = require("@ai-matrx/records/react");
@@ -26156,6 +26157,31 @@ function ExportMenu({ tableId, rows, label, className, view }) {
26156
26157
  children: "XLSX"
26157
26158
  }
26158
26159
  ),
26160
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
26161
+ import_design_system67.Button,
26162
+ {
26163
+ size: "sm",
26164
+ variant: "outline",
26165
+ onClick: () => void exported().then((rows2) => download(`${name}.md`, "text/markdown;charset=utf-8", (0, import_core18.exportMarkdown)(columns, rows2))).catch(
26166
+ (thrown) => setFailure((0, refusals_exports.refusalFromThrown)(thrown, "The Markdown could not be written.", "The CSV beside this button carries the same rows."))
26167
+ ),
26168
+ children: "Markdown"
26169
+ }
26170
+ ),
26171
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
26172
+ import_design_system67.Button,
26173
+ {
26174
+ size: "sm",
26175
+ variant: "outline",
26176
+ onClick: () => void exported().then(async (rows2) => {
26177
+ if (await (0, import_clipboard3.copyText)((0, import_core18.exportMarkdown)(columns, rows2))) host.notify?.success("Markdown copied");
26178
+ else host.notify?.error("Couldn\u2019t copy the Markdown");
26179
+ }).catch(
26180
+ (thrown) => setFailure((0, refusals_exports.refusalFromThrown)(thrown, "The Markdown could not be written.", "The CSV beside this button carries the same rows."))
26181
+ ),
26182
+ children: "Copy Markdown"
26183
+ }
26184
+ ),
26159
26185
  /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
26160
26186
  import_react135.AlchemyMenu,
26161
26187
  {
@@ -26465,14 +26491,14 @@ function fieldsForNewColumns(columns) {
26465
26491
  }
26466
26492
 
26467
26493
  // src/BookingSlots.tsx
26468
- var import_clipboard4 = require("@ai-matrx/kit/clipboard");
26494
+ var import_clipboard5 = require("@ai-matrx/kit/clipboard");
26469
26495
  var import_react143 = require("react");
26470
26496
  var import_react144 = require("@ai-matrx/records/react");
26471
26497
  var import_records48 = require("@ai-matrx/records");
26472
26498
  var import_design_system75 = require("@ai-matrx/design-system");
26473
26499
 
26474
26500
  // src/BookingBuilder.tsx
26475
- var import_clipboard3 = require("@ai-matrx/kit/clipboard");
26501
+ var import_clipboard4 = require("@ai-matrx/kit/clipboard");
26476
26502
  var import_design_system70 = require("@ai-matrx/design-system");
26477
26503
  var import_react139 = require("react");
26478
26504
  var import_react140 = require("@ai-matrx/records/react");
@@ -26949,7 +26975,7 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, startNew, classN
26949
26975
  size: "sm",
26950
26976
  variant: "outline",
26951
26977
  onClick: () => {
26952
- void (0, import_clipboard3.copyText)(url).then((landed) => {
26978
+ void (0, import_clipboard4.copyText)(url).then((landed) => {
26953
26979
  setCopied(landed);
26954
26980
  if (landed) window.setTimeout(() => setCopied(false), 1600);
26955
26981
  });
@@ -27126,7 +27152,7 @@ function tableActions(input) {
27126
27152
  const url = tableLink(table.id, host.origin);
27127
27153
  const favorite = host.isFavorite === true;
27128
27154
  const openInNewTab = host.openInNewTab;
27129
- const copyText14 = host.copyText;
27155
+ const copyText16 = host.copyText;
27130
27156
  const openBuiltOn = host.openBuiltOn;
27131
27157
  const built = [
27132
27158
  action({ id: "open", label: "Open", icon: "folder-open", group: "open", verb: "open" }, "read", input, bind(host.open, table)),
@@ -27140,7 +27166,7 @@ function tableActions(input) {
27140
27166
  { id: "copy-link", label: "Copy link", icon: "link", group: "open", verb: "copy-link" },
27141
27167
  "read",
27142
27168
  input,
27143
- copyText14 ? () => copyText14(url, table) : void 0
27169
+ copyText16 ? () => copyText16(url, table) : void 0
27144
27170
  ),
27145
27171
  action({ id: "rename", label: "Rename\u2026", icon: "pencil", group: "organize", verb: "rename" }, "structure", input, bind(host.rename, table)),
27146
27172
  action({ id: "duplicate", label: "Duplicate", icon: "copy", group: "organize", verb: "duplicate" }, "read", input, bind(host.duplicate, table)),
@@ -27550,7 +27576,7 @@ function BookingSlots({ tableId, activeBookingId, className }) {
27550
27576
  [client, load]
27551
27577
  );
27552
27578
  const copy = (0, import_react143.useCallback)(async (url, formId) => {
27553
- if (await (0, import_clipboard4.copyText)(url)) {
27579
+ if (await (0, import_clipboard5.copyText)(url)) {
27554
27580
  setCopied(formId);
27555
27581
  setShown(null);
27556
27582
  window.setTimeout(() => setCopied(null), 1600);
@@ -30259,7 +30285,7 @@ function RecordFieldsInPlace({
30259
30285
  }
30260
30286
 
30261
30287
  // src/ShareControl.tsx
30262
- var import_clipboard5 = require("@ai-matrx/kit/clipboard");
30288
+ var import_clipboard6 = require("@ai-matrx/kit/clipboard");
30263
30289
  var import_react171 = require("react");
30264
30290
  var import_design_system88 = require("@ai-matrx/design-system");
30265
30291
  var import_jsx_runtime102 = require("react/jsx-runtime");
@@ -30322,7 +30348,7 @@ function ShareForSomebodyElse({
30322
30348
  }) {
30323
30349
  const [copied, setCopied] = (0, import_react171.useState)(null);
30324
30350
  const copy = async () => {
30325
- if (await (0, import_clipboard5.copyText)(window.location.href)) {
30351
+ if (await (0, import_clipboard6.copyText)(window.location.href)) {
30326
30352
  setCopied("yes");
30327
30353
  } else {
30328
30354
  setCopied("no");
@@ -31021,7 +31047,7 @@ function CardDates({ record, fields }) {
31021
31047
  }
31022
31048
 
31023
31049
  // src/RecordActionMenu.tsx
31024
- var import_clipboard6 = require("@ai-matrx/kit/clipboard");
31050
+ var import_clipboard7 = require("@ai-matrx/kit/clipboard");
31025
31051
  var import_react181 = require("react");
31026
31052
  var import_react182 = require("@ai-matrx/records/react");
31027
31053
  var import_design_system92 = require("@ai-matrx/design-system");
@@ -31048,7 +31074,7 @@ function recordActions(input) {
31048
31074
  const origin = (host.origin ?? DEFAULT_ACTION_ORIGIN).replace(/\/+$/, "");
31049
31075
  const url = host.href ? /^https?:/.test(host.href) ? host.href : `${origin}${host.href}` : recordLink(record.tableId, record.id, host.origin);
31050
31076
  const openInNewTab = host.openInNewTab;
31051
- const copyText14 = host.copyText;
31077
+ const copyText16 = host.copyText;
31052
31078
  const built = [
31053
31079
  action2({ id: "open", label: "Open", icon: "folder-open", group: "open", verb: "open" }, "read", input, bind2(host.open, record)),
31054
31080
  action2(
@@ -31061,7 +31087,7 @@ function recordActions(input) {
31061
31087
  { id: "copy-link", label: "Copy link", icon: "link", group: "open", verb: "copy-link" },
31062
31088
  "read",
31063
31089
  input,
31064
- copyText14 ? () => copyText14(url, record) : void 0
31090
+ copyText16 ? () => copyText16(url, record) : void 0
31065
31091
  ),
31066
31092
  action2({ id: "duplicate", label: "Duplicate", icon: "copy", group: "organize", verb: "duplicate" }, "organise", input, bind2(host.duplicate, record)),
31067
31093
  action2(
@@ -31114,7 +31140,7 @@ function useRecordActionHost({ tableId, row, onOpenRecord, onChanged, onMerge })
31114
31140
  window.open(url, "_blank", "noopener,noreferrer");
31115
31141
  },
31116
31142
  copyText: async (url) => {
31117
- if (await (0, import_clipboard6.copyText)(url)) {
31143
+ if (await (0, import_clipboard7.copyText)(url)) {
31118
31144
  said2("Link copied");
31119
31145
  } else {
31120
31146
  notify?.error("Couldn\u2019t copy the link");
@@ -40221,7 +40247,7 @@ function clientNoun(table) {
40221
40247
  }
40222
40248
 
40223
40249
  // src/PortalsPanel.tsx
40224
- var import_clipboard7 = require("@ai-matrx/kit/clipboard");
40250
+ var import_clipboard8 = require("@ai-matrx/kit/clipboard");
40225
40251
  var import_react232 = require("react");
40226
40252
  var import_react233 = require("@ai-matrx/records/react");
40227
40253
  var import_records61 = require("@ai-matrx/records");
@@ -40822,7 +40848,7 @@ function CopyLink({ url, what }) {
40822
40848
  variant: "outline",
40823
40849
  onClick: () => {
40824
40850
  void (async () => {
40825
- if (await (0, import_clipboard7.copyText)(url)) {
40851
+ if (await (0, import_clipboard8.copyText)(url)) {
40826
40852
  setCopied(true);
40827
40853
  setShown(false);
40828
40854
  window.setTimeout(() => setCopied(false), 1600);
@@ -42125,7 +42151,7 @@ function SubscriptionsPanel({ tableId, activeRuleId, className }) {
42125
42151
  }
42126
42152
 
42127
42153
  // src/FormBuilder.tsx
42128
- var import_clipboard9 = require("@ai-matrx/kit/clipboard");
42154
+ var import_clipboard10 = require("@ai-matrx/kit/clipboard");
42129
42155
  var import_design_system123 = require("@ai-matrx/design-system");
42130
42156
  var import_react243 = require("react");
42131
42157
  var import_core21 = require("@dnd-kit/core");
@@ -42138,7 +42164,7 @@ var import_design_system124 = require("@ai-matrx/design-system");
42138
42164
  // src/FormFlowEditor.tsx
42139
42165
  var import_react240 = require("react");
42140
42166
  var import_design_system121 = require("@ai-matrx/design-system");
42141
- var import_clipboard8 = require("@ai-matrx/kit/clipboard");
42167
+ var import_clipboard9 = require("@ai-matrx/kit/clipboard");
42142
42168
  var import_forms = require("@ai-matrx/records/forms");
42143
42169
  var import_jsx_runtime138 = require("react/jsx-runtime");
42144
42170
  function freshEndingId(taken) {
@@ -42353,7 +42379,7 @@ function ThemeEditor({
42353
42379
  }
42354
42380
  var EMBED_LABELS = { inline: "Inline", popup: "Popup", slider: "Slider" };
42355
42381
  function EmbedSnippets({ url, label }) {
42356
- const { copyText: copyText14 } = (0, import_clipboard8.useClipboard)();
42382
+ const { copyText: copyText16 } = (0, import_clipboard9.useClipboard)();
42357
42383
  const [kind, setKind] = (0, import_react240.useState)("inline");
42358
42384
  const [copied, setCopied] = (0, import_react240.useState)(false);
42359
42385
  const snippet = (0, import_forms.formEmbedSnippet)(kind, url, { label });
@@ -42367,7 +42393,7 @@ function EmbedSnippets({ url, label }) {
42367
42393
  size: "sm",
42368
42394
  variant: "outline",
42369
42395
  className: "ml-auto",
42370
- onClick: () => void copyText14(snippet).then((ok) => {
42396
+ onClick: () => void copyText16(snippet).then((ok) => {
42371
42397
  setCopied(Boolean(ok));
42372
42398
  window.setTimeout(() => setCopied(false), 1500);
42373
42399
  }),
@@ -43287,7 +43313,7 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, startWithOne,
43287
43313
  await load();
43288
43314
  }
43289
43315
  async function copyLink(url) {
43290
- if (await (0, import_clipboard9.copyText)(url)) {
43316
+ if (await (0, import_clipboard10.copyText)(url)) {
43291
43317
  setCopied(true);
43292
43318
  setShownUrl(null);
43293
43319
  window.setTimeout(() => setCopied(false), 1600);
@@ -46065,7 +46091,7 @@ function TargetControl({
46065
46091
  }
46066
46092
 
46067
46093
  // src/QuestionPanel.tsx
46068
- var import_clipboard10 = require("@ai-matrx/kit/clipboard");
46094
+ var import_clipboard11 = require("@ai-matrx/kit/clipboard");
46069
46095
  var import_react262 = require("react");
46070
46096
  var import_design_system133 = require("@ai-matrx/design-system");
46071
46097
  var import_react263 = require("@ai-matrx/records/react");
@@ -46236,7 +46262,7 @@ function QuestionPanel({ tableId, activeQuestionId, draft, className }) {
46236
46262
  const url = new URL(window.location.href);
46237
46263
  url.searchParams.set("view", "questions");
46238
46264
  url.searchParams.set("item", current.id);
46239
- void (0, import_clipboard10.copyText)(url.toString());
46265
+ void (0, import_clipboard11.copyText)(url.toString());
46240
46266
  };
46241
46267
  if (fields.loading || hidden === null) {
46242
46268
  return /* @__PURE__ */ (0, import_jsx_runtime150.jsxs)("div", { className: (0, import_design_system133.cn)("flex flex-col gap-2 p-3", className), "data-testid": "question-panel", children: [
@@ -47709,7 +47735,7 @@ function onePerKey3(all) {
47709
47735
  }
47710
47736
 
47711
47737
  // src/FormsPanel.tsx
47712
- var import_clipboard11 = require("@ai-matrx/kit/clipboard");
47738
+ var import_clipboard12 = require("@ai-matrx/kit/clipboard");
47713
47739
  var import_react268 = require("react");
47714
47740
  var import_react269 = require("@ai-matrx/records/react");
47715
47741
  var import_records68 = require("@ai-matrx/records");
@@ -47768,7 +47794,7 @@ function FormsPanel({ tableId, activeFormId, className }) {
47768
47794
  );
47769
47795
  const [shown4, setShown] = (0, import_react268.useState)(null);
47770
47796
  const copy = (0, import_react268.useCallback)(async (url, formId) => {
47771
- if (await (0, import_clipboard11.copyText)(url)) {
47797
+ if (await (0, import_clipboard12.copyText)(url)) {
47772
47798
  setCopied(formId);
47773
47799
  setShown(null);
47774
47800
  window.setTimeout(() => setCopied(null), 1600);
@@ -48727,7 +48753,7 @@ function PublicRow({ row, fields }) {
48727
48753
  }
48728
48754
 
48729
48755
  // src/EmbedFrame.tsx
48730
- var import_clipboard12 = require("@ai-matrx/kit/clipboard");
48756
+ var import_clipboard13 = require("@ai-matrx/kit/clipboard");
48731
48757
  var import_react278 = require("react");
48732
48758
  var import_react279 = require("@ai-matrx/records/react");
48733
48759
  var import_design_system141 = require("@ai-matrx/design-system");
@@ -48825,7 +48851,7 @@ function EmbedFrame({
48825
48851
  {
48826
48852
  size: "sm",
48827
48853
  variant: "outline",
48828
- onClick: () => void (0, import_clipboard12.copyText)(snippet ?? ""),
48854
+ onClick: () => void (0, import_clipboard13.copyText)(snippet ?? ""),
48829
48855
  children: "Copy"
48830
48856
  }
48831
48857
  ),
@@ -48863,7 +48889,7 @@ function useEmbedHandshake(args) {
48863
48889
  }
48864
48890
 
48865
48891
  // src/TablePage.tsx
48866
- var import_clipboard15 = require("@ai-matrx/kit/clipboard");
48892
+ var import_clipboard17 = require("@ai-matrx/kit/clipboard");
48867
48893
  var import_react291 = require("react");
48868
48894
  var import_records70 = require("@ai-matrx/records");
48869
48895
  var import_react292 = require("@ai-matrx/records/react");
@@ -48890,15 +48916,23 @@ function subscribeCalendarAction(args) {
48890
48916
  }
48891
48917
 
48892
48918
  // src/CalendarSubscribe.tsx
48893
- var import_clipboard13 = require("@ai-matrx/kit/clipboard");
48919
+ var import_clipboard14 = require("@ai-matrx/kit/clipboard");
48894
48920
  var import_react281 = require("react");
48921
+
48922
+ // src/asRefusal.ts
48923
+ function asRefusal3(e, fallback) {
48924
+ if (e instanceof Error && e.message.trim() !== "") return e;
48925
+ return { message: fallback };
48926
+ }
48927
+
48928
+ // src/CalendarSubscribe.tsx
48895
48929
  var import_design_system142 = require("@ai-matrx/design-system");
48896
48930
  var import_jsx_runtime159 = require("react/jsx-runtime");
48897
48931
  function CalendarLinkOnce({ url }) {
48898
48932
  const notify = useRecordsUi().notify;
48899
48933
  const [copied, setCopied] = (0, import_react281.useState)(false);
48900
48934
  const copy = async () => {
48901
- if (await (0, import_clipboard13.copyText)(url)) {
48935
+ if (await (0, import_clipboard14.copyText)(url)) {
48902
48936
  setCopied(true);
48903
48937
  notify?.success("Link copied");
48904
48938
  } else notify?.error("Couldn\u2019t copy the link");
@@ -48950,7 +48984,7 @@ function CalendarSubscribeDialog({
48950
48984
  });
48951
48985
  setUrl(port.urlFor(made.token));
48952
48986
  } catch (e) {
48953
- setError(e instanceof Error ? e.message : "The link could not be made");
48987
+ setError(asRefusal3(e, "The link could not be made"));
48954
48988
  } finally {
48955
48989
  setBusy(false);
48956
48990
  }
@@ -48960,21 +48994,13 @@ function CalendarSubscribeDialog({
48960
48994
  /* @__PURE__ */ (0, import_jsx_runtime159.jsx)("p", { className: "text-sm text-muted-foreground", children: "Shows the rows this view shows, read as you." }),
48961
48995
  url ? /* @__PURE__ */ (0, import_jsx_runtime159.jsx)(CalendarLinkOnce, { url }) : /* @__PURE__ */ (0, import_jsx_runtime159.jsxs)("div", { className: "flex flex-col gap-2", children: [
48962
48996
  /* @__PURE__ */ (0, import_jsx_runtime159.jsx)(import_design_system142.Button, { size: "sm", onClick: () => void make(), disabled: busy, "data-calendar-make": "", children: busy ? "Making\u2026" : "Make link" }),
48963
- error ? /* @__PURE__ */ (0, import_jsx_runtime159.jsx)(
48964
- import_design_system142.ErrorBox,
48965
- {
48966
- className: "text-sm text-destructive",
48967
- "data-calendar-error": "",
48968
- message: error,
48969
- operation: "Create a calendar link",
48970
- origin: "records-ui/CalendarSubscribe"
48971
- }
48972
- ) : null
48997
+ error ? /* @__PURE__ */ (0, import_jsx_runtime159.jsx)(RefusalNotice, { error }) : null
48973
48998
  ] })
48974
48999
  ] }) });
48975
49000
  }
48976
49001
 
48977
49002
  // src/viewShare.ts
49003
+ var import_clipboard15 = require("@ai-matrx/kit/clipboard");
48978
49004
  var import_core24 = require("@ai-matrx/records/core");
48979
49005
  var NO_VIEW_REASON = "No saved view yet";
48980
49006
  function viewLink(tableId, viewId, origin) {
@@ -49014,6 +49040,56 @@ async function downloadViewCsv(args) {
49014
49040
  download(`${name}.csv`, "text/csv;charset=utf-8", (0, import_core24.exportCsv)(columns, rows));
49015
49041
  host.notify?.success(read.cut ? cutWords(read.rows.length) : "CSV downloaded");
49016
49042
  }
49043
+ function downloadMarkdownAction(args) {
49044
+ return {
49045
+ id: "download-markdown",
49046
+ label: "Download Markdown",
49047
+ icon: "file-text",
49048
+ group: "share",
49049
+ ...args.disabledReason ? { disabledReason: args.disabledReason } : {},
49050
+ run: args.run
49051
+ };
49052
+ }
49053
+ function copyMarkdownAction(args) {
49054
+ return {
49055
+ id: "copy-markdown",
49056
+ label: "Copy as Markdown",
49057
+ icon: "copy",
49058
+ group: "share",
49059
+ ...args.disabledReason ? { disabledReason: args.disabledReason } : {},
49060
+ run: args.run
49061
+ };
49062
+ }
49063
+ async function readViewMarkdown(args) {
49064
+ const { client, host, tableId, fields, view, labels } = args;
49065
+ const read = await readViewRows(client, tableId, fields, view, args.ceiling);
49066
+ if ("error" in read) return null;
49067
+ const columns = viewColumns(fields, view.presentation);
49068
+ const rows = await rowsForFile({ client, host, fields: columns, records: read.rows, labels });
49069
+ return { markdown: (0, import_core24.exportMarkdown)(columns, rows), cut: read.cut, count: read.rows.length };
49070
+ }
49071
+ async function downloadViewMarkdown(args) {
49072
+ const table = await readViewMarkdown(args);
49073
+ if (!table) {
49074
+ args.host.notify?.error("The Markdown could not be written");
49075
+ return;
49076
+ }
49077
+ const name = fileNameOf(args.tableName) || "records";
49078
+ download(`${name}.md`, "text/markdown;charset=utf-8", table.markdown);
49079
+ args.host.notify?.success(table.cut ? cutWords(table.count) : "Markdown downloaded");
49080
+ }
49081
+ async function copyViewMarkdown(args) {
49082
+ const table = await readViewMarkdown(args);
49083
+ if (!table) {
49084
+ args.host.notify?.error("The Markdown could not be written");
49085
+ return;
49086
+ }
49087
+ if (await (0, import_clipboard15.copyText)(table.markdown)) {
49088
+ args.host.notify?.success(table.cut ? cutWords(table.count) : "Markdown copied");
49089
+ } else {
49090
+ args.host.notify?.error("Couldn\u2019t copy the Markdown");
49091
+ }
49092
+ }
49017
49093
 
49018
49094
  // src/RecordPanel.tsx
49019
49095
  var import_react282 = require("react");
@@ -49164,7 +49240,7 @@ function BreakDownDialog({
49164
49240
  }
49165
49241
 
49166
49242
  // src/TableReference.tsx
49167
- var import_clipboard14 = require("@ai-matrx/kit/clipboard");
49243
+ var import_clipboard16 = require("@ai-matrx/kit/clipboard");
49168
49244
  var import_react285 = require("react");
49169
49245
  var import_workspace2 = require("@ai-matrx/alchemy/react/workspace");
49170
49246
  var import_design_system145 = require("@ai-matrx/design-system");
@@ -49202,7 +49278,7 @@ function TableReferenceDialog({
49202
49278
  async (choice) => {
49203
49279
  if (!port) return;
49204
49280
  try {
49205
- if (!await (0, import_clipboard14.copyText)(await port.build(choice.reference))) throw new Error("clipboard refused");
49281
+ if (!await (0, import_clipboard16.copyText)(await port.build(choice.reference))) throw new Error("clipboard refused");
49206
49282
  setCopied(choice.id);
49207
49283
  notify?.success("Reference copied");
49208
49284
  } catch {
@@ -50441,7 +50517,7 @@ function TablePage({
50441
50517
  viewId: view?.id ?? null,
50442
50518
  origin: actionOrigin,
50443
50519
  copy: async (text) => {
50444
- if (await (0, import_clipboard15.copyText)(text)) {
50520
+ if (await (0, import_clipboard17.copyText)(text)) {
50445
50521
  recordsUi.notify?.success("Link copied");
50446
50522
  } else {
50447
50523
  recordsUi.notify?.error("Couldn\u2019t copy the link");
@@ -50461,6 +50537,30 @@ function TablePage({
50461
50537
  labels: viewLabels
50462
50538
  })
50463
50539
  }),
50540
+ downloadMarkdownAction({
50541
+ ...mayDo.known && !mayDo.read ? { disabledReason: "Needs Viewer access" } : !allFields.data ? { disabledReason: "Reading this table\u2026" } : {},
50542
+ run: () => downloadViewMarkdown({
50543
+ client,
50544
+ host: recordsUi,
50545
+ tableId,
50546
+ tableName: table.data?.name ?? "",
50547
+ fields: allFields.data ?? [],
50548
+ view: viewReading,
50549
+ labels: viewLabels
50550
+ })
50551
+ }),
50552
+ copyMarkdownAction({
50553
+ ...mayDo.known && !mayDo.read ? { disabledReason: "Needs Viewer access" } : !allFields.data ? { disabledReason: "Reading this table\u2026" } : {},
50554
+ run: () => copyViewMarkdown({
50555
+ client,
50556
+ host: recordsUi,
50557
+ tableId,
50558
+ tableName: table.data?.name ?? "",
50559
+ fields: allFields.data ?? [],
50560
+ view: viewReading,
50561
+ labels: viewLabels
50562
+ })
50563
+ }),
50464
50564
  // THE PRIVATE CALENDAR LINK (CAL-FEED-UI): only where the host bound the doors.
50465
50565
  ...recordsUi.calendarFeed && organizationId ? [
50466
50566
  subscribeCalendarAction({
@@ -50474,7 +50574,7 @@ function TablePage({
50474
50574
  window.open(url, "_blank", "noopener,noreferrer");
50475
50575
  },
50476
50576
  copyText: async (url) => {
50477
- if (await (0, import_clipboard15.copyText)(url)) {
50577
+ if (await (0, import_clipboard17.copyText)(url)) {
50478
50578
  recordsUi.notify?.success("Link copied");
50479
50579
  } else {
50480
50580
  recordsUi.notify?.error("Couldn\u2019t copy the link");
@@ -51739,7 +51839,7 @@ function CalendarLinks({ port }) {
51739
51839
  setRows(await port.list());
51740
51840
  setError(null);
51741
51841
  } catch (e) {
51742
- setError(e instanceof Error ? e.message : "The links could not be read");
51842
+ setError(asRefusal3(e, "The links could not be read"));
51743
51843
  }
51744
51844
  }, [port]);
51745
51845
  (0, import_react300.useEffect)(() => {
@@ -51750,21 +51850,12 @@ function CalendarLinks({ port }) {
51750
51850
  await run();
51751
51851
  setError(null);
51752
51852
  } catch (e) {
51753
- setError(e instanceof Error ? e.message : "That didn\u2019t work");
51853
+ setError(asRefusal3(e, "That didn\u2019t work"));
51754
51854
  }
51755
51855
  };
51756
51856
  if (rows === null && !error) return /* @__PURE__ */ (0, import_jsx_runtime172.jsx)("p", { className: "text-sm text-muted-foreground", "data-calendar-links-loading": "", children: "Reading your links\u2026" });
51757
51857
  return /* @__PURE__ */ (0, import_jsx_runtime172.jsxs)("div", { className: "flex flex-col gap-2", "data-calendar-links": "", children: [
51758
- error ? /* @__PURE__ */ (0, import_jsx_runtime172.jsx)(
51759
- import_design_system154.ErrorBox,
51760
- {
51761
- className: "text-sm text-destructive",
51762
- "data-calendar-error": "",
51763
- message: error,
51764
- operation: "Manage calendar links",
51765
- origin: "records-ui/CalendarLinks"
51766
- }
51767
- ) : null,
51858
+ error ? /* @__PURE__ */ (0, import_jsx_runtime172.jsx)(RefusalNotice, { error }) : null,
51768
51859
  rows && rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime172.jsx)("p", { className: "text-sm text-muted-foreground", children: "No calendar links yet." }) : null,
51769
51860
  rows?.map((row) => /* @__PURE__ */ (0, import_jsx_runtime172.jsxs)("div", { className: "flex flex-col gap-2 rounded-md border px-3 py-2", "data-calendar-link-row": row.id, children: [
51770
51861
  /* @__PURE__ */ (0, import_jsx_runtime172.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [