@gooddata/sdk-ui-dashboard 11.35.0-alpha.6 → 11.35.0

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 (34) hide show
  1. package/esm/__version.d.ts +1 -1
  2. package/esm/__version.js +1 -1
  3. package/esm/_staging/dashboard/dashboardFilterContext.js +18 -1
  4. package/esm/_staging/sharedHooks/useFiltersNamings.d.ts +1 -1
  5. package/esm/_staging/sharedHooks/useFiltersNamings.js +32 -5
  6. package/esm/index.d.ts +1 -1
  7. package/esm/index.js +1 -1
  8. package/esm/kdaDialog/dialog/hooks/useChangeAnalysis.js +21 -5
  9. package/esm/kdaDialog/internalTypes.d.ts +6 -1
  10. package/esm/kdaDialog/providers/Kda.js +4 -1
  11. package/esm/kdaDialog/providers/KdaState.js +1 -0
  12. package/esm/kdaDialog/types.d.ts +13 -2
  13. package/esm/model/commandHandlers/drill/keyDriverAnalysisHandler.js +8 -3
  14. package/esm/model/store/_infra/generators.d.ts +1 -0
  15. package/esm/model/store/_infra/generators.js +4 -1
  16. package/esm/model/store/filtering/dashboardFilterSelectors.d.ts +1 -1
  17. package/esm/model/store/filtering/dashboardFilterSelectors.js +8 -5
  18. package/esm/model/store/tabs/filterContext/filterContextReducers.js +2 -2
  19. package/esm/model/utils/widgetFilters.d.ts +1 -1
  20. package/esm/model/utils/widgetFilters.js +1 -1
  21. package/esm/presentation/automationFilters/components/AutomationFiltersSelect.js +8 -2
  22. package/esm/presentation/automationFilters/components/AutomationMeasureValueFilter.d.ts +10 -0
  23. package/esm/presentation/automationFilters/components/AutomationMeasureValueFilter.js +66 -0
  24. package/esm/presentation/automationFilters/components/AutomationMeasureValueFilterContext.d.ts +25 -0
  25. package/esm/presentation/automationFilters/components/AutomationMeasureValueFilterContext.js +28 -0
  26. package/esm/presentation/automationFilters/useAutomationFilters.d.ts +4 -1
  27. package/esm/presentation/automationFilters/useAutomationFilters.js +35 -4
  28. package/esm/presentation/automationFilters/utils.d.ts +2 -1
  29. package/esm/presentation/automationFilters/utils.js +34 -5
  30. package/esm/presentation/filterBar/measureValueFilter/DefaultDashboardMeasureValueFilter.js +8 -42
  31. package/esm/presentation/filterBar/measureValueFilter/useDashboardMeasureValueFilterData.d.ts +86 -0
  32. package/esm/presentation/filterBar/measureValueFilter/useDashboardMeasureValueFilterData.js +105 -0
  33. package/esm/sdk-ui-dashboard.d.ts +17 -6
  34. package/package.json +20 -20
@@ -1,3 +1,3 @@
1
- export declare const LIB_VERSION = "11.35.0-alpha.6";
1
+ export declare const LIB_VERSION = "11.35.0";
2
2
  export declare const LIB_DESCRIPTION = "GoodData SDK - Dashboard Component";
3
3
  export declare const LIB_NAME = "@gooddata/sdk-ui-dashboard";
package/esm/__version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // (C) 2021 GoodData Corporation
2
2
  // DO NOT CHANGE THIS FILE, IT IS RE-GENERATED ON EVERY BUILD
3
- export const LIB_VERSION = "11.35.0-alpha.6";
3
+ export const LIB_VERSION = "11.35.0";
4
4
  export const LIB_DESCRIPTION = "GoodData SDK - Dashboard Component";
5
5
  export const LIB_NAME = "@gooddata/sdk-ui-dashboard";
@@ -1,6 +1,7 @@
1
1
  // (C) 2021-2026 GoodData Corporation
2
+ import { v4 as uuidv4 } from "uuid";
2
3
  import { NotSupported } from "@gooddata/sdk-backend-spi";
3
- import { dashboardAttributeFilterItemFilterElementsBy, dashboardFilterLocalIdentifier, filterAttributeElements, filterLocalIdentifier, filterObjRef, isAbsoluteDateFilter, isAllTimeDateFilter, isArbitraryAttributeFilter, isAttributeFilterWithSelection, isDashboardArbitraryAttributeFilter, isDashboardAttributeFilter, isDashboardAttributeFilterItem, isMatchAttributeFilter, isNegativeAttributeFilter, isRelativeBoundedDateFilter, isRelativeDateFilter, isTempFilterContext, newAbsoluteDashboardDateFilter, newAllTimeDashboardDateFilter, newRelativeDashboardDateFilter, } from "@gooddata/sdk-model";
4
+ import { dashboardAttributeFilterItemFilterElementsBy, dashboardFilterLocalIdentifier, filterAttributeElements, filterLocalIdentifier, filterObjRef, isAbsoluteDateFilter, isAllTimeDateFilter, isArbitraryAttributeFilter, isAttributeFilterWithSelection, isDashboardArbitraryAttributeFilter, isDashboardAttributeFilter, isDashboardAttributeFilterItem, isMatchAttributeFilter, isMeasureValueFilter, isNegativeAttributeFilter, isObjRef, isRelativeBoundedDateFilter, isRelativeDateFilter, isTempFilterContext, measureValueFilterConditions, measureValueFilterMeasure, newAbsoluteDashboardDateFilter, newAllTimeDashboardDateFilter, newRelativeDashboardDateFilter, } from "@gooddata/sdk-model";
4
5
  import { createDefaultFilterContext } from "./defaultFilterContext.js";
