@carto/ps-react-ui 4.6.3 → 4.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/{download-config-C3I0jWIL.js → download-config-DNLkypdN.js} +8 -7
  2. package/dist/{download-config-C3I0jWIL.js.map → download-config-DNLkypdN.js.map} +1 -1
  3. package/dist/shared-resize-observer-98b1SK1e.js +17 -0
  4. package/dist/shared-resize-observer-98b1SK1e.js.map +1 -0
  5. package/dist/types/widgets/actions/brush-toggle/brush-overlay.d.ts +24 -0
  6. package/dist/types/widgets/actions/brush-toggle/brush-toggle.d.ts +15 -10
  7. package/dist/types/widgets/actions/brush-toggle/hit-test.d.ts +19 -0
  8. package/dist/types/widgets/actions/brush-toggle/hit-test.test.d.ts +1 -0
  9. package/dist/types/widgets/actions/brush-toggle/style.d.ts +8 -0
  10. package/dist/types/widgets/actions/brush-toggle/types.d.ts +35 -1
  11. package/dist/widgets/actions.js +1020 -787
  12. package/dist/widgets/actions.js.map +1 -1
  13. package/dist/widgets/bar.js +1 -1
  14. package/dist/widgets/category.js +9 -8
  15. package/dist/widgets/category.js.map +1 -1
  16. package/dist/widgets/echart.js +79 -91
  17. package/dist/widgets/echart.js.map +1 -1
  18. package/dist/widgets/formula.js +43 -42
  19. package/dist/widgets/formula.js.map +1 -1
  20. package/dist/widgets/histogram.js +37 -36
  21. package/dist/widgets/histogram.js.map +1 -1
  22. package/dist/widgets/markdown.js +15 -14
  23. package/dist/widgets/markdown.js.map +1 -1
  24. package/dist/widgets/pie.js +1 -1
  25. package/dist/widgets/scatterplot.js +1 -1
  26. package/dist/widgets/spread.js +47 -46
  27. package/dist/widgets/spread.js.map +1 -1
  28. package/dist/widgets/table.js +17 -16
  29. package/dist/widgets/table.js.map +1 -1
  30. package/dist/widgets/timeseries.js +1 -1
  31. package/dist/widgets/utils.js +1 -1
  32. package/package.json +3 -1
  33. package/src/widgets/actions/brush-toggle/brush-overlay.tsx +408 -0
  34. package/src/widgets/actions/brush-toggle/brush-toggle.tsx +88 -152
  35. package/src/widgets/actions/brush-toggle/hit-test.test.ts +65 -0
  36. package/src/widgets/actions/brush-toggle/hit-test.ts +45 -0
  37. package/src/widgets/actions/brush-toggle/style.ts +32 -0
  38. package/src/widgets/actions/brush-toggle/types.ts +36 -1
  39. package/src/widgets/histogram/config.ts +1 -3
@@ -11,7 +11,8 @@ import "./cjs-D4KH3azB.js";
11
11
  import "@dnd-kit/core";
12
12
  import "@dnd-kit/sortable";
13
13
  import "@dnd-kit/utilities";
14
- function E(r) {
14
+ import "react-dom";
15
+ function T(r) {
15
16
  const o = [];
16
17
  if (r.length > 0 && (r[0]?.length ?? 0) > 0) {
17
18
  const i = r?.[0]?.[0] ?? {}, t = Object.keys(i);
@@ -24,7 +25,7 @@ function E(r) {
24
25
  });
25
26
  }), o;
26
27
  }
