@arbidocs/blocks 0.4.96 → 0.4.97

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.
Files changed (73) hide show
  1. package/dist/agents/index.cjs +280 -280
  2. package/dist/agents/index.js +4 -4
  3. package/dist/{chunk-3WW32OUU.cjs → chunk-3US5OIDQ.cjs} +3 -3
  4. package/dist/{chunk-3WW32OUU.cjs.map → chunk-3US5OIDQ.cjs.map} +1 -1
  5. package/dist/{chunk-SJVUKXS6.js → chunk-5NQIBJPP.js} +5 -5
  6. package/dist/{chunk-SJVUKXS6.js.map → chunk-5NQIBJPP.js.map} +1 -1
  7. package/dist/chunk-D54JXTPG.cjs +164 -0
  8. package/dist/chunk-D54JXTPG.cjs.map +1 -0
  9. package/dist/{chunk-MROSCSPW.cjs → chunk-DDYXFALG.cjs} +43 -43
  10. package/dist/{chunk-MROSCSPW.cjs.map → chunk-DDYXFALG.cjs.map} +1 -1
  11. package/dist/{chunk-CK6TU76J.cjs → chunk-EHB7J6SR.cjs} +5 -5
  12. package/dist/{chunk-CK6TU76J.cjs.map → chunk-EHB7J6SR.cjs.map} +1 -1
  13. package/dist/{chunk-SC33PQTQ.cjs → chunk-GVOTXXZG.cjs} +5 -5
  14. package/dist/{chunk-SC33PQTQ.cjs.map → chunk-GVOTXXZG.cjs.map} +1 -1
  15. package/dist/{chunk-7RI3G5BO.cjs → chunk-HGJGALLN.cjs} +296 -53
  16. package/dist/chunk-HGJGALLN.cjs.map +1 -0
  17. package/dist/{chunk-PSN4VWI7.cjs → chunk-LENXDIMY.cjs} +5 -5
  18. package/dist/{chunk-PSN4VWI7.cjs.map → chunk-LENXDIMY.cjs.map} +1 -1
  19. package/dist/{chunk-SF4BDUZS.js → chunk-PGDL26TQ.js} +3 -3
  20. package/dist/{chunk-SF4BDUZS.js.map → chunk-PGDL26TQ.js.map} +1 -1
  21. package/dist/{chunk-K27SDLLN.js → chunk-QIEEFBZ5.js} +299 -56
  22. package/dist/chunk-QIEEFBZ5.js.map +1 -0
  23. package/dist/{chunk-Y52CEKVD.js → chunk-RSUOOMPT.js} +3 -3
  24. package/dist/{chunk-Y52CEKVD.js.map → chunk-RSUOOMPT.js.map} +1 -1
  25. package/dist/{chunk-H4SVY5FH.js → chunk-YH6SSJDW.js} +3 -3
  26. package/dist/{chunk-H4SVY5FH.js.map → chunk-YH6SSJDW.js.map} +1 -1
  27. package/dist/{chunk-JID3CZSY.js → chunk-Z3G65XHZ.js} +3 -3
  28. package/dist/{chunk-JID3CZSY.js.map → chunk-Z3G65XHZ.js.map} +1 -1
  29. package/dist/chunk-ZCOVDK2E.js +153 -0
  30. package/dist/chunk-ZCOVDK2E.js.map +1 -0
  31. package/dist/components/DetailPanel.d.ts +106 -0
  32. package/dist/connect/docx.cjs +6 -6
  33. package/dist/connect/docx.js +4 -4
  34. package/dist/connect/index.cjs +25 -25
  35. package/dist/connect/index.js +5 -5
  36. package/dist/databases/DatabaseRowDetail.d.ts +32 -0
  37. package/dist/databases/DatabaseTable.d.ts +3 -1
  38. package/dist/databases/DatabaseToolbar.d.ts +9 -1
  39. package/dist/databases/PickCellEditor.d.ts +8 -1
  40. package/dist/databases/SelectCellEditor.d.ts +6 -1
  41. package/dist/databases/column-types.d.ts +5 -0
  42. package/dist/databases/databaseColumns.d.ts +7 -0
  43. package/dist/databases/index.cjs +381 -11
  44. package/dist/databases/index.cjs.map +1 -1
  45. package/dist/databases/index.d.ts +7 -5
  46. package/dist/databases/index.js +379 -14
  47. package/dist/databases/index.js.map +1 -1
  48. package/dist/databases/linkCells.d.ts +4 -2
  49. package/dist/docx/RibbonMenu.d.ts +15 -0
  50. package/dist/docx/StyleGallery.d.ts +9 -0
  51. package/dist/docx/WordReferences.d.ts +21 -0
  52. package/dist/docx/index.cjs +24 -24
  53. package/dist/docx/index.js +3 -3
  54. package/dist/docx/wordStyles.d.ts +21 -0
  55. package/dist/files/index.cjs +308 -0
  56. package/dist/files/index.cjs.map +1 -1
  57. package/dist/files/index.js +298 -2
  58. package/dist/files/index.js.map +1 -1
  59. package/dist/files/views/gridViews.d.ts +80 -0
  60. package/dist/files/views/index.d.ts +2 -0
  61. package/dist/files/views/useGridViews.d.ts +38 -0
  62. package/dist/index.cjs +428 -428
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.d.ts +1 -0
  65. package/dist/index.js +87 -126
  66. package/dist/index.js.map +1 -1
  67. package/dist/tags/TagDetail.d.ts +1 -0
  68. package/dist/workflow-canvas/index.cjs +47 -47
  69. package/dist/workflow-canvas/index.js +4 -4
  70. package/package.json +4 -4
  71. package/src/docx/styles.css +91 -0
  72. package/dist/chunk-7RI3G5BO.cjs.map +0 -1
  73. package/dist/chunk-K27SDLLN.js.map +0 -1
