@vuu-ui/vuu-filters 3.5.0 → 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 +4 -2
- package/src/toggle-filter/ToggleFilter.css.js +8 -0
- package/src/toggle-filter/ToggleFilter.js +21 -11
- package/src/toggle-filter/useToggleFilter.js +57 -33
- package/types/column-filter/ColumnFilter.d.ts +1 -1
- package/types/toggle-filter/ToggleFilter.d.ts +5 -0
- 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",
|
|
@@ -9,7 +9,7 @@ import { useWindow } from "@salt-ds/window";
|
|
|
9
9
|
import ColumnFilter_0 from "./ColumnFilter.css";
|
|
10
10
|
import { isBetweenOperator, withDateTimePattern } from "@vuu-ui/vuu-utils";
|
|
11
11
|
const classBase = "vuuColumnFilter";
|
|
12
|
-
const ColumnFilter_ColumnFilter = /*#__PURE__*/ external_react_forwardRef(function({ InputProps: InputPropsProp, TypeaheadProps, className, column, defaultValue, extendedFilterOptions, onColumnFilterChange, onColumnRangeFilterChange, onCommit: onCommitProp, operator = "=", pattern, table, value: valueProp, values, variant, ...buttonGroupProps }, forwardRef) {
|
|
12
|
+
const ColumnFilter_ColumnFilter = /*#__PURE__*/ external_react_forwardRef(function({ InputProps: InputPropsProp, TypeaheadProps, className, column, defaultValue, extendedFilterOptions, labels, onColumnFilterChange, onColumnRangeFilterChange, onCommit: onCommitProp, operator = "=", pattern, table, value: valueProp, values, variant, ...buttonGroupProps }, forwardRef) {
|
|
13
13
|
const targetWindow = useWindow();
|
|
14
14
|
useComponentCssInjection({
|
|
15
15
|
testId: "vuu-filter-editor",
|
|
@@ -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: [
|
|
@@ -48,6 +49,7 @@ const ColumnFilter_ColumnFilter = /*#__PURE__*/ external_react_forwardRef(functi
|
|
|
48
49
|
TypeaheadProps,
|
|
49
50
|
commitWhenCleared: true,
|
|
50
51
|
dataDescriptor: controlDescriptor,
|
|
52
|
+
labels,
|
|
51
53
|
onCommit,
|
|
52
54
|
table,
|
|
53
55
|
values,
|
|
@@ -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,15 +24,17 @@ const getValues = (defaultValue, value)=>{
|
|
|
24
24
|
];
|
|
25
25
|
};
|
|
26
26
|
const classBase = "vuuToggleFilter";
|
|
27
|
-
const
|
|
27
|
+
const NO_MATCHING_DATA = "No matching data";
|
|
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({
|
|
30
31
|
testId: "vuu-toggle-filter",
|
|
31
32
|
css: ToggleFilter_0,
|
|
32
33
|
window: targetWindow
|
|
33
34
|
});
|
|
35
|
+
if (void 0 !== labels && labels.length !== values.length) throw Error("[ToggleFilter] labels must have the same number of items as values");
|
|
34
36
|
const [defaultValue, value] = getValues(defaultValueProp, valueProp);
|
|
35
|
-
const onlyAvailableValue = useToggleFilter({
|
|
37
|
+
const { onlyAvailableValue, unavailableValues } = useToggleFilter({
|
|
36
38
|
column,
|
|
37
39
|
table,
|
|
38
40
|
values
|
|
@@ -53,15 +55,23 @@ const ToggleFilter_ToggleFilter = /*#__PURE__*/ forwardRef(function({ className,
|
|
|
53
55
|
children: [
|
|
54
56
|
/*#__PURE__*/ jsx(ToggleButton, {
|
|
55
57
|
value: "all",
|
|
56
|
-
children: "
|
|
58
|
+
children: "All"
|
|
57
59
|
}, "all"),
|
|
58
|
-
values.map((toggleValue
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
children:
|
|
64
|
-
|
|
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
|
+
})
|
|
65
75
|
]
|
|
66
76
|
});
|
|
67
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 };
|
|
@@ -2,7 +2,7 @@ import { type SegmentedButtonGroupProps } from "@salt-ds/core";
|
|
|
2
2
|
import { DataItemEditControlProps } from "@vuu-ui/vuu-data-react";
|
|
3
3
|
import { ColumnFilterHookProps } from "./useColumnFilter";
|
|
4
4
|
import { type DateTimePattern } from "@vuu-ui/vuu-utils";
|
|
5
|
-
export interface ColumnFilterProps extends ColumnFilterHookProps, Omit<SegmentedButtonGroupProps, "defaultValue">, Pick<DataItemEditControlProps, "TypeaheadProps" | "table" | "values" | "variant"> {
|
|
5
|
+
export interface ColumnFilterProps extends ColumnFilterHookProps, Omit<SegmentedButtonGroupProps, "defaultValue">, Pick<DataItemEditControlProps, "TypeaheadProps" | "labels" | "table" | "values" | "variant"> {
|
|
6
6
|
/**
|
|
7
7
|
* Temporal columns only. The date/time pattern used by the filter control,
|
|
8
8
|
* overriding any pattern configured on the column type. The pattern also
|
|
@@ -12,6 +12,11 @@ import { type ToggleFilterHookProps } from "./useToggleFilter";
|
|
|
12
12
|
* behaving like a regular ToggleButtonGroup.
|
|
13
13
|
*/
|
|
14
14
|
export interface ToggleFilterProps extends ToggleButtonGroupProps, ToggleFilterHookProps {
|
|
15
|
+
/**
|
|
16
|
+
* Optional labels for the toggle buttons. If provided, must contain
|
|
17
|
+
* the same number of items as values. Defaults to values.
|
|
18
|
+
*/
|
|
19
|
+
labels?: string[];
|
|
15
20
|
onCommit: CommitHandler<HTMLElement>;
|
|
16
21
|
}
|
|
17
22
|
export declare const ToggleFilter: import("react").ForwardRefExoticComponent<ToggleFilterProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -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;
|