27
- function T(r) {
28
+ function b(r) {
28
29
  const o = [];
29
30
  return o.push(["x", "y"]), r.forEach((i) => {
30
31
  i.forEach((t) => {
@@ -32,7 +33,7 @@ function T(r) {
32
33
  });
33
34
  }), o;
34
35
  }
35
- function b(r) {
36
+ function j(r) {
36
37
  return function({
37
38
  refUI: o
38
39
  }) {
@@ -49,8 +50,8 @@ function b(r) {
49
50
  };
50
51
  }
51
52
  export {
52
- b as c,
53
- E as f,
54
- T as s
53
+ j as c,
54
+ T as f,
55
+ b as s
55
56
  };
56
- //# sourceMappingURL=download-config-C3I0jWIL.js.map
57
+ //# sourceMappingURL=download-config-DNLkypdN.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"download-config-C3I0jWIL.js","sources":["../src/widgets/utils/chart-config/csv-modifiers.ts","../src/widgets/utils/chart-config/download-config.ts"],"sourcesContent":["/**\n * Shared CSV export modifiers for chart widgets\n */\n\n/**\n * Flattens object array data into CSV-ready rows.\n * Used by bar, pie, histogram, and timeseries widgets.\n *\n * @param data - Array of series, where each series is an array of data objects\n * @returns CSV rows with headers and values\n */\nexport function flattenObjectArrayToCSV<T extends Record<string, unknown>>(\n data: T[][],\n): string[][] {\n const rows: string[][] = []\n\n // Add headers from first data point if available\n if (data.length > 0 && (data[0]?.length ?? 0) > 0) {\n const firstDataPoint = data?.[0]?.[0] ?? {}\n const headers = Object.keys(firstDataPoint)\n rows.push(headers)\n }\n\n // Add data rows from all series\n data.forEach((series) => {\n series.forEach((dataPoint) => {\n const values = Object.values(dataPoint).map((v) => String(v))\n rows.push(values)\n })\n })\n\n return rows\n}\n\n/**\n * Creates CSV rows for scatterplot data.\n * Scatterplot uses array format [x, y] instead of objects.\n *\n * @param data - Array of series, where each series is an array of [x, y] tuples\n * @returns CSV rows with ['x', 'y'] headers\n */\nexport function scatterplotDataToCSV(data: number[][][]): string[][] {\n const rows: string[][] = []\n\n // Add headers\n rows.push(['x', 'y'])\n\n // Add data rows from all series\n data.forEach((series) => {\n series.forEach((dataPoint) => {\n rows.push([String(dataPoint[0]), String(dataPoint[1])])\n })\n })\n\n return rows\n}\n","import { downloadToCSV, downloadToPNG, type DownloadItem } from '../../actions'\nimport type { ConfigProps } from '../../loader/types'\n\nexport function createChartDownloadConfig<TData>(\n csvModifier: (data: TData) => string[][],\n) {\n return function ({ refUI }: ConfigProps): DownloadItem<TData>[] {\n return [\n {\n ...downloadToPNG,\n modifier: () => downloadToPNG.modifier(refUI),\n },\n {\n ...downloadToCSV,\n modifier: async (data) => {\n const rows = csvModifier(data)\n return downloadToCSV.modifier(rows)\n },\n },\n ]\n }\n}\n"],"names":["flattenObjectArrayToCSV","data","rows","length","firstDataPoint","headers","Object","keys","push","forEach","series","dataPoint","values","map","v","String","scatterplotDataToCSV","createChartDownloadConfig","csvModifier","refUI","downloadToPNG","modifier","downloadToCSV"],"mappings":";;;;;;;;;;;;;AAWO,SAASA,EACdC,GACY;AACZ,QAAMC,IAAmB,CAAA;AAGzB,MAAID,EAAKE,SAAS,MAAMF,EAAK,CAAC,GAAGE,UAAU,KAAK,GAAG;AACjD,UAAMC,IAAiBH,IAAO,CAAC,IAAI,CAAC,KAAK,CAAA,GACnCI,IAAUC,OAAOC,KAAKH,CAAc;AAC1CF,IAAAA,EAAKM,KAAKH,CAAO;AAAA,EACnB;AAGAJ,SAAAA,EAAKQ,QAASC,CAAAA,MAAW;AACvBA,IAAAA,EAAOD,QAASE,CAAAA,MAAc;AAC5B,YAAMC,IAASN,OAAOM,OAAOD,CAAS,EAAEE,IAAKC,CAAAA,MAAMC,OAAOD,CAAC,CAAC;AAC5DZ,MAAAA,EAAKM,KAAKI,CAAM;AAAA,IAClB,CAAC;AAAA,EACH,CAAC,GAEMV;AACT;AASO,SAASc,EAAqBf,GAAgC;AACnE,QAAMC,IAAmB,CAAA;AAGzBA,SAAAA,EAAKM,KAAK,CAAC,KAAK,GAAG,CAAC,GAGpBP,EAAKQ,QAASC,CAAAA,MAAW;AACvBA,IAAAA,EAAOD,QAASE,CAAAA,MAAc;AAC5BT,MAAAA,EAAKM,KAAK,CAACO,OAAOJ,EAAU,CAAC,CAAC,GAAGI,OAAOJ,EAAU,CAAC,CAAC,CAAC,CAAC;AAAA,IACxD,CAAC;AAAA,EACH,CAAC,GAEMT;AACT;ACpDO,SAASe,EACdC,GACA;AACA,SAAO,SAAU;AAAA,IAAEC,OAAAA;AAAAA,EAAAA,GAA6C;AAC9D,WAAO,CACL;AAAA,MACE,GAAGC;AAAAA,MACHC,UAAUA,MAAMD,EAAcC,SAASF,CAAK;AAAA,IAAA,GAE9C;AAAA,MACE,GAAGG;AAAAA,MACHD,UAAU,OAAOpB,MAAS;AACxB,cAAMC,IAAOgB,EAAYjB,CAAI;AAC7B,eAAOqB,EAAcD,SAASnB,CAAI;AAAA,MACpC;AAAA,IAAA,CACD;AAAA,EAEL;AACF;"}
1
+ {"version":3,"file":"download-config-DNLkypdN.js","sources":["../src/widgets/utils/chart-config/csv-modifiers.ts","../src/widgets/utils/chart-config/download-config.ts"],"sourcesContent":["/**\n * Shared CSV export modifiers for chart widgets\n */\n\n/**\n * Flattens object array data into CSV-ready rows.\n * Used by bar, pie, histogram, and timeseries widgets.\n *\n * @param data - Array of series, where each series is an array of data objects\n * @returns CSV rows with headers and values\n */\nexport function flattenObjectArrayToCSV<T extends Record<string, unknown>>(\n data: T[][],\n): string[][] {\n const rows: string[][] = []\n\n // Add headers from first data point if available\n if (data.length > 0 && (data[0]?.length ?? 0) > 0) {\n const firstDataPoint = data?.[0]?.[0] ?? {}\n const headers = Object.keys(firstDataPoint)\n rows.push(headers)\n }\n\n // Add data rows from all series\n data.forEach((series) => {\n series.forEach((dataPoint) => {\n const values = Object.values(dataPoint).map((v) => String(v))\n rows.push(values)\n })\n })\n\n return rows\n}\n\n/**\n * Creates CSV rows for scatterplot data.\n * Scatterplot uses array format [x, y] instead of objects.\n *\n * @param data - Array of series, where each series is an array of [x, y] tuples\n * @returns CSV rows with ['x', 'y'] headers\n */\nexport function scatterplotDataToCSV(data: number[][][]): string[][] {\n const rows: string[][] = []\n\n // Add headers\n rows.push(['x', 'y'])\n\n // Add data rows from all series\n data.forEach((series) => {\n series.forEach((dataPoint) => {\n rows.push([String(dataPoint[0]), String(dataPoint[1])])\n })\n })\n\n return rows\n}\n","import { downloadToCSV, downloadToPNG, type DownloadItem } from '../../actions'\nimport type { ConfigProps } from '../../loader/types'\n\nexport function createChartDownloadConfig<TData>(\n csvModifier: (data: TData) => string[][],\n) {\n return function ({ refUI }: ConfigProps): DownloadItem<TData>[] {\n return [\n {\n ...downloadToPNG,\n modifier: () => downloadToPNG.modifier(refUI),\n },\n {\n ...downloadToCSV,\n modifier: async (data) => {\n const rows = csvModifier(data)\n return downloadToCSV.modifier(rows)\n },\n },\n ]\n }\n}\n"],"names":["flattenObjectArrayToCSV","data","rows","length","firstDataPoint","headers","Object","keys","push","forEach","series","dataPoint","values","map","v","String","scatterplotDataToCSV","createChartDownloadConfig","csvModifier","refUI","downloadToPNG","modifier","downloadToCSV"],"mappings":";;;;;;;;;;;;;;AAWO,SAASA,EACdC,GACY;AACZ,QAAMC,IAAmB,CAAA;AAGzB,MAAID,EAAKE,SAAS,MAAMF,EAAK,CAAC,GAAGE,UAAU,KAAK,GAAG;AACjD,UAAMC,IAAiBH,IAAO,CAAC,IAAI,CAAC,KAAK,CAAA,GACnCI,IAAUC,OAAOC,KAAKH,CAAc;AAC1CF,IAAAA,EAAKM,KAAKH,CAAO;AAAA,EACnB;AAGAJ,SAAAA,EAAKQ,QAASC,CAAAA,MAAW;AACvBA,IAAAA,EAAOD,QAASE,CAAAA,MAAc;AAC5B,YAAMC,IAASN,OAAOM,OAAOD,CAAS,EAAEE,IAAKC,CAAAA,MAAMC,OAAOD,CAAC,CAAC;AAC5DZ,MAAAA,EAAKM,KAAKI,CAAM;AAAA,IAClB,CAAC;AAAA,EACH,CAAC,GAEMV;AACT;AASO,SAASc,EAAqBf,GAAgC;AACnE,QAAMC,IAAmB,CAAA;AAGzBA,SAAAA,EAAKM,KAAK,CAAC,KAAK,GAAG,CAAC,GAGpBP,EAAKQ,QAASC,CAAAA,MAAW;AACvBA,IAAAA,EAAOD,QAASE,CAAAA,MAAc;AAC5BT,MAAAA,EAAKM,KAAK,CAACO,OAAOJ,EAAU,CAAC,CAAC,GAAGI,OAAOJ,EAAU,CAAC,CAAC,CAAC,CAAC;AAAA,IACxD,CAAC;AAAA,EACH,CAAC,GAEMT;AACT;ACpDO,SAASe,EACdC,GACA;AACA,SAAO,SAAU;AAAA,IAAEC,OAAAA;AAAAA,EAAAA,GAA6C;AAC9D,WAAO,CACL;AAAA,MACE,GAAGC;AAAAA,MACHC,UAAUA,MAAMD,EAAcC,SAASF,CAAK;AAAA,IAAA,GAE9C;AAAA,MACE,GAAGG;AAAAA,MACHD,UAAU,OAAOpB,MAAS;AACxB,cAAMC,IAAOgB,EAAYjB,CAAI;AAC7B,eAAOqB,EAAcD,SAASnB,CAAI;AAAA,MACpC;AAAA,IAAA,CACD;AAAA,EAEL;AACF;"}
@@ -0,0 +1,17 @@
1
+ const s = /* @__PURE__ */ new Map();
2
+ let o = null;
3
+ function t() {
4
+ return o ??= new ResizeObserver((e) => {
5
+ for (const r of e)
6
+ s.get(r.target)?.();
7
+ }), o;
8
+ }
9
+ function n(e, r) {
10
+ return s.set(e, r), t().observe(e), () => {
11
+ s.delete(e), t().unobserve(e);
12
+ };
13
+ }
14
+ export {
15
+ n as o
16
+ };
17
+ //# sourceMappingURL=shared-resize-observer-98b1SK1e.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-resize-observer-98b1SK1e.js","sources":["../src/widgets/echart/shared-resize-observer.ts"],"sourcesContent":["/**\n * Shared ResizeObserver singleton for all ECharts instances.\n *\n * Instead of creating 100+ individual ResizeObserver instances (one per chart),\n * this module provides a single shared observer that efficiently handles resize\n * callbacks for all registered elements.\n */\n\ntype ResizeCallback = () => void\n\nconst callbacks = new Map<Element, ResizeCallback>()\n\nlet observer: ResizeObserver | null = null\n\nfunction getObserver(): ResizeObserver {\n observer ??= new ResizeObserver((entries) => {\n for (const entry of entries) {\n const callback = callbacks.get(entry.target)\n callback?.()\n }\n })\n return observer\n}\n\nexport function observeResize(\n element: Element,\n callback: ResizeCallback,\n): () => void {\n callbacks.set(element, callback)\n getObserver().observe(element)\n\n return () => {\n callbacks.delete(element)\n getObserver().unobserve(element)\n }\n}\n\n/** Reset the shared observer (for testing only). */\nexport function resetSharedResizeObserver(): void {\n if (observer) {\n observer.disconnect()\n observer = null\n }\n callbacks.clear()\n}\n"],"names":["callbacks","Map","observer","getObserver","ResizeObserver","entries","entry","callback","get","target","observeResize","element","set","observe","delete","unobserve"],"mappings":"AAUA,MAAMA,wBAAgBC,IAAAA;AAEtB,IAAIC,IAAkC;AAEtC,SAASC,IAA8B;AACrCD,SAAAA,MAAa,IAAIE,eAAgBC,CAAAA,MAAY;AAC3C,eAAWC,KAASD;AAElBE,MADiBP,EAAUQ,IAAIF,EAAMG,MAAM,IAC3CF;AAAAA,EAEJ,CAAC,GACML;AACT;AAEO,SAASQ,EACdC,GACAJ,GACY;AACZP,SAAAA,EAAUY,IAAID,GAASJ,CAAQ,GAC/BJ,EAAAA,EAAcU,QAAQF,CAAO,GAEtB,MAAM;AACXX,IAAAA,EAAUc,OAAOH,CAAO,GACxBR,EAAAA,EAAcY,UAAUJ,CAAO;AAAA,EACjC;AACF;"}
@@ -0,0 +1,24 @@
1
+ interface BrushOverlayProps {
2
+ id: string;
3
+ multiBrush?: boolean;
4
+ }
5
+ /**
6
+ * Portaled overlay rendered inside the ECharts chart `<div>`. Handles brush
7
+ * drawing entirely in DOM, independent of ECharts' built-in brush.
8
+ *
9
+ * Rectangles are stored in x-axis data coords (category indices) in the
10
+ * widget store. The overlay re-projects them to pixel coords on every chart
11
+ * `finished` event and container resize, so `setOption({ notMerge: true })`
12
+ * by the config pipeline is a non-event.
13
+ *
14
+ * Pointer capture and rectangle rendering are both clamped to the ECharts
15
+ * grid (plot area), so the legend, axis labels, and other chart chrome
16
+ * receive their usual events and aren't visually covered.
17
+ *
18
+ * Hit-testing happens on `pointerup` using `hitTestRects` against the widget's
19
+ * data length (derived from `widget.data`). The result is written to
20
+ * `brushSelection` in the store; `BrushToggle` subscribes to that and invokes
21
+ * the consumer's `onBrushSelected` callback.
22
+ */
23
+ export declare function BrushOverlay({ id, multiBrush }: BrushOverlayProps): import('react').ReactPortal | null;
24
+ export {};
@@ -1,17 +1,22 @@
1
1
  import { BrushToggleProps } from './types';
2
+ /**
3
+ * Kept for backwards compatibility. The tool is no longer registered with the
4
+ * widget store — brush state is now owned directly by this component and the
5
+ * associated DOM overlay instead of being driven through the config pipeline.
6
+ * Existing code that looks this constant up in `registeredTools` will simply
7
+ * find no match.
8
+ */
2
9
  export declare const BRUSH_TOGGLE_TOOL_ID = "brush-toggle";
3
10
  /**
4
- * Widget action to toggle EChart brush selection functionality.
5
- *
6
- * Registers as a config pipeline tool so that brush configuration is automatically
7
- * re-applied when the base config is updated (e.g., by WidgetLoader).
11
+ * Widget action to toggle brush-style selection on bar and histogram widgets.
8
12
  *
9
- * Brush state is stored in the widget store root, and the tool derives its
10
- * `enabled` flag from the store. This keeps state accessible across component instances.
13
+ * Renders a toggle button and a portaled overlay rendered inside the chart's
14
+ * `<div>`. The overlay handles all pointer interactions, draws selection
15
+ * rectangles in DOM, and hit-tests against the widget data. All state lives
16
+ * in the widget store — rectangles survive config-pipeline re-renders
17
+ * (`setOption({ notMerge: true })`) automatically.
11
18
  *
12
- * When brush is active, users can drag across bars to select a range.
13
- * Selection clearing is handled via the chart's brush interactions/toolbox configuration.
14
- * Only intended for use in fullscreen ToolbarActions for bar and histogram widgets.
19
+ * Only intended for bar and histogram widgets (both use `xAxis.type === 'category'`).
15
20
  *
16
21
  * @example
17
22
  * ```tsx
@@ -21,4 +26,4 @@ export declare const BRUSH_TOGGLE_TOOL_ID = "brush-toggle";
21
26
  * />
22
27
  * ```
23
28
  */
24
- export declare function BrushToggle({ id, onBrushSelected, labels, Icon, IconButtonProps, }: BrushToggleProps): import("react/jsx-runtime").JSX.Element;
29
+ export declare function BrushToggle({ id, onBrushSelected, multiBrush, selections, defaultEnabled, labels, Icon, IconButtonProps, }: BrushToggleProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,19 @@
1
+ import { BrushRect } from './types';
2
+ /**
3
+ * Returns integer dataIndices covered by a brush rectangle on a category axis.
4
+ *
5
+ * `xStart` / `xEnd` come from `instance.convertFromPixel({ xAxisIndex: 0 }, …)`
6
+ * which, for a category axis, returns fractional positions around integer
7
+ * category indices (e.g. `1.3` lands between categories 1 and 2). We snap the
8
+ * range outward (`floor` / `ceil`) so a drag that visually covers any part of
9
+ * a category's bar includes that index.
10
+ *
11
+ * Results are clamped to `[0, dataLength - 1]` and returned in ascending order.
12
+ */
13
+ export declare function hitTestCategoryRange(xStart: number, xEnd: number, dataLength: number): number[];
14
+ /**
15
+ * Union of `hitTestCategoryRange` across multiple rectangles. Used for
16
+ * multi-brush selections where each drawn rectangle contributes to the
17
+ * combined selection.
18
+ */
19
+ export declare function hitTestRects(rects: BrushRect[], dataLength: number): number[];
@@ -1,4 +1,5 @@
1
1
  import { Theme } from '@mui/material';
2
+ import { CSSProperties } from 'react';
2
3
  export declare const styles: {
3
4
  container: {
4
5
  display: "flex";
@@ -11,3 +12,10 @@ export declare const styles: {
11
12
  };
12
13
  };
13
14
  };
15
+ /**
16
+ * Plain CSS objects for the brush overlay — we're outside MUI's sx pipeline
17
+ * here because the rectangles are rendered via a React portal into the chart
18
+ * div (not part of the MUI tree). Colors borrow from the base palette; if
19
+ * theme-aware styling is needed later, move to styled components.
20
+ */
21
+ export declare const overlayStyles: Record<string, CSSProperties>;
@@ -12,10 +12,29 @@ export interface BrushSelectedItems {
12
12
  seriesIndex: number;
13
13
  }
14
14
  /**
15
- * State stored in widget store for brush functionality
15
+ * A selection rectangle in x-axis data coords. Stored in the widget store so
16
+ * it survives config-pipeline re-renders (which call `setOption` with
17
+ * `notMerge: true` and wipe any ECharts-side state). The overlay re-projects
18
+ * these to pixel positions on every chart render / resize.
19
+ *
20
+ * Both bar and histogram widgets use `xAxis.type === 'category'`, so the
21
+ * coords are category indices (possibly fractional — `convertFromPixel`
22
+ * returns floats like `1.3` between categories 1 and 2).
23
+ */
24
+ export interface BrushRect {
25
+ xStart: number;
26
+ xEnd: number;
27
+ }
28
+ /**
29
+ * State stored in widget store for brush functionality.
16
30
  */
17
31
  export interface BrushConfig {
32
+ /** Whether brush mode is enabled. */
18
33
  brush?: boolean;
34
+ /** Persisted selection rectangles in data-axis coords. */
35
+ brushRects?: BrushRect[];
36
+ /** Last selection emitted to the `onBrushSelected` callback. */
37
+ brushSelection?: BrushSelectedItems;
19
38
  }
20
39
  export type BrushState<T = unknown> = BaseWidgetState<T & BrushConfig>;
21
40
  export interface BrushToggleProps {
@@ -23,6 +42,21 @@ export interface BrushToggleProps {
23
42
  id: string;
24
43
  /** Callback fired when items are selected via brush */
25
44
  onBrushSelected?: (items: BrushSelectedItems) => void;
45
+ /** When true, allows multiple brush selection areas. Brush stays active after each selection. */
46
+ multiBrush?: boolean;
47
+ /**
48
+ * Initial brush-enabled state. Only applied on first mount if the widget
49
+ * store has no `brush` value yet — subsequent remounts preserve whatever
50
+ * state the user has toggled to.
51
+ */
52
+ defaultEnabled?: boolean;
53
+ /**
54
+ * Current selection count from the consumer (e.g. `selectedItems.length`).
55
+ * When this transitions to `0` (typically when the user presses the clear
56
+ * button in `WidgetSelectionSummary`), BrushToggle clears its persisted
57
+ * brush rectangles and the on-chart selection.
58
+ */
59
+ selections?: number;
26
60
  /** Custom labels for the action */
27
61
  labels?: {
28
62
  /** Tooltip when brush is disabled (button will enable brush) */