@@ -1,14 +1,16 @@
1
1
  /**
2
2
  * Databases: user-defined tables (a client database, billing records, a precedent database) in a
3
3
  * Notion/Airtable-style grid. Presentational: the host supplies the data and saves the edits.
4
- * Uses AG Grid (import `@arbidocs/blocks/grid.css`).
4
+ * Uses AG Grid (import `@arbidocs/blocks/grid.css`). A row opens in full in `DatabaseRowDetail` (the
5
+ * shared `DetailPanel`), and the grid's saved views are the Files table's (`useGridViews`).
5
6
  */
6
- export { COMPUTED_COLUMN_TYPES, DATABASE_COLUMN_TYPES, DATABASE_ROLLUP_OPS, DEFAULT_DATABASE_COLUMN_TYPE_LABELS, LINK_COLUMN_TYPES, cellIds, cellList, compareCells, formatCell, formatDateValue, formatLookupValue, formatNumberValue, isComputedColumn, optionTone, sameCellValue, titleOf, toApiValue, type DatabaseColumnType, type DatabaseColumnTypeLabels, type DatabaseColumnView, type DatabaseLookupView, type DatabaseRelationView, type DatabaseRollupOp, type DatabaseRollupView, type DatabaseRowView, type DatabaseSummaryView, } from './column-types';
7
+ export { COMPUTED_COLUMN_TYPES, DATABASE_COLUMN_TYPES, DATABASE_ROLLUP_OPS, DEFAULT_DATABASE_COLUMN_TYPE_LABELS, LINK_COLUMN_TYPES, cellIds, cellList, compareCells, formatCell, formatDateValue, formatLookupValue, formatNumberValue, isComputedColumn, optionTone, rowTitle, sameCellValue, titleOf, toApiValue, type DatabaseColumnType, type DatabaseColumnTypeLabels, type DatabaseColumnView, type DatabaseLookupView, type DatabaseRelationView, type DatabaseRollupOp, type DatabaseRollupView, type DatabaseRowView, type DatabaseSummaryView, } from './column-types';
7
8
  export { LinkChip, LinkChipsCell, LookupCell, PersonCell, PersonChip, type DatabaseCellSources, type DatabasePickOption, } from './linkCells';
8
- export { DEFAULT_PICK_CELL_EDITOR_LABELS, PickCellEditor, type PickCellEditorLabels, type PickCellEditorParams, } from './PickCellEditor';
9
+ export { DEFAULT_PICK_CELL_EDITOR_LABELS, PickCellEditor, type PickCellEditorLabels, type PickCellEditorParams, type PickCellEditorProps, } from './PickCellEditor';
9
10
  export { DEFAULT_COLUMN_CONFIG_LABELS, type ColumnConfigLabels } from './ColumnConfigFields';
