@revisium/schema-toolkit-ui 0.6.2 → 0.6.4

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/README.md CHANGED
@@ -236,6 +236,7 @@ All callbacks are optional and passed via `TableEditorOptions.callbacks`:
236
236
  | `onBreadcrumbClick` | `(segment, index) => void` | Navigate on breadcrumb click |
237
237
  | `onCreateRow` | `() => void` | Create a new row (shows "+" button) |
238
238
  | `onOpenRow` | `(rowId: string) => void` | Navigate to row detail view |
239
+ | `onPickRow` | `(rowId: string) => void` | Pick a row (e.g. foreign key selection). When set, the primary row action becomes "Pick" and the table behaves as read-only |
239
240
  | `onDuplicateRow` | `(rowId: string) => void` | Duplicate a row |
240
241
  | `onSearchForeignKey` | `SearchForeignKeySearchFn` | Foreign key search handler |
241
242
  | `onUploadFile` | `(params: { rowId: string; fileId: string; file: File }) => Promise<Record<string, unknown> \| null>` | Upload a file for a file field |
package/dist/index.cjs CHANGED
@@ -5757,21 +5757,25 @@ const Row = ({ node, name, guides, isCollapsible = false, isExpanded = true, onT
5757
5757
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Flex, {
5758
5758
  width: "100%",
5759
5759
  alignItems: "center",
5760
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Flex, { children: [
5761
- !skipDot && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dot, {
5762
- isCollapsed,
5763
- isCollapsible,
5764
- toggleCollapsed: onToggle,
5765
- testId
5766
- }),
5767
- !skipField && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Field, {
5768
- name,
5769
- formula,
5770
- description,
5771
- isDeprecated
5772
- }),
5773
- children
5774
- ] }), !skipMore && isCollapsed && collapsedLabel && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(More, {
5760
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Flex, {
5761
+ flex: skipDot && skipField ? 1 : void 0,
5762
+ minWidth: 0,
5763
+ children: [
5764
+ !skipDot && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dot, {
5765
+ isCollapsed,
5766
+ isCollapsible,
5767
+ toggleCollapsed: onToggle,
5768
+ testId
5769
+ }),
5770
+ !skipField && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Field, {
5771
+ name,
5772
+ formula,
5773
+ description,
5774
+ isDeprecated
5775
+ }),
5776
+ children
5777
+ ]
5778
+ }), !skipMore && isCollapsed && collapsedLabel && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(More, {
5775
5779
  onClick: onToggle,
5776
5780
  label: collapsedLabel
5777
5781
  })]
@@ -6997,7 +7001,10 @@ var SchemaContext = class {
6997
7001
  const wrapped = wrapDataSchema(dataSchema);
6998
7002
  this._wrappedDataSchema = wrapped;
6999
7003
  const rowSchema = buildRowSchema(wrapped);
7000
- this._rootNode = new _revisium_schema_toolkit.SchemaParser().parse(rowSchema, this._fullRefSchemas);
7004
+ const parser = new _revisium_schema_toolkit.SchemaParser();
7005
+ this._rootNode = parser.parse(rowSchema, this._fullRefSchemas);
7006
+ const tree = (0, _revisium_schema_toolkit.createSchemaTree)(this._rootNode);
7007
+ parser.parseFormulas(tree);
7001
7008
  this._allColumns = extractColumns(this._rootNode);
7002
7009
  }
7003
7010
  };
@@ -7067,7 +7074,11 @@ function resolveFileRefColumns(child, fieldPath) {
7067
7074
  if (child.isObject()) for (const subField of child.properties()) {
7068
7075
  const subFieldPath = buildFieldPath(fieldPath, subField.name());
7069
7076
  const fieldType = NODE_TYPE_TO_FIELD_TYPE[subField.nodeType()];
7070
- if (fieldType) result.push(createColumn(subFieldPath, subField, fieldType));
7077
+ if (fieldType) {
7078
+ const subCol = createColumn(subFieldPath, subField, fieldType);
7079
+ subCol.parentFileField = fieldPath;
7080
+ result.push(subCol);
7081
+ }
7071
7082
  }
7072
7083
  return result;
7073
7084
  }
