@vuu-ui/vuu-filters 4.0.0-beta.7 → 4.0.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.
Files changed (91) hide show
  1. package/README.md +40 -0
  2. package/package.json +14 -14
  3. package/src/FilterAggregator.js +16 -5
  4. package/src/column-filter/ColumnFilter.css.js +23 -0
  5. package/src/column-filter/ColumnFilter.js +35 -8
  6. package/src/column-filter/column-filter-utils.js +40 -0
  7. package/src/column-filter/useColumnFilter.js +68 -16
  8. package/src/filter-clause/operator-picker/OperatorPicker.js +30 -3
  9. package/src/filter-container/ExtendedSingleValueFilterClause.js +25 -17
  10. package/src/filter-container/FilterContainer.js +75 -5
  11. package/src/filter-container/useFilterContainer.js +7 -0
  12. package/src/filter-context-menu/useFilterContextMenu.js +6 -1
  13. package/types/column-filter/column-filter-utils.d.ts +8 -0
  14. package/types/column-filter/useColumnFilter.d.ts +15 -1
  15. package/types/filter-clause/operator-picker/OperatorPicker.d.ts +17 -7
  16. package/types/filter-container/ExtendedSingleValueFilterClause.d.ts +6 -3
  17. package/types/filter-container/FilterContainer.d.ts +1 -1
  18. package/types/filter-container/useFilterContainer.d.ts +3 -1
  19. package/types/index.d.ts +1 -0
  20. package/types/src/FilterAggregator.d.ts +28 -0
  21. package/types/src/FilterModel.d.ts +44 -0
  22. package/types/src/column-filter/ColumnFilter.d.ts +6 -0
  23. package/types/src/column-filter/useColumnFilter.d.ts +43 -0
  24. package/types/src/column-filter/utils.d.ts +4 -0
  25. package/types/src/custom-filters/CustomFilters.d.ts +7 -0
  26. package/types/src/custom-filters/filterBarFocusManagement.d.ts +1 -0
  27. package/types/src/custom-filters/index.d.ts +1 -0
  28. package/types/src/custom-filters/useCustomFilters.d.ts +33 -0
  29. package/types/src/custom-filters/useFilterState.d.ts +17 -0
  30. package/types/src/filter-bar/FilterBar.d.ts +33 -0
  31. package/types/src/filter-bar/FilterBarMenu.d.ts +1 -0
  32. package/types/src/filter-bar/index.d.ts +2 -0
  33. package/types/src/filter-bar/useFilterBar.d.ts +7 -0
  34. package/types/src/filter-clause/ExpandoCombobox.d.ts +10 -0
  35. package/types/src/filter-clause/FilterClause.d.ts +16 -0
  36. package/types/src/filter-clause/column-picker/ColumnPicker.d.ts +13 -0
  37. package/types/src/filter-clause/column-picker/useColumnPicker.d.ts +11 -0
  38. package/types/src/filter-clause/filterClauseFocusManagement.d.ts +15 -0
  39. package/types/src/filter-clause/filterClauseTypes.d.ts +12 -0
  40. package/types/src/filter-clause/index.d.ts +5 -0
  41. package/types/src/filter-clause/operator-picker/OperatorPicker.d.ts +14 -0
  42. package/types/src/filter-clause/operator-picker/operator-utils.d.ts +5 -0
  43. package/types/src/filter-clause/operator-picker/useOperatorPicker.d.ts +12 -0
  44. package/types/src/filter-clause/useFilterClause.d.ts +26 -0
  45. package/types/src/filter-clause/value-editors/FilterClauseValueEditor.d.ts +26 -0
  46. package/types/src/filter-clause/value-editors/FilterClauseValueEditorDate.d.ts +9 -0
  47. package/types/src/filter-clause/value-editors/FilterClauseValueEditorNumber.d.ts +9 -0
  48. package/types/src/filter-clause/value-editors/FilterClauseValueEditorText.d.ts +9 -0
  49. package/types/src/filter-clause/value-editors/FilterClauseValueEditorTime.d.ts +9 -0
  50. package/types/src/filter-container/ExtendedSingleValueFilterClause.d.ts +21 -0
  51. package/types/src/filter-container/FilterContainer.d.ts +23 -0
  52. package/types/src/filter-container/useFilterContainer.d.ts +22 -0
  53. package/types/src/filter-context-menu/useFilterContextMenu.d.ts +6 -0
  54. package/types/src/filter-display/FilterDisplay.d.ts +10 -0
  55. package/types/src/filter-editor/FilterClauseCombinator.d.ts +9 -0
  56. package/types/src/filter-editor/FilterEditor.d.ts +14 -0
  57. package/types/src/filter-editor/index.d.ts +1 -0
  58. package/types/src/filter-editor/useFilterEditor.d.ts +32 -0
  59. package/types/src/filter-panel/FilterPanel.d.ts +9 -0
  60. package/types/src/filter-panel/useFilterPanel.d.ts +14 -0
  61. package/types/src/filter-pill/FilterMenu.d.ts +24 -0
  62. package/types/src/filter-pill/FilterPill.d.ts +16 -0
  63. package/types/src/filter-pill/FilterPillNext.d.ts +15 -0
  64. package/types/src/filter-pill/filterAsReactNode.d.ts +3 -0
  65. package/types/src/filter-pill/getFilterLabel.d.ts +2 -0
  66. package/types/src/filter-pill/getFilterTooltipText.d.ts +2 -0
  67. package/types/src/filter-pill/index.d.ts +1 -0
  68. package/types/src/filter-pill/useFilterPillNext.d.ts +25 -0
  69. package/types/src/filter-pill-menu/FilterPillMenu.d.ts +17 -0
  70. package/types/src/filter-pill-menu/FilterPillMenuOptions.d.ts +12 -0
  71. package/types/src/filter-pill-menu/index.d.ts +1 -0
  72. package/types/src/filter-provider/FilterContext.d.ts +39 -0
  73. package/types/src/filter-provider/FilterProvider.d.ts +10 -0
  74. package/types/src/filter-provider/filter-descriptor-utils.d.ts +7 -0
  75. package/types/src/filter-toggle-button/FilterToggleButton.d.ts +9 -0
  76. package/types/src/filter-utils.d.ts +60 -0
  77. package/types/src/index.d.ts +24 -0
  78. package/types/src/inline-filter/InlineFilter.d.ts +12 -0
  79. package/types/src/inline-filter/index.d.ts +1 -0
  80. package/types/src/inline-filter/useInlineFilter.d.ts +5 -0
  81. package/types/src/quick-filters/QuickFilters.d.ts +17 -0
  82. package/types/src/quick-filters/index.d.ts +1 -0
  83. package/types/src/quick-filters/useQuickFilters.d.ts +12 -0
  84. package/types/src/saved-filters/DeleteFilterPrompt.d.ts +9 -0
  85. package/types/src/saved-filters/FilterNamePrompt.d.ts +6 -0
  86. package/types/src/saved-filters/SavedFilterPanel.d.ts +14 -0
  87. package/types/src/saved-filters/useFilterNamePrompt.d.ts +28 -0
  88. package/types/src/saved-filters/useSavedFilterPanel.d.ts +13 -0
  89. package/types/src/tabbed-filter-container/TabbedFilterContainer.d.ts +10 -0
  90. package/types/src/toggle-filter/ToggleFilter.d.ts +17 -0
  91. package/types/src/toggle-filter/useToggleFilter.d.ts +11 -0
