@vuu-ui/vuu-filters 3.5.1 → 3.5.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 -12
- package/src/column-filter/ColumnFilter.css.js +4 -0
- package/src/column-filter/ColumnFilter.js +2 -1
- package/src/toggle-filter/ToggleFilter.css.js +8 -0
- package/src/toggle-filter/ToggleFilter.js +19 -10
- package/src/toggle-filter/useToggleFilter.js +57 -33
- package/types/toggle-filter/useToggleFilter.d.ts +19 -1
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "3.5.
|
|
2
|
+
"version": "3.5.2",
|
|
3
3
|
"main": "./src/index.js",
|
|
4
4
|
"author": "heswell",
|
|
5
5
|
"license": "Apache-2.0",
|
|
@@ -10,19 +10,19 @@
|
|
|
10
10
|
"type-defs": "node ../../scripts/build-type-defs.mjs"
|
|
11
11
|
},
|
|
12
12
|
"devDependencies": {
|
|
13
|
-
"@vuu-ui/vuu-data-types": "3.5.
|
|
14
|
-
"@vuu-ui/vuu-protocol-types": "3.5.
|
|
15
|
-
"@vuu-ui/vuu-table-types": "3.5.
|
|
16
|
-
"@vuu-ui/vuu-filter-types": "3.5.
|
|
13
|
+
"@vuu-ui/vuu-data-types": "3.5.2",
|
|
14
|
+
"@vuu-ui/vuu-protocol-types": "3.5.2",
|
|
15
|
+
"@vuu-ui/vuu-table-types": "3.5.2",
|
|
16
|
+
"@vuu-ui/vuu-filter-types": "3.5.2"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@vuu-ui/vuu-context-menu": "3.5.
|
|
20
|
-
"@vuu-ui/vuu-data-react": "3.5.
|
|
21
|
-
"@vuu-ui/vuu-filter-parser": "3.5.
|
|
22
|
-
"@vuu-ui/vuu-popups": "3.5.
|
|
23
|
-
"@vuu-ui/vuu-ui-controls": "3.5.
|
|
24
|
-
"@vuu-ui/vuu-table": "3.5.
|
|
25
|
-
"@vuu-ui/vuu-utils": "3.5.
|
|
19
|
+
"@vuu-ui/vuu-context-menu": "3.5.2",
|
|
20
|
+
"@vuu-ui/vuu-data-react": "3.5.2",
|
|
21
|
+
"@vuu-ui/vuu-filter-parser": "3.5.2",
|
|
22
|
+
"@vuu-ui/vuu-popups": "3.5.2",
|
|
23
|
+
"@vuu-ui/vuu-ui-controls": "3.5.2",
|
|
24
|
+
"@vuu-ui/vuu-table": "3.5.2",
|
|
25
|
+
"@vuu-ui/vuu-utils": "3.5.2",
|
|
26
26
|
"@salt-ds/core": "1.54.1",
|
|
27
27
|
"@salt-ds/lab": "1.0.0-alpha.83",
|
|
28
28
|
"@salt-ds/styles": "0.2.1",
|
|
@@ -39,7 +39,8 @@ const ColumnFilter_ColumnFilter = /*#__PURE__*/ external_react_forwardRef(functi
|
|
|
39
39
|
return /*#__PURE__*/ jsxs(SegmentedButtonGroup, {
|
|
40
40
|
...buttonGroupProps,
|
|
41
41
|
className: clsx(classBase, className, {
|
|
42
|
-
[`${classBase}-invalid`]: isInvalid
|
|
42
|
+
[`${classBase}-invalid`]: isInvalid,
|
|
43
|
+
[`${classBase}-toggle`]: "toggle" === variant
|
|
43
44
|
}),
|
|
44
45
|
ref: forwardRef,
|
|
45
46
|
children: [
|
|
@@ -3,6 +3,14 @@ const css = `
|
|
|
3
3
|
& .vuuToggleFilter-onlyAvailableValue:not([aria-checked="true"], :hover) {
|
|
4
4
|
background-color: var(--vuuToggleFilter-implicitActive-bg, var(--salt-actionable-bold-background));
|
|
5
5
|
}
|
|
6
|
+
|
|
7
|
+
& .vuuToggleFilter-unavailableValue:not([aria-checked="true"]) {
|
|
8
|
+
background: var(--toggleButton-background);
|
|
9
|
+
border-color: var(--toggleButton-borderColor);
|
|
10
|
+
color: var(--toggleButton-text-color);
|
|
11
|
+
cursor: var(--vuuToggleFilter-unavailableValue-cursor, var(--salt-cursor-disabled));
|
|
12
|
+
opacity: var(--vuuToggleFilter-unavailableValue-opacity, .4);
|
|
13
|
+
}
|
|
6
14
|
}
|
|
7
15
|
|
|
8
16
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { ToggleButton, ToggleButtonGroup } from "@salt-ds/core";
|
|
2
|
+
import { ToggleButton, ToggleButtonGroup, Tooltip } from "@salt-ds/core";
|
|
3
3
|
import { useComponentCssInjection } from "@salt-ds/styles";
|
|
4
4
|
import { useWindow } from "@salt-ds/window";
|
|
5
5
|
import clsx from "clsx";
|
|
@@ -24,6 +24,7 @@ const getValues = (defaultValue, value)=>{
|
|
|
24
24
|
];
|
|
25
25
|
};
|
|
26
26
|
const classBase = "vuuToggleFilter";
|
|
27
|
+
const NO_MATCHING_DATA = "No matching data";
|
|
27
28
|
const ToggleFilter_ToggleFilter = /*#__PURE__*/ forwardRef(function({ className, column, defaultValue: defaultValueProp, labels, onCommit, table, value: valueProp, values, ...ToggleButtonGroupProps }, forwardedRef) {
|
|
28
29
|
const targetWindow = useWindow();
|
|
29
30
|
useComponentCssInjection({
|
|
@@ -33,7 +34,7 @@ const ToggleFilter_ToggleFilter = /*#__PURE__*/ forwardRef(function({ className,
|
|
|
33
34
|
});
|
|
34
35
|
if (void 0 !== labels && labels.length !== values.length) throw Error("[ToggleFilter] labels must have the same number of items as values");
|
|
35
36
|
const [defaultValue, value] = getValues(defaultValueProp, valueProp);
|
|
36
|
-
const onlyAvailableValue = useToggleFilter({
|
|
37
|
+
const { onlyAvailableValue, unavailableValues } = useToggleFilter({
|
|
37
38
|
column,
|
|
38
39
|
table,
|
|
39
40
|
values
|
|
@@ -54,15 +55,23 @@ const ToggleFilter_ToggleFilter = /*#__PURE__*/ forwardRef(function({ className,
|
|
|
54
55
|
children: [
|
|
55
56
|
/*#__PURE__*/ jsx(ToggleButton, {
|
|
56
57
|
value: "all",
|
|
57
|
-
children: "
|
|
58
|
+
children: "All"
|
|
58
59
|
}, "all"),
|
|
59
|
-
values.map((toggleValue, i)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
children:
|
|
65
|
-
|
|
60
|
+
values.map((toggleValue, i)=>{
|
|
61
|
+
const unavailable = unavailableValues.includes(toggleValue);
|
|
62
|
+
return /*#__PURE__*/ jsx(Tooltip, {
|
|
63
|
+
content: NO_MATCHING_DATA,
|
|
64
|
+
disabled: !unavailable,
|
|
65
|
+
children: /*#__PURE__*/ jsx(ToggleButton, {
|
|
66
|
+
className: clsx({
|
|
67
|
+
[`${classBase}-onlyAvailableValue`]: onlyAvailableValue === toggleValue,
|
|
68
|
+
[`${classBase}-unavailableValue`]: unavailable
|
|
69
|
+
}),
|
|
70
|
+
value: toggleValue,
|
|
71
|
+
children: labels?.[i] ?? toggleValue
|
|
72
|
+
})
|
|
73
|
+
}, toggleValue);
|
|
74
|
+
})
|
|
66
75
|
]
|
|
67
76
|
});
|
|
68
77
|
});
|
|
@@ -1,57 +1,81 @@
|
|
|
1
|
-
import { useSavedFilters } from "../filter-provider/FilterContext.js";
|
|
2
1
|
import { useTypeaheadSuggestions } from "@vuu-ui/vuu-data-react";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { parseFilter } from "@vuu-ui/vuu-filter-parser";
|
|
3
|
+
import { extractFilterForColumn, getVuuTable, useDataSource } from "@vuu-ui/vuu-utils";
|
|
4
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
5
5
|
const assertValid = (values, actualValues)=>{
|
|
6
6
|
if (actualValues.some((val)=>-1 === values.indexOf(val))) console.warn(`[useToggleFilter] ToggleFilter is configured with values which do not include all values from data source
|
|
7
7
|
[${values.join()}]
|
|
8
8
|
[${actualValues.join()}]`);
|
|
9
9
|
};
|
|
10
|
-
const
|
|
11
|
-
if (
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return true;
|
|
10
|
+
const hasFilterOnColumn = (filterSpec, column)=>{
|
|
11
|
+
if (void 0 === filterSpec || "" === filterSpec.filter) return false;
|
|
12
|
+
const filter = filterSpec.filterStruct ?? parseFilter(filterSpec.filter);
|
|
13
|
+
return void 0 !== extractFilterForColumn(filter, column);
|
|
15
14
|
};
|
|
16
15
|
const useToggleFilter = ({ column, table, values })=>{
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const [typeaheadValues, setTypeaheadValues] = useState([]);
|
|
16
|
+
const dataSource = useDataSource(false);
|
|
17
|
+
const [typeaheadValues, setTypeaheadValues] = useState(void 0);
|
|
20
18
|
const getSuggestions = useTypeaheadSuggestions();
|
|
21
|
-
const
|
|
22
|
-
|
|
19
|
+
const requestIdRef = useRef(0);
|
|
20
|
+
const valuesRef = useRef(values);
|
|
21
|
+
valuesRef.current = values;
|
|
22
|
+
const valuesKey = values.join("\u0000");
|
|
23
|
+
const vuuTable = table ? getVuuTable(table) : void 0;
|
|
24
|
+
const tableModule = vuuTable?.module;
|
|
25
|
+
const tableName = vuuTable?.table;
|
|
26
|
+
const checkAvailability = useCallback(()=>{
|
|
27
|
+
if (void 0 === tableModule || void 0 === tableName || void 0 === dataSource) return;
|
|
28
|
+
if (hasFilterOnColumn(dataSource.filter, column)) return;
|
|
29
|
+
const requestId = ++requestIdRef.current;
|
|
23
30
|
const params = [
|
|
24
|
-
|
|
31
|
+
{
|
|
32
|
+
module: tableModule,
|
|
33
|
+
table: tableName
|
|
34
|
+
},
|
|
25
35
|
column
|
|
26
36
|
];
|
|
27
37
|
getSuggestions(params).then((suggestions)=>{
|
|
28
|
-
if (false === suggestions)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
setTypeaheadValues(suggestions);
|
|
32
|
-
}
|
|
38
|
+
if (requestId !== requestIdRef.current || false === suggestions) return;
|
|
39
|
+
assertValid(valuesRef.current, suggestions);
|
|
40
|
+
setTypeaheadValues(suggestions);
|
|
33
41
|
});
|
|
34
42
|
}, [
|
|
35
43
|
column,
|
|
44
|
+
dataSource,
|
|
36
45
|
getSuggestions,
|
|
37
|
-
|
|
46
|
+
tableModule,
|
|
47
|
+
tableName
|
|
38
48
|
]);
|
|
39
|
-
|
|
40
|
-
|
|
49
|
+
useEffect(()=>{
|
|
50
|
+
checkAvailability();
|
|
41
51
|
}, [
|
|
42
|
-
|
|
43
|
-
table
|
|
52
|
+
checkAvailability
|
|
44
53
|
]);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
54
|
+
useEffect(()=>{
|
|
55
|
+
if (dataSource) {
|
|
56
|
+
const handleConfigChange = (_config, _range, _confirmed, configChanges)=>{
|
|
57
|
+
if (configChanges?.filterChanged) checkAvailability();
|
|
58
|
+
};
|
|
59
|
+
dataSource.on("config", handleConfigChange);
|
|
60
|
+
return ()=>{
|
|
61
|
+
dataSource.removeListener("config", handleConfigChange);
|
|
62
|
+
};
|
|
63
|
+
}
|
|
49
64
|
}, [
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
65
|
+
checkAvailability,
|
|
66
|
+
dataSource
|
|
67
|
+
]);
|
|
68
|
+
return useMemo(()=>{
|
|
69
|
+
if (void 0 === typeaheadValues) return {
|
|
70
|
+
unavailableValues: []
|
|
71
|
+
};
|
|
72
|
+
return {
|
|
73
|
+
onlyAvailableValue: 1 === typeaheadValues.length ? typeaheadValues[0] : void 0,
|
|
74
|
+
unavailableValues: valuesRef.current.filter((value)=>!typeaheadValues.includes(value))
|
|
75
|
+
};
|
|
76
|
+
}, [
|
|
77
|
+
typeaheadValues,
|
|
78
|
+
valuesKey
|
|
53
79
|
]);
|
|
54
|
-
const [firstValue] = typeaheadValues;
|
|
55
|
-
return 1 === typeaheadValues.length ? firstValue : void 0;
|
|
56
80
|
};
|
|
57
81
|
export { useToggleFilter };
|
|
@@ -8,4 +8,22 @@ export interface ToggleFilterHookProps {
|
|
|
8
8
|
table?: TableSchemaTable;
|
|
9
9
|
values: string[];
|
|
10
10
|
}
|
|
11
|
-
export
|
|
11
|
+
export interface ToggleFilterHookResult {
|
|
12
|
+
/**
|
|
13
|
+
* If only one of the toggle values has matching data, that value.
|
|
14
|
+
*/
|
|
15
|
+
onlyAvailableValue?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Toggle values for which there is no matching data.
|
|
18
|
+
*/
|
|
19
|
+
unavailableValues: string[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Determines which toggle values have matching data, using typeahead
|
|
23
|
+
* against the DataSource. Typeahead respects the filter applied to the
|
|
24
|
+
* DataSource, so while a filter on this column is in effect, results
|
|
25
|
+
* would only reflect the filtered value. In that case no check is made
|
|
26
|
+
* and the result of the last check (if any) is retained. If there has
|
|
27
|
+
* been no check, all values are assumed to possibly have data.
|
|
28
|
+
*/
|
|
29
|
+
export declare const useToggleFilter: ({ column, table, values, }: ToggleFilterHookProps) => ToggleFilterHookResult;
|