@@ -7156,6 +7167,9 @@ var ColumnsModel = class {
7156
7167
  constructor() {
7157
7168
  (0, mobx.makeAutoObservable)(this, {}, { autoBind: true });
7158
7169
  }
7170
+ get allColumns() {
7171
+ return this._allColumns;
7172
+ }
7159
7173
  get visibleColumns() {
7160
7174
  const lookup = this._columnLookup;
7161
7175
  const result = [];
@@ -7588,6 +7602,49 @@ var ColumnsModel = class {
7588
7602
  }
7589
7603
  };
7590
7604
 
7605
+ //#endregion
7606
+ //#region src/table-editor/Columns/model/groupFileFields.ts
7607
+ function isFileFieldGroup(item) {
7608
+ return "parent" in item && "children" in item;
7609
+ }
7610
+ function groupFileFields(columns, allColumns) {
7611
+ const allLookup = allColumns ? new Map(allColumns.map((c) => [c.field, c])) : null;
7612
+ const groups = /* @__PURE__ */ new Map();
7613
+ const result = [];
7614
+ for (const col of columns) if (col.fieldType === FilterFieldType.File) {
7615
+ const existing = groups.get(col.field);
7616
+ if (existing) {
7617
+ existing.parent = col;
7618
+ existing.parentVisible = false;
7619
+ } else {
7620
+ const group = {
7621
+ parent: col,
7622
+ children: [],
7623
+ parentVisible: false
7624
+ };
7625
+ groups.set(col.field, group);
7626
+ result.push(group);
7627
+ }
7628
+ } else if (col.parentFileField) {
7629
+ let group = groups.get(col.parentFileField);
7630
+ if (!group) {
7631
+ const parentCol = allLookup?.get(col.parentFileField);
7632
+ if (parentCol) {
7633
+ group = {
7634
+ parent: parentCol,
7635
+ children: [],
7636
+ parentVisible: true
7637
+ };
7638
+ groups.set(col.parentFileField, group);
7639
+ result.push(group);
7640
+ }
7641
+ }
7642
+ if (group) group.children.push(col);
7643
+ else result.push(col);
7644
+ } else result.push(col);
7645
+ return result;
7646
+ }
7647
+
7591
7648
  //#endregion
7592
7649
  //#region src/table-editor/Filters/model/utils/operators.ts
7593
7650
  let FilterOperator = /* @__PURE__ */ function(FilterOperator) {
@@ -8049,15 +8106,15 @@ function parseValue(value, fieldType) {
8049
8106
  }
8050
8107
  return value;
8051
8108
  }
8052
- function buildOperatorClause(operator, value, fieldType) {
8109
+ function buildOperatorClause(operator, value, fieldType, isSystemField) {
8053
8110
  const parsed = parseValue(value, fieldType);
8054
8111
  switch (operator) {
8055
8112
  case FilterOperator.Equals: return { equals: parsed };
8056
8113
  case FilterOperator.NotEquals: return { not: { equals: parsed } };
8057
- case FilterOperator.Contains: return { string_contains: value };
8058
- case FilterOperator.NotContains: return { not: { string_contains: value } };
8059
- case FilterOperator.StartsWith: return { string_starts_with: value };
8060
- case FilterOperator.EndsWith: return { string_ends_with: value };
8114
+ case FilterOperator.Contains: return isSystemField ? { contains: value } : { string_contains: value };
8115
+ case FilterOperator.NotContains: return isSystemField ? { not: { contains: value } } : { not: { string_contains: value } };
8116
+ case FilterOperator.StartsWith: return isSystemField ? { startsWith: value } : { string_starts_with: value };
8117
+ case FilterOperator.EndsWith: return isSystemField ? { endsWith: value } : { string_ends_with: value };
8061
8118
  case FilterOperator.Gt: return { gt: parsed };
8062
8119
  case FilterOperator.Gte: return { gte: parsed };
8063
8120
  case FilterOperator.Lt: return { lt: parsed };
@@ -8084,8 +8141,9 @@ function buildConditionClause(condition) {
8084
8141
  searchType: condition.searchType || "plain"
8085
8142
  } };
8086
8143
  }
8087
- const opClause = buildOperatorClause(condition.operator, condition.value, condition.fieldType);
8088
- if (SYSTEM_FIELD_IDS.has(condition.field)) return { [condition.field]: opClause };
8144
+ const isSystemField = SYSTEM_FIELD_IDS.has(condition.field);
8145
+ const opClause = buildOperatorClause(condition.operator, condition.value, condition.fieldType, isSystemField);
8146
+ if (isSystemField) return { [condition.field]: opClause };
8089
8147
  return { data: {
8090
8148
  path: stripDataFieldPrefix(condition.field),
8091
8149
  ...opClause
@@ -9254,7 +9312,10 @@ const SearchWidget = (0, mobx_react_lite.observer)(({ model }) => {
9254
9312
  right: "0",
9255
9313
  top: "50%",
9256
9314
  transform: "translateY(-50%)",
9257
- onClick: () => model.clear(),
9315
+ onClick: () => {
9316
+ model.clear();
9317
+ setExpanded(false);
9318
+ },
9258
9319
  color: "gray.400",
9259
9320
  _hover: { color: "black" },
9260
9321
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_pi.PiXBold, {})
@@ -12125,6 +12186,19 @@ const FilterIndicator = (0, mobx_react_lite.observer)(({ field, filterModel }) =
12125
12186
  });
12126
12187
  });
12127
12188
 
12189
+ //#endregion
12190
+ //#region src/table-editor/Table/ui/Header/FormulaIndicator.tsx
12191
+ const FormulaIndicator = ({ column }) => {
12192
+ if (!column.hasFormula) return null;
12193
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Flex, {
12194
+ alignItems: "center",
12195
+ color: "gray.400",
12196
+ flexShrink: 0,
12197
+ "data-testid": `formula-indicator-${column.field}`,
12198
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_pi.PiFunction, { size: 12 })
12199
+ });
12200
+ };
12201
+
12128
12202
  //#endregion
