@vuu-ui/vuu-table 2.1.19-beta.1 → 2.1.19-beta.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/package.json +12 -13
- package/src/CellFocusState.mjs +25 -0
- package/src/Row.mjs +83 -0
- package/src/Table.css.js +441 -0
- package/src/Table.mjs +297 -0
- package/src/VirtualColSpan.mjs +12 -0
- package/src/applyHighlighting.mjs +28 -0
- package/src/bulk-edit/BulkEditPanel.css.js +27 -0
- package/src/bulk-edit/BulkEditPanel.mjs +77 -0
- package/src/bulk-edit/ColumnCascadingUpdateEditor.css.js +86 -0
- package/src/bulk-edit/ColumnCascadingUpdateEditor.mjs +59 -0
- package/src/bulk-edit/InsertNewRowEditor.css.js +86 -0
- package/src/bulk-edit/InsertNewRowEditor.mjs +59 -0
- package/src/bulk-edit/useBulkEditPanel.mjs +61 -0
- package/src/bulk-edit/useColumnCascadingEditor.mjs +124 -0
- package/src/cell-block/CellBlock.css.js +95 -0
- package/src/cell-block/CellBlock.mjs +32 -0
- package/src/cell-block/cellblock-utils.mjs +114 -0
- package/src/cell-block/useCellBlockSelection.mjs +245 -0
- package/src/cell-renderers/checkbox-cell/CheckboxCell.css.js +16 -0
- package/src/cell-renderers/checkbox-cell/CheckboxCell.mjs +56 -0
- package/src/cell-renderers/checkbox-cell/index.mjs +1 -0
- package/src/cell-renderers/checkbox-row-selector/CheckboxRowSelectorCell.css.js +19 -0
- package/src/cell-renderers/checkbox-row-selector/CheckboxRowSelectorCell.mjs +34 -0
- package/src/cell-renderers/checkbox-row-selector/index.mjs +1 -0
- package/src/cell-renderers/index.mjs +4 -0
- package/src/cell-renderers/input-cell/InputCell.css.js +81 -0
- package/src/cell-renderers/input-cell/InputCell.mjs +73 -0
- package/src/cell-renderers/input-cell/index.mjs +1 -0
- package/src/cell-renderers/input-cell/useInputCell.mjs +199 -0
- package/src/cell-renderers/toggle-cell/ToggleCell.css.js +31 -0
- package/src/cell-renderers/toggle-cell/ToggleCell.mjs +47 -0
- package/src/cell-renderers/toggle-cell/index.mjs +1 -0
- package/src/column-header-pill/ColumnHeaderPill.css.js +34 -0
- package/src/column-header-pill/ColumnHeaderPill.mjs +39 -0
- package/src/column-header-pill/GroupColumnPill.css.js +10 -0
- package/src/column-header-pill/GroupColumnPill.mjs +33 -0
- package/src/column-header-pill/SortIndicator.css.js +15 -0
- package/src/column-header-pill/SortIndicator.mjs +29 -0
- package/src/column-header-pill/index.mjs +3 -0
- package/src/column-resizing/ColumnResizer.css.js +32 -0
- package/src/column-resizing/ColumnResizer.mjs +69 -0
- package/src/column-resizing/index.mjs +2 -0
- package/src/column-resizing/useTableColumnResize.mjs +57 -0
- package/src/data-row/DataRow.mjs +298 -0
- package/src/header-cell/GroupHeaderCell.css.js +91 -0
- package/src/header-cell/GroupHeaderCell.mjs +98 -0
- package/src/header-cell/HeaderCell.css.js +182 -0
- package/src/header-cell/HeaderCell.mjs +126 -0
- package/src/header-cell/index.mjs +2 -0
- package/src/index.mjs +20 -0
- package/src/pagination/PaginationControl.css.js +18 -0
- package/src/pagination/PaginationControl.mjs +34 -0
- package/src/pagination/index.mjs +1 -0
- package/src/pagination/usePagination.mjs +29 -0
- package/src/table-cell/TableCell.css.js +67 -0
- package/src/table-cell/TableCell.mjs +54 -0
- package/src/table-cell/TableGroupCell.css.js +91 -0
- package/src/table-cell/TableGroupCell.mjs +61 -0
- package/src/table-cell/index.mjs +2 -0
- package/src/table-config/useTableConfig.mjs +49 -0
- package/src/table-config.mjs +38 -0
- package/src/table-data-source/DataRowMovingWindow.mjs +66 -0
- package/src/table-data-source/useDataSource.mjs +177 -0
- package/src/table-dom-utils.mjs +162 -0
- package/src/table-header/HeaderProvider.mjs +14 -0
- package/src/table-header/TableHeader.mjs +182 -0
- package/src/table-header/index.mjs +2 -0
- package/src/table-header/useTableHeader.mjs +69 -0
- package/src/useCell.mjs +22 -0
- package/src/useCellEditing.mjs +58 -0
- package/src/useCellFocus.mjs +112 -0
- package/src/useControlledTableNavigation.mjs +34 -0
- package/src/useEditableCell.mjs +18 -0
- package/src/useInitialValue.mjs +6 -0
- package/src/useKeyboardNavigation.mjs +275 -0
- package/src/useMeasuredHeight.mjs +44 -0
- package/src/useResizeObserver.mjs +118 -0
- package/src/useRowClassNameGenerators.mjs +21 -0
- package/src/useSelection.mjs +101 -0
- package/src/useTable.mjs +588 -0
- package/src/useTableContextMenu.mjs +54 -0
- package/src/useTableModel.mjs +344 -0
- package/src/useTableScroll.mjs +382 -0
- package/src/useTableViewport.mjs +120 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useComponentCssInjection } from "@salt-ds/styles";
|
|
3
|
+
import { useWindow } from "@salt-ds/window";
|
|
4
|
+
import { getDataItemEditControl } from "@vuu-ui/vuu-data-react";
|
|
5
|
+
import clsx from "clsx";
|
|
6
|
+
import { VirtualColSpan } from "../VirtualColSpan.mjs";
|
|
7
|
+
import { useHeaderProps } from "../table-header/index.mjs";
|
|
8
|
+
import { useBulkEditRow } from "./useColumnCascadingEditor.mjs";
|
|
9
|
+
import { isNotHidden } from "@vuu-ui/vuu-utils";
|
|
10
|
+
import InsertNewRowEditor from "./InsertNewRowEditor.css";
|
|
11
|
+
const classBase = "vuuBulkEditRow";
|
|
12
|
+
const InsertNewRowEditor_InsertNewRowEditor = ({ ariaRole, onBulkChange, onRowChange, ...htmlAttributes })=>{
|
|
13
|
+
const targetWindow = useWindow();
|
|
14
|
+
useComponentCssInjection({
|
|
15
|
+
testId: "vuu-bulk-edit-row",
|
|
16
|
+
css: InsertNewRowEditor,
|
|
17
|
+
window: targetWindow
|
|
18
|
+
});
|
|
19
|
+
const { columns, virtualColSpan = 0 } = useHeaderProps();
|
|
20
|
+
const { errorMessages, formFieldsContainerRef, InputProps, onCommit, onFocus, onKeyDown } = useBulkEditRow({
|
|
21
|
+
descriptors: columns,
|
|
22
|
+
onBulkChange,
|
|
23
|
+
onRowChange
|
|
24
|
+
});
|
|
25
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
26
|
+
...htmlAttributes,
|
|
27
|
+
className: classBase,
|
|
28
|
+
onFocus: onFocus,
|
|
29
|
+
onKeyDown: onKeyDown,
|
|
30
|
+
ref: formFieldsContainerRef,
|
|
31
|
+
role: ariaRole,
|
|
32
|
+
children: [
|
|
33
|
+
/*#__PURE__*/ jsx(VirtualColSpan, {
|
|
34
|
+
width: virtualColSpan
|
|
35
|
+
}),
|
|
36
|
+
columns.filter(isNotHidden).map((column, i)=>{
|
|
37
|
+
const errorMessage = errorMessages[column.name];
|
|
38
|
+
return /*#__PURE__*/ jsx("div", {
|
|
39
|
+
"aria-colindex": i + 1,
|
|
40
|
+
className: clsx(`${classBase}Cell`, "vuuTableCell", {
|
|
41
|
+
"vuuTableCell-right": "right" === column.align
|
|
42
|
+
}),
|
|
43
|
+
"data-field": column.name,
|
|
44
|
+
role: "cell",
|
|
45
|
+
style: {
|
|
46
|
+
width: column.width
|
|
47
|
+
},
|
|
48
|
+
children: column.editable ? getDataItemEditControl({
|
|
49
|
+
InputProps,
|
|
50
|
+
dataDescriptor: column,
|
|
51
|
+
errorMessage,
|
|
52
|
+
onCommit
|
|
53
|
+
}) : null
|
|
54
|
+
}, column.name);
|
|
55
|
+
})
|
|
56
|
+
]
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
export { InsertNewRowEditor_InsertNewRowEditor as InsertNewRowEditor };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { buildValidationChecker } from "@vuu-ui/vuu-data-react";
|
|
2
|
+
import { hasValidationRules, isTypeDescriptor } from "@vuu-ui/vuu-utils";
|
|
3
|
+
import { useCallback, useMemo, useState } from "react";
|
|
4
|
+
const addRenderer = (colType, rendererName)=>({
|
|
5
|
+
name: colType.name,
|
|
6
|
+
rules: colType.rules,
|
|
7
|
+
formatting: colType.formatting,
|
|
8
|
+
renderer: {
|
|
9
|
+
name: rendererName
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
const useBulkEditPanel = ({ columns, sessionDs: dataSource })=>{
|
|
13
|
+
const [rowState, setRowState] = useState(true);
|
|
14
|
+
const tableConfig = useMemo(()=>({
|
|
15
|
+
columns: columns ? columns.map((col)=>({
|
|
16
|
+
editable: "bulk" === col.editableBulk,
|
|
17
|
+
hidden: false === col.editableBulk,
|
|
18
|
+
name: col.name,
|
|
19
|
+
serverDataType: col.serverDataType ?? "string",
|
|
20
|
+
type: isTypeDescriptor(col.type) ? addRenderer(col.type, "input-cell") : "string",
|
|
21
|
+
clientSideEditValidationCheck: hasValidationRules(col.type) ? buildValidationChecker(col.type.rules) : void 0,
|
|
22
|
+
width: 120
|
|
23
|
+
})) : dataSource.columns.map((name)=>({
|
|
24
|
+
editable: true,
|
|
25
|
+
name,
|
|
26
|
+
serverDataType: "string"
|
|
27
|
+
})),
|
|
28
|
+
columnLayout: "fit",
|
|
29
|
+
columnDefaultWidth: 100,
|
|
30
|
+
rowSeparators: true
|
|
31
|
+
}), [
|
|
32
|
+
columns,
|
|
33
|
+
dataSource.columns
|
|
34
|
+
]);
|
|
35
|
+
const handleRowChange = useCallback((isValid)=>{
|
|
36
|
+
if (isValid !== rowState) setRowState(isValid);
|
|
37
|
+
}, [
|
|
38
|
+
rowState
|
|
39
|
+
]);
|
|
40
|
+
const handleBulkChange = useCallback(async (column, value)=>{
|
|
41
|
+
const response = await dataSource.rpcRequest?.({
|
|
42
|
+
params: {
|
|
43
|
+
column: column.name,
|
|
44
|
+
value
|
|
45
|
+
},
|
|
46
|
+
rpcName: "VP_BULK_EDIT_COLUMN_CELLS_RPC",
|
|
47
|
+
type: "RPC_REQUEST"
|
|
48
|
+
});
|
|
49
|
+
console.log({
|
|
50
|
+
response
|
|
51
|
+
});
|
|
52
|
+
}, [
|
|
53
|
+
dataSource
|
|
54
|
+
]);
|
|
55
|
+
return {
|
|
56
|
+
tableConfig,
|
|
57
|
+
onBulkChange: handleBulkChange,
|
|
58
|
+
onRowChange: handleRowChange
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
export { useBulkEditPanel };
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { buildValidationChecker, getEditValidationRules } from "@vuu-ui/vuu-data-react";
|
|
2
|
+
import { getTypedValue, queryClosest } from "@vuu-ui/vuu-utils";
|
|
3
|
+
import { useCallback, useMemo, useRef, useState } from "react";
|
|
4
|
+
import { useEditableCell } from "../useEditableCell.mjs";
|
|
5
|
+
const getValidationChecker = (descriptor, editPhase)=>{
|
|
6
|
+
const rules = getEditValidationRules(descriptor, editPhase);
|
|
7
|
+
return buildValidationChecker(rules);
|
|
8
|
+
};
|
|
9
|
+
const nextValidationState = (state, dataDescriptor, value)=>{
|
|
10
|
+
const check = getValidationChecker(dataDescriptor, "change");
|
|
11
|
+
const result = check(value, "change");
|
|
12
|
+
const { name } = dataDescriptor;
|
|
13
|
+
const { ok: wasOk, messages: existingMessages } = state;
|
|
14
|
+
if (!result.ok) return {
|
|
15
|
+
ok: false,
|
|
16
|
+
messages: {
|
|
17
|
+
...existingMessages,
|
|
18
|
+
[name]: result.messages.join("\n")
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
if (!wasOk) {
|
|
22
|
+
const fieldsInError = Object.keys(existingMessages);
|
|
23
|
+
if (fieldsInError.includes(name)) if (1 === fieldsInError.length) return {
|
|
24
|
+
ok: true,
|
|
25
|
+
messages: {}
|
|
26
|
+
};
|
|
27
|
+
else {
|
|
28
|
+
const messages = {
|
|
29
|
+
...existingMessages
|
|
30
|
+
};
|
|
31
|
+
delete messages[name];
|
|
32
|
+
return {
|
|
33
|
+
ok: false,
|
|
34
|
+
messages
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return state;
|
|
39
|
+
};
|
|
40
|
+
function find(descriptors, fieldname) {
|
|
41
|
+
const d = descriptors.find(({ name })=>name === fieldname);
|
|
42
|
+
if (d) return d;
|
|
43
|
+
throw Error(`DataValueDescriptor not found for field ${fieldname}`);
|
|
44
|
+
}
|
|
45
|
+
const getField = (target)=>{
|
|
46
|
+
const fieldElement = queryClosest(target, "[data-field]");
|
|
47
|
+
if (fieldElement) return fieldElement.dataset.field;
|
|
48
|
+
throw Error("no field ");
|
|
49
|
+
};
|
|
50
|
+
const useBulkEditRow = ({ descriptors, onBulkChange, onRowChange })=>{
|
|
51
|
+
const formFieldsContainerRef = useRef(null);
|
|
52
|
+
const focusedFieldRef = useRef("");
|
|
53
|
+
const [, forceUpdate] = useState({});
|
|
54
|
+
const validationStateRef = useRef({
|
|
55
|
+
ok: true,
|
|
56
|
+
messages: {}
|
|
57
|
+
});
|
|
58
|
+
const bulkRowValidationState = useCallback((state)=>{
|
|
59
|
+
validationStateRef.current = state;
|
|
60
|
+
onRowChange(state.ok);
|
|
61
|
+
forceUpdate({});
|
|
62
|
+
}, [
|
|
63
|
+
onRowChange
|
|
64
|
+
]);
|
|
65
|
+
const handleFocus = useCallback((evt)=>{
|
|
66
|
+
if (formFieldsContainerRef.current?.contains(evt.target)) {
|
|
67
|
+
const fieldName = getField(evt.target);
|
|
68
|
+
if (fieldName) {
|
|
69
|
+
if (fieldName) focusedFieldRef.current = fieldName;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}, []);
|
|
73
|
+
const handleChange = useCallback((evt)=>{
|
|
74
|
+
const { current: fieldName } = focusedFieldRef;
|
|
75
|
+
if (fieldName) {
|
|
76
|
+
const input = queryClosest(evt.target, "input", true);
|
|
77
|
+
const dataDescriptor = find(descriptors, fieldName);
|
|
78
|
+
const value = input.value;
|
|
79
|
+
const { current: state } = validationStateRef;
|
|
80
|
+
const newState = nextValidationState(state, dataDescriptor, value);
|
|
81
|
+
if (newState !== state) bulkRowValidationState(newState);
|
|
82
|
+
}
|
|
83
|
+
}, [
|
|
84
|
+
descriptors,
|
|
85
|
+
bulkRowValidationState
|
|
86
|
+
]);
|
|
87
|
+
const { current: { messages: errorMessages } } = validationStateRef;
|
|
88
|
+
const handleCommit = useCallback((evt, value)=>{
|
|
89
|
+
if ("string" == typeof value && "" !== value.trim()) {
|
|
90
|
+
const columnName = focusedFieldRef.current;
|
|
91
|
+
if (columnName) {
|
|
92
|
+
const column = descriptors.find((c)=>c.name === columnName);
|
|
93
|
+
if (column && void 0 === errorMessages[columnName]) {
|
|
94
|
+
const { serverDataType = "string" } = column;
|
|
95
|
+
const typedValue = getTypedValue(value, serverDataType, true);
|
|
96
|
+
onBulkChange(column, typedValue);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}, [
|
|
101
|
+
descriptors,
|
|
102
|
+
errorMessages,
|
|
103
|
+
onBulkChange
|
|
104
|
+
]);
|
|
105
|
+
const InputProps = useMemo(()=>({
|
|
106
|
+
inputProps: {
|
|
107
|
+
placeholder: "Enter value"
|
|
108
|
+
},
|
|
109
|
+
onChange: handleChange,
|
|
110
|
+
variant: "primary"
|
|
111
|
+
}), [
|
|
112
|
+
handleChange
|
|
113
|
+
]);
|
|
114
|
+
const onKeyDown = useEditableCell();
|
|
115
|
+
return {
|
|
116
|
+
errorMessages,
|
|
117
|
+
formFieldsContainerRef,
|
|
118
|
+
InputProps,
|
|
119
|
+
onCommit: handleCommit,
|
|
120
|
+
onFocus: handleFocus,
|
|
121
|
+
onKeyDown
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
export { useBulkEditRow };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
const css = `
|
|
2
|
+
.vuuCellBlock {
|
|
3
|
+
opacity: .3;
|
|
4
|
+
bottom: anchor(--cellblock-start bottom);
|
|
5
|
+
left: anchor(--cellblock-start left);
|
|
6
|
+
right: anchor(--cellblock-start right);
|
|
7
|
+
top: anchor(--cellblock-start top);
|
|
8
|
+
background-color: #00bdff;
|
|
9
|
+
border: 1px solid #00f;
|
|
10
|
+
position: absolute;
|
|
11
|
+
|
|
12
|
+
&.cellblock-direction-n {
|
|
13
|
+
bottom: anchor(--cellblock-start bottom);
|
|
14
|
+
left: anchor(--cellblock-start left);
|
|
15
|
+
right: anchor(--cellblock-start right);
|
|
16
|
+
top: anchor(--cellblock-end top);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
&.cellblock-direction-ne {
|
|
20
|
+
bottom: anchor(--cellblock-start bottom);
|
|
21
|
+
left: anchor(--cellblock-start left);
|
|
22
|
+
right: anchor(--cellblock-end right);
|
|
23
|
+
top: anchor(--cellblock-end top);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&.cellblock-direction-e {
|
|
27
|
+
bottom: anchor(--cellblock-start bottom);
|
|
28
|
+
left: anchor(--cellblock-start left);
|
|
29
|
+
right: anchor(--cellblock-end right);
|
|
30
|
+
top: anchor(--cellblock-start top);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&.cellblock-direction-se {
|
|
34
|
+
bottom: anchor(--cellblock-end bottom);
|
|
35
|
+
left: anchor(--cellblock-start left);
|
|
36
|
+
right: anchor(--cellblock-end right);
|
|
37
|
+
top: anchor(--cellblock-start top);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
&.cellblock-direction-s {
|
|
41
|
+
bottom: anchor(--cellblock-end bottom);
|
|
42
|
+
left: anchor(--cellblock-start left);
|
|
43
|
+
right: anchor(--cellblock-start right);
|
|
44
|
+
top: anchor(--cellblock-start top);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
&.cellblock-direction-sw {
|
|
48
|
+
bottom: anchor(--cellblock-end bottom);
|
|
49
|
+
left: anchor(--cellblock-end left);
|
|
50
|
+
right: anchor(--cellblock-start right);
|
|
51
|
+
top: anchor(--cellblock-start top);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&.cellblock-direction-w {
|
|
55
|
+
bottom: anchor(--cellblock-start bottom);
|
|
56
|
+
left: anchor(--cellblock-end left);
|
|
57
|
+
right: anchor(--cellblock-start right);
|
|
58
|
+
top: anchor(--cellblock-start top);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
&.cellblock-direction-nw {
|
|
62
|
+
bottom: anchor(--cellblock-start bottom);
|
|
63
|
+
left: anchor(--cellblock-end left);
|
|
64
|
+
right: anchor(--cellblock-start right);
|
|
65
|
+
top: anchor(--cellblock-end top);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.vuu-cellblock-start {
|
|
70
|
+
anchor-name: --cellblock-start;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.vuuTable.vuu-cellblock-select-in-progress-keyboard {
|
|
74
|
+
& .vuuTableCell:focus {
|
|
75
|
+
anchor-name: --cellblock-end;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
& .vuuCellBlock {
|
|
79
|
+
pointer-events: none;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.vuuTable.vuu-cellblock-select-in-progress-mouse {
|
|
84
|
+
& .vuuCellBlock {
|
|
85
|
+
pointer-events: none;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.vuu-cellblock-end {
|
|
90
|
+
anchor-name: --cellblock-end;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
`;
|
|
95
|
+
export default css;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useCallback } from "react";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import { useComponentCssInjection } from "@salt-ds/styles";
|
|
5
|
+
import { useWindow } from "@salt-ds/window";
|
|
6
|
+
import CellBlock_0 from "./CellBlock.css";
|
|
7
|
+
const classBase = "vuuCellBlock";
|
|
8
|
+
const CellBlock_CellBlock = /*#__PURE__*/ forwardRef(function({ className, onCopy, ...htmlAttributes }, forwardedRef) {
|
|
9
|
+
const targetWindow = useWindow();
|
|
10
|
+
useComponentCssInjection({
|
|
11
|
+
testId: "vuu-cell-block",
|
|
12
|
+
css: CellBlock_0,
|
|
13
|
+
window: targetWindow
|
|
14
|
+
});
|
|
15
|
+
const handleKeyDown = useCallback(async (evt)=>{
|
|
16
|
+
if (evt.metaKey && "c" === evt.key) onCopy?.();
|
|
17
|
+
}, [
|
|
18
|
+
onCopy
|
|
19
|
+
]);
|
|
20
|
+
const onContextMenu = useCallback(()=>{
|
|
21
|
+
console.log("on cvontext menu");
|
|
22
|
+
}, []);
|
|
23
|
+
return /*#__PURE__*/ jsx("div", {
|
|
24
|
+
...htmlAttributes,
|
|
25
|
+
className: clsx(classBase, className),
|
|
26
|
+
ref: forwardedRef,
|
|
27
|
+
onContextMenu: onContextMenu,
|
|
28
|
+
onKeyDown: handleKeyDown,
|
|
29
|
+
tabIndex: 0
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
export { CellBlock_CellBlock as CellBlock };
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { getAriaColIndex, getAriaRowIndex, queryClosest } from "@vuu-ui/vuu-utils";
|
|
2
|
+
import { getAriaCellPos } from "../table-dom-utils.mjs";
|
|
3
|
+
const isNullCellBox = ({ bottom, left, right, top })=>-1 === bottom && -1 === left && -1 === right && -1 === top;
|
|
4
|
+
const Hi = Number.MAX_SAFE_INTEGER;
|
|
5
|
+
const getEndCellDirection = (startBox, endBox)=>{
|
|
6
|
+
const { bottom: sBottom, left: sLeft, right: sRight, top: sTop } = startBox;
|
|
7
|
+
const { bottom: eBottom, left: eLeft, right: eRight, top: eTop } = endBox;
|
|
8
|
+
const north = eTop < sTop;
|
|
9
|
+
const east = eRight > sRight;
|
|
10
|
+
const south = eBottom > sBottom;
|
|
11
|
+
const west = eLeft < sLeft;
|
|
12
|
+
if (north && east) return "ne";
|
|
13
|
+
if (south && east) return "se";
|
|
14
|
+
if (south && west) return "sw";
|
|
15
|
+
if (north && west) return "nw";
|
|
16
|
+
if (north) return "n";
|
|
17
|
+
else if (east) return "e";
|
|
18
|
+
else if (south) return "s";
|
|
19
|
+
else if (west) return "w";
|
|
20
|
+
else return "self";
|
|
21
|
+
};
|
|
22
|
+
const setElementBox = (el, box)=>{
|
|
23
|
+
const { bottom, left, right, top } = el.getBoundingClientRect();
|
|
24
|
+
box.bottom = bottom;
|
|
25
|
+
box.left = left;
|
|
26
|
+
box.right = right;
|
|
27
|
+
box.top = top;
|
|
28
|
+
};
|
|
29
|
+
const outsideBox = ({ bottom, left, right, top }, x, y)=>x < left || x > right || y < top || y > bottom;
|
|
30
|
+
const getRowIndex = (cell)=>getAriaRowIndex(queryClosest(cell, ".vuuTableRow"));
|
|
31
|
+
const getTableCellBlock = (startCell, endCell)=>{
|
|
32
|
+
const colStart = getAriaColIndex(startCell);
|
|
33
|
+
const colEnd = getAriaColIndex(endCell);
|
|
34
|
+
const rowStart = getRowIndex(startCell);
|
|
35
|
+
const rowEnd = getRowIndex(endCell);
|
|
36
|
+
const columnRange = {
|
|
37
|
+
from: Math.min(colStart, colEnd),
|
|
38
|
+
to: Math.max(colStart, colEnd)
|
|
39
|
+
};
|
|
40
|
+
const rowRange = {
|
|
41
|
+
from: Math.min(rowStart, rowEnd),
|
|
42
|
+
to: Math.max(rowStart, rowEnd)
|
|
43
|
+
};
|
|
44
|
+
return {
|
|
45
|
+
columnRange,
|
|
46
|
+
rowRange
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
const refState = {
|
|
50
|
+
cellBlock: null,
|
|
51
|
+
cellBlockClassName: "",
|
|
52
|
+
dragState: "pending",
|
|
53
|
+
endBox: {
|
|
54
|
+
bottom: -1,
|
|
55
|
+
left: Hi,
|
|
56
|
+
right: -1,
|
|
57
|
+
top: Hi
|
|
58
|
+
},
|
|
59
|
+
endCell: null,
|
|
60
|
+
endPos: [
|
|
61
|
+
-1,
|
|
62
|
+
-1
|
|
63
|
+
],
|
|
64
|
+
mousePosX: -1,
|
|
65
|
+
mousePosY: -1,
|
|
66
|
+
mouseStartX: -1,
|
|
67
|
+
mouseStartY: -1,
|
|
68
|
+
startBox: {
|
|
69
|
+
bottom: -1,
|
|
70
|
+
left: -1,
|
|
71
|
+
right: -1,
|
|
72
|
+
top: -1
|
|
73
|
+
},
|
|
74
|
+
startCell: null,
|
|
75
|
+
startPos: [
|
|
76
|
+
-1,
|
|
77
|
+
-1
|
|
78
|
+
]
|
|
79
|
+
};
|
|
80
|
+
const updateCellBlockClassName = (state)=>{
|
|
81
|
+
const { cellBlock, cellBlockClassName, startBox, endBox } = state;
|
|
82
|
+
const endBlockDirection = getEndCellDirection(startBox, endBox);
|
|
83
|
+
const newCellBlockClassName = `cellblock-direction-${endBlockDirection}`;
|
|
84
|
+
if (newCellBlockClassName !== cellBlockClassName) {
|
|
85
|
+
if (cellBlockClassName) cellBlock?.classList.replace(cellBlockClassName, newCellBlockClassName);
|
|
86
|
+
else cellBlock?.classList.add(newCellBlockClassName);
|
|
87
|
+
state.cellBlockClassName = newCellBlockClassName;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
const getTextFromCells = (startCell, endCell)=>{
|
|
91
|
+
const tableBody = queryClosest(startCell, ".vuuTable-body", true);
|
|
92
|
+
const [startRow, startCol] = getAriaCellPos(startCell);
|
|
93
|
+
const [endRow, endCol] = getAriaCellPos(endCell);
|
|
94
|
+
const rowRange = {
|
|
95
|
+
from: Math.min(startRow, endRow),
|
|
96
|
+
to: Math.max(startRow, endRow)
|
|
97
|
+
};
|
|
98
|
+
const colRange = {
|
|
99
|
+
from: Math.min(startCol, endCol),
|
|
100
|
+
to: Math.max(startCol, endCol)
|
|
101
|
+
};
|
|
102
|
+
const results = [];
|
|
103
|
+
for(let rowIdx = rowRange.from; rowIdx <= rowRange.to; rowIdx++){
|
|
104
|
+
const row = tableBody.querySelector(`.vuuTableRow[aria-rowindex='${rowIdx}']`);
|
|
105
|
+
const rowData = [];
|
|
106
|
+
for(let colIdx = colRange.from; colIdx <= colRange.to; colIdx++){
|
|
107
|
+
const cell = row?.querySelector(`.vuuTableCell[aria-colindex='${colIdx}']`);
|
|
108
|
+
if (cell) rowData.push(cell.textContent ?? "");
|
|
109
|
+
}
|
|
110
|
+
results.push(rowData);
|
|
111
|
+
}
|
|
112
|
+
return results.map((r)=>r.join("\t")).join("\n");
|
|
113
|
+
};
|
|
114
|
+
export { getEndCellDirection, getTableCellBlock, getTextFromCells, isNullCellBox, outsideBox, refState, setElementBox, updateCellBlockClassName };
|