@neo4j-ndl/react-charts 1.1.1 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/lib/cjs/charts/Chart.js +56 -462
  2. package/lib/cjs/charts/Chart.js.map +1 -1
  3. package/lib/cjs/charts/ChartContainer.js +71 -0
  4. package/lib/cjs/charts/ChartContainer.js.map +1 -0
  5. package/lib/cjs/charts/ChartEmpty.js.map +1 -1
  6. package/lib/cjs/charts/ChartRender.js +97 -0
  7. package/lib/cjs/charts/ChartRender.js.map +1 -0
  8. package/lib/cjs/charts/ChartTooltip.js.map +1 -1
  9. package/lib/cjs/charts/Legend.js +32 -246
  10. package/lib/cjs/charts/Legend.js.map +1 -1
  11. package/lib/cjs/charts/LegendItem.js +68 -0
  12. package/lib/cjs/charts/LegendItem.js.map +1 -0
  13. package/lib/cjs/charts/LegendLayout.js +363 -0
  14. package/lib/cjs/charts/LegendLayout.js.map +1 -0
  15. package/lib/cjs/charts/hooks/use-chart-instance.js +133 -0
  16. package/lib/cjs/charts/hooks/use-chart-instance.js.map +1 -0
  17. package/lib/cjs/charts/hooks/use-chart-option.js +79 -0
  18. package/lib/cjs/charts/hooks/use-chart-option.js.map +1 -0
  19. package/lib/cjs/charts/hooks/use-chart-refs.js +52 -0
  20. package/lib/cjs/charts/hooks/use-chart-refs.js.map +1 -0
  21. package/lib/cjs/charts/hooks/use-chart-zoom.js +117 -0
  22. package/lib/cjs/charts/hooks/use-chart-zoom.js.map +1 -0
  23. package/lib/cjs/charts/hooks/use-legend-interactions.js +149 -0
  24. package/lib/cjs/charts/hooks/use-legend-interactions.js.map +1 -0
  25. package/lib/cjs/charts/hooks/use-legend-series.js +181 -0
  26. package/lib/cjs/charts/hooks/use-legend-series.js.map +1 -0
  27. package/lib/cjs/charts/hooks/use-legend-visibility.js +91 -0
  28. package/lib/cjs/charts/hooks/use-legend-visibility.js.map +1 -0
  29. package/lib/cjs/charts/index.js +1 -1
  30. package/lib/cjs/charts/index.js.map +1 -1
  31. package/lib/cjs/charts/tests/chart-test-utils.js +56 -9
  32. package/lib/cjs/charts/tests/chart-test-utils.js.map +1 -1
  33. package/lib/cjs/charts/themes/ndl-echarts-theme.js.map +1 -1
  34. package/lib/cjs/charts/{aria-description.js → utils/aria-description.js} +4 -45
  35. package/lib/cjs/charts/utils/aria-description.js.map +1 -0
  36. package/lib/cjs/charts/utils/build-chart-option.js +74 -0
  37. package/lib/cjs/charts/utils/build-chart-option.js.map +1 -0
  38. package/lib/cjs/charts/utils/chart-tooltip-formatter.js +86 -0
  39. package/lib/cjs/charts/utils/chart-tooltip-formatter.js.map +1 -0
  40. package/lib/cjs/charts/utils/chart-types.js.map +1 -0
  41. package/lib/cjs/charts/utils/defaults.js.map +1 -0
  42. package/lib/cjs/charts/{utils.js → utils/format-utils.js} +3 -19
  43. package/lib/cjs/charts/utils/format-utils.js.map +1 -0
  44. package/lib/cjs/charts/utils/legend-layout.js +65 -0
  45. package/lib/cjs/charts/utils/legend-layout.js.map +1 -0
  46. package/lib/cjs/charts/{legend-utils.js → utils/legend-utils.js} +1 -78
  47. package/lib/cjs/charts/utils/legend-utils.js.map +1 -0
  48. package/lib/cjs/charts/utils/threshold.js +114 -0
  49. package/lib/cjs/charts/utils/threshold.js.map +1 -0
  50. package/lib/cjs/charts/{user-option-utils.js → utils/user-option-utils.js} +7 -16
  51. package/lib/cjs/charts/utils/user-option-utils.js.map +1 -0
  52. package/lib/esm/charts/Chart.js +50 -457
  53. package/lib/esm/charts/Chart.js.map +1 -1
  54. package/lib/esm/charts/ChartContainer.js +67 -0
  55. package/lib/esm/charts/ChartContainer.js.map +1 -0
  56. package/lib/esm/charts/ChartEmpty.js.map +1 -1
  57. package/lib/esm/charts/ChartRender.js +93 -0
  58. package/lib/esm/charts/ChartRender.js.map +1 -0
  59. package/lib/esm/charts/ChartTooltip.js.map +1 -1
  60. package/lib/esm/charts/Legend.js +32 -243
  61. package/lib/esm/charts/Legend.js.map +1 -1
  62. package/lib/esm/charts/LegendItem.js +61 -0
  63. package/lib/esm/charts/LegendItem.js.map +1 -0
  64. package/lib/esm/charts/LegendLayout.js +323 -0
  65. package/lib/esm/charts/LegendLayout.js.map +1 -0
  66. package/lib/esm/charts/hooks/use-chart-instance.js +128 -0
  67. package/lib/esm/charts/hooks/use-chart-instance.js.map +1 -0
  68. package/lib/esm/charts/hooks/use-chart-option.js +76 -0
  69. package/lib/esm/charts/hooks/use-chart-option.js.map +1 -0
  70. package/lib/esm/charts/hooks/use-chart-refs.js +48 -0
  71. package/lib/esm/charts/hooks/use-chart-refs.js.map +1 -0
  72. package/lib/esm/charts/hooks/use-chart-zoom.js +114 -0
  73. package/lib/esm/charts/hooks/use-chart-zoom.js.map +1 -0
  74. package/lib/esm/charts/hooks/use-legend-interactions.js +145 -0
  75. package/lib/esm/charts/hooks/use-legend-interactions.js.map +1 -0
  76. package/lib/esm/charts/hooks/use-legend-series.js +178 -0
  77. package/lib/esm/charts/hooks/use-legend-series.js.map +1 -0
  78. package/lib/esm/charts/hooks/use-legend-visibility.js +87 -0
  79. package/lib/esm/charts/hooks/use-legend-visibility.js.map +1 -0
  80. package/lib/esm/charts/index.js +1 -1
  81. package/lib/esm/charts/index.js.map +1 -1
  82. package/lib/esm/charts/tests/chart-test-utils.js +53 -8
  83. package/lib/esm/charts/tests/chart-test-utils.js.map +1 -1
  84. package/lib/esm/charts/themes/ndl-echarts-theme.js.map +1 -1
  85. package/lib/esm/charts/{aria-description.js → utils/aria-description.js} +4 -45
  86. package/lib/esm/charts/utils/aria-description.js.map +1 -0
  87. package/lib/esm/charts/utils/build-chart-option.js +69 -0
  88. package/lib/esm/charts/utils/build-chart-option.js.map +1 -0
  89. package/lib/esm/charts/utils/chart-tooltip-formatter.js +82 -0
  90. package/lib/esm/charts/utils/chart-tooltip-formatter.js.map +1 -0
  91. package/lib/esm/charts/utils/chart-types.js.map +1 -0
  92. package/lib/esm/charts/utils/defaults.js.map +1 -0
  93. package/lib/esm/charts/{utils.js → utils/format-utils.js} +2 -17
  94. package/lib/esm/charts/utils/format-utils.js.map +1 -0
  95. package/lib/esm/charts/utils/legend-layout.js +59 -0
  96. package/lib/esm/charts/utils/legend-layout.js.map +1 -0
  97. package/lib/esm/charts/{legend-utils.js → utils/legend-utils.js} +1 -75
  98. package/lib/esm/charts/utils/legend-utils.js.map +1 -0
  99. package/lib/esm/charts/utils/threshold.js +106 -0
  100. package/lib/esm/charts/utils/threshold.js.map +1 -0
  101. package/lib/esm/charts/{user-option-utils.js → utils/user-option-utils.js} +5 -14
  102. package/lib/esm/charts/utils/user-option-utils.js.map +1 -0
  103. package/lib/types/charts/Chart.d.ts +2 -2
  104. package/lib/types/charts/Chart.d.ts.map +1 -1
  105. package/lib/{esm/charts/types.js → types/charts/ChartContainer.d.ts} +14 -1
  106. package/lib/types/charts/ChartContainer.d.ts.map +1 -0
  107. package/lib/types/charts/ChartEmpty.d.ts +1 -1
  108. package/lib/types/charts/ChartEmpty.d.ts.map +1 -1
  109. package/lib/types/charts/ChartRender.d.ts +36 -0
  110. package/lib/types/charts/ChartRender.d.ts.map +1 -0
  111. package/lib/types/charts/ChartTooltip.d.ts +1 -1
  112. package/lib/types/charts/ChartTooltip.d.ts.map +1 -1
  113. package/lib/types/charts/Legend.d.ts +15 -3
  114. package/lib/types/charts/Legend.d.ts.map +1 -1
  115. package/lib/{cjs/charts/types.js → types/charts/LegendItem.d.ts} +10 -3
  116. package/lib/types/charts/LegendItem.d.ts.map +1 -0
  117. package/lib/types/charts/LegendLayout.d.ts +38 -0
  118. package/lib/types/charts/LegendLayout.d.ts.map +1 -0
  119. package/lib/types/charts/hooks/use-chart-instance.d.ts +62 -0
  120. package/lib/types/charts/hooks/use-chart-instance.d.ts.map +1 -0
  121. package/lib/types/charts/hooks/use-chart-option.d.ts +48 -0
  122. package/lib/types/charts/hooks/use-chart-option.d.ts.map +1 -0
  123. package/lib/types/charts/hooks/use-chart-refs.d.ts +38 -0
  124. package/lib/types/charts/hooks/use-chart-refs.d.ts.map +1 -0
  125. package/lib/types/charts/hooks/use-chart-zoom.d.ts +36 -0
  126. package/lib/types/charts/hooks/use-chart-zoom.d.ts.map +1 -0
  127. package/lib/types/charts/hooks/use-legend-interactions.d.ts +56 -0
  128. package/lib/types/charts/hooks/use-legend-interactions.d.ts.map +1 -0
  129. package/lib/types/charts/hooks/use-legend-series.d.ts +42 -0
  130. package/lib/types/charts/hooks/use-legend-series.d.ts.map +1 -0
  131. package/lib/types/charts/hooks/use-legend-visibility.d.ts +24 -0
  132. package/lib/types/charts/hooks/use-legend-visibility.d.ts.map +1 -0
  133. package/lib/types/charts/index.d.ts +2 -2
  134. package/lib/types/charts/index.d.ts.map +1 -1
  135. package/lib/types/charts/tests/chart-test-utils.d.ts +7 -1
  136. package/lib/types/charts/tests/chart-test-utils.d.ts.map +1 -1
  137. package/lib/types/charts/themes/ndl-echarts-theme.d.ts +1 -1
  138. package/lib/types/charts/themes/ndl-echarts-theme.d.ts.map +1 -1
  139. package/lib/types/charts/utils/aria-description.d.ts.map +1 -0
  140. package/lib/types/charts/utils/build-chart-option.d.ts +52 -0
  141. package/lib/types/charts/utils/build-chart-option.d.ts.map +1 -0
  142. package/lib/types/charts/utils/chart-tooltip-formatter.d.ts +37 -0
  143. package/lib/types/charts/utils/chart-tooltip-formatter.d.ts.map +1 -0
  144. package/lib/types/charts/{chart-types.d.ts → utils/chart-types.d.ts} +23 -22
  145. package/lib/types/charts/utils/chart-types.d.ts.map +1 -0
  146. package/lib/types/charts/utils/defaults.d.ts.map +1 -0
  147. package/lib/types/charts/{utils.d.ts → utils/format-utils.d.ts} +2 -4
  148. package/lib/types/charts/utils/format-utils.d.ts.map +1 -0
  149. package/lib/types/charts/utils/legend-layout.d.ts +37 -0
  150. package/lib/types/charts/utils/legend-layout.d.ts.map +1 -0
  151. package/lib/types/charts/{legend-utils.d.ts → utils/legend-utils.d.ts} +1 -11
  152. package/lib/types/charts/utils/legend-utils.d.ts.map +1 -0
  153. package/lib/types/charts/utils/threshold.d.ts +45 -0
  154. package/lib/types/charts/utils/threshold.d.ts.map +1 -0
  155. package/lib/types/charts/utils/user-option-utils.d.ts.map +1 -0
  156. package/package.json +3 -3
  157. package/lib/cjs/charts/aria-description.js.map +0 -1
  158. package/lib/cjs/charts/chart-types.js.map +0 -1
  159. package/lib/cjs/charts/defaults.js.map +0 -1
  160. package/lib/cjs/charts/legend-utils.js.map +0 -1
  161. package/lib/cjs/charts/types.js.map +0 -1
  162. package/lib/cjs/charts/user-option-utils.js.map +0 -1
  163. package/lib/cjs/charts/utils.js.map +0 -1
  164. package/lib/esm/charts/aria-description.js.map +0 -1
  165. package/lib/esm/charts/chart-types.js.map +0 -1
  166. package/lib/esm/charts/defaults.js.map +0 -1
  167. package/lib/esm/charts/legend-utils.js.map +0 -1
  168. package/lib/esm/charts/types.js.map +0 -1
  169. package/lib/esm/charts/user-option-utils.js.map +0 -1
  170. package/lib/esm/charts/utils.js.map +0 -1
  171. package/lib/types/charts/aria-description.d.ts.map +0 -1
  172. package/lib/types/charts/chart-types.d.ts.map +0 -1
  173. package/lib/types/charts/defaults.d.ts.map +0 -1
  174. package/lib/types/charts/legend-utils.d.ts.map +0 -1
  175. package/lib/types/charts/types.d.ts +0 -44
  176. package/lib/types/charts/types.d.ts.map +0 -1
  177. package/lib/types/charts/user-option-utils.d.ts.map +0 -1
  178. package/lib/types/charts/utils.d.ts.map +0 -1
  179. /package/lib/cjs/charts/{chart-types.js → utils/chart-types.js} +0 -0
  180. /package/lib/cjs/charts/{defaults.js → utils/defaults.js} +0 -0
  181. /package/lib/esm/charts/{chart-types.js → utils/chart-types.js} +0 -0
  182. /package/lib/esm/charts/{defaults.js → utils/defaults.js} +0 -0
  183. /package/lib/types/charts/{aria-description.d.ts → utils/aria-description.d.ts} +0 -0
  184. /package/lib/types/charts/{defaults.d.ts → utils/defaults.d.ts} +0 -0
  185. /package/lib/types/charts/{user-option-utils.d.ts → utils/user-option-utils.d.ts} +0 -0
