@revisium/schema-toolkit-ui 0.6.1 → 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.mjs CHANGED
@@ -6894,6 +6894,88 @@ const SYSTEM_FIELD_IDS = new Set([
6894
6894
  "schemaHash"
6895
6895
  ]);
6896
6896
 
6897
+ //#endregion
6898
+ //#region src/table-editor/TableEditor/model/SchemaContext.ts
6899
+ const DATA_FIELD = "data";
6900
+ function stripDataFieldPrefix(field) {
6901
+ const prefix = `${DATA_FIELD}.`;
6902
+ if (field.startsWith(prefix)) return field.slice(prefix.length);
6903
+ if (field === DATA_FIELD) return "";
6904
+ return field;
6905
+ }
6906
+ const SYSTEM_REF_SCHEMAS = {
6907
+ [SystemSchemaIds.File]: fileSchema,
6908
+ [SystemSchemaIds.RowId]: rowIdSchema,
6909
+ [SystemSchemaIds.RowCreatedAt]: rowCreatedAtSchema,
6910
+ [SystemSchemaIds.RowCreatedId]: rowCreatedIdSchema,
6911
+ [SystemSchemaIds.RowVersionId]: rowVersionIdSchema,
6912
+ [SystemSchemaIds.RowPublishedAt]: rowPublishedAtSchema,
6913
+ [SystemSchemaIds.RowUpdatedAt]: rowUpdatedAtSchema,
6914
+ [SystemSchemaIds.RowHash]: rowHashSchema,
6915
+ [SystemSchemaIds.RowSchemaHash]: rowSchemaHashSchema
6916
+ };
6917
+ function wrapDataSchema(dataSchema) {
6918
+ return {
6919
+ type: "object",
6920
+ properties: { [DATA_FIELD]: dataSchema },
6921
+ additionalProperties: false,
6922
+ required: [DATA_FIELD]
6923
+ };
6924
+ }
6925
+ function buildRowSchema(wrappedDataSchema) {
6926
+ const systemProperties = {};
6927
+ for (const sf of SYSTEM_FIELDS) systemProperties[sf.id] = { $ref: sf.ref };
6928
+ return {
6929
+ type: "object",
6930
+ properties: {
6931
+ ...systemProperties,
6932
+ ...wrappedDataSchema.properties
6933
+ },
6934
+ additionalProperties: false,
6935
+ required: [...Object.keys(systemProperties), ...wrappedDataSchema.required]
6936
+ };
6937
+ }
6938
+ var SchemaContext = class {
6939
+ _allColumns = [];
6940
+ _dataSchema = null;
6941
+ _wrappedDataSchema = null;
6942
+ _fullRefSchemas = {};
6943
+ _rootNode = null;
6944
+ get allColumns() {
6945
+ return this._allColumns;
6946
+ }
6947
+ get sortableFields() {
6948
+ return this._allColumns.filter((col) => !col.isDeprecated && col.fieldType !== FilterFieldType.File);
6949
+ }
6950
+ get filterableFields() {
6951
+ return this.sortableFields;
6952
+ }
6953
+ get dataSchema() {
6954
+ return this._dataSchema;
6955
+ }
6956
+ get wrappedDataSchema() {
6957
+ return this._wrappedDataSchema;
6958
+ }
6959
+ get fullRefSchemas() {
6960
+ return this._fullRefSchemas;
6961
+ }
6962
+ get rootNode() {
6963
+ return this._rootNode;
6964
+ }
6965
+ init(dataSchema, refSchemas) {
6966
+ this._dataSchema = dataSchema;
6967
+ this._fullRefSchemas = {
6968
+ ...SYSTEM_REF_SCHEMAS,
6969
+ ...refSchemas
6970
+ };
6971
+ const wrapped = wrapDataSchema(dataSchema);
6972
+ this._wrappedDataSchema = wrapped;
6973
+ const rowSchema = buildRowSchema(wrapped);
6974
+ this._rootNode = new SchemaParser().parse(rowSchema, this._fullRefSchemas);
6975
+ this._allColumns = extractColumns(this._rootNode);
6976
+ }
6977
+ };
6978
+
6897
6979
  //#endregion
6898
6980
  //#region src/table-editor/Columns/model/extractColumns.ts