10
- export { ADD_COLUMN_COL_ID, COLUMN_TYPE_ICONS, DEFAULT_DATABASE_COLUMN_LABELS, SelectChip, columnWidth, createDatabaseColumns, type DatabaseColumnLabels, type DatabaseColumnOptions, } from './databaseColumns';
11
- export { SelectCellEditor, type SelectCellEditorParams } from './SelectCellEditor';
11
+ export { ADD_COLUMN_COL_ID, COLUMN_TYPE_ICONS, OPEN_ROW_COL_ID, canEditColumn, DEFAULT_DATABASE_COLUMN_LABELS, SelectChip, columnWidth, createDatabaseColumns, type DatabaseColumnLabels, type DatabaseColumnOptions, } from './databaseColumns';
12
+ export { SelectCellEditor, type SelectCellEditorParams, type SelectCellEditorProps, } from './SelectCellEditor';
13
+ export { DatabaseRowDetail, DEFAULT_DATABASE_ROW_DETAIL_LABELS, type DatabaseRowDetailLabels, type DatabaseRowDetailProps, } from './DatabaseRowDetail';
12
14
  export { DatabaseTable, DEFAULT_DATABASE_TABLE_LABELS, type DatabaseTableLabels, type DatabaseTableProps, } from './DatabaseTable';
13
15
  export { DatabaseToolbar, DEFAULT_DATABASE_TOOLBAR_LABELS, type DatabaseExportFormat, type DatabaseToolbarLabels, type DatabaseToolbarProps, } from './DatabaseToolbar';
14
16
  export { DatabaseColumnDialog, DEFAULT_DATABASE_COLUMN_DIALOG_LABELS, type DatabaseColumnDialogLabels, type DatabaseColumnDialogProps, type DatabaseColumnDraft, } from './DatabaseColumnDialog';
@@ -1,10 +1,11 @@
1
1
  "use client";
2
+ import { DetailPanel, DetailSection, DetailFields, DetailField, DetailLinkList, DetailLinkItem, DetailEmpty } from '../chunk-ZCOVDK2E.js';
2
3
  import { GridView } from '../chunk-ZPLG7QYF.js';
3
4
  import '../chunk-SLSBJRWW.js';
4
5
  import { testIdOr } from '../chunk-7F6CBP3Z.js';
5
6
  import '../chunk-VUNV25KB.js';
6
- import { Sigma, Search, ArrowUpRight, FileText, UserRound, ChevronDown, CheckSquare, CalendarDays, Hash, Type, X, Loader2, Check, Plus, ArrowLeft, FileSpreadsheet, Eye, Trash2, MoreHorizontal, Upload, Download, Table2, Lock } from 'lucide-react';
7
- import { cn, Button, Input, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Label, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, DialogFooter, Textarea, Switch } from '@arbidocs/react/ui';
7
+ import { Sigma, Search, ArrowUpRight, FileText, UserRound, ChevronDown, CheckSquare, CalendarDays, Hash, Type, X, Loader2, Check, Maximize2, Plus, Trash2, Rows3, ArrowLeft, FileSpreadsheet, Eye, MoreHorizontal, Upload, Download, Table2, Lock } from 'lucide-react';
8
+ import { cn, Button, Input, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Label, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, DialogFooter, Textarea, Checkbox, Switch, Popover, PopoverTrigger, PopoverContent } from '@arbidocs/react/ui';
8
9
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
9
10
  import { useState, useRef, useEffect, useMemo } from 'react';
10
11
 
@@ -139,6 +140,10 @@ function compareCells(a, b, type, titlesA, titlesB) {
139
140
  const tb = shown ? formatCell(b, type, void 0, titlesB) : String(b);
140
141
  return ta.localeCompare(tb, void 0, { sensitivity: "base", numeric: true });
141
142
  }
143
+ function rowTitle(row, columns, locale) {
144
+ const first = columns[0];
145
+ return first ? formatCell(row.values[first.id], first.type, locale, row.titles) : "";
146
+ }
142
147
  var CHIP = "inline-flex h-[22px] min-w-0 max-w-[14rem] shrink-0 items-center gap-1 rounded-md border border-border bg-muted/50 px-1.5 text-xs text-foreground";
143
148
  function initials(name) {
144
149
  const parts = name.trim().split(/\s+/).filter(Boolean);
@@ -190,8 +195,17 @@ function LinkChip({
190
195
  }
191
196
  );
192
197
  }