5
6
  /**
6
7
  * Given a dashboard, this function will inspect its filter context and always return a valid instance of IFilterContextDefinition to use.
@@ -154,5 +155,21 @@ export function dashboardFilterToFilterContextItem(filter, keepDatasets) {
154
155
  else if (isRelativeDateFilter(filter)) {
155
156
  return newRelativeDashboardDateFilter(filter.relativeDateFilter.granularity, filter.relativeDateFilter.from, filter.relativeDateFilter.to, keepDatasets ? filter.relativeDateFilter.dataSet : undefined, filter.relativeDateFilter.localIdentifier, isRelativeBoundedDateFilter(filter) ? filter.relativeDateFilter.boundedFilter : undefined, filter.relativeDateFilter.emptyValueHandling);
156
157
  }
158
+ else if (isMeasureValueFilter(filter)) {
159
+ const measure = measureValueFilterMeasure(filter);
160
+ // Dashboard MVF requires an ObjRef (catalog metric reference); LocalIdRef cannot
161
+ // survive the round-trip from execution to filter context.
162
+ if (!isObjRef(measure)) {
163
+ throw new NotSupported(`Unsupported filter type! Please provide valid dashboard filter. Filter: ${JSON.stringify(filter)}`);
164
+ }
165
+ const conditions = measureValueFilterConditions(filter);
166
+ return {
167
+ dashboardMeasureValueFilter: {
168
+ measure,
169
+ localIdentifier: filter.measureValueFilter.localIdentifier ?? uuidv4(),
170
+ ...(conditions ? { conditions } : {}),
171
+ },
172
+ };
173
+ }
157
174
  throw new NotSupported(`Unsupported filter type! Please provide valid dashboard filter. Filter: ${JSON.stringify(filter)}`);
158
175
  }
@@ -1,6 +1,6 @@
1
1
  import { type FilterContextItem, type ObjRef } from "@gooddata/sdk-model";
2
2
  export type FilterNaming = {
3
- type: "attributeFilter" | "dateFilter";
3
+ type: "attributeFilter" | "dateFilter" | "measureValueFilter";
4
4
  all: boolean;
5
5
  id: string;
6
6
  title: string;
@@ -1,11 +1,11 @@
1
1
  // (C) 2024-2026 GoodData Corporation
2
2
  import { useIntl } from "react-intl";
3
3
  import { v4 as uuidv4 } from "uuid";
4
- import { dashboardAttributeFilterItemLocalIdentifier, dashboardAttributeFilterItemTitle, getAttributeElementsItems, isAllTimeDashboardDateFilter, isAllValuesDashboardAttributeFilter, isDashboardArbitraryAttributeFilter, isDashboardAttributeFilter, isDashboardCommonDateFilter, isDashboardDateFilter, isDashboardDateFilterWithDimension, isDashboardMatchAttributeFilter, serializeObjRef, } from "@gooddata/sdk-model";
5
- import { DateFilterHelpers, getAttributeFilterSubtitle, getLocalizedIcuDateFormatPattern, getTextFilterStateText, } from "@gooddata/sdk-ui-filters";
4
+ import { areObjRefsEqual, dashboardAttributeFilterItemLocalIdentifier, dashboardAttributeFilterItemTitle, getAttributeElementsItems, isAllDashboardMeasureValueFilter, isAllTimeDashboardDateFilter, isAllValuesDashboardAttributeFilter, isDashboardArbitraryAttributeFilter, isDashboardAttributeFilter, isDashboardCommonDateFilter, isDashboardDateFilter, isDashboardDateFilterWithDimension, isDashboardMatchAttributeFilter, isDashboardMeasureValueFilter, objRefToString, serializeObjRef, } from "@gooddata/sdk-model";
5
+ import { DateFilterHelpers, getAttributeFilterSubtitle, getLocalizedIcuDateFormatPattern, getMeasureValueFilterConditionLabel, getTextFilterStateText, } from "@gooddata/sdk-ui-filters";
6
6
  import { useDashboardSelector } from "../../model/react/DashboardStoreProvider.js";
7
- import { selectAllCatalogAttributesMap } from "../../model/store/catalog/catalogSelectors.js";
8
- import { selectLocale, selectSettings } from "../../model/store/config/configSelectors.js";
7
+ import { selectAllCatalogAttributesMap, selectCatalogMeasures, } from "../../model/store/catalog/catalogSelectors.js";
8
+ import { selectLocale, selectSeparators, selectSettings } from "../../model/store/config/configSelectors.js";
9
9
  import { convertDateFilterConfigToDateFilterOptions } from "../dateFilterConfig/dateFilterConfigConverters.js";
10
10
  import { matchDateFilterToDateFilterOptionWithPreference } from "../dateFilterConfig/dateFilterOptionMapping.js";
11
11
  import { defaultDateFilterConfig } from "../dateFilterConfig/defaultConfig.js";
@@ -13,6 +13,10 @@ import { ensureAllTimeFilterForExport } from "../exportUtils/filterUtils.js";
13
13
  import { useAttributeFilterDisplayFormFromMap } from "./useAttributeFilterDisplayFormFromMap.js";
14
14
  import { useCommonDateFilterTitle } from "./useCommonDateFilterTitle.js";
15
15
  import { useDateFiltersTitles } from "./useDateFiltersTitles.js";
16
+ const PERCENT_FORMAT_REGEX = /%/;
17
+ function isPercentageFormat(format) {
18
+ return !!format && PERCENT_FORMAT_REGEX.test(format);
19
+ }
16
20
  /**
17
21
  * Hook that gathers all dependencies needed for filter naming transformations.
18
22
  * Reusable across different hooks that need to transform filters to namings.
@@ -29,6 +33,8 @@ function useFilterNamingDependencies(filtersForTitles) {
29
33
  : settings.responsiveUiDateFormat;
30
34
  const getAttributeFilterDisplayFormFromMap = useAttributeFilterDisplayFormFromMap();
31
35
  const attrMap = useDashboardSelector(selectAllCatalogAttributesMap);
36
+ const measures = useDashboardSelector(selectCatalogMeasures);
37
+ const separators = useDashboardSelector(selectSeparators);
32
38
  const dateFiltersForTitles = filtersForTitles.filter(isDashboardDateFilterWithDimension);
33
39
  const commonDateFilterTitle = useCommonDateFilterTitle(intl);
34
40
  const allDateFiltersTitlesObj = useDateFiltersTitles(dateFiltersForTitles, intl);
@@ -38,6 +44,8 @@ function useFilterNamingDependencies(filtersForTitles) {
38
44
  dateFormat,
39
45
  getAttributeFilterDisplayFormFromMap,
40
46
  attrMap,
47
+ measures,
48
+ separators,
41
49
  commonDateFilterTitle,
42
50
  allDateFiltersTitlesObj,
43
51
  };
@@ -47,7 +55,7 @@ function useFilterNamingDependencies(filtersForTitles) {
47
55
  * Extracted to avoid code duplication between useFiltersNamings and useFiltersByTabNamings.
48
56
  */
