@gooddata/sdk-ui-ext 11.52.0-alpha.4 → 11.52.0-alpha.6

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 (41) hide show
  1. package/NOTICE +22 -22
  2. package/esm/insightView/InsightRenderer.d.ts +5 -5
  3. package/esm/insightView/InsightRenderer.d.ts.map +1 -1
  4. package/esm/insightView/InsightRenderer.js +164 -140
  5. package/esm/internal/components/configurationControls/conditionalFormatting/CfDateValueDropdown.d.ts +3 -4
  6. package/esm/internal/components/configurationControls/conditionalFormatting/CfDateValueDropdown.d.ts.map +1 -1
  7. package/esm/internal/components/configurationControls/conditionalFormatting/CfDateValueDropdown.js +9 -7
  8. package/esm/internal/components/configurationControls/conditionalFormatting/ConditionEditor.d.ts.map +1 -1
  9. package/esm/internal/components/configurationControls/conditionalFormatting/ConditionEditor.js +57 -37
  10. package/esm/internal/components/configurationControls/conditionalFormatting/cfFieldProps.d.ts +12 -0
  11. package/esm/internal/components/configurationControls/conditionalFormatting/cfFieldProps.d.ts.map +1 -0
  12. package/esm/internal/components/configurationControls/conditionalFormatting/cfFieldProps.js +2 -0
  13. package/esm/internal/components/configurationControls/conditionalFormatting/conditionalFormattingModel.d.ts +10 -10
  14. package/esm/internal/components/configurationControls/conditionalFormatting/conditionalFormattingModel.d.ts.map +1 -1
  15. package/esm/internal/components/configurationControls/conditionalFormatting/conditionalFormattingModel.js +11 -11
  16. package/esm/internal/components/configurationPanels/PivotTableConfigurationPanel.d.ts.map +1 -1
  17. package/esm/internal/components/configurationPanels/PivotTableConfigurationPanel.js +2 -1
  18. package/esm/internal/components/pluggableVisualizations/mekko/PluggableMekko.d.ts.map +1 -1
  19. package/esm/internal/components/pluggableVisualizations/mekko/PluggableMekko.js +14 -1
  20. package/esm/internal/components/pluggableVisualizations/pivotTableNext/PivotTableNextDescriptor.d.ts.map +1 -1
  21. package/esm/internal/components/pluggableVisualizations/pivotTableNext/PivotTableNextDescriptor.js +2 -9
  22. package/esm/internal/components/pluggableVisualizations/pivotTableNext/PluggablePivotTableNext.d.ts.map +1 -1
  23. package/esm/internal/components/pluggableVisualizations/pivotTableNext/PluggablePivotTableNext.js +2 -2
  24. package/esm/internal/components/pluggableVisualizations/pivotTableNext/pivotTableNextConfigFromInsight.d.ts +8 -3
  25. package/esm/internal/components/pluggableVisualizations/pivotTableNext/pivotTableNextConfigFromInsight.d.ts.map +1 -1
  26. package/esm/internal/components/pluggableVisualizations/pivotTableNext/pivotTableNextConfigFromInsight.js +41 -37
  27. package/esm/internal/translations/en-US.localization-bundle.d.ts +8 -0
  28. package/esm/internal/translations/en-US.localization-bundle.d.ts.map +1 -1
  29. package/esm/internal/translations/en-US.localization-bundle.js +8 -0
  30. package/esm/internal/utils/bucketHelper.d.ts.map +1 -1
  31. package/esm/internal/utils/bucketHelper.js +7 -14
  32. package/esm/internal/utils/embeddingCodeGenerator/insightToPropsConverter/convertor.d.ts +2 -2
  33. package/esm/internal/utils/embeddingCodeGenerator/insightToPropsConverter/convertor.d.ts.map +1 -1
  34. package/esm/internal/utils/embeddingCodeGenerator/insightToPropsConverter/convertor.js +4 -2
  35. package/esm/internal/utils/propertiesHelper.d.ts +5 -0
  36. package/esm/internal/utils/propertiesHelper.d.ts.map +1 -1
  37. package/esm/internal/utils/propertiesHelper.js +7 -0
  38. package/esm/locales.d.ts +6 -0
  39. package/esm/locales.d.ts.map +1 -1
  40. package/esm/locales.js +2 -0
  41. package/package.json +21 -21
package/NOTICE CHANGED
@@ -7,9 +7,9 @@
7
7
 
8
8
  The following 3rd-party software packages may be used by or distributed with gooddata-ui-sdk. Any information relevant to third-party vendors listed below are collected using common, reasonable means.
9
9
 
10
- Date generated: 2026-8-7
10
+ Date generated: 2026-8-10
11
11
 
12
- Revision ID: 81ef8e705df7e83197c71d5bca4ff1d157c580f3
12
+ Revision ID: df24fd6388dc31e841cd593b9a048731ec44afec
13
13
 
14
14
  ================================================================================
15
15
  ================================================================================
@@ -373,7 +373,7 @@ Revision ID: 81ef8e705df7e83197c71d5bca4ff1d157c580f3
373
373
  - balanced-match (2.0.0) [MIT]
374
374
  - balanced-match (4.0.4) [MIT]
375
375
  - base64-js (1.5.1) [MIT]
376
- - baseline-browser-mapping (2.11.4) [Apache-2.0]
376
+ - baseline-browser-mapping (2.11.13) [Apache-2.0]
377
377
  - batch (0.6.1) [MIT]
378
378
  - binary-extensions (2.3.0) [MIT]
379
379
  - bl (4.1.0) [MIT]
@@ -382,7 +382,7 @@ Revision ID: 81ef8e705df7e83197c71d5bca4ff1d157c580f3
382
382
  - brace-expansion (1.1.16) [MIT]
383
383
  - brace-expansion (5.0.8) [MIT]
384
384
  - braces (3.0.3) [MIT]