12129
12203
  //#region src/table-editor/Table/ui/Header/SortSubmenu.tsx
12130
12204
  const SortSubmenu = (0, mobx_react_lite.observer)(({ field, sortModel }) => {
@@ -12248,10 +12322,69 @@ const FieldMenuItem = (0, react.memo)(({ field, name, fieldType, valuePrefix, on
12248
12322
  });
12249
12323
  });
12250
12324
 
12325
+ //#endregion
12326
+ //#region src/table-editor/Table/ui/Header/FileFieldSubmenu.tsx
12327
+ const FileFieldSubmenu = ({ group, parentVisible, valuePrefix, onClick }) => {
12328
+ if (group.children.length === 0 && !parentVisible) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldMenuItem, {
12329
+ field: group.parent.field,
12330
+ name: group.parent.label,
12331
+ fieldType: group.parent.fieldType,
12332
+ valuePrefix,
12333
+ onClick
12334
+ });
12335
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Menu.Root, {
12336
+ positioning: {
12337
+ placement: "right-start",
12338
+ gutter: 2
12339
+ },
12340
+ lazyMount: true,
12341
+ unmountOnExit: true,
12342
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Menu.TriggerItem, {
12343
+ "data-testid": `file-group-${group.parent.field}`,
12344
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Box, {
12345
+ display: "flex",
12346
+ alignItems: "center",
12347
+ gap: 2,
12348
+ flex: 1,
12349
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Box, {
12350
+ as: "span",
12351
+ fontSize: "xs",
12352
+ fontWeight: "medium",
12353
+ color: "gray.400",
12354
+ fontFamily: "mono",
12355
+ minWidth: "20px",
12356
+ children: getFieldTypeIcon(group.parent.fieldType)
12357
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Text, {
12358
+ truncate: true,
12359
+ children: group.parent.label
12360
+ })]
12361
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_lu.LuChevronRight, {})]
12362
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Portal, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.Positioner, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Menu.Content, {
12363
+ maxH: "300px",
12364
+ minW: "200px",
12365
+ overflowY: "auto",
12366
+ children: [!parentVisible && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldMenuItem, {
12367
+ field: group.parent.field,
12368
+ name: group.parent.label,
12369
+ fieldType: group.parent.fieldType,
12370
+ valuePrefix,
12371
+ onClick
12372
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.Separator, {})] }), group.children.map((col) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldMenuItem, {
12373
+ field: col.field,
12374
+ name: col.label,
12375
+ fieldType: col.fieldType,
12376
+ valuePrefix,
12377
+ onClick
12378
+ }, col.field))]
12379
+ }) }) })]
12380
+ });
12381
+ };
12382
+
12251
12383
  //#endregion
