@revisium/schema-toolkit-ui 0.6.0 → 0.6.2
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 +519 -384
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -32
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +37 -32
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +519 -384
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6920,6 +6920,88 @@ const SYSTEM_FIELD_IDS = new Set([
|
|
|
6920
6920
|
"schemaHash"
|
|
6921
6921
|
]);
|
|
6922
6922
|
|
|
6923
|
+
//#endregion
|
|
6924
|
+
//#region src/table-editor/TableEditor/model/SchemaContext.ts
|
|
6925
|
+
const DATA_FIELD = "data";
|
|
6926
|
+
function stripDataFieldPrefix(field) {
|
|
6927
|
+
const prefix = `${DATA_FIELD}.`;
|
|
6928
|
+
if (field.startsWith(prefix)) return field.slice(prefix.length);
|
|
6929
|
+
if (field === DATA_FIELD) return "";
|
|
6930
|
+
return field;
|
|
6931
|
+
}
|
|
6932
|
+
const SYSTEM_REF_SCHEMAS = {
|
|
6933
|
+
[_revisium_schema_toolkit.SystemSchemaIds.File]: _revisium_schema_toolkit.fileSchema,
|
|
6934
|
+
[_revisium_schema_toolkit.SystemSchemaIds.RowId]: _revisium_schema_toolkit.rowIdSchema,
|
|
6935
|
+
[_revisium_schema_toolkit.SystemSchemaIds.RowCreatedAt]: _revisium_schema_toolkit.rowCreatedAtSchema,
|
|
6936
|
+
[_revisium_schema_toolkit.SystemSchemaIds.RowCreatedId]: _revisium_schema_toolkit.rowCreatedIdSchema,
|
|
6937
|
+
[_revisium_schema_toolkit.SystemSchemaIds.RowVersionId]: _revisium_schema_toolkit.rowVersionIdSchema,
|
|
6938
|
+
[_revisium_schema_toolkit.SystemSchemaIds.RowPublishedAt]: _revisium_schema_toolkit.rowPublishedAtSchema,
|
|
6939
|
+
[_revisium_schema_toolkit.SystemSchemaIds.RowUpdatedAt]: _revisium_schema_toolkit.rowUpdatedAtSchema,
|
|
6940
|
+
[_revisium_schema_toolkit.SystemSchemaIds.RowHash]: _revisium_schema_toolkit.rowHashSchema,
|
|
6941
|
+
[_revisium_schema_toolkit.SystemSchemaIds.RowSchemaHash]: _revisium_schema_toolkit.rowSchemaHashSchema
|
|
6942
|
+
};
|
|
6943
|
+
function wrapDataSchema(dataSchema) {
|
|
6944
|
+
return {
|
|
6945
|
+
type: "object",
|
|
6946
|
+
properties: { [DATA_FIELD]: dataSchema },
|
|
6947
|
+
additionalProperties: false,
|
|
6948
|
+
required: [DATA_FIELD]
|
|
6949
|
+
};
|
|
6950
|
+
}
|
|
6951
|
+
function buildRowSchema(wrappedDataSchema) {
|
|
6952
|
+
const systemProperties = {};
|
|
6953
|
+
for (const sf of SYSTEM_FIELDS) systemProperties[sf.id] = { $ref: sf.ref };
|
|
6954
|
+
return {
|
|
6955
|
+
type: "object",
|
|
6956
|
+
properties: {
|
|
6957
|
+
...systemProperties,
|
|
6958
|
+
...wrappedDataSchema.properties
|
|
6959
|
+
},
|
|
6960
|
+
additionalProperties: false,
|
|
6961
|
+
required: [...Object.keys(systemProperties), ...wrappedDataSchema.required]
|
|
6962
|
+
};
|
|
6963
|
+
}
|
|
6964
|
+
var SchemaContext = class {
|
|
6965
|
+
_allColumns = [];
|
|
6966
|
+
_dataSchema = null;
|
|
6967
|
+
_wrappedDataSchema = null;
|
|
6968
|
+
_fullRefSchemas = {};
|
|
6969
|
+
_rootNode = null;
|
|
6970
|
+
get allColumns() {
|
|
6971
|
+
return this._allColumns;
|
|
6972
|
+
}
|
|
6973
|
+
get sortableFields() {
|
|
6974
|
+
return this._allColumns.filter((col) => !col.isDeprecated && col.fieldType !== FilterFieldType.File);
|
|
6975
|
+
}
|
|
6976
|
+
get filterableFields() {
|
|
6977
|
+
return this.sortableFields;
|
|
6978
|
+
}
|
|
6979
|
+
get dataSchema() {
|
|
6980
|
+
return this._dataSchema;
|
|
6981
|
+
}
|
|
6982
|
+
get wrappedDataSchema() {
|
|
6983
|
+
return this._wrappedDataSchema;
|
|
6984
|
+
}
|
|
6985
|
+
get fullRefSchemas() {
|
|
6986
|
+
return this._fullRefSchemas;
|
|
6987
|
+
}
|
|
6988
|
+
get rootNode() {
|
|
6989
|
+
return this._rootNode;
|
|
6990
|
+
}
|
|
6991
|
+
init(dataSchema, refSchemas) {
|
|
6992
|
+
this._dataSchema = dataSchema;
|
|
6993
|
+
this._fullRefSchemas = {
|
|
6994
|
+
...SYSTEM_REF_SCHEMAS,
|
|
6995
|
+
...refSchemas
|
|
6996
|
+
};
|
|
6997
|
+
const wrapped = wrapDataSchema(dataSchema);
|
|
6998
|
+
this._wrappedDataSchema = wrapped;
|
|
6999
|
+
const rowSchema = buildRowSchema(wrapped);
|
|
7000
|
+
this._rootNode = new _revisium_schema_toolkit.SchemaParser().parse(rowSchema, this._fullRefSchemas);
|
|
7001
|
+
this._allColumns = extractColumns(this._rootNode);
|
|
7002
|
+
}
|
|
7003
|
+
};
|
|
7004
|
+
|
|
6923
7005
|
//#endregion
|
|
6924
7006
|
//#region src/table-editor/Columns/model/extractColumns.ts
|
|
6925
7007
|
const NODE_TYPE_TO_FIELD_TYPE = {
|
|
@@ -6963,15 +7045,20 @@ function resolveRefColumn(child, fieldPath) {
|
|
|
6963
7045
|
const refValue = child.ref();
|
|
6964
7046
|
if (!refValue) return null;
|
|
6965
7047
|
const systemDef = SYSTEM_FIELD_BY_REF.get(refValue);
|
|
6966
|
-
if (systemDef)
|
|
6967
|
-
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
7048
|
+
if (systemDef) {
|
|
7049
|
+
const isDeprecated = child.metadata().deprecated ?? false;
|
|
7050
|
+
const hasFormula = child.hasFormula();
|
|
7051
|
+
return {
|
|
7052
|
+
field: systemDef.id,
|
|
7053
|
+
label: systemDef.label,
|
|
7054
|
+
fieldType: systemDef.fieldType,
|
|
7055
|
+
isSystem: true,
|
|
7056
|
+
systemFieldId: systemDef.id,
|
|
7057
|
+
isDeprecated,
|
|
7058
|
+
hasFormula,
|
|
7059
|
+
isSortable: !isDeprecated && !hasFormula
|
|
7060
|
+
};
|
|
7061
|
+
}
|
|
6975
7062
|
if (refValue === _revisium_schema_toolkit.SystemSchemaIds.File) return resolveFileRefColumns(child, fieldPath);
|
|
6976
7063
|
return null;
|
|
6977
7064
|
}
|
|
@@ -6984,14 +7071,22 @@ function resolveFileRefColumns(child, fieldPath) {
|
|
|
6984
7071
|
}
|
|
6985
7072
|
return result;
|
|
6986
7073
|
}
|
|
7074
|
+
function stripDataPrefix(fieldPath) {
|
|
7075
|
+
if (fieldPath === DATA_FIELD) return DATA_FIELD;
|
|
7076
|
+
if (fieldPath.startsWith(`${DATA_FIELD}.`)) return fieldPath.slice(DATA_FIELD.length + 1);
|
|
7077
|
+
return fieldPath;
|
|
7078
|
+
}
|
|
6987
7079
|
function createColumn(fieldPath, child, fieldType) {
|
|
7080
|
+
const isDeprecated = child.metadata().deprecated ?? false;
|
|
7081
|
+
const hasFormula = child.hasFormula();
|
|
6988
7082
|
return {
|
|
6989
7083
|
field: fieldPath,
|
|
6990
|
-
label: fieldPath,
|
|
7084
|
+
label: stripDataPrefix(fieldPath),
|
|
6991
7085
|
fieldType,
|
|
6992
7086
|
isSystem: false,
|
|
6993
|
-
isDeprecated
|
|
6994
|
-
hasFormula
|
|
7087
|
+
isDeprecated,
|
|
7088
|
+
hasFormula,
|
|
7089
|
+
isSortable: !isDeprecated && !hasFormula && fieldType !== FilterFieldType.File
|
|
6995
7090
|
};
|
|
6996
7091
|
}
|
|
6997
7092
|
|
|
@@ -7033,6 +7128,9 @@ function selectDefaultColumns(columns, maxVisible = 4) {
|
|
|
7033
7128
|
//#region src/table-editor/Columns/model/ColumnsModel.ts
|
|
7034
7129
|
const DEFAULT_COLUMN_WIDTH = 150;
|
|
7035
7130
|
const DEFAULT_ID_COLUMN_WIDTH = 240;
|
|
7131
|
+
function fieldToCssVar(field) {
|
|
7132
|
+
return `--cw-${field.replaceAll(".", "-")}`;
|
|
7133
|
+
}
|
|
7036
7134
|
function isValidPinZoneOrder(fields, pins) {
|
|
7037
7135
|
let zone = "left";
|
|
7038
7136
|
for (const field of fields) {
|
|
@@ -7075,6 +7173,10 @@ var ColumnsModel = class {
|
|
|
7075
7173
|
const visible = this._visibleFieldSet;
|
|
7076
7174
|
return this._allColumns.filter((col) => !visible.has(col.field) && !col.isSystem);
|
|
7077
7175
|
}
|
|
7176
|
+
get availableFieldsToInsert() {
|
|
7177
|
+
const visible = this._visibleFieldSet;
|
|
7178
|
+
return this._allColumns.filter((col) => !visible.has(col.field));
|
|
7179
|
+
}
|
|
7078
7180
|
get availableSystemFieldsToAdd() {
|
|
7079
7181
|
const visible = this._visibleFieldSet;
|
|
7080
7182
|
return this._allColumns.filter((col) => !visible.has(col.field) && col.isSystem);
|
|
@@ -7222,7 +7324,7 @@ var ColumnsModel = class {
|
|
|
7222
7324
|
setColumnWidth(field, width) {
|
|
7223
7325
|
this._isResizing = true;
|
|
7224
7326
|
this._columnWidths.set(field, width);
|
|
7225
|
-
if (this._wrapperElement) this._wrapperElement.style.setProperty(
|
|
7327
|
+
if (this._wrapperElement) this._wrapperElement.style.setProperty(fieldToCssVar(field), `${width}px`);
|
|
7226
7328
|
}
|
|
7227
7329
|
commitColumnWidth() {
|
|
7228
7330
|
this._isResizing = false;
|
|
@@ -7242,7 +7344,7 @@ var ColumnsModel = class {
|
|
|
7242
7344
|
return this._buildCssVarsUntracked();
|
|
7243
7345
|
}
|
|
7244
7346
|
columnWidthCssVar(field) {
|
|
7245
|
-
return `var(
|
|
7347
|
+
return `var(${fieldToCssVar(field)}, ${field === "id" ? DEFAULT_ID_COLUMN_WIDTH : DEFAULT_COLUMN_WIDTH}px)`;
|
|
7246
7348
|
}
|
|
7247
7349
|
getPinState(field) {
|
|
7248
7350
|
return this._pinnedColumns.get(field);
|
|
@@ -7455,11 +7557,9 @@ var ColumnsModel = class {
|
|
|
7455
7557
|
return this._pinnedColumns.get(neighbor) === pin;
|
|
7456
7558
|
}
|
|
7457
7559
|
_toViewField(field) {
|
|
7458
|
-
|
|
7459
|
-
return `data.${field}`;
|
|
7560
|
+
return field;
|
|
7460
7561
|
}
|
|
7461
7562
|
_fromViewField(viewField) {
|
|
7462
|
-
if (viewField.startsWith("data.")) return viewField.slice(5);
|
|
7463
7563
|
return viewField;
|
|
7464
7564
|
}
|
|
7465
7565
|
_resolveWidthUntracked(field) {
|
|
@@ -7469,7 +7569,7 @@ var ColumnsModel = class {
|
|
|
7469
7569
|
const vars = {};
|
|
7470
7570
|
for (const field of this._visibleFields) {
|
|
7471
7571
|
const width = this._columnWidths.get(field) ?? (field === "id" ? DEFAULT_ID_COLUMN_WIDTH : DEFAULT_COLUMN_WIDTH);
|
|
7472
|
-
vars[
|
|
7572
|
+
vars[fieldToCssVar(field)] = `${width}px`;
|
|
7473
7573
|
}
|
|
7474
7574
|
return vars;
|
|
7475
7575
|
}
|
|
@@ -7478,7 +7578,7 @@ var ColumnsModel = class {
|
|
|
7478
7578
|
const vars = {};
|
|
7479
7579
|
for (const field of this._visibleFields) {
|
|
7480
7580
|
const width = this._columnWidths.get(field) ?? (field === "id" ? DEFAULT_ID_COLUMN_WIDTH : DEFAULT_COLUMN_WIDTH);
|
|
7481
|
-
vars[
|
|
7581
|
+
vars[fieldToCssVar(field)] = `${width}px`;
|
|
7482
7582
|
}
|
|
7483
7583
|
return vars;
|
|
7484
7584
|
});
|
|
@@ -7978,7 +8078,7 @@ function buildConditionClause(condition) {
|
|
|
7978
8078
|
searchType: condition.searchType || "plain"
|
|
7979
8079
|
} };
|
|
7980
8080
|
return { data: {
|
|
7981
|
-
path: condition.field,
|
|
8081
|
+
path: stripDataFieldPrefix(condition.field),
|
|
7982
8082
|
search: condition.value,
|
|
7983
8083
|
searchLanguage: condition.searchLanguage || "simple",
|
|
7984
8084
|
searchType: condition.searchType || "plain"
|
|
@@ -7987,7 +8087,7 @@ function buildConditionClause(condition) {
|
|
|
7987
8087
|
const opClause = buildOperatorClause(condition.operator, condition.value, condition.fieldType);
|
|
7988
8088
|
if (SYSTEM_FIELD_IDS.has(condition.field)) return { [condition.field]: opClause };
|
|
7989
8089
|
return { data: {
|
|
7990
|
-
path: condition.field,
|
|
8090
|
+
path: stripDataFieldPrefix(condition.field),
|
|
7991
8091
|
...opClause
|
|
7992
8092
|
} };
|
|
7993
8093
|
}
|
|
@@ -9313,22 +9413,18 @@ var SortModel = class {
|
|
|
9313
9413
|
if (firstAvailable) this.addSort(firstAvailable.field);
|
|
9314
9414
|
}
|
|
9315
9415
|
serializeToViewSorts() {
|
|
9316
|
-
|
|
9317
|
-
|
|
9318
|
-
|
|
9319
|
-
|
|
9320
|
-
direction: sort.direction
|
|
9321
|
-
};
|
|
9322
|
-
});
|
|
9416
|
+
return this.sorts.map((sort) => ({
|
|
9417
|
+
field: sort.field,
|
|
9418
|
+
direction: sort.direction
|
|
9419
|
+
}));
|
|
9323
9420
|
}
|
|
9324
9421
|
applyViewSorts(viewSorts) {
|
|
9325
9422
|
const lookup = this._fieldLookup;
|
|
9326
9423
|
const sorts = [];
|
|
9327
9424
|
for (const vs of viewSorts) {
|
|
9328
|
-
const field = vs.field.startsWith("data.") ? vs.field.slice(5) : vs.field;
|
|
9329
9425
|
const direction = vs.direction === "desc" ? "desc" : "asc";
|
|
9330
|
-
if (lookup.has(field)) sorts.push({
|
|
9331
|
-
field,
|
|
9426
|
+
if (lookup.has(vs.field)) sorts.push({
|
|
9427
|
+
field: vs.field,
|
|
9332
9428
|
direction
|
|
9333
9429
|
});
|
|
9334
9430
|
}
|
|
@@ -10851,6 +10947,242 @@ const CellContextMenu = (0, mobx_react_lite.observer)(({ cell, onEditPointerDown
|
|
|
10851
10947
|
}) }) });
|
|
10852
10948
|
});
|
|
10853
10949
|
|
|
10950
|
+
//#endregion
|
|
10951
|
+
//#region src/table-editor/Table/ui/Cell/cellStyles.ts
|
|
10952
|
+
const SELECTION_BORDER_COLOR = "#3b82f6";
|
|
10953
|
+
function getCellState(cell) {
|
|
10954
|
+
if (cell.isReadOnly) {
|
|
10955
|
+
if (cell.isFocused && !cell.isInSelection) return "readonlyFocused";
|
|
10956
|
+
if (cell.isInSelection) return "selected";
|
|
10957
|
+
return "readonly";
|
|
10958
|
+
}
|
|
10959
|
+
if (cell.isEditing) return "editing";
|
|
10960
|
+
if (cell.isFocused && !cell.isInSelection) return "focused";
|
|
10961
|
+
if (cell.isInSelection) return "selected";
|
|
10962
|
+
return "display";
|
|
10963
|
+
}
|
|
10964
|
+
function isPrintableKey(e) {
|
|
10965
|
+
if (e.ctrlKey || e.metaKey || e.altKey) return false;
|
|
10966
|
+
return e.key.length === 1;
|
|
10967
|
+
}
|
|
10968
|
+
|
|
10969
|
+
//#endregion
|
|
10970
|
+
//#region src/table-editor/Table/ui/Cell/cellCss.ts
|
|
10971
|
+
const CLS = "cw";
|
|
10972
|
+
const CLS_DISPLAY = `${CLS} cw-display`;
|
|
10973
|
+
const CLS_READONLY = `${CLS} cw-readonly`;
|
|
10974
|
+
const CLS_FOCUSED = `${CLS} cw-focused`;
|
|
10975
|
+
const CLS_EDITING = `${CLS} cw-editing`;
|
|
10976
|
+
const CLS_READONLY_FOCUSED = `${CLS} cw-readonlyFocused`;
|
|
10977
|
+
const CLS_SELECTED = `${CLS} cw-selected`;
|
|
10978
|
+
const CLS_ANCHOR = "cw-anchor";
|
|
10979
|
+
const STATE_CLASS = {
|
|
10980
|
+
display: CLS_DISPLAY,
|
|
10981
|
+
readonly: CLS_READONLY,
|
|
10982
|
+
focused: CLS_FOCUSED,
|
|
10983
|
+
editing: CLS_EDITING,
|
|
10984
|
+
readonlyFocused: CLS_READONLY_FOCUSED,
|
|
10985
|
+
selected: CLS_SELECTED
|
|
10986
|
+
};
|
|
10987
|
+
const CELL_STYLE_ID = "cell-wrapper-styles";
|
|
10988
|
+
function ensureCellStyles() {
|
|
10989
|
+
if (typeof document === "undefined") return;
|
|
10990
|
+
if (document.getElementById(CELL_STYLE_ID)) return;
|
|
10991
|
+
const style = document.createElement("style");
|
|
10992
|
+
style.id = CELL_STYLE_ID;
|
|
10993
|
+
style.textContent = [
|
|
10994
|
+
".cw{height:40px;padding:0 8px;position:relative;overflow:hidden;cursor:cell;box-shadow:var(--cw-shadow,none)}",
|
|
10995
|
+
".cw:focus,.cw:focus-visible{outline:none;box-shadow:var(--cw-shadow,none)}",
|
|
10996
|
+
".cw-display:hover,.cw-readonly:hover{background-color:var(--chakra-colors-gray-50);box-shadow:inset 0 -1px 0 0 #ededed}",
|
|
10997
|
+
".cw-focused{background-color:var(--chakra-colors-blue-50)}",
|
|
10998
|
+
".cw-focused::before,.cw-editing::before,.cw-readonlyFocused::before,.cw-anchor::before{content:\"\";position:absolute;inset:1px;border-radius:1px;pointer-events:none}",
|
|
10999
|
+
".cw-focused::before{border:2px solid var(--chakra-colors-blue-400)}",
|
|
11000
|
+
".cw-editing{cursor:text;background-color:white;z-index:1}",
|
|
11001
|
+
".cw-editing::before{border:2px solid var(--chakra-colors-blue-500)}",
|
|
11002
|
+
".cw-readonlyFocused{background-color:var(--chakra-colors-gray-50)}",
|
|
11003
|
+
".cw-readonlyFocused::before{border:2px solid var(--chakra-colors-gray-400)}",
|
|
11004
|
+
".cw-selected{background-color:var(--chakra-colors-blue-100);user-select:none}",
|
|
11005
|
+
".cw-anchor::before{border:2px solid var(--chakra-colors-blue-400)}"
|
|
11006
|
+
].join("");
|
|
11007
|
+
document.head.appendChild(style);
|
|
11008
|
+
}
|
|
11009
|
+
const INNER_STYLE = {
|
|
11010
|
+
display: "flex",
|
|
11011
|
+
alignItems: "center",
|
|
11012
|
+
height: "100%",
|
|
11013
|
+
width: "100%",
|
|
11014
|
+
minWidth: 0,
|
|
11015
|
+
overflow: "hidden"
|
|
11016
|
+
};
|
|
11017
|
+
function buildSelectionBoxShadow(edges) {
|
|
11018
|
+
const shadows = [];
|
|
11019
|
+
if (edges.top) shadows.push(`inset 0 2px 0 0 ${SELECTION_BORDER_COLOR}`);
|
|
11020
|
+
if (edges.bottom) shadows.push(`inset 0 -2px 0 0 ${SELECTION_BORDER_COLOR}`);
|
|
11021
|
+
if (edges.left) shadows.push(`inset 2px 0 0 0 ${SELECTION_BORDER_COLOR}`);
|
|
11022
|
+
if (edges.right) shadows.push(`inset -2px 0 0 0 ${SELECTION_BORDER_COLOR}`);
|
|
11023
|
+
return shadows.length > 0 ? shadows.join(", ") : null;
|
|
11024
|
+
}
|
|
11025
|
+
|
|
11026
|
+
//#endregion
|
|
11027
|
+
//#region src/table-editor/Table/ui/Cell/useCellContextMenu.ts
|
|
11028
|
+
let pendingContextMenu = null;
|
|
11029
|
+
function clearPendingContextMenu() {
|
|
11030
|
+
const pending = pendingContextMenu;
|
|
11031
|
+
pendingContextMenu = null;
|
|
11032
|
+
return pending;
|
|
11033
|
+
}
|
|
11034
|
+
function setPendingContextMenu(value) {
|
|
11035
|
+
pendingContextMenu = value;
|
|
11036
|
+
}
|
|
11037
|
+
const cellMenuRegistry = /* @__PURE__ */ new WeakMap();
|
|
11038
|
+
function useCellContextMenu(cell, cellRef, deferredEdit) {
|
|
11039
|
+
const [menuAnchor, setMenuAnchor] = (0, react.useState)(null);
|
|
11040
|
+
const menuOpen = menuAnchor !== null;
|
|
11041
|
+
const openContextMenuAt = (0, react.useCallback)((clientX, clientY) => {
|
|
11042
|
+
if (!cell.isFocused && !cell.isInSelection) cell.focus();
|
|
11043
|
+
setMenuAnchor(new DOMRect(clientX, clientY, 0, 0));
|
|
11044
|
+
}, [cell]);
|
|
11045
|
+
(0, react.useEffect)(() => {
|
|
11046
|
+
const el = cellRef.current;
|
|
11047
|
+
if (el) cellMenuRegistry.set(el, openContextMenuAt);
|
|
11048
|
+
return () => {
|
|
11049
|
+
if (el) cellMenuRegistry.delete(el);
|
|
11050
|
+
};
|
|
11051
|
+
}, [cellRef, openContextMenuAt]);
|
|
11052
|
+
const menuCloseRef = (0, react.useRef)(null);
|
|
11053
|
+
const handleMenuClose = (0, react.useCallback)(() => {
|
|
11054
|
+
const pending = clearPendingContextMenu();
|
|
11055
|
+
const didTriggerEdit = deferredEdit.triggerIfRequested();
|
|
11056
|
+
if (!pending && !didTriggerEdit && !cell.isEditing) if (cell.isAnchor || cell.isFocused && !cell.hasRangeSelection) cellRef.current?.focus();
|
|
11057
|
+
else ((cellRef.current?.closest("[data-testid=\"table-widget\"]"))?.querySelector("[data-testid^=\"cell-\"][tabindex=\"0\"]"))?.focus();
|
|
11058
|
+
setMenuAnchor(null);
|
|
11059
|
+
if (pending) {
|
|
11060
|
+
const openFn = cellMenuRegistry.get(pending.target);
|
|
11061
|
+
if (openFn) setTimeout(() => {
|
|
11062
|
+
openFn(pending.clientX, pending.clientY);
|
|
11063
|
+
}, 0);
|
|
11064
|
+
}
|
|
11065
|
+
}, [
|
|
11066
|
+
cell,
|
|
11067
|
+
cellRef,
|
|
11068
|
+
deferredEdit
|
|
11069
|
+
]);
|
|
11070
|
+
menuCloseRef.current = handleMenuClose;
|
|
11071
|
+
return {
|
|
11072
|
+
menuAnchor,
|
|
11073
|
+
menuOpen,
|
|
11074
|
+
openContextMenuAt,
|
|
11075
|
+
handleMenuClose,
|
|
11076
|
+
menuCloseRef
|
|
11077
|
+
};
|
|
11078
|
+
}
|
|
11079
|
+
|
|
11080
|
+
//#endregion
|
|
11081
|
+
//#region src/table-editor/Table/ui/Cell/useCellFocus.ts
|
|
11082
|
+
function useCellFocus(cellRef, state, isAnchorInRange, navVersion) {
|
|
11083
|
+
(0, react.useEffect)(() => {
|
|
11084
|
+
if (!cellRef.current) return;
|
|
11085
|
+
if (state === "focused" || state === "readonlyFocused" || isAnchorInRange) cellRef.current.focus();
|
|
11086
|
+
else if (state === "display" || state === "readonly" || state === "selected") cellRef.current.blur();
|
|
11087
|
+
}, [
|
|
11088
|
+
cellRef,
|
|
11089
|
+
state,
|
|
11090
|
+
isAnchorInRange,
|
|
11091
|
+
navVersion
|
|
11092
|
+
]);
|
|
11093
|
+
}
|
|
11094
|
+
|
|
11095
|
+
//#endregion
|
|
11096
|
+
//#region src/table-editor/Table/ui/Cell/useCellKeyboard.ts
|
|
11097
|
+
function handleArrowKey(cell, e, shiftAction, moveAction) {
|
|
11098
|
+
e.preventDefault();
|
|
11099
|
+
if (e.shiftKey) shiftAction();
|
|
11100
|
+
else if (cell.hasRangeSelection) cell.focus();
|
|
11101
|
+
else moveAction();
|
|
11102
|
+
}
|
|
11103
|
+
function handleEditableKeys(cell, e, callbacks) {
|
|
11104
|
+
if (cell.isReadOnly) {
|
|
11105
|
+
if (e.key === "Enter" || e.key === "Delete" || e.key === "Backspace" || isPrintableKey(e)) {
|
|
11106
|
+
e.preventDefault();
|
|
11107
|
+
cell.notifyReadonlyEditAttempt();
|
|
11108
|
+
}
|
|
11109
|
+
return;
|
|
11110
|
+
}
|
|
11111
|
+
const hasRange = cell.hasRangeSelection;
|
|
11112
|
+
if (!hasRange && e.key === "Enter") {
|
|
11113
|
+
e.preventDefault();
|
|
11114
|
+
if (callbacks.onStartEdit) callbacks.onStartEdit();
|
|
11115
|
+
else if (callbacks.onDoubleClick) callbacks.onDoubleClick();
|
|
11116
|
+
} else if (!hasRange && (e.key === "Delete" || e.key === "Backspace") && callbacks.onDelete) {
|
|
11117
|
+
e.preventDefault();
|
|
11118
|
+
callbacks.onDelete();
|
|
11119
|
+
} else if (isPrintableKey(e) && callbacks.onTypeChar) {
|
|
11120
|
+
e.preventDefault();
|
|
11121
|
+
callbacks.onTypeChar(e.key);
|
|
11122
|
+
}
|
|
11123
|
+
}
|
|
11124
|
+
function useCellKeyboard(cell, state, isAnchorInRange, menuOpen, menuCloseRef, callbacks) {
|
|
11125
|
+
const { onStartEdit, onDoubleClick, onTypeChar, onDelete } = callbacks;
|
|
11126
|
+
return {
|
|
11127
|
+
handleKeyDown: (0, react.useCallback)((e) => {
|
|
11128
|
+
if (menuOpen && e.key === "Escape") {
|
|
11129
|
+
e.preventDefault();
|
|
11130
|
+
menuCloseRef.current?.();
|
|
11131
|
+
return;
|
|
11132
|
+
}
|
|
11133
|
+
if (!(state === "focused" || state === "readonlyFocused" || isAnchorInRange)) return;
|
|
11134
|
+
const isMod = e.ctrlKey || e.metaKey;
|
|
11135
|
+
if (isMod && e.key === "c" && !cell.hasRangeSelection) {
|
|
11136
|
+
e.preventDefault();
|
|
11137
|
+
cell.copyToClipboard();
|
|
11138
|
+
return;
|
|
11139
|
+
}
|
|
11140
|
+
if (isMod && e.key === "v") return;
|
|
11141
|
+
const arrow = {
|
|
11142
|
+
ArrowUp: [cell.shiftMoveUp, cell.moveUp],
|
|
11143
|
+
ArrowDown: [cell.shiftMoveDown, cell.moveDown],
|
|
11144
|
+
ArrowLeft: [cell.shiftMoveLeft, cell.moveLeft],
|
|
11145
|
+
ArrowRight: [cell.shiftMoveRight, cell.moveRight]
|
|
11146
|
+
}[e.key];
|
|
11147
|
+
if (e.key === "Escape") {
|
|
11148
|
+
e.preventDefault();
|
|
11149
|
+
if (cell.hasRangeSelection) cell.focus();
|
|
11150
|
+
else cell.blur();
|
|
11151
|
+
} else if (arrow) handleArrowKey(cell, e, arrow[0], arrow[1]);
|
|
11152
|
+
else if (e.key === "Tab") {
|
|
11153
|
+
e.preventDefault();
|
|
11154
|
+
cell.handleTab(e.shiftKey);
|
|
11155
|
+
} else handleEditableKeys(cell, e, {
|
|
11156
|
+
onStartEdit,
|
|
11157
|
+
onDoubleClick,
|
|
11158
|
+
onTypeChar,
|
|
11159
|
+
onDelete
|
|
11160
|
+
});
|
|
11161
|
+
}, [
|
|
11162
|
+
state,
|
|
11163
|
+
cell,
|
|
11164
|
+
isAnchorInRange,
|
|
11165
|
+
menuOpen,
|
|
11166
|
+
menuCloseRef,
|
|
11167
|
+
onStartEdit,
|
|
11168
|
+
onDoubleClick,
|
|
11169
|
+
onTypeChar,
|
|
11170
|
+
onDelete
|
|
11171
|
+
]),
|
|
11172
|
+
handleDoubleClick: (0, react.useCallback)((e) => {
|
|
11173
|
+
if (state === "readonly" || state === "readonlyFocused") {
|
|
11174
|
+
cell.notifyReadonlyEditAttempt();
|
|
11175
|
+
return;
|
|
11176
|
+
}
|
|
11177
|
+
onDoubleClick?.(e.clientX);
|
|
11178
|
+
}, [
|
|
11179
|
+
state,
|
|
11180
|
+
cell,
|
|
11181
|
+
onDoubleClick
|
|
11182
|
+
])
|
|
11183
|
+
};
|
|
11184
|
+
}
|
|
11185
|
+
|
|
10854
11186
|
//#endregion
|
|
10855
11187
|
//#region src/table-editor/Table/ui/Cell/useDeferredMenuEdit.ts
|
|
10856
11188
|
/**
|
|
@@ -10905,299 +11237,117 @@ function useDeferredMenuEdit(editFn) {
|
|
|
10905
11237
|
};
|
|
10906
11238
|
}
|
|
10907
11239
|
|
|
10908
|
-
//#endregion
|
|
10909
|
-
//#region src/table-editor/Table/ui/borderConstants.ts
|
|
10910
|
-
const CELL_BORDER_COLOR = "#ededed";
|
|
10911
|
-
const BOTTOM_BORDER_SHADOW = `inset 0 -1px 0 0 ${CELL_BORDER_COLOR}`;
|
|
10912
|
-
function buildAddColumnShadowCss() {
|
|
10913
|
-
return { "&::after": {
|
|
10914
|
-
content: "\"\"",
|
|
10915
|
-
position: "absolute",
|
|
10916
|
-
top: 0,
|
|
10917
|
-
bottom: 0,
|
|
10918
|
-
width: "8px",
|
|
10919
|
-
left: "-8px",
|
|
10920
|
-
pointerEvents: "none",
|
|
10921
|
-
transition: "opacity 0.15s",
|
|
10922
|
-
opacity: "var(--shadow-right-opacity, 0)",
|
|
10923
|
-
boxShadow: "inset -8px 0 12px -8px rgba(0,0,0,0.1)"
|
|
10924
|
-
} };
|
|
10925
|
-
}
|
|
10926
|
-
function adjustRightOffsetCss(rightCss, addColOffset) {
|
|
10927
|
-
if (addColOffset <= 0) return rightCss;
|
|
10928
|
-
if (rightCss === "0px") return `${addColOffset}px`;
|
|
10929
|
-
return `calc(${rightCss} + ${addColOffset}px)`;
|
|
10930
|
-
}
|
|
10931
|
-
|
|
10932
|
-
//#endregion
|
|
10933
|
-
//#region src/table-editor/Table/ui/Cell/cellStyles.ts
|
|
10934
|
-
const FOCUS_RING_RESET = {
|
|
10935
|
-
outline: "none",
|
|
10936
|
-
boxShadow: "none"
|
|
10937
|
-
};
|
|
10938
|
-
const SELECTION_BORDER_COLOR = "#3b82f6";
|
|
10939
|
-
function buildSelectionBoxShadow(edges) {
|
|
10940
|
-
const shadows = [];
|
|
10941
|
-
if (edges.top) shadows.push(`inset 0 2px 0 0 ${SELECTION_BORDER_COLOR}`);
|
|
10942
|
-
if (edges.bottom) shadows.push(`inset 0 -2px 0 0 ${SELECTION_BORDER_COLOR}`);
|
|
10943
|
-
if (edges.left) shadows.push(`inset 2px 0 0 0 ${SELECTION_BORDER_COLOR}`);
|
|
10944
|
-
if (edges.right) shadows.push(`inset -2px 0 0 0 ${SELECTION_BORDER_COLOR}`);
|
|
10945
|
-
return shadows.length > 0 ? shadows.join(", ") : null;
|
|
10946
|
-
}
|
|
10947
|
-
const stateStyles = {
|
|
10948
|
-
display: {
|
|
10949
|
-
cursor: "cell",
|
|
10950
|
-
_hover: {
|
|
10951
|
-
bg: "gray.50",
|
|
10952
|
-
boxShadow: BOTTOM_BORDER_SHADOW
|
|
10953
|
-
}
|
|
10954
|
-
},
|
|
10955
|
-
focused: {
|
|
10956
|
-
cursor: "cell",
|
|
10957
|
-
bg: "blue.50",
|
|
10958
|
-
_before: {
|
|
10959
|
-
content: "\"\"",
|
|
10960
|
-
position: "absolute",
|
|
10961
|
-
inset: "1px",
|
|
10962
|
-
border: "2px solid",
|
|
10963
|
-
borderColor: "blue.400",
|
|
10964
|
-
borderRadius: "1px",
|
|
10965
|
-
pointerEvents: "none"
|
|
10966
|
-
},
|
|
10967
|
-
_focus: FOCUS_RING_RESET,
|
|
10968
|
-
_focusVisible: FOCUS_RING_RESET
|
|
10969
|
-
},
|
|
10970
|
-
editing: {
|
|
10971
|
-
cursor: "text",
|
|
10972
|
-
bg: "white",
|
|
10973
|
-
zIndex: 1,
|
|
10974
|
-
_before: {
|
|
10975
|
-
content: "\"\"",
|
|
10976
|
-
position: "absolute",
|
|
10977
|
-
inset: "1px",
|
|
10978
|
-
border: "2px solid",
|
|
10979
|
-
borderColor: "blue.500",
|
|
10980
|
-
borderRadius: "1px",
|
|
10981
|
-
pointerEvents: "none"
|
|
10982
|
-
},
|
|
10983
|
-
_focus: FOCUS_RING_RESET,
|
|
10984
|
-
_focusVisible: FOCUS_RING_RESET
|
|
10985
|
-
},
|
|
10986
|
-
readonly: {
|
|
10987
|
-
cursor: "cell",
|
|
10988
|
-
_hover: {
|
|
10989
|
-
bg: "gray.50",
|
|
10990
|
-
boxShadow: BOTTOM_BORDER_SHADOW
|
|
10991
|
-
}
|
|
10992
|
-
},
|
|
10993
|
-
readonlyFocused: {
|
|
10994
|
-
cursor: "cell",
|
|
10995
|
-
bg: "gray.50",
|
|
10996
|
-
_before: {
|
|
10997
|
-
content: "\"\"",
|
|
10998
|
-
position: "absolute",
|
|
10999
|
-
inset: "1px",
|
|
11000
|
-
border: "2px solid",
|
|
11001
|
-
borderColor: "gray.400",
|
|
11002
|
-
borderRadius: "1px",
|
|
11003
|
-
pointerEvents: "none"
|
|
11004
|
-
},
|
|
11005
|
-
_focus: FOCUS_RING_RESET,
|
|
11006
|
-
_focusVisible: FOCUS_RING_RESET
|
|
11007
|
-
},
|
|
11008
|
-
selected: {
|
|
11009
|
-
cursor: "cell",
|
|
11010
|
-
bg: "blue.100"
|
|
11011
|
-
}
|
|
11012
|
-
};
|
|
11013
|
-
function getCellState(cell) {
|
|
11014
|
-
if (cell.isReadOnly) {
|
|
11015
|
-
if (cell.isFocused && !cell.isInSelection) return "readonlyFocused";
|
|
11016
|
-
if (cell.isInSelection) return "selected";
|
|
11017
|
-
return "readonly";
|
|
11018
|
-
}
|
|
11019
|
-
if (cell.isEditing) return "editing";
|
|
11020
|
-
if (cell.isFocused && !cell.isInSelection) return "focused";
|
|
11021
|
-
if (cell.isInSelection) return "selected";
|
|
11022
|
-
return "display";
|
|
11023
|
-
}
|
|
11024
|
-
function isPrintableKey(e) {
|
|
11025
|
-
if (e.ctrlKey || e.metaKey || e.altKey) return false;
|
|
11026
|
-
return e.key.length === 1;
|
|
11027
|
-
}
|
|
11028
|
-
|
|
11029
11240
|
//#endregion
|
|
11030
11241
|
//#region src/table-editor/Table/ui/Cell/CellWrapper.tsx
|
|
11031
|
-
|
|
11032
|
-
|
|
11033
|
-
|
|
11034
|
-
|
|
11035
|
-
|
|
11036
|
-
|
|
11037
|
-
|
|
11038
|
-
|
|
11039
|
-
if (
|
|
11040
|
-
|
|
11041
|
-
|
|
11042
|
-
|
|
11043
|
-
|
|
11044
|
-
|
|
11045
|
-
|
|
11046
|
-
|
|
11047
|
-
}
|
|
11048
|
-
|
|
11049
|
-
|
|
11050
|
-
|
|
11051
|
-
|
|
11052
|
-
|
|
11053
|
-
|
|
11054
|
-
|
|
11242
|
+
const LazyContextMenu = (0, mobx_react_lite.observer)(({ cell, cellRef, anchorRect, onClose, onEditPointerDown }) => {
|
|
11243
|
+
const handleOpenChange = (0, react.useCallback)((details) => {
|
|
11244
|
+
if (!details.open) onClose();
|
|
11245
|
+
}, [onClose]);
|
|
11246
|
+
const handleInteractOutside = (0, react.useCallback)((e) => {
|
|
11247
|
+
const originalEvent = e.detail?.originalEvent;
|
|
11248
|
+
if (!originalEvent || originalEvent.button !== 2) return;
|
|
11249
|
+
const targetCell = originalEvent.target?.closest("[data-testid^=\"cell-\"]");
|
|
11250
|
+
if (targetCell) setPendingContextMenu({
|
|
11251
|
+
target: targetCell,
|
|
11252
|
+
clientX: originalEvent.clientX,
|
|
11253
|
+
clientY: originalEvent.clientY
|
|
11254
|
+
});
|
|
11255
|
+
}, []);
|
|
11256
|
+
const getAnchorRect = (0, react.useCallback)(() => {
|
|
11257
|
+
return anchorRect ?? (cellRef.current?.getBoundingClientRect() || null);
|
|
11258
|
+
}, [anchorRect, cellRef]);
|
|
11259
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.Root, {
|
|
11260
|
+
open: true,
|
|
11261
|
+
onOpenChange: handleOpenChange,
|
|
11262
|
+
onInteractOutside: handleInteractOutside,
|
|
11263
|
+
positioning: {
|
|
11264
|
+
placement: "bottom-start",
|
|
11265
|
+
getAnchorRect
|
|
11266
|
+
},
|
|
11267
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CellContextMenu, {
|
|
11268
|
+
cell,
|
|
11269
|
+
onEditPointerDown
|
|
11270
|
+
})
|
|
11271
|
+
});
|
|
11272
|
+
});
|
|
11055
11273
|
const CellWrapper = (0, mobx_react_lite.observer)(({ cell, children, onDoubleClick, onStartEdit, onTypeChar, onDelete }) => {
|
|
11274
|
+
ensureCellStyles();
|
|
11056
11275
|
const cellRef = (0, react.useRef)(null);
|
|
11057
|
-
const menuOpenRef = (0, react.useRef)(false);
|
|
11058
|
-
const deferredEdit = useDeferredMenuEdit(onStartEdit ?? onDoubleClick);
|
|
11059
11276
|
const state = getCellState(cell);
|
|
11060
11277
|
const selectionEdges = cell.selectionEdges;
|
|
11061
11278
|
const isAnchorInRange = cell.isAnchor && cell.isInSelection;
|
|
11062
11279
|
const navVersion = cell.navigationVersion;
|
|
11063
|
-
|
|
11064
|
-
|
|
11065
|
-
|
|
11066
|
-
|
|
11067
|
-
},
|
|
11068
|
-
|
|
11069
|
-
|
|
11070
|
-
|
|
11071
|
-
|
|
11072
|
-
|
|
11073
|
-
if (state === "editing") return;
|
|
11074
|
-
if (e.shiftKey) cell.selectTo();
|
|
11075
|
-
else cell.focus();
|
|
11076
|
-
}, [state, cell]);
|
|
11280
|
+
const isActive = state === "focused" || state === "editing" || state === "readonlyFocused" || isAnchorInRange;
|
|
11281
|
+
const deferredEdit = useDeferredMenuEdit(onStartEdit ?? onDoubleClick);
|
|
11282
|
+
const { menuAnchor, menuOpen, openContextMenuAt, handleMenuClose, menuCloseRef } = useCellContextMenu(cell, cellRef, deferredEdit);
|
|
11283
|
+
useCellFocus(cellRef, state, isAnchorInRange, navVersion);
|
|
11284
|
+
const { handleKeyDown, handleDoubleClick } = useCellKeyboard(cell, state, isAnchorInRange, menuOpen, menuCloseRef, {
|
|
11285
|
+
onStartEdit,
|
|
11286
|
+
onDoubleClick,
|
|
11287
|
+
onTypeChar,
|
|
11288
|
+
onDelete
|
|
11289
|
+
});
|
|
11077
11290
|
const handleMouseDown = (0, react.useCallback)((e) => {
|
|
11078
11291
|
if (e.detail === 2 && state !== "readonly" && state !== "readonlyFocused") e.preventDefault();
|
|
11292
|
+
if (e.button === 2) {
|
|
11293
|
+
openContextMenuAt(e.clientX, e.clientY);
|
|
11294
|
+
return;
|
|
11295
|
+
}
|
|
11079
11296
|
if (!e.shiftKey && e.button === 0 && state !== "editing") {
|
|
11080
11297
|
e.preventDefault();
|
|
11081
11298
|
cell.dragStart();
|
|
11082
11299
|
cellRef.current?.focus();
|
|
11083
11300
|
}
|
|
11084
|
-
}, [state, cell]);
|
|
11085
|
-
const handleMouseEnter = (0, react.useCallback)((e) => {
|
|
11086
|
-
if (e.buttons === 1) cell.dragExtend();
|
|
11087
|
-
}, [cell]);
|
|
11088
|
-
const handleDoubleClick = (0, react.useCallback)((e) => {
|
|
11089
|
-
if (state === "readonly" || state === "readonlyFocused") {
|
|
11090
|
-
cell.notifyReadonlyEditAttempt();
|
|
11091
|
-
return;
|
|
11092
|
-
}
|
|
11093
|
-
onDoubleClick?.(e.clientX);
|
|
11094
|
-
}, [
|
|
11095
|
-
state,
|
|
11096
|
-
cell,
|
|
11097
|
-
onDoubleClick
|
|
11098
|
-
]);
|
|
11099
|
-
const handleKeyDown = (0, react.useCallback)((e) => {
|
|
11100
|
-
if (!(state === "focused" || state === "readonlyFocused" || isAnchorInRange)) return;
|
|
11101
|
-
const isMod = e.ctrlKey || e.metaKey;
|
|
11102
|
-
if (isMod && e.key === "c" && !cell.hasRangeSelection) {
|
|
11103
|
-
e.preventDefault();
|
|
11104
|
-
cell.copyToClipboard();
|
|
11105
|
-
return;
|
|
11106
|
-
}
|
|
11107
|
-
if (isMod && e.key === "v") return;
|
|
11108
|
-
if (e.key === "Escape") {
|
|
11109
|
-
e.preventDefault();
|
|
11110
|
-
if (cell.hasRangeSelection) cell.focus();
|
|
11111
|
-
else cell.blur();
|
|
11112
|
-
} else if (e.key === "ArrowUp") handleArrowKey(cell, e, cell.shiftMoveUp, cell.moveUp);
|
|
11113
|
-
else if (e.key === "ArrowDown") handleArrowKey(cell, e, cell.shiftMoveDown, cell.moveDown);
|
|
11114
|
-
else if (e.key === "ArrowLeft") handleArrowKey(cell, e, cell.shiftMoveLeft, cell.moveLeft);
|
|
11115
|
-
else if (e.key === "ArrowRight") handleArrowKey(cell, e, cell.shiftMoveRight, cell.moveRight);
|
|
11116
|
-
else if (e.key === "Tab") {
|
|
11117
|
-
e.preventDefault();
|
|
11118
|
-
cell.handleTab(e.shiftKey);
|
|
11119
|
-
} else handleEditableKeys(cell, e, onStartEdit, onDoubleClick, onTypeChar, onDelete);
|
|
11120
11301
|
}, [
|
|
11121
11302
|
state,
|
|
11122
11303
|
cell,
|
|
11123
|
-
|
|
11124
|
-
onStartEdit,
|
|
11125
|
-
onDoubleClick,
|
|
11126
|
-
onTypeChar,
|
|
11127
|
-
onDelete
|
|
11304
|
+
openContextMenuAt
|
|
11128
11305
|
]);
|
|
11129
|
-
const
|
|
11130
|
-
|
|
11306
|
+
const handleClick = (0, react.useCallback)((e) => {
|
|
11307
|
+
if (state === "editing") return;
|
|
11308
|
+
if (e.shiftKey) cell.selectTo();
|
|
11309
|
+
else cell.focus();
|
|
11310
|
+
}, [state, cell]);
|
|
11311
|
+
const handleMouseEnter = (0, react.useCallback)((e) => {
|
|
11312
|
+
if (e.buttons === 1) cell.dragExtend();
|
|
11313
|
+
}, [cell]);
|
|
11131
11314
|
const handleBlur = (0, react.useCallback)((e) => {
|
|
11132
11315
|
if (!cell.isFocused || cell.isEditing) return;
|
|
11133
|
-
if (
|
|
11316
|
+
if (menuOpen) return;
|
|
11134
11317
|
if (e.relatedTarget?.closest("[data-testid^=\"cell-\"]")) return;
|
|
11135
11318
|
cell.blur();
|
|
11136
|
-
}, [cell]);
|
|
11137
|
-
const
|
|
11138
|
-
|
|
11139
|
-
|
|
11140
|
-
|
|
11141
|
-
|
|
11142
|
-
|
|
11143
|
-
|
|
11144
|
-
|
|
11145
|
-
|
|
11146
|
-
|
|
11147
|
-
|
|
11148
|
-
|
|
11149
|
-
|
|
11150
|
-
|
|
11151
|
-
|
|
11152
|
-
|
|
11153
|
-
|
|
11154
|
-
|
|
11155
|
-
|
|
11156
|
-
|
|
11157
|
-
|
|
11158
|
-
|
|
11159
|
-
|
|
11160
|
-
|
|
11161
|
-
|
|
11162
|
-
|
|
11163
|
-
|
|
11164
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.ContextTrigger, {
|
|
11165
|
-
asChild: true,
|
|
11166
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Box, {
|
|
11167
|
-
ref: cellRef,
|
|
11168
|
-
height: "40px",
|
|
11169
|
-
px: "8px",
|
|
11170
|
-
position: "relative",
|
|
11171
|
-
overflow: "hidden",
|
|
11172
|
-
onClick: handleClick,
|
|
11173
|
-
onMouseDown: handleMouseDown,
|
|
11174
|
-
onMouseEnter: handleMouseEnter,
|
|
11175
|
-
onDoubleClick: handleDoubleClick,
|
|
11176
|
-
onKeyDown: handleKeyDown,
|
|
11177
|
-
onBlur: handleBlur,
|
|
11178
|
-
onContextMenu: handleContextMenu,
|
|
11179
|
-
tabIndex: needsFocus ? 0 : -1,
|
|
11180
|
-
userSelect: state === "selected" ? "none" : void 0,
|
|
11181
|
-
"data-testid": `cell-${cell.rowId}-${cell.field}`,
|
|
11182
|
-
...stateStyles[state],
|
|
11183
|
-
...extraStyles,
|
|
11184
|
-
boxShadow: selectionShadow || void 0,
|
|
11185
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Box, {
|
|
11186
|
-
display: "flex",
|
|
11187
|
-
alignItems: "center",
|
|
11188
|
-
height: "100%",
|
|
11189
|
-
width: "100%",
|
|
11190
|
-
minWidth: 0,
|
|
11191
|
-
overflow: "hidden",
|
|
11192
|
-
children
|
|
11193
|
-
})
|
|
11194
|
-
})
|
|
11195
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CellContextMenu, {
|
|
11196
|
-
cell,
|
|
11197
|
-
onEditPointerDown: deferredEdit.requestEdit
|
|
11198
|
-
})]
|
|
11199
|
-
});
|
|
11319
|
+
}, [cell, menuOpen]);
|
|
11320
|
+
const selectionShadow = selectionEdges ? buildSelectionBoxShadow(selectionEdges) : null;
|
|
11321
|
+
let className = STATE_CLASS[state];
|
|
11322
|
+
if (isAnchorInRange) className += ` ${CLS_ANCHOR}`;
|
|
11323
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
11324
|
+
ref: cellRef,
|
|
11325
|
+
className,
|
|
11326
|
+
style: selectionShadow ? { "--cw-shadow": selectionShadow } : void 0,
|
|
11327
|
+
tabIndex: isActive ? 0 : -1,
|
|
11328
|
+
onClick: handleClick,
|
|
11329
|
+
onMouseDown: handleMouseDown,
|
|
11330
|
+
onMouseEnter: handleMouseEnter,
|
|
11331
|
+
onDoubleClick: isActive ? handleDoubleClick : void 0,
|
|
11332
|
+
onKeyDown: isActive ? handleKeyDown : void 0,
|
|
11333
|
+
onBlur: isActive ? handleBlur : void 0,
|
|
11334
|
+
onContextMenu: preventContextMenu,
|
|
11335
|
+
"data-testid": `cell-${cell.rowId}-${cell.field}`,
|
|
11336
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
11337
|
+
style: INNER_STYLE,
|
|
11338
|
+
children
|
|
11339
|
+
})
|
|
11340
|
+
}), menuOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LazyContextMenu, {
|
|
11341
|
+
cell,
|
|
11342
|
+
cellRef,
|
|
11343
|
+
anchorRect: menuAnchor,
|
|
11344
|
+
onClose: handleMenuClose,
|
|
11345
|
+
onEditPointerDown: deferredEdit.requestEdit
|
|
11346
|
+
})] });
|
|
11200
11347
|
});
|
|
11348
|
+
function preventContextMenu(e) {
|
|
11349
|
+
e.preventDefault();
|
|
11350
|
+
}
|
|
11201
11351
|
|
|
11202
11352
|
//#endregion
|
|
11203
11353
|
//#region src/table-editor/Table/ui/Cell/useTextareaCell.ts
|
|
@@ -11830,6 +11980,30 @@ function clearRange(range, rows, cols) {
|
|
|
11830
11980
|
}
|
|
11831
11981
|
}
|
|
11832
11982
|
|
|
11983
|
+
//#endregion
|
|
11984
|
+
//#region src/table-editor/Table/ui/borderConstants.ts
|
|
11985
|
+
const CELL_BORDER_COLOR = "#ededed";
|
|
11986
|
+
const BOTTOM_BORDER_SHADOW = `inset 0 -1px 0 0 ${CELL_BORDER_COLOR}`;
|
|
11987
|
+
function buildAddColumnShadowCss() {
|
|
11988
|
+
return { "&::after": {
|
|
11989
|
+
content: "\"\"",
|
|
11990
|
+
position: "absolute",
|
|
11991
|
+
top: 0,
|
|
11992
|
+
bottom: 0,
|
|
11993
|
+
width: "8px",
|
|
11994
|
+
left: "-8px",
|
|
11995
|
+
pointerEvents: "none",
|
|
11996
|
+
transition: "opacity 0.15s",
|
|
11997
|
+
opacity: "var(--shadow-right-opacity, 0)",
|
|
11998
|
+
boxShadow: "inset -8px 0 12px -8px rgba(0,0,0,0.1)"
|
|
11999
|
+
} };
|
|
12000
|
+
}
|
|
12001
|
+
function adjustRightOffsetCss(rightCss, addColOffset) {
|
|
12002
|
+
if (addColOffset <= 0) return rightCss;
|
|
12003
|
+
if (rightCss === "0px") return `${addColOffset}px`;
|
|
12004
|
+
return `calc(${rightCss} + ${addColOffset}px)`;
|
|
12005
|
+
}
|
|
12006
|
+
|
|
11833
12007
|
//#endregion
|
|
11834
12008
|
//#region src/table-editor/Table/ui/ResizeHandle.tsx
|
|
11835
12009
|
const MIN_COLUMN_WIDTH = 40;
|
|
@@ -12107,8 +12281,8 @@ const InsertColumnSubmenu = ({ label, valuePrefix, availableFields, onSelect })
|
|
|
12107
12281
|
//#region src/table-editor/Table/ui/Header/ColumnHeaderMenu.tsx
|
|
12108
12282
|
const ColumnHeaderMenu = (0, mobx_react_lite.observer)(({ column, columnsModel, sortModel, filterModel, onCopyPath, onClose }) => {
|
|
12109
12283
|
const canRemove = columnsModel.canRemoveColumn;
|
|
12110
|
-
const
|
|
12111
|
-
const
|
|
12284
|
+
const insertableFields = columnsModel.availableFieldsToInsert;
|
|
12285
|
+
const hasInsertableFields = insertableFields.length > 0;
|
|
12112
12286
|
const canMove = columnsModel.canMoveLeft(column.field) || columnsModel.canMoveRight(column.field);
|
|
12113
12287
|
const isPinned = columnsModel.isPinned(column.field);
|
|
12114
12288
|
const canPinLeft = columnsModel.canPinLeft(column.field);
|
|
@@ -12146,11 +12320,11 @@ const ColumnHeaderMenu = (0, mobx_react_lite.observer)(({ column, columnsModel,
|
|
|
12146
12320
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Menu.Content, {
|
|
12147
12321
|
minW: "180px",
|
|
12148
12322
|
children: [
|
|
12149
|
-
sortModel &&
|
|
12323
|
+
sortModel && column.isSortable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SortSubmenu, {
|
|
12150
12324
|
field: column.field,
|
|
12151
12325
|
sortModel
|
|
12152
12326
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.Separator, {})] }),
|
|
12153
|
-
filterModel &&
|
|
12327
|
+
filterModel && column.isSortable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_chakra_ui_react.Menu.Item, {
|
|
12154
12328
|
value: "add-filter",
|
|
12155
12329
|
onClick: handleAddFilter,
|
|
12156
12330
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_icons_lu.LuFilter, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Text, { children: "Add filter" })]
|
|
@@ -12176,17 +12350,17 @@ const ColumnHeaderMenu = (0, mobx_react_lite.observer)(({ column, columnsModel,
|
|
|
12176
12350
|
}),
|
|
12177
12351
|
(canPinLeft || canPinRight) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.Separator, {})
|
|
12178
12352
|
] }),
|
|
12179
|
-
|
|
12353
|
+
hasInsertableFields && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
12180
12354
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InsertColumnSubmenu, {
|
|
12181
12355
|
label: "Insert before",
|
|
12182
12356
|
valuePrefix: "before",
|
|
12183
|
-
availableFields,
|
|
12357
|
+
availableFields: insertableFields,
|
|
12184
12358
|
onSelect: handleInsertBefore
|
|
12185
12359
|
}),
|
|
12186
12360
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InsertColumnSubmenu, {
|
|
12187
12361
|
label: "Insert after",
|
|
12188
12362
|
valuePrefix: "after",
|
|
12189
|
-
availableFields,
|
|
12363
|
+
availableFields: insertableFields,
|
|
12190
12364
|
onSelect: handleInsertAfter
|
|
12191
12365
|
}),
|
|
12192
12366
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_chakra_ui_react.Menu.Separator, {})
|
|
@@ -12304,11 +12478,11 @@ const ColumnHeader = (0, mobx_react_lite.observer)(({ column, columnsModel, sort
|
|
|
12304
12478
|
field: column.field,
|
|
12305
12479
|
columnsModel
|
|
12306
12480
|
}),
|
|
12307
|
-
filterModel &&
|
|
12481
|
+
filterModel && column.isSortable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FilterIndicator, {
|
|
12308
12482
|
field: column.field,
|
|
12309
12483
|
filterModel
|
|
12310
12484
|
}),
|
|
12311
|
-
sortModel &&
|
|
12485
|
+
sortModel && column.isSortable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SortIndicator, {
|
|
12312
12486
|
field: column.field,
|
|
12313
12487
|
sortModel
|
|
12314
12488
|
})
|
|
@@ -13018,12 +13192,20 @@ const TableWidget = (0, mobx_react_lite.observer)(({ rows, columnsModel, cellFSM
|
|
|
13018
13192
|
if (isResizing) shadowModel.pause();
|
|
13019
13193
|
else shadowModel.resume();
|
|
13020
13194
|
}, [isResizing, shadowModel]);
|
|
13195
|
+
const [wrapperEl, setWrapperEl] = (0, react.useState)(null);
|
|
13021
13196
|
const wrapperRefCallback = (0, react.useCallback)((el) => {
|
|
13197
|
+
setWrapperEl(el);
|
|
13022
13198
|
columnsModel.setWrapperElement(el);
|
|
13023
|
-
|
|
13199
|
+
}, [columnsModel]);
|
|
13200
|
+
(0, react.useEffect)(() => {
|
|
13201
|
+
if (!useWindowScrollProp || !wrapperEl) return;
|
|
13202
|
+
setScrollerRef(wrapperEl);
|
|
13203
|
+
return () => {
|
|
13204
|
+
setScrollerRef(null);
|
|
13205
|
+
};
|
|
13024
13206
|
}, [
|
|
13025
|
-
columnsModel,
|
|
13026
13207
|
useWindowScrollProp,
|
|
13208
|
+
wrapperEl,
|
|
13027
13209
|
setScrollerRef
|
|
13028
13210
|
]);
|
|
13029
13211
|
const handleSelectRow = (0, react.useCallback)((rowId) => {
|
|
@@ -13416,67 +13598,6 @@ var ViewSettingsBadgeModel = class {
|
|
|
13416
13598
|
}
|
|
13417
13599
|
};
|
|
13418
13600
|
|
|
13419
|
-
//#endregion
|
|
13420
|
-
//#region src/table-editor/TableEditor/model/SchemaContext.ts
|
|
13421
|
-
const SYSTEM_REF_SCHEMAS = {
|
|
13422
|
-
[_revisium_schema_toolkit.SystemSchemaIds.File]: _revisium_schema_toolkit.fileSchema,
|
|
13423
|
-
[_revisium_schema_toolkit.SystemSchemaIds.RowId]: _revisium_schema_toolkit.rowIdSchema,
|
|
13424
|
-
[_revisium_schema_toolkit.SystemSchemaIds.RowCreatedAt]: _revisium_schema_toolkit.rowCreatedAtSchema,
|
|
13425
|
-
[_revisium_schema_toolkit.SystemSchemaIds.RowCreatedId]: _revisium_schema_toolkit.rowCreatedIdSchema,
|
|
13426
|
-
[_revisium_schema_toolkit.SystemSchemaIds.RowVersionId]: _revisium_schema_toolkit.rowVersionIdSchema,
|
|
13427
|
-
[_revisium_schema_toolkit.SystemSchemaIds.RowPublishedAt]: _revisium_schema_toolkit.rowPublishedAtSchema,
|
|
13428
|
-
[_revisium_schema_toolkit.SystemSchemaIds.RowUpdatedAt]: _revisium_schema_toolkit.rowUpdatedAtSchema,
|
|
13429
|
-
[_revisium_schema_toolkit.SystemSchemaIds.RowHash]: _revisium_schema_toolkit.rowHashSchema,
|
|
13430
|
-
[_revisium_schema_toolkit.SystemSchemaIds.RowSchemaHash]: _revisium_schema_toolkit.rowSchemaHashSchema
|
|
13431
|
-
};
|
|
13432
|
-
function buildRowSchema(dataSchema) {
|
|
13433
|
-
const systemProperties = {};
|
|
13434
|
-
for (const sf of SYSTEM_FIELDS) systemProperties[sf.id] = { $ref: sf.ref };
|
|
13435
|
-
return {
|
|
13436
|
-
type: "object",
|
|
13437
|
-
properties: {
|
|
13438
|
-
...systemProperties,
|
|
13439
|
-
...dataSchema.properties
|
|
13440
|
-
},
|
|
13441
|
-
additionalProperties: false,
|
|
13442
|
-
required: [...Object.keys(systemProperties), ...dataSchema.required ?? []]
|
|
13443
|
-
};
|
|
13444
|
-
}
|
|
13445
|
-
var SchemaContext = class {
|
|
13446
|
-
_allColumns = [];
|
|
13447
|
-
_dataSchema = null;
|
|
13448
|
-
_fullRefSchemas = {};
|
|
13449
|
-
_rootNode = null;
|
|
13450
|
-
get allColumns() {
|
|
13451
|
-
return this._allColumns;
|
|
13452
|
-
}
|
|
13453
|
-
get sortableFields() {
|
|
13454
|
-
return this._allColumns.filter((col) => !col.isDeprecated && col.fieldType !== FilterFieldType.File);
|
|
13455
|
-
}
|
|
13456
|
-
get filterableFields() {
|
|
13457
|
-
return this.sortableFields;
|
|
13458
|
-
}
|
|
13459
|
-
get dataSchema() {
|
|
13460
|
-
return this._dataSchema;
|
|
13461
|
-
}
|
|
13462
|
-
get fullRefSchemas() {
|
|
13463
|
-
return this._fullRefSchemas;
|
|
13464
|
-
}
|
|
13465
|
-
get rootNode() {
|
|
13466
|
-
return this._rootNode;
|
|
13467
|
-
}
|
|
13468
|
-
init(dataSchema, refSchemas) {
|
|
13469
|
-
this._dataSchema = dataSchema;
|
|
13470
|
-
this._fullRefSchemas = {
|
|
13471
|
-
...SYSTEM_REF_SCHEMAS,
|
|
13472
|
-
...refSchemas
|
|
13473
|
-
};
|
|
13474
|
-
const rowSchema = buildRowSchema(dataSchema);
|
|
13475
|
-
this._rootNode = new _revisium_schema_toolkit.SchemaParser().parse(rowSchema, this._fullRefSchemas);
|
|
13476
|
-
this._allColumns = extractColumns(this._rootNode);
|
|
13477
|
-
}
|
|
13478
|
-
};
|
|
13479
|
-
|
|
13480
13601
|
//#endregion
|
|
13481
13602
|
//#region src/table-editor/TableEditor/model/TableEditorCore.ts
|
|
13482
13603
|
const DEFAULT_PAGE_SIZE = 50;
|
|
@@ -13623,7 +13744,10 @@ var TableEditorCore = class {
|
|
|
13623
13744
|
_buildQuery(after = null) {
|
|
13624
13745
|
return {
|
|
13625
13746
|
where: this.filters.hasActiveFilters ? this.filters.buildCurrentWhereClause() : null,
|
|
13626
|
-
orderBy: this.sorts.serializeToViewSorts()
|
|
13747
|
+
orderBy: this.sorts.serializeToViewSorts().map((s) => ({
|
|
13748
|
+
field: stripDataFieldPrefix(s.field),
|
|
13749
|
+
direction: s.direction
|
|
13750
|
+
})),
|
|
13627
13751
|
search: this.search.debouncedQuery,
|
|
13628
13752
|
first: this._pageSize,
|
|
13629
13753
|
after
|
|
@@ -13658,14 +13782,14 @@ var TableEditorCore = class {
|
|
|
13658
13782
|
this._updateNavigationContext();
|
|
13659
13783
|
}
|
|
13660
13784
|
_createRowVMs(rawRows) {
|
|
13661
|
-
const
|
|
13662
|
-
if (!
|
|
13785
|
+
const wrappedSchema = this._schemaContext.wrappedDataSchema;
|
|
13786
|
+
if (!wrappedSchema) return [];
|
|
13663
13787
|
const tableModel = (0, _revisium_schema_toolkit.createTableModel)({
|
|
13664
13788
|
tableId: this._tableId,
|
|
13665
|
-
schema:
|
|
13789
|
+
schema: wrappedSchema,
|
|
13666
13790
|
rows: rawRows.map((r) => ({
|
|
13667
13791
|
rowId: r.rowId,
|
|
13668
|
-
data: r.data
|
|
13792
|
+
data: { data: r.data }
|
|
13669
13793
|
})),
|
|
13670
13794
|
refSchemas: this._schemaContext.fullRefSchemas
|
|
13671
13795
|
});
|
|
@@ -13679,10 +13803,14 @@ var TableEditorCore = class {
|
|
|
13679
13803
|
id: rawRow.rowId
|
|
13680
13804
|
};
|
|
13681
13805
|
}
|
|
13806
|
+
_toPatchField(field) {
|
|
13807
|
+
return stripDataFieldPrefix(field);
|
|
13808
|
+
}
|
|
13682
13809
|
async _commitCell(rowId, field, value, previousValue) {
|
|
13810
|
+
const patchField = this._toPatchField(field);
|
|
13683
13811
|
const result = (await this._dataSource.patchCells([{
|
|
13684
13812
|
rowId,
|
|
13685
|
-
field,
|
|
13813
|
+
field: patchField,
|
|
13686
13814
|
value
|
|
13687
13815
|
}]))[0];
|
|
13688
13816
|
if (result && !result.ok) (0, mobx.runInAction)(() => {
|
|
@@ -13762,7 +13890,7 @@ var MockDataSource = class {
|
|
|
13762
13890
|
static createRow(rowId, data, systemFields) {
|
|
13763
13891
|
const row = {
|
|
13764
13892
|
rowId,
|
|
13765
|
-
data: { ...data }
|
|
13893
|
+
data: data && typeof data === "object" && !Array.isArray(data) ? { ...data } : data
|
|
13766
13894
|
};
|
|
13767
13895
|
if (systemFields) row.systemFields = systemFields;
|
|
13768
13896
|
return row;
|
|
@@ -13781,16 +13909,23 @@ var MockDataSource = class {
|
|
|
13781
13909
|
let rows = [...this._allRows];
|
|
13782
13910
|
if (query.search) {
|
|
13783
13911
|
const lower = query.search.toLowerCase();
|
|
13784
|
-
rows = rows.filter((row) =>
|
|
13912
|
+
rows = rows.filter((row) => {
|
|
13913
|
+
const data = row.data;
|
|
13914
|
+
if (data && typeof data === "object") return Object.values(data).some((val) => typeof val === "string" && val.toLowerCase().includes(lower));
|
|
13915
|
+
if (typeof data === "string") return data.toLowerCase().includes(lower);
|
|
13916
|
+
return false;
|
|
13917
|
+
});
|
|
13785
13918
|
}
|
|
13786
13919
|
if (query.orderBy.length > 0) {
|
|
13787
13920
|
const firstOrder = query.orderBy[0];
|
|
13788
13921
|
if (firstOrder) {
|
|
13789
|
-
const field = firstOrder.field
|
|
13922
|
+
const field = firstOrder.field;
|
|
13790
13923
|
const dir = firstOrder.direction === "desc" ? -1 : 1;
|
|
13791
13924
|
rows.sort((a, b) => {
|
|
13792
|
-
const
|
|
13793
|
-
const
|
|
13925
|
+
const aData = a.data;
|
|
13926
|
+
const bData = b.data;
|
|
13927
|
+
const aVal = aData?.[field];
|
|
13928
|
+
const bVal = bData?.[field];
|
|
13794
13929
|
if (aVal === bVal) return 0;
|
|
13795
13930
|
if (aVal == null) return 1;
|
|
13796
13931
|
if (bVal == null) return -1;
|
|
@@ -13826,7 +13961,7 @@ var MockDataSource = class {
|
|
|
13826
13961
|
error: "Mock failure"
|
|
13827
13962
|
};
|
|
13828
13963
|
const row = this._allRows.find((r) => r.rowId === patch.rowId);
|
|
13829
|
-
if (row) row.data[patch.field] = patch.value;
|
|
13964
|
+
if (row?.data && typeof row.data === "object" && !Array.isArray(row.data)) row.data[patch.field] = patch.value;
|
|
13830
13965
|
return {
|
|
13831
13966
|
rowId: patch.rowId,
|
|
13832
13967
|
field: patch.field,
|