385
- - browserslist (4.28.7) [MIT]
385
+ - browserslist (4.28.8) [MIT]
386
386
  - buffer (5.7.1) [MIT]
387
387
  - buffer-from (1.1.2) [MIT]
388
388
  - bundle-name (4.1.0) [MIT]
@@ -394,7 +394,7 @@ Revision ID: 81ef8e705df7e83197c71d5bca4ff1d157c580f3
394
394
  - call-bind-apply-helpers (1.0.2) [MIT]
395
395
  - call-bound (1.0.4) [MIT]
396
396
  - callsites (3.1.0) [MIT]
397
- - caniuse-lite (1.0.30001806) [CC-BY-4.0]
397
+ - caniuse-lite (1.0.30001809) [CC-BY-4.0]
398
398
  - ccount (2.0.1) [MIT]
399
399
  - chalk (5.3.0) [MIT]
400
400
  - chalk (4.1.2) [MIT]
@@ -487,7 +487,7 @@ Revision ID: 81ef8e705df7e83197c71d5bca4ff1d157c580f3
487
487
  - earcut (2.2.4) [ISC]
488
488
  - earcut (3.2.3) [ISC]
489
489
  - ee-first (1.1.1) [MIT]
490
- - electron-to-chromium (1.5.396) [ISC]
490
+ - electron-to-chromium (1.5.403) [ISC]
491
491
  - emailjs-base64 (1.1.4) [MIT]
492
492
  - emoji-regex (8.0.0) [MIT]
493
493
  - emojilib (2.4.0) [MIT]
@@ -775,7 +775,7 @@ Revision ID: 81ef8e705df7e83197c71d5bca4ff1d157c580f3
775
775
  - negotiator (0.6.4) [MIT]
776
776
  - neo-async (2.6.2) [MIT]
777
777
  - node-emoji (2.2.0) [MIT]
778
- - node-releases (2.0.51) [MIT]
778
+ - node-releases (2.0.53) [MIT]
779
779
  - normalize-path (3.0.0) [MIT]
780
780
  - object-assign (4.1.1) [MIT]
781
781
  - object-code (2.0.0) [MIT]
@@ -1017,7 +1017,7 @@ Revision ID: 81ef8e705df7e83197c71d5bca4ff1d157c580f3
1017
1017
  - unist-util-visit-parents (6.0.2) [MIT]
1018
1018
  - universalify (2.0.1) [MIT]
1019
1019
  - unpipe (1.0.0) [MIT]
1020
- - update-browserslist-db (1.2.3) [MIT]
1020
+ - update-browserslist-db (1.3.0) [MIT]
1021
1021
  - use-composed-ref (1.4.0) [MIT]
1022
1022
  - use-is-mounted-ref (1.5.0) [MIT]
1023
1023
  - use-isomorphic-layout-effect (1.2.1) [MIT]
@@ -5277,9 +5277,9 @@ MIT
5277
5277
 
5278
5278
 
5279
5279
  --------------------------------------------------------------------------------
5280
- Package Title: baseline-browser-mapping (2.11.4)
5280
+ Package Title: baseline-browser-mapping (2.11.13)
5281
5281
 
5282
- Package Locator: npm+baseline-browser-mapping$2.11.4
5282
+ Package Locator: npm+baseline-browser-mapping$2.11.13
5283
5283
 
5284
5284
  Package Depth: Transitive
5285
5285
  --------------------------------------------------------------------------------
@@ -5385,9 +5385,9 @@ MIT
5385
5385
 
5386
5386
 
5387
5387
  --------------------------------------------------------------------------------
5388
- Package Title: browserslist (4.28.7)
5388
+ Package Title: browserslist (4.28.8)
5389
5389
 
5390
- Package Locator: npm+browserslist$4.28.7
5390
+ Package Locator: npm+browserslist$4.28.8
5391
5391
 
5392
5392
  Package Depth: Transitive
5393
5393
  --------------------------------------------------------------------------------
@@ -5529,9 +5529,9 @@ MIT
5529
5529
 
5530
5530
 
5531
5531
  --------------------------------------------------------------------------------
5532
- Package Title: caniuse-lite (1.0.30001806)
5532
+ Package Title: caniuse-lite (1.0.30001809)
5533
5533
 
5534
- Package Locator: npm+caniuse-lite$1.0.30001806
5534
+ Package Locator: npm+caniuse-lite$1.0.30001809
5535
5535
 
5536
5536
  Package Depth: Transitive
5537
5537
  --------------------------------------------------------------------------------
@@ -6649,9 +6649,9 @@ MIT
6649
6649
 
6650
6650
 
6651
6651
  --------------------------------------------------------------------------------
6652
- Package Title: electron-to-chromium (1.5.396)
6652
+ Package Title: electron-to-chromium (1.5.403)
6653
6653
 
6654
- Package Locator: npm+electron-to-chromium$1.5.396
6654
+ Package Locator: npm+electron-to-chromium$1.5.403
6655
6655
 
6656
6656
  Package Depth: Transitive
6657
6657
  --------------------------------------------------------------------------------
@@ -10123,9 +10123,9 @@ MIT
10123
10123
 
10124
10124
 
10125
10125
  --------------------------------------------------------------------------------
10126
- Package Title: node-releases (2.0.51)
10126
+ Package Title: node-releases (2.0.53)
10127
10127
 
10128
- Package Locator: npm+node-releases$2.0.51
10128
+ Package Locator: npm+node-releases$2.0.53
10129
10129
 
10130
10130
  Package Depth: Transitive
10131
10131
  --------------------------------------------------------------------------------
@@ -13081,9 +13081,9 @@ MIT
13081
13081
 
13082
13082
 
13083
13083
  --------------------------------------------------------------------------------
13084
- Package Title: update-browserslist-db (1.2.3)
13084
+ Package Title: update-browserslist-db (1.3.0)
13085
13085
 