12252
12384
  //#region src/table-editor/Table/ui/Header/InsertColumnSubmenu.tsx
12253
- const InsertColumnSubmenu = ({ label, valuePrefix, availableFields, onSelect }) => {
12385
+ const InsertColumnSubmenu = ({ label, valuePrefix, availableFields, allColumns, onSelect }) => {
12254
12386
  if (availableFields.length === 0) return null;
12387
+ const groupedFields = groupFileFields(availableFields, allColumns);
12255
12388
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Menu.Root, {
12256
12389
  positioning: {
12257
12390
  placement: "right-start",
@@ -12266,13 +12399,18 @@ const InsertColumnSubmenu = ({ label, valuePrefix, availableFields, onSelect })
12266
12399
  maxH: "300px",
12267
12400
  minW: "200px",
12268
12401
  overflowY: "auto",
12269
- children: availableFields.map((col) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldMenuItem, {
12270
- field: col.field,
12271
- name: col.label,
12272
- fieldType: col.fieldType,
12402
+ children: groupedFields.map((item) => isFileFieldGroup(item) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FileFieldSubmenu, {
12403
+ group: item,
12404
+ parentVisible: item.parentVisible,
12273
12405
  valuePrefix,
12274
12406
  onClick: onSelect
12275
- }, col.field))
12407
+ }, item.parent.field) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldMenuItem, {
12408
+ field: item.field,
12409
+ name: item.label,
12410
+ fieldType: item.fieldType,
12411
+ valuePrefix,
12412
+ onClick: onSelect
12413
+ }, item.field))
12276
12414
  }) }) })]
12277
12415
  });
12278
12416
  };
@@ -12329,10 +12467,6 @@ const ColumnHeaderMenu = (0, mobx_react_lite.observer)(({ column, columnsModel,
12329
12467
  onClick: handleAddFilter,
12330
12468
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_lu.LuFilter, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Text, { children: "Add filter" })]
12331
12469
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.Separator, {})] }),
12332
- canMove && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MoveColumnSubmenu, {
12333
- field: column.field,
12334
- columnsModel
12335
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.Separator, {})] }),
12336
12470
  isPinned ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Menu.Item, {
12337
12471
  value: "unpin",
12338
12472
  onClick: handleUnpin,
@@ -12350,17 +12484,23 @@ const ColumnHeaderMenu = (0, mobx_react_lite.observer)(({ column, columnsModel,
12350
12484
  }),
12351
12485
  (canPinLeft || canPinRight) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.Separator, {})
12352
12486
  ] }),
12487
+ canMove && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MoveColumnSubmenu, {
12488
+ field: column.field,
12489
+ columnsModel
12490
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.Separator, {})] }),
12353
12491
  hasInsertableFields && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
12354
12492
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InsertColumnSubmenu, {
12355
12493
  label: "Insert before",
12356
12494
  valuePrefix: "before",
12357
12495
  availableFields: insertableFields,
12496
+ allColumns: columnsModel.allColumns,
12358
12497
  onSelect: handleInsertBefore
12359
12498
  }),
