@revisium/schema-toolkit-ui 0.6.3 → 0.6.5

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.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as mobx from "mobx";
2
2
  import { comparer, computed, makeAutoObservable, observable, reaction, runInAction, untracked } from "mobx";
3
- import { FIELD_NAME_ERROR_MESSAGE, SchemaParser, SystemSchemaIds, arr, createRowModel, createTableModel, fileSchema, generateDefaultValue, isForeignKeyValueNode, isValidFieldName, jsonPointerToSimplePath, num, obj, rowCreatedAtSchema, rowCreatedIdSchema, rowHashSchema, rowIdSchema, rowPublishedAtSchema, rowSchemaHashSchema, rowUpdatedAtSchema, rowVersionIdSchema, str, validateFormulaAgainstSchema } from "@revisium/schema-toolkit";
3
+ import { FIELD_NAME_ERROR_MESSAGE, SchemaParser, SystemSchemaIds, arr, createRowModel, createSchemaTree, createTableModel, fileSchema, generateDefaultValue, isForeignKeyValueNode, isValidFieldName, jsonPointerToSimplePath, num, obj, rowCreatedAtSchema, rowCreatedIdSchema, rowHashSchema, rowIdSchema, rowPublishedAtSchema, rowSchemaHashSchema, rowUpdatedAtSchema, rowVersionIdSchema, str, validateFormulaAgainstSchema } from "@revisium/schema-toolkit";
4
4
  import { createMobxProvider, setReactivityProvider } from "@revisium/schema-toolkit/core";
5
5
  import { ActionBar, Badge, Box, Button, Checkbox, Flex, HStack, HoverCard, Icon, IconButton, Image, Input, Kbd, Menu, Popover, Portal, SegmentGroup, Spinner, Text, Textarea, Tooltip as Tooltip$1, VStack } from "@chakra-ui/react";
6
6
  import { observer } from "mobx-react-lite";