13086
- Package Locator: npm+update-browserslist-db$1.2.3
13086
+ Package Locator: npm+update-browserslist-db$1.3.0
13087
13087
 
13088
13088
  Package Depth: Transitive
13089
13089
  --------------------------------------------------------------------------------
@@ -28551,7 +28551,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28551
28551
 
28552
28552
  The MIT License (MIT)
28553
28553
 
28554
- Copyright 2022 Andrey Sitnik <andrey@sitnik.ru> and other contributors
28554
+ Copyright 2022 Andrey Sitnik <andrey@sitnik.es> and other contributors
28555
28555
 
28556
28556
  Permission is hereby granted, free of charge, to any person obtaining a copy of
28557
28557
  this software and associated documentation files (the "Software"), to deal in
@@ -29357,4 +29357,4 @@ POSSIBILITY OF SUCH DAMAGE.
29357
29357
  --------------------------------------------------------------------------------
29358
29358
  --------------------------------------------------------------------------------
29359
29359
 
29360
- Report Generated by FOSSA on 2026-8-7
29360
+ Report Generated by FOSSA on 2026-8-10
@@ -21,12 +21,11 @@ export interface IInsightRendererProps extends Omit<IInsightViewProps, "insight"
21
21
  */
22
22
  widget?: IInsightWidget;
23
23
  }