12360
12499
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InsertColumnSubmenu, {
12361
12500
  label: "Insert after",
12362
12501
  valuePrefix: "after",
12363
12502
  availableFields: insertableFields,
12503
+ allColumns: columnsModel.allColumns,
12364
12504
  onSelect: handleInsertAfter
12365
12505
  }),
12366
12506
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.Separator, {})
@@ -12474,6 +12614,7 @@ const ColumnHeader = (0, mobx_react_lite.observer)(({ column, columnsModel, sort
12474
12614
  textDecoration: column.isDeprecated ? "line-through" : void 0,
12475
12615
  children: column.label
12476
12616
  }),
12617
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormulaIndicator, { column }),
12477
12618
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PinIndicator, {
12478
12619
  field: column.field,
12479
12620
  columnsModel
@@ -12509,6 +12650,7 @@ const AddColumnButton = (0, mobx_react_lite.observer)(({ columnsModel }) => {
12509
12650
  const availableFields = columnsModel.availableFieldsToAdd;
12510
12651
  const availableSystemFields = columnsModel.availableSystemFieldsToAdd;
12511
12652
  if (!columnsModel.hasHiddenColumns) return null;
12653
+ const groupedFields = groupFileFields(availableFields, columnsModel.allColumns);
12512
12654
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Flex, {
12513
12655
  alignItems: "center",
12514
12656
  px: "4px",
@@ -12542,17 +12684,21 @@ const AddColumnButton = (0, mobx_react_lite.observer)(({ columnsModel }) => {
12542
12684
  onClick: columnsModel.addAll,
12543
12685
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_pi.PiListBullets, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Text, { children: "Add all columns" })]
12544
12686
  }),
12545
- availableFields.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.Separator, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Menu.ItemGroup, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.ItemGroupLabel, {
12687
+ groupedFields.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.Separator, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Menu.ItemGroup, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.ItemGroupLabel, {
12546
12688
  fontWeight: "medium",
12547
12689
  color: "gray.500",
12548
12690
  fontSize: "xs",
12549
12691
  children: "Data fields"
12550
- }), availableFields.map((col) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldMenuItem, {
12551
- field: col.field,
12552
- name: col.label,
12553
- fieldType: col.fieldType,
12692
+ }), groupedFields.map((item) => isFileFieldGroup(item) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FileFieldSubmenu, {
12693
+ group: item,
12694
+ parentVisible: item.parentVisible,
12554
12695
  onClick: columnsModel.showColumn
12555
- }, col.field))] })] }),
12696
+ }, item.parent.field) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldMenuItem, {
12697
+ field: item.field,
12698
+ name: item.label,
12699
+ fieldType: item.fieldType,
12700
+ onClick: columnsModel.showColumn
12701
+ }, item.field))] })] }),
12556
12702
  availableSystemFields.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.Separator, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Menu.ItemGroup, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.ItemGroupLabel, {
12557
12703
  fontWeight: "medium",
12558
12704
  color: "gray.500",
@@ -12670,8 +12816,12 @@ const RowActionMenuItems = ({ rowId, testIdPrefix, onSelect, onDuplicate, onDele
12670
12816
 
12671
12817
  //#endregion
12672
12818
  //#region src/table-editor/Table/ui/RowActionOverlay.tsx
12673
- const RowActionOverlay = ({ rowId, onOpen, onSelect, onDuplicate, onDelete }) => {
12819
+ const RowActionOverlay = ({ rowId, onOpen, onPick, onSelect, onDuplicate, onDelete }) => {
12674
12820
  const [isMenuOpen, setIsMenuOpen] = (0, react.useState)(false);
12821
+ const primaryAction = onPick ?? onOpen;
12822
+ const primaryIcon = onPick ? react_icons_pi.PiCheckSquare : react_icons_pi.PiArrowSquareRightLight;
12823
+ const primaryTestId = onPick ? `row-action-pick-${rowId}` : `row-action-open-${rowId}`;
12824
+ const hasMenuItems = Boolean(onOpen || onSelect || onDuplicate || onDelete);
12675
12825
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Flex, {
12676
12826
  position: "absolute",
12677
12827
  right: "8px",
@@ -12689,7 +12839,7 @@ const RowActionOverlay = ({ rowId, onOpen, onSelect, onDuplicate, onDelete }) =>
12689
12839
  boxShadow: "0px 2px 8px rgba(0,0,0,0.16)",
12690
12840
  overflow: "hidden",
12691
12841
  "data-testid": `row-action-split-${rowId}`,
12692
- children: [onOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Flex, {
12842
+ children: [primaryAction && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Flex, {
12693
12843
  alignItems: "center",
12694
12844
  justifyContent: "center",
12695
12845
  height: "100%",
@@ -12699,15 +12849,15 @@ const RowActionOverlay = ({ rowId, onOpen, onSelect, onDuplicate, onDelete }) =>
12699
12849
  _hover: { bg: "gray.100" },
12700
12850
  onClick: (e) => {
12701
12851
  e.stopPropagation();
12702
- onOpen(rowId);
12852
+ primaryAction(rowId);
12703
12853
  },
12704
- "data-testid": `row-action-open-${rowId}`,
12854
+ "data-testid": primaryTestId,
12705
12855
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Icon, {
12706
12856
  boxSize: "20px",
12707
12857
  color: "gray.400",
12708
- as: react_icons_pi.PiArrowSquareRightLight
12858
+ as: primaryIcon
12709
12859
  })
12710
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Menu.Root, {
12860
+ }), hasMenuItems && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Menu.Root, {
12711
12861
  lazyMount: true,
12712
12862
  unmountOnExit: true,
12713
12863
  onOpenChange: ({ open }) => setIsMenuOpen(open),
@@ -12721,7 +12871,7 @@ const RowActionOverlay = ({ rowId, onOpen, onSelect, onDuplicate, onDelete }) =>
12721
12871
  width: "18px",
12722
12872
  minWidth: "18px",
12723
12873
  cursor: "pointer",
12724
- borderLeft: onOpen ? "1px solid" : void 0,
12874
+ borderLeft: primaryAction ? "1px solid" : void 0,
12725
12875
  borderColor: "gray.100",
12726
12876
  _hover: { bg: "gray.100" },
12727
12877
  onClick: (e) => e.stopPropagation(),
@@ -12847,8 +12997,8 @@ function getCellBoxShadow(isSticky, side) {
12847
12997
  if (!isSticky) return BOTTOM_BORDER_SHADOW;
12848
12998
  return `${BOTTOM_BORDER_SHADOW}, ${side === "left" ? `inset -1px 0 0 0 ${CELL_BORDER_COLOR}` : `inset 1px 0 0 0 ${CELL_BORDER_COLOR}`}`;
12849
12999
  }
12850
- const DataRow = (0, mobx_react_lite.observer)(({ row, columnsModel, showSelection, onSearchForeignKey, onUploadFile, onOpenFile, onOpenRow, onSelectRow, onDuplicateRow, onDeleteRow }) => {
12851
- const hasRowActions = Boolean(onOpenRow || onSelectRow || onDuplicateRow || onDeleteRow);
13000
+ const DataRow = (0, mobx_react_lite.observer)(({ row, columnsModel, showSelection, onSearchForeignKey, onUploadFile, onOpenFile, onOpenRow, onPickRow, onSelectRow, onDuplicateRow, onDeleteRow }) => {
13001
+ const hasRowActions = Boolean(onOpenRow || onPickRow || onSelectRow || onDuplicateRow || onDeleteRow);
12852
13002
  const selectionWidth = showSelection ? SELECTION_COLUMN_WIDTH : 0;
12853
13003
  const addColumnStickyRight = columnsModel.hasHiddenColumns;
12854
13004
  const addColOffset = addColumnStickyRight ? ADD_COLUMN_BUTTON_WIDTH : 0;
@@ -12895,6 +13045,7 @@ const DataRow = (0, mobx_react_lite.observer)(({ row, columnsModel, showSelectio
12895
13045
  }), showOverlay && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowActionOverlay, {
12896
13046
  rowId: row.rowId,
12897
13047
  onOpen: onOpenRow,
13048
+ onPick: onPickRow,
12898
13049
  onSelect: onSelectRow,
12899
13050
  onDuplicate: onDuplicateRow,
12900
13051
  onDelete: onDeleteRow
@@ -12927,45 +13078,48 @@ const SelectionToolbar = (0, mobx_react_lite.observer)(({ selection, allRowIds,
12927
13078
  const isAllSelected = selection.isAllSelected(allRowIds);
12928
13079
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.ActionBar.Root, {
12929
13080
  open: selection.isSelectionMode,
12930
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Portal, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.ActionBar.Positioner, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.ActionBar.Content, {
12931
- "data-testid": "selection-toolbar",
12932
- children: [
12933
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.ActionBar.SelectionTrigger, { children: [selection.selectedCount, " selected"] }),
12934
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.ActionBar.Separator, {}),
12935
- !isAllSelected && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Button, {
12936
- variant: "outline",
12937
- size: "sm",
12938
- onClick: () => selection.selectAll(allRowIds),
12939
- "data-testid": "select-all",
12940
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_pi.PiCheckSquare, {}), "Select all"]
12941
- }),
12942
- onDuplicate && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Button, {
12943
- variant: "outline",
12944
- size: "sm",
12945
- onClick: () => onDuplicate(selection.selectedIds),
12946
- "data-testid": "duplicate-selected",
12947
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_lu.LuCopy, {}), "Duplicate"]
12948
- }),
12949
- onDelete && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Button, {
12950
- variant: "outline",
12951
- size: "sm",
12952
- onClick: () => onDelete(selection.selectedIds),
12953
- "data-testid": "delete-selected",
12954
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_lu.LuTrash2, {}), "Delete"]
12955
- }),
12956
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.ActionBar.CloseTrigger, {
12957
- asChild: true,
12958
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Button, {
12959
- variant: "ghost",
13081
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Portal, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.ActionBar.Positioner, {
13082
+ zIndex: 5,
13083
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.ActionBar.Content, {
13084
+ "data-testid": "selection-toolbar",
13085
+ children: [
13086
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.ActionBar.SelectionTrigger, { children: [selection.selectedCount, " selected"] }),
13087
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.ActionBar.Separator, {}),
13088
+ !isAllSelected && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Button, {
13089
+ variant: "outline",
12960
13090
  size: "sm",
12961
- "aria-label": "Exit selection",
12962
- onClick: () => selection.exitSelectionMode(),
12963
- "data-testid": "exit-selection",
12964
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_pi.PiX, {})
13091
+ onClick: () => selection.selectAll(allRowIds),
13092
+ "data-testid": "select-all",
13093
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_pi.PiCheckSquare, {}), "Select all"]
13094
+ }),
13095
+ onDuplicate && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Button, {
13096
+ variant: "outline",
13097
+ size: "sm",
13098
+ onClick: () => onDuplicate(selection.selectedIds),
13099
+ "data-testid": "duplicate-selected",
13100
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_lu.LuCopy, {}), "Duplicate"]
13101
+ }),
13102
+ onDelete && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Button, {
13103
+ variant: "outline",
13104
+ size: "sm",
13105
+ onClick: () => onDelete(selection.selectedIds),
13106
+ "data-testid": "delete-selected",
13107
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_lu.LuTrash2, {}), "Delete"]
13108
+ }),
13109
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.ActionBar.CloseTrigger, {
13110
+ asChild: true,
13111
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Button, {
13112
+ variant: "ghost",
13113
+ size: "sm",
13114
+ "aria-label": "Exit selection",
13115
+ onClick: () => selection.exitSelectionMode(),
13116
+ "data-testid": "exit-selection",
13117
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_pi.PiX, {})
13118
+ })
12965
13119
  })