6899
6981
  const NODE_TYPE_TO_FIELD_TYPE = {
@@ -6937,15 +7019,20 @@ function resolveRefColumn(child, fieldPath) {
6937
7019
  const refValue = child.ref();
6938
7020
  if (!refValue) return null;
6939
7021
  const systemDef = SYSTEM_FIELD_BY_REF.get(refValue);
6940
- if (systemDef) return {
6941
- field: systemDef.id,
6942
- label: systemDef.label,
6943
- fieldType: systemDef.fieldType,
6944
- isSystem: true,
6945
- systemFieldId: systemDef.id,
6946
- isDeprecated: child.metadata().deprecated ?? false,
6947
- hasFormula: child.hasFormula()
6948
- };
7022
+ if (systemDef) {
7023
+ const isDeprecated = child.metadata().deprecated ?? false;
7024
+ const hasFormula = child.hasFormula();
7025
+ return {
7026
+ field: systemDef.id,
7027
+ label: systemDef.label,
7028
+ fieldType: systemDef.fieldType,
7029
+ isSystem: true,
7030
+ systemFieldId: systemDef.id,
7031
+ isDeprecated,
7032
+ hasFormula,
7033
+ isSortable: !isDeprecated && !hasFormula
7034
+ };
7035
+ }
6949
7036
  if (refValue === SystemSchemaIds.File) return resolveFileRefColumns(child, fieldPath);
6950
7037
  return null;
6951
7038
  }
@@ -6954,18 +7041,30 @@ function resolveFileRefColumns(child, fieldPath) {
6954
7041
  if (child.isObject()) for (const subField of child.properties()) {
6955
7042
  const subFieldPath = buildFieldPath(fieldPath, subField.name());
6956
7043
  const fieldType = NODE_TYPE_TO_FIELD_TYPE[subField.nodeType()];
6957
- if (fieldType) result.push(createColumn(subFieldPath, subField, fieldType));
7044
+ if (fieldType) {
7045
+ const subCol = createColumn(subFieldPath, subField, fieldType);
7046
+ subCol.parentFileField = fieldPath;
7047
+ result.push(subCol);
7048
+ }
6958
7049
  }
6959
7050
  return result;
6960
7051
  }
7052
+ function stripDataPrefix(fieldPath) {
7053
+ if (fieldPath === DATA_FIELD) return DATA_FIELD;
7054
+ if (fieldPath.startsWith(`${DATA_FIELD}.`)) return fieldPath.slice(DATA_FIELD.length + 1);
7055
+ return fieldPath;
7056
+ }
6961
7057
  function createColumn(fieldPath, child, fieldType) {
7058
+ const isDeprecated = child.metadata().deprecated ?? false;
7059
+ const hasFormula = child.hasFormula();
6962
7060
  return {
6963
7061
  field: fieldPath,
6964
- label: fieldPath,
7062
+ label: stripDataPrefix(fieldPath),
6965
7063
  fieldType,
6966
7064
  isSystem: false,
6967
- isDeprecated: child.metadata().deprecated ?? false,
6968
- hasFormula: child.hasFormula()
7065
+ isDeprecated,
7066
+ hasFormula,
7067
+ isSortable: !isDeprecated && !hasFormula && fieldType !== FilterFieldType.File
6969
7068
  };
6970
7069
  }
6971
7070
 
@@ -7035,6 +7134,9 @@ var ColumnsModel = class {
7035
7134
  constructor() {
7036
7135
  makeAutoObservable(this, {}, { autoBind: true });
7037
7136
  }
7137
+ get allColumns() {
7138
+ return this._allColumns;
7139
+ }
7038
7140
  get visibleColumns() {
7039
7141
  const lookup = this._columnLookup;
7040
7142
  const result = [];
@@ -7052,6 +7154,10 @@ var ColumnsModel = class {
7052
7154
  const visible = this._visibleFieldSet;
7053
7155
  return this._allColumns.filter((col) => !visible.has(col.field) && !col.isSystem);
7054
7156
  }
7157
+ get availableFieldsToInsert() {
7158
+ const visible = this._visibleFieldSet;
7159
+ return this._allColumns.filter((col) => !visible.has(col.field));
7160
+ }
7055
7161
  get availableSystemFieldsToAdd() {
7056
7162
  const visible = this._visibleFieldSet;
7057
7163
  return this._allColumns.filter((col) => !visible.has(col.field) && col.isSystem);
@@ -7432,11 +7538,9 @@ var ColumnsModel = class {
7432
7538
  return this._pinnedColumns.get(neighbor) === pin;
7433
7539
  }
7434
7540
  _toViewField(field) {
7435
- if (this._columnLookup.get(field)?.isSystem) return field;
7436
- return `data.${field}`;
7541
+ return field;
7437
7542
  }
7438
7543
  _fromViewField(viewField) {
7439
- if (viewField.startsWith("data.")) return viewField.slice(5);
7440
7544
  return viewField;
7441
7545
  }
7442
7546
  _resolveWidthUntracked(field) {
@@ -7465,6 +7569,49 @@ var ColumnsModel = class {
7465
7569
  }
7466
7570
  };
7467
7571
 
7572
+ //#endregion
7573
+ //#region src/table-editor/Columns/model/groupFileFields.ts
7574
+ function isFileFieldGroup(item) {
7575
+ return "parent" in item && "children" in item;
7576
+ }
7577
+ function groupFileFields(columns, allColumns) {
7578
+ const allLookup = allColumns ? new Map(allColumns.map((c) => [c.field, c])) : null;
7579
+ const groups = /* @__PURE__ */ new Map();
7580
+ const result = [];
7581
+ for (const col of columns) if (col.fieldType === FilterFieldType.File) {
7582
+ const existing = groups.get(col.field);
7583
+ if (existing) {
7584
+ existing.parent = col;
7585
+ existing.parentVisible = false;
7586
+ } else {
7587
+ const group = {
7588
+ parent: col,
7589
+ children: [],
7590
+ parentVisible: false
7591
+ };
7592
+ groups.set(col.field, group);
7593
+ result.push(group);
7594
+ }
7595
+ } else if (col.parentFileField) {
7596
+ let group = groups.get(col.parentFileField);
7597
+ if (!group) {
7598
+ const parentCol = allLookup?.get(col.parentFileField);
7599
+ if (parentCol) {
7600
+ group = {
7601
+ parent: parentCol,
7602
+ children: [],
7603
+ parentVisible: true
7604
+ };
7605
+ groups.set(col.parentFileField, group);
7606
+ result.push(group);
7607
+ }
7608
+ }
7609
+ if (group) group.children.push(col);
7610
+ else result.push(col);
7611
+ } else result.push(col);
7612
+ return result;
7613
+ }
7614
+
7468
7615
  //#endregion
7469
7616
  //#region src/table-editor/Filters/model/utils/operators.ts
7470
7617
  let FilterOperator = /* @__PURE__ */ function(FilterOperator) {
@@ -7926,15 +8073,15 @@ function parseValue(value, fieldType) {
7926
8073
  }
7927
8074
  return value;
7928
8075
  }
7929
- function buildOperatorClause(operator, value, fieldType) {
8076
+ function buildOperatorClause(operator, value, fieldType, isSystemField) {
7930
8077
  const parsed = parseValue(value, fieldType);
7931
8078
  switch (operator) {
7932
8079
  case FilterOperator.Equals: return { equals: parsed };
7933
8080
  case FilterOperator.NotEquals: return { not: { equals: parsed } };
7934
- case FilterOperator.Contains: return { string_contains: value };
7935
- case FilterOperator.NotContains: return { not: { string_contains: value } };
7936
- case FilterOperator.StartsWith: return { string_starts_with: value };
7937
- case FilterOperator.EndsWith: return { string_ends_with: value };
8081
+ case FilterOperator.Contains: return isSystemField ? { contains: value } : { string_contains: value };
8082
+ case FilterOperator.NotContains: return isSystemField ? { not: { contains: value } } : { not: { string_contains: value } };
8083
+ case FilterOperator.StartsWith: return isSystemField ? { startsWith: value } : { string_starts_with: value };
8084
+ case FilterOperator.EndsWith: return isSystemField ? { endsWith: value } : { string_ends_with: value };
7938
8085
  case FilterOperator.Gt: return { gt: parsed };
7939
8086
  case FilterOperator.Gte: return { gte: parsed };
7940
8087
  case FilterOperator.Lt: return { lt: parsed };
@@ -7955,16 +8102,17 @@ function buildConditionClause(condition) {
7955
8102
  searchType: condition.searchType || "plain"
7956
8103
  } };
7957
8104
  return { data: {
7958
- path: condition.field,
8105
+ path: stripDataFieldPrefix(condition.field),
7959
8106
  search: condition.value,
7960
8107
  searchLanguage: condition.searchLanguage || "simple",
7961
8108
  searchType: condition.searchType || "plain"
7962
8109
  } };
7963
8110
  }
7964
- const opClause = buildOperatorClause(condition.operator, condition.value, condition.fieldType);
7965
- if (SYSTEM_FIELD_IDS.has(condition.field)) return { [condition.field]: opClause };
8111
+ const isSystemField = SYSTEM_FIELD_IDS.has(condition.field);
8112
+ const opClause = buildOperatorClause(condition.operator, condition.value, condition.fieldType, isSystemField);
8113
+ if (isSystemField) return { [condition.field]: opClause };
7966
8114
  return { data: {
7967
- path: condition.field,
8115
+ path: stripDataFieldPrefix(condition.field),
7968
8116
  ...opClause
7969
8117
  } };
7970
8118
  }
@@ -9131,7 +9279,10 @@ const SearchWidget = observer(({ model }) => {
9131
9279
  right: "0",
9132
9280
  top: "50%",
9133
9281
  transform: "translateY(-50%)",
9134
- onClick: () => model.clear(),
9282
+ onClick: () => {
9283
+ model.clear();
9284
+ setExpanded(false);
9285
+ },
9135
9286
  color: "gray.400",
9136
9287
  _hover: { color: "black" },
9137
9288
  children: /* @__PURE__ */ jsx(PiXBold, {})
@@ -9290,22 +9441,18 @@ var SortModel = class {
9290
9441
  if (firstAvailable) this.addSort(firstAvailable.field);
9291
9442
  }
9292
9443
  serializeToViewSorts() {
9293
- const lookup = this._fieldLookup;
9294
- return this.sorts.map((sort) => {
9295
- return {
9296
- field: lookup.get(sort.field)?.isSystem ? sort.field : `data.${sort.field}`,
9297
- direction: sort.direction
9298
- };
9299
- });
9444
+ return this.sorts.map((sort) => ({
9445
+ field: sort.field,
9446
+ direction: sort.direction
9447
+ }));
9300
9448
  }
9301
9449
  applyViewSorts(viewSorts) {
9302
9450
  const lookup = this._fieldLookup;
9303
9451
  const sorts = [];
9304
9452
  for (const vs of viewSorts) {
9305
- const field = vs.field.startsWith("data.") ? vs.field.slice(5) : vs.field;
9306
9453
  const direction = vs.direction === "desc" ? "desc" : "asc";
9307
- if (lookup.has(field)) sorts.push({
9308
- field,
9454
+ if (lookup.has(vs.field)) sorts.push({
9455
+ field: vs.field,
9309
9456
  direction
9310
9457
  });
9311
9458
  }
@@ -12129,10 +12276,69 @@ const FieldMenuItem = memo(({ field, name, fieldType, valuePrefix, onClick }) =>
12129
12276
  });
12130
12277
  });
12131
12278
 
12279
+ //#endregion
12280
+ //#region src/table-editor/Table/ui/Header/FileFieldSubmenu.tsx
12281
+ const FileFieldSubmenu = ({ group, parentVisible, valuePrefix, onClick }) => {
12282
+ if (group.children.length === 0 && !parentVisible) return /* @__PURE__ */ jsx(FieldMenuItem, {
12283
+ field: group.parent.field,
12284
+ name: group.parent.label,
12285
+ fieldType: group.parent.fieldType,
12286
+ valuePrefix,
12287
+ onClick
12288
+ });
12289
+ return /* @__PURE__ */ jsxs(Menu.Root, {
12290
+ positioning: {
12291
+ placement: "right-start",
12292
+ gutter: 2
12293
+ },
12294
+ lazyMount: true,
12295
+ unmountOnExit: true,
12296
+ children: [/* @__PURE__ */ jsxs(Menu.TriggerItem, {
12297
+ "data-testid": `file-group-${group.parent.field}`,
12298
+ children: [/* @__PURE__ */ jsxs(Box, {
12299
+ display: "flex",
12300
+ alignItems: "center",
12301
+ gap: 2,
12302
+ flex: 1,
12303
+ children: [/* @__PURE__ */ jsx(Box, {
12304
+ as: "span",
12305
+ fontSize: "xs",
12306
+ fontWeight: "medium",
12307
+ color: "gray.400",
12308
+ fontFamily: "mono",
12309
+ minWidth: "20px",
12310
+ children: getFieldTypeIcon(group.parent.fieldType)
12311
+ }), /* @__PURE__ */ jsx(Text, {
12312
+ truncate: true,
12313
+ children: group.parent.label
12314
+ })]
12315
+ }), /* @__PURE__ */ jsx(LuChevronRight, {})]
12316
+ }), /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Menu.Positioner, { children: /* @__PURE__ */ jsxs(Menu.Content, {
12317
+ maxH: "300px",
12318
+ minW: "200px",
12319
+ overflowY: "auto",
12320
+ children: [!parentVisible && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(FieldMenuItem, {
12321
+ field: group.parent.field,
12322
+ name: group.parent.label,
12323
+ fieldType: group.parent.fieldType,
12324
+ valuePrefix,
12325
+ onClick
12326
+ }), /* @__PURE__ */ jsx(Menu.Separator, {})] }), group.children.map((col) => /* @__PURE__ */ jsx(FieldMenuItem, {
12327
+ field: col.field,
12328
+ name: col.label,
12329
+ fieldType: col.fieldType,
12330
+ valuePrefix,
12331
+ onClick
12332
+ }, col.field))]
12333
+ }) }) })]
12334
+ });
12335
+ };
12336
+
12132
12337
  //#endregion
