@vuu-ui/vuu-filters 4.0.0-alpha.8 → 4.0.0-beta.1
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 +16 -16
- package/src/FilterAggregator.js +61 -42
- package/src/column-filter/ColumnFilter.css.js +4 -0
- package/src/column-filter/ColumnFilter.js +18 -7
- package/src/filter-clause/FilterClause.css.js +1 -1
- package/src/filter-clause/operator-picker/operator-utils.js +2 -2
- package/src/filter-clause/value-editors/FilterClauseValueEditor.js +8 -5
- package/src/filter-clause/value-editors/FilterClauseValueEditorDate.js +11 -43
- package/src/filter-clause/value-editors/FilterClauseValueEditorTime.js +16 -42
- package/src/filter-container/ExtendedSingleValueFilterClause.js +21 -7
- package/src/filter-container/FilterContainer.js +22 -10
- package/src/filter-context-menu/useFilterContextMenu.js +36 -9
- package/src/filter-pill/getFilterTooltipText.js +2 -8
- package/src/filter-provider/FilterContext.js +20 -1
- package/src/filter-provider/FilterProvider.js +20 -2
- package/src/filter-utils.js +5 -10
- package/src/index.js +1 -1
- package/src/quick-filters/useQuickFilters.js +6 -1
- package/src/tabbed-filter-container/TabbedFilterContainer.js +19 -17
- package/src/toggle-filter/ToggleFilter.css.js +8 -0
- package/src/toggle-filter/ToggleFilter.js +34 -15
- package/src/toggle-filter/useToggleFilter.js +57 -33
- package/types/column-filter/ColumnFilter.d.ts +16 -3
- package/types/custom-filters/CustomFilters.d.ts +1 -1
- package/types/filter-bar/FilterBar.d.ts +1 -1
- package/types/filter-bar/FilterBarMenu.d.ts +1 -1
- package/types/filter-clause/FilterClause.d.ts +1 -1
- package/types/filter-clause/value-editors/FilterClauseValueEditorDate.d.ts +13 -2
- package/types/filter-clause/value-editors/FilterClauseValueEditorText.d.ts +2 -2
- package/types/filter-clause/value-editors/FilterClauseValueEditorTime.d.ts +15 -4
- package/types/filter-container/ExtendedSingleValueFilterClause.d.ts +6 -0
- package/types/filter-container/FilterContainer.d.ts +11 -4
- package/types/filter-context-menu/useFilterContextMenu.d.ts +11 -1
- package/types/filter-editor/FilterClauseCombinator.d.ts +1 -1
- package/types/filter-editor/FilterEditor.d.ts +1 -1
- package/types/filter-pill/FilterMenu.d.ts +1 -1
- package/types/filter-pill/FilterPill.d.ts +1 -1
- package/types/filter-pill/FilterPillNext.d.ts +1 -1
- package/types/filter-pill-menu/FilterPillMenu.d.ts +1 -1
- package/types/filter-provider/FilterContext.d.ts +34 -0
- package/types/filter-provider/FilterProvider.d.ts +19 -1
- package/types/filter-toggle-button/FilterToggleButton.d.ts +1 -1
- package/types/index.d.ts +4 -4
- package/types/inline-filter/InlineFilter.d.ts +1 -1
- package/types/quick-filters/QuickFilters.d.ts +1 -1
- package/types/saved-filters/DeleteFilterPrompt.d.ts +1 -1
- package/types/saved-filters/FilterNamePrompt.d.ts +1 -1
- package/types/saved-filters/SavedFilterPanel.d.ts +1 -1
- package/types/tabbed-filter-container/TabbedFilterContainer.d.ts +3 -3
- package/types/toggle-filter/ToggleFilter.d.ts +16 -1
- package/types/toggle-filter/useToggleFilter.d.ts +19 -1
- package/types/src/FilterAggregator.d.ts +0 -28
- package/types/src/FilterModel.d.ts +0 -44
- package/types/src/column-filter/ColumnFilter.d.ts +0 -6
- package/types/src/column-filter/useColumnFilter.d.ts +0 -43
- package/types/src/column-filter/utils.d.ts +0 -4
- package/types/src/custom-filters/CustomFilters.d.ts +0 -7
- package/types/src/custom-filters/filterBarFocusManagement.d.ts +0 -1
- package/types/src/custom-filters/index.d.ts +0 -1
- package/types/src/custom-filters/useCustomFilters.d.ts +0 -33
- package/types/src/custom-filters/useFilterState.d.ts +0 -17
- package/types/src/filter-bar/FilterBar.d.ts +0 -33
- package/types/src/filter-bar/FilterBarMenu.d.ts +0 -1
- package/types/src/filter-bar/index.d.ts +0 -2
- package/types/src/filter-bar/useFilterBar.d.ts +0 -7
- package/types/src/filter-clause/ExpandoCombobox.d.ts +0 -10
- package/types/src/filter-clause/FilterClause.d.ts +0 -16
- package/types/src/filter-clause/column-picker/ColumnPicker.d.ts +0 -13
- package/types/src/filter-clause/column-picker/useColumnPicker.d.ts +0 -11
- package/types/src/filter-clause/filterClauseFocusManagement.d.ts +0 -15
- package/types/src/filter-clause/filterClauseTypes.d.ts +0 -12
- package/types/src/filter-clause/index.d.ts +0 -5
- package/types/src/filter-clause/operator-picker/OperatorPicker.d.ts +0 -14
- package/types/src/filter-clause/operator-picker/operator-utils.d.ts +0 -5
- package/types/src/filter-clause/operator-picker/useOperatorPicker.d.ts +0 -12
- package/types/src/filter-clause/useFilterClause.d.ts +0 -26
- package/types/src/filter-clause/value-editors/FilterClauseValueEditor.d.ts +0 -26
- package/types/src/filter-clause/value-editors/FilterClauseValueEditorDate.d.ts +0 -9
- package/types/src/filter-clause/value-editors/FilterClauseValueEditorNumber.d.ts +0 -9
- package/types/src/filter-clause/value-editors/FilterClauseValueEditorText.d.ts +0 -9
- package/types/src/filter-clause/value-editors/FilterClauseValueEditorTime.d.ts +0 -9
- package/types/src/filter-container/ExtendedSingleValueFilterClause.d.ts +0 -21
- package/types/src/filter-container/FilterContainer.d.ts +0 -23
- package/types/src/filter-container/useFilterContainer.d.ts +0 -22
- package/types/src/filter-context-menu/useFilterContextMenu.d.ts +0 -6
- package/types/src/filter-display/FilterDisplay.d.ts +0 -10
- package/types/src/filter-editor/FilterClauseCombinator.d.ts +0 -9
- package/types/src/filter-editor/FilterEditor.d.ts +0 -14
- package/types/src/filter-editor/index.d.ts +0 -1
- package/types/src/filter-editor/useFilterEditor.d.ts +0 -32
- package/types/src/filter-panel/FilterPanel.d.ts +0 -9
- package/types/src/filter-panel/useFilterPanel.d.ts +0 -14
- package/types/src/filter-pill/FilterMenu.d.ts +0 -24
- package/types/src/filter-pill/FilterPill.d.ts +0 -16
- package/types/src/filter-pill/FilterPillNext.d.ts +0 -15
- package/types/src/filter-pill/filterAsReactNode.d.ts +0 -3
- package/types/src/filter-pill/getFilterLabel.d.ts +0 -2
- package/types/src/filter-pill/getFilterTooltipText.d.ts +0 -2
- package/types/src/filter-pill/index.d.ts +0 -1
- package/types/src/filter-pill/useFilterPillNext.d.ts +0 -25
- package/types/src/filter-pill-menu/FilterPillMenu.d.ts +0 -17
- package/types/src/filter-pill-menu/FilterPillMenuOptions.d.ts +0 -12
- package/types/src/filter-pill-menu/index.d.ts +0 -1
- package/types/src/filter-provider/FilterContext.d.ts +0 -39
- package/types/src/filter-provider/FilterProvider.d.ts +0 -10
- package/types/src/filter-provider/filter-descriptor-utils.d.ts +0 -7
- package/types/src/filter-toggle-button/FilterToggleButton.d.ts +0 -9
- package/types/src/filter-utils.d.ts +0 -60
- package/types/src/index.d.ts +0 -24
- package/types/src/inline-filter/InlineFilter.d.ts +0 -12
- package/types/src/inline-filter/index.d.ts +0 -1
- package/types/src/inline-filter/useInlineFilter.d.ts +0 -5
- package/types/src/quick-filters/QuickFilters.d.ts +0 -17
- package/types/src/quick-filters/index.d.ts +0 -1
- package/types/src/quick-filters/useQuickFilters.d.ts +0 -12
- package/types/src/saved-filters/DeleteFilterPrompt.d.ts +0 -9
- package/types/src/saved-filters/FilterNamePrompt.d.ts +0 -6
- package/types/src/saved-filters/SavedFilterPanel.d.ts +0 -14
- package/types/src/saved-filters/useFilterNamePrompt.d.ts +0 -28
- package/types/src/saved-filters/useSavedFilterPanel.d.ts +0 -13
- package/types/src/tabbed-filter-container/TabbedFilterContainer.d.ts +0 -10
- package/types/src/toggle-filter/ToggleFilter.d.ts +0 -17
- package/types/src/toggle-filter/useToggleFilter.d.ts +0 -11
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "4.0.0-
|
|
2
|
+
"version": "4.0.0-beta.1",
|
|
3
3
|
"main": "./src/index.js",
|
|
4
4
|
"author": "heswell",
|
|
5
5
|
"license": "Apache-2.0",
|
|
@@ -10,23 +10,22 @@
|
|
|
10
10
|
"type-defs": "node ../../scripts/build-type-defs.mjs"
|
|
11
11
|
},
|
|
12
12
|
"devDependencies": {
|
|
13
|
-
"@vuu-ui/vuu-data-types": "4.0.0-
|
|
14
|
-
"@vuu-ui/vuu-protocol-types": "4.0.0-
|
|
15
|
-
"@vuu-ui/vuu-table-types": "4.0.0-
|
|
16
|
-
"@vuu-ui/vuu-filter-types": "4.0.0-
|
|
13
|
+
"@vuu-ui/vuu-data-types": "4.0.0-beta.1",
|
|
14
|
+
"@vuu-ui/vuu-protocol-types": "4.0.0-beta.1",
|
|
15
|
+
"@vuu-ui/vuu-table-types": "4.0.0-beta.1",
|
|
16
|
+
"@vuu-ui/vuu-filter-types": "4.0.0-beta.1"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@vuu-ui/vuu-context-menu": "4.0.0-
|
|
20
|
-
"@vuu-ui/vuu-data-react": "4.0.0-
|
|
21
|
-
"@vuu-ui/vuu-filter-parser": "4.0.0-
|
|
22
|
-
"@vuu-ui/vuu-popups": "4.0.0-
|
|
23
|
-
"@vuu-ui/vuu-ui-controls": "4.0.0-
|
|
24
|
-
"@vuu-ui/vuu-table": "4.0.0-
|
|
25
|
-
"@vuu-ui/vuu-utils": "4.0.0-
|
|
26
|
-
"@salt-ds/core": "1.
|
|
27
|
-
"@salt-ds/
|
|
28
|
-
"@salt-ds/
|
|
29
|
-
"@salt-ds/window": "0.1.1"
|
|
19
|
+
"@vuu-ui/vuu-context-menu": "4.0.0-beta.1",
|
|
20
|
+
"@vuu-ui/vuu-data-react": "4.0.0-beta.1",
|
|
21
|
+
"@vuu-ui/vuu-filter-parser": "4.0.0-beta.1",
|
|
22
|
+
"@vuu-ui/vuu-popups": "4.0.0-beta.1",
|
|
23
|
+
"@vuu-ui/vuu-ui-controls": "4.0.0-beta.1",
|
|
24
|
+
"@vuu-ui/vuu-table": "4.0.0-beta.1",
|
|
25
|
+
"@vuu-ui/vuu-utils": "4.0.0-beta.1",
|
|
26
|
+
"@salt-ds/core": "1.72.0",
|
|
27
|
+
"@salt-ds/styles": "0.4.1",
|
|
28
|
+
"@salt-ds/window": "0.1.2"
|
|
30
29
|
},
|
|
31
30
|
"peerDependencies": {
|
|
32
31
|
"@internationalized/date": "^3.0.0",
|
|
@@ -42,6 +41,7 @@
|
|
|
42
41
|
"exports": {
|
|
43
42
|
".": {
|
|
44
43
|
"import": "./src/index.js",
|
|
44
|
+
"default": "./src/index.js",
|
|
45
45
|
"types": "./types/index.d.ts"
|
|
46
46
|
}
|
|
47
47
|
},
|
package/src/FilterAggregator.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EpochTimestamp, getTemporalInfo, getTypedValueForDescriptor, isAndFilter, isBetweenFilter, isExtendedFilter, isMultiClauseFilter, isSingleValueFilter } from "@vuu-ui/vuu-utils";
|
|
2
2
|
import { ExtendedSingleValueFilterClause } from "./filter-container/ExtendedSingleValueFilterClause.js";
|
|
3
3
|
function installExtendedFilters(filter, throwIfUndefined = false) {
|
|
4
4
|
if (void 0 !== filter) if (isExtendedFilter(filter)) {
|
|
@@ -12,6 +12,47 @@ function installExtendedFilters(filter, throwIfUndefined = false) {
|
|
|
12
12
|
else return filter;
|
|
13
13
|
if (throwIfUndefined) throw Error("filter is undefined");
|
|
14
14
|
}
|
|
15
|
+
const getExtendedFilterOptions = (temporalInfo, extendedFilterOptions)=>{
|
|
16
|
+
if (temporalInfo?.kind === "time") return {
|
|
17
|
+
type: "TimeString",
|
|
18
|
+
date: "today",
|
|
19
|
+
encoding: temporalInfo.encoding,
|
|
20
|
+
timeZone: temporalInfo.timeZone,
|
|
21
|
+
...extendedFilterOptions
|
|
22
|
+
};
|
|
23
|
+
return extendedFilterOptions;
|
|
24
|
+
};
|
|
25
|
+
const getFilterValue = (column, value, temporalInfo, options, throwIfInvalid)=>{
|
|
26
|
+
if ("" === value) {
|
|
27
|
+
if (throwIfInvalid && !temporalInfo) return getTypedValueForDescriptor(value, column, true);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (options?.type === "TimeString") return asFilterTimeString(value, temporalInfo, throwIfInvalid);
|
|
31
|
+
return getTypedValueForDescriptor(value, column, throwIfInvalid);
|
|
32
|
+
};
|
|
33
|
+
const timeOfDayPattern = /^\d{2}:\d{2}(?::\d{2}(?:\.\d{1,9})?)?$/;
|
|
34
|
+
const asFilterTimeString = (value, temporalInfo, throwIfInvalid)=>{
|
|
35
|
+
if (timeOfDayPattern.test(value)) return 5 === value.length ? `${value}:00` : value;
|
|
36
|
+
const timestamp = EpochTimestamp.fromWire(value, temporalInfo?.encoding ?? "epochMillis");
|
|
37
|
+
if (timestamp && /^\d+$/.test(value)) {
|
|
38
|
+
const { hour, minute, second } = timestamp.getFields(temporalInfo?.timeZone);
|
|
39
|
+
const pad = (n)=>`${n}`.padStart(2, "0");
|
|
40
|
+
return `${pad(hour)}:${pad(minute)}:${pad(second)}`;
|
|
41
|
+
}
|
|
42
|
+
if (throwIfInvalid) throw Error(`[FilterAggregator] value ${value} is not a valid time`);
|
|
43
|
+
};
|
|
44
|
+
const singleValueOps = [
|
|
45
|
+
"=",
|
|
46
|
+
"!=",
|
|
47
|
+
">",
|
|
48
|
+
">=",
|
|
49
|
+
"<",
|
|
50
|
+
"<=",
|
|
51
|
+
"contains",
|
|
52
|
+
"starts",
|
|
53
|
+
"ends"
|
|
54
|
+
];
|
|
55
|
+
const asSingleValueOp = (op)=>singleValueOps.includes(op) ? op : "=";
|
|
15
56
|
class FilterAggregator {
|
|
16
57
|
#filters = new Map();
|
|
17
58
|
constructor(filter){
|
|
@@ -24,51 +65,29 @@ class FilterAggregator {
|
|
|
24
65
|
});
|
|
25
66
|
}
|
|
26
67
|
add(column, value, op = "=", extendedFilterOptions) {
|
|
27
|
-
const
|
|
68
|
+
const temporalInfo = getTemporalInfo(column);
|
|
69
|
+
const options = getExtendedFilterOptions(temporalInfo, extendedFilterOptions);
|
|
28
70
|
const isInclusive = "between-inclusive" === op;
|
|
29
|
-
const
|
|
30
|
-
if (Array.isArray(value)) {
|
|
31
|
-
const [value1, value2] = getTypedRange(value, dataType, extendedFilterOptions);
|
|
32
|
-
if (void 0 !== value1 && void 0 !== value2) {
|
|
33
|
-
const filter = extendedFilterOptions ? {
|
|
34
|
-
op: "and",
|
|
35
|
-
filters: [
|
|
36
|
-
new ExtendedSingleValueFilterClause(column.name, isInclusive ? ">=" : ">", value1, extendedFilterOptions),
|
|
37
|
-
new ExtendedSingleValueFilterClause(column.name, isInclusive ? "<=" : "<", value2, extendedFilterOptions)
|
|
38
|
-
]
|
|
39
|
-
} : {
|
|
40
|
-
op: "and",
|
|
41
|
-
filters: [
|
|
42
|
-
{
|
|
43
|
-
column: column.name,
|
|
44
|
-
op: ">",
|
|
45
|
-
value: value1
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
column: column.name,
|
|
49
|
-
op: "<",
|
|
50
|
-
value: value2
|
|
51
|
-
}
|
|
52
|
-
]
|
|
53
|
-
};
|
|
54
|
-
this.#filters.set(column.name, filter);
|
|
55
|
-
} else if (void 0 !== value1) this.#filters.set(column.name, {
|
|
71
|
+
const createClause = (op, value)=>options ? new ExtendedSingleValueFilterClause(column.name, op, value, options) : {
|
|
56
72
|
column: column.name,
|
|
57
|
-
op
|
|
58
|
-
value
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
73
|
+
op,
|
|
74
|
+
value
|
|
75
|
+
};
|
|
76
|
+
if (Array.isArray(value)) {
|
|
77
|
+
const [value1, value2] = value.map((v)=>getFilterValue(column, v, temporalInfo, options, false));
|
|
78
|
+
if (void 0 !== value1 && void 0 !== value2) this.#filters.set(column.name, {
|
|
79
|
+
op: "and",
|
|
80
|
+
filters: [
|
|
81
|
+
createClause(isInclusive ? ">=" : ">", value1),
|
|
82
|
+
createClause(isInclusive ? "<=" : "<", value2)
|
|
83
|
+
]
|
|
64
84
|
});
|
|
85
|
+
else if (void 0 !== value1) this.#filters.set(column.name, createClause("=", value1));
|
|
86
|
+
else if (void 0 !== value2) this.#filters.set(column.name, createClause(isInclusive ? "<=" : "<", value2));
|
|
65
87
|
} else {
|
|
66
|
-
const typedValue =
|
|
67
|
-
this.#filters.
|
|
68
|
-
|
|
69
|
-
op: "=",
|
|
70
|
-
value: typedValue
|
|
71
|
-
});
|
|
88
|
+
const typedValue = getFilterValue(column, value.toString(), temporalInfo, options, true);
|
|
89
|
+
if (void 0 === typedValue) this.#filters.delete(column.name);
|
|
90
|
+
else this.#filters.set(column.name, createClause(temporalInfo ? asSingleValueOp(op) : "=", typedValue));
|
|
72
91
|
}
|
|
73
92
|
}
|
|
74
93
|
has({ name }) {
|
|
@@ -2,23 +2,32 @@ import { jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { SegmentedButtonGroup } from "@salt-ds/core";
|
|
3
3
|
import { getDataItemEditControl } from "@vuu-ui/vuu-data-react";
|
|
4
4
|
import clsx from "clsx";
|
|
5
|
-
import { forwardRef as external_react_forwardRef } from "react";
|
|
5
|
+
import { forwardRef as external_react_forwardRef, useMemo } from "react";
|
|
6
6
|
import { useColumnFilter } from "./useColumnFilter.js";
|
|
7
7
|
import { useComponentCssInjection } from "@salt-ds/styles";
|
|
8
8
|
import { useWindow } from "@salt-ds/window";
|
|
9
9
|
import ColumnFilter_0 from "./ColumnFilter.css";
|
|
10
|
-
import { isBetweenOperator } from "@vuu-ui/vuu-utils";
|
|
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 = "=", 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",
|
|
16
16
|
css: ColumnFilter_0,
|
|
17
17
|
window: targetWindow
|
|
18
18
|
});
|
|
19
|
+
const { date, time } = pattern ?? {};
|
|
20
|
+
const controlDescriptor = useMemo(()=>withDateTimePattern(column, date || time ? {
|
|
21
|
+
date,
|
|
22
|
+
time
|
|
23
|
+
} : void 0), [
|
|
24
|
+
column,
|
|
25
|
+
date,
|
|
26
|
+
time
|
|
27
|
+
]);
|
|
19
28
|
const { InputProps, InputPropsRange, isInvalid, onCommit, onCommitRange } = useColumnFilter({
|
|
20
29
|
InputProps: InputPropsProp,
|
|
21
|
-
column,
|
|
30
|
+
column: controlDescriptor,
|
|
22
31
|
defaultValue,
|
|
23
32
|
extendedFilterOptions,
|
|
24
33
|
onColumnFilterChange,
|
|
@@ -30,7 +39,8 @@ const ColumnFilter_ColumnFilter = /*#__PURE__*/ external_react_forwardRef(functi
|
|
|
30
39
|
return /*#__PURE__*/ jsxs(SegmentedButtonGroup, {
|
|
31
40
|
...buttonGroupProps,
|
|
32
41
|
className: clsx(classBase, className, {
|
|
33
|
-
[`${classBase}-invalid`]: isInvalid
|
|
42
|
+
[`${classBase}-invalid`]: isInvalid,
|
|
43
|
+
[`${classBase}-toggle`]: "toggle" === variant
|
|
34
44
|
}),
|
|
35
45
|
ref: forwardRef,
|
|
36
46
|
children: [
|
|
@@ -38,7 +48,8 @@ const ColumnFilter_ColumnFilter = /*#__PURE__*/ external_react_forwardRef(functi
|
|
|
38
48
|
InputProps,
|
|
39
49
|
TypeaheadProps,
|
|
40
50
|
commitWhenCleared: true,
|
|
41
|
-
dataDescriptor:
|
|
51
|
+
dataDescriptor: controlDescriptor,
|
|
52
|
+
labels,
|
|
42
53
|
onCommit,
|
|
43
54
|
table,
|
|
44
55
|
values,
|
|
@@ -49,7 +60,7 @@ const ColumnFilter_ColumnFilter = /*#__PURE__*/ external_react_forwardRef(functi
|
|
|
49
60
|
className: `${classBase}-rangeHigh`,
|
|
50
61
|
commitWhenCleared: true,
|
|
51
62
|
variant,
|
|
52
|
-
dataDescriptor:
|
|
63
|
+
dataDescriptor: controlDescriptor,
|
|
53
64
|
onCommit: onCommitRange,
|
|
54
65
|
table
|
|
55
66
|
}) : null
|
|
@@ -12,7 +12,7 @@ const css = `
|
|
|
12
12
|
border-radius: var(--saltButton-borderRadius);
|
|
13
13
|
align-items: center;
|
|
14
14
|
gap: var(--salt-spacing-50);
|
|
15
|
-
height: calc(var(--salt-size-base) + var(--salt-
|
|
15
|
+
height: calc(var(--salt-size-base) + var(--salt-spacing-100));
|
|
16
16
|
min-width: calc(var(--salt-size-base) * 4);
|
|
17
17
|
padding: 0 var(--salt-spacing-100);
|
|
18
18
|
border-style: solid;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isNumericColumn,
|
|
1
|
+
import { isNumericColumn, isTemporalColumn, isTextColumn } from "@vuu-ui/vuu-utils";
|
|
2
2
|
const textOperators = [
|
|
3
3
|
"=",
|
|
4
4
|
"in",
|
|
@@ -17,7 +17,7 @@ const numericOperators = [
|
|
|
17
17
|
];
|
|
18
18
|
const getOperators = (column)=>{
|
|
19
19
|
if (isTextColumn(column)) return textOperators;
|
|
20
|
-
if (isNumericColumn(column) ||
|
|
20
|
+
if (isNumericColumn(column) || isTemporalColumn(column)) return numericOperators;
|
|
21
21
|
throw Error("getOperators only supports text and numeric columns");
|
|
22
22
|
};
|
|
23
23
|
export { getOperators, numericOperators, textOperators };
|
|
@@ -2,26 +2,29 @@ import { jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import clsx from "clsx";
|
|
3
3
|
import { FilterClauseValueEditorNumber } from "./FilterClauseValueEditorNumber.js";
|
|
4
4
|
import { FilterClauseValueEditorText } from "./FilterClauseValueEditorText.js";
|
|
5
|
-
import {
|
|
5
|
+
import { getTemporalInfo } from "@vuu-ui/vuu-utils";
|
|
6
6
|
import { forwardRef } from "react";
|
|
7
7
|
import { FilterClauseValueEditorDate } from "./FilterClauseValueEditorDate.js";
|
|
8
8
|
import { FilterClauseValueEditorTime } from "./FilterClauseValueEditorTime.js";
|
|
9
9
|
const classBase = "vuuFilterClause";
|
|
10
10
|
const FilterClauseValueEditor_FilterClauseValueEditor = /*#__PURE__*/ forwardRef(function({ selectedColumn, operator, inputProps, onChangeValue, onDeselectValue, onOpenChange, table, value, dropdownOnAutofocus = true }, forwardedRef) {
|
|
11
11
|
if (void 0 === selectedColumn || void 0 === operator) return null;
|
|
12
|
-
|
|
12
|
+
const temporalInfo = getTemporalInfo(selectedColumn);
|
|
13
|
+
if (temporalInfo?.kind === "time") return /*#__PURE__*/ jsx(FilterClauseValueEditorTime, {
|
|
13
14
|
inputProps: inputProps,
|
|
14
15
|
className: clsx(`${classBase}Field`, `${classBase}Value`),
|
|
15
16
|
value: value,
|
|
16
17
|
operator: operator,
|
|
17
|
-
onChangeValue: onChangeValue
|
|
18
|
+
onChangeValue: onChangeValue,
|
|
19
|
+
temporalInfo: temporalInfo
|
|
18
20
|
});
|
|
19
|
-
if (
|
|
21
|
+
if (temporalInfo) return /*#__PURE__*/ jsx(FilterClauseValueEditorDate, {
|
|
20
22
|
inputProps: inputProps,
|
|
21
23
|
className: clsx(`${classBase}Field`, `${classBase}Value`),
|
|
22
24
|
value: value,
|
|
23
25
|
operator: operator,
|
|
24
|
-
onChangeValue: onChangeValue
|
|
26
|
+
onChangeValue: onChangeValue,
|
|
27
|
+
temporalInfo: temporalInfo
|
|
25
28
|
});
|
|
26
29
|
switch(selectedColumn.serverDataType){
|
|
27
30
|
case "string":
|
|
@@ -1,55 +1,23 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback
|
|
3
|
-
import {
|
|
4
|
-
import { toCalendarDate } from "@vuu-ui/vuu-utils";
|
|
2
|
+
import { useCallback } from "react";
|
|
3
|
+
import { EpochTimestamp } from "@vuu-ui/vuu-utils";
|
|
5
4
|
import { VuuDatePicker } from "@vuu-ui/vuu-ui-controls";
|
|
6
|
-
const FilterClauseValueEditorDate = (
|
|
7
|
-
const {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
console.log("change date");
|
|
12
|
-
if (selectedDateInputValue) {
|
|
13
|
-
const dateValue = toCalendarDate(new Date(selectedDateInputValue));
|
|
14
|
-
setDate(dateValue);
|
|
15
|
-
if (selectedDateInputValue) onChangeValue(toEpochMilliS(dateValue));
|
|
16
|
-
}
|
|
5
|
+
const FilterClauseValueEditorDate = ({ className, inputProps, onChangeValue, temporalInfo, value })=>{
|
|
6
|
+
const { encoding, timeZone } = temporalInfo;
|
|
7
|
+
const handleCommit = useCallback((_e, startOfDayMillis)=>{
|
|
8
|
+
const timestamp = EpochTimestamp.fromMillis(startOfDayMillis);
|
|
9
|
+
onChangeValue("epochNanos" === encoding ? timestamp.toWire("epochNanos") : timestamp.toWire("epochMillis"));
|
|
17
10
|
}, [
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
]);
|
|
21
|
-
const onBlur = useCallback(()=>{
|
|
22
|
-
date && onChangeValue(toEpochMilliS(date));
|
|
23
|
-
}, [
|
|
24
|
-
date,
|
|
25
|
-
onChangeValue,
|
|
26
|
-
toEpochMilliS
|
|
11
|
+
encoding,
|
|
12
|
+
onChangeValue
|
|
27
13
|
]);
|
|
28
14
|
return /*#__PURE__*/ jsx(VuuDatePicker, {
|
|
29
15
|
"data-field": "value",
|
|
30
16
|
inputProps: inputProps,
|
|
31
17
|
className: className,
|
|
32
|
-
onBlur: onBlur,
|
|
33
18
|
onCommit: handleCommit,
|
|
34
|
-
|
|
19
|
+
timeZone: timeZone,
|
|
20
|
+
value: EpochTimestamp.fromWire(value, encoding)
|
|
35
21
|
});
|
|
36
22
|
};
|
|
37
|
-
function getInitialState(value) {
|
|
38
|
-
return value ? toCalendarDate(new Date(value)) : void 0;
|
|
39
|
-
}
|
|
40
|
-
const getEpochMillisConverter = (op)=>(date, timezone = getLocalTimeZone())=>{
|
|
41
|
-
const d = date.toDate(timezone);
|
|
42
|
-
switch(op){
|
|
43
|
-
case ">":
|
|
44
|
-
case "<=":
|
|
45
|
-
d.setHours(23, 59, 59, 999);
|
|
46
|
-
return d.getTime();
|
|
47
|
-
case ">=":
|
|
48
|
-
case "<":
|
|
49
|
-
case "=":
|
|
50
|
-
case "!=":
|
|
51
|
-
d.setHours(0, 0, 0, 0);
|
|
52
|
-
return d.getTime();
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
23
|
export { FilterClauseValueEditorDate };
|
|
@@ -1,53 +1,27 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback
|
|
3
|
-
import {
|
|
4
|
-
import { toCalendarDate } from "@vuu-ui/vuu-utils";
|
|
2
|
+
import { useCallback } from "react";
|
|
3
|
+
import { EpochTimestamp, isValidTimeString } from "@vuu-ui/vuu-utils";
|
|
5
4
|
import { VuuTimePicker } from "@vuu-ui/vuu-ui-controls";
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
onChangeValue,
|
|
19
|
-
toEpochMilliS
|
|
20
|
-
]);
|
|
21
|
-
const onBlur = useCallback(()=>{
|
|
22
|
-
date && onChangeValue(toEpochMilliS(date));
|
|
5
|
+
const pad = (n)=>`${n}`.padStart(2, "0");
|
|
6
|
+
const toTimeString = (value, { encoding, timeZone })=>{
|
|
7
|
+
if (isValidTimeString(value)) return value;
|
|
8
|
+
const timestamp = EpochTimestamp.fromWire(value, encoding);
|
|
9
|
+
if (timestamp) {
|
|
10
|
+
const { hour, minute, second } = timestamp.getFields(timeZone);
|
|
11
|
+
return `${pad(hour)}:${pad(minute)}:${pad(second)}`;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
const FilterClauseValueEditorTime = ({ className, onChangeValue, temporalInfo, value })=>{
|
|
15
|
+
const handleCommit = useCallback((_e, timeString)=>{
|
|
16
|
+
if (isValidTimeString(timeString)) onChangeValue(timeString);
|
|
23
17
|
}, [
|
|
24
|
-
|
|
25
|
-
onChangeValue,
|
|
26
|
-
toEpochMilliS
|
|
18
|
+
onChangeValue
|
|
27
19
|
]);
|
|
28
20
|
return /*#__PURE__*/ jsx(VuuTimePicker, {
|
|
29
21
|
"data-field": "value",
|
|
30
22
|
className: className,
|
|
31
|
-
|
|
23
|
+
defaultValue: toTimeString(value, temporalInfo),
|
|
32
24
|
onCommit: handleCommit
|
|
33
25
|
});
|
|
34
26
|
};
|
|
35
|
-
function getInitialState(value) {
|
|
36
|
-
return value ? toCalendarDate(new Date(value)) : void 0;
|
|
37
|
-
}
|
|
38
|
-
const getEpochMillisConverter = (op)=>(date, timezone = getLocalTimeZone())=>{
|
|
39
|
-
const d = date.toDate(timezone);
|
|
40
|
-
switch(op){
|
|
41
|
-
case ">":
|
|
42
|
-
case "<=":
|
|
43
|
-
d.setHours(23, 59, 59, 999);
|
|
44
|
-
return d.getTime();
|
|
45
|
-
case ">=":
|
|
46
|
-
case "<":
|
|
47
|
-
case "=":
|
|
48
|
-
case "!=":
|
|
49
|
-
d.setHours(0, 0, 0, 0);
|
|
50
|
-
return d.getTime();
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
27
|
export { FilterClauseValueEditorTime };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getDefaultTimeZone, isValidTimeString, temporalFilterAsQuery } from "@vuu-ui/vuu-utils";
|
|
2
2
|
const isTimeToday = (options)=>"TimeString" === options.type && "today" === options.date;
|
|
3
|
+
const timeStringWithFraction = /^\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?$/;
|
|
3
4
|
class ExtendedSingleValueFilterClause {
|
|
4
5
|
column;
|
|
5
6
|
op;
|
|
@@ -12,14 +13,27 @@ class ExtendedSingleValueFilterClause {
|
|
|
12
13
|
this.#options = extendedOptions;
|
|
13
14
|
}
|
|
14
15
|
name;
|
|
16
|
+
get extendedOptions() {
|
|
17
|
+
return this.#options;
|
|
18
|
+
}
|
|
15
19
|
asQuery() {
|
|
16
20
|
const { column, op, value } = this;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
const { date, encoding = "epochMillis", timeZone } = this.#options;
|
|
22
|
+
if ("TimeString" === this.#options.type) if ("string" == typeof value && (isValidTimeString(value) || timeStringWithFraction.test(value))) {
|
|
23
|
+
const temporalInfo = {
|
|
24
|
+
kind: "time",
|
|
25
|
+
encoding,
|
|
26
|
+
precision: "epochNanos" === encoding ? "ns" : "ms",
|
|
27
|
+
timeZone: timeZone ?? getDefaultTimeZone()
|
|
28
|
+
};
|
|
29
|
+
return temporalFilterAsQuery({
|
|
30
|
+
column,
|
|
31
|
+
op,
|
|
32
|
+
value
|
|
33
|
+
}, temporalInfo, {
|
|
34
|
+
date: date
|
|
35
|
+
});
|
|
36
|
+
} else throw Error(`[ExtendedSingleValueFilterClause] invalid TimeString ${value}`);
|
|
23
37
|
throw Error("[ExtendedSingleValueFilterClause] unhandled extended filter type");
|
|
24
38
|
}
|
|
25
39
|
toJSON() {
|
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import clsx from "clsx";
|
|
3
|
-
import { useCallback, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { ColumnFilterContext, useFilterContainer, useFilterContext } from "./useFilterContainer.js";
|
|
5
5
|
import { ColumnFilter } from "../column-filter/ColumnFilter.js";
|
|
6
|
-
import { filterDescriptorHasFilter, isNullFilter, useSavedFilters } from "../filter-provider/FilterContext.js";
|
|
7
|
-
import { filtersAreEqual, getColumnValueFromFilter, isBetweenOperator } from "@vuu-ui/vuu-utils";
|
|
6
|
+
import { filterDescriptorHasFilter, isNullFilter, useColumnFilterRegistry, useSavedFilters } from "../filter-provider/FilterContext.js";
|
|
7
|
+
import { filtersAreEqual, getColumnValueFromFilter, getDefaultTimeRange, isBetweenOperator, isTimeDataValue, withDateTimePattern } from "@vuu-ui/vuu-utils";
|
|
8
8
|
import { useComponentCssInjection } from "@salt-ds/styles";
|
|
9
9
|
import { useWindow } from "@salt-ds/window";
|
|
10
10
|
import FilterContainer from "./FilterContainer.css";
|
|
11
11
|
const classBase = "vuuFilterContainer";
|
|
12
12
|
const notEmpty = (value)=>Array.isArray(value) ? "" !== value[0] && "" !== value[1] : "" !== value;
|
|
13
|
-
const FilterContainerColumnFilter = ({ column, operator = "=", variant, ...props })=>{
|
|
13
|
+
const FilterContainerColumnFilter = ({ column: columnProp, operator = "=", pattern: patternProp, variant, ...props })=>{
|
|
14
|
+
const { getColumnFilterPattern } = useColumnFilterRegistry();
|
|
15
|
+
const pattern = patternProp ?? getColumnFilterPattern(columnProp);
|
|
16
|
+
const { date, time } = pattern ?? {};
|
|
17
|
+
const column = useMemo(()=>withDateTimePattern(columnProp, date || time ? {
|
|
18
|
+
date,
|
|
19
|
+
time
|
|
20
|
+
} : void 0), [
|
|
21
|
+
columnProp,
|
|
22
|
+
date,
|
|
23
|
+
time
|
|
24
|
+
]);
|
|
14
25
|
const { filterProviderKey, onChange: onFilterContextChange, onCommit: onFilterContextCommit, register } = useFilterContext(column, true);
|
|
26
|
+
const { registerColumnFilterColumn } = useColumnFilterRegistry(filterProviderKey);
|
|
27
|
+
useEffect(()=>registerColumnFilterColumn(column), [
|
|
28
|
+
column,
|
|
29
|
+
registerColumnFilterColumn
|
|
30
|
+
]);
|
|
15
31
|
const initialValue = useMemo(()=>register(column, operator), [
|
|
16
32
|
column,
|
|
17
33
|
operator,
|
|
@@ -25,10 +41,7 @@ const FilterContainerColumnFilter = ({ column, operator = "=", variant, ...props
|
|
|
25
41
|
if (currentFilterRef.current.id !== currentFilter.id || !filtersAreEqual(currentFilterRef.current.filter, currentFilter.filter)) {
|
|
26
42
|
currentFilterRef.current = currentFilter;
|
|
27
43
|
if (isNullFilter(currentFilter) && notEmpty(valueRef.current)) {
|
|
28
|
-
if (Array.isArray(valueRef.current)) if (
|
|
29
|
-
"00:00:00",
|
|
30
|
-
"23:59:59"
|
|
31
|
-
];
|
|
44
|
+
if (Array.isArray(valueRef.current)) if (isTimeDataValue(column)) valueRef.current = getDefaultTimeRange(column);
|
|
32
45
|
else valueRef.current = [
|
|
33
46
|
"",
|
|
34
47
|
""
|
|
@@ -53,8 +66,7 @@ const FilterContainerColumnFilter = ({ column, operator = "=", variant, ...props
|
|
|
53
66
|
}
|
|
54
67
|
}, [
|
|
55
68
|
column,
|
|
56
|
-
currentFilter
|
|
57
|
-
operator
|
|
69
|
+
currentFilter
|
|
58
70
|
]);
|
|
59
71
|
const handleCommit = useCallback((column, op, value, extendedFilterOptions)=>{
|
|
60
72
|
valueRef.current = value;
|