@revisium/schema-toolkit-ui 0.6.2 → 0.6.3

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.cjs CHANGED
@@ -7067,7 +7067,11 @@ function resolveFileRefColumns(child, fieldPath) {
7067
7067
  if (child.isObject()) for (const subField of child.properties()) {
7068
7068
  const subFieldPath = buildFieldPath(fieldPath, subField.name());
7069
7069
  const fieldType = NODE_TYPE_TO_FIELD_TYPE[subField.nodeType()];
7070
- if (fieldType) result.push(createColumn(subFieldPath, subField, fieldType));
7070
+ if (fieldType) {
7071
+ const subCol = createColumn(subFieldPath, subField, fieldType);
7072
+ subCol.parentFileField = fieldPath;
7073
+ result.push(subCol);
7074
+ }
7071
7075
  }
7072
7076
  return result;
7073
7077
  }
@@ -7156,6 +7160,9 @@ var ColumnsModel = class {
7156
7160
  constructor() {
7157
7161
  (0, mobx.makeAutoObservable)(this, {}, { autoBind: true });
7158
7162
  }
7163
+ get allColumns() {
7164
+ return this._allColumns;
7165
+ }
7159
7166
  get visibleColumns() {
7160
7167
  const lookup = this._columnLookup;
7161
7168
  const result = [];
@@ -7588,6 +7595,49 @@ var ColumnsModel = class {
7588
7595
  }
7589
7596
  };
7590
7597
 
7598
+ //#endregion
7599
+ //#region src/table-editor/Columns/model/groupFileFields.ts
7600
+ function isFileFieldGroup(item) {
7601
+ return "parent" in item && "children" in item;
7602
+ }
7603
+ function groupFileFields(columns, allColumns) {
7604
+ const allLookup = allColumns ? new Map(allColumns.map((c) => [c.field, c])) : null;
7605
+ const groups = /* @__PURE__ */ new Map();
7606
+ const result = [];
7607
+ for (const col of columns) if (col.fieldType === FilterFieldType.File) {
7608
+ const existing = groups.get(col.field);
7609
+ if (existing) {
7610
+ existing.parent = col;
7611
+ existing.parentVisible = false;
7612
+ } else {
7613
+ const group = {
7614
+ parent: col,
7615
+ children: [],
7616
+ parentVisible: false
7617
+ };
7618
+ groups.set(col.field, group);
7619
+ result.push(group);
7620
+ }
7621
+ } else if (col.parentFileField) {
7622
+ let group = groups.get(col.parentFileField);
7623
+ if (!group) {
7624
+ const parentCol = allLookup?.get(col.parentFileField);
7625
+ if (parentCol) {
7626
+ group = {
7627
+ parent: parentCol,
7628
+ children: [],
7629
+ parentVisible: true
7630
+ };
7631
+ groups.set(col.parentFileField, group);
7632
+ result.push(group);
7633
+ }
7634
+ }
7635
+ if (group) group.children.push(col);
7636
+ else result.push(col);
7637
+ } else result.push(col);
7638
+ return result;
7639
+ }
7640
+
7591
7641
  //#endregion
7592
7642
  //#region src/table-editor/Filters/model/utils/operators.ts
7593
7643
  let FilterOperator = /* @__PURE__ */ function(FilterOperator) {
@@ -8049,15 +8099,15 @@ function parseValue(value, fieldType) {
8049
8099
  }
8050
8100
  return value;
8051
8101
  }
8052
- function buildOperatorClause(operator, value, fieldType) {
8102
+ function buildOperatorClause(operator, value, fieldType, isSystemField) {
8053
8103
  const parsed = parseValue(value, fieldType);
8054
8104
  switch (operator) {
8055
8105
  case FilterOperator.Equals: return { equals: parsed };
8056
8106
  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 };
8107
+ case FilterOperator.Contains: return isSystemField ? { contains: value } : { string_contains: value };
8108
+ case FilterOperator.NotContains: return isSystemField ? { not: { contains: value } } : { not: { string_contains: value } };
8109
+ case FilterOperator.StartsWith: return isSystemField ? { startsWith: value } : { string_starts_with: value };
8110
+ case FilterOperator.EndsWith: return isSystemField ? { endsWith: value } : { string_ends_with: value };
8061
8111
  case FilterOperator.Gt: return { gt: parsed };
8062
8112
  case FilterOperator.Gte: return { gte: parsed };
8063
8113
  case FilterOperator.Lt: return { lt: parsed };
@@ -8084,8 +8134,9 @@ function buildConditionClause(condition) {
8084
8134
  searchType: condition.searchType || "plain"
8085
8135
  } };
8086
8136
  }
8087
- const opClause = buildOperatorClause(condition.operator, condition.value, condition.fieldType);
8088
- if (SYSTEM_FIELD_IDS.has(condition.field)) return { [condition.field]: opClause };
8137
+ const isSystemField = SYSTEM_FIELD_IDS.has(condition.field);
8138
+ const opClause = buildOperatorClause(condition.operator, condition.value, condition.fieldType, isSystemField);
8139
+ if (isSystemField) return { [condition.field]: opClause };
8089
8140
  return { data: {
8090
8141
  path: stripDataFieldPrefix(condition.field),
8091
8142
  ...opClause
@@ -9254,7 +9305,10 @@ const SearchWidget = (0, mobx_react_lite.observer)(({ model }) => {
9254
9305
  right: "0",
9255
9306
  top: "50%",
9256
9307
  transform: "translateY(-50%)",
9257
- onClick: () => model.clear(),
9308
+ onClick: () => {
9309
+ model.clear();
9310
+ setExpanded(false);
9311
+ },
9258
9312
  color: "gray.400",
9259
9313
  _hover: { color: "black" },
9260
9314
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_pi.PiXBold, {})
@@ -12248,10 +12302,69 @@ const FieldMenuItem = (0, react.memo)(({ field, name, fieldType, valuePrefix, on
12248
12302
  });
12249
12303
  });
12250
12304
 
12305
+ //#endregion
12306
+ //#region src/table-editor/Table/ui/Header/FileFieldSubmenu.tsx
12307
+ const FileFieldSubmenu = ({ group, parentVisible, valuePrefix, onClick }) => {
12308
+ if (group.children.length === 0 && !parentVisible) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldMenuItem, {
12309
+ field: group.parent.field,
12310
+ name: group.parent.label,
12311
+ fieldType: group.parent.fieldType,
12312
+ valuePrefix,
12313
+ onClick
12314
+ });
12315
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Menu.Root, {
12316
+ positioning: {
12317
+ placement: "right-start",
12318
+ gutter: 2
12319
+ },
12320
+ lazyMount: true,
12321
+ unmountOnExit: true,
12322
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Menu.TriggerItem, {
12323
+ "data-testid": `file-group-${group.parent.field}`,
12324
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Box, {
12325
+ display: "flex",
12326
+ alignItems: "center",
12327
+ gap: 2,
12328
+ flex: 1,
12329
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Box, {
12330
+ as: "span",
12331
+ fontSize: "xs",
12332
+ fontWeight: "medium",
12333
+ color: "gray.400",
12334
+ fontFamily: "mono",
12335
+ minWidth: "20px",
12336
+ children: getFieldTypeIcon(group.parent.fieldType)
12337
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Text, {
12338
+ truncate: true,
12339
+ children: group.parent.label
12340
+ })]
12341
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_lu.LuChevronRight, {})]
12342
+ }), /* @__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, {
12343
+ maxH: "300px",
12344
+ minW: "200px",
12345
+ overflowY: "auto",
12346
+ children: [!parentVisible && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldMenuItem, {
12347
+ field: group.parent.field,
12348
+ name: group.parent.label,
12349
+ fieldType: group.parent.fieldType,
12350
+ valuePrefix,
12351
+ onClick
12352
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.Separator, {})] }), group.children.map((col) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldMenuItem, {
12353
+ field: col.field,
12354
+ name: col.label,
12355
+ fieldType: col.fieldType,
12356
+ valuePrefix,
12357
+ onClick
12358
+ }, col.field))]
12359
+ }) }) })]
12360
+ });
12361
+ };
12362
+
12251
12363
  //#endregion
12252
12364
  //#region src/table-editor/Table/ui/Header/InsertColumnSubmenu.tsx
12253
- const InsertColumnSubmenu = ({ label, valuePrefix, availableFields, onSelect }) => {
12365
+ const InsertColumnSubmenu = ({ label, valuePrefix, availableFields, allColumns, onSelect }) => {
12254
12366
  if (availableFields.length === 0) return null;
12367
+ const groupedFields = groupFileFields(availableFields, allColumns);
12255
12368
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Menu.Root, {
12256
12369
  positioning: {
12257
12370
  placement: "right-start",
@@ -12266,13 +12379,18 @@ const InsertColumnSubmenu = ({ label, valuePrefix, availableFields, onSelect })
12266
12379
  maxH: "300px",
12267
12380
  minW: "200px",
12268
12381
  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,
12382
+ children: groupedFields.map((item) => isFileFieldGroup(item) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FileFieldSubmenu, {
12383
+ group: item,
12384
+ parentVisible: item.parentVisible,
12385
+ valuePrefix,
12386
+ onClick: onSelect
12387
+ }, item.parent.field) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldMenuItem, {
12388
+ field: item.field,
12389
+ name: item.label,
12390
+ fieldType: item.fieldType,
12273
12391
  valuePrefix,
12274
12392
  onClick: onSelect
12275
- }, col.field))
12393
+ }, item.field))
12276
12394
  }) }) })]
12277
12395
  });
12278
12396
  };
@@ -12355,12 +12473,14 @@ const ColumnHeaderMenu = (0, mobx_react_lite.observer)(({ column, columnsModel,
12355
12473
  label: "Insert before",
12356
12474
  valuePrefix: "before",
12357
12475
  availableFields: insertableFields,
12476
+ allColumns: columnsModel.allColumns,
12358
12477
  onSelect: handleInsertBefore
12359
12478
  }),
12360
12479
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InsertColumnSubmenu, {
12361
12480
  label: "Insert after",
12362
12481
  valuePrefix: "after",
12363
12482
  availableFields: insertableFields,
12483
+ allColumns: columnsModel.allColumns,
12364
12484
  onSelect: handleInsertAfter
12365
12485
  }),
12366
12486
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.Separator, {})
@@ -12509,6 +12629,7 @@ const AddColumnButton = (0, mobx_react_lite.observer)(({ columnsModel }) => {
12509
12629
  const availableFields = columnsModel.availableFieldsToAdd;
12510
12630
  const availableSystemFields = columnsModel.availableSystemFieldsToAdd;
12511
12631
  if (!columnsModel.hasHiddenColumns) return null;
12632
+ const groupedFields = groupFileFields(availableFields, columnsModel.allColumns);
12512
12633
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Flex, {
12513
12634
  alignItems: "center",
12514
12635
  px: "4px",
@@ -12542,17 +12663,21 @@ const AddColumnButton = (0, mobx_react_lite.observer)(({ columnsModel }) => {
12542
12663
  onClick: columnsModel.addAll,
12543
12664
  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
12665
  }),
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, {
12666
+ 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
12667
  fontWeight: "medium",
12547
12668
  color: "gray.500",
12548
12669
  fontSize: "xs",
12549
12670
  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,
12671
+ }), groupedFields.map((item) => isFileFieldGroup(item) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FileFieldSubmenu, {
12672
+ group: item,
12673
+ parentVisible: item.parentVisible,
12674
+ onClick: columnsModel.showColumn
12675
+ }, item.parent.field) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldMenuItem, {
12676
+ field: item.field,
12677
+ name: item.label,
12678
+ fieldType: item.fieldType,
12554
12679
  onClick: columnsModel.showColumn
12555
- }, col.field))] })] }),
12680
+ }, item.field))] })] }),
12556
12681
  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
12682
  fontWeight: "medium",
12558
12683
  color: "gray.500",
@@ -12927,45 +13052,48 @@ const SelectionToolbar = (0, mobx_react_lite.observer)(({ selection, allRowIds,
12927
13052
  const isAllSelected = selection.isAllSelected(allRowIds);
12928
13053
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.ActionBar.Root, {
12929
13054
  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",
13055
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Portal, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.ActionBar.Positioner, {
13056
+ zIndex: 5,
13057
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.ActionBar.Content, {
13058
+ "data-testid": "selection-toolbar",
13059
+ children: [
13060
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.ActionBar.SelectionTrigger, { children: [selection.selectedCount, " selected"] }),
13061
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.ActionBar.Separator, {}),
13062
+ !isAllSelected && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Button, {
13063
+ variant: "outline",
13064
+ size: "sm",
13065
+ onClick: () => selection.selectAll(allRowIds),
13066
+ "data-testid": "select-all",
13067
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_pi.PiCheckSquare, {}), "Select all"]
13068
+ }),
13069
+ onDuplicate && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Button, {
13070
+ variant: "outline",
12960
13071
  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, {})
13072
+ onClick: () => onDuplicate(selection.selectedIds),
13073
+ "data-testid": "duplicate-selected",
13074
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_lu.LuCopy, {}), "Duplicate"]
13075
+ }),
13076
+ onDelete && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Button, {
13077
+ variant: "outline",
13078
+ size: "sm",
13079
+ onClick: () => onDelete(selection.selectedIds),
13080
+ "data-testid": "delete-selected",
13081
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_lu.LuTrash2, {}), "Delete"]
13082
+ }),
13083
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.ActionBar.CloseTrigger, {
13084
+ asChild: true,
13085
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Button, {
13086
+ variant: "ghost",
13087
+ size: "sm",
13088
+ "aria-label": "Exit selection",
13089
+ onClick: () => selection.exitSelectionMode(),
13090
+ "data-testid": "exit-selection",
13091
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_pi.PiX, {})
13092
+ })
12965
13093
  })
12966
- })
12967
- ]
12968
- }) }) })
13094
+ ]
13095
+ })
13096
+ }) })
12969
13097
  });
12970
13098
  });
12971
13099
 
@@ -14264,6 +14392,8 @@ exports.getDefaultOperator = getDefaultOperator;
14264
14392
  exports.getLabelByRef = getLabelByRef;
14265
14393
  exports.getOperatorLabel = getOperatorLabel;
14266
14394
  exports.getOperatorsForType = getOperatorsForType;
14395
+ exports.groupFileFields = groupFileFields;
14396
+ exports.isFileFieldGroup = isFileFieldGroup;
14267
14397
  exports.operatorRequiresValue = operatorRequiresValue;
14268
14398
  exports.selectDefaultColumns = selectDefaultColumns;
14269
14399
  exports.typeMenuGroups = typeMenuGroups;