@gooddata/sdk-ui-filters 11.54.0-alpha.0 → 11.54.0-alpha.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/esm/DateFilter/DateFilter.d.ts +2 -23
- package/esm/DateFilter/DateFilter.d.ts.map +1 -1
- package/esm/DateFilter/DateFilter.js +180 -145
- package/esm/sdk-ui-filters.d.ts +1 -23
- package/package.json +12 -12
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ComponentType,
|
|
1
|
+
import { type ComponentType, type ReactNode } from "react";
|
|
2
2
|
import { type DateFilterGranularity, type IActiveCalendars, type WeekStart } from "@gooddata/sdk-model";
|
|
3
3
|
import { type OverlayPositionType } from "@gooddata/sdk-ui-kit";
|
|
4
4
|
import { type IFilterButtonCustomIcon, type VisibilityMode } from "../shared/interfaces/index.js";
|
|
@@ -169,26 +169,5 @@ export interface IDateFilterState extends IDateFilterStatePropsIntersection {
|
|
|
169
169
|
*
|
|
170
170
|
* @public
|
|
171
171
|
*/
|
|
172
|
-
export declare
|
|
173
|
-
static defaultProps: Partial<IDateFilterProps>;
|
|
174
|
-
static getDerivedStateFromProps(nextProps: IDateFilterProps, prevState: IDateFilterState): IDateFilterState | null;
|
|
175
|
-
private static getStateFromProps;
|
|
176
|
-
private static getStateFromWorkingProps;
|
|
177
|
-
private static getStateFromSelectedOption;
|
|
178
|
-
private static checkInitialFilterOption;
|
|
179
|
-
constructor(props: IDateFilterProps);
|
|
180
|
-
componentDidMount(): void;
|
|
181
|
-
render(): import("react/jsx-runtime").JSX.Element | null;
|
|
182
|
-
private handleApplyClick;
|
|
183
|
-
private onChangesDiscarded;
|
|
184
|
-
private onCancelClicked;
|
|
185
|
-
private onDropdownOpenChanged;
|
|
186
|
-
private handleExcludeCurrentPeriodChange;
|
|
187
|
-
private handleSelectedFilterOptionChange;
|
|
188
|
-
private handleSelectChange;
|
|
189
|
-
private fireOnSelect;
|
|
190
|
-
private normalizeEmptyValueHandling;
|
|
191
|
-
private mergeEmptyValueHandling;
|
|
192
|
-
private isSameOptionExceptEmptyValueHandling;
|
|
193
|
-
}
|
|
172
|
+
export declare const DateFilter: import("react").NamedExoticComponent<IDateFilterProps>;
|
|
194
173
|
//# sourceMappingURL=DateFilter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateFilter.d.ts","sourceRoot":"","sources":["../../src/DateFilter/DateFilter.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"DateFilter.d.ts","sourceRoot":"","sources":["../../src/DateFilter/DateFilter.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
// (C) 2007-2026 GoodData Corporation
|
|
3
|
-
import {
|
|
3
|
+
import { memo, useCallback, useEffect, useRef, useState } from "react";
|
|
4
4
|
import { isEmpty, isEqual } from "lodash-es";
|
|
5
5
|
import { isAbsoluteDateFilterForm, isAllTimeDateFilterOption, isEmptyValuesDateFilterOption, } from "@gooddata/sdk-model";
|
|
6
6
|
import { DEFAULT_DATE_FORMAT } from "./constants/Platform.js";
|
|
@@ -9,149 +9,125 @@ import { isUiRelativeDateFilterForm, } from "./interfaces/index.js";
|
|
|
9
9
|
import { normalizeSelectedFilterOption } from "./utils/FilterOptionNormalization.js";
|
|
10
10
|
import { canExcludeCurrentPeriod } from "./utils/PeriodExclusion.js";
|
|
11
11
|
import { validateFilterOption } from "./validation/OptionValidation.js";
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
isSecondsForAbsoluteRangeEnabled: false,
|
|
23
|
-
locale: "en-US",
|
|
24
|
-
onCancel: () => { },
|
|
25
|
-
onOpen: () => { },
|
|
26
|
-
onClose: () => { },
|
|
27
|
-
weekStart: "Sunday",
|
|
28
|
-
withoutApply: false,
|
|
29
|
-
hideDisabledExclude: false,
|
|
12
|
+
function getStateFromProps(props) {
|
|
13
|
+
const canExcludeCurrent = canExcludeCurrentPeriod(props.selectedFilterOption);
|
|
14
|
+
return {
|
|
15
|
+
initSelectedFilterOption: props.selectedFilterOption,
|
|
16
|
+
selectedFilterOption: props.selectedFilterOption,
|
|
17
|
+
initExcludeCurrentPeriod: props.excludeCurrentPeriod,
|
|
18
|
+
excludeCurrentPeriod: canExcludeCurrent ? props.excludeCurrentPeriod : false,
|
|
19
|
+
isExcludeCurrentPeriodEnabled: canExcludeCurrent,
|
|
20
|
+
initWorkingSelectedFilterOption: props.workingSelectedFilterOption ?? props.selectedFilterOption,
|
|
21
|
+
initWorkingExcludeCurrentPeriod: props.workingExcludeCurrentPeriod ?? props.excludeCurrentPeriod,
|
|
30
22
|
};
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
static getStateFromProps(props) {
|
|
46
|
-
const canExcludeCurrent = canExcludeCurrentPeriod(props.selectedFilterOption);
|
|
47
|
-
return {
|
|
48
|
-
initSelectedFilterOption: props.selectedFilterOption,
|
|
49
|
-
selectedFilterOption: props.selectedFilterOption,
|
|
50
|
-
initExcludeCurrentPeriod: props.excludeCurrentPeriod,
|
|
51
|
-
excludeCurrentPeriod: canExcludeCurrent ? props.excludeCurrentPeriod : false,
|
|
52
|
-
isExcludeCurrentPeriodEnabled: canExcludeCurrent,
|
|
53
|
-
initWorkingSelectedFilterOption: props.workingSelectedFilterOption ?? props.selectedFilterOption,
|
|
54
|
-
initWorkingExcludeCurrentPeriod: props.workingExcludeCurrentPeriod ?? props.excludeCurrentPeriod,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
static getStateFromWorkingProps(props) {
|
|
58
|
-
const selectedFilterOption = props.workingSelectedFilterOption ?? props.selectedFilterOption;
|
|
59
|
-
const canExcludeCurrent = canExcludeCurrentPeriod(selectedFilterOption);
|
|
60
|
-
return {
|
|
61
|
-
...DateFilter.getStateFromProps(props),
|
|
62
|
-
selectedFilterOption: selectedFilterOption,
|
|
63
|
-
excludeCurrentPeriod: canExcludeCurrent
|
|
64
|
-
? (props.workingExcludeCurrentPeriod ?? props.excludeCurrentPeriod)
|
|
65
|
-
: false,
|
|
66
|
-
initWorkingExcludeCurrentPeriod: props.workingExcludeCurrentPeriod ?? props.excludeCurrentPeriod,
|
|
67
|
-
initWorkingSelectedFilterOption: selectedFilterOption,
|
|
68
|
-
initExcludeCurrentPeriod: props.excludeCurrentPeriod,
|
|
69
|
-
isExcludeCurrentPeriodEnabled: canExcludeCurrent,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
static getStateFromSelectedOption = (selectedFilterOption, excludeCurrentPeriod) => {
|
|
73
|
-
const canExcludeCurrent = canExcludeCurrentPeriod(selectedFilterOption);
|
|
74
|
-
return {
|
|
75
|
-
selectedFilterOption,
|
|
76
|
-
excludeCurrentPeriod: canExcludeCurrent ? excludeCurrentPeriod : false,
|
|
77
|
-
isExcludeCurrentPeriodEnabled: canExcludeCurrent,
|
|
78
|
-
};
|
|
23
|
+
}
|
|
24
|
+
function getStateFromWorkingProps(props) {
|
|
25
|
+
const selectedFilterOption = props.workingSelectedFilterOption ?? props.selectedFilterOption;
|
|
26
|
+
const canExcludeCurrent = canExcludeCurrentPeriod(selectedFilterOption);
|
|
27
|
+
return {
|
|
28
|
+
...getStateFromProps(props),
|
|
29
|
+
selectedFilterOption: selectedFilterOption,
|
|
30
|
+
excludeCurrentPeriod: canExcludeCurrent
|
|
31
|
+
? (props.workingExcludeCurrentPeriod ?? props.excludeCurrentPeriod)
|
|
32
|
+
: false,
|
|
33
|
+
initWorkingExcludeCurrentPeriod: props.workingExcludeCurrentPeriod ?? props.excludeCurrentPeriod,
|
|
34
|
+
initWorkingSelectedFilterOption: selectedFilterOption,
|
|
35
|
+
initExcludeCurrentPeriod: props.excludeCurrentPeriod,
|
|
36
|
+
isExcludeCurrentPeriodEnabled: canExcludeCurrent,
|
|
79
37
|
};
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
if (isUiRelativeDateFilterForm(filterOption) &&
|
|
89
|
-
(filterOption.from === null ||
|
|
90
|
-
filterOption.from === undefined ||
|
|
91
|
-
filterOption.to === null ||
|
|
92
|
-
filterOption.to === undefined)) {
|
|
93
|
-
console.warn("The default filter option is not valid. Values 'from' and 'to' from relativeForm filter option must be specified.");
|
|
94
|
-
}
|
|
38
|
+
}
|
|
39
|
+
function getStateFromSelectedOption(selectedFilterOption, excludeCurrentPeriod) {
|
|
40
|
+
const canExcludeCurrent = canExcludeCurrentPeriod(selectedFilterOption);
|
|
41
|
+
return {
|
|
42
|
+
selectedFilterOption,
|
|
43
|
+
excludeCurrentPeriod: canExcludeCurrent ? excludeCurrentPeriod : false,
|
|
44
|
+
isExcludeCurrentPeriodEnabled: canExcludeCurrent,
|
|
95
45
|
};
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Equivalent of the former `getDerivedStateFromProps`: re-syncs the state whenever the incoming
|
|
49
|
+
* props no longer match the `init*` sentinels stored in the state. Returns `null` when the state
|
|
50
|
+
* is already in sync.
|
|
51
|
+
*/
|
|
52
|
+
function getDerivedStateFromProps(nextProps, prevState) {
|
|
53
|
+
if (nextProps.withoutApply &&
|
|
54
|
+
nextProps.workingSelectedFilterOption &&
|
|
55
|
+
nextProps.excludeCurrentPeriod !== undefined &&
|
|
56
|
+
(!isEqual(nextProps.workingSelectedFilterOption, prevState.initWorkingSelectedFilterOption) ||
|
|
57
|
+
nextProps.workingExcludeCurrentPeriod !== prevState.initWorkingExcludeCurrentPeriod)) {
|
|
58
|
+
return getStateFromWorkingProps(nextProps);
|
|
99
59
|
}
|
|
100
|
-
|
|
101
|
-
|
|
60
|
+
if (!isEqual(nextProps.selectedFilterOption, prevState.initSelectedFilterOption) ||
|
|
61
|
+
nextProps.excludeCurrentPeriod !== prevState.initExcludeCurrentPeriod) {
|
|
62
|
+
return getStateFromProps(nextProps);
|
|
102
63
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
function checkInitialFilterOption(filterOption) {
|
|
67
|
+
if (isAbsoluteDateFilterForm(filterOption) &&
|
|
68
|
+
(filterOption.from === null ||
|
|
69
|
+
filterOption.from === undefined ||
|
|
70
|
+
filterOption.to === null ||
|
|
71
|
+
filterOption.to === undefined)) {
|
|
72
|
+
console.warn("The default filter option is not valid. Values 'from' and 'to' from absoluteForm filter option must be specified.");
|
|
107
73
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
this.setState(() => DateFilter.getStateFromProps(this.props), this.handleSelectChange);
|
|
115
|
-
}
|
|
116
|
-
else if (this.props.withoutApply &&
|
|
117
|
-
!isEmpty(validateFilterOption(this.state.selectedFilterOption))) {
|
|
118
|
-
this.setState(() => DateFilter.getStateFromWorkingProps(this.props));
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
onCancelClicked = () => {
|
|
122
|
-
this.props.onCancel?.();
|
|
123
|
-
this.onChangesDiscarded();
|
|
124
|
-
};
|
|
125
|
-
onDropdownOpenChanged = (isOpen) => {
|
|
126
|
-
if (isOpen) {
|
|
127
|
-
this.props.onOpen?.();
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
this.props.onClose?.();
|
|
131
|
-
this.onChangesDiscarded();
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
handleExcludeCurrentPeriodChange = (excludeCurrentPeriod) => {
|
|
135
|
-
this.setState({ excludeCurrentPeriod }, this.handleSelectChange);
|
|
136
|
-
};
|
|
137
|
-
handleSelectedFilterOptionChange = (selectedFilterOption) => {
|
|
138
|
-
let nextSelectedFilterOption;
|
|
139
|
-
this.setState((state) => {
|
|
140
|
-
nextSelectedFilterOption = this.normalizeEmptyValueHandling(this.mergeEmptyValueHandling(selectedFilterOption, state.selectedFilterOption));
|
|
141
|
-
return DateFilter.getStateFromSelectedOption(nextSelectedFilterOption, state.excludeCurrentPeriod);
|
|
142
|
-
}, () => this.fireOnSelect(nextSelectedFilterOption));
|
|
143
|
-
};
|
|
144
|
-
handleSelectChange = () => {
|
|
145
|
-
this.fireOnSelect();
|
|
146
|
-
};
|
|
147
|
-
fireOnSelect(selectedFilterOption = this.state.selectedFilterOption, excludeCurrentPeriod = this.state.excludeCurrentPeriod) {
|
|
148
|
-
const normalizedSelectedFilterOption = this.normalizeEmptyValueHandling(normalizeSelectedFilterOption(selectedFilterOption));
|
|
149
|
-
if (isEmpty(validateFilterOption(normalizedSelectedFilterOption))) {
|
|
150
|
-
this.props.onSelect?.(normalizedSelectedFilterOption, excludeCurrentPeriod);
|
|
151
|
-
}
|
|
74
|
+
if (isUiRelativeDateFilterForm(filterOption) &&
|
|
75
|
+
(filterOption.from === null ||
|
|
76
|
+
filterOption.from === undefined ||
|
|
77
|
+
filterOption.to === null ||
|
|
78
|
+
filterOption.to === undefined)) {
|
|
79
|
+
console.warn("The default filter option is not valid. Values 'from' and 'to' from relativeForm filter option must be specified.");
|
|
152
80
|
}
|
|
153
|
-
|
|
154
|
-
|
|
81
|
+
}
|
|
82
|
+
function isSameOptionExceptEmptyValueHandling(a, b) {
|
|
83
|
+
const { emptyValueHandling: _aEmptyValueHandling, ...aWithoutEmptyValueHandling } = a;
|
|
84
|
+
const { emptyValueHandling: _bEmptyValueHandling, ...bWithoutEmptyValueHandling } = b;
|
|
85
|
+
return isEqual(aWithoutEmptyValueHandling, bWithoutEmptyValueHandling);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* {@link https://www.gooddata.com/docs/gooddata-ui/latest/references/filters/date_filter | DateFilter} is a component for configuring a date filter value.
|
|
89
|
+
*
|
|
90
|
+
* @public
|
|
91
|
+
*/
|
|
92
|
+
export const DateFilter = memo(function DateFilter(props) {
|
|
93
|
+
const { customFilterName, dateFilterMode, dateFormat = DEFAULT_DATE_FORMAT, filterOptions, selectedFilterOption: originalSelectedFilterOption, excludeCurrentPeriod: originalExcludeCurrentPeriod, availableGranularities, isEditMode = false, openOnInit, locale = "en-US", isTimeForAbsoluteRangeEnabled = false, isSecondsForAbsoluteRangeEnabled = false, weekStart = "Sunday", customIcon, showDropDownHeaderMessage, FilterConfigurationComponent, withoutApply = false, ButtonComponent, overlayPositionType, activeCalendars, enableEmptyDateValues, customRangeHint, hideDisabledExclude = false, onApply, onSelect, onCancel = () => { }, onOpen = () => { }, onClose = () => { }, } = props;
|
|
94
|
+
const [storedState, setStoredState] = useState(() => getStateFromProps(props));
|
|
95
|
+
// The class component read `this.state` at call time, so a handler invoked later than the
|
|
96
|
+
// render that produced it still saw the current state. Handlers of a function component
|
|
97
|
+
// capture their render instead, and the range picker defers the Enter submit by a tick (see
|
|
98
|
+
// `updateRangeState` in DateRangePicker) - the deferred `submitForm` therefore calls the
|
|
99
|
+
// `onApplyClick` of the render that scheduled it, i.e. from before the typed date was stored.
|
|
100
|
+
// Mirroring the state in a ref and updating it together with the state restores the original
|
|
101
|
+
// semantics for such deferred calls.
|
|
102
|
+
const stateRef = useRef(storedState);
|
|
103
|
+
const setState = useCallback((updater) => {
|
|
104
|
+
stateRef.current = updater(stateRef.current);
|
|
105
|
+
setStoredState(stateRef.current);
|
|
106
|
+
}, []);
|
|
107
|
+
// The class fired `onSelect` from a `setState` callback, i.e. only after the new state was
|
|
108
|
+
// committed and re-synced from the (possibly already updated) props. Firing it straight from
|
|
109
|
+
// the handler would emit the pre-commit option - most visibly on Apply, where the body runs
|
|
110
|
+
// `onApplyClick(); closeDropdown();` in a single batch, so the discard triggered by closing
|
|
111
|
+
// would report the option that Apply has just replaced. Handlers therefore only mark a
|
|
112
|
+
// pending emission here and the effect below fires it once the state has settled.
|
|
113
|
+
// `selectedFilterOption` is set when the handler already knows the option to report.
|
|
114
|
+
const pendingSelectRef = useRef(null);
|
|
115
|
+
// Replacement of the former `getDerivedStateFromProps`: the state is adjusted during render
|
|
116
|
+
// (see https://react.dev/reference/react/useState#storing-information-from-previous-renders)
|
|
117
|
+
// so that the re-synced option is rendered right away instead of flashing the stale one.
|
|
118
|
+
// The `isEqual` guard makes the extra render pass a no-op once the state is in sync.
|
|
119
|
+
let state = storedState;
|
|
120
|
+
const derivedState = getDerivedStateFromProps(props, storedState);
|
|
121
|
+
if (derivedState !== null && !isEqual(derivedState, storedState)) {
|
|
122
|
+
setState(() => derivedState);
|
|
123
|
+
state = derivedState;
|
|
124
|
+
}
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
checkInitialFilterOption(originalSelectedFilterOption);
|
|
127
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
128
|
+
}, []);
|
|
129
|
+
const normalizeEmptyValueHandling = (selectedFilterOption) => {
|
|
130
|
+
if (!enableEmptyDateValues) {
|
|
155
131
|
return selectedFilterOption;
|
|
156
132
|
}
|
|
157
133
|
if (isEmptyValuesDateFilterOption(selectedFilterOption)) {
|
|
@@ -168,8 +144,8 @@ export class DateFilter extends PureComponent {
|
|
|
168
144
|
}
|
|
169
145
|
return selectedFilterOption;
|
|
170
146
|
};
|
|
171
|
-
mergeEmptyValueHandling = (nextSelectedFilterOption, currentSelectedFilterOption) => {
|
|
172
|
-
if (!
|
|
147
|
+
const mergeEmptyValueHandling = (nextSelectedFilterOption, currentSelectedFilterOption) => {
|
|
148
|
+
if (!enableEmptyDateValues) {
|
|
173
149
|
return nextSelectedFilterOption;
|
|
174
150
|
}
|
|
175
151
|
if (isEmptyValuesDateFilterOption(nextSelectedFilterOption)) {
|
|
@@ -189,7 +165,7 @@ export class DateFilter extends PureComponent {
|
|
|
189
165
|
currentHandling !== "only") {
|
|
190
166
|
// If the only difference is `emptyValueHandling` (e.g. user unchecks the checkbox),
|
|
191
167
|
// do not carry the previous value back in.
|
|
192
|
-
if (
|
|
168
|
+
if (isSameOptionExceptEmptyValueHandling(nextSelectedFilterOption, currentSelectedFilterOption)) {
|
|
193
169
|
return nextSelectedFilterOption;
|
|
194
170
|
}
|
|
195
171
|
return {
|
|
@@ -199,9 +175,68 @@ export class DateFilter extends PureComponent {
|
|
|
199
175
|
}
|
|
200
176
|
return nextSelectedFilterOption;
|
|
201
177
|
};
|
|
202
|
-
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
178
|
+
const fireOnSelect = (selectedFilterOption, excludeCurrentPeriod) => {
|
|
179
|
+
const normalizedSelectedFilterOption = normalizeEmptyValueHandling(normalizeSelectedFilterOption(selectedFilterOption));
|
|
180
|
+
if (isEmpty(validateFilterOption(normalizedSelectedFilterOption))) {
|
|
181
|
+
onSelect?.(normalizedSelectedFilterOption, excludeCurrentPeriod);
|
|
182
|
+
}
|
|
206
183
|
};
|
|
207
|
-
|
|
184
|
+
// Runs after every commit, i.e. after the derived-state block above has re-synced `state` with
|
|
185
|
+
// the incoming props - the equivalent of the former `setState(updater, callback)` timing.
|
|
186
|
+
useEffect(() => {
|
|
187
|
+
const pendingSelect = pendingSelectRef.current;
|
|
188
|
+
if (!pendingSelect) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
pendingSelectRef.current = null;
|
|
192
|
+
fireOnSelect(pendingSelect.selectedFilterOption ?? state.selectedFilterOption, state.excludeCurrentPeriod);
|
|
193
|
+
});
|
|
194
|
+
const handleApplyClick = () => {
|
|
195
|
+
// `stateRef`, not `state`: this can run from the range picker's deferred submit.
|
|
196
|
+
const { selectedFilterOption: optionToApply, excludeCurrentPeriod: excludeToApply } = stateRef.current;
|
|
197
|
+
const normalizedSelectedFilterOption = normalizeEmptyValueHandling(normalizeSelectedFilterOption(optionToApply));
|
|
198
|
+
onApply(normalizedSelectedFilterOption, excludeToApply);
|
|
199
|
+
};
|
|
200
|
+
const onChangesDiscarded = () => {
|
|
201
|
+
if (!withoutApply) {
|
|
202
|
+
setState(() => getStateFromProps(props));
|
|
203
|
+
pendingSelectRef.current = {};
|
|
204
|
+
}
|
|
205
|
+
else if (withoutApply && !isEmpty(validateFilterOption(stateRef.current.selectedFilterOption))) {
|
|
206
|
+
setState(() => getStateFromWorkingProps(props));
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
const onCancelClicked = () => {
|
|
210
|
+
onCancel();
|
|
211
|
+
onChangesDiscarded();
|
|
212
|
+
};
|
|
213
|
+
const onDropdownOpenChanged = (isOpen) => {
|
|
214
|
+
if (isOpen) {
|
|
215
|
+
onOpen();
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
onClose();
|
|
219
|
+
onChangesDiscarded();
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
const handleExcludeCurrentPeriodChange = (excludeCurrentPeriod) => {
|
|
223
|
+
setState((prevState) => ({ ...prevState, excludeCurrentPeriod }));
|
|
224
|
+
pendingSelectRef.current = {};
|
|
225
|
+
};
|
|
226
|
+
const handleSelectedFilterOptionChange = (selectedFilterOption) => {
|
|
227
|
+
setState((prevState) => {
|
|
228
|
+
// Merging against `prevState` rather than the render snapshot mirrors the former
|
|
229
|
+
// updater: two option changes batched into one event must both be taken into account.
|
|
230
|
+
const nextSelectedFilterOption = normalizeEmptyValueHandling(mergeEmptyValueHandling(selectedFilterOption, prevState.selectedFilterOption));
|
|
231
|
+
// Recorded here - as the former updater did with its closure variable - so that the
|
|
232
|
+
// effect above reports the option this change actually resolved to.
|
|
233
|
+
pendingSelectRef.current = { selectedFilterOption: nextSelectedFilterOption };
|
|
234
|
+
return {
|
|
235
|
+
...prevState,
|
|
236
|
+
...getStateFromSelectedOption(nextSelectedFilterOption, prevState.excludeCurrentPeriod),
|
|
237
|
+
};
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
const { excludeCurrentPeriod, selectedFilterOption, isExcludeCurrentPeriodEnabled } = state;
|
|
241
|
+
return dateFilterMode === "hidden" ? null : (_jsx(DateFilterCore, { availableGranularities: availableGranularities, customFilterName: customFilterName, dateFormat: dateFormat ?? DEFAULT_DATE_FORMAT, openOnInit: openOnInit, showDropDownHeaderMessage: showDropDownHeaderMessage, disabled: dateFilterMode === "readonly", excludeCurrentPeriod: excludeCurrentPeriod, originalExcludeCurrentPeriod: originalExcludeCurrentPeriod, isExcludeCurrentPeriodEnabled: isExcludeCurrentPeriodEnabled, hideDisabledExclude: hideDisabledExclude, isTimeForAbsoluteRangeEnabled: isTimeForAbsoluteRangeEnabled ?? false, isSecondsForAbsoluteRangeEnabled: isSecondsForAbsoluteRangeEnabled ?? false, isEditMode: isEditMode ?? false, filterOptions: filterOptions, selectedFilterOption: selectedFilterOption, originalSelectedFilterOption: originalSelectedFilterOption, locale: locale, onApplyClick: handleApplyClick, onCancelClick: onCancelClicked, onDropdownOpenChanged: onDropdownOpenChanged, onExcludeCurrentPeriodChange: handleExcludeCurrentPeriodChange, onSelectedFilterOptionChange: handleSelectedFilterOptionChange, errors: validateFilterOption(selectedFilterOption), weekStart: weekStart, customIcon: customIcon, FilterConfigurationComponent: FilterConfigurationComponent, withoutApply: withoutApply, ButtonComponent: ButtonComponent, overlayPositionType: overlayPositionType, activeCalendars: activeCalendars, enableEmptyDateValues: enableEmptyDateValues, customRangeHint: customRangeHint }));
|
|
242
|
+
});
|
package/esm/sdk-ui-filters.d.ts
CHANGED
|
@@ -61,7 +61,6 @@ import { NamedExoticComponent } from 'react';
|
|
|
61
61
|
import { ObjRef } from '@gooddata/sdk-model';
|
|
62
62
|
import { ObjRefInScope } from '@gooddata/sdk-model';
|
|
63
63
|
import { OverlayPositionType } from '@gooddata/sdk-ui-kit';
|
|
64
|
-
import { PureComponent } from 'react';
|
|
65
64
|
import { RangeConditionOperator } from '@gooddata/sdk-model';
|
|
66
65
|
import { ReactElement } from 'react';
|
|
67
66
|
import { ReactNode } from 'react';
|
|
@@ -513,28 +512,7 @@ export declare function createFilterFromOperator(operator: TextFilterOperator, v
|
|
|
513
512
|
*
|
|
514
513
|
* @public
|
|
515
514
|
*/
|
|
516
|
-
export declare
|
|
517
|
-
static defaultProps: Partial<IDateFilterProps>;
|
|
518
|
-
static getDerivedStateFromProps(nextProps: IDateFilterProps, prevState: IDateFilterState): IDateFilterState | null;
|
|
519
|
-
private static getStateFromProps;
|
|
520
|
-
private static getStateFromWorkingProps;
|
|
521
|
-
private static getStateFromSelectedOption;
|
|
522
|
-
private static checkInitialFilterOption;
|
|
523
|
-
constructor(props: IDateFilterProps);
|
|
524
|
-
componentDidMount(): void;
|
|
525
|
-
render(): JSX.Element | null;
|
|
526
|
-
private handleApplyClick;
|
|
527
|
-
private onChangesDiscarded;
|
|
528
|
-
private onCancelClicked;
|
|
529
|
-
private onDropdownOpenChanged;
|
|
530
|
-
private handleExcludeCurrentPeriodChange;
|
|
531
|
-
private handleSelectedFilterOptionChange;
|
|
532
|
-
private handleSelectChange;
|
|
533
|
-
private fireOnSelect;
|
|
534
|
-
private normalizeEmptyValueHandling;
|
|
535
|
-
private mergeEmptyValueHandling;
|
|
536
|
-
private isSameOptionExceptEmptyValueHandling;
|
|
537
|
-
}
|
|
515
|
+
export declare const DateFilter: NamedExoticComponent<IDateFilterProps>;
|
|
538
516
|
|
|
539
517
|
/**
|
|
540
518
|
* @beta
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gooddata/sdk-ui-filters",
|
|
3
|
-
"version": "11.54.0-alpha.
|
|
3
|
+
"version": "11.54.0-alpha.2",
|
|
4
4
|
"description": "GoodData.UI SDK - Filter Components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "GoodData Corporation",
|
|
@@ -46,11 +46,11 @@
|
|
|
46
46
|
"ts-invariant": "0.10.3",
|
|
47
47
|
"tslib": "2.8.1",
|
|
48
48
|
"uuid": "11.1.1",
|
|
49
|
-
"@gooddata/sdk-backend-spi": "11.54.0-alpha.
|
|
50
|
-
"@gooddata/sdk-model": "11.54.0-alpha.
|
|
51
|
-
"@gooddata/sdk-ui": "11.54.0-alpha.
|
|
52
|
-
"@gooddata/
|
|
53
|
-
"@gooddata/
|
|
49
|
+
"@gooddata/sdk-backend-spi": "11.54.0-alpha.2",
|
|
50
|
+
"@gooddata/sdk-model": "11.54.0-alpha.2",
|
|
51
|
+
"@gooddata/sdk-ui": "11.54.0-alpha.2",
|
|
52
|
+
"@gooddata/util": "11.54.0-alpha.2",
|
|
53
|
+
"@gooddata/sdk-ui-kit": "11.54.0-alpha.2"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@microsoft/api-documenter": "^7.17.0",
|
|
@@ -92,12 +92,12 @@
|
|
|
92
92
|
"typescript": "5.9.3",
|
|
93
93
|
"vitest": "4.1.8",
|
|
94
94
|
"vitest-dom": "0.1.1",
|
|
95
|
-
"@gooddata/eslint-config": "11.54.0-alpha.
|
|
96
|
-
"@gooddata/
|
|
97
|
-
"@gooddata/
|
|
98
|
-
"@gooddata/sdk-backend-mockingbird": "11.54.0-alpha.
|
|
99
|
-
"@gooddata/
|
|
100
|
-
"@gooddata/
|
|
95
|
+
"@gooddata/eslint-config": "11.54.0-alpha.2",
|
|
96
|
+
"@gooddata/reference-workspace": "11.54.0-alpha.2",
|
|
97
|
+
"@gooddata/oxlint-config": "11.54.0-alpha.2",
|
|
98
|
+
"@gooddata/sdk-backend-mockingbird": "11.54.0-alpha.2",
|
|
99
|
+
"@gooddata/sdk-ui-theme-provider": "11.54.0-alpha.2",
|
|
100
|
+
"@gooddata/stylelint-config": "11.54.0-alpha.2"
|
|
101
101
|
},
|
|
102
102
|
"peerDependencies": {
|
|
103
103
|
"react": "^18.0.0 || ^19.0.0",
|