12133
12338
  //#region src/table-editor/Table/ui/Header/InsertColumnSubmenu.tsx
12134
- const InsertColumnSubmenu = ({ label, valuePrefix, availableFields, onSelect }) => {
12339
+ const InsertColumnSubmenu = ({ label, valuePrefix, availableFields, allColumns, onSelect }) => {
12135
12340
  if (availableFields.length === 0) return null;
12341
+ const groupedFields = groupFileFields(availableFields, allColumns);
12136
12342
  return /* @__PURE__ */ jsxs(Menu.Root, {
12137
12343
  positioning: {
12138
12344
  placement: "right-start",
@@ -12147,13 +12353,18 @@ const InsertColumnSubmenu = ({ label, valuePrefix, availableFields, onSelect })
12147
12353
  maxH: "300px",
12148
12354
  minW: "200px",
12149
12355
  overflowY: "auto",
12150
- children: availableFields.map((col) => /* @__PURE__ */ jsx(FieldMenuItem, {
12151
- field: col.field,
12152
- name: col.label,
12153
- fieldType: col.fieldType,
12356
+ children: groupedFields.map((item) => isFileFieldGroup(item) ? /* @__PURE__ */ jsx(FileFieldSubmenu, {
12357
+ group: item,
12358
+ parentVisible: item.parentVisible,
12359
+ valuePrefix,
12360
+ onClick: onSelect
12361
+ }, item.parent.field) : /* @__PURE__ */ jsx(FieldMenuItem, {
12362
+ field: item.field,
12363
+ name: item.label,
12364
+ fieldType: item.fieldType,
12154
12365
  valuePrefix,
12155
12366
  onClick: onSelect
12156
- }, col.field))
12367
+ }, item.field))
12157
12368
  }) }) })]