@@ -5731,21 +5731,25 @@ const Row = ({ node, name, guides, isCollapsible = false, isExpanded = true, onT
5731
5731
  /* @__PURE__ */ jsxs(Flex, {
5732
5732
  width: "100%",
5733
5733
  alignItems: "center",
5734
- children: [/* @__PURE__ */ jsxs(Flex, { children: [
5735
- !skipDot && /* @__PURE__ */ jsx(Dot, {
5736
- isCollapsed,
5737
- isCollapsible,
5738
- toggleCollapsed: onToggle,
5739
- testId
5740
- }),
5741
- !skipField && /* @__PURE__ */ jsx(Field, {
5742
- name,
5743
- formula,
5744
- description,
5745
- isDeprecated
5746
- }),
5747
- children
5748
- ] }), !skipMore && isCollapsed && collapsedLabel && /* @__PURE__ */ jsx(More, {
5734
+ children: [/* @__PURE__ */ jsxs(Flex, {
5735
+ flex: skipDot && skipField ? 1 : void 0,
5736
+ minWidth: 0,
5737
+ children: [
5738
+ !skipDot && /* @__PURE__ */ jsx(Dot, {
5739
+ isCollapsed,
5740
+ isCollapsible,
5741
+ toggleCollapsed: onToggle,
5742
+ testId
5743
+ }),
5744
+ !skipField && /* @__PURE__ */ jsx(Field, {
5745
+ name,
5746
+ formula,
5747
+ description,
5748
+ isDeprecated
5749
+ }),
5750
+ children
5751
+ ]
5752
+ }), !skipMore && isCollapsed && collapsedLabel && /* @__PURE__ */ jsx(More, {
5749
5753
  onClick: onToggle,
5750
5754
  label: collapsedLabel
5751
5755
  })]
@@ -6971,7 +6975,10 @@ var SchemaContext = class {
6971
6975
  const wrapped = wrapDataSchema(dataSchema);
6972
6976
  this._wrappedDataSchema = wrapped;
6973
6977
  const rowSchema = buildRowSchema(wrapped);
6974
- this._rootNode = new SchemaParser().parse(rowSchema, this._fullRefSchemas);
6978
+ const parser = new SchemaParser();
6979
+ this._rootNode = parser.parse(rowSchema, this._fullRefSchemas);
6980
+ const tree = createSchemaTree(this._rootNode);
6981
+ parser.parseFormulas(tree);
6975
6982
  this._allColumns = extractColumns(this._rootNode);
6976
6983
  }
6977
6984
  };
@@ -10407,13 +10414,15 @@ var CellVM = class {
10407
10414
  _cellFSM;
10408
10415
  _onCommit;
10409
10416
  _systemValues;
10410
- constructor(rowModel, column, rowId, cellFSM, onCommit, systemValues) {
10417
+ _readonly;
10418
+ constructor(rowModel, column, rowId, cellFSM, onCommit, systemValues, readonly) {
10411
10419
  this._rowModel = rowModel;
10412
10420
  this._column = column;
10413
10421
  this._rowId = rowId;
10414
10422
  this._cellFSM = cellFSM;
10415
10423
  this._onCommit = onCommit ?? null;
10416
10424
  this._systemValues = systemValues ?? null;
10425
+ this._readonly = readonly ?? false;
10417
10426
  makeAutoObservable(this, { selectionEdges: computed({ equals: comparer.structural }) }, { autoBind: true });
10418
10427
  }
10419
10428
  get field() {
@@ -10450,6 +10459,7 @@ var CellVM = class {
10450
10459
  return "";
10451
10460
  }
10452
10461
  get isReadOnly() {
10462
+ if (this._readonly) return true;
10453
10463
  if (this._systemValues) return true;
10454
10464
  if (this._column.fieldType === FilterFieldType.File) {
10455
10465
  const fileNameNode = this._getFileNameNode();
@@ -10695,14 +10705,16 @@ var RowVM = class {
10695
10705
  _selection;
10696
10706
  _onCellCommit;
10697
10707
  _systemValues;
10708
+ _readonly;
10698
10709
  _cellCache = /* @__PURE__ */ new Map();
10699
- constructor(rowModel, rowId, cellFSM, selection, onCellCommit, systemValues) {
10710
+ constructor(rowModel, rowId, cellFSM, selection, onCellCommit, systemValues, readonly) {
10700
10711
  this._rowModel = rowModel;
10701
10712
  this._rowId = rowId;
10702
10713
  this._cellFSM = cellFSM;
10703
10714
  this._selection = selection;
10704
10715
  this._onCellCommit = onCellCommit ?? null;
10705
10716
  this._systemValues = systemValues ?? {};
10717
+ this._readonly = readonly ?? false;
10706
10718
  makeAutoObservable(this, {}, { autoBind: true });
10707
10719
  }
10708
10720
  get rowId() {
@@ -10720,7 +10732,7 @@ var RowVM = class {
10720
10732
  getCellVM(column) {
10721
10733
  const cached = this._cellCache.get(column.field);
10722
10734
  if (cached) return cached;
10723
- const cell = new CellVM(this._rowModel, column, this._rowId, this._cellFSM, this._onCellCommit ?? void 0, column.isSystem ? this._systemValues : void 0);
10735
+ const cell = new CellVM(this._rowModel, column, this._rowId, this._cellFSM, this._onCellCommit ?? void 0, column.isSystem ? this._systemValues : void 0, this._readonly);
10724
10736
  this._cellCache.set(column.field, cell);
10725
10737
  return cell;
10726
10738
  }
@@ -12153,6 +12165,19 @@ const FilterIndicator = observer(({ field, filterModel }) => {
12153
12165
  });
12154
12166
  });
12155
12167
 
12168
+ //#endregion
12169
+ //#region src/table-editor/Table/ui/Header/FormulaIndicator.tsx
12170
+ const FormulaIndicator = ({ column }) => {
12171
+ if (!column.hasFormula) return null;
12172
+ return /* @__PURE__ */ jsx(Flex, {
12173
+ alignItems: "center",
12174
+ color: "gray.400",
12175
+ flexShrink: 0,
12176
+ "data-testid": `formula-indicator-${column.field}`,
12177
+ children: /* @__PURE__ */ jsx(PiFunction, { size: 12 })
12178
+ });
12179
+ };
12180
+
12156
12181
  //#endregion
12157
12182
  //#region src/table-editor/Table/ui/Header/SortSubmenu.tsx
12158
12183
  const SortSubmenu = observer(({ field, sortModel }) => {
@@ -12421,10 +12446,6 @@ const ColumnHeaderMenu = observer(({ column, columnsModel, sortModel, filterMode
12421
12446
  onClick: handleAddFilter,
12422
12447
  children: [/* @__PURE__ */ jsx(LuFilter, {}), /* @__PURE__ */ jsx(Text, { children: "Add filter" })]
12423
12448
  }), /* @__PURE__ */ jsx(Menu.Separator, {})] }),
12424
- canMove && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(MoveColumnSubmenu, {
12425
- field: column.field,
12426
- columnsModel
12427
- }), /* @__PURE__ */ jsx(Menu.Separator, {})] }),
12428
12449
  isPinned ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Menu.Item, {
12429
12450
  value: "unpin",
12430
12451
  onClick: handleUnpin,
@@ -12442,6 +12463,10 @@ const ColumnHeaderMenu = observer(({ column, columnsModel, sortModel, filterMode
12442
12463
  }),
12443
12464
  (canPinLeft || canPinRight) && /* @__PURE__ */ jsx(Menu.Separator, {})
12444
12465
  ] }),
12466
+ canMove && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(MoveColumnSubmenu, {
12467
+ field: column.field,
12468
+ columnsModel
12469
+ }), /* @__PURE__ */ jsx(Menu.Separator, {})] }),
12445
12470
  hasInsertableFields && /* @__PURE__ */ jsxs(Fragment$1, { children: [
12446
12471
  /* @__PURE__ */ jsx(InsertColumnSubmenu, {
12447
12472
  label: "Insert before",
@@ -12568,6 +12593,7 @@ const ColumnHeader = observer(({ column, columnsModel, sortModel, filterModel, o
12568
12593
  textDecoration: column.isDeprecated ? "line-through" : void 0,
12569
12594
  children: column.label
12570
12595
  }),
12596
+ /* @__PURE__ */ jsx(FormulaIndicator, { column }),
12571
12597
  /* @__PURE__ */ jsx(PinIndicator, {
12572
12598
  field: column.field,
12573
12599
  columnsModel
@@ -12769,8 +12795,12 @@ const RowActionMenuItems = ({ rowId, testIdPrefix, onSelect, onDuplicate, onDele
12769
12795
 
12770
12796
  //#endregion
12771
12797
  //#region src/table-editor/Table/ui/RowActionOverlay.tsx
12772
- const RowActionOverlay = ({ rowId, onOpen, onSelect, onDuplicate, onDelete }) => {
12798
+ const RowActionOverlay = ({ rowId, onOpen, onPick, onSelect, onDuplicate, onDelete }) => {
12773
12799
  const [isMenuOpen, setIsMenuOpen] = useState(false);
12800
+ const primaryAction = onPick ?? onOpen;
12801
+ const primaryIcon = onPick ? PiCheckSquare : PiArrowSquareRightLight;
12802
+ const primaryTestId = onPick ? `row-action-pick-${rowId}` : `row-action-open-${rowId}`;
12803
+ const hasMenuItems = Boolean(onOpen || onSelect || onDuplicate || onDelete);
12774
12804
  return /* @__PURE__ */ jsx(Flex, {
12775
12805
  position: "absolute",
12776
12806
  right: "8px",
@@ -12788,7 +12818,7 @@ const RowActionOverlay = ({ rowId, onOpen, onSelect, onDuplicate, onDelete }) =>
12788
12818
  boxShadow: "0px 2px 8px rgba(0,0,0,0.16)",
12789
12819
  overflow: "hidden",
12790
12820
  "data-testid": `row-action-split-${rowId}`,
12791
- children: [onOpen && /* @__PURE__ */ jsx(Flex, {
12821
+ children: [primaryAction && /* @__PURE__ */ jsx(Flex, {
12792
12822
  alignItems: "center",
12793
12823
  justifyContent: "center",
12794
12824
  height: "100%",
@@ -12798,15 +12828,15 @@ const RowActionOverlay = ({ rowId, onOpen, onSelect, onDuplicate, onDelete }) =>
12798
12828
  _hover: { bg: "gray.100" },
12799
12829
  onClick: (e) => {
12800
12830
  e.stopPropagation();
12801
- onOpen(rowId);
12831
+ primaryAction(rowId);
12802
12832
  },
12803
- "data-testid": `row-action-open-${rowId}`,
12833
+ "data-testid": primaryTestId,
12804
12834
  children: /* @__PURE__ */ jsx(Icon, {
12805
12835
  boxSize: "20px",
12806
12836
  color: "gray.400",
12807
- as: PiArrowSquareRightLight
12837
+ as: primaryIcon
12808
12838
  })
12809
- }), /* @__PURE__ */ jsxs(Menu.Root, {
12839
+ }), hasMenuItems && /* @__PURE__ */ jsxs(Menu.Root, {
12810
12840
  lazyMount: true,
12811
12841
  unmountOnExit: true,
12812
12842
  onOpenChange: ({ open }) => setIsMenuOpen(open),
@@ -12820,7 +12850,7 @@ const RowActionOverlay = ({ rowId, onOpen, onSelect, onDuplicate, onDelete }) =>
12820
12850
  width: "18px",
12821
12851
  minWidth: "18px",
12822
12852
  cursor: "pointer",
12823
- borderLeft: onOpen ? "1px solid" : void 0,
12853
+ borderLeft: primaryAction ? "1px solid" : void 0,
12824
12854
  borderColor: "gray.100",
12825
12855
  _hover: { bg: "gray.100" },
12826
12856
  onClick: (e) => e.stopPropagation(),
@@ -12946,8 +12976,8 @@ function getCellBoxShadow(isSticky, side) {
12946
12976
  if (!isSticky) return BOTTOM_BORDER_SHADOW;
12947
12977
  return `${BOTTOM_BORDER_SHADOW}, ${side === "left" ? `inset -1px 0 0 0 ${CELL_BORDER_COLOR}` : `inset 1px 0 0 0 ${CELL_BORDER_COLOR}`}`;
12948
12978
  }
12949
- const DataRow = observer(({ row, columnsModel, showSelection, onSearchForeignKey, onUploadFile, onOpenFile, onOpenRow, onSelectRow, onDuplicateRow, onDeleteRow }) => {
12950
- const hasRowActions = Boolean(onOpenRow || onSelectRow || onDuplicateRow || onDeleteRow);
12979
+ const DataRow = observer(({ row, columnsModel, showSelection, onSearchForeignKey, onUploadFile, onOpenFile, onOpenRow, onPickRow, onSelectRow, onDuplicateRow, onDeleteRow }) => {
12980
+ const hasRowActions = Boolean(onOpenRow || onPickRow || onSelectRow || onDuplicateRow || onDeleteRow);
12951
12981
  const selectionWidth = showSelection ? SELECTION_COLUMN_WIDTH : 0;
12952
12982
  const addColumnStickyRight = columnsModel.hasHiddenColumns;
12953
12983
  const addColOffset = addColumnStickyRight ? ADD_COLUMN_BUTTON_WIDTH : 0;
@@ -12994,6 +13024,7 @@ const DataRow = observer(({ row, columnsModel, showSelection, onSearchForeignKey
12994
13024
  }), showOverlay && /* @__PURE__ */ jsx(RowActionOverlay, {
12995
13025
  rowId: row.rowId,
12996
13026
  onOpen: onOpenRow,
13027
+ onPick: onPickRow,
12997
13028
  onSelect: onSelectRow,
12998
13029
  onDuplicate: onDuplicateRow,
12999
13030
  onDelete: onDeleteRow
@@ -13284,7 +13315,7 @@ const baseComponents = {
13284
13315
  Table: TableComponent,
13285
13316
  TableRow: TableRowComponent
13286
13317
  };
13287
- const TableWidget = observer(({ rows, columnsModel, cellFSM, selection, sortModel, filterModel, onSearchForeignKey, onUploadFile, onOpenFile, onOpenRow, onDeleteSelected, onDuplicateSelected, onDeleteRow, onDuplicateRow, onCopyPath, onEndReached, isLoadingMore, useWindowScroll: useWindowScrollProp }) => {
13318
+ const TableWidget = observer(({ rows, columnsModel, cellFSM, selection, sortModel, filterModel, onSearchForeignKey, onUploadFile, onOpenFile, onOpenRow, onPickRow, onDeleteSelected, onDuplicateSelected, onDeleteRow, onDuplicateRow, onCopyPath, onEndReached, isLoadingMore, useWindowScroll: useWindowScrollProp }) => {
13288
13319
  const showSelection = selection.isSelectionMode;
13289
13320
  const allRowIds = rows.map((r) => r.rowId);
13290
13321
  const [deleteConfirm, setDeleteConfirm] = useState(null);
@@ -13411,6 +13442,7 @@ const TableWidget = observer(({ rows, columnsModel, cellFSM, selection, sortMode
13411
13442
  onUploadFile,
13412
13443
  onOpenFile,
13413
13444
  onOpenRow,
13445
+ onPickRow,
13414
13446
  onSelectRow: canSelect ? handleSelectRow : void 0,
13415
13447
  onDuplicateRow: canDuplicateRow ? onDuplicateRow : void 0,
13416
13448
  onDeleteRow: canDeleteRow ? handleDeleteRowRequest : void 0
@@ -13421,6 +13453,7 @@ const TableWidget = observer(({ rows, columnsModel, cellFSM, selection, sortMode
13421
13453
  onUploadFile,
13422
13454
  onOpenFile,
13423
13455
  onOpenRow,
13456
+ onPickRow,
13424
13457
  canSelect,
13425
13458
  canDeleteRow,
13426
13459
  canDuplicateRow,
@@ -13729,6 +13762,7 @@ var TableEditorCore = class {
13729
13762
  this._dataSource = dataSource;
13730
13763
  this._tableId = options.tableId;
13731
13764
  this._pageSize = options.pageSize ?? DEFAULT_PAGE_SIZE;
13765
+ this._readonly = options.readonly ?? false;
13732
13766
  this._breadcrumbs = options.breadcrumbs ?? [];
13733
13767
  this._callbacks = options.callbacks ?? {};
13734
13768
  this.columns = new ColumnsModel();
@@ -13825,8 +13859,8 @@ var TableEditorCore = class {
13825
13859
  const meta = await this._dataSource.fetchMetadata();
13826
13860
  runInAction(() => {
13827
13861
  this._schemaContext.init(meta.dataSchema, meta.refSchemas);
13828
- this._readonly = meta.readonly;
13829
- this.viewBadge.setCanSave(!meta.readonly);
13862
+ this._readonly = this._readonly || meta.readonly;
13863
+ this.viewBadge.setCanSave(!this._readonly);
13830
13864
  });
13831
13865
  this.columns.init(this._schemaContext.allColumns);
13832
13866
  this.sorts.init(this._schemaContext.sortableFields);
@@ -13897,7 +13931,7 @@ var TableEditorCore = class {
13897
13931
  });
13898
13932
  const systemValuesMap = /* @__PURE__ */ new Map();
13899
13933
  for (const raw of rawRows) systemValuesMap.set(raw.rowId, this._buildSystemValues(raw));
13900
- return tableModel.rows.map((rowModel) => new RowVM(rowModel, rowModel.rowId, this.cellFSM, this.selection, (rowId, field, value, previousValue) => this._commitCell(rowId, field, value, previousValue), systemValuesMap.get(rowModel.rowId)));
13934
+ return tableModel.rows.map((rowModel) => new RowVM(rowModel, rowModel.rowId, this.cellFSM, this.selection, (rowId, field, value, previousValue) => this._commitCell(rowId, field, value, previousValue), systemValuesMap.get(rowModel.rowId), this._readonly));
13901
13935
  }
13902
13936
  _buildSystemValues(rawRow) {
13903
13937
  return {
@@ -14251,6 +14285,7 @@ const TableEditor = observer(({ viewModel, useWindowScroll }) => {
14251
14285
  isLoadingMore: viewModel.isLoadingMore,
14252
14286
  onEndReached: viewModel.loadMore,
14253
14287
  onOpenRow: callbacks.onOpenRow,
14288
+ onPickRow: callbacks.onPickRow,
14254
14289
  onDeleteRow: isReadonly ? void 0 : (id) => viewModel.deleteRows([id]),
14255
14290
  onDuplicateRow: isReadonly ? void 0 : callbacks.onDuplicateRow,
14256
14291
  onDeleteSelected: isReadonly ? void 0 : (ids) => viewModel.deleteRows(ids),