@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,298 @@
|
|
|
1
|
+
import { getCalculatedColumnDetails, getServerDataType, isCalculatedColumn, isVuuColumnDataType } from "@vuu-ui/vuu-utils";
|
|
2
|
+
const dataRowSymbol = Symbol("DataRow");
|
|
3
|
+
const dataRowIntrinsicAttributes = {
|
|
4
|
+
childCount: true,
|
|
5
|
+
depth: true,
|
|
6
|
+
index: true,
|
|
7
|
+
isExpanded: true,
|
|
8
|
+
isSelected: true,
|
|
9
|
+
isLeaf: true,
|
|
10
|
+
key: true,
|
|
11
|
+
renderIndex: true
|
|
12
|
+
};
|
|
13
|
+
const dataRowOperations = {
|
|
14
|
+
hasColumn: true
|
|
15
|
+
};
|
|
16
|
+
const isDataRowIntrinsicAttribute = (attrName)=>true === dataRowIntrinsicAttributes[attrName];
|
|
17
|
+
const isDataRowOperation = (attrName)=>true === dataRowOperations[attrName];
|
|
18
|
+
const stringNumericTypes = {
|
|
19
|
+
long: true,
|
|
20
|
+
scaleddecimal2: true,
|
|
21
|
+
scaleddecimal4: true,
|
|
22
|
+
scaleddecimal6: true,
|
|
23
|
+
scaleddecimal8: true
|
|
24
|
+
};
|
|
25
|
+
const isStringNumericType = (type)=>true === stringNumericTypes[type];
|
|
26
|
+
const MAX_DECIMALS = "0000000";
|
|
27
|
+
const TRAILING_ZEROES = /0+$/;
|
|
28
|
+
const stripTrailingZeroes = (value)=>value.endsWith("0") ? value.replace(TRAILING_ZEROES, "") : value;
|
|
29
|
+
const injectDecimalPoint = (value, decimal)=>{
|
|
30
|
+
if ("0" === value || "-0" === value || "" === value) return value;
|
|
31
|
+
if ("-" === value[0]) {
|
|
32
|
+
const digits = value.slice(1);
|
|
33
|
+
if (digits.length < decimal) return `-0.${(MAX_DECIMALS + digits).slice(-decimal)}`;
|
|
34
|
+
if (digits.length === decimal) return `-0.${stripTrailingZeroes(digits)}`;
|
|
35
|
+
return `-${digits.slice(0, -decimal)}.${digits.slice(-decimal)}`;
|
|
36
|
+
}
|
|
37
|
+
if (value.length < decimal) {
|
|
38
|
+
const decimals = (MAX_DECIMALS + value).slice(-decimal);
|
|
39
|
+
return `0.${stripTrailingZeroes(decimals)}`;
|
|
40
|
+
}
|
|
41
|
+
{
|
|
42
|
+
if (value.length === decimal) return `0.${stripTrailingZeroes(value)}`;
|
|
43
|
+
const decimals = value.slice(-decimal);
|
|
44
|
+
return `${value.slice(0, -decimal)}.${stripTrailingZeroes(decimals)}`;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const formatStringNumeric = (value, type)=>{
|
|
48
|
+
switch(type){
|
|
49
|
+
case "long":
|
|
50
|
+
return value;
|
|
51
|
+
case "scaleddecimal2":
|
|
52
|
+
return injectDecimalPoint(value, 2);
|
|
53
|
+
case "scaleddecimal4":
|
|
54
|
+
return injectDecimalPoint(value, 4);
|
|
55
|
+
case "scaleddecimal6":
|
|
56
|
+
return injectDecimalPoint(value, 6);
|
|
57
|
+
case "scaleddecimal8":
|
|
58
|
+
return injectDecimalPoint(value, 8);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
function DataRowImpl(data, columnMap) {
|
|
62
|
+
const target = {};
|
|
63
|
+
const getPropertyNames = ()=>Object.keys(columnMap);
|
|
64
|
+
const jsonSerializer = ()=>Object.entries(columnMap).reduce((json, [name, mapEntry])=>{
|
|
65
|
+
if (mapEntry) json[name] = data[mapEntry.index];
|
|
66
|
+
return json;
|
|
67
|
+
}, {});
|
|
68
|
+
const DataRowOperations = {
|
|
69
|
+
hasColumn: (name)=>void 0 !== columnMap[name]
|
|
70
|
+
};
|
|
71
|
+
return new Proxy(target, {
|
|
72
|
+
get (_obj, prop) {
|
|
73
|
+
if ("symbol" == typeof prop) {
|
|
74
|
+
if (prop === dataRowSymbol) return true;
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if ("toJSON" === prop) return jsonSerializer;
|
|
78
|
+
if ("toString" === prop) return "DataRow";
|
|
79
|
+
if ("$$typeof" === prop) return;
|
|
80
|
+
if (isDataRowOperation(prop)) return DataRowOperations[prop];
|
|
81
|
+
else if ("getPropertyNames" === prop) return getPropertyNames;
|
|
82
|
+
const columnMapEntry = columnMap[prop];
|
|
83
|
+
if (void 0 === columnMapEntry) {
|
|
84
|
+
if ("" !== prop) console.warn(`[DataRow:Proxy] unknown column ${prop}`);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (isDataRowIntrinsicAttribute(prop)) return data[columnMapEntry.index];
|
|
88
|
+
if (isStringNumericType(columnMapEntry.type)) return formatStringNumeric(data[columnMapEntry.index], columnMapEntry.type);
|
|
89
|
+
return data[columnMapEntry.index];
|
|
90
|
+
},
|
|
91
|
+
set () {
|
|
92
|
+
throw new TypeError("DataRow is readonly");
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
const ColumnMapIntrinsicColumns = {
|
|
97
|
+
index: {
|
|
98
|
+
index: 0,
|
|
99
|
+
type: "int"
|
|
100
|
+
},
|
|
101
|
+
renderIndex: {
|
|
102
|
+
index: 1,
|
|
103
|
+
type: "int"
|
|
104
|
+
},
|
|
105
|
+
isLeaf: {
|
|
106
|
+
index: 2,
|
|
107
|
+
type: "boolean"
|
|
108
|
+
},
|
|
109
|
+
isExpanded: {
|
|
110
|
+
index: 3,
|
|
111
|
+
type: "boolean"
|
|
112
|
+
},
|
|
113
|
+
depth: {
|
|
114
|
+
index: 4,
|
|
115
|
+
type: "int"
|
|
116
|
+
},
|
|
117
|
+
childCount: {
|
|
118
|
+
index: 5,
|
|
119
|
+
type: "int"
|
|
120
|
+
},
|
|
121
|
+
key: {
|
|
122
|
+
index: 6,
|
|
123
|
+
type: "string"
|
|
124
|
+
},
|
|
125
|
+
isSelected: {
|
|
126
|
+
index: 7,
|
|
127
|
+
type: "boolean"
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
function createColumnMap(columns, schemaColumns) {
|
|
131
|
+
const columnMap = {
|
|
132
|
+
...ColumnMapIntrinsicColumns
|
|
133
|
+
};
|
|
134
|
+
columns.forEach((name, i, cols)=>{
|
|
135
|
+
const schemaColumn = schemaColumns.find((col)=>col.name === name);
|
|
136
|
+
if (schemaColumn) {
|
|
137
|
+
const serverDataType = getServerDataType(schemaColumn, true);
|
|
138
|
+
columnMap[name] = {
|
|
139
|
+
index: i + 10,
|
|
140
|
+
type: serverDataType
|
|
141
|
+
};
|
|
142
|
+
} else if (isCalculatedColumn(name)) {
|
|
143
|
+
const { serverDataType } = getCalculatedColumnDetails(name);
|
|
144
|
+
if (isVuuColumnDataType(serverDataType)) columnMap[name] = {
|
|
145
|
+
index: i + 10,
|
|
146
|
+
type: serverDataType
|
|
147
|
+
};
|
|
148
|
+
else throw Error(`[DataRow] calculated column with invalid serverDataType ${name}`);
|
|
149
|
+
} else if ("vuuMsg" === name && i === cols.length - 1) columnMap[name] = {
|
|
150
|
+
index: i + 10,
|
|
151
|
+
type: "string"
|
|
152
|
+
};
|
|
153
|
+
else throw Error(`[DataRow] dataRowFactory column not in schema ${name}`);
|
|
154
|
+
});
|
|
155
|
+
if (void 0 === columnMap.vuuMsg) return {
|
|
156
|
+
...columnMap,
|
|
157
|
+
vuuMsg: {
|
|
158
|
+
index: columns.length + 10,
|
|
159
|
+
type: "string"
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
return columnMap;
|
|
163
|
+
}
|
|
164
|
+
const dataRowFactory = (columns, schemaColumns)=>{
|
|
165
|
+
let columnMap = createColumnMap(columns, schemaColumns);
|
|
166
|
+
const setColumns = (columns)=>{
|
|
167
|
+
columnMap = createColumnMap(columns, schemaColumns);
|
|
168
|
+
};
|
|
169
|
+
const DataRow = function(data) {
|
|
170
|
+
return DataRowImpl(data, columnMap);
|
|
171
|
+
};
|
|
172
|
+
return [
|
|
173
|
+
DataRow,
|
|
174
|
+
setColumns
|
|
175
|
+
];
|
|
176
|
+
};
|
|
177
|
+
if ("production" !== process.env.NODE_ENV) window.devtoolsFormatters = [
|
|
178
|
+
{
|
|
179
|
+
header: function(obj) {
|
|
180
|
+
if (obj[dataRowSymbol]) return [
|
|
181
|
+
"div",
|
|
182
|
+
{
|
|
183
|
+
style: "display: flex; gap: 4px; justify-content: space-between"
|
|
184
|
+
},
|
|
185
|
+
[
|
|
186
|
+
"span",
|
|
187
|
+
{},
|
|
188
|
+
"Vuu DataRow"
|
|
189
|
+
],
|
|
190
|
+
[
|
|
191
|
+
"span",
|
|
192
|
+
{
|
|
193
|
+
style: "font-weight: bold;"
|
|
194
|
+
},
|
|
195
|
+
`[${obj.index}]`
|
|
196
|
+
],
|
|
197
|
+
[
|
|
198
|
+
"span",
|
|
199
|
+
{
|
|
200
|
+
style: "font-weight: bold; color: blue;"
|
|
201
|
+
},
|
|
202
|
+
`#${obj.key}`
|
|
203
|
+
]
|
|
204
|
+
];
|
|
205
|
+
return null;
|
|
206
|
+
},
|
|
207
|
+
hasBody: function() {
|
|
208
|
+
return true;
|
|
209
|
+
},
|
|
210
|
+
body: function(obj) {
|
|
211
|
+
return [
|
|
212
|
+
"div",
|
|
213
|
+
{},
|
|
214
|
+
[
|
|
215
|
+
"div",
|
|
216
|
+
{
|
|
217
|
+
style: "display: flex; gap: 4px;"
|
|
218
|
+
},
|
|
219
|
+
[
|
|
220
|
+
"span",
|
|
221
|
+
{},
|
|
222
|
+
"index"
|
|
223
|
+
],
|
|
224
|
+
[
|
|
225
|
+
"span",
|
|
226
|
+
{},
|
|
227
|
+
obj.index
|
|
228
|
+
]
|
|
229
|
+
],
|
|
230
|
+
[
|
|
231
|
+
"div",
|
|
232
|
+
{
|
|
233
|
+
style: "display: flex; gap: 4px;"
|
|
234
|
+
},
|
|
235
|
+
[
|
|
236
|
+
"span",
|
|
237
|
+
{},
|
|
238
|
+
"key"
|
|
239
|
+
],
|
|
240
|
+
[
|
|
241
|
+
"span",
|
|
242
|
+
{},
|
|
243
|
+
obj.key
|
|
244
|
+
]
|
|
245
|
+
],
|
|
246
|
+
[
|
|
247
|
+
"div",
|
|
248
|
+
{
|
|
249
|
+
style: "display: flex; gap: 4px;"
|
|
250
|
+
},
|
|
251
|
+
[
|
|
252
|
+
"span",
|
|
253
|
+
{},
|
|
254
|
+
"renderIndex"
|
|
255
|
+
],
|
|
256
|
+
[
|
|
257
|
+
"span",
|
|
258
|
+
{},
|
|
259
|
+
obj.renderIndex
|
|
260
|
+
]
|
|
261
|
+
],
|
|
262
|
+
[
|
|
263
|
+
"div",
|
|
264
|
+
{
|
|
265
|
+
style: "display: flex; gap: 4px;"
|
|
266
|
+
},
|
|
267
|
+
[
|
|
268
|
+
"span",
|
|
269
|
+
{},
|
|
270
|
+
"isSelected"
|
|
271
|
+
],
|
|
272
|
+
[
|
|
273
|
+
"span",
|
|
274
|
+
{},
|
|
275
|
+
obj.isSelected
|
|
276
|
+
]
|
|
277
|
+
],
|
|
278
|
+
...obj.getPropertyNames().map((name)=>[
|
|
279
|
+
"div",
|
|
280
|
+
{
|
|
281
|
+
style: "display: flex; gap: 4px;"
|
|
282
|
+
},
|
|
283
|
+
[
|
|
284
|
+
"span",
|
|
285
|
+
{},
|
|
286
|
+
name
|
|
287
|
+
],
|
|
288
|
+
[
|
|
289
|
+
"span",
|
|
290
|
+
{},
|
|
291
|
+
obj[name]
|
|
292
|
+
]
|
|
293
|
+
])
|
|
294
|
+
];
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
];
|
|
298
|
+
export { dataRowFactory };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const css = `
|
|
2
|
+
.vuu-theme {
|
|
3
|
+
--svg-spinner: url("data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\"><path fill=\"rgb%2838, 112, 169%29\" d=\"M73,50c0-12.7-10.3-23-23-23S27,37.3,27,50 M30.9,50c0-10.5,8.5-19.1,19.1-19.1S69.1,39.5,69.1,50\"><animateTransform attributeName=\"transform\" attributeType=\"XML\" type=\"rotate\" dur=\"1s\" from=\"0 50 50\" to=\"360 50 50\" repeatCount=\"indefinite\" /></path></svg>");
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.vuuTableGroupHeaderCell {
|
|
7
|
+
--vuuColumnHeaderPill-margin: 0;
|
|
8
|
+
--cell-align: "flex-start";
|
|
9
|
+
text-align: left;
|
|
10
|
+
cursor: default;
|
|
11
|
+
--vuuColumnHeaderPill-flex: 0 0 24px;
|
|
12
|
+
background-color: var(--vuuTableHeaderCell-background, var(--table-background));
|
|
13
|
+
border-bottom: none;
|
|
14
|
+
border-right-color: var(--cell-borderColor);
|
|
15
|
+
box-sizing: border-box;
|
|
16
|
+
vertical-align: top;
|
|
17
|
+
border-right-style: solid;
|
|
18
|
+
border-right-width: 1px;
|
|
19
|
+
align-items: center;
|
|
20
|
+
gap: 4px;
|
|
21
|
+
height: 100%;
|
|
22
|
+
padding: 0 12px 0 4px;
|
|
23
|
+
display: inline-flex;
|
|
24
|
+
position: relative;
|
|
25
|
+
|
|
26
|
+
&.vuuPinLeft, &.vuuPinRight {
|
|
27
|
+
background-color: var(--vuuTableHeaderCell-background, var(--table-background));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.vuuTableGroupHeaderCell-inner {
|
|
32
|
+
align-items: center;
|
|
33
|
+
gap: 4px;
|
|
34
|
+
height: 100%;
|
|
35
|
+
padding-left: 1px;
|
|
36
|
+
display: flex;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.vuuTableGroupHeaderCell-col {
|
|
40
|
+
background-color: inherit;
|
|
41
|
+
height: calc(var(--vuuTableHeaderHeight) - 2px);
|
|
42
|
+
flex: 0 auto;
|
|
43
|
+
justify-content: space-between;
|
|
44
|
+
align-items: center;
|
|
45
|
+
padding-right: 8px;
|
|
46
|
+
display: inline-flex;
|
|
47
|
+
position: relative;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.vuuTableGroupHeaderCell-label {
|
|
51
|
+
flex: none;
|
|
52
|
+
align-items: center;
|
|
53
|
+
display: flex;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.vuuTableGroupHeaderCell-close {
|
|
57
|
+
--vuu-icon-height: 18px;
|
|
58
|
+
--vuu-icon-width: 18px;
|
|
59
|
+
cursor: pointer;
|
|
60
|
+
left: 3px;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.vuuTableGroupHeaderCell-resizing {
|
|
64
|
+
--columnResizer-color: var(--salt-color-blue-500);
|
|
65
|
+
--columnResizer-height: var(--table-height);
|
|
66
|
+
--columnResizer-width: 2px;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.vuuTableGroupHeaderCell-pending {
|
|
70
|
+
--pending-content: "";
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.vuuTableGroupHeaderCell-col:has( + .vuuColumnResizer):after {
|
|
74
|
+
content: var(--pending-content);
|
|
75
|
+
background-image: var(--svg-spinner);
|
|
76
|
+
background-repeat: no-repeat;
|
|
77
|
+
background-size: cover;
|
|
78
|
+
width: 24px;
|
|
79
|
+
height: 24px;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.vuuTableGroupHeaderCell:focus {
|
|
83
|
+
outline: var(--vuuTableCell-outline, solid var(--salt-focused-outlineColor) 2px);
|
|
84
|
+
outline-offset: -2px;
|
|
85
|
+
box-shadow: inset 0 0 0 var(--cell-outline-width) white;
|
|
86
|
+
border-bottom: none;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
`;
|
|
91
|
+
export default css;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { createElement, useCallback, useRef, useState } from "react";
|
|
3
|
+
import { OverflowContainer } from "@vuu-ui/vuu-ui-controls";
|
|
4
|
+
import { useLayoutEffectSkipFirst } from "@vuu-ui/vuu-utils";
|
|
5
|
+
import { useComponentCssInjection } from "@salt-ds/styles";
|
|
6
|
+
import { useWindow } from "@salt-ds/window";
|
|
7
|
+
import clsx from "clsx";
|
|
8
|
+
import { ColumnHeaderPill, GroupColumnPill } from "../column-header-pill/index.mjs";
|
|
9
|
+
import { ColumnResizer, useTableColumnResize } from "../column-resizing/index.mjs";
|
|
10
|
+
import { useCell } from "../useCell.mjs";
|
|
11
|
+
import GroupHeaderCell from "./GroupHeaderCell.css";
|
|
12
|
+
const classBase = "vuuTableGroupHeaderCell";
|
|
13
|
+
const switchIfChanged = (columns, newColumns)=>{
|
|
14
|
+
if (columns === newColumns) return columns;
|
|
15
|
+
return newColumns;
|
|
16
|
+
};
|
|
17
|
+
const GroupHeaderCell_GroupHeaderCell = ({ column: groupColumn, className: classNameProp, onMoveColumn, onRemoveColumn, onResize, ...htmlAttributes })=>{
|
|
18
|
+
const targetWindow = useWindow();
|
|
19
|
+
useComponentCssInjection({
|
|
20
|
+
testId: "vuu-group-header-cell",
|
|
21
|
+
css: GroupHeaderCell,
|
|
22
|
+
window: targetWindow
|
|
23
|
+
});
|
|
24
|
+
const rootRef = useRef(null);
|
|
25
|
+
const { isResizing, ...resizeProps } = useTableColumnResize({
|
|
26
|
+
column: groupColumn,
|
|
27
|
+
onResize,
|
|
28
|
+
rootRef
|
|
29
|
+
});
|
|
30
|
+
const [columns, setColumns] = useState(groupColumn.columns);
|
|
31
|
+
const { className, style } = useCell(groupColumn, classBase, true);
|
|
32
|
+
const columnPillProps = columns.length > 1 ? {
|
|
33
|
+
removable: true,
|
|
34
|
+
onRemove: onRemoveColumn
|
|
35
|
+
} : void 0;
|
|
36
|
+
const handleMoveItem = useCallback((fromIndex, toIndex)=>{
|
|
37
|
+
setColumns((cols)=>{
|
|
38
|
+
const newCols = cols.slice();
|
|
39
|
+
const [tab] = newCols.splice(fromIndex, 1);
|
|
40
|
+
if (-1 === toIndex) {
|
|
41
|
+
const result = newCols.concat(tab);
|
|
42
|
+
requestAnimationFrame(()=>onMoveColumn?.(result));
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
newCols.splice(toIndex, 0, tab);
|
|
46
|
+
requestAnimationFrame(()=>onMoveColumn?.(newCols));
|
|
47
|
+
return newCols;
|
|
48
|
+
});
|
|
49
|
+
}, [
|
|
50
|
+
onMoveColumn
|
|
51
|
+
]);
|
|
52
|
+
useLayoutEffectSkipFirst(()=>{
|
|
53
|
+
setColumns((cols)=>switchIfChanged(cols, groupColumn.columns));
|
|
54
|
+
}, [
|
|
55
|
+
groupColumn.columns
|
|
56
|
+
]);
|
|
57
|
+
const handleClick = useCallback(()=>{
|
|
58
|
+
console.log("click");
|
|
59
|
+
}, []);
|
|
60
|
+
const handleKeyDown = useCallback(()=>{
|
|
61
|
+
console.log("keydown");
|
|
62
|
+
}, []);
|
|
63
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
64
|
+
...htmlAttributes,
|
|
65
|
+
"aria-colindex": groupColumn.ariaColIndex,
|
|
66
|
+
className: clsx(className, classNameProp, {
|
|
67
|
+
[`${classBase}-pending`]: false === groupColumn.groupConfirmed
|
|
68
|
+
}),
|
|
69
|
+
ref: rootRef,
|
|
70
|
+
role: "columnheader",
|
|
71
|
+
style: style,
|
|
72
|
+
children: [
|
|
73
|
+
/*#__PURE__*/ jsx(OverflowContainer, {
|
|
74
|
+
allowDragDrop: true,
|
|
75
|
+
className: `${classBase}-inner`,
|
|
76
|
+
onMoveItem: handleMoveItem,
|
|
77
|
+
overflowPosition: "start",
|
|
78
|
+
children: columns.map((column)=>/*#__PURE__*/ createElement(GroupColumnPill, {
|
|
79
|
+
...columnPillProps,
|
|
80
|
+
column: column,
|
|
81
|
+
key: column.name,
|
|
82
|
+
onClick: handleClick,
|
|
83
|
+
onKeyDown: handleKeyDown
|
|
84
|
+
}))
|
|
85
|
+
}),
|
|
86
|
+
/*#__PURE__*/ jsx(ColumnHeaderPill, {
|
|
87
|
+
className: `${classBase}-removeAll`,
|
|
88
|
+
column: groupColumn,
|
|
89
|
+
removable: true,
|
|
90
|
+
onRemove: onRemoveColumn
|
|
91
|
+
}),
|
|
92
|
+
false !== groupColumn.resizeable ? /*#__PURE__*/ jsx(ColumnResizer, {
|
|
93
|
+
...resizeProps
|
|
94
|
+
}) : null
|
|
95
|
+
]
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
export { GroupHeaderCell_GroupHeaderCell as GroupHeaderCell };
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
const css = `
|
|
2
|
+
.vuuTableHeaderCell {
|
|
3
|
+
--selected-column-borderColor: var(--vuuTable-column-selected-borderColor, var(--salt-selectable-borderColor-selected));
|
|
4
|
+
--cell-align: "flex-start";
|
|
5
|
+
--vuuColumnHeaderPill-margin: 0;
|
|
6
|
+
--vuuColumnHeaderPill-flex: 0 0 24px;
|
|
7
|
+
background-color: var(--vuuTableHeaderCell-background, var(--table-background));
|
|
8
|
+
border-bottom: none;
|
|
9
|
+
border-right-color: var(--cell-borderColor);
|
|
10
|
+
box-sizing: border-box;
|
|
11
|
+
cursor: default;
|
|
12
|
+
vertical-align: top;
|
|
13
|
+
border-right-style: solid;
|
|
14
|
+
border-right-width: 1px;
|
|
15
|
+
align-items: center;
|
|
16
|
+
gap: 2px;
|
|
17
|
+
height: 100%;
|
|
18
|
+
padding: 0 4px 0 8px;
|
|
19
|
+
display: inline-flex;
|
|
20
|
+
position: relative;
|
|
21
|
+
|
|
22
|
+
&.vuuPinLeft, &.vuuPinRight {
|
|
23
|
+
background-color: var(--vuuTableHeaderCell-background, var(--table-background));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.vuuTableHeaderCell.vuuDragging, .vuuTableHeaderCell:focus {
|
|
28
|
+
outline: var(--vuuTableCell-outline, solid var(--salt-focused-outlineColor) 2px);
|
|
29
|
+
outline-offset: -3px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.vuuTableHeaderCell.vuuDragging {
|
|
33
|
+
height: var(--vuu-table-col-header-row-height);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.vuuTableHeaderCell-right {
|
|
37
|
+
--columnResizer-left: 0;
|
|
38
|
+
--vuuTable-columnMenu-margin: 0;
|
|
39
|
+
--column-menu-left: 2px;
|
|
40
|
+
justify-content: flex-end;
|
|
41
|
+
padding: 0 3px 0 12px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.vuuTableHeaderCell-noMenu {
|
|
45
|
+
padding-left: var(--salt-spacing-300);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.vuuTableHeaderCell-label {
|
|
49
|
+
line-height: calc(var(--vuu-table-cell-header-height) - 1px);
|
|
50
|
+
text-overflow: ellipsis;
|
|
51
|
+
white-space: nowrap;
|
|
52
|
+
flex: auto;
|
|
53
|
+
overflow: hidden;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.vuuTableHeaderCell-right .vuuTableHeaderCell-label {
|
|
57
|
+
text-align: right;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.vuuTableHeaderCell-resizing {
|
|
61
|
+
--columnResizeThumb-color: var(--vuu-color-purple-10);
|
|
62
|
+
--columnResizer-color: var(--vuu-color-purple-10);
|
|
63
|
+
--columnResizer-height: var(--table-height);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.vuuTableHeaderCell.vuuPinLeft {
|
|
67
|
+
padding-left: 2px;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.vuuTableHeaderCell.vuuPinLeft.vuuEndPin .vuuColumnResizer:before {
|
|
71
|
+
--height: calc(var(--table-height) - var(--horizontal-scrollbar-height));
|
|
72
|
+
--inset-r: calc(var(--pin-width) - 2px);
|
|
73
|
+
--inset-b: calc(var(--height) - 2px);
|
|
74
|
+
--clip-path: polygon(0% 0%,
|
|
75
|
+
0% 120%,
|
|
76
|
+
2px 120%,
|
|
77
|
+
2px 2px,
|
|
78
|
+
var(--inset-r) 2px,
|
|
79
|
+
var(--inset-r) var(--inset-b),
|
|
80
|
+
2px var(--inset-b),
|
|
81
|
+
2px 120%,
|
|
82
|
+
120% 120%,
|
|
83
|
+
120% 0%);
|
|
84
|
+
border-color: var(--vuuTablePinnedColumn-borderColor, var(--salt-container-primary-borderColor));
|
|
85
|
+
clip-path: var(--clip-path);
|
|
86
|
+
content: "";
|
|
87
|
+
width: var(--pin-width);
|
|
88
|
+
height: var(--height);
|
|
89
|
+
z-index: -5;
|
|
90
|
+
background-color: #0000;
|
|
91
|
+
border-style: solid;
|
|
92
|
+
border-width: 1px;
|
|
93
|
+
border-radius: 4px;
|
|
94
|
+
position: absolute;
|
|
95
|
+
top: 0;
|
|
96
|
+
bottom: 0;
|
|
97
|
+
right: 3px;
|
|
98
|
+
box-shadow: 2px 1px 4px #0000001a;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.vuuTableHeaderCell.vuuPinRight.vuuEndPin .vuuColumnResizer:before {
|
|
102
|
+
--height: calc(var(--table-height) - var(--horizontal-scrollbar-height));
|
|
103
|
+
--inset-r: calc(var(--pin-width) - 2px);
|
|
104
|
+
--inset-b: calc(var(--height) - 2px);
|
|
105
|
+
--clip-path: polygon(-20% 0%,
|
|
106
|
+
-20% 120%,
|
|
107
|
+
2px 120%,
|
|
108
|
+
2px 2px,
|
|
109
|
+
var(--inset-r) 2px,
|
|
110
|
+
var(--inset-r) var(--inset-b),
|
|
111
|
+
2px var(--inset-b),
|
|
112
|
+
2px 120%,
|
|
113
|
+
120% 120%,
|
|
114
|
+
120% 0%);
|
|
115
|
+
clip-path: var(--clip-path);
|
|
116
|
+
content: "";
|
|
117
|
+
width: var(--pin-width);
|
|
118
|
+
height: var(--height);
|
|
119
|
+
z-index: -5;
|
|
120
|
+
background-color: #0000;
|
|
121
|
+
border: 1px solid #a9aaad;
|
|
122
|
+
border-radius: 4px;
|
|
123
|
+
position: absolute;
|
|
124
|
+
top: 0;
|
|
125
|
+
bottom: 0;
|
|
126
|
+
right: 0;
|
|
127
|
+
box-shadow: -2px 1px 4px #0000001a;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.vuuTableHeaderCell.vuuDraggable-dragAway {
|
|
131
|
+
display: none;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.vuuTable-headingCell {
|
|
135
|
+
background: var(--dataTable-background);
|
|
136
|
+
border-color: var(--salt-separable-tertiary-borderColor);
|
|
137
|
+
color: var(--salt-content-secondary-foreground);
|
|
138
|
+
height: var(--vuu-table-col-heading-height);
|
|
139
|
+
border-style: solid solid solid none;
|
|
140
|
+
border-width: 1px;
|
|
141
|
+
display: inline-block;
|
|
142
|
+
padding: 0 !important;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.vuuTableHeaderCell:has(.saltCheckbox) {
|
|
146
|
+
padding-left: 6px;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.vuuTableHeaderCell.error {
|
|
150
|
+
--selected-column-borderColor: var(--salt-status-error-borderColor);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.vuuTableHeaderCell.info {
|
|
154
|
+
--selected-column-borderColor: var(--salt-status-info-borderColor);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.vuuTableHeaderCell.success {
|
|
158
|
+
--selected-column-borderColor: var(--salt-status-success-borderColor);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.vuuTableHeaderCell.warning {
|
|
162
|
+
--selected-column-borderColor: var(--salt-status-warning-borderColor);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.vuuTableHeaderCell-selected:after {
|
|
166
|
+
border: solid 1px var(--selected-column-borderColor);
|
|
167
|
+
clip-path: polygon(0 0, 0 100%, 100% 100%, 100% 0, 0 0, 2px 2px, calc(100% - 2px) 2px, calc(100% - 2px) calc(100% - 2px), 2px calc(100% - 2px), 2px 2px);
|
|
168
|
+
box-sizing: border-box;
|
|
169
|
+
content: "";
|
|
170
|
+
pointer-events: none;
|
|
171
|
+
height: calc(var(--table-height) - var(--horizontal-scrollbar-height) - 2px);
|
|
172
|
+
background-color: #0000;
|
|
173
|
+
border-radius: 6px;
|
|
174
|
+
width: calc(100% - 2px);
|
|
175
|
+
position: absolute;
|
|
176
|
+
top: 1px;
|
|
177
|
+
right: 1px;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
`;
|
|
182
|
+
export default css;
|