12158
12369
  });
12159
12370
  };
@@ -12162,8 +12373,8 @@ const InsertColumnSubmenu = ({ label, valuePrefix, availableFields, onSelect })
12162
12373
  //#region src/table-editor/Table/ui/Header/ColumnHeaderMenu.tsx
12163
12374
  const ColumnHeaderMenu = observer(({ column, columnsModel, sortModel, filterModel, onCopyPath, onClose }) => {
12164
12375
  const canRemove = columnsModel.canRemoveColumn;
12165
- const availableFields = columnsModel.availableFieldsToAdd;
12166
- const hasAvailableFields = availableFields.length > 0;
12376
+ const insertableFields = columnsModel.availableFieldsToInsert;
12377
+ const hasInsertableFields = insertableFields.length > 0;
12167
12378
  const canMove = columnsModel.canMoveLeft(column.field) || columnsModel.canMoveRight(column.field);
12168
12379
  const isPinned = columnsModel.isPinned(column.field);
12169
12380
  const canPinLeft = columnsModel.canPinLeft(column.field);
@@ -12201,11 +12412,11 @@ const ColumnHeaderMenu = observer(({ column, columnsModel, sortModel, filterMode
12201
12412
  return /* @__PURE__ */ jsxs(Menu.Content, {
12202
12413
  minW: "180px",
12203
12414
  children: [
12204
- sortModel && !column.hasFormula && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(SortSubmenu, {
12415
+ sortModel && column.isSortable && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(SortSubmenu, {
12205
12416
  field: column.field,
12206
12417
  sortModel
12207
12418
  }), /* @__PURE__ */ jsx(Menu.Separator, {})] }),
12208
- filterModel && !column.hasFormula && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Menu.Item, {
12419
+ filterModel && column.isSortable && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Menu.Item, {
12209
12420
  value: "add-filter",
12210
12421
  onClick: handleAddFilter,
12211
12422
  children: [/* @__PURE__ */ jsx(LuFilter, {}), /* @__PURE__ */ jsx(Text, { children: "Add filter" })]
@@ -12231,17 +12442,19 @@ const ColumnHeaderMenu = observer(({ column, columnsModel, sortModel, filterMode
12231
12442
  }),
12232
12443
  (canPinLeft || canPinRight) && /* @__PURE__ */ jsx(Menu.Separator, {})
12233
12444
  ] }),
12234
- hasAvailableFields && /* @__PURE__ */ jsxs(Fragment$1, { children: [
12445
+ hasInsertableFields && /* @__PURE__ */ jsxs(Fragment$1, { children: [
12235
12446
  /* @__PURE__ */ jsx(InsertColumnSubmenu, {
12236
12447
  label: "Insert before",
12237
12448
  valuePrefix: "before",
12238
- availableFields,
12449
+ availableFields: insertableFields,
12450
+ allColumns: columnsModel.allColumns,
12239
12451
  onSelect: handleInsertBefore
12240
12452
  }),
12241
12453
  /* @__PURE__ */ jsx(InsertColumnSubmenu, {
12242
12454
  label: "Insert after",
12243
12455
  valuePrefix: "after",
12244
- availableFields,
12456
+ availableFields: insertableFields,
12457
+ allColumns: columnsModel.allColumns,
12245
12458
  onSelect: handleInsertAfter
12246
12459
  }),
12247
12460
  /* @__PURE__ */ jsx(Menu.Separator, {})
@@ -12359,11 +12572,11 @@ const ColumnHeader = observer(({ column, columnsModel, sortModel, filterModel, o
12359
12572
  field: column.field,
12360
12573
  columnsModel
12361
12574
  }),
12362
- filterModel && !column.hasFormula && /* @__PURE__ */ jsx(FilterIndicator, {
12575
+ filterModel && column.isSortable && /* @__PURE__ */ jsx(FilterIndicator, {
12363
12576
  field: column.field,
12364
12577
  filterModel
12365
12578
  }),
12366
- sortModel && !column.hasFormula && /* @__PURE__ */ jsx(SortIndicator, {
12579
+ sortModel && column.isSortable && /* @__PURE__ */ jsx(SortIndicator, {
12367
12580
  field: column.field,
12368
12581
  sortModel
12369
12582
  })
@@ -12390,6 +12603,7 @@ const AddColumnButton = observer(({ columnsModel }) => {
12390
12603
  const availableFields = columnsModel.availableFieldsToAdd;
12391
12604
  const availableSystemFields = columnsModel.availableSystemFieldsToAdd;
12392
12605
  if (!columnsModel.hasHiddenColumns) return null;
12606
+ const groupedFields = groupFileFields(availableFields, columnsModel.allColumns);
12393
12607
  return /* @__PURE__ */ jsx(Flex, {
12394
12608
  alignItems: "center",
12395
12609
  px: "4px",
@@ -12423,17 +12637,21 @@ const AddColumnButton = observer(({ columnsModel }) => {
12423
12637
  onClick: columnsModel.addAll,
12424
12638
  children: [/* @__PURE__ */ jsx(PiListBullets, {}), /* @__PURE__ */ jsx(Text, { children: "Add all columns" })]
12425
12639
  }),
12426
- availableFields.length > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Menu.Separator, {}), /* @__PURE__ */ jsxs(Menu.ItemGroup, { children: [/* @__PURE__ */ jsx(Menu.ItemGroupLabel, {
12640
+ groupedFields.length > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Menu.Separator, {}), /* @__PURE__ */ jsxs(Menu.ItemGroup, { children: [/* @__PURE__ */ jsx(Menu.ItemGroupLabel, {
12427
12641
  fontWeight: "medium",
12428
12642
  color: "gray.500",
12429
12643
  fontSize: "xs",
12430
12644
  children: "Data fields"
12431
- }), availableFields.map((col) => /* @__PURE__ */ jsx(FieldMenuItem, {
12432
- field: col.field,
12433
- name: col.label,
12434
- fieldType: col.fieldType,
12645
+ }), groupedFields.map((item) => isFileFieldGroup(item) ? /* @__PURE__ */ jsx(FileFieldSubmenu, {
12646
+ group: item,
12647
+ parentVisible: item.parentVisible,
12648
+ onClick: columnsModel.showColumn
12649
+ }, item.parent.field) : /* @__PURE__ */ jsx(FieldMenuItem, {
12650
+ field: item.field,
12651
+ name: item.label,
12652
+ fieldType: item.fieldType,
12435
12653
  onClick: columnsModel.showColumn
12436
- }, col.field))] })] }),
12654
+ }, item.field))] })] }),
12437
12655
  availableSystemFields.length > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Menu.Separator, {}), /* @__PURE__ */ jsxs(Menu.ItemGroup, { children: [/* @__PURE__ */ jsx(Menu.ItemGroupLabel, {
12438
12656
  fontWeight: "medium",
12439
12657
  color: "gray.500",
@@ -12808,45 +13026,48 @@ const SelectionToolbar = observer(({ selection, allRowIds, onDuplicate, onDelete
12808
13026
  const isAllSelected = selection.isAllSelected(allRowIds);
12809
13027
  return /* @__PURE__ */ jsx(ActionBar.Root, {
12810
13028
  open: selection.isSelectionMode,
12811
- children: /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(ActionBar.Positioner, { children: /* @__PURE__ */ jsxs(ActionBar.Content, {
12812
- "data-testid": "selection-toolbar",
12813
- children: [
12814
- /* @__PURE__ */ jsxs(ActionBar.SelectionTrigger, { children: [selection.selectedCount, " selected"] }),
12815
- /* @__PURE__ */ jsx(ActionBar.Separator, {}),
12816
- !isAllSelected && /* @__PURE__ */ jsxs(Button, {
12817
- variant: "outline",
12818
- size: "sm",
12819
- onClick: () => selection.selectAll(allRowIds),
12820
- "data-testid": "select-all",
12821
- children: [/* @__PURE__ */ jsx(PiCheckSquare, {}), "Select all"]
12822
- }),
12823
- onDuplicate && /* @__PURE__ */ jsxs(Button, {
12824
- variant: "outline",
12825
- size: "sm",
12826
- onClick: () => onDuplicate(selection.selectedIds),
12827
- "data-testid": "duplicate-selected",
12828
- children: [/* @__PURE__ */ jsx(LuCopy, {}), "Duplicate"]
12829
- }),
12830
- onDelete && /* @__PURE__ */ jsxs(Button, {
12831
- variant: "outline",
12832
- size: "sm",
12833
- onClick: () => onDelete(selection.selectedIds),
12834
- "data-testid": "delete-selected",
12835
- children: [/* @__PURE__ */ jsx(LuTrash2, {}), "Delete"]
12836
- }),
12837
- /* @__PURE__ */ jsx(ActionBar.CloseTrigger, {
12838
- asChild: true,
12839
- children: /* @__PURE__ */ jsx(Button, {
12840
- variant: "ghost",
13029
+ children: /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(ActionBar.Positioner, {
13030
+ zIndex: 5,
13031
+ children: /* @__PURE__ */ jsxs(ActionBar.Content, {
13032
+ "data-testid": "selection-toolbar",
13033
+ children: [
13034
+ /* @__PURE__ */ jsxs(ActionBar.SelectionTrigger, { children: [selection.selectedCount, " selected"] }),
13035
+ /* @__PURE__ */ jsx(ActionBar.Separator, {}),
13036
+ !isAllSelected && /* @__PURE__ */ jsxs(Button, {
13037
+ variant: "outline",
13038
+ size: "sm",
13039
+ onClick: () => selection.selectAll(allRowIds),
13040
+ "data-testid": "select-all",
13041
+ children: [/* @__PURE__ */ jsx(PiCheckSquare, {}), "Select all"]
13042
+ }),
13043
+ onDuplicate && /* @__PURE__ */ jsxs(Button, {
13044
+ variant: "outline",
12841
13045
  size: "sm",
12842
- "aria-label": "Exit selection",
12843
- onClick: () => selection.exitSelectionMode(),
12844
- "data-testid": "exit-selection",
12845
- children: /* @__PURE__ */ jsx(PiX, {})
13046
+ onClick: () => onDuplicate(selection.selectedIds),
13047
+ "data-testid": "duplicate-selected",
13048
+ children: [/* @__PURE__ */ jsx(LuCopy, {}), "Duplicate"]
13049
+ }),
13050
+ onDelete && /* @__PURE__ */ jsxs(Button, {
13051
+ variant: "outline",
13052
+ size: "sm",
13053
+ onClick: () => onDelete(selection.selectedIds),
13054
+ "data-testid": "delete-selected",
13055
+ children: [/* @__PURE__ */ jsx(LuTrash2, {}), "Delete"]
13056
+ }),
13057
+ /* @__PURE__ */ jsx(ActionBar.CloseTrigger, {
13058
+ asChild: true,
13059
+ children: /* @__PURE__ */ jsx(Button, {
13060
+ variant: "ghost",
13061
+ size: "sm",
13062
+ "aria-label": "Exit selection",
13063
+ onClick: () => selection.exitSelectionMode(),
13064
+ "data-testid": "exit-selection",
13065
+ children: /* @__PURE__ */ jsx(PiX, {})
13066
+ })
12846
13067
  })
12847
- })
12848
- ]
12849
- }) }) })
13068
+ ]
13069
+ })
13070
+ }) })
12850
13071
  });
12851
13072
  });
12852
13073
 
@@ -13479,67 +13700,6 @@ var ViewSettingsBadgeModel = class {
13479
13700
  }
13480
13701
  };
13481
13702
 
13482
- //#endregion
13483
- //#region src/table-editor/TableEditor/model/SchemaContext.ts
13484
- const SYSTEM_REF_SCHEMAS = {
13485
- [SystemSchemaIds.File]: fileSchema,
13486
- [SystemSchemaIds.RowId]: rowIdSchema,
13487
- [SystemSchemaIds.RowCreatedAt]: rowCreatedAtSchema,
13488
- [SystemSchemaIds.RowCreatedId]: rowCreatedIdSchema,
13489
- [SystemSchemaIds.RowVersionId]: rowVersionIdSchema,
13490
- [SystemSchemaIds.RowPublishedAt]: rowPublishedAtSchema,
13491
- [SystemSchemaIds.RowUpdatedAt]: rowUpdatedAtSchema,
13492
- [SystemSchemaIds.RowHash]: rowHashSchema,
13493
- [SystemSchemaIds.RowSchemaHash]: rowSchemaHashSchema
13494
- };
13495
- function buildRowSchema(dataSchema) {
13496
- const systemProperties = {};
13497
- for (const sf of SYSTEM_FIELDS) systemProperties[sf.id] = { $ref: sf.ref };
13498
- return {
13499
- type: "object",
13500
- properties: {
13501
- ...systemProperties,
13502
- ...dataSchema.properties
13503
- },
13504
- additionalProperties: false,
13505
- required: [...Object.keys(systemProperties), ...dataSchema.required ?? []]
13506
- };
13507
- }
13508
- var SchemaContext = class {
13509
- _allColumns = [];
13510
- _dataSchema = null;
13511
- _fullRefSchemas = {};
13512
- _rootNode = null;
13513
- get allColumns() {
13514
- return this._allColumns;
13515
- }
13516
- get sortableFields() {
13517
- return this._allColumns.filter((col) => !col.isDeprecated && col.fieldType !== FilterFieldType.File);
13518
- }
13519
- get filterableFields() {
13520
- return this.sortableFields;
13521
- }
13522
- get dataSchema() {
13523
- return this._dataSchema;
13524
- }
13525
- get fullRefSchemas() {
13526
- return this._fullRefSchemas;
13527
- }
13528
- get rootNode() {
13529
- return this._rootNode;
13530
- }
13531
- init(dataSchema, refSchemas) {
13532
- this._dataSchema = dataSchema;
13533
- this._fullRefSchemas = {
13534
- ...SYSTEM_REF_SCHEMAS,
13535
- ...refSchemas
13536
- };
13537
- const rowSchema = buildRowSchema(dataSchema);
13538
- this._rootNode = new SchemaParser().parse(rowSchema, this._fullRefSchemas);
13539
- this._allColumns = extractColumns(this._rootNode);
13540
- }
13541
- };
13542
-
13543
13703
  //#endregion
13544
13704
  //#region src/table-editor/TableEditor/model/TableEditorCore.ts
13545
13705
  const DEFAULT_PAGE_SIZE = 50;
@@ -13686,7 +13846,10 @@ var TableEditorCore = class {
13686
13846
  _buildQuery(after = null) {
13687
13847
  return {
13688
13848
  where: this.filters.hasActiveFilters ? this.filters.buildCurrentWhereClause() : null,
13689
- orderBy: this.sorts.serializeToViewSorts(),
13849
+ orderBy: this.sorts.serializeToViewSorts().map((s) => ({
13850
+ field: stripDataFieldPrefix(s.field),
13851
+ direction: s.direction
13852
+ })),
13690
13853
  search: this.search.debouncedQuery,
13691
13854
  first: this._pageSize,
13692
13855
  after
@@ -13721,14 +13884,14 @@ var TableEditorCore = class {
13721
13884
  this._updateNavigationContext();
13722
13885
  }
13723
13886
  _createRowVMs(rawRows) {
13724
- const dataSchema = this._schemaContext.dataSchema;
13725
- if (!dataSchema) return [];
13887
+ const wrappedSchema = this._schemaContext.wrappedDataSchema;
13888
+ if (!wrappedSchema) return [];
13726
13889
  const tableModel = createTableModel({
13727
13890
  tableId: this._tableId,
13728
- schema: dataSchema,
13891
+ schema: wrappedSchema,
13729
13892
  rows: rawRows.map((r) => ({
13730
13893
  rowId: r.rowId,
13731
- data: r.data
13894
+ data: { data: r.data }
13732
13895
  })),
13733
13896
  refSchemas: this._schemaContext.fullRefSchemas
13734
13897
  });
@@ -13742,10 +13905,14 @@ var TableEditorCore = class {
13742
13905
  id: rawRow.rowId
13743
13906
  };
13744
13907
  }
13908
+ _toPatchField(field) {
13909
+ return stripDataFieldPrefix(field);
13910
+ }
13745
13911
  async _commitCell(rowId, field, value, previousValue) {
13912
+ const patchField = this._toPatchField(field);
13746
13913
  const result = (await this._dataSource.patchCells([{
13747
13914
  rowId,
13748
- field,
13915
+ field: patchField,
13749
13916
  value
13750
13917
  }]))[0];
13751
13918
  if (result && !result.ok) runInAction(() => {
@@ -13825,7 +13992,7 @@ var MockDataSource = class {
13825
13992
  static createRow(rowId, data, systemFields) {
13826
13993
  const row = {
13827
13994
  rowId,
13828
- data: { ...data }
13995
+ data: data && typeof data === "object" && !Array.isArray(data) ? { ...data } : data
13829
13996
  };
13830
13997
  if (systemFields) row.systemFields = systemFields;
13831
13998
  return row;
@@ -13844,16 +14011,23 @@ var MockDataSource = class {
13844
14011
  let rows = [...this._allRows];
13845
14012
  if (query.search) {
13846
14013
  const lower = query.search.toLowerCase();
13847
- rows = rows.filter((row) => Object.values(row.data).some((val) => typeof val === "string" && val.toLowerCase().includes(lower)));
14014
+ rows = rows.filter((row) => {
14015
+ const data = row.data;
14016
+ if (data && typeof data === "object") return Object.values(data).some((val) => typeof val === "string" && val.toLowerCase().includes(lower));
14017
+ if (typeof data === "string") return data.toLowerCase().includes(lower);
14018
+ return false;
14019
+ });
13848
14020
  }
13849
14021
  if (query.orderBy.length > 0) {
13850
14022
  const firstOrder = query.orderBy[0];
13851
14023
  if (firstOrder) {
13852
- const field = firstOrder.field.startsWith("data.") ? firstOrder.field.slice(5) : firstOrder.field;
14024
+ const field = firstOrder.field;
13853
14025
  const dir = firstOrder.direction === "desc" ? -1 : 1;
13854
14026
  rows.sort((a, b) => {
13855
- const aVal = a.data[field];
13856
- const bVal = b.data[field];
14027
+ const aData = a.data;
14028
+ const bData = b.data;
14029
+ const aVal = aData?.[field];
14030
+ const bVal = bData?.[field];
13857
14031
  if (aVal === bVal) return 0;
13858
14032
  if (aVal == null) return 1;
13859
14033
  if (bVal == null) return -1;
@@ -13889,7 +14063,7 @@ var MockDataSource = class {
13889
14063
  error: "Mock failure"
13890
14064
  };
13891
14065
  const row = this._allRows.find((r) => r.rowId === patch.rowId);
13892
- if (row) row.data[patch.field] = patch.value;
14066
+ if (row?.data && typeof row.data === "object" && !Array.isArray(row.data)) row.data[patch.field] = patch.value;
13893
14067
  return {
13894
14068
  rowId: patch.rowId,
13895
14069
  field: patch.field,
@@ -14104,5 +14278,5 @@ const TableEditor = observer(({ viewModel, useWindowScroll }) => {
14104
14278
  });
14105
14279
 
14106
14280
  //#endregion
14107
- export { BackButton, BooleanCell, Breadcrumbs, CellFSM, CellRenderer, CellVM, CellWrapper, CloseButton, ColumnsModel, ContentEditable, CopyButton, CreateButton, CreatingEditorVM, CreatingSchemaEditor, DataRow, DateTimeCell, DeleteConfirmDialog, FieldSelect, FileCell, FilterConditionVM, FilterConditionView, FilterCore, FilterCore as FilterModel, FilterFieldType, FilterGroupVM, FilterGroupView, FilterOperator, FilterValueInput, FilterWidget, ForeignKeyCell, GrayButton, HeaderRow, JsonCard, MockDataSource, NumberCell, OPERATORS_BY_TYPE, OperatorSelect, PlusButton, ReadonlyCell, ResizeHandle, RowActionsMenu, RowCountModel, RowCountWidget, RowEditor, RowEditorVM, RowVM, SEARCH_LANGUAGES, SEARCH_TYPES, SORT_SCHEMA, SYSTEM_FIELDS, SYSTEM_FIELD_BY_REF, SYSTEM_FIELD_IDS, SchemaContext, SchemaEditorCore, SchemaTypeIds, SearchForeignKey, SearchForeignKeyVM, SearchLanguage, SearchModel, SearchType, SearchWidget, SelectionModel, SelectionToolbar, SettingsButton, SortDirectionSelect, SortFieldSelect, SortModel, SortRow, SortingsWidget, StringCell, SystemFieldId, TableEditor, TableEditorCore, TableWidget, Tooltip, UpdatingEditorVM, UpdatingSchemaEditor, ViewSettingsBadge, ViewSettingsBadgeModel, ViewerSwitcher, ViewerSwitcherMode, buildWhereClause, ensureReactivityProvider, extractColumns, getDefaultOperator, getLabelByRef, getOperatorLabel, getOperatorsForType, operatorRequiresValue, selectDefaultColumns, typeMenuGroups, useContentEditable };
14281
+ export { BackButton, BooleanCell, Breadcrumbs, CellFSM, CellRenderer, CellVM, CellWrapper, CloseButton, ColumnsModel, ContentEditable, CopyButton, CreateButton, CreatingEditorVM, CreatingSchemaEditor, DataRow, DateTimeCell, DeleteConfirmDialog, FieldSelect, FileCell, FilterConditionVM, FilterConditionView, FilterCore, FilterCore as FilterModel, FilterFieldType, FilterGroupVM, FilterGroupView, FilterOperator, FilterValueInput, FilterWidget, ForeignKeyCell, GrayButton, HeaderRow, JsonCard, MockDataSource, NumberCell, OPERATORS_BY_TYPE, OperatorSelect, PlusButton, ReadonlyCell, ResizeHandle, RowActionsMenu, RowCountModel, RowCountWidget, RowEditor, RowEditorVM, RowVM, SEARCH_LANGUAGES, SEARCH_TYPES, SORT_SCHEMA, SYSTEM_FIELDS, SYSTEM_FIELD_BY_REF, SYSTEM_FIELD_IDS, SchemaContext, SchemaEditorCore, SchemaTypeIds, SearchForeignKey, SearchForeignKeyVM, SearchLanguage, SearchModel, SearchType, SearchWidget, SelectionModel, SelectionToolbar, SettingsButton, SortDirectionSelect, SortFieldSelect, SortModel, SortRow, SortingsWidget, StringCell, SystemFieldId, TableEditor, TableEditorCore, TableWidget, Tooltip, UpdatingEditorVM, UpdatingSchemaEditor, ViewSettingsBadge, ViewSettingsBadgeModel, ViewerSwitcher, ViewerSwitcherMode, buildWhereClause, ensureReactivityProvider, extractColumns, getDefaultOperator, getLabelByRef, getOperatorLabel, getOperatorsForType, groupFileFields, isFileFieldGroup, operatorRequiresValue, selectDefaultColumns, typeMenuGroups, useContentEditable };
14108
14282
  //# sourceMappingURL=index.mjs.map