49
57
  function transformFiltersToNamings(filtersToDisplay, deps) {
50
- const { intl, dateFormat, getAttributeFilterDisplayFormFromMap, attrMap, commonDateFilterTitle, allDateFiltersTitlesObj, } = deps;
58
+ const { intl, dateFormat, getAttributeFilterDisplayFormFromMap, attrMap, measures, separators, commonDateFilterTitle, allDateFiltersTitlesObj, } = deps;
51
59
  // we want to show all time filter in the list of filters even if it is not stored
52
60
  const extendedFiltersToDisplay = ensureAllTimeFilterForExport(filtersToDisplay);
53
61
  return extendedFiltersToDisplay.map((filter) => {
@@ -127,6 +135,25 @@ function transformFiltersToNamings(filtersToDisplay, deps) {
127
135
  subtitle,
128
136
  };
129
137
  }
138
+ else if (isDashboardMeasureValueFilter(filter)) {
139
+ const { measure, localIdentifier, title: customTitle, conditions, } = filter.dashboardMeasureValueFilter;
140
+ const catalogMetric = measures.find((m) => areObjRefsEqual(m.measure.ref, measure));
141
+ const defaultTitle = catalogMetric?.measure.title ?? objRefToString(measure);
142
+ const title = customTitle ?? defaultTitle;
143
+ const format = catalogMetric?.measure.format;
144
+ const usePercentage = isPercentageFormat(format);
145
+ const subtitle = getMeasureValueFilterConditionLabel(intl, conditions, {
146
+ usePercentage,
147
+ separators,
148
+ });
149
+ return {
150
+ type: "measureValueFilter",
151
+ all: isAllDashboardMeasureValueFilter(filter),
152
+ id: localIdentifier,
153
+ title,
154
+ subtitle,
155
+ };
156
+ }
130
157
  else if (isDashboardMatchAttributeFilter(filter)) {
131
158
  const { operator: matchOperator, literal, negativeSelection, displayForm, } = filter.matchAttributeFilter;
132
159
  const filterDisplayForm = getAttributeFilterDisplayFormFromMap(displayForm);
package/esm/index.d.ts CHANGED
@@ -197,7 +197,7 @@ export { newDrillToSameDashboardHandler } from "./model/eventHandlers/drillToSam
197
197
  export { type IHeadlessDashboardConfig, type IMonitoredAction, HeadlessDashboard, } from "./model/headlessDashboard/HeadlessDashboard.js";
198
198
  export { isTemporaryIdentity, getWidgetTitle } from "./model/utils/dashboardItemUtils.js";
199
199
  export { existBlacklistHierarchyPredicate } from "./model/utils/attributeHierarchyUtils.js";
200
- export { removeDateFilters, removeIgnoredWidgetFilters } from "./model/utils/widgetFilters.js";
200
+ export { getAttributeFilters, removeIgnoredWidgetFilters } from "./model/utils/widgetFilters.js";
201
201
  export { getAuthor } from "./model/utils/author.js";
202
202
  export type { ICustomComponentBase, IDraggingComponentProps, IDropTargetComponentProps, IAttributeFilterDraggingComponentProps, IDateFilterDraggingComponentProps, IInsightDraggingComponentProps, IKpiDraggingComponentProps, IRichTextDraggingComponentProps, IVisualizationSwitcherDraggingComponentProps, IDashboardLayoutDraggingComponentProps, ICustomDraggingComponentProps, AttributeFilterDraggingComponent, DateFilterDraggingComponent, InsightDraggingComponent, KpiDraggingComponent, RichTextDraggingComponent, VisualizationSwitcherDraggingComponent, DashboardLayoutDraggingComponent, CustomDraggingComponent, AttributeFilterDraggableComponent, DateFilterDraggableComponent, InsightDraggableComponent, KpiDraggableComponent, RichTextDraggableComponent, VisualizationSwitcherDraggableComponent, DashboardLayoutDraggableComponent, CustomDraggableComponent, DraggableComponent, DropTarget, ICreatePanelItemComponentProps, CustomCreatePanelItemComponent, CreatableByDragComponent, CreatablePlaceholderComponent, CustomWidgetConfigPanelComponent, IWidgetConfigPanelProps, ConfigurableWidget, AttributeFilterComponentSet, DateFilterComponentSet, InsightWidgetComponentSet, RichTextWidgetComponentSet, VisualizationSwitcherWidgetComponentSet, DashboardLayoutWidgetComponentSet, CustomWidgetComponentSet, InsightComponentSetProvider, } from "./presentation/componentDefinition/types.js";
203
203
  export { renderModeAware } from "./presentation/componentDefinition/renderModeAware.js";
package/esm/index.js CHANGED
@@ -140,7 +140,7 @@ export { newDrillToSameDashboardHandler } from "./model/eventHandlers/drillToSam
140
140
  export { HeadlessDashboard, } from "./model/headlessDashboard/HeadlessDashboard.js";
141
141
  export { isTemporaryIdentity, getWidgetTitle } from "./model/utils/dashboardItemUtils.js";
142
142
  export { existBlacklistHierarchyPredicate } from "./model/utils/attributeHierarchyUtils.js";
143
- export { removeDateFilters, removeIgnoredWidgetFilters } from "./model/utils/widgetFilters.js";
143
+ export { getAttributeFilters, removeIgnoredWidgetFilters } from "./model/utils/widgetFilters.js";
144
144
  export { getAuthor } from "./model/utils/author.js";
145
145
  export { renderModeAware } from "./presentation/componentDefinition/renderModeAware.js";
146
146
  export { Dashboard } from "./presentation/dashboard/Dashboard.js";
@@ -2,9 +2,9 @@
2
2
  import { useEffect, useMemo } from "react";
3
3
  import stringify from "json-stable-stringify";
4
4
  import { ClientFormatterFacade } from "@gooddata/number-formatter";
5
- import { isAllValuesDashboardAttributeFilter, newAttribute, } from "@gooddata/sdk-model";
5
+ import { isAllDashboardMeasureValueFilter, isAllValuesDashboardAttributeFilter, newAttribute, } from "@gooddata/sdk-model";
6
6
  import { useBackendStrict, useCancelablePromise, useWorkspaceStrict } from "@gooddata/sdk-ui";
7
- import { dashboardAttributeFilterItemToAttributeFilter } from "../../../converters/filterConverters.js";
7
+ import { dashboardAttributeFilterItemToAttributeFilter, dashboardMeasureValueFilterToMeasureValueFilter, } from "../../../converters/filterConverters.js";
8
8
  import { useAttribute } from "../../hooks/useAttribute.js";
9
9
  import { useDateAttribute } from "../../hooks/useDateAttribute.js";
10
10
  import { useRelevantFilters } from "../../hooks/useRelevantFilters.js";
@@ -18,14 +18,15 @@ export function useChangeAnalysis() {
18
18
  // eslint-disable-next-line react-hooks/exhaustive-deps
19
19
  }, [state.selectedUpdated]);
20
20
  const filters = useRelevantFilters();
21
+ const measureValueFilters = state.measureValueFilters;
21
22
  const loading = state.relevantStatus === "loading" || state.relevantStatus === "pending";
22
- const results = useChangeAnalysisResults(definition, attributes, filters, loading);
23
+ const results = useChangeAnalysisResults(definition, attributes, filters, measureValueFilters, loading);
23
24
  const list = useKdaStateWithList(results, definition);
24
25
  useEffect(() => {
25
26
  setState(list);
26
27
  }, [list, setState]);
27
28
  }
28
- function useChangeAnalysisResults(definition, attrs, attrFilters, loading) {
29
+ function useChangeAnalysisResults(definition, attrs, attrFilters, measureValueFilters, loading) {
29
30
  const backend = useBackendStrict();
30
31
  const workspace = useWorkspaceStrict();
31
32
  const from = definition?.range[0].date;
@@ -38,6 +39,13 @@ function useChangeAnalysisResults(definition, attrs, attrFilters, loading) {
38
39
  .map((f) => stringify(f))
39
40
  .join();
40
41
  }, [attrFilters]);
42
+ // Use the same fingerprint approach for MVF so cancelable-promise recomputes only when conditions actually change.
43
+ const measureValueFiltersFingerprint = useMemo(() => {
44
+ return measureValueFilters
45
+ .filter((f) => !isAllDashboardMeasureValueFilter(f))
46
+ .map((f) => stringify(f))
47
+ .join();
48
+ }, [measureValueFilters]);
41
49
  const dateAttribute = dateAttributeFinder(definition?.dateAttribute);
42
50
  const shouldComputeChangeAnalysis = !!definition && !!dateAttribute && !loading;
43
51
  const { includeTags, excludeTags } = useTags();
@@ -51,9 +59,16 @@ function useChangeAnalysisResults(definition, attrs, attrFilters, loading) {
51
59
  return attr ? newAttribute(ref) : null;
52
60
  })
53
61
  .filter(Boolean);
54
- const filters = attrFilters
62
+ const attributeExecutionFilters = attrFilters
55
63
  .filter((f) => !isAllValuesDashboardAttributeFilter(f))
56
64
  .map(dashboardAttributeFilterItemToAttributeFilter);
65
+ const measureValueExecutionFilters = measureValueFilters
66
+ .filter((f) => !isAllDashboardMeasureValueFilter(f))
67
+ .map(dashboardMeasureValueFilterToMeasureValueFilter);
68
+ const filters = [
69
+ ...attributeExecutionFilters,
70
+ ...measureValueExecutionFilters,
71
+ ];
57
72
  return backend
58
73
  .workspace(workspace)
59
74
  .keyDriverAnalysis()
@@ -83,6 +98,7 @@ function useChangeAnalysisResults(definition, attrs, attrFilters, loading) {
83
98
  loading,
84
99
  dateAttribute,
85
100
  attributeFiltersFingerprint,
101
+ measureValueFiltersFingerprint,
86
102
  includeTags,
87
103
  excludeTags,
88
104
  ]);