@@ -10,9 +10,6 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  }
11
11
  return t;
12
12
  };
13
- var __importDefault = (this && this.__importDefault) || function (mod) {
14
- return (mod && mod.__esModule) ? mod : { "default": mod };
15
- };
16
13
  Object.defineProperty(exports, "__esModule", { value: true });
17
14
  exports.Legend = void 0;
18
15
  const jsx_runtime_1 = require("react/jsx-runtime");
@@ -36,254 +33,43 @@ const jsx_runtime_1 = require("react/jsx-runtime");
36
33
  * You should have received a copy of the GNU General Public License
37
34
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
38
35
  */
39
- const base_1 = require("@neo4j-ndl/base");
40
- const react_1 = require("@neo4j-ndl/react");
41
- const icons_1 = require("@neo4j-ndl/react/icons");
42
- const classnames_1 = __importDefault(require("classnames"));
43
- const echarts_1 = require("echarts");
44
- const react_2 = require("react");
45
- const legend_utils_1 = require("./legend-utils");
46
- const LegendItem = function LegendItemComponent(_a) {
47
- var _b;
48
- var { children, as, className, name, selected, deSelected, onLegendItemClick, color, hasButtons = true, ref, onLegendItemMouseEnter, onLegendItemMouseLeave } = _a, restProps = __rest(_a, ["children", "as", "className", "name", "selected", "deSelected", "onLegendItemClick", "color", "hasButtons", "ref", "onLegendItemMouseEnter", "onLegendItemMouseLeave"]);
49
- const Component = as !== null && as !== void 0 ? as : (hasButtons ? 'button' : 'div');
50
- const classes = (0, classnames_1.default)('ndl-chart-legend-item', {
51
- 'ndl-chart-legend-item-deselected': deSelected,
52
- 'ndl-chart-legend-item-selected': selected,
53
- }, className);
54
- // We don't want to display threshold lines in the legend
55
- if ((_b = (0, legend_utils_1.isThresholdLine)(name)) !== null && _b !== void 0 ? _b : false) {
56
- return null;
57
- }
58
- return ((0, jsx_runtime_1.jsxs)(Component, Object.assign({ className: classes, ref: ref, "data-labelname": name, title: name, onClick: hasButtons ? onLegendItemClick : undefined, onMouseEnter: onLegendItemMouseEnter, onMouseLeave: onLegendItemMouseLeave }, restProps, { children: [(0, jsx_runtime_1.jsx)("span", { className: "ndl-chart-legend-item-square", style: {
59
- '--ndl-chart-legend-item-color': color,
60
- backgroundColor: deSelected === true ? 'transparent' : color,
61
- }, children: selected === true && ((0, jsx_runtime_1.jsx)(icons_1.CheckIconOutline, { className: "ndl-chart-legend-item-square-checkmark" })) }), (0, jsx_runtime_1.jsx)(react_1.Typography, { variant: "body-medium", className: "ndl-chart-legend-item-text", children: children })] })));
62
- };
63
- const getAllSeriesSelected = (series) => Object.fromEntries(series.map((s) => { var _a; return [(_a = s.name) !== null && _a !== void 0 ? _a : '', true]; }));
64
- const hasSelectionForCurrentSeries = (selection, series) => {
65
- const selectedNames = Object.keys(selection);
66
- return (selectedNames.length === series.length &&
67
- series.every((s) => { var _a; return Object.prototype.hasOwnProperty.call(selection, (_a = s.name) !== null && _a !== void 0 ? _a : ''); }));
68
- };
36
+ const use_legend_interactions_1 = require("./hooks/use-legend-interactions");
37
+ const use_legend_visibility_1 = require("./hooks/use-legend-visibility");
38
+ const LegendItem_1 = require("./LegendItem");
39
+ const LegendLayout_1 = require("./LegendLayout");
69
40
  /**
70
- * Keeps legend rendering in sync with the current ECharts series names.
41
+ * Renders the interactive chart legend and keeps legend state synchronized with
42
+ * ECharts.
71
43
  *
72
- * ECharts can briefly keep selection state for the previous pie categories
73
- * after the dataset changes. Rendering with that stale state makes every new
74
- * category look deselected for one frame, so we render new series as visible
75
- * until the effect below reconciles the persisted selection state.
44
+ * The component owns the React-side selected-series state, mirrors it into the
45
+ * shared ref consumed when rebuilding chart options, and wires item hover/click
46
+ * interactions back to the ECharts instance.
76
47
  */