24
- export declare const IntlInsightRenderer: import("react").FC<import("react-intl").WithIntlProps<Omit<IInsightRendererProps & WrappedComponentProps & {
24
+ type InsightRendererCoreProps = IInsightRendererProps & WrappedComponentProps & {
25
25
  messages: ITranslations;
26
- }, "theme" | "themeIsLoading" | "themeStatus">>> & {
27
- WrappedComponent: import("react").ComponentType<Omit<IInsightRendererProps & WrappedComponentProps & {
28
- messages: ITranslations;
29
- }, "theme" | "themeIsLoading" | "themeStatus">>;
26
+ };
27
+ export declare const IntlInsightRenderer: import("react").FC<import("react-intl").WithIntlProps<Omit<InsightRendererCoreProps, "theme" | "themeIsLoading" | "themeStatus">>> & {
28
+ WrappedComponent: import("react").ComponentType<Omit<InsightRendererCoreProps, "theme" | "themeIsLoading" | "themeStatus">>;
30
29
  };
31
30
  /**
32
31
  * Renders insight passed as a parameter.
@@ -34,4 +33,5 @@ export declare const IntlInsightRenderer: import("react").FC<import("react-intl"
34
33
  * @internal
35
34
  */
36
35
  export declare function InsightRenderer(props: IInsightRendererProps): import("react/jsx-runtime").JSX.Element | null;
36
+ export {};
37
37
  //# sourceMappingURL=InsightRenderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"InsightRenderer.d.ts","sourceRoot":"","sources":["../../src/insightView/InsightRenderer.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,qBAAqB,EAAc,MAAM,YAAY,CAAC;AAOpE,OAAO,EAGH,KAAK,sBAAsB,EAC9B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACH,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,MAAM,EACX,KAAK,qBAAqB,EAM7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAKH,KAAK,OAAO,EACZ,KAAK,aAAa,EAGlB,KAAK,OAAO,EAMf,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAGH,KAAK,iBAAiB,EAIzB,MAAM,sBAAsB,CAAC;AAE9B;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAC/C,iBAAiB,EACjB,SAAS,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,WAAW,CACjE;IACG,OAAO,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACxC,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,sBAAsB,GAAG,SAAS,CAAC;IAC7C,WAAW,CAAC,EAAE,qBAAqB,CAAC;IACpC,YAAY,EAAE,aAAa,GAAG,SAAS,CAAC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB;;;OAGG;IACH,MAAM,CAAC,EAAE,cAAc,CAAC;CAC3B;AA+RD,eAAO,MAAM,mBAAmB;;;;;;CAA2D,CAAC;AAwB5F;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,qBAAqB,kDAuC3D"}
1
+ {"version":3,"file":"InsightRenderer.d.ts","sourceRoot":"","sources":["../../src/insightView/InsightRenderer.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,qBAAqB,EAAc,MAAM,YAAY,CAAC;AAOpE,OAAO,EAGH,KAAK,sBAAsB,EAC9B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACH,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,MAAM,EACX,KAAK,qBAAqB,EAM7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAKH,KAAK,OAAO,EACZ,KAAK,aAAa,EAGlB,KAAK,OAAO,EAMf,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAGH,KAAK,iBAAiB,EAKzB,MAAM,sBAAsB,CAAC;AAE9B;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAC/C,iBAAiB,EACjB,SAAS,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,WAAW,CACjE;IACG,OAAO,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACxC,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,sBAAsB,GAAG,SAAS,CAAC;IAC7C,WAAW,CAAC,EAAE,qBAAqB,CAAC;IACpC,YAAY,EAAE,aAAa,GAAG,SAAS,CAAC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB;;;OAGG;IACH,MAAM,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,KAAK,wBAAwB,GAAG,qBAAqB,GAAG,qBAAqB,GAAG;IAAE,QAAQ,EAAE,aAAa,CAAA;CAAE,CAAC;AAuV5G,eAAO,MAAM,mBAAmB;;CAA2D,CAAC;AAwB5F;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,qBAAqB,kDAuC3D"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  // (C) 2020-2026 GoodData Corporation
3
- import { PureComponent, createRef, useCallback, useEffect, useRef } from "react";
3
+ import { memo, useCallback, useEffect, useRef, useState } from "react";
4
4
  import { isEqual } from "lodash-es";
5
5
  import { createRoot } from "react-dom/client";
6
6
  import { injectIntl } from "react-intl";
@@ -17,58 +17,95 @@ const visualizationUriRootStyle = {
17
17
  flex: "1 1 auto",
18
18
  flexDirection: "column",
19
19
  };
20
- // this needs to be a pure component as it can happen that this might be rendered multiple times
20
+ const noop = () => { };
21
+ const defaultFilters = [];
22
+ const defaultDrillableItems = [];
23
+ /**
24
+ * Applies the defaults on the props. The values used as defaults are referentially stable so that they do not
25
+ * trigger any unnecessary work down the line.
26
+ */
27
+ const resolveProps = (props) => ({
28
+ ...props,
29
+ ErrorComponent: props.ErrorComponent ?? ErrorComponent,
30
+ filters: props.filters ?? defaultFilters,
31
+ drillableItems: props.drillableItems ?? defaultDrillableItems,
32
+ LoadingComponent: props.LoadingComponent ?? LoadingComponent,
33
+ pushData: props.pushData ?? noop,
34
+ locale: props.locale ?? DefaultLocale,
35
+ afterRender: props.afterRender ?? noop,
36
+ });
37
+ // this needs to be a memoized component as it can happen that this might be rendered multiple times
21
38
  // with the same props (referentially) - this might make the rendered visualization behave unpredictably
22
39
  // and is bad for performance so we need to make sure the re-renders are performed only if necessary
23
- class InsightRendererCore extends PureComponent {
24
- elementId = getElementId();
25
- visualization;
26
- containerRef = createRef();
40
+ const InsightRendererCore = memo(function InsightRendererCore(props) {
41
+ const currentProps = resolveProps(props);
42
+ const [elementId] = useState(getElementId);
43
+ const visualizationRef = useRef(undefined);
44
+ const containerRef = useRef(null);
27
45
  /**
28
46
  * The component may render both visualization and config panel. In React18 we therefore need two
29
47
  * roots with their respective render methods. This Map holds the roots for both and provides
30
48
  * render and unmount methods whenever needed.
31
49
  */
32
- reactRootsMap = new Map();
33
- static defaultProps = {
34
- ErrorComponent,
35
- filters: [],
36
- drillableItems: [],
37
- LoadingComponent,
38
- pushData: () => { },
39
- locale: DefaultLocale,
40
- afterRender: () => { },
41
- };
42
- unmountVisualization = () => {
43
- if (this.visualization) {
44
- this.visualization.unmount();
50
+ const reactRootsMapRef = useRef(new Map());
51
+ /**
52
+ * The callbacks and element getters below outlive the render they were created in (the visualization
53
+ * instance only ever gets the ones from the render it was set up in). They therefore read the props from
54
+ * this ref to always see the current values - the very same way `this.props` did before.
55
+ *
56
+ * This effect must stay first so that the ref is up to date before any other effect runs.
57
+ */
58
+ const propsRef = useRef(currentProps);
59
+ useEffect(() => {
60
+ propsRef.current = currentProps;
61
+ });
62
+ const unmountVisualization = useCallback(() => {
63
+ if (visualizationRef.current) {
64
+ visualizationRef.current.unmount();
65
+ }
66
+ visualizationRef.current = undefined;
67
+ }, []);
68
+ const getExecutionFactory = useCallback(() => {
69
+ const { backend, workspace, executeByReference, filters } = propsRef.current;
70
+ const factory = backend.workspace(workspace).execution();
71
+ if (executeByReference) {
72
+ /*
73
+ * When executing by reference, decorate the original execution factory so that it
74
+ * transparently routes `forInsight` to `forInsightByRef` AND adds the filters
75
+ * from InsightView props.
76
+ *
77
+ * Code will pass this factory over to the pluggable visualizations - they will do execution
78
+ * `forInsight` and under the covers things will be routed and done differently without the
79
+ * plug viz knowing.
80
+ */
81
+ return new ExecutionFactoryUpgradingToExecByReference(new ExecutionFactoryWithFixedFilters(factory, filters));
45
82
  }
46
- this.visualization = undefined;
47
- };
48
- updateVisualization = () => {
83
+ return factory;
84
+ }, []);
85
+ const updateVisualization = useCallback(() => {
49
86
  // if the container no longer exists, update was called after unmount -> do nothing
50
- if (!this.visualization || !this.containerRef.current) {
87
+ if (!visualizationRef.current || !containerRef.current) {
51
88
  return;
52
89
  }
90
+ const { insight: insightProp, config = {}, settings, locale, messages, widget, drillableItems, colorPalette, execConfig, theme, } = propsRef.current;
53
91
  // if there is no insight, bail early
54
- if (!this.props.insight) {
92
+ if (!insightProp) {
55
93
  return;
56
94
  }
57
- const { config = {} } = this.props;
58
- const { responsiveUiDateFormat } = this.props.settings ?? {};
95
+ const { responsiveUiDateFormat } = settings ?? {};
59
96
  const visProps = {
60
- locale: this.props.locale,
61
- messages: this.props.messages,
97
+ locale,
98
+ messages,
62
99
  dateFormat: responsiveUiDateFormat,
63
- a11yTitle: this.props.widget?.title,
64
- a11yDescription: this.props.widget?.description,
100
+ a11yTitle: widget?.title,
101
+ a11yDescription: widget?.description,
65
102
  custom: {
66
- drillableItems: this.props.drillableItems,
67
- lastSavedVisClassUrl: insightVisualizationUrl(this.props.insight),
103
+ drillableItems,
104
+ lastSavedVisClassUrl: insightVisualizationUrl(insightProp),
68
105
  },
69
106
  config: {
70
107
  separators: config.separators,
71
- colorPalette: this.props.colorPalette,
108
+ colorPalette,
72
109
  mapboxToken: config.mapboxToken,
73
110
  agGridToken: config.agGridToken,
74
111
  forceDisableDrillOnAxes: config.forceDisableDrillOnAxes,
@@ -76,13 +113,13 @@ class InsightRendererCore extends PureComponent {
76
113
  isExportMode: config.isExportMode,
77
114
  enableExecutionCancelling: config.enableExecutionCancelling,
78
115
  },
79
- executionConfig: this.props.execConfig,
116
+ executionConfig: execConfig,
80
117
  customVisualizationConfig: config,
81
- theme: this.props.theme,
118
+ theme,
82
119
  supportsChartFill: config.supportsChartFill,
83
120
  };
84
- const visClass = insightVisualizationType(this.props.insight);
85
- const filled = fillMissingTitlesWithMessages(this.props.insight, this.props.locale, this.props.messages, undefined);
121
+ const visClass = insightVisualizationType(insightProp);
122
+ const filled = fillMissingTitlesWithMessages(insightProp, locale, messages, undefined);
86
123
  let insight = fillMissingFormats(filled);
87
124
  /**
88
125
  * Ignore titles for simple measures in all visualizations except for repeater.
@@ -95,29 +132,60 @@ class InsightRendererCore extends PureComponent {
95
132
  if (visClass !== "repeater") {
96
133
  insight = ignoreTitlesForSimpleMeasures(insight);
97
134
  }
98
- this.visualization?.update(visProps, insight, {}, this.getExecutionFactory());
99
- };
100
- setupVisualization = () => {
135
+ visualizationRef.current?.update(visProps, insight, {}, getExecutionFactory());
136
+ }, [getExecutionFactory]);
137
+ const reactRenderFunction = useCallback((children, element) => {
138
+ if (!element) {
139
+ return;
140
+ }
141
+ const htmlElement = element;
142
+ if (!reactRootsMapRef.current.get(htmlElement)) {
143
+ reactRootsMapRef.current.set(htmlElement, createRoot(htmlElement));
144
+ }
145
+ reactRootsMapRef.current.get(htmlElement).render(children);
146
+ }, []);
147
+ const reactUnmountFunction = useCallback(() => {
148
+ reactRootsMapRef.current.forEach((root) => root.render(null));
149
+ }, []);
150
+ const onExportReadyDecorator = useCallback((exportFunction) => {
151
+ const { onExportReady } = propsRef.current;
152
+ if (!onExportReady) {
153
+ return;
154
+ }
155
+ const decorator = (exportConfig) => {
156
+ const { insight } = propsRef.current;
157
+ if (exportConfig.title || !insight) {
158
+ return exportFunction(exportConfig);
159
+ }
160
+ return exportFunction({
161
+ ...exportConfig,
162
+ title: insightTitle(insight),
163
+ });
164
+ };
165
+ onExportReady(decorator);
166
+ }, []);
167
+ const setupVisualization = useCallback(() => {
168
+ const { insight, settings, backend, workspace, permissions, locale, messages, pushData, onDrill, onDataView, onLoadingChanged, afterRender, } = propsRef.current;
101
169
  // if there is no insight, bail early
102
- if (!this.props.insight) {
170
+ if (!insight) {
103
171
  return;
104
172
  }
105
173
  // the visualization we may have from earlier is no longer valid -> get rid of it
106
- this.unmountVisualization();
107
- const visualizationFactory = FullVisualizationCatalog.forInsight(this.props.insight, this.props.settings?.enableNewPivotTable ?? true, this.props.settings?.enableNewGeoPushpin ?? false).getFactory();
108
- this.visualization = visualizationFactory({
109
- backend: this.props.backend,
174
+ unmountVisualization();
175
+ const visualizationFactory = FullVisualizationCatalog.forInsight(insight, settings?.enableNewPivotTable ?? true, settings?.enableNewGeoPushpin ?? false).getFactory();
176
+ visualizationRef.current = visualizationFactory({
177
+ backend: backend,
110
178
  callbacks: {
111
179
  onError: (error) => {
112
- this.props.onError?.(error);
113
- this.props.onLoadingChanged?.({ isLoading: false });
180
+ propsRef.current.onError?.(error);
181
+ propsRef.current.onLoadingChanged?.({ isLoading: false });
114
182
  },
115
- onLoadingChanged: this.props.onLoadingChanged,
116
- pushData: this.props.pushData,
117
- onDrill: this.props.onDrill,
118
- onDataView: this.props.onDataView,
119
- onExportReady: this.onExportReadyDecorator,
120
- afterRender: this.props.afterRender,
183
+ onLoadingChanged,
184
+ pushData,
185
+ onDrill,
186
+ onDataView,
187
+ onExportReady: onExportReadyDecorator,
188
+ afterRender,
121
189
  },
122
190
  // This renderer has no configuration panel of its own — it renders read-only insights.
123
191
  // It used to resolve the panel with a document-wide lookup of the well-known
@@ -130,106 +198,62 @@ class InsightRendererCore extends PureComponent {
130
198
  // fix STL-3184
131
199
  configPanelElement: () => null,
132
200
  element: () => {
133
- const rootNode = this.containerRef.current?.getRootNode() ?? document;
134
- return rootNode.querySelector(`#${this.elementId}`);
201
+ const rootNode = containerRef.current?.getRootNode() ?? document;
202
+ return rootNode.querySelector(`#${elementId}`);
135
203
  },
136
204
  environment: "dashboards", // TODO get rid of this
137
- locale: this.props.locale,
138
- messages: this.props.messages,
139
- projectId: this.props.workspace,
140
- visualizationProperties: insightProperties(this.props.insight),
141
- featureFlags: this.props.settings,
142
- permissions: this.props.permissions,
143
- renderFun: this.getReactRenderFunction(),
144
- unmountFun: this.getReactUnmountFunction(),
205
+ locale,
206
+ messages,
207
+ projectId: workspace,
208
+ visualizationProperties: insightProperties(insight),
209
+ featureFlags: settings,
210
+ permissions,
211
+ renderFun: reactRenderFunction,
212
+ unmountFun: reactUnmountFunction,
145
213
  });
146
- };
147
- getReactRenderFunction = () => {
148
- return (children, element) => {
149
- if (!element) {
150
- return;
151
- }
152
- const htmlElement = element;
153
- if (!this.reactRootsMap.get(htmlElement)) {
154
- this.reactRootsMap.set(htmlElement, createRoot(htmlElement));
155
- }
156
- this.reactRootsMap.get(htmlElement).render(children);
157
- };
158
- };
159
- getReactUnmountFunction = () => {
160
- return () => this.reactRootsMap.forEach((root) => root.render(null));
161
- };
162
- onExportReadyDecorator = (exportFunction) => {
163
- if (!this.props.onExportReady) {
214
+ }, [elementId, onExportReadyDecorator, reactRenderFunction, reactUnmountFunction, unmountVisualization]);
215
+ const prevPropsRef = useRef(undefined);
216
+ // componentDidMount & componentDidUpdate: intentionally without dependencies so that it runs after
217
+ // every render of this (memoized) component
218
+ useEffect(() => {
219
+ const prevProps = prevPropsRef.current;
220
+ prevPropsRef.current = currentProps;
221
+ if (!prevProps) {
222
+ setupVisualization();
223
+ updateVisualization();
164
224
  return;
165
225
  }
166
- const decorator = (exportConfig) => {
167
- if (exportConfig.title || !this.props.insight) {
168
- return exportFunction(exportConfig);
169
- }
170
- return exportFunction({
171
- ...exportConfig,
172
- title: insightTitle(this.props.insight),
173
- });
174
- };
175
- this.props.onExportReady(decorator);
176
- };
177
- getExecutionFactory = () => {
178
- const factory = this.props.backend.workspace(this.props.workspace).execution();
179
- if (this.props.executeByReference) {
180
- /*
181
- * When executing by reference, decorate the original execution factory so that it
182
- * transparently routes `forInsight` to `forInsightByRef` AND adds the filters
183
- * from InsightView props.
184
- *
185
- * Code will pass this factory over to the pluggable visualizations - they will do execution
186
- * `forInsight` and under the covers things will be routed and done differently without the
187
- * plug viz knowing.
188
- */
189
- return new ExecutionFactoryUpgradingToExecByReference(new ExecutionFactoryWithFixedFilters(factory, this.props.filters));
190
- }
191
- return factory;
192
- };
193
- componentDidMountInner = () => {
194
- this.setupVisualization();
195
- return this.updateVisualization();
196
- };
197
- componentDidMount() {
198
- this.componentDidMountInner();
199
- }
200
- componentDidUpdateInner = (prevProps) => {
201
226
  /**
202
227
  * Ignore properties when comparing insights to determine if a new setup is needed: changes to properties
203
228
  * only will be handled using the updateVisualization without unnecessary new setup just fine.
204
229
  */
205
230
  const prevInsightForCompare = prevProps.insight && insightSetProperties(prevProps.insight, {});
206
- const newInsightForCompare = this.props.insight && insightSetProperties(this.props.insight, {});
231
+ const newInsightForCompare = currentProps.insight && insightSetProperties(currentProps.insight, {});
207
232
  const needsNewSetup = !isEqual(newInsightForCompare, prevInsightForCompare) ||
208
- !isEqual(this.props.filters, prevProps.filters) ||
209
- !isEqual(this.props.settings, prevProps.settings) ||
210
- this.props.workspace !== prevProps.workspace;
233
+ !isEqual(currentProps.filters, prevProps.filters) ||
234
+ !isEqual(currentProps.settings, prevProps.settings) ||
235
+ currentProps.workspace !== prevProps.workspace;
211
236
  if (needsNewSetup) {
212
- this.setupVisualization();
237
+ setupVisualization();
213
238
  }
214
- return this.updateVisualization();
215
- };
216
- componentDidUpdate(prevProps) {
217
- this.componentDidUpdateInner(prevProps);
218
- }
219
- componentWillUnmount() {
220
- this.unmountVisualization();
221
- // In order to avoid race conditions when mounting and unmounting synchronously,
222
- // we use timeout for React18.
223
- // https://github.com/facebook/react/issues/25675
224
- this.reactRootsMap.forEach((root) => setTimeout(() => root.unmount(), 0));
225
- }
226
- render() {
227
- return (
228
- // never ever dynamically change the props of this div, otherwise bad things will happen
229
- // e.g. visualization being rendered multiple times, etc.
230
- _jsx("div", { className: "visualization-uri-root", id: this.elementId, ref: this.containerRef, style: visualizationUriRootStyle }));
231
- }
232
- }
239
+ updateVisualization();
240
+ });
241
+ // componentWillUnmount
242
+ useEffect(() => {
243
+ const reactRootsMap = reactRootsMapRef.current;
244
+ return () => {
245
+ unmountVisualization();
246
+ // In order to avoid race conditions when mounting and unmounting synchronously,
247
+ // we use timeout for React18.
248
+ // https://github.com/facebook/react/issues/25675
249
+ reactRootsMap.forEach((root) => setTimeout(() => root.unmount(), 0));
250
+ };
251
+ }, [unmountVisualization]);
252
+ return (
253
+ // never ever dynamically change the props of this div, otherwise bad things will happen
254
+ // e.g. visualization being rendered multiple times, etc.
255
+ _jsx("div", { className: "visualization-uri-root", id: elementId, ref: containerRef, style: visualizationUriRootStyle }));
256
+ });
233
257
  export const IntlInsightRenderer = injectIntl(withTheme(withContexts(InsightRendererCore)));
234
258
  /**
235
259
  * Updated callback (callback with a different reference) is not properly propagated to the "visualization" instance
@@ -1,15 +1,14 @@
1
1
  import { type IDateFilterOptionsByType } from "@gooddata/sdk-ui-filters";
2
2
  import { type ConditionalFormattingValue } from "@gooddata/sdk-ui-pivot/next";
3
+ import { type ICfFieldProps } from "./cfFieldProps.js";
3
4
  import { type ICfDateMeta, type ICfDateSettings } from "./conditionalFormattingModel.js";
4
- export interface ICfDateValueDropdownProps {
5
+ export interface ICfDateValueDropdownProps extends ICfFieldProps {
5
6
  value: ConditionalFormattingValue;
6
7
  date: ICfDateMeta;
7
8
  /** Workspace preset catalog (shared with the dashboard date filter); undefined = static only. */
8
9
  catalogOptions?: IDateFilterOptionsByType;
9
10
  /** Workspace date-display settings (format, week start). */
10
11
  dateSettings?: ICfDateSettings;
11
- /** Id of the rendered inline error, associated with the trigger for assistive tech. */
12
- errorId?: string;
13
12
  onChange: (value: ConditionalFormattingValue) => void;
14
13
  }
15
14
  /**
@@ -21,5 +20,5 @@ export interface ICfDateValueDropdownProps {
21
20
  * already-shifted range (no flag), and reopening reconstructs the preset + checked toggle by
22
21
  * matching the stored range against "preset shifted by one".
23
22
  */
24
- export declare function CfDateValueDropdown({ value, date, catalogOptions, dateSettings, errorId, onChange }: ICfDateValueDropdownProps): import("react/jsx-runtime").JSX.Element;
23
+ export declare function CfDateValueDropdown({ value, date, catalogOptions, dateSettings, hasError, errorId, onChange, onVisit }: ICfDateValueDropdownProps): import("react/jsx-runtime").JSX.Element;
25
24
  //# sourceMappingURL=CfDateValueDropdown.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CfDateValueDropdown.d.ts","sourceRoot":"","sources":["../../../../../src/internal/components/configurationControls/conditionalFormatting/CfDateValueDropdown.tsx"],"names":[],"mappings":"AAQA,OAAO,EAKH,KAAK,wBAAwB,EAIhC,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACH,KAAK,0BAA0B,EAKlC,MAAM,6BAA6B,CAAC;AAIrC,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,iCAAiC,CAAC;AA6GzF,MAAM,WAAW,yBAAyB;IACtC,KAAK,EAAE,0BAA0B,CAAC;IAClC,IAAI,EAAE,WAAW,CAAC;IAClB,iGAAiG;IACjG,cAAc,CAAC,EAAE,wBAAwB,CAAC;IAC1C,4DAA4D;IAC5D,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,CAAC;CACzD;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,EAChC,KAAK,EACL,IAAI,EACJ,cAAc,EACd,YAAY,EACZ,OAAO,EACP,QAAQ,EACX,EAAE,yBAAyB,2CA4E3B"}
1
+ {"version":3,"file":"CfDateValueDropdown.d.ts","sourceRoot":"","sources":["../../../../../src/internal/components/configurationControls/conditionalFormatting/CfDateValueDropdown.tsx"],"names":[],"mappings":"AAQA,OAAO,EAKH,KAAK,wBAAwB,EAIhC,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACH,KAAK,0BAA0B,EAKlC,MAAM,6BAA6B,CAAC;AAIrC,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,iCAAiC,CAAC;AA4GzF,MAAM,WAAW,yBAA0B,SAAQ,aAAa;IAC5D,KAAK,EAAE,0BAA0B,CAAC;IAClC,IAAI,EAAE,WAAW,CAAC;IAClB,iGAAiG;IACjG,cAAc,CAAC,EAAE,wBAAwB,CAAC;IAC1C,4DAA4D;IAC5D,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,CAAC;CACzD;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,EAChC,KAAK,EACL,IAAI,EACJ,cAAc,EACd,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,OAAO,EACV,EAAE,yBAAyB,2CA+E3B"}
@@ -65,15 +65,14 @@ function matchStoredValue(value, absoluteForm, filterOptions, granularity) {
65
65
  }
66
66
  return matchDateFilterToDateFilterOptionWithPreference(storedFilter, filterOptions, undefined);
67
67
  }
68
- // DateFilter's button contract is fixed, so the error association travels via context.
68
+ // DateFilter's button contract is fixed, so the error state travels via context.
69
69
  const CfDateButtonA11yContext = createContext({});
70
70
  // Rendered through DateFilter's button slot. Module-level so its identity is stable across renders.
71
71
  // Deliberately NOT wiring props.onClick: DateFilterCore's wrapping span already toggles the dropdown,
72
72
  // so wiring both toggles it twice per click (open → instantly closed).
73
73
  function CfDateButton({ customFilterName, textSubtitle, isOpen, buttonRef, dropdownId, }) {
74
- // describedBy is only set while the value has an inline error — it doubles as the error state.
75
- const { describedBy } = useContext(CfDateButtonA11yContext);
76
- return (_jsx(DropdownButton, { className: cx("gd-cf-date-value", { "gd-cf-date-value--error": describedBy !== undefined }), value: customFilterName ?? textSubtitle, isOpen: isOpen, isFullWidth: true, buttonRef: buttonRef, dropdownId: dropdownId, accessibilityConfig: describedBy ? { ariaDescribedBy: describedBy } : undefined }));
74
+ const { describedBy, hasError } = useContext(CfDateButtonA11yContext);
75
+ return (_jsx(DropdownButton, { className: cx("gd-cf-date-value", { "gd-cf-date-value--error": hasError }), value: customFilterName ?? textSubtitle, isOpen: isOpen, isFullWidth: true, buttonRef: buttonRef, dropdownId: dropdownId, accessibilityConfig: describedBy ? { ariaDescribedBy: describedBy } : undefined }));
77
76
  }
78
77
  /**
79
78
  * The value picker of a date condition: the standard DateFilter embedded with a dialog-styled
@@ -84,7 +83,7 @@ function CfDateButton({ customFilterName, textSubtitle, isOpen, buttonRef, dropd
84
83
  * already-shifted range (no flag), and reopening reconstructs the preset + checked toggle by
85
84
  * matching the stored range against "preset shifted by one".
86
85
  */
87
- export function CfDateValueDropdown({ value, date, catalogOptions, dateSettings, errorId, onChange, }) {
86
+ export function CfDateValueDropdown({ value, date, catalogOptions, dateSettings, hasError, errorId, onChange, onVisit, }) {
88
87
  const intl = useIntl();
89
88
  const stored = value.kind === "absoluteDate" ? { from: value.from, to: value.to } : undefined;
90
89
  // The static form needs bounds to open on; pin the current period at mount (recomputing "now"
@@ -131,10 +130,13 @@ export function CfDateValueDropdown({ value, date, catalogOptions, dateSettings,
131
130
  }
132
131
  // allTime/emptyValues never appear among the options (the All time / Is empty operators cover them).
133
132
  };
134
- return (_jsx(CfDateButtonA11yContext.Provider, { value: { describedBy: errorId }, children: _jsx(DateFilter, { dateFilterMode: "active", filterOptions: filterOptions, availableGranularities: filterOptions.relativeForm ? [...allowedValueGranularities(date.granularity)] : [], selectedFilterOption: matched.dateFilterOption, excludeCurrentPeriod: matched.excludeCurrentPeriod, isTimeForAbsoluteRangeEnabled: usesTimeResolution(date.granularity), dateFormat: dateSettings?.dateFormat,
133
+ return (_jsx(CfDateButtonA11yContext.Provider, { value: { describedBy: errorId, hasError }, children: _jsx(DateFilter, { dateFilterMode: "active", filterOptions: filterOptions, availableGranularities: filterOptions.relativeForm ? [...allowedValueGranularities(date.granularity)] : [], selectedFilterOption: matched.dateFilterOption, excludeCurrentPeriod: matched.excludeCurrentPeriod, isTimeForAbsoluteRangeEnabled: usesTimeResolution(date.granularity), dateFormat: dateSettings?.dateFormat,
135
134
  // Week columns pin Monday: the resolver snaps ISO weeks, and a Sunday-start calendar
136
135
  // would let a selection straddle the snap boundary.
137
- weekStart: date.granularity === "GDC.time.week_us" ? "Monday" : dateSettings?.weekStart, locale: intl.locale, onApply: handleApply, overlayPositionType: "sameAsTarget", ButtonComponent: CfDateButton, customFilterName: value.kind === "none"
136
+ weekStart: date.granularity === "GDC.time.week_us" ? "Monday" : dateSettings?.weekStart, locale: intl.locale, onApply: handleApply,
137
+ // Every close counts as a visit, applied or not. Blur can't serve as that signal: opening
138
+ // the picker moves focus into its own overlay.
139
+ onClose: onVisit, overlayPositionType: "sameAsTarget", ButtonComponent: CfDateButton, customFilterName: value.kind === "none"
138
140
  ? intl.formatMessage(conditionalFormattingMessages.dialogSelectPeriod)
139
141
  : undefined }) }));
140
142
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ConditionEditor.d.ts","sourceRoot":"","sources":["../../../../../src/internal/components/configurationControls/conditionalFormatting/ConditionEditor.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAiBzE,OAAO,EACH,KAAK,2BAA2B,EAEhC,KAAK,+BAA+B,EAEvC,MAAM,6BAA6B,CAAC;AAYrC,OAAO,EAEH,KAAK,WAAW,EAChB,KAAK,eAAe,EAWvB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAsTrD,MAAM,WAAW,qBAAqB;IAClC,SAAS,EAAE,+BAA+B,CAAC;IAC3C,IAAI,EAAE,2BAA2B,CAAC,MAAM,CAAC,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,WAAW,GAAG,SAAS,CAAC;IACpC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,IAAI,EAAE,WAAW,GAAG,SAAS,CAAC;IAC9B,iBAAiB,EAAE,wBAAwB,GAAG,SAAS,CAAC;IACxD,YAAY,EAAE,eAAe,GAAG,SAAS,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,YAAY,CAAC;IACnB,QAAQ,EAAE,CAAC,SAAS,EAAE,+BAA+B,KAAK,IAAI,CAAC;IAC/D,QAAQ,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,wBAAgB,eAAe,CAAC,EAC5B,SAAS,EACT,IAAI,EACJ,SAAS,EACT,UAAU,EACV,WAAW,EACX,IAAI,EACJ,iBAAiB,EACjB,YAAY,EACZ,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,QAAQ,EACX,EAAE,qBAAqB,2CAiFvB"}
1
+ {"version":3,"file":"ConditionEditor.d.ts","sourceRoot":"","sources":["../../../../../src/internal/components/configurationControls/conditionalFormatting/ConditionEditor.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAiBzE,OAAO,EACH,KAAK,2BAA2B,EAEhC,KAAK,+BAA+B,EAEvC,MAAM,6BAA6B,CAAC;AAarC,OAAO,EAGH,KAAK,WAAW,EAChB,KAAK,eAAe,EAWvB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAwXrD,MAAM,WAAW,qBAAqB;IAClC,SAAS,EAAE,+BAA+B,CAAC;IAC3C,IAAI,EAAE,2BAA2B,CAAC,MAAM,CAAC,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,WAAW,GAAG,SAAS,CAAC;IACpC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,IAAI,EAAE,WAAW,GAAG,SAAS,CAAC;IAC9B,iBAAiB,EAAE,wBAAwB,GAAG,SAAS,CAAC;IACxD,YAAY,EAAE,eAAe,GAAG,SAAS,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,YAAY,CAAC;IACnB,QAAQ,EAAE,CAAC,SAAS,EAAE,+BAA+B,KAAK,IAAI,CAAC;IAC/D,QAAQ,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,wBAAgB,eAAe,CAAC,EAC5B,SAAS,EACT,IAAI,EACJ,SAAS,EACT,UAAU,EACV,WAAW,EACX,IAAI,EACJ,iBAAiB,EACjB,YAAY,EACZ,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,QAAQ,EACX,EAAE,qBAAqB,2CAoFvB"}