@@ -1,4 +1,4 @@
1
- import { type DashboardAttributeFilterItem, type ICatalogDateAttribute, type ISeparators, type ObjRef } from "@gooddata/sdk-model";
1
+ import { type DashboardAttributeFilterItem, type ICatalogDateAttribute, type IDashboardMeasureValueFilter, type ISeparators, type ObjRef } from "@gooddata/sdk-model";
2
2
  import { type IUiListboxInteractiveItem } from "@gooddata/sdk-ui-kit";
3
3
  import { type DeepReadonly, type IKdaDataPoint, type IKdaDefinition, type KdaPeriodType } from "./types.js";
4
4
  export interface IKdaDateOptions {
@@ -48,6 +48,11 @@ export interface IKdaState {
48
48
  selectedStatus: KdaAsyncStatus;
49
49
  selectedError: Error | undefined;
50
50
  attributeFilters: DashboardAttributeFilterItem[];
51
+ /**
52
+ * Dashboard measure value filters propagated to the change analysis computation.
53
+ * Not editable in the dialog UI — these flow through from the dashboard filter context.
54
+ */
55
+ measureValueFilters: IDashboardMeasureValueFilter[];
51
56
  items: IUiListboxInteractiveItem<IKdaItem>[];
52
57
  itemsStatus: KdaAsyncStatus;
53
58
  itemsError: Error | undefined;
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  // (C) 2025-2026 GoodData Corporation
3
3
  import { useMemo } from "react";
4
- import { isAllValuesDashboardAttributeFilter } from "@gooddata/sdk-model";
4
+ import { isAllDashboardMeasureValueFilter, isAllValuesDashboardAttributeFilter, } from "@gooddata/sdk-model";
5
5
  import { KdaStateProvider } from "./KdaState.js";
6
6
  export function KdaProvider({ children, definition, separators, includeTags, excludeTags }) {
7
7
  const state = useMemo(() => {
@@ -15,6 +15,9 @@ export function KdaProvider({ children, definition, separators, includeTags, exc
15
15
  definitionStatus: "success",
16
16
  isMinimized: true,
17
17
  attributeFilters: (definition.filters?.slice() ?? []).filter((f) => !isAllValuesDashboardAttributeFilter(f)),
18
+ // MVF flows through from the dashboard filter context; noop "All" MVFs are dropped
19
+ // so the backend only receives meaningful conditions.
20
+ measureValueFilters: (definition.measureValueFilters?.slice() ?? []).filter((f) => !isAllDashboardMeasureValueFilter(f)),
18
21
  };
19
22
  }, [definition, separators, includeTags, excludeTags]);
20
23
  return _jsx(KdaStateProvider, { value: state, children: children });
@@ -22,6 +22,7 @@ const defaultState = {
22
22
  selectedError: undefined,
23
23
  //root data
24
24
  attributeFilters: [],
25
+ measureValueFilters: [],
25
26
  //attributes data
26
27
  selectedAttributes: [],
27
28
  selectedUpdated: 0,
@@ -1,4 +1,4 @@
1
- import { type DashboardAttributeFilterItem, type IAttributeDescriptorBody, type IMeasure, type ObjRef } from "@gooddata/sdk-model";
1
+ import { type DashboardAttributeFilterItem, type IAttributeDescriptorBody, type IDashboardMeasureValueFilter, type IMeasure, type ObjRef } from "@gooddata/sdk-model";
2
2
  import { type OverlayController } from "@gooddata/sdk-ui-kit";
3
3
  /**
4
4
  * @internal
@@ -60,9 +60,20 @@ export interface IKdaDefinition {
60
60
  */
61
61
  metrics?: IMeasure[];
62
62
  /**
63
- * Filters to apply
63
+ * Attribute filters to apply.
64
+ *
65
+ * Attribute filters drive both the KDA "segment-by attribute" UI in the dialog and the
66
+ * scope of the change analysis computation.
64
67
  */
65
68
  filters?: DashboardAttributeFilterItem[];
69
+ /**
70
+ * Measure value filters to apply to the change analysis computation.
71
+ *
72
+ * They are not editable in the dialog UI (KDA segments by attribute, not by metric value),
73
+ * but the dashboard MVFs are propagated to the backend so the computation respects the
74
+ * same metric-driven scope as the rest of the dashboard.
75
+ */
76
+ measureValueFilters?: IDashboardMeasureValueFilter[];
66
77
  /**
67
78
  * Date attribute
68
79
  */
@@ -1,12 +1,12 @@
1
1
  // (C) 2021-2026 GoodData Corporation
2
2
  import { put, select } from "redux-saga/effects";
3
- import { areObjRefsEqual, dashboardAttributeFilterItemDisplayForm, isAttributeDescriptor, isMeasureDescriptor, } from "@gooddata/sdk-model";
3
+ import { areObjRefsEqual, dashboardAttributeFilterItemDisplayForm, isAttributeDescriptor, isDashboardMeasureValueFilter, isMeasureDescriptor, } from "@gooddata/sdk-model";
4
4
  import { keyDriverAnalysisRequested, keyDriverAnalysisResolved, } from "../../events/drill.js";
5
5
  import { invalidArgumentsProvided } from "../../events/general.js";
6
6
  import { generateFilterLocalIdentifier } from "../../store/_infra/generators.js";
7
7
  import { selectCatalogDateAttributes } from "../../store/catalog/catalogSelectors.js";
8
8
  import { selectWidgetByRef } from "../../store/tabs/layout/layoutSelectors.js";
9
- import { removeDateFilters, removeIgnoredWidgetFilters } from "../../utils/widgetFilters.js";
9
+ import { getAttributeFilters, removeIgnoredWidgetFilters } from "../../utils/widgetFilters.js";
10
10
  import { convertIntersectionToAttributeFilters } from "./common/intersectionUtils.js";
11
11
  export function* keyDriverAnalysisHandler(ctx, cmd) {
12
12
  const { drillDefinition, drillEvent, keyDriveItem, filters: availableFilters } = cmd.payload;
@@ -52,7 +52,11 @@ export function* keyDriverAnalysisHandler(ctx, cmd) {
52
52
  return dashboardFilter;
53
53
  });
54
54
  const widget = yield select(selectWidgetByRef(drillEvent.widgetRef));
55
- const attributeFilters = removeDateFilters(removeIgnoredWidgetFilters(availableFilters, widget));
55
+ const widgetFilters = removeIgnoredWidgetFilters(availableFilters, widget);
56
+ // KDA defines its own date range — drop date filters. Keep attribute and measure value
57
+ // filters so the change analysis respects the rest of the dashboard filter context.
58
+ const attributeFilters = getAttributeFilters(widgetFilters);
59
+ const measureValueFilters = widgetFilters.filter(isDashboardMeasureValueFilter);
56
60
  const filters = mergeFilters(intersectionFilters, attributeFilters);
57
61
  return keyDriverAnalysisResolved(ctx, cmd.payload.drillDefinition, cmd.payload.drillEvent, {
58
62
  metric: {
@@ -65,6 +69,7 @@ export function* keyDriverAnalysisHandler(ctx, cmd) {
65
69
  },
66
70
  metrics,
67
71
  filters,
72
+ measureValueFilters,
68
73
  dateAttribute: dateAttribute.attribute.ref,
69
74
  range: [
70
75
  {
@@ -1,2 +1,3 @@
1
1
  import { type ObjRef } from "@gooddata/sdk-model";
2
2
  export declare const generateFilterLocalIdentifier: (ref: ObjRef, index: number) => string;
3
+ export declare const generateMeasureValueFilterLocalIdentifier: (ref: ObjRef, index: number) => string;
@@ -1,5 +1,8 @@
1
- // (C) 2024 GoodData Corporation
1
+ // (C) 2024-2026 GoodData Corporation
2
2
  import { objRefToString } from "@gooddata/sdk-model";
3
3
  export const generateFilterLocalIdentifier = (ref, index) => {
4
4
  return `${objRefToString(ref)}_${index}_attributeFilter`;
5
5
  };
6
+ export const generateMeasureValueFilterLocalIdentifier = (ref, index) => {
7
+ return `${objRefToString(ref)}_${index}_measureValueFilter`;
8
+ };
@@ -24,7 +24,7 @@ export declare const selectAutomationDefaultSelectedFilters: DashboardSelector<F
24
24
  * @alpha
25
25
  */
26
26
  export declare const selectAutomationCommonDateFilterId: DashboardSelector<string | undefined>;
27
- export declare function removeEmptyDashboardAttributeFilters(filters?: FilterContextItem[]): FilterContextItem[];
27
+ export declare function removeEmptyDashboardFilters(filters?: FilterContextItem[]): FilterContextItem[];
28
28
  export declare const isFilterContextItemHidden: (filter: FilterContextItem, filterConfigurations: {
29
29
  commonDateFilterConfig?: IDashboardDateFilterConfig | undefined;
30
30
  dateFilterWithDimensionConfigs: IDashboardDateFilterConfigItem[];
@@ -1,7 +1,7 @@
1
1
  // (C) 2024-2026 GoodData Corporation
2
2
  import { createSelector } from "@reduxjs/toolkit";
3
3
  import { generateDateFilterLocalIdentifier } from "@gooddata/sdk-backend-base";
4
- import { areObjRefsEqual, dashboardAttributeFilterItemLocalIdentifier, isAllValuesDashboardAttributeFilter, isDashboardAttributeFilterItem, isDashboardCommonDateFilter, isDashboardDateFilter, isDashboardDateFilterWithDimension, newAllTimeDashboardDateFilter, } from "@gooddata/sdk-model";
4
+ import { areObjRefsEqual, dashboardAttributeFilterItemLocalIdentifier, isAllDashboardMeasureValueFilter, isAllValuesDashboardAttributeFilter, isDashboardAttributeFilterItem, isDashboardCommonDateFilter, isDashboardDateFilter, isDashboardDateFilterWithDimension, isDashboardMeasureValueFilter, newAllTimeDashboardDateFilter, } from "@gooddata/sdk-model";
5
5
  import { selectCrossFilteringItems, selectCrossFilteringItemsByTab } from "../drill/drillSelectors.js";
6
6
  import { selectAttributeFilterConfigsOverrides, selectAttributeFilterConfigsOverridesByTab, } from "../tabs/attributeFilterConfigs/attributeFilterConfigsSelectors.js";
7
7
  import { selectDateFilterConfigOverrides, selectDateFilterConfigOverridesByTab, } from "../tabs/dateFilterConfig/dateFilterConfigSelectors.js";
@@ -55,7 +55,7 @@ export const selectAutomationAvailableDashboardFilters = createSelector(selectDa
55
55
  * @alpha
56
56
  */
57
57
  export const selectAutomationDefaultSelectedFilters = createSelector(selectAutomationAvailableDashboardFilters, (availableDashboardFilters) => {
58
- return removeEmptyDashboardAttributeFilters(availableDashboardFilters);
58
+ return removeEmptyDashboardFilters(availableDashboardFilters);
59
59
  });
60
60
  /**
61
61
  * @alpha
@@ -79,11 +79,14 @@ const removeCrossFilteringFilters = (filters, crossFilteringItems) => {
79
79
  return true;
80
80
  });
81
81
  };
82
- export function removeEmptyDashboardAttributeFilters(filters = []) {
82
+ export function removeEmptyDashboardFilters(filters = []) {
83
83
  return filters.filter((filter) => {
84
84
  if (isDashboardAttributeFilterItem(filter)) {
85
85
  return !isAllValuesDashboardAttributeFilter(filter);
86
86
  }
87
+ if (isDashboardMeasureValueFilter(filter)) {
88
+ return !isAllDashboardMeasureValueFilter(filter);
89
+ }
87
90
  return true;
88
91
  });
89
92
  }
@@ -166,8 +169,8 @@ export const selectAutomationFiltersByTab = createSelector(selectTabs, selectFil
166
169
  const lockedFilters = filtersWithCommonDate.filter((filter) => isFilterContextItemLocked(filter, filterConfigurations));
167
170
  // Get hidden filters
168
171
  const hiddenFilters = filtersWithCommonDate.filter((filter) => isFilterContextItemHidden(filter, filterConfigurations));
169
- // Get default selected filters (empty "All values" attribute filters removed)
170
- const defaultSelectedFilters = removeEmptyDashboardAttributeFilters(availableFilters);
172
+ // Get default selected filters (noop "All" filters removed — attribute and MVF)
173
+ const defaultSelectedFilters = removeEmptyDashboardFilters(availableFilters);
171
174
  return {
172
175
  tabId,
173
176
  tabTitle,
@@ -1,7 +1,7 @@
1
1
  // (C) 2021-2026 GoodData Corporation
2
2
  import { invariant } from "ts-invariant";
3
3
  import { areObjRefsEqual, attributeElementsIsEmpty, dashboardAttributeFilterItemFilterElementsBy, dashboardAttributeFilterItemFilterElementsByDate, dashboardAttributeFilterItemLocalIdentifier, dashboardAttributeFilterItemValidateElementsBy, dashboardFilterLocalIdentifier, isAttributeElementsByRef, isDashboardArbitraryAttributeFilter, isDashboardAttributeFilter, isDashboardAttributeFilterItem, isDashboardCommonDateFilter, isDashboardDateFilter, isDashboardMatchAttributeFilter, isDashboardMeasureValueFilter, newAllTimeDashboardDateFilter, } from "@gooddata/sdk-model";
4
- import { generateFilterLocalIdentifier } from "../../_infra/generators.js";
4
+ import { generateFilterLocalIdentifier, generateMeasureValueFilterLocalIdentifier, } from "../../_infra/generators.js";
5
5
  import { getActiveTab, getTabOrActive } from "../tabsState.js";
6
6
  import { filterContextInitialState } from "./filterContextState.js";
7
7
  import { applyFilterContext, initializeFilterContext } from "./filterContextUtils.js";
@@ -674,7 +674,7 @@ const addMeasureValueFilter = (state, action) => {
674
674
  const filter = {
675
675
  dashboardMeasureValueFilter: {
676
676
  measure,
677
- localIdentifier: localIdentifier ?? generateFilterLocalIdentifier(measure, Math.max(0, index)),
677
+ localIdentifier: localIdentifier ?? generateMeasureValueFilterLocalIdentifier(measure, Math.max(0, index)),
678
678
  title,
679
679
  },
680
680
  };
@@ -7,4 +7,4 @@ export declare function removeIgnoredWidgetFilters(filters: FilterContextItem[],
7
7
  /**
8
8
  * @internal
9
9
  */
10
- export declare function removeDateFilters(filters: FilterContextItem[]): DashboardAttributeFilterItem[];
10
+ export declare function getAttributeFilters(filters: FilterContextItem[]): DashboardAttributeFilterItem[];
@@ -27,6 +27,6 @@ export function removeIgnoredWidgetFilters(filters, widget) {
27
27
  /**
28
28
  * @internal
29
29
  */
30
- export function removeDateFilters(filters) {
30
+ export function getAttributeFilters(filters) {
31
31
  return filters.filter(isDashboardAttributeFilterItem);
32
32
  }
@@ -9,6 +9,7 @@ import { AttributesDropdown } from "../../filterBar/attributeFilter/addAttribute
9
9
  import { useAutomationFilters, useAutomationFiltersByTab } from "../useAutomationFilters.js";
10
10
  import { AutomationAttributeFilter } from "./AutomationAttributeFilter.js";
11
11
  import { AutomationDateFilter } from "./AutomationDateFilter.js";
12
+ import { AutomationMeasureValueFilter } from "./AutomationMeasureValueFilter.js";
12
13
  const COLLAPSED_FILTERS_COUNT = 2;
13
14
  function AutomationCheckboxOrNote({ isDashboardAutomation, storeFilters, handleStoreFiltersChange, handleKeyDown, automationFilterSelectTooltipId, }) {
14
15
  const intl = useIntl();
@@ -51,6 +52,7 @@ export function AutomationFiltersSelect({ availableFilters = [], selectedFilters
51
52
  const filters = shouldRenderByTab ? [] : flatFiltersData.visibleFilters;
52
53
  const attributes = shouldRenderByTab ? [] : flatFiltersData.attributes;
53
54
  const dateDatasets = shouldRenderByTab ? [] : flatFiltersData.dateDatasets;
55
+ const measures = shouldRenderByTab ? [] : flatFiltersData.measures;
54
56
  const handleChangeFilter = shouldRenderByTab
55
57
  ? () => { } // Not used in tab mode
56
58
  : flatFiltersData.handleChangeFilter;
@@ -109,7 +111,7 @@ export function AutomationFiltersSelect({ availableFilters = [], selectedFilters
109
111
  // Add button for each tab section
110
112
  addFilterButton: _jsx(AttributesDropdown, { id: `${AUTOMATION_FILTERS_DIALOG_ID}-${tab.tabId}`, onClose: () => { }, onSelect: (value) => {
111
113
  tabFiltersData.handleTabFilterAdd(tab.tabId, value, tab.attributes, tab.dateDatasets);
112
- }, attributes: tab.attributes, dateDatasets: tab.dateDatasets, openOnInit: false, overlayPositionType: overlayPositionType, className: "gd-automation-filters__dropdown s-automation-filters-add-filter-dropdown", getCustomItemTitle: (item) => getCatalogItemCustomTitle(item, availableFilters, tab.dateConfigs), accessibilityConfig: {
114
+ }, attributes: tab.attributes, dateDatasets: tab.dateDatasets, measures: tab.measures, openOnInit: false, overlayPositionType: overlayPositionType, className: "gd-automation-filters__dropdown s-automation-filters-add-filter-dropdown", getCustomItemTitle: (item) => getCatalogItemCustomTitle(item, availableFilters, tab.dateConfigs), accessibilityConfig: {
113
115
  ariaLabelledBy: AUTOMATION_FILTERS_DIALOG_TITLE_ID,
114
116
  searchAriaLabel: searchAriaLabel,
115
117
  }, DropdownButtonComponent: ({ buttonRef, isOpen, onClick }) => (_jsx(UiTooltip, { arrowPlacement: "left", triggerBy: ["hover", "focus"], content: tabTooltipText, anchor: _jsx(ButtonDisabledFocusableWrapper, { isDisabled: isTabAddButtonDisabled, ariaLabel: tabTooltipText, onRefSet: (element) => setAddFilterButtonRefs(element, buttonRef), children: _jsx(UiIconButton, { icon: "plus", label: tabTooltipText, onClick: onClick, variant: "tertiary", isDisabled: isTabAddButtonDisabled, ref: (element) => {
@@ -136,7 +138,7 @@ export function AutomationFiltersSelect({ availableFilters = [], selectedFilters
136
138
  }), isExpanded || !isExpandable ? (_jsx(AttributesDropdown, { id: AUTOMATION_FILTERS_DIALOG_ID, onClose: () => { }, onSelect: (value) => {
137
139
  handleAddFilter(value, attributes, dateDatasets);
138
140
  setIsExpanded(true);
139
- }, attributes: attributes, dateDatasets: dateDatasets, openOnInit: false, overlayPositionType: overlayPositionType, className: "gd-automation-filters__dropdown s-automation-filters-add-filter-dropdown", getCustomItemTitle: (item) => getCatalogItemCustomTitle(item, availableFilters, dateConfigs), accessibilityConfig: {
141
+ }, attributes: attributes, dateDatasets: dateDatasets, measures: measures, openOnInit: false, overlayPositionType: overlayPositionType, className: "gd-automation-filters__dropdown s-automation-filters-add-filter-dropdown", getCustomItemTitle: (item) => getCatalogItemCustomTitle(item, availableFilters, dateConfigs), accessibilityConfig: {
140
142
  ariaLabelledBy: AUTOMATION_FILTERS_DIALOG_TITLE_ID,
141
143
  searchAriaLabel: searchAriaLabel,
142
144
  }, DropdownButtonComponent: ({ buttonRef, isOpen, onClick }) => (_jsx(UiTooltip, { arrowPlacement: "left", triggerBy: ["hover", "focus"], content: tooltipText, anchor: _jsx(ButtonDisabledFocusableWrapper, { isDisabled: isAddButtonDisabled, ariaLabel: tooltipText, onRefSet: (element) => setAddFilterButtonRefs(element, buttonRef), children: _jsx(UiIconButton, { icon: "plus", label: tooltipText, onClick: onClick, variant: "tertiary", isDisabled: isAddButtonDisabled, ref: (element) => {
@@ -170,6 +172,10 @@ function AutomationFilter({ filter, attributeConfigs, onChange, onDelete, isComm
170
172
  const isLocked = lockedFilters.some((f) => dashboardFilterLocalIdentifier(f) === dashboardFilterLocalIdentifier(filter));
171
173
  return (_jsx(AutomationDateFilter, { filter: filter, onChange: onChange, onDelete: onDelete, isLocked: isLocked, isCommonDateFilter: isCommonDateFilter, overlayPositionType: overlayPositionType, readonly: isReadOnly, tabId: tabId }, filter.dateFilter.localIdentifier));
172
174
  }
175
+ else if (isDashboardMeasureValueFilter(filter)) {
176
+ const isLocked = lockedFilters.some((f) => dashboardFilterLocalIdentifier(f) === dashboardFilterLocalIdentifier(filter));
177
+ return (_jsx(AutomationMeasureValueFilter, { filter: filter, onChange: onChange, onDelete: onDelete, isLocked: isLocked, overlayPositionType: overlayPositionType, readonly: isReadOnly }, filter.dashboardMeasureValueFilter.localIdentifier));
178
+ }
173
179
  return null;
174
180
  }
175
181
  /**
@@ -0,0 +1,10 @@
1
+ import { type FilterContextItem, type IDashboardMeasureValueFilter } from "@gooddata/sdk-model";
2
+ import { type OverlayPositionType } from "@gooddata/sdk-ui-kit";
3
+ export declare function AutomationMeasureValueFilter({ filter, onChange, onDelete, isLocked, overlayPositionType, readonly }: {
4
+ filter: IDashboardMeasureValueFilter;
5
+ onChange: (filter: FilterContextItem) => void;
6
+ onDelete: (filter: FilterContextItem) => void;
7
+ isLocked?: boolean;
8
+ overlayPositionType?: OverlayPositionType;
9
+ readonly?: boolean;
10
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,66 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useCallback } from "react";
4
+ import { useIntl } from "react-intl";
5
+ import { MeasureValueFilter } from "@gooddata/sdk-ui-filters";
6
+ import { UiChip, UiTooltip, isActionKey, useIdPrefixed, } from "@gooddata/sdk-ui-kit";
7
+ import { getSharedDashboardMvfProps, normalizeMeasureValueFilterConditions, useDashboardMeasureValueFilterData, } from "../../filterBar/measureValueFilter/useDashboardMeasureValueFilterData.js";
8
+ import { AutomationMeasureValueFilterProvider, useAutomationMeasureValueFilterContext, } from "./AutomationMeasureValueFilterContext.js";
9
+ export function AutomationMeasureValueFilter({ filter, onChange, onDelete, isLocked, overlayPositionType, readonly, }) {
10
+ const intl = useIntl();
11
+ const deleteAriaLabel = intl.formatMessage({ id: "dialogs.automation.filters.deleteAriaLabel" });
12
+ const deleteTooltipContent = intl.formatMessage({ id: "dialogs.automation.filters.deleteTooltip" });
13
+ const lockedTooltipContent = intl.formatMessage({ id: "dialogs.automation.filters.lockedTooltip" });
14
+ // Automation/scheduling has no "Apply together" working filter — just reflect the persisted filter.
15
+ const mvfData = useDashboardMeasureValueFilterData(filter);
16
+ const { conditionLabel } = mvfData;
17
+ const handleApply = useCallback((updated) => {
18
+ const newConditions = normalizeMeasureValueFilterConditions(updated);
19
+ const next = {
20
+ dashboardMeasureValueFilter: {
21
+ ...filter.dashboardMeasureValueFilter,
22
+ ...(newConditions && newConditions.length > 0
23
+ ? { conditions: newConditions }
24
+ : { conditions: undefined }),
25
+ },
26
+ };
27
+ onChange(next);
28
+ }, [filter, onChange]);
29
+ return (_jsx(AutomationMeasureValueFilterProvider, { filter: filter, onChange: onChange, onDelete: onDelete, isLocked: isLocked, deleteAriaLabel: deleteAriaLabel, deleteTooltipContent: deleteTooltipContent, lockedTooltipContent: lockedTooltipContent, children: _jsx(MeasureValueFilter, { ...getSharedDashboardMvfProps(mvfData), onApply: handleApply, DropdownButtonComponent: (props) => (_jsx(AutomationMeasureValueFilterButton, { ...props, conditionLabel: conditionLabel, overlayPositionType: overlayPositionType, readonly: readonly })) }) }));
30
+ }
31
+ function AutomationMeasureValueFilterButton({ isActive, buttonTitle, onClick, conditionLabel, readonly, }) {
32
+ const { isLocked, onDelete, filter, deleteAriaLabel, deleteTooltipContent, lockedTooltipContent } = useAutomationMeasureValueFilterContext();
33
+ const label = `${buttonTitle}: ${conditionLabel}`;
34
+ const mvfTooltipId = useIdPrefixed("mvf-filter-tooltip");
35
+ const mvfDeleteTooltipId = useIdPrefixed("mvf-filter-delete-tooltip");
36
+ const tooltipContent = (_jsxs(_Fragment, { children: [label, isLocked ? _jsx("div", { children: lockedTooltipContent }) : null] }));
37
+ // The whole-panel disabled state is handled by a visual overlay in
38
+ // AutomationFiltersSelect (`gd-automation-filters__overlay`), so the chip should not
39
+ // claim a locked state from it. The lock icon only reflects the filter's own config.
40
+ const isDeletable = !isLocked && !readonly;
41
+ return (_jsx(UiChip, { label: label, iconBefore: "metric", isActive: isActive, isLocked: isLocked, isDeletable: isDeletable, onClick: onClick, onDelete: () => onDelete?.(filter), onKeyDown: (event) => {
42
+ // In case the button is locked and not disabled we need to explicitly
43
+ // stop the event propagation to prevent dropdown from opening
44
+ if (isLocked && isActionKey(event)) {
45
+ event.stopPropagation();
46
+ }
47
+ }, onDeleteKeyDown: (event) => {
48
+ // Do not propagate event to parent as MVF dropdown would always open
49
+ if (isActionKey(event)) {
50
+ event.stopPropagation();
51
+ }
52
+ }, accessibilityConfig: {
53
+ isExpanded: isActive,
54
+ popupType: "dialog",
55
+ ariaDescribedBy: mvfTooltipId,
56
+ deleteAriaLabel: buttonTitle ? `${deleteAriaLabel} ${buttonTitle}` : deleteAriaLabel,
57
+ deleteAriaDescribedBy: mvfDeleteTooltipId,
58
+ }, renderChipContent: (content) => (_jsx(UiTooltip, { id: mvfTooltipId, arrowPlacement: "top-start", content: tooltipContent, triggerBy: ["hover", "focus"], anchor: content, anchorWrapperStyles: {
59
+ display: "flex",
60
+ width: "100%",
61
+ height: "100%",
62
+ minWidth: 0,
63
+ } })), renderDeleteButton: (button) => (_jsx(UiTooltip, { id: mvfDeleteTooltipId, arrowPlacement: "top-start", content: deleteTooltipContent, triggerBy: ["hover", "focus"], anchor: button, anchorWrapperStyles: {
64
+ height: "100%",
65
+ } })) }));
66
+ }
@@ -0,0 +1,25 @@
1
+ import { type ReactNode } from "react";
2
+ import { type FilterContextItem, type IDashboardMeasureValueFilter } from "@gooddata/sdk-model";
3
+ /**
4
+ * @internal
5
+ */
6
+ export interface IAutomationMeasureValueFilterContext {
7
+ onChange: (filter: FilterContextItem) => void;
8
+ onDelete: (filter: FilterContextItem) => void;
9
+ filter: IDashboardMeasureValueFilter;
10
+ isLocked?: boolean;
11
+ deleteAriaLabel?: string;
12
+ deleteTooltipContent?: string;
13
+ lockedTooltipContent?: string;
14
+ }
15
+ /**
16
+ * @internal
17
+ */
18
+ export declare const useAutomationMeasureValueFilterContext: () => IAutomationMeasureValueFilterContext;
19
+ export interface IAutomationMeasureValueFilterProviderProps extends IAutomationMeasureValueFilterContext {
20
+ children: ReactNode;
21
+ }
22
+ /**
23
+ * @internal
24
+ */
25
+ export declare function AutomationMeasureValueFilterProvider({ children, onChange, onDelete, isLocked, filter, deleteAriaLabel, deleteTooltipContent, lockedTooltipContent }: IAutomationMeasureValueFilterProviderProps): import("react/jsx-runtime").JSX.Element;