@classic-homes/charts-react 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,10 @@
1
1
  // src/components/base/ChartContainer.tsx
2
2
  import * as React4 from "react";
3
+ import {
4
+ chartFilename,
5
+ downloadCsv,
6
+ downloadFile
7
+ } from "@classic-homes/charts-core";
3
8
 
4
9
  // src/lib/utils.ts
5
10
  import { clsx } from "clsx";
@@ -83,7 +88,7 @@ var ChartError = React2.forwardRef(
83
88
  {
84
89
  type: "button",
85
90
  onClick: onRetry,
86
- className: "rounded-md bg-destructive px-3 py-1.5 text-xs font-medium text-destructive-foreground transition-colors hover:bg-destructive/90",
91
+ className: "rounded-md bg-destructive px-3 py-1.5 text-xs font-medium text-destructive-foreground hover:bg-destructive/90",
87
92
  children: "Retry"
88
93
  }
89
94
  )
@@ -139,20 +144,64 @@ var ChartEmpty = React3.forwardRef(
139
144
  );
140
145
  ChartEmpty.displayName = "ChartEmpty";
141
146
 
142
- // src/components/base/ChartContainer.tsx
147
+ // src/components/base/ChartDataTable.tsx
148
+ import {
149
+ formatTableCell
150
+ } from "@classic-homes/charts-core";
143
151
  import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