77
- const useLegendSelectionForCurrentSeries = (series) => {
78
- const initialSelected = (0, react_2.useMemo)(() => getAllSeriesSelected(series), [series]);
79
- const [selectedSeries, setSelectedSeries] = (0, react_2.useState)(initialSelected);
80
- const renderedSelectedSeries = hasSelectionForCurrentSeries(selectedSeries, series)
81
- ? selectedSeries
82
- : initialSelected;
83
- return { renderedSelectedSeries, selectedSeries, setSelectedSeries };
84
- };
85
- const Legend = function LegendComponent(_a) {
86
- var { className, wrappingType = 'wrapping', series, chartRef, selectedRef, ref, htmlAttributes } = _a, restProps = __rest(_a, ["className", "wrappingType", "series", "chartRef", "selectedRef", "ref", "htmlAttributes"]);
87
- const { renderedSelectedSeries, selectedSeries, setSelectedSeries } = useLegendSelectionForCurrentSeries(series);
88
- // Keep the shared ref in sync so Chart can read the latest selection state
89
- // when building setOption. This is the single source of truth for legend filters.
90
- (0, react_2.useEffect)(() => {
91
- if (selectedRef) {
92
- selectedRef.current = selectedSeries;
93
- }
94
- }, [selectedRef, selectedSeries]);
95
- const highlightTimeOut = (0, react_2.useRef)(null);
96
- const downplayTimeOut = (0, react_2.useRef)(null);
97
- const hoverTimeOut = 80;
98
- const highlightSeries = (seriesToUpdate) => {
99
- // Clear the downplay timeout when a new item is hovered
100
- if (downplayTimeOut.current) {
101
- clearTimeout(downplayTimeOut.current);
102
- }
103
- // Delay the highlight to avoid flickering when quickly hovering the legend items
104
- highlightTimeOut.current = setTimeout(() => {
105
- (0, legend_utils_1.highlightOrDownplaySeries)(chartRef, series, renderedSelectedSeries, seriesToUpdate, 'highlight');
106
- }, hoverTimeOut);
107
- };
108
- const downplaySeries = (seriesToUpdate) => {
109
- // Clear the highlight timeout when the mouse is leaving the legend item
110
- if (highlightTimeOut.current) {
111
- clearTimeout(highlightTimeOut.current);
112
- }
113
- // Delay the downplay to avoid flickering when moving the highlight between legend items (no downplay needed in between)
114
- downplayTimeOut.current = setTimeout(() => {
115
- (0, legend_utils_1.highlightOrDownplaySeries)(chartRef, series, renderedSelectedSeries, seriesToUpdate, 'downplay');
116
- }, hoverTimeOut);
117
- };
118
- (0, react_2.useEffect)(() => {
119
- var _a, _b, _c;
120
- // Preserve existing legend selection state across re-renders.
121
- // Only new series default to visible (true); removed series are dropped.
122
- const prev = (_a = selectedRef === null || selectedRef === void 0 ? void 0 : selectedRef.current) !== null && _a !== void 0 ? _a : {};
123
- const next = {};
124
- for (const s of series) {
125
- const name = (_b = s.name) !== null && _b !== void 0 ? _b : '';
126
- next[name] = (_c = prev[name]) !== null && _c !== void 0 ? _c : true;
127
- }
128
- setSelectedSeries(next);
129
- if (chartRef.current === null) {
130
- return;
131
- }
132
- const chart = (0, echarts_1.getInstanceByDom)(chartRef.current);
133
- const eventTypes = [
134
- 'legendselectchanged',
135
- 'legendselectall',
136
- 'legendselected',
137
- 'legendunselected',
138
- ];
139
- eventTypes.forEach((eventType) => {
140
- chart === null || chart === void 0 ? void 0 : chart.on(eventType, (params) => {
141
- var _a;
142
- if (typeof params === 'object' &&
143
- params !== null &&
144
- 'selected' in params &&
145
- params.selected !== null) {
146
- const selected = (_a = params.selected) !== null && _a !== void 0 ? _a : {};
147
- const filteredSelected = Object.fromEntries(Object.entries(selected).filter(([key]) => { var _a; return !((_a = (0, legend_utils_1.isThresholdLine)(key)) !== null && _a !== void 0 ? _a : false); }));
148
- // Reset the series highlight to avoid series to stay blurred on selection change
149
- if (eventType === 'legendselectchanged') {
150
- (0, legend_utils_1.resetAllSeriesHighlight)(chart);
151
- }
152
- setSelectedSeries(filteredSelected);
153
- }
154
- });
155
- });
156
- return () => {
157
- eventTypes.forEach((eventType) => {
158
- chart === null || chart === void 0 ? void 0 : chart.off(eventType);
159
- });
160
- };
161
- }, [chartRef, selectedRef, series, setSelectedSeries]);
162
- const classes = (0, classnames_1.default)(`ndl-chart-legend`, {
163
- 'ndl-chart-legend-truncation': wrappingType === 'truncation',
164
- 'ndl-chart-legend-wrapping': wrappingType === 'wrapping',
165
- }, className);
166
- const { toggleLegendVisibility, setAllVisible } = (0, legend_utils_1.useLegendVisibility)(chartRef, renderedSelectedSeries);
167
- return ((0, jsx_runtime_1.jsx)("div", Object.assign({ ref: ref, className: "ndl-chart-legend-container" }, restProps, htmlAttributes, { children: wrappingType === 'truncation' || wrappingType === 'wrapping' ? ((0, jsx_runtime_1.jsx)("div", { className: classes, children: series.map((currentSeries, index) => {
168
- var _a, _b;
169
- const hasMoreThanOneItem = series.length > 1;
170
- const selectedSeriesLength = Object.values(renderedSelectedSeries).filter(Boolean).length;
171
- const isAllSeriesVisible = selectedSeriesLength === series.length;
172
- const color = currentSeries.color;
173
- const isDeselected = currentSeries.name === undefined
174
- ? false
175
- : !renderedSelectedSeries[currentSeries.name];
176
- return ((0, jsx_runtime_1.jsx)(react_1.ConditionalWrap, { shouldWrap: wrappingType === 'truncation', wrap: (children) => ((0, jsx_runtime_1.jsx)(react_1.Tooltip, { type: "simple", children: (0, jsx_runtime_1.jsx)(react_1.Tooltip.Trigger, { hasButtonWrapper: true, children: children }) }, index)), children: (0, jsx_runtime_1.jsx)(LegendItem, { name: currentSeries.name, color: color, hasButtons: hasMoreThanOneItem && currentSeries.name !== undefined, onLegendItemMouseEnter: () => {
177
- if (!isDeselected) {
178
- highlightSeries([currentSeries]);
179
- }
180
- }, onLegendItemMouseLeave: () => {
181
- if (!isDeselected) {
182
- downplaySeries([currentSeries]);
183
- }
184
- }, onLegendItemClick: () => {
185
- var _a;
186
- const isAllSeriesSelected = selectedSeriesLength === series.length;
187
- const isOnlyVisible = renderedSelectedSeries[(_a = currentSeries.name) !== null && _a !== void 0 ? _a : ''] &&
188
- selectedSeriesLength === 1;
189
- toggleLegendVisibility(currentSeries.name, isAllSeriesSelected, isOnlyVisible);
190
- }, selected: !isAllSeriesVisible &&
191
- renderedSelectedSeries[(_a = currentSeries.name) !== null && _a !== void 0 ? _a : ''], deSelected: isDeselected, children: (_b = currentSeries.name) !== null && _b !== void 0 ? _b : `Series ${index}` }) }, index));
192
- }) })) : ((0, jsx_runtime_1.jsx)(LegendOverflowType, { className: classes, selectedSeries: renderedSelectedSeries, wrappingType: wrappingType, chartRef: chartRef, series: series, onSetAllVisible: setAllVisible, onLegendItemMouseEnter: (seriesToUpdate) => highlightSeries(seriesToUpdate), onLegendItemMouseLeave: (seriesToUpdate) => downplaySeries(seriesToUpdate), onToggleLegendVisibility: (name, isAllSeriesSelected, isOnlyVisible) => {
193
- toggleLegendVisibility(name, isAllSeriesSelected, isOnlyVisible);
194
- } })) })));
195
- };
196
- exports.Legend = Legend;
197
- const LegendOverflowType = function LegendOverflow({ className, series, onSetAllVisible, onToggleLegendVisibility, selectedSeries, onLegendItemMouseEnter, onLegendItemMouseLeave, }) {
198
- const containerRef = (0, react_2.useRef)(null);
199
- const [nonOverflowItemsNames, setNonOverflowItemsNames] = (0, react_2.useState)(series.map((s) => s.name));
200
- (0, react_2.useEffect)(() => {
201
- setNonOverflowItemsNames(series.map((s) => s.name));
202
- }, [series]);
203
- const overflowItemsNames = series.filter((item) => !nonOverflowItemsNames.includes(item.name));
204
- const [width, setWidth] = (0, react_2.useState)(Infinity);
205
- (0, react_1.useResizeObserver)({
206
- // TODO: remove type cast. use-hooks.ts 3.1.1 has a type issue with the ref, it should be HTMLElement | null
207
- // https://github.com/juliencrn/usehooks-ts/pull/680
208
- onResize: (entry) => {
209
- if (entry.width === undefined) {
210
- return;
211
- }
212
- if (width < entry.width) {
213
- setNonOverflowItemsNames(series.map((s) => s.name));
214
- }
215
- setWidth(entry.width);
216
- },
217
- ref: containerRef,
48
+ const Legend = (_a) => {
49
+ var { className, series, isLayoutReady = true, onLayoutReady, htmlAttributes } = _a, restProps = __rest(_a, ["className", "series", "isLayoutReady", "onLayoutReady", "htmlAttributes"]);
50
+ const { renderedSelectedSeries } = (0, use_legend_interactions_1.useLegendSelection)({
51
+ series,
218
52
  });
219
- (0, react_2.useEffect)(() => {
220
- const container = containerRef.current;
221
- if (!container) {
222
- return;
223
- }
224
- let elements = Array.from(container.children);
225
- if (elements.length === 0 || series.length === 0) {
226
- return;
227
- }
228
- let totalWidth = 0;
229
- if (overflowItemsNames.length > 0) {
230
- const lastElementItem = elements[elements.length - 1];
231
- const lastItemWidth = (0, legend_utils_1.getComputedElementWidth)(lastElementItem);
232
- elements = elements.slice(0, elements.length - 1);
233
- totalWidth += lastItemWidth;
234
- }
235
- elements.forEach((element) => {
236
- const elementWidth = (0, legend_utils_1.getComputedElementWidth)(element);
237
- totalWidth += elementWidth;
238
- const textContent = element.textContent;
239
- if (!textContent) {
240
- return;
241
- }
242
- const itemName = element.getAttribute('data-labelname');
243
- if (itemName === null) {
244
- return;
245
- }
246
- if (totalWidth > width) {
247
- setNonOverflowItemsNames((oldNames) => oldNames.filter((name) => name !== itemName));
248
- }
249
- });
250
- }, [overflowItemsNames.length, series.length, width]);
251
- const classes = (0, classnames_1.default)({
252
- 'ndl-chart-legend-calculating': width === Infinity,
253
- }, className);
254
- const selectedSeriesLength = Object.values(selectedSeries).filter(Boolean).length;
255
- const hasMoreThanOneItem = nonOverflowItemsNames.length > 1;
53
+ const { toggleHighlight } = (0, use_legend_interactions_1.useLegendHoverHighlight)({
54
+ selectedSeries: renderedSelectedSeries,
55
+ series,
56
+ });
57
+ const { toggleLegendVisibility } = (0, use_legend_visibility_1.useLegendVisibility)(renderedSelectedSeries);
58
+ const selectedSeriesLength = Object.values(renderedSelectedSeries).filter(Boolean).length;
256
59
  const isAllSeriesVisible = selectedSeriesLength === series.length;
257
- const isOverflowItemsDeselected = overflowItemsNames.every((item) => { var _a; return !selectedSeries[(_a = item.name) !== null && _a !== void 0 ? _a : '']; });
258
- return ((0, jsx_runtime_1.jsxs)("div", { className: classes, ref: containerRef, children: [nonOverflowItemsNames.map((name) => {
259
- var _a;
260
- const currentSeries = series.find((s) => s.name === name);
261
- if (currentSeries === undefined) {
262
- return null;
263
- }
264
- const isDeselected = currentSeries.name === undefined
60
+ const hasMoreThanOneItem = series.length > 1;
61
+ return ((0, jsx_runtime_1.jsx)(LegendLayout_1.LegendLayout, Object.assign({ className: className, isLayoutReady: isLayoutReady, itemCount: series.length, onLayoutReady: onLayoutReady, htmlAttributes: htmlAttributes }, restProps, { children: series.map((currentSeries, index) => {
62
+ var _a, _b, _c;
63
+ return ((0, jsx_runtime_1.jsx)(LegendItem_1.LegendItem, { name: currentSeries.name, color: currentSeries.color, hasButtons: hasMoreThanOneItem && currentSeries.name !== undefined, onLegendItemMouseEnter: () => toggleHighlight(currentSeries, true), onLegendItemMouseLeave: () => toggleHighlight(currentSeries, false), onLegendItemClick: () => {
64
+ var _a;
65
+ const isOnlyVisible = renderedSelectedSeries[(_a = currentSeries.name) !== null && _a !== void 0 ? _a : ''] &&
66
+ selectedSeriesLength === 1;
67
+ toggleLegendVisibility(currentSeries.name, isAllSeriesVisible, isOnlyVisible);
68
+ }, selected: !isAllSeriesVisible &&
69
+ renderedSelectedSeries[(_a = currentSeries.name) !== null && _a !== void 0 ? _a : ''], deSelected: currentSeries.name === undefined
265
70
  ? false
266
- : !selectedSeries[currentSeries.name];
267
- return ((0, jsx_runtime_1.jsx)(LegendItem, { name: name, color: currentSeries.color, onLegendItemMouseEnter: () => !isDeselected && onLegendItemMouseEnter([currentSeries]), onLegendItemMouseLeave: () => !isDeselected && onLegendItemMouseLeave([currentSeries]), onLegendItemClick: () => {
268
- const isAllSeriesSelected = selectedSeriesLength === series.length;
269
- const isOnlyVisible = selectedSeries[name !== null && name !== void 0 ? name : ''] && selectedSeriesLength === 1;
270
- onToggleLegendVisibility === null || onToggleLegendVisibility === void 0 ? void 0 : onToggleLegendVisibility(name, isAllSeriesSelected, isOnlyVisible, series);
271
- }, hasButtons: hasMoreThanOneItem, selected: !isAllSeriesVisible && selectedSeries[(_a = currentSeries.name) !== null && _a !== void 0 ? _a : ''], deSelected: isDeselected, children: name }, name));
272
- }), overflowItemsNames.length > 0 && ((0, jsx_runtime_1.jsxs)(react_1.Tooltip, { type: "simple", children: [(0, jsx_runtime_1.jsx)(react_1.Tooltip.Trigger, { hasButtonWrapper: true, children: (0, jsx_runtime_1.jsxs)(LegendItem, { name: "ndl-overflow-items", color: base_1.tokens.palette.neutral[30], selected: !isAllSeriesVisible &&
273
- overflowItemsNames.every((item) => { var _a; return selectedSeries[(_a = item.name) !== null && _a !== void 0 ? _a : '']; }), deSelected: isOverflowItemsDeselected, onLegendItemMouseEnter: () => !isOverflowItemsDeselected &&
274
- onLegendItemMouseEnter(overflowItemsNames), onLegendItemMouseLeave: () => !isOverflowItemsDeselected &&
275
- onLegendItemMouseLeave(overflowItemsNames), onLegendItemClick: () => {
276
- const selectedSeriesLength = Object.values(selectedSeries).filter(Boolean).length;
277
- const isOnlyOverflowItemsVisible = selectedSeriesLength === overflowItemsNames.length &&
278
- overflowItemsNames.every((item) => { var _a; return selectedSeries[(_a = item.name) !== null && _a !== void 0 ? _a : '']; });
279
- if (isOnlyOverflowItemsVisible) {
280
- onSetAllVisible();
281
- return;
282
- }
283
- overflowItemsNames.forEach((item, index) => {
284
- const isAllSeriesSelected = selectedSeriesLength === series.length && index === 0;
285
- onToggleLegendVisibility === null || onToggleLegendVisibility === void 0 ? void 0 : onToggleLegendVisibility(item.name, isAllSeriesSelected, false, series);
286
- });
287
- }, children: [overflowItemsNames.length, " more"] }) }), (0, jsx_runtime_1.jsx)(react_1.Tooltip.Content, { children: overflowItemsNames.map((item) => ((0, jsx_runtime_1.jsx)("p", { children: item.name }, item.name))) })] }))] }));
71
+ : !renderedSelectedSeries[currentSeries.name], children: (_b = currentSeries.name) !== null && _b !== void 0 ? _b : `Series ${index}` }, (_c = currentSeries.name) !== null && _c !== void 0 ? _c : index));
72
+ }) })));
288
73
  };
74
+ exports.Legend = Legend;
289
75
  //# sourceMappingURL=Legend.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Legend.js","sourceRoot":"","sources":["../../../src/charts/Legend.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport { tokens } from '@neo4j-ndl/base';\nimport {\n ConditionalWrap,\n Tooltip,\n Typography,\n useResizeObserver,\n} from '@neo4j-ndl/react';\nimport { CheckIconOutline } from '@neo4j-ndl/react/icons';\nimport classNames from 'classnames';\nimport { type EChartsType, getInstanceByDom } from 'echarts';\nimport type React from 'react';\nimport { useEffect, useMemo, useRef, useState } from 'react';\n\nimport {\n type LegendItemProps,\n type LegendOverflowProps,\n type LegendProps,\n} from './chart-types';\nimport {\n getComputedElementWidth,\n highlightOrDownplaySeries,\n isThresholdLine,\n resetAllSeriesHighlight,\n useLegendVisibility,\n} from './legend-utils';\nimport { type CommonProps } from './types';\n\nconst LegendItem = function LegendItemComponent({\n children,\n as,\n className,\n name,\n selected,\n deSelected,\n onLegendItemClick,\n color,\n hasButtons = true,\n ref,\n onLegendItemMouseEnter,\n onLegendItemMouseLeave,\n ...restProps\n}: LegendItemProps) {\n const Component = as ?? (hasButtons ? 'button' : 'div');\n\n const classes = classNames(\n 'ndl-chart-legend-item',\n {\n 'ndl-chart-legend-item-deselected': deSelected,\n 'ndl-chart-legend-item-selected': selected,\n },\n className,\n );\n\n // We don't want to display threshold lines in the legend\n if (isThresholdLine(name) ?? false) {\n return null;\n }\n\n return (\n <Component\n className={classes}\n ref={ref}\n data-labelname={name}\n title={name}\n onClick={hasButtons ? onLegendItemClick : undefined}\n onMouseEnter={onLegendItemMouseEnter}\n onMouseLeave={onLegendItemMouseLeave}\n {...restProps}\n >\n <span\n className=\"ndl-chart-legend-item-square\"\n style={\n {\n '--ndl-chart-legend-item-color': color,\n backgroundColor: deSelected === true ? 'transparent' : color,\n } as React.CSSProperties\n }\n >\n {selected === true && (\n <CheckIconOutline className=\"ndl-chart-legend-item-square-checkmark\" />\n )}\n </span>\n <Typography variant=\"body-medium\" className=\"ndl-chart-legend-item-text\">\n {children}\n </Typography>\n </Component>\n );\n};\n\nconst getAllSeriesSelected = (series: LegendProps['series']) =>\n Object.fromEntries(series.map((s) => [s.name ?? '', true]));\n\nconst hasSelectionForCurrentSeries = (\n selection: Record<string, boolean>,\n series: LegendProps['series'],\n) => {\n const selectedNames = Object.keys(selection);\n\n return (\n selectedNames.length === series.length &&\n series.every((s) =>\n Object.prototype.hasOwnProperty.call(selection, s.name ?? ''),\n )\n );\n};\n\n/**\n * Keeps legend rendering in sync with the current ECharts series names.\n *\n * ECharts can briefly keep selection state for the previous pie categories\n * after the dataset changes. Rendering with that stale state makes every new\n * category look deselected for one frame, so we render new series as visible\n * until the effect below reconciles the persisted selection state.\n */\nconst useLegendSelectionForCurrentSeries = (series: LegendProps['series']) => {\n const initialSelected = useMemo(() => getAllSeriesSelected(series), [series]);\n const [selectedSeries, setSelectedSeries] =\n useState<Record<string, boolean>>(initialSelected);\n\n const renderedSelectedSeries = hasSelectionForCurrentSeries(\n selectedSeries,\n series,\n )\n ? selectedSeries\n : initialSelected;\n\n return { renderedSelectedSeries, selectedSeries, setSelectedSeries };\n};\n\nexport const Legend = function LegendComponent({\n className,\n wrappingType = 'wrapping',\n series,\n chartRef,\n selectedRef,\n ref,\n htmlAttributes,\n ...restProps\n}: CommonProps<'div', LegendProps>) {\n const { renderedSelectedSeries, selectedSeries, setSelectedSeries } =\n useLegendSelectionForCurrentSeries(series);\n\n // Keep the shared ref in sync so Chart can read the latest selection state\n // when building setOption. This is the single source of truth for legend filters.\n useEffect(() => {\n if (selectedRef) {\n selectedRef.current = selectedSeries;\n }\n }, [selectedRef, selectedSeries]);\n\n const highlightTimeOut = useRef<ReturnType<typeof setTimeout> | null>(null);\n const downplayTimeOut = useRef<ReturnType<typeof setTimeout> | null>(null);\n const hoverTimeOut = 80;\n\n const highlightSeries = (\n seriesToUpdate: { name: string; color: string }[],\n ) => {\n // Clear the downplay timeout when a new item is hovered\n if (downplayTimeOut.current) {\n clearTimeout(downplayTimeOut.current);\n }\n\n // Delay the highlight to avoid flickering when quickly hovering the legend items\n highlightTimeOut.current = setTimeout(() => {\n highlightOrDownplaySeries(\n chartRef,\n series,\n renderedSelectedSeries,\n seriesToUpdate,\n 'highlight',\n );\n }, hoverTimeOut);\n };\n\n const downplaySeries = (\n seriesToUpdate: { name: string; color: string }[],\n ) => {\n // Clear the highlight timeout when the mouse is leaving the legend item\n if (highlightTimeOut.current) {\n clearTimeout(highlightTimeOut.current);\n }\n\n // Delay the downplay to avoid flickering when moving the highlight between legend items (no downplay needed in between)\n downplayTimeOut.current = setTimeout(() => {\n highlightOrDownplaySeries(\n chartRef,\n series,\n renderedSelectedSeries,\n seriesToUpdate,\n 'downplay',\n );\n }, hoverTimeOut);\n };\n\n useEffect(() => {\n // Preserve existing legend selection state across re-renders.\n // Only new series default to visible (true); removed series are dropped.\n const prev = selectedRef?.current ?? {};\n const next: Record<string, boolean> = {};\n for (const s of series) {\n const name = s.name ?? '';\n next[name] = prev[name] ?? true;\n }\n setSelectedSeries(next);\n\n if (chartRef.current === null) {\n return;\n }\n const chart = getInstanceByDom(chartRef.current);\n\n const eventTypes = [\n 'legendselectchanged',\n 'legendselectall',\n 'legendselected',\n 'legendunselected',\n ] as const;\n\n eventTypes.forEach((eventType) => {\n chart?.on(eventType, (params) => {\n if (\n typeof params === 'object' &&\n params !== null &&\n 'selected' in params &&\n params.selected !== null\n ) {\n const selected = params.selected ?? {};\n const filteredSelected = Object.fromEntries(\n Object.entries(selected).filter(\n ([key]) => !(isThresholdLine(key) ?? false),\n ),\n );\n\n // Reset the series highlight to avoid series to stay blurred on selection change\n if (eventType === 'legendselectchanged') {\n resetAllSeriesHighlight(chart as EChartsType);\n }\n\n setSelectedSeries(filteredSelected);\n }\n });\n });\n\n return () => {\n eventTypes.forEach((eventType) => {\n chart?.off(eventType);\n });\n };\n }, [chartRef, selectedRef, series, setSelectedSeries]);\n\n const classes = classNames(\n `ndl-chart-legend`,\n {\n 'ndl-chart-legend-truncation': wrappingType === 'truncation',\n 'ndl-chart-legend-wrapping': wrappingType === 'wrapping',\n },\n className,\n );\n\n const { toggleLegendVisibility, setAllVisible } = useLegendVisibility(\n chartRef,\n renderedSelectedSeries,\n );\n\n return (\n <div\n ref={ref}\n className=\"ndl-chart-legend-container\"\n {...restProps}\n {...htmlAttributes}\n >\n {wrappingType === 'truncation' || wrappingType === 'wrapping' ? (\n <div className={classes}>\n {series.map((currentSeries, index) => {\n const hasMoreThanOneItem = series.length > 1;\n\n const selectedSeriesLength = Object.values(\n renderedSelectedSeries,\n ).filter(Boolean).length;\n\n const isAllSeriesVisible = selectedSeriesLength === series.length;\n\n const color = currentSeries.color;\n\n const isDeselected =\n currentSeries.name === undefined\n ? false\n : !renderedSelectedSeries[currentSeries.name];\n\n return (\n <ConditionalWrap\n key={index}\n shouldWrap={wrappingType === 'truncation'}\n wrap={(children) => (\n <Tooltip type=\"simple\" key={index}>\n <Tooltip.Trigger hasButtonWrapper>\n {children}\n </Tooltip.Trigger>\n </Tooltip>\n )}\n >\n <LegendItem\n name={currentSeries.name}\n color={color}\n hasButtons={\n hasMoreThanOneItem && currentSeries.name !== undefined\n }\n onLegendItemMouseEnter={() => {\n if (!isDeselected) {\n highlightSeries([currentSeries]);\n }\n }}\n onLegendItemMouseLeave={() => {\n if (!isDeselected) {\n downplaySeries([currentSeries]);\n }\n }}\n onLegendItemClick={() => {\n const isAllSeriesSelected =\n selectedSeriesLength === series.length;\n\n const isOnlyVisible =\n renderedSelectedSeries[currentSeries.name ?? ''] &&\n selectedSeriesLength === 1;\n\n toggleLegendVisibility(\n currentSeries.name,\n isAllSeriesSelected,\n isOnlyVisible,\n );\n }}\n selected={\n !isAllSeriesVisible &&\n renderedSelectedSeries[currentSeries.name ?? '']\n }\n deSelected={isDeselected}\n >\n {currentSeries.name ?? `Series ${index}`}\n </LegendItem>\n </ConditionalWrap>\n );\n })}\n </div>\n ) : (\n <LegendOverflowType\n className={classes}\n selectedSeries={renderedSelectedSeries}\n wrappingType={wrappingType}\n chartRef={chartRef}\n series={series}\n onSetAllVisible={setAllVisible}\n onLegendItemMouseEnter={(seriesToUpdate) =>\n highlightSeries(seriesToUpdate)\n }\n onLegendItemMouseLeave={(seriesToUpdate) =>\n downplaySeries(seriesToUpdate)\n }\n onToggleLegendVisibility={(\n name,\n isAllSeriesSelected,\n isOnlyVisible,\n ) => {\n toggleLegendVisibility(name, isAllSeriesSelected, isOnlyVisible);\n }}\n />\n )}\n </div>\n );\n};\n\nconst LegendOverflowType = function LegendOverflow({\n className,\n series,\n onSetAllVisible,\n onToggleLegendVisibility,\n selectedSeries,\n onLegendItemMouseEnter,\n onLegendItemMouseLeave,\n}: LegendOverflowProps) {\n const containerRef = useRef<HTMLDivElement>(null);\n\n const [nonOverflowItemsNames, setNonOverflowItemsNames] = useState<string[]>(\n series.map((s) => s.name),\n );\n\n useEffect(() => {\n setNonOverflowItemsNames(series.map((s) => s.name));\n }, [series]);\n\n const overflowItemsNames = series.filter(\n (item) => !nonOverflowItemsNames.includes(item.name),\n );\n\n const [width, setWidth] = useState(Infinity);\n useResizeObserver({\n // TODO: remove type cast. use-hooks.ts 3.1.1 has a type issue with the ref, it should be HTMLElement | null\n // https://github.com/juliencrn/usehooks-ts/pull/680\n onResize: (entry) => {\n if (entry.width === undefined) {\n return;\n }\n if (width < entry.width) {\n setNonOverflowItemsNames(series.map((s) => s.name));\n }\n setWidth(entry.width);\n },\n ref: containerRef as React.RefObject<HTMLElement>,\n });\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) {\n return;\n }\n\n let elements = Array.from(container.children);\n if (elements.length === 0 || series.length === 0) {\n return;\n }\n\n let totalWidth = 0;\n\n if (overflowItemsNames.length > 0) {\n const lastElementItem = elements[elements.length - 1];\n const lastItemWidth = getComputedElementWidth(lastElementItem);\n\n elements = elements.slice(0, elements.length - 1);\n totalWidth += lastItemWidth;\n }\n\n elements.forEach((element) => {\n const elementWidth = getComputedElementWidth(element);\n totalWidth += elementWidth;\n const textContent = element.textContent;\n if (!textContent) {\n return;\n }\n const itemName = element.getAttribute('data-labelname');\n if (itemName === null) {\n return;\n }\n if (totalWidth > width) {\n setNonOverflowItemsNames((oldNames) =>\n oldNames.filter((name) => name !== itemName),\n );\n }\n });\n }, [overflowItemsNames.length, series.length, width]);\n\n const classes = classNames(\n {\n 'ndl-chart-legend-calculating': width === Infinity,\n },\n className,\n );\n\n const selectedSeriesLength =\n Object.values(selectedSeries).filter(Boolean).length;\n\n const hasMoreThanOneItem = nonOverflowItemsNames.length > 1;\n const isAllSeriesVisible = selectedSeriesLength === series.length;\n\n const isOverflowItemsDeselected = overflowItemsNames.every(\n (item) => !selectedSeries[item.name ?? ''],\n );\n\n return (\n <div className={classes} ref={containerRef}>\n {nonOverflowItemsNames.map((name) => {\n const currentSeries = series.find((s) => s.name === name);\n if (currentSeries === undefined) {\n return null;\n }\n\n const isDeselected =\n currentSeries.name === undefined\n ? false\n : !selectedSeries[currentSeries.name];\n\n return (\n <LegendItem\n key={name}\n name={name}\n color={currentSeries.color}\n onLegendItemMouseEnter={() =>\n !isDeselected && onLegendItemMouseEnter([currentSeries])\n }\n onLegendItemMouseLeave={() =>\n !isDeselected && onLegendItemMouseLeave([currentSeries])\n }\n onLegendItemClick={() => {\n const isAllSeriesSelected =\n selectedSeriesLength === series.length;\n\n const isOnlyVisible =\n selectedSeries[name ?? ''] && selectedSeriesLength === 1;\n\n onToggleLegendVisibility?.(\n name,\n isAllSeriesSelected,\n isOnlyVisible,\n series,\n );\n }}\n hasButtons={hasMoreThanOneItem}\n selected={\n !isAllSeriesVisible && selectedSeries[currentSeries.name ?? '']\n }\n deSelected={isDeselected}\n >\n {name}\n </LegendItem>\n );\n })}\n\n {overflowItemsNames.length > 0 && (\n <Tooltip type=\"simple\">\n <Tooltip.Trigger hasButtonWrapper>\n <LegendItem\n name=\"ndl-overflow-items\"\n color={tokens.palette.neutral[30]}\n selected={\n !isAllSeriesVisible &&\n overflowItemsNames.every(\n (item) => selectedSeries[item.name ?? ''],\n )\n }\n deSelected={isOverflowItemsDeselected}\n onLegendItemMouseEnter={() =>\n !isOverflowItemsDeselected &&\n onLegendItemMouseEnter(overflowItemsNames)\n }\n onLegendItemMouseLeave={() =>\n !isOverflowItemsDeselected &&\n onLegendItemMouseLeave(overflowItemsNames)\n }\n onLegendItemClick={() => {\n const selectedSeriesLength =\n Object.values(selectedSeries).filter(Boolean).length;\n\n const isOnlyOverflowItemsVisible =\n selectedSeriesLength === overflowItemsNames.length &&\n overflowItemsNames.every(\n (item) => selectedSeries[item.name ?? ''],\n );\n\n if (isOnlyOverflowItemsVisible) {\n onSetAllVisible();\n return;\n }\n\n overflowItemsNames.forEach((item, index) => {\n const isAllSeriesSelected =\n selectedSeriesLength === series.length && index === 0;\n\n onToggleLegendVisibility?.(\n item.name,\n isAllSeriesSelected,\n false,\n series,\n );\n });\n }}\n >\n {overflowItemsNames.length} more\n </LegendItem>\n </Tooltip.Trigger>\n <Tooltip.Content>\n {overflowItemsNames.map((item) => (\n <p key={item.name}>{item.name}</p>\n ))}\n </Tooltip.Content>\n </Tooltip>\n )}\n </div>\n );\n};\n"]}
1
+ {"version":3,"file":"Legend.js","sourceRoot":"","sources":["../../../src/charts/Legend.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,6EAGyC;AACzC,yEAAoE;AACpE,6CAA0C;AAC1C,iDAA8C;AAQ9C;;;;;;;GAOG;AACI,MAAM,MAAM,GAAG,CAAC,EAOiC,EAAE,EAAE;QAPrC,EACrB,SAAS,EACT,MAAM,EACN,aAAa,GAAG,IAAI,EACpB,aAAa,EACb,cAAc,OAEwC,EADnD,SAAS,cANS,2EAOtB,CADa;IAEZ,MAAM,EAAE,sBAAsB,EAAE,GAAG,IAAA,4CAAkB,EAAC;QACpD,MAAM;KACP,CAAC,CAAC;IAEH,MAAM,EAAE,eAAe,EAAE,GAAG,IAAA,iDAAuB,EAAC;QAClD,cAAc,EAAE,sBAAsB;QACtC,MAAM;KACP,CAAC,CAAC;IAEH,MAAM,EAAE,sBAAsB,EAAE,GAAG,IAAA,2CAAmB,EACpD,sBAAsB,CACvB,CAAC;IAEF,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,MAAM,CACvE,OAAO,CACR,CAAC,MAAM,CAAC;IACT,MAAM,kBAAkB,GAAG,oBAAoB,KAAK,MAAM,CAAC,MAAM,CAAC;IAClE,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IAE7C,OAAO,CACL,uBAAC,2BAAY,kBACX,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,aAAa,EAC5B,SAAS,EAAE,MAAM,CAAC,MAAM,EACxB,aAAa,EAAE,aAAa,EAC5B,cAAc,EAAE,cAAc,IAC1B,SAAS,cAEZ,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,KAAK,EAAE,EAAE;;YAAC,OAAA,CACpC,uBAAC,uBAAU,IAET,IAAI,EAAE,aAAa,CAAC,IAAI,EACxB,KAAK,EAAE,aAAa,CAAC,KAAK,EAC1B,UAAU,EAAE,kBAAkB,IAAI,aAAa,CAAC,IAAI,KAAK,SAAS,EAClE,sBAAsB,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,aAAa,EAAE,IAAI,CAAC,EAClE,sBAAsB,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,aAAa,EAAE,KAAK,CAAC,EACnE,iBAAiB,EAAE,GAAG,EAAE;;oBACtB,MAAM,aAAa,GACjB,sBAAsB,CAAC,MAAA,aAAa,CAAC,IAAI,mCAAI,EAAE,CAAC;wBAChD,oBAAoB,KAAK,CAAC,CAAC;oBAE7B,sBAAsB,CACpB,aAAa,CAAC,IAAI,EAClB,kBAAkB,EAClB,aAAa,CACd,CAAC;gBACJ,CAAC,EACD,QAAQ,EACN,CAAC,kBAAkB;oBACnB,sBAAsB,CAAC,MAAA,aAAa,CAAC,IAAI,mCAAI,EAAE,CAAC,EAElD,UAAU,EACR,aAAa,CAAC,IAAI,KAAK,SAAS;oBAC9B,CAAC,CAAC,KAAK;oBACP,CAAC,CAAC,CAAC,sBAAsB,CAAC,aAAa,CAAC,IAAI,CAAC,YAGhD,MAAA,aAAa,CAAC,IAAI,mCAAI,UAAU,KAAK,EAAE,IA3BnC,MAAA,aAAa,CAAC,IAAI,mCAAI,KAAK,CA4BrB,CACd,CAAA;SAAA,CAAC,IACW,CAChB,CAAC;AACJ,CAAC,CAAC;AAtEW,QAAA,MAAM,UAsEjB","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport {\n useLegendHoverHighlight,\n useLegendSelection,\n} from './hooks/use-legend-interactions';\nimport { useLegendVisibility } from './hooks/use-legend-visibility';\nimport { LegendItem } from './LegendItem';\nimport { LegendLayout } from './LegendLayout';\nimport { type CommonProps, type LegendProps } from './utils/chart-types';\n\ntype LegendComponentProps = LegendProps & {\n isLayoutReady?: boolean;\n onLayoutReady?: () => void;\n};\n\n/**\n * Renders the interactive chart legend and keeps legend state synchronized with\n * ECharts.\n *\n * The component owns the React-side selected-series state, mirrors it into the\n * shared ref consumed when rebuilding chart options, and wires item hover/click\n * interactions back to the ECharts instance.\n */\nexport const Legend = ({\n className,\n series,\n isLayoutReady = true,\n onLayoutReady,\n htmlAttributes,\n ...restProps\n}: Omit<CommonProps<'div', LegendComponentProps>, 'ref'>) => {\n const { renderedSelectedSeries } = useLegendSelection({\n series,\n });\n\n const { toggleHighlight } = useLegendHoverHighlight({\n selectedSeries: renderedSelectedSeries,\n series,\n });\n\n const { toggleLegendVisibility } = useLegendVisibility(\n renderedSelectedSeries,\n );\n\n const selectedSeriesLength = Object.values(renderedSelectedSeries).filter(\n Boolean,\n ).length;\n const isAllSeriesVisible = selectedSeriesLength === series.length;\n const hasMoreThanOneItem = series.length > 1;\n\n return (\n <LegendLayout\n className={className}\n isLayoutReady={isLayoutReady}\n itemCount={series.length}\n onLayoutReady={onLayoutReady}\n htmlAttributes={htmlAttributes}\n {...restProps}\n >\n {series.map((currentSeries, index) => (\n <LegendItem\n key={currentSeries.name ?? index}\n name={currentSeries.name}\n color={currentSeries.color}\n hasButtons={hasMoreThanOneItem && currentSeries.name !== undefined}\n onLegendItemMouseEnter={() => toggleHighlight(currentSeries, true)}\n onLegendItemMouseLeave={() => toggleHighlight(currentSeries, false)}\n onLegendItemClick={() => {\n const isOnlyVisible =\n renderedSelectedSeries[currentSeries.name ?? ''] &&\n selectedSeriesLength === 1;\n\n toggleLegendVisibility(\n currentSeries.name,\n isAllSeriesVisible,\n isOnlyVisible,\n );\n }}\n selected={\n !isAllSeriesVisible &&\n renderedSelectedSeries[currentSeries.name ?? '']\n }\n deSelected={\n currentSeries.name === undefined\n ? false\n : !renderedSelectedSeries[currentSeries.name]\n }\n >\n {currentSeries.name ?? `Series ${index}`}\n </LegendItem>\n ))}\n </LegendLayout>\n );\n};\n"]}
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.LegendItem = void 0;
18
+ const jsx_runtime_1 = require("react/jsx-runtime");
19
+ /**
20
+ *
21
+ * Copyright (c) "Neo4j"
22
+ * Neo4j Sweden AB [http://neo4j.com]
23
+ *
24
+ * This file is part of Neo4j.
25
+ *
26
+ * Neo4j is free software: you can redistribute it and/or modify
27
+ * it under the terms of the GNU General Public License as published by
28
+ * the Free Software Foundation, either version 3 of the License, or
29
+ * (at your option) any later version.
30
+ *
31
+ * This program is distributed in the hope that it will be useful,
32
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
33
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34
+ * GNU General Public License for more details.
35
+ *
36
+ * You should have received a copy of the GNU General Public License
37
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
38
+ */
39
+ const react_1 = require("@neo4j-ndl/react");
40
+ const icons_1 = require("@neo4j-ndl/react/icons");
41
+ const classnames_1 = __importDefault(require("classnames"));
42
+ const threshold_1 = require("./utils/threshold");
43
+ /**
44
+ * Renders a single legend entry with its series color, selection indicator, and
45
+ * optional button semantics.
46
+ *
47
+ * Threshold-line series are intentionally skipped because they are chart
48
+ * annotations rather than user-toggleable data series.
49
+ */
50
+ const LegendItem = (_a) => {
51
+ var _b;
52
+ var { children, as, className, name, selected, deSelected, onLegendItemClick, color, hasButtons = true, ref, onLegendItemMouseEnter, onLegendItemMouseLeave } = _a, restProps = __rest(_a, ["children", "as", "className", "name", "selected", "deSelected", "onLegendItemClick", "color", "hasButtons", "ref", "onLegendItemMouseEnter", "onLegendItemMouseLeave"]);
53
+ const Component = as !== null && as !== void 0 ? as : (hasButtons ? 'button' : 'div');
54
+ const classes = (0, classnames_1.default)('ndl-chart-legend-item', {
55
+ 'ndl-chart-legend-item-deselected': deSelected,
56
+ 'ndl-chart-legend-item-selected': selected,
57
+ }, className);
58
+ // We don't want to display threshold lines in the legend
59
+ if ((_b = (0, threshold_1.isThresholdLine)(name)) !== null && _b !== void 0 ? _b : false) {
60
+ return null;
61
+ }
62
+ return ((0, jsx_runtime_1.jsxs)(Component, Object.assign({ className: classes, ref: ref, "data-labelname": name, title: name, onClick: hasButtons ? onLegendItemClick : undefined, onMouseEnter: onLegendItemMouseEnter, onMouseLeave: onLegendItemMouseLeave }, restProps, { children: [(0, jsx_runtime_1.jsx)("span", { className: "ndl-chart-legend-item-square", style: {
63
+ '--ndl-chart-legend-item-color': color,
64
+ backgroundColor: deSelected === true ? 'transparent' : color,
65
+ }, children: selected === true && ((0, jsx_runtime_1.jsx)(icons_1.CheckIconOutline, { className: "ndl-chart-legend-item-square-checkmark" })) }), (0, jsx_runtime_1.jsx)(react_1.Typography, { variant: "body-medium", className: "ndl-chart-legend-item-text", children: children })] })));
66
+ };
67
+ exports.LegendItem = LegendItem;
68
+ //# sourceMappingURL=LegendItem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LegendItem.js","sourceRoot":"","sources":["../../../src/charts/LegendItem.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,4CAA8C;AAC9C,kDAA0D;AAC1D,4DAAoC;AAIpC,iDAAoD;AAEpD;;;;;;GAMG;AACI,MAAM,UAAU,GAAG,CAAC,EAcT,EAAE,EAAE;;QAdK,EACzB,QAAQ,EACR,EAAE,EACF,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,UAAU,EACV,iBAAiB,EACjB,KAAK,EACL,UAAU,GAAG,IAAI,EACjB,GAAG,EACH,sBAAsB,EACtB,sBAAsB,OAEN,EADb,SAAS,cAba,wKAc1B,CADa;IAEZ,MAAM,SAAS,GAAG,EAAE,aAAF,EAAE,cAAF,EAAE,GAAI,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAExD,MAAM,OAAO,GAAG,IAAA,oBAAU,EACxB,uBAAuB,EACvB;QACE,kCAAkC,EAAE,UAAU;QAC9C,gCAAgC,EAAE,QAAQ;KAC3C,EACD,SAAS,CACV,CAAC;IAEF,yDAAyD;IACzD,IAAI,MAAA,IAAA,2BAAe,EAAC,IAAI,CAAC,mCAAI,KAAK,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,wBAAC,SAAS,kBACR,SAAS,EAAE,OAAO,EAClB,GAAG,EAAE,GAAG,oBACQ,IAAI,EACpB,KAAK,EAAE,IAAI,EACX,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS,EACnD,YAAY,EAAE,sBAAsB,EACpC,YAAY,EAAE,sBAAsB,IAChC,SAAS,eAEb,iCACE,SAAS,EAAC,8BAA8B,EACxC,KAAK,EACH;oBACE,+BAA+B,EAAE,KAAK;oBACtC,eAAe,EAAE,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK;iBACtC,YAGzB,QAAQ,KAAK,IAAI,IAAI,CACpB,uBAAC,wBAAgB,IAAC,SAAS,EAAC,wCAAwC,GAAG,CACxE,GACI,EACP,uBAAC,kBAAU,IAAC,OAAO,EAAC,aAAa,EAAC,SAAS,EAAC,4BAA4B,YACrE,QAAQ,GACE,KACH,CACb,CAAC;AACJ,CAAC,CAAC;AA5DW,QAAA,UAAU,cA4DrB","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport { Typography } from '@neo4j-ndl/react';\nimport { CheckIconOutline } from '@neo4j-ndl/react/icons';\nimport classNames from 'classnames';\nimport type React from 'react';\n\nimport { type LegendItemProps } from './utils/chart-types';\nimport { isThresholdLine } from './utils/threshold';\n\n/**\n * Renders a single legend entry with its series color, selection indicator, and\n * optional button semantics.\n *\n * Threshold-line series are intentionally skipped because they are chart\n * annotations rather than user-toggleable data series.\n */\nexport const LegendItem = ({\n children,\n as,\n className,\n name,\n selected,\n deSelected,\n onLegendItemClick,\n color,\n hasButtons = true,\n ref,\n onLegendItemMouseEnter,\n onLegendItemMouseLeave,\n ...restProps\n}: LegendItemProps) => {\n const Component = as ?? (hasButtons ? 'button' : 'div');\n\n const classes = classNames(\n 'ndl-chart-legend-item',\n {\n 'ndl-chart-legend-item-deselected': deSelected,\n 'ndl-chart-legend-item-selected': selected,\n },\n className,\n );\n\n // We don't want to display threshold lines in the legend\n if (isThresholdLine(name) ?? false) {\n return null;\n }\n\n return (\n <Component\n className={classes}\n ref={ref}\n data-labelname={name}\n title={name}\n onClick={hasButtons ? onLegendItemClick : undefined}\n onMouseEnter={onLegendItemMouseEnter}\n onMouseLeave={onLegendItemMouseLeave}\n {...restProps}\n >\n <span\n className=\"ndl-chart-legend-item-square\"\n style={\n {\n '--ndl-chart-legend-item-color': color,\n backgroundColor: deSelected === true ? 'transparent' : color,\n } as React.CSSProperties\n }\n >\n {selected === true && (\n <CheckIconOutline className=\"ndl-chart-legend-item-square-checkmark\" />\n )}\n </span>\n <Typography variant=\"body-medium\" className=\"ndl-chart-legend-item-text\">\n {children}\n </Typography>\n </Component>\n );\n};\n"]}