@vuu-ui/vuu-table-extras 4.0.0-alpha.1 → 4.0.0-alpha.10
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 +14 -12
- package/src/calculated-column/CalculatedColumnPanel.js +2 -2
- package/src/calculated-column/useEditCalculatedColumn.js +1 -1
- package/src/column-picker/ColumnModel.js +14 -25
- package/src/column-picker/ColumnPicker.css.js +0 -86
- package/src/column-picker/ColumnPicker.js +12 -180
- package/src/column-picker/useColumnPicker.js +28 -22
- package/src/csv-upload/CsvUpload.css.js +34 -0
- package/src/csv-upload/CsvUpload.js +109 -45
- package/src/csv-upload/parse/csv-constants.js +2 -2
- package/src/csv-upload/parse/csv-errors.js +2 -1
- package/src/csv-upload/parse/csv-parse.js +1 -1
- package/src/csv-upload/parse/csv-schema-validation.js +54 -6
- package/src/csv-upload/useCsvUpload.js +16 -16
- package/src/tabbed-table-config-panel/TabbedTableConfigPanel.js +17 -8
- package/src/tabbed-table-config-panel/useTabbedTableConfigPanel.js +1 -1
- package/types/calculated-column/CalculatedColumnPanel.d.ts +2 -2
- package/types/column-picker/ColumnModel.d.ts +4 -3
- package/types/column-picker/ColumnPicker.d.ts +4 -6
- package/types/column-picker/useColumnPicker.d.ts +7 -10
- package/types/column-settings-panel/useColumnSettings.d.ts +3 -3
- package/types/csv-upload/CsvUpload.d.ts +3 -6
- package/types/csv-upload/data-upload-preview/useDataUploadPreview.d.ts +1 -1
- package/types/csv-upload/index.d.ts +1 -1
- package/types/csv-upload/parse/csv-constants.d.ts +2 -2
- package/types/csv-upload/parse/csv-errors.d.ts +3 -2
- package/types/csv-upload/parse/csv-schema-validation.d.ts +10 -2
- package/types/csv-upload/parse/index.d.ts +1 -1
- package/types/csv-upload/useCsvUpload.d.ts +4 -3
- package/types/index.d.ts +0 -1
- package/types/src/csv-upload/CsvUpload.d.ts +2 -1
- package/types/src/csv-upload/index.d.ts +1 -1
- package/types/src/csv-upload/parse/csv-constants.d.ts +2 -2
- package/types/src/csv-upload/parse/csv-errors.d.ts +2 -1
- package/types/src/csv-upload/parse/csv-schema-validation.d.ts +2 -0
- package/types/src/csv-upload/parse/index.d.ts +1 -1
- package/types/src/csv-upload/useCsvUpload.d.ts +3 -2
- package/types/tabbed-table-config-panel/useTabbedTableConfigPanel.d.ts +4 -3
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "4.0.0-alpha.
|
|
2
|
+
"version": "4.0.0-alpha.10",
|
|
3
3
|
"author": "heswell",
|
|
4
4
|
"main": "./src/index.js",
|
|
5
5
|
"license": "Apache-2.0",
|
|
@@ -12,19 +12,20 @@
|
|
|
12
12
|
"lezer-generate:column": "lezer-generator --output ./src/column-expression-input/column-language-parser/generated/column-parser.ts ./src/column-expression-input/column-language-parser/grammar/column.grammar"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@vuu-ui/vuu-filter-types": "4.0.0-alpha.
|
|
16
|
-
"@vuu-ui/vuu-protocol-types": "4.0.0-alpha.
|
|
15
|
+
"@vuu-ui/vuu-filter-types": "4.0.0-alpha.10",
|
|
16
|
+
"@vuu-ui/vuu-protocol-types": "4.0.0-alpha.10"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@vuu-ui/
|
|
20
|
-
"@vuu-ui/vuu-
|
|
21
|
-
"@vuu-ui/vuu-data-
|
|
22
|
-
"@vuu-ui/vuu-data-
|
|
23
|
-
"@vuu-ui/vuu-
|
|
24
|
-
"@vuu-ui/vuu-
|
|
25
|
-
"@vuu-ui/vuu-
|
|
26
|
-
"@vuu-ui/vuu-
|
|
27
|
-
"@vuu-ui/vuu-
|
|
19
|
+
"@vuu-ui/core": "4.0.0-alpha.10",
|
|
20
|
+
"@vuu-ui/vuu-codemirror": "4.0.0-alpha.10",
|
|
21
|
+
"@vuu-ui/vuu-data-editing": "4.0.0-alpha.10",
|
|
22
|
+
"@vuu-ui/vuu-data-react": "4.0.0-alpha.10",
|
|
23
|
+
"@vuu-ui/vuu-data-types": "4.0.0-alpha.10",
|
|
24
|
+
"@vuu-ui/vuu-table-types": "4.0.0-alpha.10",
|
|
25
|
+
"@vuu-ui/vuu-popups": "4.0.0-alpha.10",
|
|
26
|
+
"@vuu-ui/vuu-table": "4.0.0-alpha.10",
|
|
27
|
+
"@vuu-ui/vuu-utils": "4.0.0-alpha.10",
|
|
28
|
+
"@vuu-ui/vuu-ui-controls": "4.0.0-alpha.10",
|
|
28
29
|
"@lezer/lr": "1.4.2",
|
|
29
30
|
"@salt-ds/core": "1.67.0",
|
|
30
31
|
"@salt-ds/lab": "1.0.0-alpha.99",
|
|
@@ -46,6 +47,7 @@
|
|
|
46
47
|
"exports": {
|
|
47
48
|
".": {
|
|
48
49
|
"import": "./src/index.js",
|
|
50
|
+
"default": "./src/index.js",
|
|
49
51
|
"types": "./types/index.d.ts"
|
|
50
52
|
}
|
|
51
53
|
},
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Dropdown, FormField, FormFieldLabel, Input, Option } from "@salt-ds/core";
|
|
3
|
-
import { useCalculatedColumnPanel } from "./useCalculatedColumnPanel.js";
|
|
4
|
-
import { useCallback, useRef } from "react";
|
|
5
3
|
import { getCalculatedColumnDetails } from "@vuu-ui/vuu-utils";
|
|
4
|
+
import { useCallback, useRef } from "react";
|
|
6
5
|
import { ColumnExpressionInput, useColumnExpressionSuggestionProvider } from "../column-expression-input/index.js";
|
|
6
|
+
import { useCalculatedColumnPanel } from "./useCalculatedColumnPanel.js";
|
|
7
7
|
const classBase = "vuuCalculatedColumnPanel";
|
|
8
8
|
const CalculatedColumnPanel = ({ column: columnProp, columnModel, onChangeColumn, onChangeServerDataType: onChangeServerDataTypeProp, vuuTable })=>{
|
|
9
9
|
const typeRef = useRef(null);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useModal } from "@vuu-ui/
|
|
2
|
+
import { useModal } from "@vuu-ui/core";
|
|
3
3
|
import { useCallback, useRef } from "react";
|
|
4
4
|
import { CalculatedColumnPanel } from "./CalculatedColumnPanel.js";
|
|
5
5
|
const useEditCalculatedColumn = ({ calculatedColumn, columnModel, onSaveColumn, vuuTable })=>{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventEmitter, reorderItems } from "@vuu-ui/vuu-utils";
|
|
1
|
+
import { EventEmitter, getAddedItems, getRemovedItems, itemsOrOrderChanged, reorderItems } from "@vuu-ui/vuu-utils";
|
|
2
2
|
const ColumnChangeSource = {
|
|
3
3
|
ColumnPicker: "column-picker",
|
|
4
4
|
ColumnSettings: "column-settings",
|
|
@@ -15,37 +15,16 @@ const isColumnAdded = (change)=>change?.type === SelectedColumnChangeType.Column
|
|
|
15
15
|
const isColumnRemoved = (change)=>change?.type === SelectedColumnChangeType.ColumnRemoved;
|
|
16
16
|
const isColumnUpdated = (change)=>change?.type === SelectedColumnChangeType.ColumnUpdated;
|
|
17
17
|
const isColumnsReordered = (change)=>change?.type === SelectedColumnChangeType.ColumnsReordered;
|
|
18
|
-
const
|
|
19
|
-
const filterColumns = (columns, pattern)=>{
|
|
20
|
-
if (!pattern) return columns;
|
|
21
|
-
{
|
|
22
|
-
const lowerCasePattern = pattern.toLowerCase();
|
|
23
|
-
return columns.filter(({ name, label = name })=>-1 !== label.toLowerCase().indexOf(lowerCasePattern));
|
|
24
|
-
}
|
|
25
|
-
};
|
|
18
|
+
const columnDescriptorComparator = (col1, col2)=>col1.name === col2.name;
|
|
26
19
|
class ColumnModel extends EventEmitter {
|
|
27
20
|
allColumns;
|
|
28
|
-
#searchPattern = "";
|
|
29
21
|
#selectedColumns;
|
|
30
22
|
constructor(allColumns, selectedColumns){
|
|
31
23
|
super(), this.allColumns = allColumns;
|
|
32
24
|
this.#selectedColumns = selectedColumns;
|
|
33
25
|
}
|
|
34
|
-
get availableColumns() {
|
|
35
|
-
return filterColumns(this.allColumns, this.#searchPattern).filter(({ name })=>-1 === this.#selectedColumns.findIndex((c)=>c.name === name)).toSorted(byColumnName);
|
|
36
|
-
}
|
|
37
|
-
set searchPattern(pattern) {
|
|
38
|
-
const searchPattern = pattern;
|
|
39
|
-
if (searchPattern !== this.#searchPattern) {
|
|
40
|
-
this.#searchPattern = searchPattern;
|
|
41
|
-
this.emit("render", {});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
get searchPattern() {
|
|
45
|
-
return this.#searchPattern ?? "";
|
|
46
|
-
}
|
|
47
26
|
get selectedColumns() {
|
|
48
|
-
return
|
|
27
|
+
return this.#selectedColumns;
|
|
49
28
|
}
|
|
50
29
|
setSelectedColumns(selectedColumns, source, changeDescriptor) {
|
|
51
30
|
this.#selectedColumns = selectedColumns;
|
|
@@ -56,6 +35,16 @@ class ColumnModel extends EventEmitter {
|
|
|
56
35
|
if (col) return col;
|
|
57
36
|
throw Error(`[ColumnModel] columns does not contain column ${name}`);
|
|
58
37
|
}
|
|
38
|
+
addRemoveOrReorderSelectedColumns(newSelectedColumns, source) {
|
|
39
|
+
if (!itemsOrOrderChanged(this.#selectedColumns, newSelectedColumns)) throw Error("[ColumnModel] addRemoveOrReorderSelectedColumns no change detected between current and new selected columns");
|
|
40
|
+
const addedColumns = getAddedItems(this.#selectedColumns, newSelectedColumns, columnDescriptorComparator);
|
|
41
|
+
if (addedColumns.length > 0) if (1 == addedColumns.length) return void this.addItemToSelectedColumns(addedColumns[0].name, source);
|
|
42
|
+
else throw Error("[ColumnModel] addRemoveOrReorderSelectedColumns attempt to add multiple selected columns in a single call");
|
|
43
|
+
const removedColumns = getRemovedItems(this.#selectedColumns, newSelectedColumns, columnDescriptorComparator);
|
|
44
|
+
if (removedColumns.length > 0) if (1 == removedColumns.length) return void this.removeItemFromSelectedColumns(removedColumns[0].name, source);
|
|
45
|
+
else throw Error("[ColumnModel] addRemoveOrReorderSelectedColumns attempt to remove multiple selected columns in a single call");
|
|
46
|
+
this.reorderSelectedColumns(newSelectedColumns.map(({ name })=>name), source);
|
|
47
|
+
}
|
|
59
48
|
addItemToSelectedColumns(name, source) {
|
|
60
49
|
const column = this.allColumns.find((col)=>col.name === name);
|
|
61
50
|
if (column) {
|
|
@@ -97,7 +86,7 @@ class ColumnModel extends EventEmitter {
|
|
|
97
86
|
}
|
|
98
87
|
addColumn(column, addToSelectedColumns = false) {
|
|
99
88
|
console.log(`[ColumnModel] add column ${JSON.stringify(column)}`);
|
|
100
|
-
if (addToSelectedColumns) console.log("add it to selected
|
|
89
|
+
if (addToSelectedColumns) console.log("add it to selected columns");
|
|
101
90
|
this.allColumns = this.allColumns.concat(column);
|
|
102
91
|
this.#selectedColumns = this.#selectedColumns.concat(column);
|
|
103
92
|
this.notifyListeners(this.#selectedColumns, "column-picker", {
|
|
@@ -1,94 +1,8 @@
|
|
|
1
1
|
const css = `
|
|
2
2
|
.vuuColumnPicker {
|
|
3
|
-
--label-margin-left: 0px;
|
|
4
|
-
--columnpicker-background: var(--vuuColumnPicker-background, var(--salt-container-primary-background));
|
|
5
|
-
background: var(--columnpicker-background);
|
|
6
|
-
gap: var(--salt-spacing-300);
|
|
7
|
-
height: var(--vuuColumnPicker-height, 100%);
|
|
8
|
-
padding: var(--salt-spacing-300) 0;
|
|
9
|
-
flex-direction: column;
|
|
10
|
-
display: flex;
|
|
11
|
-
overflow: hidden;
|
|
12
|
-
container-type: inline-size;
|
|
13
|
-
|
|
14
3
|
&.vuuColumnPicker-withCalculated {
|
|
15
4
|
--label-margin-left: 8px;
|
|
16
5
|
}
|
|
17
|
-
|
|
18
|
-
& .saltListBox {
|
|
19
|
-
background-color: inherit;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
& .saltOption {
|
|
23
|
-
background-color: inherit;
|
|
24
|
-
border-bottom: var(--vuuColumnListItem-border, solid) 1px
|
|
25
|
-
var(--salt-separable-tertiary-borderColor);
|
|
26
|
-
align-items: center;
|
|
27
|
-
gap: var(--salt-spacing-200);
|
|
28
|
-
height: calc(var(--salt-size-base) + var(--salt-spacing-200));
|
|
29
|
-
|
|
30
|
-
& .vuuIcon {
|
|
31
|
-
--vuu-icon-color: var(--salt-content-secondary-foreground);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
& .vuuCalculatedColumnIcon {
|
|
35
|
-
--vuu-icon-color: var(--salt-content-secondary-foreground);
|
|
36
|
-
position: absolute;
|
|
37
|
-
top: 8px;
|
|
38
|
-
left: 32px;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
& .vuuHighlight {
|
|
42
|
-
color: var(--vuu-color-blue-40);
|
|
43
|
-
text-decoration: underline;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
& .vuuColumnPicker-text {
|
|
47
|
-
margin-left: var(--label-margin-left);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
& .vuuColumnPickerListItem-action {
|
|
52
|
-
visibility: hidden;
|
|
53
|
-
margin-left: auto;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
& .saltOption:hover {
|
|
57
|
-
& .vuuColumnPickerListItem-action {
|
|
58
|
-
visibility: visible;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
& .vuuColumnPicker-search {
|
|
63
|
-
--saltInput-paddingLeft: var(--salt-spacing-300);
|
|
64
|
-
padding: var(--salt-spacing-200) var(--salt-spacing-300) 0 var(--salt-spacing-300);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
& .vuuColumnPicker-scrollContainer {
|
|
68
|
-
flex: 1 1 0;
|
|
69
|
-
overflow: auto;
|
|
70
|
-
|
|
71
|
-
& .vuuColumnPicker-sectionHeader {
|
|
72
|
-
background: var(--columnpicker-background);
|
|
73
|
-
height: 32px;
|
|
74
|
-
padding: 0 var(--salt-spacing-300);
|
|
75
|
-
z-index: 1;
|
|
76
|
-
align-items: center;
|
|
77
|
-
display: flex;
|
|
78
|
-
position: sticky;
|
|
79
|
-
top: 0;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
& .vuuColumnPicker-availableHeader {
|
|
83
|
-
top: 32px;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
& .vuuColumnPicker-availableList {
|
|
87
|
-
& .saltOption {
|
|
88
|
-
padding-left: var(--salt-spacing-300);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
6
|
}
|
|
93
7
|
|
|
94
8
|
|
|
@@ -1,204 +1,36 @@
|
|
|
1
|
-
import { jsx
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useComponentCssInjection } from "@salt-ds/styles";
|
|
3
3
|
import { useWindow } from "@salt-ds/window";
|
|
4
|
-
import { DragDropProvider, getColumnLabel, isCalculatedColumn, useSortable } from "@vuu-ui/vuu-utils";
|
|
5
4
|
import clsx from "clsx";
|
|
6
|
-
import { forwardRef
|
|
7
|
-
import { Button, Input, ListBox, Option } from "@salt-ds/core";
|
|
8
|
-
import { applyHighlighting } from "@vuu-ui/vuu-table";
|
|
9
|
-
import { Icon, IconButton } from "@vuu-ui/vuu-ui-controls";
|
|
10
|
-
import { ColumnChangeSource } from "./ColumnModel.js";
|
|
5
|
+
import { forwardRef } from "react";
|
|
11
6
|
import { useColumnPicker } from "./useColumnPicker.js";
|
|
7
|
+
import { ItemPicker } from "@vuu-ui/vuu-ui-controls";
|
|
12
8
|
import ColumnPicker_0 from "./ColumnPicker.css";
|
|
13
9
|
const classBase = "vuuColumnPicker";
|
|
14
10
|
const classBaseListItem = "vuuColumnPickerListItem";
|
|
15
|
-
const searchIcon = /*#__PURE__*/ jsx("span", {
|
|
16
|
-
"data-icon": "search"
|
|
17
|
-
});
|
|
18
11
|
const NO_SELECTION = [];
|
|
19
|
-
const
|
|
20
|
-
const { handleRef: sortableHandleRef, ref: sortableRef } = useSortable({
|
|
21
|
-
id,
|
|
22
|
-
index
|
|
23
|
-
});
|
|
24
|
-
const [handleRef, ref] = useMemo(()=>[
|
|
25
|
-
sortableHandleRef,
|
|
26
|
-
sortableRef
|
|
27
|
-
], [
|
|
28
|
-
sortableHandleRef,
|
|
29
|
-
sortableRef
|
|
30
|
-
]);
|
|
31
|
-
return {
|
|
32
|
-
handleRef,
|
|
33
|
-
ref
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
const SelectedColumnListItem = ({ className: classNameProp, index, column, onRemove, searchPattern = "", ...optionProps })=>{
|
|
37
|
-
const { handleRef, ref } = useSorting(column.name, index);
|
|
38
|
-
const value = getColumnLabel(column);
|
|
39
|
-
const valueWithHighlighting = applyHighlighting(value, searchPattern);
|
|
40
|
-
const handleRemoveButtonClick = useCallback((e)=>{
|
|
41
|
-
e.stopPropagation();
|
|
42
|
-
onRemove?.(e);
|
|
43
|
-
}, [
|
|
44
|
-
onRemove
|
|
45
|
-
]);
|
|
46
|
-
return /*#__PURE__*/ jsxs(Option, {
|
|
47
|
-
...optionProps,
|
|
48
|
-
className: clsx(classNameProp, classBaseListItem),
|
|
49
|
-
"data-name": column.name,
|
|
50
|
-
ref: ref,
|
|
51
|
-
children: [
|
|
52
|
-
/*#__PURE__*/ jsx(IconButton, {
|
|
53
|
-
"data-embedded": true,
|
|
54
|
-
appearance: "transparent",
|
|
55
|
-
icon: "draggable",
|
|
56
|
-
ref: handleRef,
|
|
57
|
-
size: 16
|
|
58
|
-
}),
|
|
59
|
-
isCalculatedColumn(column.name) ? /*#__PURE__*/ jsx(Icon, {
|
|
60
|
-
className: "vuuCalculatedColumnIcon",
|
|
61
|
-
name: "function"
|
|
62
|
-
}) : null,
|
|
63
|
-
/*#__PURE__*/ jsx("span", {
|
|
64
|
-
className: `${classBase}-text`,
|
|
65
|
-
children: valueWithHighlighting
|
|
66
|
-
}),
|
|
67
|
-
/*#__PURE__*/ jsx(IconButton, {
|
|
68
|
-
className: `${classBaseListItem}-action`,
|
|
69
|
-
"data-embedded": true,
|
|
70
|
-
appearance: "transparent",
|
|
71
|
-
icon: "cross",
|
|
72
|
-
onClick: handleRemoveButtonClick,
|
|
73
|
-
size: 16
|
|
74
|
-
})
|
|
75
|
-
]
|
|
76
|
-
});
|
|
77
|
-
};
|
|
78
|
-
const AvailableColumnListItem = ({ className: classNameProp, index, column: item, onAdd, searchPattern = "", ...optionProps })=>{
|
|
79
|
-
const value = getColumnLabel(item);
|
|
80
|
-
const valueWithHighlighting = applyHighlighting(value, searchPattern);
|
|
81
|
-
return /*#__PURE__*/ jsxs(Option, {
|
|
82
|
-
...optionProps,
|
|
83
|
-
className: clsx(classNameProp, classBaseListItem),
|
|
84
|
-
"data-name": item.name,
|
|
85
|
-
children: [
|
|
86
|
-
/*#__PURE__*/ jsx("span", {
|
|
87
|
-
className: `${classBase}-text`,
|
|
88
|
-
children: valueWithHighlighting
|
|
89
|
-
}),
|
|
90
|
-
/*#__PURE__*/ jsx(IconButton, {
|
|
91
|
-
className: `${classBaseListItem}-action`,
|
|
92
|
-
"data-embedded": true,
|
|
93
|
-
appearance: "transparent",
|
|
94
|
-
icon: "plus",
|
|
95
|
-
onClick: onAdd,
|
|
96
|
-
size: 16
|
|
97
|
-
})
|
|
98
|
-
]
|
|
99
|
-
});
|
|
100
|
-
};
|
|
101
|
-
const ColumnPicker_ColumnPicker = /*#__PURE__*/ forwardRef(function({ allowCreateCalculatedColumn, columnModel, className, onClickCreateCalculatedColumn, onSelectionChange, selected = NO_SELECTION, ...htmlAttributes }, forwardedRef) {
|
|
12
|
+
const ColumnPicker_ColumnPicker = /*#__PURE__*/ forwardRef(function({ columnModel, className, onSelectionChange, selected = NO_SELECTION, ...htmlAttributes }, forwardedRef) {
|
|
102
13
|
const targetWindow = useWindow();
|
|
103
14
|
useComponentCssInjection({
|
|
104
15
|
testId: "vuu-column-picker",
|
|
105
16
|
css: ColumnPicker_0,
|
|
106
17
|
window: targetWindow
|
|
107
18
|
});
|
|
108
|
-
const
|
|
109
|
-
setTimeout(()=>{
|
|
110
|
-
el?.querySelector("input")?.focus();
|
|
111
|
-
}, 100);
|
|
112
|
-
}, []);
|
|
113
|
-
const { availableColumns, onAddItemToSelectedList, onChangeSearchInput, onRemoveItemFromSelectedList, searchText, selectedColumns } = useColumnPicker({
|
|
19
|
+
const { allItems, selectedItems, oneOrMoreColumnsIsCalculated, handleSelectedItemsChange } = useColumnPicker({
|
|
114
20
|
columnModel: columnModel
|
|
115
21
|
});
|
|
116
|
-
|
|
117
|
-
const getOptionName = (option)=>{
|
|
118
|
-
if (option) {
|
|
119
|
-
const { name } = option.dataset;
|
|
120
|
-
if (name) return name;
|
|
121
|
-
}
|
|
122
|
-
throw Error("[ColumnPicker] list option has no data-name");
|
|
123
|
-
};
|
|
124
|
-
const handleDragEnd = useCallback(()=>{
|
|
125
|
-
setTimeout(()=>{
|
|
126
|
-
const listItems = listRef.current?.querySelectorAll(".saltOption");
|
|
127
|
-
if (listItems) {
|
|
128
|
-
const orderedColumnNames = Array.from(listItems).map(getOptionName);
|
|
129
|
-
columnModel.reorderSelectedColumns(orderedColumnNames, ColumnChangeSource.ColumnPicker);
|
|
130
|
-
}
|
|
131
|
-
}, 300);
|
|
132
|
-
}, [
|
|
133
|
-
columnModel
|
|
134
|
-
]);
|
|
135
|
-
const oneOrMoreColumnsIsCalculated = selectedColumns.some((column)=>isCalculatedColumn(column.name));
|
|
136
|
-
return /*#__PURE__*/ jsxs("div", {
|
|
22
|
+
return /*#__PURE__*/ jsx(ItemPicker, {
|
|
137
23
|
...htmlAttributes,
|
|
138
24
|
className: clsx(classBase, className, {
|
|
139
25
|
[`${classBase}-withCalculated`]: oneOrMoreColumnsIsCalculated
|
|
140
26
|
}),
|
|
27
|
+
allItems: allItems,
|
|
28
|
+
selectedItems: selectedItems,
|
|
29
|
+
itemTypeName: "column",
|
|
30
|
+
onSelectedItemsChange: handleSelectedItemsChange,
|
|
31
|
+
onSelectionChange: onSelectionChange,
|
|
141
32
|
ref: forwardedRef,
|
|
142
|
-
|
|
143
|
-
/*#__PURE__*/ jsx("form", {
|
|
144
|
-
className: `${classBase}-search`,
|
|
145
|
-
role: "search",
|
|
146
|
-
children: /*#__PURE__*/ jsx(Input, {
|
|
147
|
-
startAdornment: searchIcon,
|
|
148
|
-
placeholder: "Find column",
|
|
149
|
-
ref: searchCallbackRef,
|
|
150
|
-
value: searchText,
|
|
151
|
-
onChange: onChangeSearchInput
|
|
152
|
-
})
|
|
153
|
-
}),
|
|
154
|
-
/*#__PURE__*/ jsxs("div", {
|
|
155
|
-
className: `${classBase}-scrollContainer vuuScrollable`,
|
|
156
|
-
children: [
|
|
157
|
-
/*#__PURE__*/ jsx("div", {
|
|
158
|
-
className: `${classBase}-sectionHeader`,
|
|
159
|
-
children: "Columns in view"
|
|
160
|
-
}),
|
|
161
|
-
/*#__PURE__*/ jsx(DragDropProvider, {
|
|
162
|
-
onDragEnd: handleDragEnd,
|
|
163
|
-
children: /*#__PURE__*/ jsx(ListBox, {
|
|
164
|
-
className: `${classBase}-selectedList`,
|
|
165
|
-
onSelectionChange: onSelectionChange,
|
|
166
|
-
ref: listRef,
|
|
167
|
-
selected: selected,
|
|
168
|
-
children: selectedColumns.map((column, index)=>/*#__PURE__*/ jsx(SelectedColumnListItem, {
|
|
169
|
-
column: column,
|
|
170
|
-
index: index,
|
|
171
|
-
onRemove: onRemoveItemFromSelectedList,
|
|
172
|
-
searchPattern: searchText.toLowerCase(),
|
|
173
|
-
value: column
|
|
174
|
-
}, column.name))
|
|
175
|
-
})
|
|
176
|
-
}),
|
|
177
|
-
/*#__PURE__*/ jsx("div", {
|
|
178
|
-
className: clsx(`${classBase}-sectionHeader`, `${classBase}-availableHeader`),
|
|
179
|
-
children: "Available columns"
|
|
180
|
-
}),
|
|
181
|
-
/*#__PURE__*/ jsx(ListBox, {
|
|
182
|
-
className: `${classBase}-availableList`,
|
|
183
|
-
selected: NO_SELECTION,
|
|
184
|
-
children: availableColumns.map((column, index)=>/*#__PURE__*/ jsx(AvailableColumnListItem, {
|
|
185
|
-
column: column,
|
|
186
|
-
index: index,
|
|
187
|
-
onAdd: onAddItemToSelectedList,
|
|
188
|
-
searchPattern: searchText.toLowerCase(),
|
|
189
|
-
value: column
|
|
190
|
-
}, column.name))
|
|
191
|
-
})
|
|
192
|
-
]
|
|
193
|
-
}),
|
|
194
|
-
allowCreateCalculatedColumn ? /*#__PURE__*/ jsx("div", {
|
|
195
|
-
className: `${classBase}-column-buttons`,
|
|
196
|
-
children: /*#__PURE__*/ jsx(Button, {
|
|
197
|
-
onClick: onClickCreateCalculatedColumn,
|
|
198
|
-
children: "Create calculated column"
|
|
199
|
-
})
|
|
200
|
-
}) : null
|
|
201
|
-
]
|
|
33
|
+
selected: selected
|
|
202
34
|
});
|
|
203
35
|
});
|
|
204
36
|
export { ColumnPicker_ColumnPicker as ColumnPicker, classBaseListItem };
|
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useCallback, useEffect, useState } from "react";
|
|
1
|
+
import { isCalculatedColumn } from "@vuu-ui/vuu-utils";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
3
3
|
import { ColumnChangeSource } from "./ColumnModel.js";
|
|
4
4
|
const SOURCE = ColumnChangeSource.ColumnPicker;
|
|
5
|
-
const columnName = (target)=>{
|
|
6
|
-
const listItem = queryClosest(target, ".saltOption", true);
|
|
7
|
-
const { name } = listItem.dataset;
|
|
8
|
-
if (name) return name;
|
|
9
|
-
throw Error("[useColumnPicker] column name could not be identified, data-name attribute not found");
|
|
10
|
-
};
|
|
11
5
|
const useColumnPicker = ({ columnModel: model })=>{
|
|
12
6
|
const [, forceRender] = useState({});
|
|
13
7
|
useEffect(()=>{
|
|
@@ -18,25 +12,37 @@ const useColumnPicker = ({ columnModel: model })=>{
|
|
|
18
12
|
}, [
|
|
19
13
|
model
|
|
20
14
|
]);
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
15
|
+
const allItems = useMemo(()=>{
|
|
16
|
+
const itemDescriptors = model.allColumns.map((column)=>({
|
|
17
|
+
name: column.name,
|
|
18
|
+
label: column.label,
|
|
19
|
+
icon: isCalculatedColumn(column.name) ? "vuuCalculatedColumnIcon" : void 0
|
|
20
|
+
}));
|
|
21
|
+
return itemDescriptors;
|
|
24
22
|
}, [
|
|
25
|
-
model
|
|
23
|
+
model.allColumns
|
|
26
24
|
]);
|
|
27
|
-
const
|
|
28
|
-
model
|
|
25
|
+
const selectedItems = useMemo(()=>{
|
|
26
|
+
const itemDescriptors = model.selectedColumns.map((column)=>allItems.find((item)=>item.name === column.name));
|
|
27
|
+
return itemDescriptors;
|
|
28
|
+
}, [
|
|
29
|
+
model.selectedColumns,
|
|
30
|
+
allItems
|
|
29
31
|
]);
|
|
30
|
-
const
|
|
31
|
-
model
|
|
32
|
+
const oneOrMoreColumnsIsCalculated = useMemo(()=>model.selectedColumns.some((column)=>isCalculatedColumn(column.name)), [
|
|
33
|
+
model.selectedColumns
|
|
34
|
+
]);
|
|
35
|
+
const handleSelectedItemsChange = useCallback((newSelectedItems)=>{
|
|
36
|
+
const newSelectedColumns = newSelectedItems.map((item)=>model.allColumns.find((column)=>column.name === item.name));
|
|
37
|
+
model.addRemoveOrReorderSelectedColumns(newSelectedColumns, SOURCE);
|
|
38
|
+
}, [
|
|
39
|
+
model.allColumns
|
|
32
40
|
]);
|
|
33
41
|
return {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
searchText: model.searchPattern,
|
|
39
|
-
selectedColumns: model.selectedColumns
|
|
42
|
+
allItems,
|
|
43
|
+
selectedItems,
|
|
44
|
+
oneOrMoreColumnsIsCalculated,
|
|
45
|
+
handleSelectedItemsChange
|
|
40
46
|
};
|
|
41
47
|
};
|
|
42
48
|
export { useColumnPicker };
|
|
@@ -14,6 +14,40 @@ const css = `
|
|
|
14
14
|
display: grid;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
.vuuCsvUpload-errorContainer {
|
|
18
|
+
margin-top: var(--salt-spacing-100);
|
|
19
|
+
width: 100%;
|
|
20
|
+
max-width: 480px;
|
|
21
|
+
max-height: 120px;
|
|
22
|
+
padding: var(--salt-spacing-100) var(--salt-spacing-200);
|
|
23
|
+
background-color: rgba(var(--salt-palette-interact-error-background), .05);
|
|
24
|
+
border-radius: var(--salt-size-borderRadius);
|
|
25
|
+
text-align: left;
|
|
26
|
+
overflow-y: auto;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.vuuCsvUpload-errorList {
|
|
30
|
+
padding-left: var(--salt-spacing-200);
|
|
31
|
+
margin: 0;
|
|
32
|
+
list-style-type: disc;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.vuuCsvUpload-errorItem {
|
|
36
|
+
font-size: var(--salt-text-fontSize-small);
|
|
37
|
+
color: var(--salt-status-error-foreground);
|
|
38
|
+
line-height: var(--salt-text-lineHeight-small);
|
|
39
|
+
word-break: break-word;
|
|
40
|
+
margin-bottom: var(--salt-spacing-50);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.vuuCsvUpload-importErrorItem {
|
|
44
|
+
text-align: center;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.vuuCsvUpload-rectifyPrompt {
|
|
48
|
+
margin-top: var(--salt-spacing-100);
|
|
49
|
+
}
|
|
50
|
+
|
|
17
51
|
.vuuCsvUpload-errors {
|
|
18
52
|
border: solid 1px var(--salt-status-error-borderColor);
|
|
19
53
|
border-radius: var(--salt-size-borderRadius);
|