193
- function ChipRow({ children }) {
194
- return /* @__PURE__ */ jsx("span", { className: "flex h-full min-w-0 items-center gap-1 overflow-hidden", children });
198
+ function ChipRow({ children, wrap }) {
199
+ return /* @__PURE__ */ jsx(
200
+ "span",
201
+ {
202
+ className: cn(
203
+ "flex min-w-0 items-center gap-1",
204
+ wrap ? "flex-wrap py-0.5" : "h-full overflow-hidden"
205
+ ),
206
+ children
207
+ }
208
+ );
195
209
  }
196
210
  function PersonCell({ value, titles }) {
197
211
  const [id] = cellIds(value);
@@ -201,11 +215,12 @@ function LinkChipsCell({
201
215
  value,
202
216
  titles,
203
217
  kind,
204
- onOpenDocument
218
+ onOpenDocument,
219
+ wrap
205
220
  }) {
206
221
  const ids = cellIds(value);
207
222
  if (ids.length === 0) return null;
208
- return /* @__PURE__ */ jsx(ChipRow, { children: ids.map((id) => /* @__PURE__ */ jsx(
223
+ return /* @__PURE__ */ jsx(ChipRow, { wrap, children: ids.map((id) => /* @__PURE__ */ jsx(
209
224
  LinkChip,
210
225
  {
211
226
  label: titleOf(id, titles),
@@ -219,11 +234,12 @@ function LinkChipsCell({
219
234
  function LookupCell({
220
235
  value,
221
236
  titles,
222
- locale
237
+ locale,
238
+ wrap
223
239
  }) {
224
240
  const values = cellList(value);
225
241
  if (values.length === 0) return null;
226
- return /* @__PURE__ */ jsx(ChipRow, { children: values.map((v, i) => {
242
+ return /* @__PURE__ */ jsx(ChipRow, { wrap, children: values.map((v, i) => {
227
243
  const text = formatLookupValue(v, titles, locale);
228
244
  const key = `${i}-${text}`;
229
245
  if (typeof v === "string" && /^doc-/.test(v))
@@ -492,9 +508,11 @@ function SelectCellEditor(props) {
492
508
  var DEFAULT_DATABASE_COLUMN_LABELS = {
493
509
  addColumn: "Add a column",
494
510
  columnSettings: (name) => `${name} column settings`,
495
- computed: "Computed from a relation (read-only)"
511
+ computed: "Computed from a relation (read-only)",
512
+ openRow: "Open row"
496
513
  };
497
514
  var ADD_COLUMN_COL_ID = "__add_column";
515
+ var OPEN_ROW_COL_ID = "__open_row";
498
516
  var COLUMN_TYPE_ICONS = {
499
517
  text: Type,
500
518
  number: Hash,
@@ -552,7 +570,7 @@ function columnWidth(column) {
552
570
  const header = Math.round(column.name.length * 8) + 76 + (isComputedColumn(column) ? 16 : 0);
553
571
  return Math.min(320, Math.max(WIDTHS[column.type], header));
554
572
  }
555
- function canEdit(column, sources) {
573
+ function canEditColumn(column, sources) {
556
574
  if (isComputedColumn(column)) return false;
557
575
  if (column.type === "person") return Boolean(sources?.members);
558
576
  if (column.type === "document") return Boolean(sources?.documents);
@@ -648,8 +666,43 @@ function rendererFor(column, locale, sources) {
648
666
  }
649
667
  }
650
668
  function createDatabaseColumns(columns, options = {}) {
651
- const { readOnly, onEditColumn, onAddColumn, locale, sources } = options;
669
+ const { readOnly, onEditColumn, onAddColumn, onOpenRow, locale, sources } = options;
652
670
  const l = { ...DEFAULT_DATABASE_COLUMN_LABELS, ...options.labels };
671
+ const openRow = onOpenRow && columns.length > 0 ? [
672
+ {
673
+ colId: OPEN_ROW_COL_ID,
674
+ headerName: "",
675
+ width: 40,
676
+ minWidth: 40,
677
+ maxWidth: 40,
678
+ resizable: false,
679
+ sortable: false,
680
+ editable: false,
681
+ suppressMovable: true,
682
+ // Pinned: the button stays in view however far the table scrolls.
683
+ pinned: "left",
684
+ lockPinned: true,
685
+ lockPosition: "left",
686
+ cellClass: "flex items-center justify-center !px-0",
687
+ valueGetter: () => null,
688
+ cellRenderer: (p) => p.data ? /* @__PURE__ */ jsx(
689
+ "button",
690
+ {
691
+ type: "button",
692
+ "aria-label": l.openRow,
693
+ title: l.openRow,
694
+ "data-testid": `database-open-row-${p.data.id}`,
695
+ onClick: (e) => {
696
+ e.stopPropagation();
697
+ if (p.data) onOpenRow(p.data);
698
+ },
699
+ onDoubleClick: (e) => e.stopPropagation(),
700
+ className: "flex size-6 items-center justify-center rounded text-muted-foreground/70 hover:bg-muted hover:text-foreground",
701
+ children: /* @__PURE__ */ jsx(Maximize2, { className: "size-3.5" })
702
+ }
703
+ ) : null
704
+ }
705
+ ] : [];
653
706
  const defs = columns.map((column) => ({
654
707
  colId: column.id,
655
708
  headerName: column.name,
@@ -657,7 +710,7 @@ function createDatabaseColumns(columns, options = {}) {
657
710
  minWidth: 90,
658
711
  resizable: true,
659
712
  sortable: true,
660
- editable: !readOnly && canEdit(column, sources),
713
+ editable: !readOnly && canEditColumn(column, sources),
661
714
  // The grid's own type inference must not second-guess the database's column type.
662
715
  cellDataType: false,
663
716
  headerComponentParams: {
@@ -687,6 +740,7 @@ function createDatabaseColumns(columns, options = {}) {
687
740
  ...editorFor(column, sources),
688
741
  ...rendererFor(column, locale, sources)
689
742
  }));
743
+ defs.unshift(...openRow);
690
744
  if (!readOnly && onAddColumn) {
691
745
  defs.push({
692
746
  colId: ADD_COLUMN_COL_ID,
@@ -936,6 +990,313 @@ function RollupFields({
936
990
  ] })
937
991
  ] });
938
992
  }
993
+ var DEFAULT_DATABASE_ROW_DETAIL_LABELS = {
994
+ untitled: "Untitled",
995
+ fields: "Fields",
996
+ documents: "Linked documents",
997
+ noDocuments: "No document is linked to this row.",
998
+ empty: "Empty",
999
+ deleteRow: "Delete row",
1000
+ close: "Close",
1001
+ computed: "Computed from a relation"
1002
+ };
1003
+ function DraftInput({
1004
+ value,
1005
+ type,
1006
+ onCommit,
1007
+ testId,
1008
+ label
1009
+ }) {
1010
+ const [draft, setDraft] = useState(value);
1011
+ useEffect(() => setDraft(value), [value]);
1012
+ return /* @__PURE__ */ jsx(
1013
+ Input,
1014
+ {
1015
+ type,
1016
+ value: draft,
1017
+ "aria-label": label,
1018
+ onChange: (e) => setDraft(e.target.value),
1019
+ onBlur: () => draft !== value && onCommit(draft),
1020
+ onKeyDown: (e) => {
1021
+ if (e.key === "Enter") e.currentTarget.blur();
1022
+ if (e.key === "Escape") {
1023
+ setDraft(value);
1024
+ requestAnimationFrame(() => e.target.blur());
1025
+ }
1026
+ },
1027
+ className: "h-8",
1028
+ "data-testid": testId
1029
+ }
1030
+ );
1031
+ }
1032
+ function PopoverField({
1033
+ display,
1034
+ emptyLabel,
1035
+ testId,
1036
+ label,
1037
+ renderEditor,
1038
+ onCommit
1039
+ }) {
1040
+ const [open, setOpen] = useState(false);
1041
+ const pending = useRef(null);
1042
+ const cancelled = useRef(false);
1043
+ const close = (keep) => {
1044
+ setOpen(false);
1045
+ const change = pending.current;
1046
+ pending.current = null;
1047
+ if (change && !cancelled.current) onCommit(change.value);
1048
+ cancelled.current = false;
1049
+ };
1050
+ return /* @__PURE__ */ jsxs(
1051
+ Popover,
1052
+ {
1053
+ open,
1054
+ onOpenChange: (next) => {
1055
+ if (next) {
1056
+ pending.current = null;
1057
+ cancelled.current = false;
1058
+ setOpen(true);
1059
+ } else close();
1060
+ },
1061
+ children: [
1062
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
1063
+ "div",
1064
+ {
1065
+ role: "button",
1066
+ tabIndex: 0,
1067
+ "aria-label": label,
1068
+ "aria-haspopup": "dialog",
1069
+ onKeyDown: (e) => {
1070
+ if (e.target === e.currentTarget && (e.key === "Enter" || e.key === " ")) {
1071
+ e.preventDefault();
1072
+ setOpen(true);
1073
+ }
1074
+ },
1075
+ className: "flex min-h-8 w-full min-w-0 cursor-pointer items-center rounded-md border border-input bg-transparent px-2 py-1 text-left text-sm outline-none hover:bg-muted/50 focus-visible:ring-2 focus-visible:ring-ring",
1076
+ "data-testid": testId,
1077
+ children: display ?? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: emptyLabel })
1078
+ }
1079
+ ) }),
1080
+ /* @__PURE__ */ jsx(
1081
+ PopoverContent,
1082
+ {
1083
+ align: "start",
1084
+ className: "w-auto border-0 bg-transparent p-0 shadow-none",
1085
+ onEscapeKeyDown: () => {
1086
+ cancelled.current = true;
1087
+ },
1088
+ children: renderEditor({
1089
+ onValueChange: (value) => {
1090
+ pending.current = { value };
1091
+ },
1092
+ stopEditing: () => close()
1093
+ })
1094
+ }
1095
+ )
1096
+ ]
1097
+ }
1098
+ );
1099
+ }
1100
+ function DatabaseRowDetail({
1101
+ row,
1102
+ columns,
1103
+ onChange,
1104
+ sources,
1105
+ onDelete,
1106
+ onClose,
1107
+ readOnly = false,
1108
+ locale,
1109
+ labels,
1110
+ className,
1111
+ testId = "database-row-detail"
1112
+ }) {
1113
+ const l = { ...DEFAULT_DATABASE_ROW_DETAIL_LABELS, ...labels };
1114
+ const title = row ? rowTitle(row, columns, locale) || l.untitled : "";
1115
+ const commit = (column, value) => {
1116
+ if (!row || !onChange) return;
1117
+ const next = toApiValue(value, column.type);
1118
+ if (sameCellValue(next, row.values[column.id])) return;
1119
+ onChange(row, column.id, next);
1120
+ };
1121
+ const fieldEditor = (column) => {
1122
+ if (!row) return null;
1123
+ const value = row.values[column.id];
1124
+ const id = `${testId}-input-${column.id}`;
1125
+ const editable = !readOnly && Boolean(onChange) && canEditColumn(column, sources);
1126
+ const display = () => {
1127
+ switch (column.type) {
1128
+ case "select":
1129
+ return typeof value === "string" && value ? /* @__PURE__ */ jsx(SelectChip, { value }) : null;
1130
+ case "person":
1131
+ return cellIds(value).length ? /* @__PURE__ */ jsx(PersonCell, { value, titles: row.titles }) : null;
1132
+ case "document":
1133
+ case "relation":
1134
+ return cellIds(value).length ? /* @__PURE__ */ jsx(
1135
+ LinkChipsCell,
1136
+ {
1137
+ value,
1138
+ titles: row.titles,
1139
+ kind: column.type,
1140
+ onOpenDocument: sources?.onOpenDocument,
1141
+ wrap: true
1142
+ }
1143
+ ) : null;
1144
+ case "lookup":
1145
+ return /* @__PURE__ */ jsx(LookupCell, { value, titles: row.titles, locale, wrap: true });
1146
+ default: {
1147
+ const text = formatCell(value, column.type, locale, row.titles);
1148
+ return text ? /* @__PURE__ */ jsx("span", { className: "break-words", children: text }) : null;
1149
+ }
1150
+ }
1151
+ };
1152
+ if (!editable) {
1153
+ const shown = display();
1154
+ return /* @__PURE__ */ jsx(
1155
+ "div",
1156
+ {
1157
+ className: cn(
1158
+ "flex min-h-8 min-w-0 items-center py-1 text-sm",
1159
+ isComputedColumn(column) && "text-muted-foreground"
1160
+ ),
1161
+ title: isComputedColumn(column) ? l.computed : void 0,
1162
+ "data-testid": id,
1163
+ children: shown ?? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "\u2014" })
1164
+ }
1165
+ );
1166
+ }
1167
+ switch (column.type) {
1168
+ case "checkbox":
1169
+ return /* @__PURE__ */ jsx("div", { className: "flex min-h-8 items-center", children: /* @__PURE__ */ jsx(
1170
+ Checkbox,
1171
+ {
1172
+ checked: value === true,
1173
+ "aria-label": column.name,
1174
+ onCheckedChange: (checked) => commit(column, checked === true),
1175
+ "data-testid": id
1176
+ }
1177
+ ) });
1178
+ case "number":
1179
+ case "date":
1180
+ case "text": {
1181
+ const text = value == null ? "" : column.type === "date" ? String(value).slice(0, 10) : String(value);
1182
+ return /* @__PURE__ */ jsx(
1183
+ DraftInput,
1184
+ {
1185
+ value: text,
1186
+ type: column.type,
1187
+ label: column.name,
1188
+ onCommit: (next) => commit(column, next),
1189
+ testId: id
1190
+ }
1191
+ );
1192
+ }
1193
+ case "select":
1194
+ return /* @__PURE__ */ jsx(
1195
+ PopoverField,
1196
+ {
1197
+ display: display(),
1198
+ emptyLabel: l.empty,
1199
+ label: column.name,
1200
+ testId: id,
1201
+ onCommit: (next) => commit(column, next),
1202
+ renderEditor: (editor) => /* @__PURE__ */ jsx(SelectCellEditor, { ...editor, value, options: column.options ?? [] })
1203
+ }
1204
+ );
1205
+ case "person":
1206
+ case "document":
1207
+ case "relation": {
1208
+ const target = column.relation?.database_id;
1209
+ const searchRows = sources?.searchRows;
1210
+ return /* @__PURE__ */ jsx(
1211
+ PopoverField,
1212
+ {
1213
+ display: display(),
1214
+ emptyLabel: l.empty,
1215
+ label: column.name,
1216
+ testId: id,
1217
+ onCommit: (next) => commit(column, next),
1218
+ renderEditor: (editor) => /* @__PURE__ */ jsx(
1219
+ PickCellEditor,
1220
+ {
1221
+ ...editor,
1222
+ value,
1223
+ data: row,
1224
+ kind: column.type,
1225
+ options: column.type === "person" ? sources?.members : column.type === "document" ? sources?.documents : void 0,
1226
+ search: column.type === "relation" && target && searchRows ? (q) => searchRows(target, q) : void 0
1227
+ }
1228
+ )
1229
+ }
1230
+ );
1231
+ }
1232
+ default:
1233
+ return null;
1234
+ }
1235
+ };
1236
+ const documents = /* @__PURE__ */ new Map();
1237
+ if (row) {
1238
+ for (const column of columns) {
1239
+ if (column.type !== "document") continue;
1240
+ for (const id of cellIds(row.values[column.id])) {
1241
+ documents.set(id, [...documents.get(id) ?? [], column.name]);
1242
+ }
1243
+ }
1244
+ }
1245
+ const openDocument = sources?.onOpenDocument;
1246
+ return /* @__PURE__ */ jsxs(
1247
+ DetailPanel,
1248
+ {
1249
+ title,
1250
+ icon: /* @__PURE__ */ jsx(Rows3, { className: "size-4" }),
1251
+ isLoading: !row,
1252
+ onClose,
1253
+ labels: { close: l.close },
1254
+ className,
1255
+ testId,
1256
+ actions: row && onDelete && !readOnly ? /* @__PURE__ */ jsx(
1257
+ Button,
1258
+ {
1259
+ variant: "ghost",
1260
+ size: "icon",
1261
+ className: "size-8 text-red-text",
1262
+ onClick: () => onDelete(row),
1263
+ "aria-label": l.deleteRow,
1264
+ title: l.deleteRow,
1265
+ "data-testid": `${testId}-delete`,
1266
+ children: /* @__PURE__ */ jsx(Trash2, { className: "size-4" })
1267
+ }
1268
+ ) : void 0,
1269
+ children: [
1270
+ /* @__PURE__ */ jsx(DetailSection, { title: l.fields, testId: `${testId}-fields`, children: /* @__PURE__ */ jsx(DetailFields, { children: columns.map((column) => {
1271
+ const Icon = COLUMN_TYPE_ICONS[column.type];
1272
+ return /* @__PURE__ */ jsx(
1273
+ DetailField,
1274
+ {
1275
+ label: column.name,
1276
+ icon: Icon ? /* @__PURE__ */ jsx(Icon, { className: "size-3.5" }) : void 0,
1277
+ testId: `${testId}-field-${column.id}`,
1278
+ children: fieldEditor(column)
1279
+ },
1280
+ column.id
1281
+ );
1282
+ }) }) }),
1283
+ columns.some((c) => c.type === "document") && /* @__PURE__ */ jsx(DetailSection, { title: l.documents, count: documents.size, testId: `${testId}-documents`, children: documents.size ? /* @__PURE__ */ jsx(DetailLinkList, { children: [...documents].map(([id, via]) => /* @__PURE__ */ jsx(
1284
+ DetailLinkItem,
1285
+ {
1286
+ icon: /* @__PURE__ */ jsx(FileText, { className: "size-4" }),
1287
+ onClick: openDocument ? () => openDocument(id) : void 0,
1288
+ testId: `${testId}-doc-${id}`,
1289
+ children: /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
1290
+ /* @__PURE__ */ jsx("span", { className: "block truncate font-medium", children: titleOf(id, row?.titles) }),
1291
+ /* @__PURE__ */ jsx("span", { className: "block truncate text-xs text-muted-foreground", children: via.join(", ") })
1292
+ ] })
1293
+ },
1294
+ id
1295
+ )) }) : /* @__PURE__ */ jsx(DetailEmpty, { children: l.noDocuments }) })
1296
+ ]
1297
+ }
1298
+ );
1299
+ }
939
1300
  var escapeHtml = (text) => text.replace(/[&<>"']/g, (ch) => `&#${ch.charCodeAt(0)};`);
940
1301
  var DEFAULT_DATABASE_TABLE_LABELS = {
941
1302
  newRow: "New row",
@@ -952,6 +1313,7 @@ function DatabaseTable({
952
1313
  onAddRow,
953
1314
  onAddColumn,
954
1315
  onEditColumn,
1316
+ onOpenRow,
955
1317
  sources,
956
1318
  onSelectionChange,
957
1319
  selected,
@@ -972,11 +1334,12 @@ function DatabaseTable({
972
1334
  readOnly,
973
1335
  onEditColumn,
974
1336
  onAddColumn,
1337
+ onOpenRow,
975
1338
  sources,
976
1339
  locale,
977
1340
  labels: columnLabels
978
1341
  }),
979
- [columns, readOnly, onEditColumn, onAddColumn, sources, locale, columnLabels]
1342
+ [columns, readOnly, onEditColumn, onAddColumn, onOpenRow, sources, locale, columnLabels]
980
1343
  );
981
1344
  const noColumns = columns.length === 0;
982
1345
  const emptyState = {
@@ -1092,6 +1455,7 @@ function DatabaseToolbar({
1092
1455
  onExport,
1093
1456
  onDeleteDatabase,
1094
1457
  readOnly = false,
1458
+ views,
1095
1459
  labels
1096
1460
  }) {
1097
1461
  const l = { ...DEFAULT_DATABASE_TOOLBAR_LABELS, ...labels };
@@ -1182,6 +1546,7 @@ function DatabaseToolbar({
1182
1546
  )
1183
1547
  ] }),
1184
1548
  /* @__PURE__ */ jsx("span", { className: "flex-1" }),
1549
+ views,
1185
1550
  !readOnly && selectedCount > 0 && onDeleteSelected && /* @__PURE__ */ jsxs(
1186
1551
  Button,
1187
1552
  {
@@ -1764,6 +2129,6 @@ function NewDatabaseDialog({
1764
2129
  ] }) }) });
1765
2130
  }
1766
2131
 
1767
- export { ADD_COLUMN_COL_ID, COLUMN_TYPE_ICONS, COMPUTED_COLUMN_TYPES, DATABASE_COLUMN_TYPES, DATABASE_ROLLUP_OPS, DEFAULT_COLUMN_CONFIG_LABELS, DEFAULT_DATABASE_COLUMN_DIALOG_LABELS, DEFAULT_DATABASE_COLUMN_LABELS, DEFAULT_DATABASE_COLUMN_TYPE_LABELS, DEFAULT_DATABASE_LIST_LABELS, DEFAULT_DATABASE_TABLE_LABELS, DEFAULT_DATABASE_TOOLBAR_LABELS, DEFAULT_NEW_DATABASE_DIALOG_LABELS, DEFAULT_PICK_CELL_EDITOR_LABELS, DatabaseColumnDialog, DatabaseList, DatabaseTable, DatabaseToolbar, LINK_COLUMN_TYPES, LinkChip, LinkChipsCell, LookupCell, NewDatabaseDialog, PersonCell, PersonChip, PickCellEditor, SelectCellEditor, SelectChip, cellIds, cellList, columnWidth, compareCells, createDatabaseColumns, formatCell, formatDateValue, formatLookupValue, formatNumberValue, isComputedColumn, optionTone, sameCellValue, titleOf, toApiValue };
2132
+ export { ADD_COLUMN_COL_ID, COLUMN_TYPE_ICONS, COMPUTED_COLUMN_TYPES, DATABASE_COLUMN_TYPES, DATABASE_ROLLUP_OPS, DEFAULT_COLUMN_CONFIG_LABELS, DEFAULT_DATABASE_COLUMN_DIALOG_LABELS, DEFAULT_DATABASE_COLUMN_LABELS, DEFAULT_DATABASE_COLUMN_TYPE_LABELS, DEFAULT_DATABASE_LIST_LABELS, DEFAULT_DATABASE_ROW_DETAIL_LABELS, DEFAULT_DATABASE_TABLE_LABELS, DEFAULT_DATABASE_TOOLBAR_LABELS, DEFAULT_NEW_DATABASE_DIALOG_LABELS, DEFAULT_PICK_CELL_EDITOR_LABELS, DatabaseColumnDialog, DatabaseList, DatabaseRowDetail, DatabaseTable, DatabaseToolbar, LINK_COLUMN_TYPES, LinkChip, LinkChipsCell, LookupCell, NewDatabaseDialog, OPEN_ROW_COL_ID, PersonCell, PersonChip, PickCellEditor, SelectCellEditor, SelectChip, canEditColumn, cellIds, cellList, columnWidth, compareCells, createDatabaseColumns, formatCell, formatDateValue, formatLookupValue, formatNumberValue, isComputedColumn, optionTone, rowTitle, sameCellValue, titleOf, toApiValue };
1768
2133
  //# sourceMappingURL=index.js.map
1769
2134
  //# sourceMappingURL=index.js.map