12966
- })
12967
- ]
12968
- }) }) })
13120
+ ]
13121
+ })
13122
+ }) })
12969
13123
  });
12970
13124
  });
12971
13125
 
@@ -13182,7 +13336,7 @@ const baseComponents = {
13182
13336
  Table: TableComponent,
13183
13337
  TableRow: TableRowComponent
13184
13338
  };
13185
- const TableWidget = (0, mobx_react_lite.observer)(({ rows, columnsModel, cellFSM, selection, sortModel, filterModel, onSearchForeignKey, onUploadFile, onOpenFile, onOpenRow, onDeleteSelected, onDuplicateSelected, onDeleteRow, onDuplicateRow, onCopyPath, onEndReached, isLoadingMore, useWindowScroll: useWindowScrollProp }) => {
13339
+ const TableWidget = (0, mobx_react_lite.observer)(({ rows, columnsModel, cellFSM, selection, sortModel, filterModel, onSearchForeignKey, onUploadFile, onOpenFile, onOpenRow, onPickRow, onDeleteSelected, onDuplicateSelected, onDeleteRow, onDuplicateRow, onCopyPath, onEndReached, isLoadingMore, useWindowScroll: useWindowScrollProp }) => {
13186
13340
  const showSelection = selection.isSelectionMode;
13187
13341
  const allRowIds = rows.map((r) => r.rowId);
13188
13342
  const [deleteConfirm, setDeleteConfirm] = (0, react.useState)(null);
@@ -13309,6 +13463,7 @@ const TableWidget = (0, mobx_react_lite.observer)(({ rows, columnsModel, cellFSM
13309
13463
  onUploadFile,
13310
13464
  onOpenFile,
13311
13465
  onOpenRow,
13466
+ onPickRow,
13312
13467
  onSelectRow: canSelect ? handleSelectRow : void 0,
13313
13468
  onDuplicateRow: canDuplicateRow ? onDuplicateRow : void 0,
13314
13469
  onDeleteRow: canDeleteRow ? handleDeleteRowRequest : void 0
@@ -13319,6 +13474,7 @@ const TableWidget = (0, mobx_react_lite.observer)(({ rows, columnsModel, cellFSM
13319
13474
  onUploadFile,
13320
13475
  onOpenFile,
13321
13476
  onOpenRow,
13477
+ onPickRow,
13322
13478
  canSelect,
13323
13479
  canDeleteRow,
13324
13480
  canDuplicateRow,
@@ -14149,6 +14305,7 @@ const TableEditor = (0, mobx_react_lite.observer)(({ viewModel, useWindowScroll
14149
14305
  isLoadingMore: viewModel.isLoadingMore,
14150
14306
  onEndReached: viewModel.loadMore,
14151
14307
  onOpenRow: callbacks.onOpenRow,
14308
+ onPickRow: callbacks.onPickRow,
14152
14309
  onDeleteRow: isReadonly ? void 0 : (id) => viewModel.deleteRows([id]),
14153
14310
  onDuplicateRow: isReadonly ? void 0 : callbacks.onDuplicateRow,
14154
14311
  onDeleteSelected: isReadonly ? void 0 : (ids) => viewModel.deleteRows(ids),
@@ -14264,6 +14421,8 @@ exports.getDefaultOperator = getDefaultOperator;
14264
14421
  exports.getLabelByRef = getLabelByRef;
14265
14422
  exports.getOperatorLabel = getOperatorLabel;
14266
14423
  exports.getOperatorsForType = getOperatorsForType;
14424
+ exports.groupFileFields = groupFileFields;
14425
+ exports.isFileFieldGroup = isFileFieldGroup;
14267
14426
  exports.operatorRequiresValue = operatorRequiresValue;
14268
14427
  exports.selectDefaultColumns = selectDefaultColumns;
14269
14428
  exports.typeMenuGroups = typeMenuGroups;