@@ -3,14 +3,16 @@ import clsx from "clsx";
3
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, useColumnFilterRegistry, useSavedFilters } from "../filter-provider/FilterContext.js";
6
+ import { UNSAVED_FILTER, filterDescriptorHasFilter, isNullFilter, useColumnFilterRegistry, useSavedFilters } from "../filter-provider/FilterContext.js";
7
7
  import { filtersAreEqual, getColumnValueFromFilter, getDefaultTimeRange, isBetweenOperator, isTimeDataValue, withDateTimePattern } from "@vuu-ui/vuu-utils";
8
+ import { useControlled } from "@salt-ds/core";
9
+ import { getColumnFilterClause, getColumnFilterOperator, getColumnFilterOperators, getDefaultColumnFilterOperator, normalizeColumnFilterValue } from "../column-filter/column-filter-utils.js";
8
10
  import { useComponentCssInjection } from "@salt-ds/styles";
9
11
  import { useWindow } from "@salt-ds/window";
10
12
  import FilterContainer from "./FilterContainer.css";
11
13
  const classBase = "vuuFilterContainer";
12
14
  const notEmpty = (value)=>Array.isArray(value) ? "" !== value[0] && "" !== value[1] : "" !== value;
13
- const FilterContainerColumnFilter = ({ column: columnProp, operator = "=", pattern: patternProp, variant, ...props })=>{
15
+ const FilterContainerColumnFilter = ({ column: columnProp, operator: operatorProp, defaultOperator, showOperatorPicker = false, operators, onOperatorChange, pattern: patternProp, variant, ...props })=>{
14
16
  const { getColumnFilterPattern } = useColumnFilterRegistry();
15
17
  const pattern = patternProp ?? getColumnFilterPattern(columnProp);
16
18
  const { date, time } = pattern ?? {};
@@ -22,7 +24,20 @@ const FilterContainerColumnFilter = ({ column: columnProp, operator = "=", patte
22
24
  date,
23
25
  time
24
26
  ]);
25
- const { filterProviderKey, onChange: onFilterContextChange, onCommit: onFilterContextCommit, register } = useFilterContext(column, true);
27
+ const { filter: containerFilter, getFilter, filterProviderKey, onChange: onFilterContextChange, onCommit: onFilterContextCommit, register } = useFilterContext(column, true);
28
+ const availableOperators = useMemo(()=>showOperatorPicker ? getColumnFilterOperators(column, operators) : void 0, [
29
+ column,
30
+ operators,
31
+ showOperatorPicker
32
+ ]);
33
+ const [initialOperator] = useState(()=>availableOperators ? getDefaultColumnFilterOperator(availableOperators, operatorProp ?? getColumnFilterOperator(column, containerFilter) ?? defaultOperator) : defaultOperator ?? "=");
34
+ const [selectedOperator, setOperator] = useControlled({
35
+ controlled: operatorProp,
36
+ default: initialOperator,
37
+ name: "FilterContainerColumnFilter",
38
+ state: "operator"
39
+ });
40
+ const operator = selectedOperator;
26
41
  const { registerColumnFilterColumn } = useColumnFilterRegistry(filterProviderKey);
27
42
  useEffect(()=>registerColumnFilterColumn(column), [
28
43
  column,
@@ -35,10 +50,50 @@ const FilterContainerColumnFilter = ({ column: columnProp, operator = "=", patte
35
50
  ]);
36
51
  const [value, setValue] = useState(initialValue);
37
52
  const valueRef = useRef(initialValue);
53
+ if (showOperatorPicker) {
54
+ const normalizedValue = normalizeColumnFilterValue(operator, value);
55
+ if (normalizedValue !== value) {
56
+ valueRef.current = normalizedValue;
57
+ setValue(normalizedValue);
58
+ }
59
+ }
38
60
  const { currentFilter } = useSavedFilters(filterProviderKey);
39
61
  const currentFilterRef = useRef(currentFilter);
62
+ const containerFilterRef = useRef(containerFilter);
63
+ const localFilterRef = useRef(containerFilter);
64
+ useMemo(()=>{
65
+ if (!showOperatorPicker) return;
66
+ const containerChanged = !filtersAreEqual(containerFilterRef.current, containerFilter);
67
+ const savedChanged = currentFilterRef.current.id !== currentFilter.id || !filtersAreEqual(currentFilterRef.current.filter, currentFilter.filter);
68
+ if (containerChanged || savedChanged) {
69
+ const savedIdChanged = currentFilterRef.current.id !== currentFilter.id;
70
+ const filter = containerChanged ? containerFilter : currentFilter.filter ?? void 0;
71
+ containerFilterRef.current = containerFilter;
72
+ currentFilterRef.current = currentFilter;
73
+ const savedFilterActivated = savedIdChanged && filterDescriptorHasFilter(currentFilter) && currentFilter.id !== UNSAVED_FILTER;
74
+ const clause = getColumnFilterClause(column, filter);
75
+ if (savedFilterActivated || !filtersAreEqual(clause, getColumnFilterClause(column, localFilterRef.current))) {
76
+ const nextOperator = operatorProp ?? (availableOperators ? getDefaultColumnFilterOperator(availableOperators, getColumnFilterOperator(column, filter) ?? defaultOperator) : operator);
77
+ const nextValue = normalizeColumnFilterValue(nextOperator, getColumnValueFromFilter(column, nextOperator, clause));
78
+ setOperator(nextOperator);
79
+ valueRef.current = nextValue;
80
+ setValue(nextValue);
81
+ localFilterRef.current = filter;
82
+ }
83
+ }
84
+ }, [
85
+ availableOperators,
86
+ column,
87
+ containerFilter,
88
+ currentFilter,
89
+ defaultOperator,
90
+ operator,
91
+ operatorProp,
92
+ setOperator,
93
+ showOperatorPicker
94
+ ]);
40
95
  useMemo(()=>{
41
- if (currentFilterRef.current.id !== currentFilter.id || !filtersAreEqual(currentFilterRef.current.filter, currentFilter.filter)) {
96
+ if (!showOperatorPicker && (currentFilterRef.current.id !== currentFilter.id || !filtersAreEqual(currentFilterRef.current.filter, currentFilter.filter))) {
42
97
  currentFilterRef.current = currentFilter;
43
98
  if (isNullFilter(currentFilter) && notEmpty(valueRef.current)) {
44
99
  if (Array.isArray(valueRef.current)) if (isTimeDataValue(column)) valueRef.current = getDefaultTimeRange(column);
@@ -66,13 +121,16 @@ const FilterContainerColumnFilter = ({ column: columnProp, operator = "=", patte
66
121
  }
67
122
  }, [
68
123
  column,
69
- currentFilter
124
+ currentFilter,
125
+ showOperatorPicker
70
126
  ]);
71
127
  const handleCommit = useCallback((column, op, value, extendedFilterOptions)=>{
72
128
  valueRef.current = value;
73
129
  setValue(value);
74
130
  onFilterContextCommit(column, op, value, extendedFilterOptions);
131
+ localFilterRef.current = getFilter();
75
132
  }, [
133
+ getFilter,
76
134
  onFilterContextCommit
77
135
  ]);
78
136
  const handleColumnFilterChange = useCallback((value, column, op)=>{
@@ -83,7 +141,9 @@ const FilterContainerColumnFilter = ({ column: columnProp, operator = "=", patte
83
141
  ] : value;
84
142
  setValue(valueRef.current);
85
143
  onFilterContextChange(valueRef.current, column, op);
144
+ localFilterRef.current = getFilter();
86
145
  }, [
146
+ getFilter,
87
147
  onFilterContextChange
88
148
  ]);
89
149
  const handleColumnRangeFilterChange = useCallback((value, column, op)=>{
@@ -94,7 +154,9 @@ const FilterContainerColumnFilter = ({ column: columnProp, operator = "=", patte
94
154
  ] : value;
95
155
  setValue(valueRef.current);
96
156
  onFilterContextChange(valueRef.current, column, op);
157
+ localFilterRef.current = getFilter();
97
158
  }, [
159
+ getFilter,
98
160
  onFilterContextChange
99
161
  ]);
100
162
  return /*#__PURE__*/ jsx(ColumnFilter, {
@@ -104,6 +166,14 @@ const FilterContainerColumnFilter = ({ column: columnProp, operator = "=", patte
104
166
  onColumnRangeFilterChange: handleColumnRangeFilterChange,
105
167
  onCommit: handleCommit,
106
168
  operator: operator,
169
+ onOperatorChange: (event, op)=>{
170
+ setOperator(op);
171
+ valueRef.current = normalizeColumnFilterValue(op, valueRef.current);
172
+ setValue(valueRef.current);
173
+ onOperatorChange?.(event, op);
174
+ },
175
+ operators: operators,
176
+ showOperatorPicker: showOperatorPicker,
107
177
  value: value,
108
178
  variant: variant
109
179
  });
@@ -7,6 +7,8 @@ const ColumnFilterContext = createContext({
7
7
  function useFilterContext(column, throwIfNoContainer = false) {
8
8
  const ctx = useContext(ColumnFilterContext);
9
9
  if (ctx) return {
10
+ filter: ctx.filter,
11
+ getFilter: ctx.getFilter,
10
12
  filterProviderKey: ctx.filterProviderKey,
11
13
  register: ctx.register,
12
14
  getValue: ctx.getValue,
@@ -29,6 +31,9 @@ const useFilterContainer = ({ filter, filterProviderKey = "GLOBAL", onFilterAppl
29
31
  const filterAggregator = useMemo(()=>new FilterAggregator(filter), [
30
32
  filter
31
33
  ]);
34
+ const getFilter = useCallback(()=>filterAggregator.filter, [
35
+ filterAggregator
36
+ ]);
32
37
  const register = useCallback((column, op)=>valueRef.current[column.name] = getColumnValueFromFilter(column, op, filterRef.current), []);
33
38
  const getValue = useCallback((column, fallbackValue)=>{
34
39
  const value = valueRef.current[column.name];
@@ -72,6 +77,8 @@ const useFilterContainer = ({ filter, filterProviderKey = "GLOBAL", onFilterAppl
72
77
  ]);
73
78
  return {
74
79
  filterContainerInstalled: true,
80
+ filter,
81
+ getFilter,
75
82
  filterProviderKey,
76
83
  onChange: handleInputChange,
77
84
  onCommit: handleCommit,
@@ -1,4 +1,4 @@
1
- import { filtersAreEqual, getTemporalCellFilter, getTemporalInfo, withDateTimePattern } from "@vuu-ui/vuu-utils";
1
+ import { filtersAreEqual, getScaledDecimalCellFilter, getTemporalCellFilter, getTemporalInfo, withDateTimePattern } from "@vuu-ui/vuu-utils";
2
2
  import { useCallback, useMemo, useRef } from "react";
3
3
  import { useColumnFilterRegistry, useSavedFilters } from "../filter-provider/FilterContext.js";
4
4
  import { FilterAggregator } from "../FilterAggregator.js";
@@ -23,6 +23,11 @@ const useFilterContextMenu = ({ filterColumns = "*", filterPatterns, filterProvi
23
23
  ...temporalCellFilter
24
24
  };
25
25
  }
26
+ const scaledDecimalCellFilter = getScaledDecimalCellFilter(column, value);
27
+ if (scaledDecimalCellFilter) return {
28
+ column,
29
+ ...scaledDecimalCellFilter
30
+ };
26
31
  return {
27
32
  column,
28
33
  label: `${value}`,
@@ -0,0 +1,8 @@
1
+ import type { ColumnFilterOp, ColumnFilterValue, FilterContainerFilter } from "@vuu-ui/vuu-filter-types";
2
+ import type { ColumnDescriptor } from "@vuu-ui/vuu-table-types";
3
+ export type SelectableColumnFilterOp = Exclude<ColumnFilterOp, "in">;
4
+ export declare const getColumnFilterOperators: (column: ColumnDescriptor, operators?: readonly SelectableColumnFilterOp[]) => readonly SelectableColumnFilterOp[];
5
+ export declare const getDefaultColumnFilterOperator: (operators: readonly SelectableColumnFilterOp[], operator?: ColumnFilterOp) => SelectableColumnFilterOp;
6
+ export declare const getColumnFilterOperator: (column: ColumnDescriptor, filter?: FilterContainerFilter) => SelectableColumnFilterOp | undefined;
7
+ export declare const getColumnFilterClause: (column: ColumnDescriptor, filter?: FilterContainerFilter) => FilterContainerFilter | undefined;
8
+ export declare const normalizeColumnFilterValue: (operator: ColumnFilterOp, value?: ColumnFilterValue) => ColumnFilterValue;
@@ -1,8 +1,10 @@
1
1
  import { ColumnFilterChangeHandler, ColumnFilterCommitHandler, ColumnFilterOp, ColumnFilterValue, ExtendedFilterOptions } from "@vuu-ui/vuu-filter-types";
2
2
  import { ColumnDescriptor } from "@vuu-ui/vuu-table-types";
3
3
  import { InputProps } from "@salt-ds/core";
4
+ import { SyntheticEvent } from "react";
4
5
  import { CommitHandler } from "@vuu-ui/vuu-utils";
5
6
  import { DataItemEditControlProps } from "@vuu-ui/vuu-data-react";
7
+ import { type SelectableColumnFilterOp } from "./column-filter-utils";
6
8
  export interface ColumnFilterHookProps extends Pick<DataItemEditControlProps, "InputProps"> {
7
9
  column: ColumnDescriptor;
8
10
  /**
@@ -27,17 +29,29 @@ export interface ColumnFilterHookProps extends Pick<DataItemEditControlProps, "I
27
29
  * tabbing away from control or making selection from list
28
30
  */
29
31
  onCommit: ColumnFilterCommitHandler;
32
+ /** Controlled operator. Defaults to '=' when the picker is hidden. */
30
33
  operator?: ColumnFilterOp;
34
+ /** Initial operator for an uncontrolled picker. Defaults to '=' or the first option. */
35
+ defaultOperator?: ColumnFilterOp;
36
+ /** Render an operator dropdown before the value. Defaults to false. */
37
+ showOperatorPicker?: boolean;
38
+ /** Ordered operator options, replacing the column-type defaults. 'in' is not supported. */
39
+ operators?: readonly SelectableColumnFilterOp[];
40
+ /** Called before committing the current value with the newly selected operator. */
41
+ onOperatorChange?: (event: SyntheticEvent, operator: ColumnFilterOp) => void;
31
42
  /**
32
43
  * Filter value. Pair of values expected when operator is
33
44
  * 'between'. If provided, component is controlled.
34
45
  */
35
46
  value?: ColumnFilterValue;
36
47
  }
37
- export declare const useColumnFilter: ({ InputProps: InputPropsProp, column, defaultValue, extendedFilterOptions, onColumnFilterChange, onColumnRangeFilterChange, onCommit, operator, value: valueProp, }: ColumnFilterHookProps) => {
48
+ export declare const useColumnFilter: ({ InputProps: InputPropsProp, column, defaultValue, defaultOperator, extendedFilterOptions, onColumnFilterChange, onColumnRangeFilterChange, onCommit, onOperatorChange, operator: operatorProp, operators: operatorsProp, showOperatorPicker, value: valueProp, }: ColumnFilterHookProps) => {
38
49
  InputProps: InputProps;
39
50
  InputPropsRange: InputProps;
40
51
  isInvalid: boolean;
41
52
  onCommit: CommitHandler<HTMLElement>;
42
53
  onCommitRange: CommitHandler<HTMLElement>;
54
+ operator: "in" | SelectableColumnFilterOp;
55
+ operators: readonly SelectableColumnFilterOp[] | undefined;
56
+ onOperatorSelect: (event: SyntheticEvent, newOperator: ColumnFilterOp) => void;
43
57
  };
@@ -1,14 +1,24 @@
1
- import type { FilterClauseOp } from "@vuu-ui/vuu-filter-types";
1
+ import type { ColumnFilterOp, FilterClauseOp } from "@vuu-ui/vuu-filter-types";
2
2
  import type { ColumnDescriptor } from "@vuu-ui/vuu-table-types";
3
3
  import { ComboBoxProps } from "@salt-ds/core";
4
4
  import { SyntheticEvent } from "react";
5
- export type OperatorPickerProps = Pick<ComboBoxProps, "className" | "inputProps" | "value"> & {
5
+ type OperatorComboboxProps = Pick<ComboBoxProps, "className" | "inputProps" | "value"> & {
6
6
  column: ColumnDescriptor;
7
7
  onSelect: (evt: SyntheticEvent, operator: FilterClauseOp) => void;
8
8
  dropdownOnAutofocus?: boolean;
9
+ variant?: "combobox";
10
+ operators?: readonly FilterClauseOp[];
9
11
  };
10
- export declare const OperatorPicker: import("react").ForwardRefExoticComponent<Pick<ComboBoxProps<string>, "className" | "inputProps" | "value"> & {
11
- column: ColumnDescriptor;
12
- onSelect: (evt: SyntheticEvent, operator: FilterClauseOp) => void;
13
- dropdownOnAutofocus?: boolean;
14
- } & import("react").RefAttributes<HTMLDivElement>>;
12
+ type OperatorDropdownProps = {
13
+ variant: "dropdown";
14
+ className?: string;
15
+ disabled?: boolean;
16
+ readOnly?: boolean;
17
+ operators: readonly ColumnFilterOp[];
18
+ value: ColumnFilterOp;
19
+ onSelect: (evt: SyntheticEvent, operator: ColumnFilterOp) => void;
20
+ "aria-label"?: string;
21
+ };
22
+ export type OperatorPickerProps = OperatorComboboxProps | OperatorDropdownProps;
23
+ export declare const OperatorPicker: import("react").ForwardRefExoticComponent<OperatorPickerProps & import("react").RefAttributes<HTMLDivElement>>;
24
+ export {};
@@ -5,9 +5,12 @@ export interface SerializableFilter {
5
5
  asQuery: () => string;
6
6
  }
7
7
  /**
8
- * A filter clause on a time of day value (TimeString). The time is resolved
9
- * against a date ('today' by default) only when the query is created, so a
10
- * persisted filter remains relative.
8
+ * A filter clause whose query depends on options beyond the column, op and value:
9
+ * - a time of day value (TimeString). The time is resolved against a date
10
+ * ('today' by default) only when the query is created, so a persisted filter
11
+ * remains relative.
12
+ * - a scaled decimal value, matched at the precision with which the column
13
+ * displays values (see scaledDecimalFilterAsQuery).
11
14
  */
12
15
  export declare class ExtendedSingleValueFilterClause implements SerializableSingleValueFilterClause {
13
16
  #private;
@@ -16,7 +16,7 @@ export interface FilterContainerColumnFilterProps extends Omit<ColumnFilterProps
16
16
  */
17
17
  pattern?: DateTimePattern;
18
18
  }
19
- export declare const FilterContainerColumnFilter: ({ column: columnProp, operator, pattern: patternProp, variant, ...props }: FilterContainerColumnFilterProps) => import("react/jsx-runtime").JSX.Element;
19
+ export declare const FilterContainerColumnFilter: ({ column: columnProp, operator: operatorProp, defaultOperator, showOperatorPicker, operators, onOperatorChange, pattern: patternProp, variant, ...props }: FilterContainerColumnFilterProps) => import("react/jsx-runtime").JSX.Element;
20
20
  /**
21
21
  * FilterContainer is a generic UI container for a collection of Filter
22
22
  * controls. Each control manages a single filter clause and the Filter
@@ -2,6 +2,8 @@ import { ColumnFilterChangeHandler, ColumnFilterCommitHandler, ColumnFilterOp, C
2
2
  import { ColumnDescriptor } from "@vuu-ui/vuu-table-types";
3
3
  export interface ColumnFilterContextProps {
4
4
  filterContainerInstalled: boolean;
5
+ filter?: FilterContainerFilter;
6
+ getFilter?: () => FilterContainerFilter | undefined;
5
7
  filterProviderKey?: string;
6
8
  onChange?: ColumnFilterChangeHandler;
7
9
  onCommit?: ColumnFilterCommitHandler;
@@ -10,7 +12,7 @@ export interface ColumnFilterContextProps {
10
12
  }
11
13
  export declare const ColumnFilterContext: import("react").Context<ColumnFilterContextProps>;
12
14
  export declare function useFilterContext(column: ColumnDescriptor, throwIfNoContainer?: false): ColumnFilterContextProps;
13
- export declare function useFilterContext(column: ColumnDescriptor, throwIfNoContainer: true): Required<ColumnFilterContextProps>;
15
+ export declare function useFilterContext(column: ColumnDescriptor, throwIfNoContainer: true): Required<Omit<ColumnFilterContextProps, "filter">> & Pick<ColumnFilterContextProps, "filter">;
14
16
  export type FilterAppliedHandler<F extends Filter = Filter> = (filter: F) => void;
15
17
  export type ColumnFilterContainerHookProps = {
16
18
  filter?: FilterContainerFilter;
package/types/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { ColumnFilter, type ColumnFilterProps, } from "./column-filter/ColumnFilter";
2
+ export type { SelectableColumnFilterOp } from "./column-filter/column-filter-utils";
2
3
  export * from "./filter-bar";
3
4
  export * from "./filter-clause";
4
5
  export { ExtendedSingleValueFilterClause } from "./filter-container/ExtendedSingleValueFilterClause";
@@ -0,0 +1,28 @@
1
+ import { ColumnFilterValue, ExtendedFilterOptions, FilterClauseOp, FilterContainerFilter } from "@vuu-ui/vuu-filter-types";
2
+ import { ColumnDescriptor } from "@vuu-ui/vuu-table-types";
3
+ /**
4
+ * Manages a filter that can be updated one clause at a time.
5
+ * Works with FilterContainer to aggregate multiple filter
6
+ * clauses edited via individual controls. It is just a wrapper
7
+ * around a Map, does not support switching filters - create a
8
+ * new FilterAggregator for a new filter.
9
+ *
10
+ */
11
+ export declare class FilterAggregator {
12
+ #private;
13
+ constructor(filter?: FilterContainerFilter);
14
+ add(column: ColumnDescriptor, value: ColumnFilterValue, op?: FilterClauseOp | "between" | "between-inclusive", extendedFilterOptions?: ExtendedFilterOptions): void;
15
+ has({ name }: ColumnDescriptor): boolean;
16
+ get({ name }: ColumnDescriptor): FilterContainerFilter | undefined;
17
+ clear(): void;
18
+ /**
19
+ * Remove filter for this column. Return false if no filter found, otw true
20
+ */
21
+ remove(column: ColumnDescriptor): boolean;
22
+ get isEmpty(): boolean;
23
+ /**
24
+ * Count of the number of columns for which filters are stored
25
+ */
26
+ get count(): number;
27
+ get filter(): FilterContainerFilter | undefined;
28
+ }
@@ -0,0 +1,44 @@
1
+ import { Filter, FilterClause, FilterClauseOp, FilterCombinatorOp } from "@vuu-ui/vuu-filter-types";
2
+ import { EventEmitter } from "@vuu-ui/vuu-utils";
3
+ export type FilterStatusChangeHandler = (isValid: boolean) => void;
4
+ export type FilterChangeHandler = (filter: Partial<Filter>, isValid: boolean) => void;
5
+ export type FilterClauseChangeHandler = (filter: Partial<FilterClause>, isValid: boolean) => void;
6
+ export type FilterClauseModelEvents = {
7
+ filterClause: FilterClauseChangeHandler;
8
+ isValid: FilterStatusChangeHandler;
9
+ };
10
+ export type FilterModelEvents = {
11
+ filter: FilterChangeHandler;
12
+ isValid: FilterStatusChangeHandler;
13
+ };
14
+ export declare class FilterClauseModel extends EventEmitter<FilterClauseModelEvents> {
15
+ #private;
16
+ constructor(filterClause: Partial<FilterClause>);
17
+ get isValid(): boolean;
18
+ private setIsValid;
19
+ get column(): undefined | string;
20
+ set column(column: undefined | string);
21
+ get op(): "in" | import("@vuu-ui/vuu-filter-types").SingleValueFilterClauseOp | undefined;
22
+ setOp(op: undefined | FilterClauseOp): void;
23
+ setValue(value: undefined | string | string[] | number | number[] | boolean | boolean[], isFinal?: boolean): void;
24
+ asFilter(throwIfInvalid?: boolean): FilterClause;
25
+ commit(): void;
26
+ }
27
+ export declare class FilterModel extends EventEmitter<FilterModelEvents> {
28
+ #private;
29
+ constructor(filter?: Filter);
30
+ get isValid(): boolean;
31
+ private setIsValid;
32
+ addNewFilterClause(operator?: FilterCombinatorOp): void;
33
+ addFilterClause(filterClause?: Partial<FilterClause>): void;
34
+ removeFilterClause(filterClause: FilterClauseModel): void;
35
+ checkValidStatus(): void;
36
+ onFilterClauseChange: FilterChangeHandler;
37
+ onFilterClauseStatusChange: (isValid: boolean) => void;
38
+ getFilterClause(index: number): FilterClauseModel;
39
+ get op(): FilterCombinatorOp | undefined;
40
+ setOp(op: FilterCombinatorOp): void;
41
+ get filterClauses(): FilterClauseModel[];
42
+ get isMultiClauseFilter(): boolean;
43
+ asFilter(throwIfInvalid?: boolean): Filter;
44
+ }
@@ -0,0 +1,6 @@
1
+ import { type SegmentedButtonGroupProps } from "@salt-ds/core";
2
+ import { DataItemEditControlProps } from "@vuu-ui/vuu-data-react";
3
+ import { ColumnFilterHookProps } from "./useColumnFilter";
4
+ export interface ColumnFilterProps extends ColumnFilterHookProps, Omit<SegmentedButtonGroupProps, "defaultValue">, Pick<DataItemEditControlProps, "TypeaheadProps" | "table" | "values" | "variant"> {
5
+ }
6
+ export declare const ColumnFilter: import("react").ForwardRefExoticComponent<ColumnFilterProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,43 @@
1
+ import { ColumnFilterChangeHandler, ColumnFilterCommitHandler, ColumnFilterOp, ColumnFilterValue, ExtendedFilterOptions } from "@vuu-ui/vuu-filter-types";
2
+ import { ColumnDescriptor } from "@vuu-ui/vuu-table-types";
3
+ import { InputProps } from "@salt-ds/core";
4
+ import { CommitHandler } from "@vuu-ui/vuu-utils";
5
+ import { DataItemEditControlProps } from "@vuu-ui/vuu-data-react";
6
+ export interface ColumnFilterHookProps extends Pick<DataItemEditControlProps, "InputProps"> {
7
+ column: ColumnDescriptor;
8
+ /**
9
+ * Filter defaultValue. Pair of values expected when operator is
10
+ * 'between'. If provided, component is uncontrolled
11
+ */
12
+ defaultValue?: ColumnFilterValue;
13
+ /**
14
+ * Provides for custom filters.
15
+ */
16
+ extendedFilterOptions?: ExtendedFilterOptions;
17
+ /**
18
+ * Filter change events.
19
+ */
20
+ onColumnFilterChange?: ColumnFilterChangeHandler;
21
+ /**
22
+ * Filter change events on second control in range filter
23
+ */
24
+ onColumnRangeFilterChange?: ColumnFilterChangeHandler;
25
+ /**
26
+ * Called when user 'commits' filter value, either by pressing enter,
27
+ * tabbing away from control or making selection from list
28
+ */
29
+ onCommit: ColumnFilterCommitHandler;
30
+ operator?: ColumnFilterOp;
31
+ /**
32
+ * Filter value. Pair of values expected when operator is
33
+ * 'between'. If provided, component is controlled.
34
+ */
35
+ value?: ColumnFilterValue;
36
+ }
37
+ export declare const useColumnFilter: ({ InputProps: InputPropsProp, column, defaultValue, extendedFilterOptions, onColumnFilterChange, onColumnRangeFilterChange, onCommit, operator, value: valueProp, }: ColumnFilterHookProps) => {
38
+ InputProps: InputProps;
39
+ InputPropsRange: InputProps;
40
+ isInvalid: boolean;
41
+ onCommit: CommitHandler<HTMLElement>;
42
+ onCommitRange: CommitHandler<HTMLElement>;
43
+ };
@@ -0,0 +1,4 @@
1
+ import { Filter } from "@vuu-ui/vuu-filter-types";
2
+ export declare const isStartsWithValue: (value: string) => boolean;
3
+ export declare const getTypeaheadFilter: (column: string, filterValues: string[], isStartsWithFilter?: boolean) => Filter | undefined;
4
+ export declare const getRangeFilter: (column: string, startValue?: number, endValue?: number) => Filter | undefined;
@@ -0,0 +1,7 @@
1
+ import type { ColumnDescriptor } from "@vuu-ui/vuu-table-types";
2
+ import { HTMLAttributes } from "react";
3
+ import { type FilterBarProps } from "../filter-bar";
4
+ export interface CustomFilterProps extends HTMLAttributes<HTMLDivElement>, Pick<FilterBarProps, "defaultFilterState" | "filterState" | "onApplyFilter" | "onClearFilter" | "onFilterDeleted" | "onFilterRenamed" | "onFilterStateChanged" | "vuuTable"> {
5
+ columnDescriptors: readonly ColumnDescriptor[];
6
+ }
7
+ export declare const CustomFilters: ({ columnDescriptors, defaultFilterState, filterState, onApplyFilter, onClearFilter, onFilterDeleted, onFilterRenamed, onFilterStateChanged, vuuTable, }: CustomFilterProps) => import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export declare const navigateToNextItem: (el: HTMLElement | EventTarget, direction?: "bwd" | "fwd") => void;
@@ -0,0 +1 @@
1
+ export * from "./CustomFilters";
@@ -0,0 +1,33 @@
1
+ import { ColumnDescriptorsByName, Filter } from "@vuu-ui/vuu-filter-types";
2
+ import { PromptProps } from "@vuu-ui/vuu-ui-controls";
3
+ import { KeyboardEventHandler, RefObject } from "react";
4
+ import { FilterBarProps } from "../filter-bar";
5
+ import { FilterEditCancelHandler, FilterEditSaveHandler } from "../filter-editor";
6
+ import { FilterPillProps } from "../filter-pill";
7
+ export type EditFilterState = "create" | "edit";
8
+ export type FilterState = EditFilterState | "rename";
9
+ export declare const isEditFilterState: (filterState?: string) => filterState is EditFilterState;
10
+ type InteractedFilterState = {
11
+ filter?: Filter;
12
+ index: number;
13
+ state: FilterState;
14
+ };
15
+ export interface CustomFilterHookProps extends Pick<FilterBarProps, "columnDescriptors" | "defaultFilterState" | "filterState" | "onApplyFilter" | "onClearFilter" | "onFilterDeleted" | "onFilterRenamed" | "onFilterStateChanged"> {
16
+ containerRef: RefObject<HTMLDivElement | null>;
17
+ }
18
+ export declare const useCustomFilters: ({ columnDescriptors, containerRef, defaultFilterState, filterState, onApplyFilter, onClearFilter, onFilterDeleted, onFilterRenamed, onFilterStateChanged, }: CustomFilterHookProps) => {
19
+ FilterPillProps: Omit<FilterPillProps, "filter" | "selected">;
20
+ activeFilterIndex: number[];
21
+ addButtonProps: {
22
+ ref: RefObject<HTMLButtonElement | null>;
23
+ onClick: () => void;
24
+ onKeyDown: KeyboardEventHandler;
25
+ };
26
+ columnsByName: ColumnDescriptorsByName;
27
+ filters: Filter[];
28
+ interactedFilterState: InteractedFilterState | undefined;
29
+ onCancelEdit: FilterEditCancelHandler;
30
+ onSave: FilterEditSaveHandler;
31
+ promptProps: PromptProps | null;
32
+ };
33
+ export {};
@@ -0,0 +1,17 @@
1
+ import { Filter, FilterState } from "@vuu-ui/vuu-filter-types";
2
+ export interface FiltersHookProps {
3
+ defaultFilterState?: FilterState;
4
+ filterState?: FilterState;
5
+ onFilterDeleted?: (filter: Filter) => void;
6
+ onFilterRenamed?: (filter: Filter, name: string) => void;
7
+ onFilterStateChanged?: (s: FilterState) => void;
8
+ }
9
+ export declare const useFilterState: ({ defaultFilterState, onFilterDeleted, onFilterRenamed, onFilterStateChanged, filterState: filterStateProp, }: FiltersHookProps) => {
10
+ activeFilterIndex: number[];
11
+ filters: Filter[];
12
+ onToggleFilterActive: (filterIndex: number, preserveRemainingFilters?: boolean) => void;
13
+ onAddFilter: (filter: Filter) => number;
14
+ onChangeFilter: (oldFilter: Filter, newFilter: Filter) => number;
15
+ onDeleteFilter: (filter: Filter) => number;
16
+ onRenameFilter: (filter: Filter, name: string) => number;
17
+ };
@@ -0,0 +1,33 @@
1
+ import { Filter, FilterHandler, FilterState } from "@vuu-ui/vuu-filter-types";
2
+ import { ColumnDescriptor } from "@vuu-ui/vuu-table-types";
3
+ import { HTMLAttributes } from "react";
4
+ import { QuickFilterProps } from "../quick-filters";
5
+ import { FilterMode } from "./useFilterBar";
6
+ import type { VuuTable } from "@vuu-ui/vuu-protocol-types";
7
+ export type FilterBarVariant = "custom-filters-only" | "quick-filters-only" | "full-filters";
8
+ export interface FilterBarProps extends HTMLAttributes<HTMLDivElement> {
9
+ QuickFilterProps?: Pick<QuickFilterProps, "quickFilterColumns" | "onChangeQuickFilterColumns">;
10
+ /**
11
+ * Used to ensure we present filter editors appropriate to the data type of column.
12
+ * NOTE: Always make sure that these are passed with proper re-render optimization (i.e make
13
+ * sure its a stable reference, in React terminology), otherwise might end up with infinite
14
+ * state updates.
15
+ */
16
+ columnDescriptors: readonly ColumnDescriptor[];
17
+ defaultFilterMode?: FilterMode;
18
+ defaultFilterState?: FilterState;
19
+ filterMode?: FilterMode;
20
+ filterState?: FilterState;
21
+ onApplyFilter: FilterHandler;
22
+ onChangeFilterMode?: (filterMode: FilterMode) => void;
23
+ onClearFilter: () => void;
24
+ onFilterDeleted?: FilterHandler;
25
+ onFilterRenamed?: (filter: Filter, name: string) => void;
26
+ onFilterStateChanged?: (state: FilterState) => void;
27
+ /**
28
+ * Defines table used in call to Vuu Typeahead service
29
+ */
30
+ vuuTable?: VuuTable;
31
+ variant?: FilterBarVariant;
32
+ }
33
+ export declare const FilterBar: ({ QuickFilterProps, className: classNameProp, columnDescriptors, defaultFilterMode, defaultFilterState, filterMode: filterModeProp, filterState, onApplyFilter, onChangeFilterMode: onChangeFilterModeProp, onClearFilter, onFilterDeleted, onFilterRenamed, onFilterStateChanged, vuuTable, variant, ...htmlAttributes }: FilterBarProps) => import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ export declare const FilterBarMenu: () => import("react").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export * from "./FilterBar";
2
+ export type { FilterMode } from "./useFilterBar";
@@ -0,0 +1,7 @@
1
+ import { SyntheticEvent } from "react";
2
+ import { FilterBarProps } from "./FilterBar";
3
+ export type FilterMode = "custom-filter" | "quick-filter";
4
+ export declare const useFilterBar: ({ defaultFilterMode, filterMode: filterModeProp, onChangeFilterMode, }: Pick<FilterBarProps, "defaultFilterMode" | "filterMode" | "onChangeFilterMode">) => {
5
+ filterMode: FilterMode;
6
+ onChangeFilterMode: (e: SyntheticEvent<HTMLButtonElement>) => void;
7
+ };
@@ -0,0 +1,10 @@
1
+ import { ComboBoxProps } from "@salt-ds/core";
2
+ import { ReactElement, Ref } from "react";
3
+ export interface ExpandoComboboxProps<Item = string> extends Omit<ComboBoxProps<Item>, "onOpenChange"> {
4
+ itemToString?: (item: Item) => string;
5
+ dropdownOnAutofocus?: boolean;
6
+ onOpenChange?: (open: boolean, reason?: "manual" | "input" | "focus") => void;
7
+ }
8
+ export declare const ExpandoCombobox: <Item = string>(props: ExpandoComboboxProps<Item> & {
9
+ ref?: Ref<HTMLDivElement>;
10
+ }) => ReactElement;
@@ -0,0 +1,16 @@
1
+ import { ColumnDescriptorsByName } from "@vuu-ui/vuu-filter-types";
2
+ import { HTMLAttributes } from "react";
3
+ import { FilterClauseModel } from "../FilterModel";
4
+ import { VuuTable } from "@vuu-ui/vuu-protocol-types";
5
+ export type FilterClauseCancelType = "Backspace" | "Escape";
6
+ export type FilterClauseCancelHandler = (filterClause: FilterClauseModel, reason: FilterClauseCancelType) => void;
7
+ export interface FilterClauseProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange"> {
8
+ columnsByName: ColumnDescriptorsByName;
9
+ filterClauseModel: FilterClauseModel;
10
+ onCancel?: FilterClauseCancelHandler;
11
+ onDropdownOpen?: () => void;
12
+ onFocusSave?: () => void;
13
+ dropdownOnAutofocus?: boolean;
14
+ vuuTable: VuuTable;
15
+ }
16
+ export declare const FilterClause: ({ className, columnsByName, onCancel, onDropdownOpen, onFocusSave, filterClauseModel, vuuTable, dropdownOnAutofocus, ...htmlAttributes }: FilterClauseProps) => import("react").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import type { ColumnDescriptor } from "@vuu-ui/vuu-table-types";
2
+ import { ComboBoxProps } from "@salt-ds/core";
3
+ import { SyntheticEvent } from "react";
4
+ export type ColumnPickerProps = Pick<ComboBoxProps, "className" | "inputProps" | "value"> & {
5
+ columns: readonly ColumnDescriptor[];
6
+ onSelect: (evt: SyntheticEvent, columnName: string) => void;
7
+ dropdownOnAutofocus?: boolean;
8
+ };
9
+ export declare const ColumnPicker: import("react").ForwardRefExoticComponent<Pick<ComboBoxProps<string>, "className" | "inputProps" | "value"> & {
10
+ columns: readonly ColumnDescriptor[];
11
+ onSelect: (evt: SyntheticEvent, columnName: string) => void;
12
+ dropdownOnAutofocus?: boolean;
13
+ } & import("react").RefAttributes<HTMLDivElement>>;