152
+ function ChartDataTable({
153
+ table,
154
+ caption,
155
+ format,
156
+ srOnly = false,
157
+ className
158
+ }) {
159
+ return /* @__PURE__ */ jsx4(
160
+ "div",
161
+ {
162
+ "data-testid": "chart-data-table",
163
+ className: cn(srOnly ? "sr-only" : "max-h-80 overflow-auto", className),
164
+ children: /* @__PURE__ */ jsxs4("table", { className: "w-full border-collapse text-sm", children: [
165
+ /* @__PURE__ */ jsx4("caption", { className: srOnly ? void 0 : "sr-only", children: caption }),
166
+ /* @__PURE__ */ jsx4("thead", { children: /* @__PURE__ */ jsx4("tr", { children: table.headers.map((header, column) => /* @__PURE__ */ jsx4(
167
+ "th",
168
+ {
169
+ scope: "col",
170
+ className: cn(
171
+ "sticky top-0 border-b border-border bg-card px-3 py-2 font-medium text-muted-foreground",
172
+ column === 0 ? "text-left" : "text-right"
173
+ ),
174
+ children: header
175
+ },
176
+ column
177
+ )) }) }),
178
+ /* @__PURE__ */ jsx4("tbody", { children: table.rows.map((row, rowIndex) => /* @__PURE__ */ jsx4("tr", { className: "border-b border-border last:border-0", children: row.map(
179
+ (cell, column) => column === 0 ? /* @__PURE__ */ jsx4(
180
+ "th",
181
+ {
182
+ scope: "row",
183
+ className: "px-3 py-1.5 text-left font-normal text-foreground",
184
+ children: formatTableCell(table, cell, column, format)
185
+ },
186
+ column
187
+ ) : /* @__PURE__ */ jsx4("td", { className: "px-3 py-1.5 text-right tabular-nums text-foreground", children: formatTableCell(table, cell, column, format) }, column)
188
+ ) }, rowIndex)) })
189
+ ] })
190
+ }
191
+ );
192
+ }
193
+
194
+ // src/components/base/ChartContainer.tsx
195
+ import { Fragment, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
144
196
  var CHART_ONLY_PROPS = [
145
- "minHeight",
146
- "maxHeight",
147
197
  "rowHeight",
148
198
  "showLegend",
149
199
  "showGrid",
150
200
  "valueFormat",
151
201
  "locale",
152
202
  "onReady",
203
+ "onHover",
153
204
  "events",
154
- "showDataTable",
155
- "exportable",
156
205
  "patterns",
157
206
  "referenceLines",
158
207
  "referenceBands",
@@ -165,11 +214,15 @@ function domProps(props) {
165
214
  for (const key of CHART_ONLY_PROPS) delete rest[key];
166
215
  return rest;
167
216
  }
217
+ var SR_TABLE_MAX_ROWS = 500;
218
+ var buttonClass = "rounded-md px-2 py-1 text-xs font-medium text-muted-foreground hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
168
219
  var ChartContainer = React4.forwardRef(
169
220
  ({
170
221
  title,
171
222
  description,
172
223
  height = 400,
224
+ minHeight,
225
+ maxHeight,
173
226
  loading,
174
227
  error,
175
228
  empty,
@@ -179,16 +232,24 @@ var ChartContainer = React4.forwardRef(
179
232
  wrapperClassName,
180
233
  legend,
181
234
  legendPosition = "bottom",
235
+ dataTable,
236
+ showDataTable = "sr-only",
237
+ format,
238
+ exportable,
239
+ exportImage,
182
240
  children,
183
241
  ...props
184
242
  }, ref) => {
185
243
  const heightStyle = typeof height === "number" ? `${height}px` : height;
186
- const descriptionId = `${React4.useId()}-desc`;
244
+ const uid = React4.useId();
245
+ const descriptionId = `${uid}-desc`;
246
+ const tableId = `${uid}-table`;
247
+ const [tableOpen, setTableOpen] = React4.useState(false);
187
248
  if (loading) {
188
- return /* @__PURE__ */ jsx4(ChartSkeleton, { height, className: wrapperClassName });
249
+ return /* @__PURE__ */ jsx5(ChartSkeleton, { height, className: wrapperClassName });
189
250
  }
190
251
  if (error) {
191
- return /* @__PURE__ */ jsx4(
252
+ return /* @__PURE__ */ jsx5(
192
253
  ChartError,
193
254
  {
194
255
  message: error,
@@ -199,9 +260,19 @@ var ChartContainer = React4.forwardRef(
199
260
  );
200
261
  }
201
262
  if (empty) {
202
- return /* @__PURE__ */ jsx4(ChartEmpty, { message: emptyMessage, height, className: wrapperClassName });
263
+ return /* @__PURE__ */ jsx5(ChartEmpty, { message: emptyMessage, height, className: wrapperClassName });
203
264
  }
204
- const chart = /* @__PURE__ */ jsxs4(
265
+ const exportConfig = exportable ? exportable === true ? {} : exportable : void 0;
266
+ const canExportImage = !!exportConfig && exportConfig.image !== false && !!exportImage;
267
+ const canExportCsv = !!exportConfig && exportConfig.csv !== false && !!dataTable;
268
+ const filename = exportConfig?.filename ?? chartFilename(title);
269
+ const toggleTable = showDataTable === true && !!dataTable;
270
+ const toolbar = canExportImage || canExportCsv || toggleTable;
271
+ const downloadImage = () => {
272
+ const url = exportImage?.();
273
+ if (url) downloadFile(url, `${filename}.png`);
274
+ };
275
+ const chart = (chartClassName) => /* @__PURE__ */ jsxs5(
205
276
  "div",
206
277
  {
207
278
  ref,
@@ -209,37 +280,95 @@ var ChartContainer = React4.forwardRef(
209
280
  "aria-label": title,
210
281
  "aria-describedby": description ? descriptionId : void 0,
211
282
  "data-testid": "chart-container",
212
- className: legend ? "min-h-0 min-w-0 flex-1" : cn("rounded-lg border border-border bg-card", wrapperClassName),
283
+ className: chartClassName,
213
284
  ...domProps(props),
214
285
  children: [
215
- description && /* @__PURE__ */ jsx4("span", { id: descriptionId, className: "sr-only", children: description }),
216
- /* @__PURE__ */ jsx4("div", { className: cn("h-full w-full", className), style: { height: heightStyle }, children })
286
+ description && /* @__PURE__ */ jsx5("span", { id: descriptionId, className: "sr-only", children: description }),
287
+ /* @__PURE__ */ jsx5(
288
+ "div",
289
+ {
290
+ className: cn("h-full w-full", className),
291
+ style: {
292
+ height: heightStyle,
293
+ minHeight: minHeight !== void 0 ? `${minHeight}px` : void 0,
294
+ maxHeight: maxHeight !== void 0 ? `${maxHeight}px` : void 0
295
+ },
296
+ children
297
+ }
298
+ )
217
299
  ]
218
300
  }
219
301
  );
220
- if (!legend) return chart;
302
+ const srTable = dataTable && showDataTable === "sr-only" && dataTable.rows.length <= SR_TABLE_MAX_ROWS ? /* @__PURE__ */ jsx5(ChartDataTable, { table: dataTable, caption: `${title} data`, format, srOnly: true }) : null;
303
+ if (!legend && !toolbar) {
304
+ return /* @__PURE__ */ jsxs5(Fragment, { children: [
305
+ chart(cn("rounded-lg border border-border bg-card", wrapperClassName)),
306
+ srTable
307
+ ] });
308
+ }
221
309
  const side = legendPosition === "left" || legendPosition === "right";
222
310
  const leading = legendPosition === "top" || legendPosition === "left";
223
- const legendNode = /* @__PURE__ */ jsx4(
311
+ const legendNode = legend ? /* @__PURE__ */ jsx5(
224
312
  "div",
225
313
  {
226
314
  "data-testid": "chart-legend",
227
315
  className: cn("flex shrink-0 p-2", side ? "items-center" : "justify-center"),
228
316
  children: legend
229
317
  }
230
- );
231
- return /* @__PURE__ */ jsxs4(
318
+ ) : null;
319
+ return /* @__PURE__ */ jsxs5(
232
320
  "div",
233
321
  {
234
- className: cn(
235
- "flex rounded-lg border border-border bg-card",
236
- side ? "flex-row" : "flex-col",
237
- wrapperClassName
238
- ),
322
+ "data-testid": "chart-frame",
323
+ className: cn("flex flex-col rounded-lg border border-border bg-card", wrapperClassName),
239
324
  children: [
240
- leading && legendNode,
241
- chart,
242
- !leading && legendNode
325
+ toolbar && /* @__PURE__ */ jsxs5(
326
+ "div",
327
+ {
328
+ "data-testid": "chart-toolbar",
329
+ className: "flex justify-end gap-1 px-2 pt-2 print:hidden",
330
+ children: [
331
+ toggleTable && /* @__PURE__ */ jsx5(
332
+ "button",
333
+ {
334
+ type: "button",
335
+ className: buttonClass,
336
+ "aria-expanded": tableOpen,
337
+ "aria-controls": tableId,
338
+ onClick: () => setTableOpen((open) => !open),
339
+ children: tableOpen ? "Hide data" : "Show data"
340
+ }
341
+ ),
342
+ canExportImage && /* @__PURE__ */ jsx5(
343
+ "button",
344
+ {
345
+ type: "button",
346
+ className: buttonClass,
347
+ "aria-label": `Download ${title} as PNG`,
348
+ onClick: downloadImage,
349
+ children: "PNG"
350
+ }
351
+ ),
352
+ canExportCsv && /* @__PURE__ */ jsx5(
353
+ "button",
354
+ {
355
+ type: "button",
356
+ className: buttonClass,
357
+ "aria-label": `Download ${title} data as CSV`,
358
+ onClick: () => downloadCsv(dataTable, filename),
359
+ children: "CSV"
360
+ }
361
+ )
362
+ ]
363
+ }
364
+ ),
365
+ /* @__PURE__ */ jsxs5("div", { className: cn("flex min-h-0 flex-1", side ? "flex-row" : "flex-col"), children: [
366
+ leading && legendNode,
367
+ chart("min-h-0 min-w-0 flex-1"),
368
+ !leading && legendNode
369
+ ] }),
370
+ toggleTable && /* @__PURE__ */ jsx5("div", { id: tableId, hidden: !tableOpen, className: "border-t border-border p-2", children: tableOpen && /* @__PURE__ */ jsx5(ChartDataTable, { table: dataTable, caption: `${title} data`, format }) }),
371
+ srTable
243
372
  ]
244
373
  }
245
374
  );
@@ -249,11 +378,11 @@ ChartContainer.displayName = "ChartContainer";
249
378
 
250
379
  // src/components/base/ChartLegend.tsx
251
380
  import * as React5 from "react";
252
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
381
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
253
382
  var ChartLegend = React5.forwardRef(
254
383
  ({ items, toggle, position = "bottom", chartTitle, orientation, className }, ref) => {
255
384
  const vertical = (orientation ?? (position === "left" || position === "right" ? "vertical" : "horizontal")) === "vertical";
256
- return /* @__PURE__ */ jsx5(
385
+ return /* @__PURE__ */ jsx6(
257
386
  "ul",
258
387
  {
259
388
  ref,
@@ -263,7 +392,7 @@ var ChartLegend = React5.forwardRef(
263
392
  vertical ? "flex-col" : "flex-wrap justify-center",
264
393
  className
265
394
  ),
266
- children: items.map((item) => /* @__PURE__ */ jsx5("li", { children: /* @__PURE__ */ jsxs5(
395
+ children: items.map((item) => /* @__PURE__ */ jsx6("li", { children: /* @__PURE__ */ jsxs6(
267
396
  "button",
268
397
  {
269
398
  type: "button",
@@ -274,7 +403,7 @@ var ChartLegend = React5.forwardRef(
274
403
  item.visible ? "text-foreground" : "text-muted-foreground line-through"
275
404
  ),
276
405
  children: [
277
- /* @__PURE__ */ jsx5(
406
+ /* @__PURE__ */ jsx6(
278
407
  "span",
279
408
  {
280
409
  "aria-hidden": "true",
@@ -302,29 +431,90 @@ import {
302
431
  LegendComponent,
303
432
  TitleComponent
304
433
  } from "echarts/components";
305
- import { CanvasRenderer } from "echarts/renderers";
434
+ import { CanvasRenderer as CanvasRenderer2 } from "echarts/renderers";
306
435
  import {
307
436
  buildAxis,
308
437
  buildDataLabel,
438
+ buildDataZoom,
309
439
  buildLegend,
310
440
  buildTooltip,
441
+ categoryTable,
442
+ chartFormatters,
311
443
  generateLineChartDescription,
312
444
  getChartColors,
313
445
  hasPointLabels,
314
446
  gridInset,
315
447
  mergeChartOption,
448
+ resolveValueFormatter,
316
449
  seriesLabelLookup,
317
450
  THEME_DARK as THEME_DARK2,
318
- withPointLabels
451
+ toPercentStack,
452
+ withPointLabels,
453
+ withReferenceMarks,
454
+ withZoomInset
319
455
  } from "@classic-homes/charts-core";
320
456
 
457
+ // src/lib/events.ts
458
+ var raw = (params) => params ?? {};
459
+ function toDataPointParams(params, fallbackType) {
460
+ const p = raw(params);
461
+ return {
462
+ type: p.type || fallbackType,
463
+ componentType: p.componentType || "series",
464
+ seriesIndex: p.seriesIndex,
465
+ seriesName: p.seriesName || "",
466
+ dataIndex: p.dataIndex ?? 0,
467
+ name: p.name || "",
468
+ value: p.value,
469
+ color: typeof p.color === "string" ? p.color : void 0,
470
+ event: p.event?.event
471
+ };
472
+ }
473
+ function toSliceParams(params, fallbackType) {
474
+ const p = raw(params);
475
+ return {
476
+ type: p.type || fallbackType,
477
+ componentType: p.componentType || "series",
478
+ seriesIndex: p.seriesIndex,
479
+ seriesName: p.seriesName,
480
+ dataIndex: p.dataIndex,
481
+ name: p.name || "",
482
+ value: p.value,
483
+ percent: p.percent,
484
+ color: typeof p.color === "string" ? p.color : void 0,
485
+ event: p.event?.event
486
+ };
487
+ }
488
+ function chartEvents(events, mapped) {
489
+ const merged = { ...events };
490
+ for (const [name, handler] of Object.entries(mapped)) {
491
+ if (!handler) continue;
492
+ const own = events?.[name];
493
+ merged[name] = own ? (params) => {
494
+ handler(params);
495
+ own(params);
496
+ } : handler;
497
+ }
498
+ return merged;
499
+ }
500
+
321
501
  // src/hooks/useChart.ts
322
- import { useEffect as useEffect4, useRef } from "react";
502
+ import { useCallback, useEffect as useEffect4, useRef, useState as useState5 } from "react";
323
503
  import * as echarts2 from "echarts/core";
504
+ import {
505
+ AriaComponent,
506
+ DataZoomInsideComponent,
507
+ DataZoomSliderComponent,
508
+ DatasetComponent,
509
+ GraphicComponent,
510
+ MarkAreaComponent,
511
+ MarkLineComponent
512
+ } from "echarts/components";
513
+ import { CanvasRenderer } from "echarts/renderers";
324
514
  import { getReplaceMerge } from "@classic-homes/charts-core";
325
515
 
326
516
  // src/hooks/useChartTheme.ts
327
- import { useEffect, useState } from "react";
517
+ import { useEffect, useState as useState2 } from "react";
328
518
  import * as echarts from "echarts/core";
329
519
  import { lightTheme, darkTheme, THEME_LIGHT, THEME_DARK } from "@classic-homes/charts-core";
330
520
  var themesRegistered = false;
@@ -342,7 +532,7 @@ function resolveTheme(preference) {
342
532
  return document.documentElement.classList.contains("dark") ? THEME_DARK : THEME_LIGHT;
343
533
  }
344
534
  function useChartTheme(preference = "auto") {
345
- const [currentTheme, setCurrentTheme] = useState(() => resolveTheme(preference));
535
+ const [currentTheme, setCurrentTheme] = useState2(() => resolveTheme(preference));
346
536
  useEffect(() => {
347
537
  registerClassicThemes();
348
538
  const updateTheme = () => setCurrentTheme(resolveTheme(preference));
@@ -367,10 +557,10 @@ function useChartTheme(preference = "auto") {
367
557
  }
368
558
 
369
559
  // src/hooks/useChartResize.ts
370
- import { useEffect as useEffect2, useLayoutEffect, useState as useState2 } from "react";
560
+ import { useEffect as useEffect2, useLayoutEffect, useState as useState3 } from "react";
371
561
  var useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect2 : useLayoutEffect;
372
562
  function useRefElement(ref) {
373
- const [element, setElement] = useState2(null);
563
+ const [element, setElement] = useState3(null);
374
564
  useIsomorphicLayoutEffect(() => {
375
565
  setElement(ref.current);
376
566
  });
@@ -399,9 +589,9 @@ function useChartResize(chartRef, containerRef) {
399
589
  }
400
590
 
401
591
  // src/hooks/useReducedMotion.ts
402
- import { useState as useState3, useEffect as useEffect3 } from "react";
592
+ import { useState as useState4, useEffect as useEffect3 } from "react";
403
593
  function useReducedMotion() {
404
- const [reducedMotion, setReducedMotion] = useState3(false);
594
+ const [reducedMotion, setReducedMotion] = useState4(false);
405
595
  useEffect3(() => {
406
596
  const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
407
597
  setReducedMotion(mediaQuery.matches);
@@ -417,6 +607,23 @@ function useReducedMotion() {
417
607
  }
418
608
 
419
609
  // src/hooks/useChart.ts
610
+ echarts2.use([
611
+ AriaComponent,
612
+ DataZoomInsideComponent,
613
+ DataZoomSliderComponent,
614
+ DatasetComponent,
615
+ GraphicComponent,
616
+ MarkAreaComponent,
617
+ MarkLineComponent,
618
+ CanvasRenderer
619
+ ]);
620
+ var registerEchartsModules = (modules) => echarts2.use(modules);
621
+ function exportChartImage(chart, { type = "png", pixelRatio = 2, backgroundColor } = {}) {
622
+ if (!chart || chart.isDisposed()) return null;
623
+ const background = backgroundColor ?? (typeof document !== "undefined" ? getComputedStyle(chart.getDom()).getPropertyValue("--card").trim() : "");
624
+ const color = !background ? "#ffffff" : /^[\d.]+\s/.test(background) ? `hsl(${background})` : background;
625
+ return chart.getDataURL({ type, pixelRatio, backgroundColor: color });
626
+ }
420
627
  var isComponentType = (mainType) => echarts2.ComponentModel.hasClass(mainType);
421
628
  function applyOption(chart, prev, next) {
422
629
  chart.setOption(next, {
@@ -424,56 +631,116 @@ function applyOption(chart, prev, next) {
424
631
  lazyUpdate: true
425
632
  });
426
633
  }
634
+ function captureState(chart) {
635
+ if (chart.isDisposed()) return null;
636
+ const option = chart.getOption();
637
+ const selected = option.legend?.[0]?.selected ?? {};
638
+ return {
639
+ hidden: Object.keys(selected).filter((name) => selected[name] === false),
640
+ zoom: (option.dataZoom ?? []).map(({ start, end }) => ({ start, end }))
641
+ };
642
+ }
643
+ function restoreState(chart, state) {
644
+ if (!state) return;
645
+ for (const name of state.hidden) chart.dispatchAction({ type: "legendUnSelect", name });
646
+ state.zoom.forEach(({ start, end }, dataZoomIndex) => {
647
+ if (start !== void 0 && end !== void 0 && (start !== 0 || end !== 100)) {
648
+ chart.dispatchAction({ type: "dataZoom", dataZoomIndex, start, end });
649
+ }
650
+ });
651
+ }
427
652
  function useChart({
428
653
  option,
429
654
  theme = "auto",
430
655
  animation,
431
- onReady
656
+ patterns,
657
+ events,
658
+ onReady,
659
+ onCreated
432
660
  }) {
433
661
  const containerRef = useRef(null);
434
662
  const container = useRefElement(containerRef);
435
663
  const chartRef = useRef(null);
664
+ const [chart, setChart] = useState5(null);
436
665
  const currentTheme = useChartTheme(theme);
437
666
  const reducedMotion = useReducedMotion();
438
667
  const onReadyRef = useRef(onReady);
439
668
  onReadyRef.current = onReady;
669
+ const onCreatedRef = useRef(onCreated);
670
+ onCreatedRef.current = onCreated;
671
+ const eventsRef = useRef(events);
672
+ eventsRef.current = events;
440
673
  const optionRef = useRef(option);
441
674
  optionRef.current = {
442
675
  ...option,
443
676
  // Reduced motion always wins over the animation prop
444
- animation: (animation ?? true) && !reducedMotion
677
+ animation: (animation ?? true) && !reducedMotion,
678
+ // Labels stay off: the container already describes the chart
679
+ ...patterns && {
680
+ aria: { enabled: true, label: { enabled: false }, decal: { show: true } }
681
+ }
445
682
  };
446
683
  const appliedRef = useRef(null);
684
+ const carriedRef = useRef(null);
447
685
  useEffect4(() => {
448
686
  if (!container) return;
449
- const chart = echarts2.init(container, currentTheme);
450
- chartRef.current = chart;
451
- applyOption(chart, null, optionRef.current);
687
+ const instance = echarts2.init(container, currentTheme);
688
+ chartRef.current = instance;
689
+ onReadyRef.current?.(instance);
690
+ applyOption(instance, null, optionRef.current);
452
691
  appliedRef.current = optionRef.current;
453
- onReadyRef.current?.(chart);
692
+ const carried = carriedRef.current;
693
+ carriedRef.current = null;
694
+ if (carried) instance.setOption({}, { lazyUpdate: false });
695
+ restoreState(instance, carried);
696
+ onCreatedRef.current?.(instance);
697
+ setChart(instance);
454
698
  return () => {
455
- chart.dispose();
456
- if (chartRef.current === chart) {
699
+ carriedRef.current = captureState(instance);
700
+ instance.dispose();
701
+ if (chartRef.current === instance) {
457
702
  chartRef.current = null;
458
703
  }
704
+ setChart((current) => current === instance ? null : current);
459
705
  };
460
706
  }, [container, currentTheme]);
461
707
  useEffect4(() => {
462
- const chart = chartRef.current;
463
- if (!chart || chart.isDisposed()) return;
464
- applyOption(chart, appliedRef.current, optionRef.current);
708
+ const instance = chartRef.current;
709
+ if (!instance || instance.isDisposed()) return;
710
+ applyOption(instance, appliedRef.current, optionRef.current);
465
711
  appliedRef.current = optionRef.current;
466
- }, [option, animation, reducedMotion]);
712
+ }, [option, animation, reducedMotion, patterns]);
713
+ const eventNames = JSON.stringify(
714
+ Object.keys(events ?? {}).filter((name) => events?.[name]).sort()
715
+ );
716
+ useEffect4(() => {
717
+ if (!chart || chart.isDisposed()) return;
718
+ const bound = JSON.parse(eventNames).map((name) => {
719
+ const listener = (params) => eventsRef.current?.[name]?.(params);
720
+ chart.on(name, listener);
721
+ return [name, listener];
722
+ });
723
+ return () => {
724
+ if (chart.isDisposed()) return;
725
+ for (const [name, listener] of bound) chart.off(name, listener);
726
+ };
727
+ }, [chart, eventNames]);
467
728
  useChartResize(chartRef, containerRef);
729
+ const exportImage = useCallback(
730
+ (options) => exportChartImage(chartRef.current, options),
731
+ []
732
+ );
468
733
  return {
469
734
  chartRef,
470
735
  containerRef,
471
- currentTheme
736
+ chart,
737
+ currentTheme,
738
+ exportImage
472
739
  };
473
740
  }
474
741
 
475
742
  // src/hooks/useChartLegend.ts
476
- import { useCallback, useRef as useRef3, useState as useState4 } from "react";
743
+ import { useCallback as useCallback2, useRef as useRef3, useState as useState6 } from "react";
477
744
  import {
478
745
  getLegendItems
479
746
  } from "@classic-homes/charts-core";
@@ -503,9 +770,9 @@ function useChartLegend({
503
770
  onLegendChange
504
771
  }) {
505
772
  const chartRef = useRef3(null);
506
- const [visible, setVisible] = useState4({});
773
+ const [visible, setVisible] = useState6({});
507
774
  const latest = useLatestRef({ onLegendChange });
508
- const attach = useCallback(
775
+ const attach = useCallback2(
509
776
  (chart) => {
510
777
  chartRef.current = chart;
511
778
  setVisible({});
@@ -541,14 +808,14 @@ function useChartLegend({
541
808
  }
542
809
 
543
810
  // src/components/core/LineChart.tsx
544
- import { jsx as jsx6 } from "react/jsx-runtime";
811
+ import { jsx as jsx7 } from "react/jsx-runtime";
545
812
  echarts3.use([
546
813
  EChartsLineChart,
547
814
  GridComponent,
548
815
  TooltipComponent,
549
816
  LegendComponent,
550
817
  TitleComponent,
551
- CanvasRenderer
818
+ CanvasRenderer2
552
819
  ]);
553
820
  var LineChart = React6.forwardRef(
554
821
  ({
@@ -556,6 +823,8 @@ var LineChart = React6.forwardRef(
556
823
  description,
557
824
  data,
558
825
  height = 400,
826
+ minHeight,
827
+ maxHeight,
559
828
  loading,
560
829
  error,
561
830
  emptyMessage,
@@ -568,22 +837,34 @@ var LineChart = React6.forwardRef(
568
837
  areaFilled = false,
569
838
  showDataPoints = false,
570
839
  stacked = false,
840
+ connectNulls = false,
571
841
  showLabels = false,
842
+ valueFormat,
843
+ locale,
572
844
  labelFormatter,
573
845
  xAxisConfig,
574
846
  yAxisConfig,
847
+ referenceLines,
848
+ referenceBands,
849
+ dataZoom,
575
850
  tooltipFormatter,
576
851
  tooltipValueFormatter,
577
852
  legend: legendConfig,
578
853
  renderLegend,
579
854
  onLegendChange,
580
855
  option: optionOverride,
856
+ onReady,
857
+ events,
858
+ showDataTable,
859
+ exportable,
860
+ patterns,
581
861
  onClick,
582
862
  onHover,
583
863
  class: className,
584
864
  ...props
585
865
  }, ref) => {
586
866
  const isEmpty = !data?.categories?.length || !data?.series?.length || data.series.every((s) => !s.data?.length);
867
+ const isPercent = stacked === "percent";
587
868
  const currentTheme = useChartTheme(theme);
588
869
  const chartColors = getChartColors(currentTheme);
589
870
  const legend = useChartLegend({
@@ -595,10 +876,41 @@ var LineChart = React6.forwardRef(
595
876
  onLegendChange
596
877
  });
597
878
  const customLegend = renderLegend !== void 0;
879
+ const builtInLegend = showLegend && !customLegend;
598
880
  const option = React6.useMemo(() => {
599
881
  if (isEmpty) return {};
882
+ const formatters = chartFormatters({
883
+ valueFormat: isPercent ? "percentValue" : valueFormat,
884
+ locale,
885
+ tooltipValueFormatter,
886
+ labelFormatter
887
+ });
888
+ const plotted = isPercent ? toPercentStack(data.series) : data.series;
600
889
  const getLabel = seriesLabelLookup(data.series);
601
890
  const showSymbol = showDataPoints || showLabels || hasPointLabels(data.series);
891
+ const legendBottom = builtInLegend && (legendConfig?.position ?? "bottom") === "bottom";
892
+ const series = data.series.map((source, index) => ({
893
+ name: source.name,
894
+ type: "line",
895
+ data: withPointLabels(plotted[index].data, source.labels, formatters.label, {
896
+ position: "top"
897
+ }),
898
+ smooth,
899
+ showSymbol,
900
+ symbolSize: showDataPoints ? 6 : 0,
901
+ connectNulls,
902
+ stack: stacked ? "Total" : void 0,
903
+ areaStyle: areaFilled ? { opacity: 0.3 } : void 0,
904
+ itemStyle: source.color ? { color: source.color } : void 0,
905
+ label: buildDataLabel({ show: true, position: "top" }, void 0, {
906
+ show: showLabels,
907
+ formatter: formatters.label,
908
+ getLabel
909
+ }),
910
+ emphasis: {
911
+ focus: "series"
912
+ }
913
+ }));
602
914
  return mergeChartOption(
603
915
  {
604
916
  grid: {
@@ -606,7 +918,11 @@ var LineChart = React6.forwardRef(
606
918
  right: "4%",
607
919
  bottom: "3%",
608
920
  containLabel: true,
609
- ...gridInset(legendConfig, showLegend && !customLegend, xAxisConfig, yAxisConfig)
921
+ ...withZoomInset(
922
+ gridInset(legendConfig, builtInLegend, xAxisConfig, yAxisConfig),
923
+ dataZoom,
924
+ "x"
925
+ )
610
926
  },
611
927
  tooltip: buildTooltip(
612
928
  {
@@ -621,7 +937,7 @@ var LineChart = React6.forwardRef(
621
937
  {
622
938
  show: showTooltip,
623
939
  formatter: tooltipFormatter,
624
- valueFormatter: tooltipValueFormatter,
940
+ valueFormatter: formatters.tooltip,
625
941
  getLabel
626
942
  }
627
943
  ),
@@ -630,6 +946,7 @@ var LineChart = React6.forwardRef(
630
946
  legendConfig,
631
947
  { show: showLegend, custom: customLegend }
632
948
  ),
949
+ dataZoom: buildDataZoom(dataZoom, "x", legendBottom ? 36 : 0),
633
950
  xAxis: buildAxis(
634
951
  {
635
952
  type: "category",
@@ -644,31 +961,19 @@ var LineChart = React6.forwardRef(
644
961
  yAxis: buildAxis(
645
962
  {
646
963
  type: "value",
964
+ ...isPercent && { max: 100 },
647
965
  splitLine: {
648
966
  show: showGrid
649
967
  }
650
968
  },
651
- yAxisConfig
969
+ formatters.axis(yAxisConfig)
652
970
  ),
653
- series: data.series.map((series) => ({
654
- name: series.name,
655
- type: "line",
656
- data: withPointLabels(series.data, series.labels, labelFormatter, { position: "top" }),
657
- smooth,
658
- showSymbol,
659
- symbolSize: showDataPoints ? 6 : 0,
660
- stack: stacked ? "Total" : void 0,
661
- areaStyle: areaFilled ? { opacity: 0.3 } : void 0,
662
- itemStyle: series.color ? { color: series.color } : void 0,
663
- label: buildDataLabel({ show: true, position: "top" }, void 0, {
664
- show: showLabels,
665
- formatter: labelFormatter,
666
- getLabel
667
- }),
668
- emphasis: {
669
- focus: "series"
670
- }
671
- }))
971
+ series: withReferenceMarks(series, referenceLines, referenceBands, {
972
+ valueAxis: "y",
973
+ format: formatters.format,
974
+ color: chartColors.reference,
975
+ bandColor: chartColors.referenceBand
976
+ })
672
977
  },
673
978
  optionOverride
674
979
  );
@@ -682,62 +987,48 @@ var LineChart = React6.forwardRef(
682
987
  areaFilled,
683
988
  showDataPoints,
684
989
  stacked,
990
+ isPercent,
991
+ connectNulls,
685
992
  chartColors,
686
993
  showLabels,
994
+ valueFormat,
995
+ locale,
687
996
  labelFormatter,
688
997
  xAxisConfig,
689
998
  yAxisConfig,
999
+ referenceLines,
1000
+ referenceBands,
1001
+ dataZoom,
690
1002
  tooltipFormatter,
691
1003
  tooltipValueFormatter,
692
1004
  legendConfig,
693
1005
  customLegend,
1006
+ builtInLegend,
694
1007
  optionOverride
695
1008
  ]);
696
- const latest = useLatestRef({ onClick, onHover });
697
- const { containerRef } = useChart({
1009
+ const { containerRef, exportImage } = useChart({
698
1010
  option,
699
1011
  theme: currentTheme === THEME_DARK2 ? "dark" : "light",
700
1012
  animation,
701
- onReady: (chart) => {
702
- legend.attach(chart);
703
- chart.on("click", (params) => {
704
- const { onClick: onClick2 } = latest.current;
705
- if (!onClick2) return;
706
- onClick2({
707
- type: params.type || "click",
708
- componentType: params.componentType || "series",
709
- seriesIndex: params.seriesIndex,
710
- seriesName: params.seriesName || "",
711
- dataIndex: params.dataIndex || 0,
712
- name: params.name || "",
713
- value: params.value,
714
- color: params.color
715
- });
716
- });
717
- chart.on("mouseover", (params) => {
718
- const { onHover: onHover2 } = latest.current;
719
- if (!onHover2) return;
720
- onHover2({
721
- type: params.type || "mouseover",
722
- componentType: params.componentType || "series",
723
- seriesIndex: params.seriesIndex,
724
- seriesName: params.seriesName || "",
725
- dataIndex: params.dataIndex || 0,
726
- name: params.name || "",
727
- value: params.value,
728
- color: params.color
729
- });
730
- });
731
- }
1013
+ patterns,
1014
+ events: chartEvents(events, {
1015
+ click: onClick && ((params) => onClick(toDataPointParams(params, "click"))),
1016
+ mouseover: onHover && ((params) => onHover(toDataPointParams(params, "mouseover")))
1017
+ }),
1018
+ onReady: legend.attach,
1019
+ onCreated: onReady
732
1020
  });
733
- const accessibilityDescription = description || (!isEmpty ? generateLineChartDescription(title, data) : void 0);
734
- return /* @__PURE__ */ jsx6(
1021
+ const format = resolveValueFormatter(valueFormat, locale);
1022
+ const accessibilityDescription = description || (!isEmpty ? generateLineChartDescription(title, data, format) : void 0);
1023
+ return /* @__PURE__ */ jsx7(
735
1024
  ChartContainer,
736
1025
  {
737
1026
  ref,
738
1027
  title,
739
1028
  description: accessibilityDescription,
740
1029
  height,
1030
+ minHeight,
1031
+ maxHeight,
741
1032
  loading,
742
1033
  error,
743
1034
  empty: isEmpty,
@@ -745,8 +1036,13 @@ var LineChart = React6.forwardRef(
745
1036
  className: cn(className),
746
1037
  legend: !isEmpty && renderLegend ? renderLegend(legend.renderProps) : void 0,
747
1038
  legendPosition: legendConfig?.position,
1039
+ dataTable: isEmpty ? void 0 : categoryTable(data),
1040
+ showDataTable,
1041
+ format,
1042
+ exportable,
1043
+ exportImage,
748
1044
  ...props,
749
- children: /* @__PURE__ */ jsx6("div", { ref: containerRef, className: "h-full w-full" })
1045
+ children: /* @__PURE__ */ jsx7("div", { ref: containerRef, className: "h-full w-full" })
750
1046
  }
751
1047
  );
752
1048
  }
@@ -763,27 +1059,35 @@ import {
763
1059
  LegendComponent as LegendComponent2,
764
1060
  TitleComponent as TitleComponent2
765
1061
  } from "echarts/components";
766
- import { CanvasRenderer as CanvasRenderer2 } from "echarts/renderers";
1062
+ import { CanvasRenderer as CanvasRenderer3 } from "echarts/renderers";
767
1063
  import {
768
1064
  buildAxis as buildAxis2,
769
1065
  buildDataLabel as buildDataLabel2,
1066
+ buildDataZoom as buildDataZoom2,
770
1067
  buildLegend as buildLegend2,
771
1068
  buildTooltip as buildTooltip2,
1069
+ categoryTable as categoryTable2,
1070
+ chartFormatters as chartFormatters2,
772
1071
  generateBarChartDescription,
773
1072
  getChartColors as getChartColors2,
774
1073
  gridInset as gridInset2,
775
1074
  mergeChartOption as mergeChartOption2,
1075
+ resolveChartHeight,
1076
+ resolveValueFormatter as resolveValueFormatter2,
776
1077
  seriesLabelLookup as seriesLabelLookup2,
777
- withPointLabels as withPointLabels2
1078
+ toPercentStack as toPercentStack2,
1079
+ withPointLabels as withPointLabels2,
1080
+ withReferenceMarks as withReferenceMarks2,
1081
+ withZoomInset as withZoomInset2
778
1082
  } from "@classic-homes/charts-core";
779
- import { jsx as jsx7 } from "react/jsx-runtime";
1083
+ import { jsx as jsx8 } from "react/jsx-runtime";
780
1084
  echarts4.use([
781
1085
  EChartsBarChart,
782
1086
  GridComponent2,
783
1087
  TooltipComponent2,
784
1088
  LegendComponent2,
785
1089
  TitleComponent2,
786
- CanvasRenderer2
1090
+ CanvasRenderer3
787
1091
  ]);
788
1092
  var BarChart = React7.forwardRef(
789
1093
  ({
@@ -791,6 +1095,9 @@ var BarChart = React7.forwardRef(
791
1095
  description,
792
1096
  data,
793
1097
  height = 400,
1098
+ minHeight,
1099
+ maxHeight,
1100
+ rowHeight,
794
1101
  loading,
795
1102
  error,
796
1103
  emptyMessage,
@@ -802,33 +1109,54 @@ var BarChart = React7.forwardRef(
802
1109
  orientation = "vertical",
803
1110
  stacked = false,
804
1111
  showValues = false,
1112
+ valueFormat,
1113
+ locale,
805
1114
  labelFormatter,
806
1115
  xAxisConfig,
807
1116
  yAxisConfig,
1117
+ referenceLines,
1118
+ referenceBands,
1119
+ dataZoom,
808
1120
  tooltipFormatter,
809
1121
  tooltipValueFormatter,
810
1122
  legend: legendConfig,
811
1123
  renderLegend,
812
1124
  onLegendChange,
813
1125
  option: optionOverride,
1126
+ onReady,
1127
+ events,
1128
+ showDataTable,
1129
+ exportable,
1130
+ patterns,
814
1131
  onClick,
1132
+ onHover,
815
1133
  class: className,
816
1134
  ...props
817
1135
  }, ref) => {
818
1136
  const isEmpty = !data?.categories?.length || !data?.series?.length || data.series.every((s) => !s.data?.length);
819
1137
  const isHorizontal = orientation === "horizontal";
1138
+ const isPercent = stacked === "percent";
820
1139
  const currentTheme = useChartTheme(theme);
1140
+ const chartColors = getChartColors2(currentTheme);
821
1141
  const legend = useChartLegend({
822
1142
  names: data?.series?.map((s) => s.name) ?? [],
823
1143
  colors: data?.series?.map((s) => s.color) ?? [],
824
- palette: getChartColors2(currentTheme).series,
1144
+ palette: chartColors.series,
825
1145
  config: legendConfig,
826
1146
  title,
827
1147
  onLegendChange
828
1148
  });
829
1149
  const customLegend = renderLegend !== void 0;
1150
+ const builtInLegend = showLegend && !customLegend;
830
1151
  const option = React7.useMemo(() => {
831
1152
  if (isEmpty) return {};
1153
+ const formatters = chartFormatters2({
1154
+ valueFormat: isPercent ? "percentValue" : valueFormat,
1155
+ locale,
1156
+ tooltipValueFormatter,
1157
+ labelFormatter
1158
+ });
1159
+ const plotted = isPercent ? toPercentStack2(data.series) : data.series;
832
1160
  const categoryAxis = {
833
1161
  type: "category",
834
1162
  data: data.categories,
@@ -840,11 +1168,32 @@ var BarChart = React7.forwardRef(
840
1168
  };
841
1169
  const valueAxis = {
842
1170
  type: "value",
1171
+ ...isPercent && { max: 100 },
843
1172
  splitLine: {
844
1173
  show: showGrid
845
1174
  }
846
1175
  };
847
1176
  const getLabel = seriesLabelLookup2(data.series);
1177
+ const labelPosition = isHorizontal ? "right" : "top";
1178
+ const zoomAxis = isHorizontal ? "y" : "x";
1179
+ const legendBottom = builtInLegend && (legendConfig?.position ?? "bottom") === "bottom";
1180
+ const series = data.series.map((source, index) => ({
1181
+ name: source.name,
1182
+ type: "bar",
1183
+ data: withPointLabels2(plotted[index].data, source.labels, formatters.label, {
1184
+ position: labelPosition
1185
+ }),
1186
+ stack: stacked ? "Total" : void 0,
1187
+ itemStyle: source.color ? { color: source.color } : void 0,
1188
+ label: buildDataLabel2({ show: true, position: labelPosition }, void 0, {
1189
+ show: showValues,
1190
+ formatter: formatters.label,
1191
+ getLabel
1192
+ }),
1193
+ emphasis: {
1194
+ focus: "series"
1195
+ }
1196
+ }));
848
1197
  return mergeChartOption2(
849
1198
  {
850
1199
  grid: {
@@ -852,7 +1201,11 @@ var BarChart = React7.forwardRef(
852
1201
  right: "4%",
853
1202
  bottom: "3%",
854
1203
  containLabel: true,
855
- ...gridInset2(legendConfig, showLegend && !customLegend, xAxisConfig, yAxisConfig)
1204
+ ...withZoomInset2(
1205
+ gridInset2(legendConfig, builtInLegend, xAxisConfig, yAxisConfig),
1206
+ dataZoom,
1207
+ zoomAxis
1208
+ )
856
1209
  },
857
1210
  tooltip: buildTooltip2(
858
1211
  {
@@ -864,7 +1217,7 @@ var BarChart = React7.forwardRef(
864
1217
  {
865
1218
  show: showTooltip,
866
1219
  formatter: tooltipFormatter,
867
- valueFormatter: tooltipValueFormatter,
1220
+ valueFormatter: formatters.tooltip,
868
1221
  getLabel
869
1222
  }
870
1223
  ),
@@ -873,28 +1226,22 @@ var BarChart = React7.forwardRef(
873
1226
  legendConfig,
874
1227
  { show: showLegend, custom: customLegend }
875
1228
  ),
876
- xAxis: buildAxis2(isHorizontal ? valueAxis : categoryAxis, xAxisConfig),
877
- yAxis: buildAxis2(isHorizontal ? categoryAxis : valueAxis, yAxisConfig),
878
- series: data.series.map((series) => ({
879
- name: series.name,
880
- type: "bar",
881
- data: withPointLabels2(series.data, series.labels, labelFormatter, {
882
- position: isHorizontal ? "right" : "top"
883
- }),
884
- stack: stacked ? "Total" : void 0,
885
- itemStyle: series.color ? { color: series.color } : void 0,
886
- label: buildDataLabel2(
887
- {
888
- show: true,
889
- position: isHorizontal ? "right" : "top"
890
- },
891
- void 0,
892
- { show: showValues, formatter: labelFormatter, getLabel }
893
- ),
894
- emphasis: {
895
- focus: "series"
896
- }
897
- }))
1229
+ dataZoom: buildDataZoom2(dataZoom, zoomAxis, legendBottom ? 36 : 0),
1230
+ xAxis: buildAxis2(
1231
+ isHorizontal ? valueAxis : categoryAxis,
1232
+ isHorizontal ? formatters.axis(xAxisConfig) : xAxisConfig
1233
+ ),
1234
+ yAxis: buildAxis2(
1235
+ isHorizontal ? categoryAxis : valueAxis,
1236
+ isHorizontal ? yAxisConfig : formatters.axis(yAxisConfig)
1237
+ ),
1238
+ series: withReferenceMarks2(series, referenceLines, referenceBands, {
1239
+ valueAxis: isHorizontal ? "x" : "y",
1240
+ inverse: isHorizontal,
1241
+ format: formatters.format,
1242
+ color: chartColors.reference,
1243
+ bandColor: chartColors.referenceBand
1244
+ })
898
1245
  },
899
1246
  optionOverride
900
1247
  );
@@ -905,48 +1252,54 @@ var BarChart = React7.forwardRef(
905
1252
  showLegend,
906
1253
  showGrid,
907
1254
  isHorizontal,
1255
+ isPercent,
908
1256
  stacked,
909
1257
  showValues,
1258
+ valueFormat,
1259
+ locale,
910
1260
  labelFormatter,
911
1261
  xAxisConfig,
912
1262
  yAxisConfig,
1263
+ referenceLines,
1264
+ referenceBands,
1265
+ dataZoom,
913
1266
  tooltipFormatter,
914
1267
  tooltipValueFormatter,
915
1268
  legendConfig,
916
1269
  customLegend,
1270
+ builtInLegend,
1271
+ chartColors,
917
1272
  optionOverride
918
1273
  ]);
919
- const latest = useLatestRef({ onClick });
920
- const { containerRef } = useChart({
1274
+ const { containerRef, exportImage } = useChart({
921
1275
  option,
922
1276
  theme,
923
1277
  animation,
924
- onReady: (chart) => {
925
- legend.attach(chart);
926
- chart.on("click", (params) => {
927
- const { onClick: onClick2 } = latest.current;
928
- if (!onClick2) return;
929
- onClick2({
930
- type: params.type || "click",
931
- componentType: params.componentType || "series",
932
- seriesIndex: params.seriesIndex,
933
- seriesName: params.seriesName || "",
934
- dataIndex: params.dataIndex || 0,
935
- name: params.name || "",
936
- value: params.value,
937
- color: params.color
938
- });
939
- });
940
- }
1278
+ patterns,
1279
+ events: chartEvents(events, {
1280
+ click: onClick && ((params) => onClick(toDataPointParams(params, "click"))),
1281
+ mouseover: onHover && ((params) => onHover(toDataPointParams(params, "mouseover")))
1282
+ }),
1283
+ onReady: legend.attach,
1284
+ onCreated: onReady
941
1285
  });
942
- const accessibilityDescription = description || (!isEmpty ? generateBarChartDescription(title, data) : void 0);
943
- return /* @__PURE__ */ jsx7(
1286
+ const format = resolveValueFormatter2(valueFormat, locale);
1287
+ const accessibilityDescription = description || (!isEmpty ? generateBarChartDescription(title, data, format) : void 0);
1288
+ const resolvedHeight = isHorizontal ? resolveChartHeight(height, data?.categories?.length ?? 0, {
1289
+ rowHeight,
1290
+ minHeight,
1291
+ maxHeight,
1292
+ chrome: 56 + (builtInLegend ? 36 : 0) + (dataZoom ? 36 : 0)
1293
+ }) : height === "auto" ? 400 : height;
1294
+ return /* @__PURE__ */ jsx8(
944
1295
  ChartContainer,
945
1296
  {
946
1297
  ref,
947
1298
  title,
948
1299
  description: accessibilityDescription,
949
- height,
1300
+ height: resolvedHeight,
1301
+ minHeight,
1302
+ maxHeight,
950
1303
  loading,
951
1304
  error,
952
1305
  empty: isEmpty,
@@ -954,8 +1307,13 @@ var BarChart = React7.forwardRef(
954
1307
  className: cn(className),
955
1308
  legend: !isEmpty && renderLegend ? renderLegend(legend.renderProps) : void 0,
956
1309
  legendPosition: legendConfig?.position,
1310
+ dataTable: isEmpty ? void 0 : categoryTable2(data),
1311
+ showDataTable,
1312
+ format,
1313
+ exportable,
1314
+ exportImage,
957
1315
  ...props,
958
- children: /* @__PURE__ */ jsx7("div", { ref: containerRef, className: "h-full w-full" })
1316
+ children: /* @__PURE__ */ jsx8("div", { ref: containerRef, className: "h-full w-full" })
959
1317
  }
960
1318
  );
961
1319
  }
@@ -967,7 +1325,7 @@ import * as React8 from "react";
967
1325
  import * as echarts5 from "echarts/core";
968
1326
  import { PieChart as EChartsPieChart } from "echarts/charts";
969
1327
  import { TooltipComponent as TooltipComponent3, LegendComponent as LegendComponent3, TitleComponent as TitleComponent3 } from "echarts/components";
970
- import { CanvasRenderer as CanvasRenderer3 } from "echarts/renderers";
1328
+ import { CanvasRenderer as CanvasRenderer4 } from "echarts/renderers";
971
1329
  import {
972
1330
  buildDataLabel as buildDataLabel3,
973
1331
  buildLegend as buildLegend3,
@@ -979,16 +1337,20 @@ import {
979
1337
  itemLabelLookup,
980
1338
  legendCenter,
981
1339
  mergeChartOption as mergeChartOption3,
982
- pointLabel
1340
+ pointLabel,
1341
+ resolveValueFormatter as resolveValueFormatter3,
1342
+ sliceTable
983
1343
  } from "@classic-homes/charts-core";
984
- import { jsx as jsx8 } from "react/jsx-runtime";
985
- echarts5.use([EChartsPieChart, TooltipComponent3, LegendComponent3, TitleComponent3, CanvasRenderer3]);
1344
+ import { jsx as jsx9 } from "react/jsx-runtime";
1345
+ echarts5.use([EChartsPieChart, TooltipComponent3, LegendComponent3, TitleComponent3, CanvasRenderer4]);
986
1346
  var PieChart = React8.forwardRef(
987
1347
  ({
988
1348
  title,
989
1349
  description,
990
1350
  data,
991
1351
  height = 400,
1352
+ minHeight,
1353
+ maxHeight,
992
1354
  loading,
993
1355
  error,
994
1356
  emptyMessage,
@@ -999,6 +1361,8 @@ var PieChart = React8.forwardRef(
999
1361
  showLabels = true,
1000
1362
  labelPosition = "outside",
1001
1363
  innerRadius = 0,
1364
+ valueFormat,
1365
+ locale,
1002
1366
  labelFormatter,
1003
1367
  tooltipFormatter,
1004
1368
  tooltipValueFormatter,
@@ -1006,6 +1370,11 @@ var PieChart = React8.forwardRef(
1006
1370
  renderLegend,
1007
1371
  onLegendChange,
1008
1372
  option: optionOverride,
1373
+ onReady,
1374
+ events,
1375
+ showDataTable,
1376
+ exportable,
1377
+ patterns,
1009
1378
  onClick,
1010
1379
  class: className,
1011
1380
  ...props
@@ -1021,9 +1390,14 @@ var PieChart = React8.forwardRef(
1021
1390
  onLegendChange
1022
1391
  });
1023
1392
  const customLegend = renderLegend !== void 0;
1393
+ const format = React8.useMemo(
1394
+ () => resolveValueFormatter3(valueFormat, locale),
1395
+ [valueFormat, locale]
1396
+ );
1397
+ const tooltipValues = tooltipValueFormatter ?? format;
1024
1398
  const option = React8.useMemo(() => {
1025
1399
  if (isEmpty) return {};
1026
- const valueFormatter = tooltipFormatter === void 0 ? tooltipValueFormatter : void 0;
1400
+ const valueFormatter = tooltipFormatter === void 0 ? tooltipValues : void 0;
1027
1401
  const tooltipBase = {
1028
1402
  trigger: "item",
1029
1403
  formatter: valueFormatter ? (params) => {
@@ -1036,7 +1410,7 @@ var PieChart = React8.forwardRef(
1036
1410
  tooltip: buildTooltip3(tooltipBase, {
1037
1411
  show: showTooltip,
1038
1412
  formatter: tooltipFormatter,
1039
- valueFormatter: tooltipValueFormatter,
1413
+ valueFormatter: tooltipValues,
1040
1414
  getLabel: itemLabelLookup(data)
1041
1415
  }),
1042
1416
  legend: buildLegend3(
@@ -1088,40 +1462,32 @@ var PieChart = React8.forwardRef(
1088
1462
  title,
1089
1463
  labelFormatter,
1090
1464
  tooltipFormatter,
1091
- tooltipValueFormatter,
1465
+ tooltipValues,
1092
1466
  legendConfig,
1093
1467
  customLegend,
1094
1468
  optionOverride
1095
1469
  ]);
1096
- const latest = useLatestRef({ onClick });
1097
- const { containerRef } = useChart({
1470
+ const { containerRef, exportImage } = useChart({
1098
1471
  option,
1099
1472
  theme,
1100
1473
  animation,
1101
- onReady: (chart) => {
1102
- legend.attach(chart);
1103
- chart.on("click", (params) => {
1104
- const { onClick: onClick2 } = latest.current;
1105
- if (!onClick2) return;
1106
- onClick2({
1107
- type: params.type || "click",
1108
- componentType: params.componentType || "series",
1109
- name: params.name || "",
1110
- value: params.value,
1111
- percent: params.percent,
1112
- color: params.color
1113
- });
1114
- });
1115
- }
1474
+ patterns,
1475
+ events: chartEvents(events, {
1476
+ click: onClick && ((params) => onClick(toSliceParams(params, "click")))
1477
+ }),
1478
+ onReady: legend.attach,
1479
+ onCreated: onReady
1116
1480
  });
1117
1481
  const accessibilityDescription = description || (!isEmpty ? generatePieChartDescription(title, data, false) : void 0);
1118
- return /* @__PURE__ */ jsx8(
1482
+ return /* @__PURE__ */ jsx9(
1119
1483
  ChartContainer,
1120
1484
  {
1121
1485
  ref,
1122
1486
  title,
1123
1487
  description: accessibilityDescription,
1124
1488
  height,
1489
+ minHeight,
1490
+ maxHeight,
1125
1491
  loading,
1126
1492
  error,
1127
1493
  empty: isEmpty,
@@ -1129,8 +1495,13 @@ var PieChart = React8.forwardRef(
1129
1495
  className: cn(className),
1130
1496
  legend: !isEmpty && renderLegend ? renderLegend(legend.renderProps) : void 0,
1131
1497
  legendPosition: legendConfig?.position,
1498
+ dataTable: isEmpty ? void 0 : sliceTable(data),
1499
+ showDataTable,
1500
+ format,
1501
+ exportable,
1502
+ exportImage,
1132
1503
  ...props,
1133
- children: /* @__PURE__ */ jsx8("div", { ref: containerRef, className: "h-full w-full" })
1504
+ children: /* @__PURE__ */ jsx9("div", { ref: containerRef, className: "h-full w-full" })
1134
1505
  }
1135
1506
  );
1136
1507
  }
@@ -1147,29 +1518,37 @@ import {
1147
1518
  LegendComponent as LegendComponent4,
1148
1519
  TitleComponent as TitleComponent4
1149
1520
  } from "echarts/components";
1150
- import { CanvasRenderer as CanvasRenderer4 } from "echarts/renderers";
1521
+ import { CanvasRenderer as CanvasRenderer5 } from "echarts/renderers";
1151
1522
  import {
1152
1523
  buildAxis as buildAxis3,
1153
1524
  buildDataLabel as buildDataLabel4,
1525
+ buildDataZoom as buildDataZoom3,
1154
1526
  buildLegend as buildLegend4,
1155
1527
  buildTooltip as buildTooltip4,
1528
+ categoryTable as categoryTable3,
1529
+ chartFormatters as chartFormatters3,
1156
1530
  colorWithAlpha,
1531
+ generateAreaChartDescription,
1157
1532
  getChartColors as getChartColors4,
1158
1533
  hasPointLabels as hasPointLabels2,
1159
1534
  gridInset as gridInset3,
1160
1535
  mergeChartOption as mergeChartOption4,
1536
+ resolveValueFormatter as resolveValueFormatter4,
1161
1537
  seriesLabelLookup as seriesLabelLookup3,
1162
1538
  THEME_DARK as THEME_DARK3,
1163
- withPointLabels as withPointLabels3
1539
+ toPercentStack as toPercentStack3,
1540
+ withPointLabels as withPointLabels3,
1541
+ withReferenceMarks as withReferenceMarks3,
1542
+ withZoomInset as withZoomInset3
1164
1543
  } from "@classic-homes/charts-core";
1165
- import { jsx as jsx9 } from "react/jsx-runtime";
1544
+ import { jsx as jsx10 } from "react/jsx-runtime";
1166
1545
  echarts6.use([
1167
1546
  EChartsLineChart2,
1168
1547
  GridComponent3,
1169
1548
  TooltipComponent4,
1170
1549
  LegendComponent4,
1171
1550
  TitleComponent4,
1172
- CanvasRenderer4
1551
+ CanvasRenderer5
1173
1552
  ]);
1174
1553
  var AreaChart = React9.forwardRef(
1175
1554
  ({
@@ -1177,6 +1556,8 @@ var AreaChart = React9.forwardRef(
1177
1556
  description,
1178
1557
  data,
1179
1558
  height = 400,
1559
+ minHeight,
1560
+ maxHeight,
1180
1561
  loading,
1181
1562
  error,
1182
1563
  emptyMessage,
@@ -1187,22 +1568,35 @@ var AreaChart = React9.forwardRef(
1187
1568
  showGrid = true,
1188
1569
  smooth = false,
1189
1570
  stacked = false,
1571
+ connectNulls = false,
1190
1572
  gradient = true,
1191
1573
  showLabels = false,
1574
+ valueFormat,
1575
+ locale,
1192
1576
  labelFormatter,
1193
1577
  xAxisConfig,
1194
1578
  yAxisConfig,
1579
+ referenceLines,
1580
+ referenceBands,
1581
+ dataZoom,
1195
1582
  tooltipFormatter,
1196
1583
  tooltipValueFormatter,
1197
1584
  legend: legendConfig,
1198
1585
  renderLegend,
1199
1586
  onLegendChange,
1200
1587
  option: optionOverride,
1588
+ onReady,
1589
+ events,
1590
+ showDataTable,
1591
+ exportable,
1592
+ patterns,
1201
1593
  onClick,
1594
+ onHover,
1202
1595
  class: className,
1203
1596
  ...props
1204
1597
  }, ref) => {
1205
1598
  const isEmpty = !data?.categories?.length || !data?.series?.length || data.series.every((s) => !s.data?.length);
1599
+ const isPercent = stacked === "percent";
1206
1600
  const currentTheme = useChartTheme(theme);
1207
1601
  const chartColors = getChartColors4(currentTheme);
1208
1602
  const legend = useChartLegend({
@@ -1214,10 +1608,49 @@ var AreaChart = React9.forwardRef(
1214
1608
  onLegendChange
1215
1609
  });
1216
1610
  const customLegend = renderLegend !== void 0;
1611
+ const builtInLegend = showLegend && !customLegend;
1217
1612
  const option = React9.useMemo(() => {
1218
1613
  if (isEmpty) return {};
1614
+ const formatters = chartFormatters3({
1615
+ valueFormat: isPercent ? "percentValue" : valueFormat,
1616
+ locale,
1617
+ tooltipValueFormatter,
1618
+ labelFormatter
1619
+ });
1620
+ const plotted = isPercent ? toPercentStack3(data.series) : data.series;
1219
1621
  const getLabel = seriesLabelLookup3(data.series);
1220
1622
  const showSymbol = showLabels || hasPointLabels2(data.series);
1623
+ const legendBottom = builtInLegend && (legendConfig?.position ?? "bottom") === "bottom";
1624
+ const series = data.series.map((source, index) => {
1625
+ const base = source.color || chartColors.series[index % chartColors.series.length];
1626
+ return {
1627
+ name: source.name,
1628
+ type: "line",
1629
+ data: withPointLabels3(plotted[index].data, source.labels, formatters.label, {
1630
+ position: "top"
1631
+ }),
1632
+ smooth,
1633
+ connectNulls,
1634
+ stack: stacked ? "Total" : void 0,
1635
+ areaStyle: gradient ? {
1636
+ opacity: 0.8,
1637
+ color: new echarts6.graphic.LinearGradient(0, 0, 0, 1, [
1638
+ { offset: 0, color: colorWithAlpha(base, 0.8) },
1639
+ { offset: 1, color: colorWithAlpha(base, 0.1) }
1640
+ ])
1641
+ } : { opacity: 0.5 },
1642
+ itemStyle: source.color ? { color: source.color } : void 0,
1643
+ label: buildDataLabel4({ show: true, position: "top" }, void 0, {
1644
+ show: showLabels,
1645
+ formatter: formatters.label,
1646
+ getLabel
1647
+ }),
1648
+ emphasis: {
1649
+ focus: "series"
1650
+ },
1651
+ showSymbol
1652
+ };
1653
+ });
1221
1654
  return mergeChartOption4(
1222
1655
  {
1223
1656
  grid: {
@@ -1225,7 +1658,11 @@ var AreaChart = React9.forwardRef(
1225
1658
  right: "4%",
1226
1659
  bottom: "3%",
1227
1660
  containLabel: true,
1228
- ...gridInset3(legendConfig, showLegend && !customLegend, xAxisConfig, yAxisConfig)
1661
+ ...withZoomInset3(
1662
+ gridInset3(legendConfig, builtInLegend, xAxisConfig, yAxisConfig),
1663
+ dataZoom,
1664
+ "x"
1665
+ )
1229
1666
  },
1230
1667
  tooltip: buildTooltip4(
1231
1668
  {
@@ -1240,7 +1677,7 @@ var AreaChart = React9.forwardRef(
1240
1677
  {
1241
1678
  show: showTooltip,
1242
1679
  formatter: tooltipFormatter,
1243
- valueFormatter: tooltipValueFormatter,
1680
+ valueFormatter: formatters.tooltip,
1244
1681
  getLabel
1245
1682
  }
1246
1683
  ),
@@ -1249,6 +1686,7 @@ var AreaChart = React9.forwardRef(
1249
1686
  legendConfig,
1250
1687
  { show: showLegend, custom: customLegend }
1251
1688
  ),
1689
+ dataZoom: buildDataZoom3(dataZoom, "x", legendBottom ? 36 : 0),
1252
1690
  xAxis: buildAxis3(
1253
1691
  {
1254
1692
  type: "category",
@@ -1260,40 +1698,18 @@ var AreaChart = React9.forwardRef(
1260
1698
  yAxis: buildAxis3(
1261
1699
  {
1262
1700
  type: "value",
1701
+ ...isPercent && { max: 100 },
1263
1702
  splitLine: {
1264
1703
  show: showGrid
1265
1704
  }
1266
1705
  },
1267
- yAxisConfig
1706
+ formatters.axis(yAxisConfig)
1268
1707
  ),
1269
- series: data.series.map((series, index) => {
1270
- const base = series.color || chartColors.series[index % chartColors.series.length];
1271
- return {
1272
- name: series.name,
1273
- type: "line",
1274
- data: withPointLabels3(series.data, series.labels, labelFormatter, {
1275
- position: "top"
1276
- }),
1277
- smooth,
1278
- stack: stacked ? "Total" : void 0,
1279
- areaStyle: gradient ? {
1280
- opacity: 0.8,
1281
- color: new echarts6.graphic.LinearGradient(0, 0, 0, 1, [
1282
- { offset: 0, color: colorWithAlpha(base, 0.8) },
1283
- { offset: 1, color: colorWithAlpha(base, 0.1) }
1284
- ])
1285
- } : { opacity: 0.5 },
1286
- itemStyle: series.color ? { color: series.color } : void 0,
1287
- label: buildDataLabel4({ show: true, position: "top" }, void 0, {
1288
- show: showLabels,
1289
- formatter: labelFormatter,
1290
- getLabel
1291
- }),
1292
- emphasis: {
1293
- focus: "series"
1294
- },
1295
- showSymbol
1296
- };
1708
+ series: withReferenceMarks3(series, referenceLines, referenceBands, {
1709
+ valueAxis: "y",
1710
+ format: formatters.format,
1711
+ color: chartColors.reference,
1712
+ bandColor: chartColors.referenceBand
1297
1713
  })
1298
1714
  },
1299
1715
  optionOverride
@@ -1306,49 +1722,49 @@ var AreaChart = React9.forwardRef(
1306
1722
  showGrid,
1307
1723
  smooth,
1308
1724
  stacked,
1725
+ isPercent,
1726
+ connectNulls,
1309
1727
  gradient,
1310
1728
  chartColors,
1311
1729
  showLabels,
1730
+ valueFormat,
1731
+ locale,
1312
1732
  labelFormatter,
1313
1733
  xAxisConfig,
1314
1734
  yAxisConfig,
1735
+ referenceLines,
1736
+ referenceBands,
1737
+ dataZoom,
1315
1738
  tooltipFormatter,
1316
1739
  tooltipValueFormatter,
1317
1740
  legendConfig,
1318
1741
  customLegend,
1742
+ builtInLegend,
1319
1743
  optionOverride
1320
1744
  ]);
1321
- const latest = useLatestRef({ onClick });
1322
- const { containerRef } = useChart({
1745
+ const { containerRef, exportImage } = useChart({
1323
1746
  option,
1324
1747
  theme: currentTheme === THEME_DARK3 ? "dark" : "light",
1325
1748
  animation,
1326
- onReady: (chart) => {
1327
- legend.attach(chart);
1328
- chart.on("click", (params) => {
1329
- const { onClick: onClick2 } = latest.current;
1330
- if (!onClick2) return;
1331
- onClick2({
1332
- type: params.type || "click",
1333
- componentType: params.componentType || "series",
1334
- seriesIndex: params.seriesIndex,
1335
- seriesName: params.seriesName || "",
1336
- dataIndex: params.dataIndex || 0,
1337
- name: params.name || "",
1338
- value: params.value,
1339
- color: params.color
1340
- });
1341
- });
1342
- }
1749
+ patterns,
1750
+ events: chartEvents(events, {
1751
+ click: onClick && ((params) => onClick(toDataPointParams(params, "click"))),
1752
+ mouseover: onHover && ((params) => onHover(toDataPointParams(params, "mouseover")))
1753
+ }),
1754
+ onReady: legend.attach,
1755
+ onCreated: onReady
1343
1756
  });
1344
- const accessibilityDescription = description || (!isEmpty ? `${title}. Area chart with ${data.categories.length} data points across ${data.series.length} series.` : void 0);
1345
- return /* @__PURE__ */ jsx9(
1757
+ const format = resolveValueFormatter4(valueFormat, locale);
1758
+ const accessibilityDescription = description || (!isEmpty ? generateAreaChartDescription(title, data, format) : void 0);
1759
+ return /* @__PURE__ */ jsx10(
1346
1760
  ChartContainer,
1347
1761
  {
1348
1762
  ref,
1349
1763
  title,
1350
1764
  description: accessibilityDescription,
1351
1765
  height,
1766
+ minHeight,
1767
+ maxHeight,
1352
1768
  loading,
1353
1769
  error,
1354
1770
  empty: isEmpty,
@@ -1356,8 +1772,13 @@ var AreaChart = React9.forwardRef(
1356
1772
  className: cn(className),
1357
1773
  legend: !isEmpty && renderLegend ? renderLegend(legend.renderProps) : void 0,
1358
1774
  legendPosition: legendConfig?.position,
1775
+ dataTable: isEmpty ? void 0 : categoryTable3(data),
1776
+ showDataTable,
1777
+ format,
1778
+ exportable,
1779
+ exportImage,
1359
1780
  ...props,
1360
- children: /* @__PURE__ */ jsx9("div", { ref: containerRef, className: "h-full w-full" })
1781
+ children: /* @__PURE__ */ jsx10("div", { ref: containerRef, className: "h-full w-full" })
1361
1782
  }
1362
1783
  );
1363
1784
  }
@@ -1374,22 +1795,26 @@ import {
1374
1795
  LegendComponent as LegendComponent5,
1375
1796
  TitleComponent as TitleComponent5
1376
1797
  } from "echarts/components";
1377
- import { CanvasRenderer as CanvasRenderer5 } from "echarts/renderers";
1798
+ import { CanvasRenderer as CanvasRenderer6 } from "echarts/renderers";
1378
1799
  import {
1379
1800
  buildAxis as buildAxis4,
1380
1801
  buildDataLabel as buildDataLabel5,
1381
1802
  buildLegend as buildLegend5,
1382
1803
  buildTooltip as buildTooltip5,
1804
+ chartFormatters as chartFormatters4,
1383
1805
  escapeHtml as escapeHtml2,
1384
1806
  formatTooltipValue as formatTooltipValue2,
1385
1807
  generateScatterChartDescription,
1386
1808
  getChartColors as getChartColors5,
1387
1809
  gridInset as gridInset4,
1388
1810
  mergeChartOption as mergeChartOption5,
1811
+ resolveValueFormatter as resolveValueFormatter5,
1812
+ scatterTable,
1389
1813
  seriesLabelLookup as seriesLabelLookup4,
1390
- withPointLabels as withPointLabels4
1814
+ withPointLabels as withPointLabels4,
1815
+ withReferenceMarks as withReferenceMarks4
1391
1816
  } from "@classic-homes/charts-core";
1392
- import { jsx as jsx10 } from "react/jsx-runtime";
1817
+ import { jsx as jsx11 } from "react/jsx-runtime";
1393
1818
  echarts7.use([
1394
1819
  EChartsScatterChart,
1395
1820
  // Trend lines are line series
@@ -1398,7 +1823,7 @@ echarts7.use([
1398
1823
  TooltipComponent5,
1399
1824
  LegendComponent5,
1400
1825
  TitleComponent5,
1401
- CanvasRenderer5
1826
+ CanvasRenderer6
1402
1827
  ]);
1403
1828
  var ScatterChart = React10.forwardRef(
1404
1829
  ({
@@ -1406,6 +1831,8 @@ var ScatterChart = React10.forwardRef(
1406
1831
  description,
1407
1832
  data,
1408
1833
  height = 400,
1834
+ minHeight,
1835
+ maxHeight,
1409
1836
  loading,
1410
1837
  error,
1411
1838
  emptyMessage,
@@ -1417,25 +1844,36 @@ var ScatterChart = React10.forwardRef(
1417
1844
  showTrendLine = false,
1418
1845
  symbolSize = 10,
1419
1846
  showLabels = false,
1847
+ valueFormat,
1848
+ locale,
1420
1849
  labelFormatter,
1421
1850
  xAxisConfig,
1422
1851
  yAxisConfig,
1852
+ referenceLines,
1853
+ referenceBands,
1423
1854
  tooltipFormatter,
1424
1855
  tooltipValueFormatter,
1425
1856
  legend: legendConfig,
1426
1857
  renderLegend,
1427
1858
  onLegendChange,
1428
1859
  option: optionOverride,
1860
+ onReady,
1861
+ events,
1862
+ showDataTable,
1863
+ exportable,
1864
+ patterns,
1429
1865
  onClick,
1866
+ onHover,
1430
1867
  class: className,
1431
1868
  ...props
1432
1869
  }, ref) => {
1433
1870
  const isEmpty = !data?.series?.length || data.series.every((s) => !s.data?.length);
1434
1871
  const currentTheme = useChartTheme(theme);
1872
+ const chartColors = getChartColors5(currentTheme);
1435
1873
  const legend = useChartLegend({
1436
1874
  names: data?.series?.map((s) => s.name) ?? [],
1437
1875
  colors: data?.series?.map((s) => s.color) ?? [],
1438
- palette: getChartColors5(currentTheme).series,
1876
+ palette: chartColors.series,
1439
1877
  config: legendConfig,
1440
1878
  title,
1441
1879
  onLegendChange
@@ -1443,16 +1881,22 @@ var ScatterChart = React10.forwardRef(
1443
1881
  const customLegend = renderLegend !== void 0;
1444
1882
  const option = React10.useMemo(() => {
1445
1883
  if (isEmpty) return {};
1884
+ const formatters = chartFormatters4({
1885
+ valueFormat,
1886
+ locale,
1887
+ tooltipValueFormatter,
1888
+ labelFormatter
1889
+ });
1446
1890
  const getLabel = seriesLabelLookup4(data.series);
1447
1891
  const series = data.series.map((s) => ({
1448
1892
  name: s.name,
1449
1893
  type: "scatter",
1450
- data: withPointLabels4(s.data, s.labels, labelFormatter, { position: "top" }),
1894
+ data: withPointLabels4(s.data, s.labels, formatters.label, { position: "top" }),
1451
1895
  symbolSize: typeof symbolSize === "function" ? symbolSize : symbolSize,
1452
1896
  itemStyle: s.color ? { color: s.color } : void 0,
1453
1897
  label: buildDataLabel5({ show: true, position: "top" }, void 0, {
1454
1898
  show: showLabels,
1455
- formatter: labelFormatter,
1899
+ formatter: formatters.label,
1456
1900
  getLabel
1457
1901
  }),
1458
1902
  emphasis: {
@@ -1517,15 +1961,15 @@ var ScatterChart = React10.forwardRef(
1517
1961
  formatter: (params) => {
1518
1962
  const p = params;
1519
1963
  if (!p.value) return "";
1520
- const x = formatTooltipValue2(p.value[0], tooltipValueFormatter);
1521
- const y = formatTooltipValue2(p.value[1], tooltipValueFormatter);
1964
+ const x = formatTooltipValue2(p.value[0], formatters.tooltip);
1965
+ const y = formatTooltipValue2(p.value[1], formatters.tooltip);
1522
1966
  return `${escapeHtml2(p.seriesName)}<br/>X: ${escapeHtml2(x)}<br/>Y: ${escapeHtml2(y)}`;
1523
1967
  }
1524
1968
  },
1525
1969
  {
1526
1970
  show: showTooltip,
1527
1971
  formatter: tooltipFormatter,
1528
- valueFormatter: tooltipValueFormatter,
1972
+ valueFormatter: formatters.tooltip,
1529
1973
  getLabel
1530
1974
  }
1531
1975
  ),
@@ -1550,9 +1994,19 @@ var ScatterChart = React10.forwardRef(
1550
1994
  show: showGrid
1551
1995
  }
1552
1996
  },
1553
- yAxisConfig
1997
+ formatters.axis(yAxisConfig)
1554
1998
  ),
1555
- series
1999
+ series: withReferenceMarks4(
2000
+ series,
2001
+ referenceLines,
2002
+ referenceBands,
2003
+ {
2004
+ valueAxis: "y",
2005
+ format: formatters.format,
2006
+ color: chartColors.reference,
2007
+ bandColor: chartColors.referenceBand
2008
+ }
2009
+ )
1556
2010
  },
1557
2011
  optionOverride
1558
2012
  );
@@ -1565,46 +2019,42 @@ var ScatterChart = React10.forwardRef(
1565
2019
  showTrendLine,
1566
2020
  symbolSize,
1567
2021
  showLabels,
2022
+ valueFormat,
2023
+ locale,
1568
2024
  labelFormatter,
1569
2025
  xAxisConfig,
1570
2026
  yAxisConfig,
2027
+ referenceLines,
2028
+ referenceBands,
2029
+ chartColors,
1571
2030
  tooltipFormatter,
1572
2031
  tooltipValueFormatter,
1573
2032
  legendConfig,
1574
2033
  customLegend,
1575
2034
  optionOverride
1576
2035
  ]);
1577
- const latest = useLatestRef({ onClick });
1578
- const { containerRef } = useChart({
2036
+ const { containerRef, exportImage } = useChart({
1579
2037
  option,
1580
2038
  theme,
1581
2039
  animation,
1582
- onReady: (chart) => {
1583
- legend.attach(chart);
1584
- chart.on("click", (params) => {
1585
- const { onClick: onClick2 } = latest.current;
1586
- if (!onClick2) return;
1587
- onClick2({
1588
- type: params.type || "click",
1589
- componentType: params.componentType || "series",
1590
- seriesIndex: params.seriesIndex,
1591
- seriesName: params.seriesName || "",
1592
- dataIndex: params.dataIndex || 0,
1593
- name: params.name || "",
1594
- value: params.value,
1595
- color: params.color
1596
- });
1597
- });
1598
- }
2040
+ patterns,
2041
+ events: chartEvents(events, {
2042
+ click: onClick && ((params) => onClick(toDataPointParams(params, "click"))),
2043
+ mouseover: onHover && ((params) => onHover(toDataPointParams(params, "mouseover")))
2044
+ }),
2045
+ onReady: legend.attach,
2046
+ onCreated: onReady
1599
2047
  });
1600
2048
  const accessibilityDescription = description || (!isEmpty ? generateScatterChartDescription(title, data) : void 0);
1601
- return /* @__PURE__ */ jsx10(
2049
+ return /* @__PURE__ */ jsx11(
1602
2050
  ChartContainer,
1603
2051
  {
1604
2052
  ref,
1605
2053
  title,
1606
2054
  description: accessibilityDescription,
1607
2055
  height,
2056
+ minHeight,
2057
+ maxHeight,
1608
2058
  loading,
1609
2059
  error,
1610
2060
  empty: isEmpty,
@@ -1612,8 +2062,13 @@ var ScatterChart = React10.forwardRef(
1612
2062
  className: cn(className),
1613
2063
  legend: !isEmpty && renderLegend ? renderLegend(legend.renderProps) : void 0,
1614
2064
  legendPosition: legendConfig?.position,
2065
+ dataTable: isEmpty ? void 0 : scatterTable(data, xAxisConfig?.name, yAxisConfig?.name),
2066
+ showDataTable,
2067
+ format: resolveValueFormatter5(valueFormat, locale),
2068
+ exportable,
2069
+ exportImage,
1615
2070
  ...props,
1616
- children: /* @__PURE__ */ jsx10("div", { ref: containerRef, className: "h-full w-full" })
2071
+ children: /* @__PURE__ */ jsx11("div", { ref: containerRef, className: "h-full w-full" })
1617
2072
  }
1618
2073
  );
1619
2074
  }
@@ -1625,7 +2080,7 @@ import * as React11 from "react";
1625
2080
  import * as echarts8 from "echarts/core";
1626
2081
  import { PieChart as EChartsPieChart2 } from "echarts/charts";
1627
2082
  import { TooltipComponent as TooltipComponent6, LegendComponent as LegendComponent6, TitleComponent as TitleComponent6 } from "echarts/components";
1628
- import { CanvasRenderer as CanvasRenderer6 } from "echarts/renderers";
2083
+ import { CanvasRenderer as CanvasRenderer7 } from "echarts/renderers";
1629
2084
  import {
1630
2085
  buildDataLabel as buildDataLabel6,
1631
2086
  buildLegend as buildLegend6,
@@ -1639,16 +2094,20 @@ import {
1639
2094
  legendCenter as legendCenter2,
1640
2095
  mergeChartOption as mergeChartOption6,
1641
2096
  pointLabel as pointLabel2,
2097
+ resolveValueFormatter as resolveValueFormatter6,
2098
+ sliceTable as sliceTable2,
1642
2099
  THEME_DARK as THEME_DARK4
1643
2100
  } from "@classic-homes/charts-core";
1644
- import { jsx as jsx11 } from "react/jsx-runtime";
1645
- echarts8.use([EChartsPieChart2, TooltipComponent6, LegendComponent6, TitleComponent6, CanvasRenderer6]);
2101
+ import { jsx as jsx12 } from "react/jsx-runtime";
2102
+ echarts8.use([EChartsPieChart2, TooltipComponent6, LegendComponent6, TitleComponent6, CanvasRenderer7]);
1646
2103
  var DonutChart = React11.forwardRef(
1647
2104
  ({
1648
2105
  title,
1649
2106
  description,
1650
2107
  data,
1651
2108
  height = 400,
2109
+ minHeight,
2110
+ maxHeight,
1652
2111
  loading,
1653
2112
  error,
1654
2113
  emptyMessage,
@@ -1661,6 +2120,8 @@ var DonutChart = React11.forwardRef(
1661
2120
  innerRadius = "50%",
1662
2121
  centerLabel,
1663
2122
  centerValue,
2123
+ valueFormat,
2124
+ locale,
1664
2125
  labelFormatter,
1665
2126
  tooltipFormatter,
1666
2127
  tooltipValueFormatter,
@@ -1668,6 +2129,11 @@ var DonutChart = React11.forwardRef(
1668
2129
  renderLegend,
1669
2130
  onLegendChange,
1670
2131
  option: optionOverride,
2132
+ onReady,
2133
+ events,
2134
+ showDataTable,
2135
+ exportable,
2136
+ patterns,
1671
2137
  onClick,
1672
2138
  class: className,
1673
2139
  ...props
@@ -1684,6 +2150,11 @@ var DonutChart = React11.forwardRef(
1684
2150
  onLegendChange
1685
2151
  });
1686
2152
  const customLegend = renderLegend !== void 0;
2153
+ const format = React11.useMemo(
2154
+ () => resolveValueFormatter6(valueFormat, locale),
2155
+ [valueFormat, locale]
2156
+ );
2157
+ const tooltipValues = tooltipValueFormatter ?? format;
1687
2158
  const option = React11.useMemo(() => {
1688
2159
  if (isEmpty) return {};
1689
2160
  const pieCenter = legendCenter2(legendConfig, showLegend && !customLegend, ["50%", "45%"]);
@@ -1730,7 +2201,7 @@ var DonutChart = React11.forwardRef(
1730
2201
  )
1731
2202
  );
1732
2203
  }
1733
- const valueFormatter = tooltipFormatter === void 0 ? tooltipValueFormatter : void 0;
2204
+ const valueFormatter = tooltipFormatter === void 0 ? tooltipValues : void 0;
1734
2205
  const tooltipBase = {
1735
2206
  trigger: "item",
1736
2207
  formatter: valueFormatter ? (params) => {
@@ -1743,7 +2214,7 @@ var DonutChart = React11.forwardRef(
1743
2214
  tooltip: buildTooltip6(tooltipBase, {
1744
2215
  show: showTooltip,
1745
2216
  formatter: tooltipFormatter,
1746
- valueFormatter: tooltipValueFormatter,
2217
+ valueFormatter: tooltipValues,
1747
2218
  getLabel: itemLabelLookup2(data)
1748
2219
  }),
1749
2220
  legend: buildLegend6(
@@ -1803,40 +2274,32 @@ var DonutChart = React11.forwardRef(
1803
2274
  chartColors,
1804
2275
  labelFormatter,
1805
2276
  tooltipFormatter,
1806
- tooltipValueFormatter,
2277
+ tooltipValues,
1807
2278
  legendConfig,
1808
2279
  customLegend,
1809
2280
  optionOverride
1810
2281
  ]);
1811
- const latest = useLatestRef({ onClick });
1812
- const { containerRef } = useChart({
2282
+ const { containerRef, exportImage } = useChart({
1813
2283
  option,
1814
2284
  theme: currentTheme === THEME_DARK4 ? "dark" : "light",
1815
2285
  animation,
1816
- onReady: (chart) => {
1817
- legend.attach(chart);
1818
- chart.on("click", (params) => {
1819
- const { onClick: onClick2 } = latest.current;
1820
- if (!onClick2) return;
1821
- onClick2({
1822
- type: params.type || "click",
1823
- componentType: params.componentType || "series",
1824
- name: params.name || "",
1825
- value: params.value,
1826
- percent: params.percent,
1827
- color: params.color
1828
- });
1829
- });
1830
- }
2286
+ patterns,
2287
+ events: chartEvents(events, {
2288
+ click: onClick && ((params) => onClick(toSliceParams(params, "click")))
2289
+ }),
2290
+ onReady: legend.attach,
2291
+ onCreated: onReady
1831
2292
  });
1832
2293
  const accessibilityDescription = description || (!isEmpty ? generatePieChartDescription2(title, data, true) : void 0);
1833
- return /* @__PURE__ */ jsx11(
2294
+ return /* @__PURE__ */ jsx12(
1834
2295
  ChartContainer,
1835
2296
  {
1836
2297
  ref,
1837
2298
  title,
1838
2299
  description: accessibilityDescription,
1839
2300
  height,
2301
+ minHeight,
2302
+ maxHeight,
1840
2303
  loading,
1841
2304
  error,
1842
2305
  empty: isEmpty,
@@ -1844,8 +2307,13 @@ var DonutChart = React11.forwardRef(
1844
2307
  className: cn(className),
1845
2308
  legend: !isEmpty && renderLegend ? renderLegend(legend.renderProps) : void 0,
1846
2309
  legendPosition: legendConfig?.position,
2310
+ dataTable: isEmpty ? void 0 : sliceTable2(data),
2311
+ showDataTable,
2312
+ format,
2313
+ exportable,
2314
+ exportImage,
1847
2315
  ...props,
1848
- children: /* @__PURE__ */ jsx11("div", { ref: containerRef, className: "h-full w-full" })
2316
+ children: /* @__PURE__ */ jsx12("div", { ref: containerRef, className: "h-full w-full" })
1849
2317
  }
1850
2318
  );
1851
2319
  }
@@ -1862,23 +2330,25 @@ import {
1862
2330
  TitleComponent as TitleComponent7,
1863
2331
  RadarComponent
1864
2332
  } from "echarts/components";
1865
- import { CanvasRenderer as CanvasRenderer7 } from "echarts/renderers";
2333
+ import { CanvasRenderer as CanvasRenderer8 } from "echarts/renderers";
1866
2334
  import {
1867
2335
  buildDataLabel as buildDataLabel7,
1868
2336
  buildLegend as buildLegend7,
1869
2337
  buildTooltip as buildTooltip7,
1870
2338
  getChartColors as getChartColors7,
1871
2339
  legendCenter as legendCenter3,
1872
- mergeChartOption as mergeChartOption7
2340
+ mergeChartOption as mergeChartOption7,
2341
+ radarTable,
2342
+ resolveValueFormatter as resolveValueFormatter7
1873
2343
  } from "@classic-homes/charts-core";
1874
- import { jsx as jsx12 } from "react/jsx-runtime";
2344
+ import { jsx as jsx13 } from "react/jsx-runtime";
1875
2345
  echarts9.use([
1876
2346
  EChartsRadarChart,
1877
2347
  TooltipComponent7,
1878
2348
  LegendComponent7,
1879
2349
  TitleComponent7,
1880
2350
  RadarComponent,
1881
- CanvasRenderer7
2351
+ CanvasRenderer8
1882
2352
  ]);
1883
2353
  var RadarChart = React12.forwardRef(
1884
2354
  ({
@@ -1887,6 +2357,8 @@ var RadarChart = React12.forwardRef(
1887
2357
  data,
1888
2358
  indicators,
1889
2359
  height = 400,
2360
+ minHeight,
2361
+ maxHeight,
1890
2362
  loading,
1891
2363
  error,
1892
2364
  emptyMessage,
@@ -1896,6 +2368,8 @@ var RadarChart = React12.forwardRef(
1896
2368
  showTooltip = true,
1897
2369
  shape = "polygon",
1898
2370
  showLabels = false,
2371
+ valueFormat,
2372
+ locale,
1899
2373
  labelFormatter,
1900
2374
  tooltipFormatter,
1901
2375
  tooltipValueFormatter,
@@ -1903,6 +2377,11 @@ var RadarChart = React12.forwardRef(
1903
2377
  renderLegend,
1904
2378
  onLegendChange,
1905
2379
  option: optionOverride,
2380
+ onReady,
2381
+ events,
2382
+ showDataTable,
2383
+ exportable,
2384
+ patterns,
1906
2385
  onClick,
1907
2386
  class: className,
1908
2387
  ...props
@@ -1918,6 +2397,11 @@ var RadarChart = React12.forwardRef(
1918
2397
  onLegendChange
1919
2398
  });
1920
2399
  const customLegend = renderLegend !== void 0;
2400
+ const format = React12.useMemo(
2401
+ () => resolveValueFormatter7(valueFormat, locale),
2402
+ [valueFormat, locale]
2403
+ );
2404
+ const valueFormatter = tooltipValueFormatter ?? format;
1921
2405
  const option = React12.useMemo(() => {
1922
2406
  if (isEmpty) return {};
1923
2407
  return mergeChartOption7(
@@ -1929,7 +2413,7 @@ var RadarChart = React12.forwardRef(
1929
2413
  {
1930
2414
  show: showTooltip,
1931
2415
  formatter: tooltipFormatter,
1932
- valueFormatter: tooltipValueFormatter
2416
+ valueFormatter
1933
2417
  }
1934
2418
  ),
1935
2419
  legend: buildLegend7(
@@ -1976,22 +2460,20 @@ var RadarChart = React12.forwardRef(
1976
2460
  showLabels,
1977
2461
  labelFormatter,
1978
2462
  tooltipFormatter,
1979
- tooltipValueFormatter,
2463
+ valueFormatter,
1980
2464
  legendConfig,
1981
2465
  customLegend,
1982
2466
  optionOverride
1983
2467
  ]);
1984
- const latest = useLatestRef({ onClick });
1985
- const { containerRef } = useChart({
2468
+ const { containerRef, exportImage } = useChart({
1986
2469
  option,
1987
2470
  theme,
1988
2471
  animation,
1989
- onReady: (chart) => {
1990
- legend.attach(chart);
1991
- chart.on("click", (params) => {
1992
- const { onClick: onClick2 } = latest.current;
1993
- if (!onClick2) return;
1994
- onClick2({
2472
+ patterns,
2473
+ events: chartEvents(events, {
2474
+ click: onClick && ((params) => {
2475
+ if (!onClick) return;
2476
+ onClick({
1995
2477
  type: params.type || "click",
1996
2478
  componentType: params.componentType || "series",
1997
2479
  seriesIndex: params.seriesIndex,
@@ -2001,17 +2483,21 @@ var RadarChart = React12.forwardRef(
2001
2483
  value: params.value,
2002
2484
  color: params.color
2003
2485
  });
2004
- });
2005
- }
2486
+ })
2487
+ }),
2488
+ onReady: legend.attach,
2489
+ onCreated: onReady
2006
2490
  });
2007
2491
  const accessibilityDescription = description || (!isEmpty ? `${title}. Radar chart with ${indicators.length} dimensions comparing ${data.series.length} series.` : void 0);
2008
- return /* @__PURE__ */ jsx12(
2492
+ return /* @__PURE__ */ jsx13(
2009
2493
  ChartContainer,
2010
2494
  {
2011
2495
  ref,
2012
2496
  title,
2013
2497
  description: accessibilityDescription,
2014
2498
  height,
2499
+ minHeight,
2500
+ maxHeight,
2015
2501
  loading,
2016
2502
  error,
2017
2503
  empty: isEmpty,
@@ -2019,8 +2505,13 @@ var RadarChart = React12.forwardRef(
2019
2505
  className: cn(className),
2020
2506
  legend: !isEmpty && renderLegend ? renderLegend(legend.renderProps) : void 0,
2021
2507
  legendPosition: legendConfig?.position,
2508
+ dataTable: isEmpty ? void 0 : radarTable(data, indicators),
2509
+ showDataTable,
2510
+ format,
2511
+ exportable,
2512
+ exportImage,
2022
2513
  ...props,
2023
- children: /* @__PURE__ */ jsx12("div", { ref: containerRef, className: "h-full w-full" })
2514
+ children: /* @__PURE__ */ jsx13("div", { ref: containerRef, className: "h-full w-full" })
2024
2515
  }
2025
2516
  );
2026
2517
  }
@@ -2032,7 +2523,7 @@ import * as React13 from "react";
2032
2523
  import * as echarts10 from "echarts/core";
2033
2524
  import { FunnelChart as EChartsFunnelChart } from "echarts/charts";
2034
2525
  import { TooltipComponent as TooltipComponent8, LegendComponent as LegendComponent8, TitleComponent as TitleComponent8 } from "echarts/components";
2035
- import { CanvasRenderer as CanvasRenderer8 } from "echarts/renderers";
2526
+ import { CanvasRenderer as CanvasRenderer9 } from "echarts/renderers";
2036
2527
  import {
2037
2528
  buildDataLabel as buildDataLabel8,
2038
2529
  buildLegend as buildLegend8,
@@ -2042,15 +2533,17 @@ import {
2042
2533
  getChartColors as getChartColors8,
2043
2534
  itemLabelLookup as itemLabelLookup3,
2044
2535
  mergeChartOption as mergeChartOption8,
2045
- pointLabel as pointLabel3
2536
+ pointLabel as pointLabel3,
2537
+ resolveValueFormatter as resolveValueFormatter8,
2538
+ sliceTable as sliceTable3
2046
2539
  } from "@classic-homes/charts-core";
2047
- import { jsx as jsx13 } from "react/jsx-runtime";
2540
+ import { jsx as jsx14 } from "react/jsx-runtime";
2048
2541
  echarts10.use([
2049
2542
  EChartsFunnelChart,
2050
2543
  TooltipComponent8,
2051
2544
  LegendComponent8,
2052
2545
  TitleComponent8,
2053
- CanvasRenderer8
2546
+ CanvasRenderer9
2054
2547
  ]);
2055
2548
  var FunnelChart = React13.forwardRef(
2056
2549
  ({
@@ -2058,6 +2551,8 @@ var FunnelChart = React13.forwardRef(
2058
2551
  description,
2059
2552
  data,
2060
2553
  height = 400,
2554
+ minHeight,
2555
+ maxHeight,
2061
2556
  loading,
2062
2557
  error,
2063
2558
  emptyMessage,
@@ -2068,6 +2563,8 @@ var FunnelChart = React13.forwardRef(
2068
2563
  sort = "descending",
2069
2564
  orientation = "vertical",
2070
2565
  showLabels = true,
2566
+ valueFormat,
2567
+ locale,
2071
2568
  labelFormatter,
2072
2569
  tooltipFormatter,
2073
2570
  tooltipValueFormatter,
@@ -2075,6 +2572,11 @@ var FunnelChart = React13.forwardRef(
2075
2572
  renderLegend,
2076
2573
  onLegendChange,
2077
2574
  option: optionOverride,
2575
+ onReady,
2576
+ events,
2577
+ showDataTable,
2578
+ exportable,
2579
+ patterns,
2078
2580
  onClick,
2079
2581
  class: className,
2080
2582
  ...props
@@ -2090,15 +2592,20 @@ var FunnelChart = React13.forwardRef(
2090
2592
  onLegendChange
2091
2593
  });
2092
2594
  const customLegend = renderLegend !== void 0;
2595
+ const format = React13.useMemo(
2596
+ () => resolveValueFormatter8(valueFormat, locale),
2597
+ [valueFormat, locale]
2598
+ );
2599
+ const valueFormatter = tooltipValueFormatter ?? format;
2093
2600
  const option = React13.useMemo(() => {
2094
2601
  if (isEmpty) return {};
2095
2602
  const getLabel = itemLabelLookup3(data);
2096
- const valueFormatter = tooltipFormatter === void 0 ? tooltipValueFormatter : void 0;
2603
+ const templateFormatter = tooltipFormatter === void 0 ? valueFormatter : void 0;
2097
2604
  const tooltipBase = {
2098
2605
  trigger: "item",
2099
- formatter: valueFormatter ? (params) => {
2606
+ formatter: templateFormatter ? (params) => {
2100
2607
  const p = params;
2101
- return `${escapeHtml4(p.seriesName)} <br/>${escapeHtml4(p.name)}: ${escapeHtml4(formatTooltipValue4(p.value, valueFormatter))}`;
2608
+ return `${escapeHtml4(p.seriesName)} <br/>${escapeHtml4(p.name)}: ${escapeHtml4(formatTooltipValue4(p.value, templateFormatter))}`;
2102
2609
  } : "{a} <br/>{b}: {c}"
2103
2610
  };
2104
2611
  return mergeChartOption8(
@@ -2106,7 +2613,7 @@ var FunnelChart = React13.forwardRef(
2106
2613
  tooltip: buildTooltip8(tooltipBase, {
2107
2614
  show: showTooltip,
2108
2615
  formatter: tooltipFormatter,
2109
- valueFormatter: tooltipValueFormatter,
2616
+ valueFormatter,
2110
2617
  getLabel
2111
2618
  }),
2112
2619
  legend: buildLegend8(
@@ -2169,39 +2676,41 @@ var FunnelChart = React13.forwardRef(
2169
2676
  title,
2170
2677
  labelFormatter,
2171
2678
  tooltipFormatter,
2172
- tooltipValueFormatter,
2679
+ valueFormatter,
2173
2680
  legendConfig,
2174
2681
  customLegend,
2175
2682
  optionOverride
2176
2683
  ]);
2177
- const latest = useLatestRef({ onClick });
2178
- const { containerRef } = useChart({
2684
+ const { containerRef, exportImage } = useChart({
2179
2685
  option,
2180
2686
  theme,
2181
2687
  animation,
2182
- onReady: (chart) => {
2183
- legend.attach(chart);
2184
- chart.on("click", (params) => {
2185
- const { onClick: onClick2 } = latest.current;
2186
- if (!onClick2) return;
2187
- onClick2({
2688
+ patterns,
2689
+ events: chartEvents(events, {
2690
+ click: onClick && ((params) => {
2691
+ if (!onClick) return;
2692
+ onClick({
2188
2693
  type: params.type || "click",
2189
2694
  componentType: params.componentType || "series",
2190
2695
  name: params.name || "",
2191
2696
  value: params.value,
2192
2697
  color: params.color
2193
2698
  });
2194
- });
2195
- }
2699
+ })
2700
+ }),
2701
+ onReady: legend.attach,
2702
+ onCreated: onReady
2196
2703
  });
2197
2704
  const accessibilityDescription = description || (!isEmpty ? `${title}. Funnel chart with ${data.length} stages.` : void 0);
2198
- return /* @__PURE__ */ jsx13(
2705
+ return /* @__PURE__ */ jsx14(
2199
2706
  ChartContainer,
2200
2707
  {
2201
2708
  ref,
2202
2709
  title,
2203
2710
  description: accessibilityDescription,
2204
2711
  height,
2712
+ minHeight,
2713
+ maxHeight,
2205
2714
  loading,
2206
2715
  error,
2207
2716
  empty: isEmpty,
@@ -2209,8 +2718,13 @@ var FunnelChart = React13.forwardRef(
2209
2718
  className: cn(className),
2210
2719
  legend: !isEmpty && renderLegend ? renderLegend(legend.renderProps) : void 0,
2211
2720
  legendPosition: legendConfig?.position,
2721
+ dataTable: isEmpty ? void 0 : sliceTable3(data, "Stage"),
2722
+ showDataTable,
2723
+ format,
2724
+ exportable,
2725
+ exportImage,
2212
2726
  ...props,
2213
- children: /* @__PURE__ */ jsx13("div", { ref: containerRef, className: "h-full w-full" })
2727
+ children: /* @__PURE__ */ jsx14("div", { ref: containerRef, className: "h-full w-full" })
2214
2728
  }
2215
2729
  );
2216
2730
  }
@@ -2222,15 +2736,16 @@ import * as React14 from "react";
2222
2736
  import * as echarts11 from "echarts/core";
2223
2737
  import { GaugeChart as EChartsGaugeChart } from "echarts/charts";
2224
2738
  import { TitleComponent as TitleComponent9, TooltipComponent as TooltipComponent9 } from "echarts/components";
2225
- import { CanvasRenderer as CanvasRenderer9 } from "echarts/renderers";
2739
+ import { CanvasRenderer as CanvasRenderer10 } from "echarts/renderers";
2226
2740
  import {
2227
2741
  buildTooltip as buildTooltip9,
2228
2742
  getChartColors as getChartColors9,
2229
2743
  mergeChartOption as mergeChartOption9,
2744
+ resolveValueFormatter as resolveValueFormatter9,
2230
2745
  THEME_DARK as THEME_DARK5
2231
2746
  } from "@classic-homes/charts-core";
2232
- import { jsx as jsx14 } from "react/jsx-runtime";
2233
- echarts11.use([EChartsGaugeChart, TitleComponent9, TooltipComponent9, CanvasRenderer9]);
2747
+ import { jsx as jsx15 } from "react/jsx-runtime";
2748
+ echarts11.use([EChartsGaugeChart, TitleComponent9, TooltipComponent9, CanvasRenderer10]);
2234
2749
  var GaugeChart = React14.forwardRef(
2235
2750
  ({
2236
2751
  title,
@@ -2239,6 +2754,8 @@ var GaugeChart = React14.forwardRef(
2239
2754
  min = 0,
2240
2755
  max = 100,
2241
2756
  height = 400,
2757
+ minHeight,
2758
+ maxHeight,
2242
2759
  loading,
2243
2760
  error,
2244
2761
  emptyMessage,
@@ -2248,9 +2765,16 @@ var GaugeChart = React14.forwardRef(
2248
2765
  showProgress = true,
2249
2766
  formatValue,
2250
2767
  showTooltip = true,
2768
+ valueFormat,
2769
+ locale,
2251
2770
  tooltipFormatter,
2252
2771
  tooltipValueFormatter,
2253
2772
  option: optionOverride,
2773
+ onReady,
2774
+ events,
2775
+ showDataTable,
2776
+ exportable,
2777
+ patterns,
2254
2778
  onClick,
2255
2779
  class: className,
2256
2780
  ...props
@@ -2258,6 +2782,11 @@ var GaugeChart = React14.forwardRef(
2258
2782
  const currentTheme = useChartTheme(theme);
2259
2783
  const chartColors = getChartColors9(currentTheme);
2260
2784
  const reducedMotion = useReducedMotion();
2785
+ const format = React14.useMemo(
2786
+ () => resolveValueFormatter9(valueFormat, locale),
2787
+ [valueFormat, locale]
2788
+ );
2789
+ const valueFormatter = formatValue ?? format;
2261
2790
  const option = React14.useMemo(() => {
2262
2791
  return mergeChartOption9(
2263
2792
  {
@@ -2329,7 +2858,7 @@ var GaugeChart = React14.forwardRef(
2329
2858
  fontSize: 28,
2330
2859
  fontWeight: "bold",
2331
2860
  offsetCenter: [0, "40%"],
2332
- formatter: formatValue || "{value}"
2861
+ formatter: valueFormatter || "{value}"
2333
2862
  },
2334
2863
  data: [
2335
2864
  {
@@ -2348,7 +2877,7 @@ var GaugeChart = React14.forwardRef(
2348
2877
  max,
2349
2878
  splitNumber,
2350
2879
  showProgress,
2351
- formatValue,
2880
+ valueFormatter,
2352
2881
  title,
2353
2882
  animation,
2354
2883
  reducedMotion,
@@ -2358,16 +2887,15 @@ var GaugeChart = React14.forwardRef(
2358
2887
  tooltipValueFormatter,
2359
2888
  optionOverride
2360
2889
  ]);
2361
- const latest = useLatestRef({ onClick });
2362
- const { containerRef } = useChart({
2890
+ const { containerRef, exportImage } = useChart({
2363
2891
  option,
2364
2892
  theme: currentTheme === THEME_DARK5 ? "dark" : "light",
2365
2893
  animation,
2366
- onReady: (chart) => {
2367
- chart.on("click", (params) => {
2368
- const { onClick: onClick2 } = latest.current;
2369
- if (!onClick2) return;
2370
- onClick2({
2894
+ patterns,
2895
+ events: chartEvents(events, {
2896
+ click: onClick && ((params) => {
2897
+ if (!onClick) return;
2898
+ onClick({
2371
2899
  type: params.type || "click",
2372
2900
  componentType: params.componentType || "series",
2373
2901
  seriesIndex: params.seriesIndex,
@@ -2377,23 +2905,35 @@ var GaugeChart = React14.forwardRef(
2377
2905
  value: params.value,
2378
2906
  color: params.color
2379
2907
  });
2380
- });
2381
- }
2908
+ })
2909
+ }),
2910
+ onCreated: onReady
2382
2911
  });
2383
- const accessibilityDescription = description || `${title}. Gauge showing value ${value} on scale from ${min} to ${max}.`;
2384
- return /* @__PURE__ */ jsx14(
2912
+ const show = (n) => valueFormatter ? valueFormatter(n) : String(n);
2913
+ const accessibilityDescription = description || `${title}. Gauge showing value ${show(value)} on scale from ${show(min)} to ${show(max)}.`;
2914
+ return /* @__PURE__ */ jsx15(
2385
2915
  ChartContainer,
2386
2916
  {
2387
2917
  ref,
2388
2918
  title,
2389
2919
  description: accessibilityDescription,
2390
2920
  height,
2921
+ minHeight,
2922
+ maxHeight,
2391
2923
  loading,
2392
2924
  error,
2393
2925
  emptyMessage,
2394
2926
  className: cn(className),
2927
+ dataTable: {
2928
+ headers: ["Metric", "Value", "Minimum", "Maximum"],
2929
+ rows: [[title, value, min, max]]
2930
+ },
2931
+ showDataTable,
2932
+ format,
2933
+ exportable,
2934
+ exportImage,
2395
2935
  ...props,
2396
- children: /* @__PURE__ */ jsx14("div", { ref: containerRef, className: "h-full w-full" })
2936
+ children: /* @__PURE__ */ jsx15("div", { ref: containerRef, className: "h-full w-full" })
2397
2937
  }
2398
2938
  );
2399
2939
  }
@@ -2410,23 +2950,25 @@ import {
2410
2950
  TitleComponent as TitleComponent10,
2411
2951
  VisualMapComponent
2412
2952
  } from "echarts/components";
2413
- import { CanvasRenderer as CanvasRenderer10 } from "echarts/renderers";
2953
+ import { CanvasRenderer as CanvasRenderer11 } from "echarts/renderers";
2414
2954
  import {
2415
2955
  buildAxis as buildAxis5,
2416
2956
  buildDataLabel as buildDataLabel9,
2417
2957
  buildTooltip as buildTooltip10,
2418
2958
  escapeHtml as escapeHtml5,
2419
2959
  formatTooltipValue as formatTooltipValue5,
2420
- mergeChartOption as mergeChartOption10
2960
+ mergeChartOption as mergeChartOption10,
2961
+ resolveValueFormatter as resolveValueFormatter10,
2962
+ heatmapTable
2421
2963
  } from "@classic-homes/charts-core";
2422
- import { jsx as jsx15 } from "react/jsx-runtime";
2964
+ import { jsx as jsx16 } from "react/jsx-runtime";
2423
2965
  echarts12.use([
2424
2966
  EChartsHeatmapChart,
2425
2967
  GridComponent5,
2426
2968
  TooltipComponent10,
2427
2969
  TitleComponent10,
2428
2970
  VisualMapComponent,
2429
- CanvasRenderer10
2971
+ CanvasRenderer11
2430
2972
  ]);
2431
2973
  var HeatmapChart = React15.forwardRef(
2432
2974
  ({
@@ -2436,6 +2978,8 @@ var HeatmapChart = React15.forwardRef(
2436
2978
  xAxis,
2437
2979
  yAxis,
2438
2980
  height = 400,
2981
+ minHeight,
2982
+ maxHeight,
2439
2983
  loading,
2440
2984
  error,
2441
2985
  emptyMessage,
@@ -2446,9 +2990,16 @@ var HeatmapChart = React15.forwardRef(
2446
2990
  labelFormatter,
2447
2991
  xAxisConfig,
2448
2992
  yAxisConfig,
2993
+ valueFormat,
2994
+ locale,
2449
2995
  tooltipFormatter,
2450
2996
  tooltipValueFormatter,
2451
2997
  option: optionOverride,
2998
+ onReady,
2999
+ events,
3000
+ showDataTable,
3001
+ exportable,
3002
+ patterns,
2452
3003
  onClick,
2453
3004
  class: className,
2454
3005
  ...props
@@ -2462,6 +3013,11 @@ var HeatmapChart = React15.forwardRef(
2462
3013
  }
2463
3014
  const minValue = data?.min ?? dataMin;
2464
3015
  const maxValue = data?.max ?? dataMax;
3016
+ const format = React15.useMemo(
3017
+ () => resolveValueFormatter10(valueFormat, locale),
3018
+ [valueFormat, locale]
3019
+ );
3020
+ const valueFormatter = tooltipValueFormatter ?? format;
2465
3021
  const option = React15.useMemo(() => {
2466
3022
  if (isEmpty) return {};
2467
3023
  return mergeChartOption10(
@@ -2473,13 +3029,13 @@ var HeatmapChart = React15.forwardRef(
2473
3029
  const p = params;
2474
3030
  if (!p.value) return "";
2475
3031
  const [xIdx, yIdx, value] = p.value;
2476
- return `${escapeHtml5(xAxis[xIdx])} / ${escapeHtml5(yAxis[yIdx])}: ${escapeHtml5(formatTooltipValue5(value, tooltipValueFormatter))}`;
3032
+ return `${escapeHtml5(xAxis[xIdx])} / ${escapeHtml5(yAxis[yIdx])}: ${escapeHtml5(formatTooltipValue5(value, valueFormatter))}`;
2477
3033
  }
2478
3034
  },
2479
3035
  {
2480
3036
  show: showTooltip,
2481
3037
  formatter: tooltipFormatter,
2482
- valueFormatter: tooltipValueFormatter
3038
+ valueFormatter
2483
3039
  }
2484
3040
  ),
2485
3041
  grid: {
@@ -2514,7 +3070,8 @@ var HeatmapChart = React15.forwardRef(
2514
3070
  calculable: true,
2515
3071
  orient: "vertical",
2516
3072
  right: "0%",
2517
- top: "center"
3073
+ top: "center",
3074
+ formatter: valueFormatter ? (value) => valueFormatter(value) : void 0
2518
3075
  },
2519
3076
  series: [
2520
3077
  {
@@ -2550,46 +3107,53 @@ var HeatmapChart = React15.forwardRef(
2550
3107
  xAxisConfig,
2551
3108
  yAxisConfig,
2552
3109
  tooltipFormatter,
2553
- tooltipValueFormatter,
3110
+ valueFormatter,
2554
3111
  optionOverride
2555
3112
  ]);
2556
- const latest = useLatestRef({ onClick, xAxis, yAxis });
2557
- const { containerRef } = useChart({
3113
+ const { containerRef, exportImage } = useChart({
2558
3114
  option,
2559
3115
  theme,
2560
3116
  animation,
2561
- onReady: (chart) => {
2562
- chart.on("click", (params) => {
2563
- const { onClick: onClick2, xAxis: xAxis2, yAxis: yAxis2 } = latest.current;
2564
- if (!onClick2) return;
3117
+ patterns,
3118
+ events: chartEvents(events, {
3119
+ click: onClick && ((params) => {
3120
+ if (!onClick) return;
2565
3121
  const [xIdx, yIdx, value] = params.value || [0, 0, 0];
2566
- onClick2({
3122
+ onClick({
2567
3123
  type: params.type || "click",
2568
3124
  componentType: params.componentType || "series",
2569
3125
  xIndex: xIdx,
2570
3126
  yIndex: yIdx,
2571
- xLabel: xAxis2[xIdx],
2572
- yLabel: yAxis2[yIdx],
3127
+ xLabel: xAxis[xIdx],
3128
+ yLabel: yAxis[yIdx],
2573
3129
  value
2574
3130
  });
2575
- });
2576
- }
3131
+ })
3132
+ }),
3133
+ onCreated: onReady
2577
3134
  });
2578
3135
  const accessibilityDescription = description || (!isEmpty ? `${title}. Heatmap with ${xAxis.length} columns and ${yAxis.length} rows.` : void 0);
2579
- return /* @__PURE__ */ jsx15(
3136
+ return /* @__PURE__ */ jsx16(
2580
3137
  ChartContainer,
2581
3138
  {
2582
3139
  ref,
2583
3140
  title,
2584
3141
  description: accessibilityDescription,
2585
3142
  height,
3143
+ minHeight,
3144
+ maxHeight,
2586
3145
  loading,
2587
3146
  error,
2588
3147
  empty: isEmpty,
2589
3148
  emptyMessage,
2590
3149
  className: cn(className),
3150
+ dataTable: isEmpty ? void 0 : heatmapTable(data, xAxis, yAxis),
3151
+ showDataTable,
3152
+ format,
3153
+ exportable,
3154
+ exportImage,
2591
3155
  ...props,
2592
- children: /* @__PURE__ */ jsx15("div", { ref: containerRef, className: "h-full w-full" })
3156
+ children: /* @__PURE__ */ jsx16("div", { ref: containerRef, className: "h-full w-full" })
2593
3157
  }
2594
3158
  );
2595
3159
  }
@@ -2601,7 +3165,7 @@ import * as React16 from "react";
2601
3165
  import * as echarts13 from "echarts/core";
2602
3166
  import { TreemapChart as EChartsTreemapChart } from "echarts/charts";
2603
3167
  import { TooltipComponent as TooltipComponent11, TitleComponent as TitleComponent11 } from "echarts/components";
2604
- import { CanvasRenderer as CanvasRenderer11 } from "echarts/renderers";
3168
+ import { CanvasRenderer as CanvasRenderer12 } from "echarts/renderers";
2605
3169
  import {
2606
3170
  buildDataLabel as buildDataLabel10,
2607
3171
  buildTooltip as buildTooltip11,
@@ -2609,12 +3173,14 @@ import {
2609
3173
  formatTooltipValue as formatTooltipValue6,
2610
3174
  getChartColors as getChartColors10,
2611
3175
  mergeChartOption as mergeChartOption11,
3176
+ resolveValueFormatter as resolveValueFormatter11,
3177
+ treemapTable,
2612
3178
  nameLabelLookup,
2613
3179
  pointLabel as pointLabel4,
2614
3180
  THEME_DARK as THEME_DARK6
2615
3181
  } from "@classic-homes/charts-core";
2616
- import { jsx as jsx16 } from "react/jsx-runtime";
2617
- echarts13.use([EChartsTreemapChart, TooltipComponent11, TitleComponent11, CanvasRenderer11]);
3182
+ import { jsx as jsx17 } from "react/jsx-runtime";
3183
+ echarts13.use([EChartsTreemapChart, TooltipComponent11, TitleComponent11, CanvasRenderer12]);
2618
3184
  var TreemapChart = React16.forwardRef(
2619
3185
  ({
2620
3186
  title,
@@ -2622,6 +3188,8 @@ var TreemapChart = React16.forwardRef(
2622
3188
  data,
2623
3189
  levels,
2624
3190
  height = 400,
3191
+ minHeight,
3192
+ maxHeight,
2625
3193
  loading,
2626
3194
  error,
2627
3195
  emptyMessage,
@@ -2629,9 +3197,16 @@ var TreemapChart = React16.forwardRef(
2629
3197
  animation = true,
2630
3198
  showTooltip = true,
2631
3199
  labelFormatter,
3200
+ valueFormat,
3201
+ locale,
2632
3202
  tooltipFormatter,
2633
3203
  tooltipValueFormatter,
2634
3204
  option: optionOverride,
3205
+ onReady,
3206
+ events,
3207
+ showDataTable,
3208
+ exportable,
3209
+ patterns,
2635
3210
  onClick,
2636
3211
  class: className,
2637
3212
  ...props
@@ -2639,6 +3214,11 @@ var TreemapChart = React16.forwardRef(
2639
3214
  const isEmpty = !data?.length;
2640
3215
  const currentTheme = useChartTheme(theme);
2641
3216
  const chartColors = getChartColors10(currentTheme);
3217
+ const format = React16.useMemo(
3218
+ () => resolveValueFormatter11(valueFormat, locale),
3219
+ [valueFormat, locale]
3220
+ );
3221
+ const valueFormatter = tooltipValueFormatter ?? format;
2642
3222
  const option = React16.useMemo(() => {
2643
3223
  if (isEmpty) return {};
2644
3224
  const toNode = (node) => ({
@@ -2652,13 +3232,13 @@ var TreemapChart = React16.forwardRef(
2652
3232
  {
2653
3233
  formatter: (params) => {
2654
3234
  const p = params;
2655
- return `${escapeHtml6(p.name)}: ${escapeHtml6(formatTooltipValue6(p.value, tooltipValueFormatter))}`;
3235
+ return `${escapeHtml6(p.name)}: ${escapeHtml6(formatTooltipValue6(p.value, valueFormatter))}`;
2656
3236
  }
2657
3237
  },
2658
3238
  {
2659
3239
  show: showTooltip,
2660
3240
  formatter: tooltipFormatter,
2661
- valueFormatter: tooltipValueFormatter
3241
+ valueFormatter
2662
3242
  }
2663
3243
  ),
2664
3244
  series: [
@@ -2718,20 +3298,19 @@ var TreemapChart = React16.forwardRef(
2718
3298
  chartColors,
2719
3299
  labelFormatter,
2720
3300
  tooltipFormatter,
2721
- tooltipValueFormatter,
3301
+ valueFormatter,
2722
3302
  optionOverride
2723
3303
  ]);
2724
- const latest = useLatestRef({ onClick });
2725
- const { containerRef } = useChart({
3304
+ const { containerRef, exportImage } = useChart({
2726
3305
  option,
2727
3306
  theme: currentTheme === THEME_DARK6 ? "dark" : "light",
2728
3307
  animation,
2729
- onReady: (chart) => {
2730
- chart.on("click", (params) => {
2731
- const { onClick: onClick2 } = latest.current;
2732
- if (!onClick2) return;
3308
+ patterns,
3309
+ events: chartEvents(events, {
3310
+ click: onClick && ((params) => {
3311
+ if (!onClick) return;
2733
3312
  const treePathInfo = params.treePathInfo || [];
2734
- onClick2({
3313
+ onClick({
2735
3314
  type: params.type || "click",
2736
3315
  componentType: params.componentType || "series",
2737
3316
  name: params.name || "",
@@ -2739,24 +3318,32 @@ var TreemapChart = React16.forwardRef(
2739
3318
  path: treePathInfo.map((item) => item.name || ""),
2740
3319
  depth: treePathInfo.length - 1
2741
3320
  });
2742
- });
2743
- }
3321
+ })
3322
+ }),
3323
+ onCreated: onReady
2744
3324
  });
2745
3325
  const accessibilityDescription = description || (!isEmpty ? `${title}. Treemap chart showing hierarchical data.` : void 0);
2746
- return /* @__PURE__ */ jsx16(
3326
+ return /* @__PURE__ */ jsx17(
2747
3327
  ChartContainer,
2748
3328
  {
2749
3329
  ref,
2750
3330
  title,
2751
3331
  description: accessibilityDescription,
2752
3332
  height,
3333
+ minHeight,
3334
+ maxHeight,
2753
3335
  loading,
2754
3336
  error,
2755
3337
  empty: isEmpty,
2756
3338
  emptyMessage,
2757
3339
  className: cn(className),
3340
+ dataTable: isEmpty ? void 0 : treemapTable(data),
3341
+ showDataTable,
3342
+ format,
3343
+ exportable,
3344
+ exportImage,
2758
3345
  ...props,
2759
- children: /* @__PURE__ */ jsx16("div", { ref: containerRef, className: "h-full w-full" })
3346
+ children: /* @__PURE__ */ jsx17("div", { ref: containerRef, className: "h-full w-full" })
2760
3347
  }
2761
3348
  );
2762
3349
  }
@@ -2776,15 +3363,17 @@ import {
2776
3363
  TitleComponent as TitleComponent12,
2777
3364
  DataZoomComponent
2778
3365
  } from "echarts/components";
2779
- import { CanvasRenderer as CanvasRenderer12 } from "echarts/renderers";
3366
+ import { CanvasRenderer as CanvasRenderer13 } from "echarts/renderers";
2780
3367
  import {
2781
3368
  buildAxis as buildAxis6,
2782
3369
  buildTooltip as buildTooltip12,
2783
3370
  getChartColors as getChartColors11,
2784
3371
  mergeChartOption as mergeChartOption12,
3372
+ resolveValueFormatter as resolveValueFormatter12,
3373
+ candlestickTable,
2785
3374
  THEME_DARK as THEME_DARK7
2786
3375
  } from "@classic-homes/charts-core";
2787
- import { jsx as jsx17 } from "react/jsx-runtime";
3376
+ import { jsx as jsx18 } from "react/jsx-runtime";
2788
3377
  echarts14.use([
2789
3378
  EChartsCandlestickChart,
2790
3379
  EChartsBarChart2,
@@ -2792,7 +3381,7 @@ echarts14.use([
2792
3381
  TooltipComponent12,
2793
3382
  TitleComponent12,
2794
3383
  DataZoomComponent,
2795
- CanvasRenderer12
3384
+ CanvasRenderer13
2796
3385
  ]);
2797
3386
  var CandlestickChart = React17.forwardRef(
2798
3387
  ({
@@ -2800,6 +3389,8 @@ var CandlestickChart = React17.forwardRef(
2800
3389
  description,
2801
3390
  data,
2802
3391
  height = 400,
3392
+ minHeight,
3393
+ maxHeight,
2803
3394
  loading,
2804
3395
  error,
2805
3396
  emptyMessage,
@@ -2807,11 +3398,19 @@ var CandlestickChart = React17.forwardRef(
2807
3398
  animation = true,
2808
3399
  showTooltip = true,
2809
3400
  showVolume = false,
3401
+ zoomStart = 80,
2810
3402
  xAxisConfig,
2811
3403
  yAxisConfig,
3404
+ valueFormat,
3405
+ locale,
2812
3406
  tooltipFormatter,
2813
3407
  tooltipValueFormatter,
2814
3408
  option: optionOverride,
3409
+ onReady,
3410
+ events,
3411
+ showDataTable,
3412
+ exportable,
3413
+ patterns,
2815
3414
  onClick,
2816
3415
  class: className,
2817
3416
  ...props
@@ -2819,6 +3418,11 @@ var CandlestickChart = React17.forwardRef(
2819
3418
  const isEmpty = !data?.dates?.length || !data?.data?.length;
2820
3419
  const currentTheme = useChartTheme(theme);
2821
3420
  const chartColors = getChartColors11(currentTheme);
3421
+ const format = React17.useMemo(
3422
+ () => resolveValueFormatter12(valueFormat, locale),
3423
+ [valueFormat, locale]
3424
+ );
3425
+ const valueFormatter = tooltipValueFormatter ?? format;
2822
3426
  const option = React17.useMemo(() => {
2823
3427
  if (isEmpty) return {};
2824
3428
  const candlestickData = data.data.map((item) => [item.open, item.close, item.low, item.high]);
@@ -2921,7 +3525,7 @@ var CandlestickChart = React17.forwardRef(
2921
3525
  {
2922
3526
  show: showTooltip,
2923
3527
  formatter: tooltipFormatter,
2924
- valueFormatter: tooltipValueFormatter
3528
+ valueFormatter
2925
3529
  }
2926
3530
  ),
2927
3531
  grid: gridArr,
@@ -2930,14 +3534,14 @@ var CandlestickChart = React17.forwardRef(
2930
3534
  dataZoom: [
2931
3535
  {
2932
3536
  type: "inside",
2933
- start: 80,
3537
+ start: zoomStart,
2934
3538
  end: 100
2935
3539
  },
2936
3540
  {
2937
3541
  show: true,
2938
3542
  type: "slider",
2939
3543
  top: "90%",
2940
- start: 80,
3544
+ start: zoomStart,
2941
3545
  end: 100
2942
3546
  }
2943
3547
  ],
@@ -2950,54 +3554,62 @@ var CandlestickChart = React17.forwardRef(
2950
3554
  isEmpty,
2951
3555
  showTooltip,
2952
3556
  showVolume,
3557
+ zoomStart,
2953
3558
  title,
2954
3559
  chartColors,
2955
3560
  xAxisConfig,
2956
3561
  yAxisConfig,
2957
3562
  tooltipFormatter,
2958
- tooltipValueFormatter,
3563
+ valueFormatter,
2959
3564
  optionOverride
2960
3565
  ]);
2961
- const latest = useLatestRef({ onClick, data });
2962
- const { containerRef } = useChart({
3566
+ const { containerRef, exportImage } = useChart({
2963
3567
  option,
2964
3568
  theme: currentTheme === THEME_DARK7 ? "dark" : "light",
2965
3569
  animation,
2966
- onReady: (chart) => {
2967
- chart.on("click", (params) => {
2968
- const { onClick: onClick2, data: data2 } = latest.current;
2969
- if (!onClick2) return;
3570
+ patterns,
3571
+ events: chartEvents(events, {
3572
+ click: onClick && ((params) => {
3573
+ if (!onClick) return;
2970
3574
  const dataIndex = params.dataIndex || 0;
2971
- const item = data2.data[dataIndex];
3575
+ const item = data.data[dataIndex];
2972
3576
  if (!item) return;
2973
- onClick2({
3577
+ onClick({
2974
3578
  type: params.type || "click",
2975
3579
  componentType: params.componentType || "series",
2976
- date: data2.dates[dataIndex],
3580
+ date: data.dates[dataIndex],
2977
3581
  open: item.open,
2978
3582
  close: item.close,
2979
3583
  high: item.high,
2980
3584
  low: item.low,
2981
- volume: data2.volume?.[dataIndex]
3585
+ volume: data.volume?.[dataIndex]
2982
3586
  });
2983
- });
2984
- }
3587
+ })
3588
+ }),
3589
+ onCreated: onReady
2985
3590
  });
2986
3591
  const accessibilityDescription = description || (!isEmpty ? `${title}. Candlestick chart with ${data.dates.length} data points.` : void 0);
2987
- return /* @__PURE__ */ jsx17(
3592
+ return /* @__PURE__ */ jsx18(
2988
3593
  ChartContainer,
2989
3594
  {
2990
3595
  ref,
2991
3596
  title,
2992
3597
  description: accessibilityDescription,
2993
3598
  height,
3599
+ minHeight,
3600
+ maxHeight,
2994
3601
  loading,
2995
3602
  error,
2996
3603
  empty: isEmpty,
2997
3604
  emptyMessage,
2998
3605
  className: cn(className),
3606
+ dataTable: isEmpty ? void 0 : candlestickTable(data),
3607
+ showDataTable,
3608
+ format,
3609
+ exportable,
3610
+ exportImage,
2999
3611
  ...props,
3000
- children: /* @__PURE__ */ jsx17("div", { ref: containerRef, className: "h-full w-full" })
3612
+ children: /* @__PURE__ */ jsx18("div", { ref: containerRef, className: "h-full w-full" })
3001
3613
  }
3002
3614
  );
3003
3615
  }
@@ -3009,22 +3621,26 @@ import * as React18 from "react";
3009
3621
  import * as echarts15 from "echarts/core";
3010
3622
  import { SankeyChart as EChartsSankeyChart } from "echarts/charts";
3011
3623
  import { TooltipComponent as TooltipComponent13, TitleComponent as TitleComponent13 } from "echarts/components";
3012
- import { CanvasRenderer as CanvasRenderer13 } from "echarts/renderers";
3624
+ import { CanvasRenderer as CanvasRenderer14 } from "echarts/renderers";
3013
3625
  import {
3014
3626
  buildDataLabel as buildDataLabel11,
3015
3627
  buildTooltip as buildTooltip13,
3016
3628
  mergeChartOption as mergeChartOption13,
3629
+ resolveValueFormatter as resolveValueFormatter13,
3630
+ sankeyTable,
3017
3631
  nameLabelLookup as nameLabelLookup2,
3018
3632
  pointLabel as pointLabel5
3019
3633
  } from "@classic-homes/charts-core";
3020
- import { jsx as jsx18 } from "react/jsx-runtime";
3021
- echarts15.use([EChartsSankeyChart, TooltipComponent13, TitleComponent13, CanvasRenderer13]);
3634
+ import { jsx as jsx19 } from "react/jsx-runtime";
3635
+ echarts15.use([EChartsSankeyChart, TooltipComponent13, TitleComponent13, CanvasRenderer14]);
3022
3636
  var SankeyChart = React18.forwardRef(
3023
3637
  ({
3024
3638
  title,
3025
3639
  description,
3026
3640
  data,
3027
3641
  height = 400,
3642
+ minHeight,
3643
+ maxHeight,
3028
3644
  loading,
3029
3645
  error,
3030
3646
  emptyMessage,
@@ -3033,14 +3649,26 @@ var SankeyChart = React18.forwardRef(
3033
3649
  showTooltip = true,
3034
3650
  orient = "horizontal",
3035
3651
  labelFormatter,
3652
+ valueFormat,
3653
+ locale,
3036
3654
  tooltipFormatter,
3037
3655
  tooltipValueFormatter,
3038
3656
  option: optionOverride,
3657
+ onReady,
3658
+ events,
3659
+ showDataTable,
3660
+ exportable,
3661
+ patterns,
3039
3662
  onClick,
3040
3663
  class: className,
3041
3664
  ...props
3042
3665
  }, ref) => {
3043
3666
  const isEmpty = !data?.nodes?.length || !data?.links?.length;
3667
+ const format = React18.useMemo(
3668
+ () => resolveValueFormatter13(valueFormat, locale),
3669
+ [valueFormat, locale]
3670
+ );
3671
+ const valueFormatter = tooltipValueFormatter ?? format;
3044
3672
  const option = React18.useMemo(() => {
3045
3673
  if (isEmpty) return {};
3046
3674
  return mergeChartOption13(
@@ -3053,7 +3681,7 @@ var SankeyChart = React18.forwardRef(
3053
3681
  {
3054
3682
  show: showTooltip,
3055
3683
  formatter: tooltipFormatter,
3056
- valueFormatter: tooltipValueFormatter
3684
+ valueFormatter
3057
3685
  }
3058
3686
  ),
3059
3687
  series: [
@@ -3096,20 +3724,19 @@ var SankeyChart = React18.forwardRef(
3096
3724
  orient,
3097
3725
  labelFormatter,
3098
3726
  tooltipFormatter,
3099
- tooltipValueFormatter,
3727
+ valueFormatter,
3100
3728
  optionOverride
3101
3729
  ]);
3102
- const latest = useLatestRef({ onClick });
3103
- const { containerRef } = useChart({
3730
+ const { containerRef, exportImage } = useChart({
3104
3731
  option,
3105
3732
  theme,
3106
3733
  animation,
3107
- onReady: (chart) => {
3108
- chart.on("click", (params) => {
3109
- const { onClick: onClick2 } = latest.current;
3110
- if (!onClick2) return;
3734
+ patterns,
3735
+ events: chartEvents(events, {
3736
+ click: onClick && ((params) => {
3737
+ if (!onClick) return;
3111
3738
  const isEdge = params.dataType === "edge";
3112
- onClick2({
3739
+ onClick({
3113
3740
  type: params.type || "click",
3114
3741
  componentType: params.componentType || "series",
3115
3742
  dataType: isEdge ? "edge" : "node",
@@ -3118,24 +3745,32 @@ var SankeyChart = React18.forwardRef(
3118
3745
  source: isEdge ? params.data?.source : void 0,
3119
3746
  target: isEdge ? params.data?.target : void 0
3120
3747
  });
3121
- });
3122
- }
3748
+ })
3749
+ }),
3750
+ onCreated: onReady
3123
3751
  });
3124
3752
  const accessibilityDescription = description || (!isEmpty ? `${title}. Sankey diagram with ${data.nodes.length} nodes and ${data.links.length} links.` : void 0);
3125
- return /* @__PURE__ */ jsx18(
3753
+ return /* @__PURE__ */ jsx19(
3126
3754
  ChartContainer,
3127
3755
  {
3128
3756
  ref,
3129
3757
  title,
3130
3758
  description: accessibilityDescription,
3131
3759
  height,
3760
+ minHeight,
3761
+ maxHeight,
3132
3762
  loading,
3133
3763
  error,
3134
3764
  empty: isEmpty,
3135
3765
  emptyMessage,
3136
3766
  className: cn(className),
3767
+ dataTable: isEmpty ? void 0 : sankeyTable(data),
3768
+ showDataTable,
3769
+ format,
3770
+ exportable,
3771
+ exportImage,
3137
3772
  ...props,
3138
- children: /* @__PURE__ */ jsx18("div", { ref: containerRef, className: "h-full w-full" })
3773
+ children: /* @__PURE__ */ jsx19("div", { ref: containerRef, className: "h-full w-full" })
3139
3774
  }
3140
3775
  );
3141
3776
  }
@@ -3146,6 +3781,7 @@ export {
3146
3781
  BarChart,
3147
3782
  CandlestickChart,
3148
3783
  ChartContainer,
3784
+ ChartDataTable,
3149
3785
  ChartEmpty,
3150
3786
  ChartError,
3151
3787
  ChartLegend,
@@ -3161,7 +3797,9 @@ export {
3161
3797
  ScatterChart,
3162
3798
  TreemapChart,
3163
3799
  cn,
3800
+ exportChartImage,
3164
3801
  registerClassicThemes,
3802
+ registerEchartsModules,
3165
3803
  useChart,
3166
3804
  useChartLegend,
3167
3805
  useChartResize,