@langchain/macaw-components 1.0.0-beta.1 → 1.0.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/dist/_chunks/{LoadingIndicator-DgtU9aqD.js → LoadingIndicator-CDcArsiM.js} +13 -12
  2. package/dist/_chunks/LoadingIndicator-CDcArsiM.js.map +1 -0
  3. package/dist/_chunks/render-attachment-icon-BWBEMxXZ.js +270 -0
  4. package/dist/_chunks/render-attachment-icon-BWBEMxXZ.js.map +1 -0
  5. package/dist/catalog.json +527 -408
  6. package/dist/components/Attachment/Attachment.d.ts +21 -0
  7. package/dist/components/Attachment/Attachment.js +165 -0
  8. package/dist/components/Attachment/Attachment.js.map +1 -0
  9. package/dist/components/Attachment/AttachmentList.d.ts +5 -0
  10. package/dist/components/Attachment/AttachmentList.js +32 -0
  11. package/dist/components/Attachment/AttachmentList.js.map +1 -0
  12. package/dist/components/Attachment/index.d.ts +4 -0
  13. package/dist/components/Attachment/index.js +3 -0
  14. package/dist/components/Attachment/render-attachment-icon.d.ts +3 -0
  15. package/dist/components/Attachment/render-attachment-icon.js +2 -0
  16. package/dist/components/Avatar/Avatar.js +2 -2
  17. package/dist/components/Badge/Badge.d.ts +2 -0
  18. package/dist/components/Badge/Badge.js +12 -1
  19. package/dist/components/Badge/Badge.js.map +1 -1
  20. package/dist/components/Banner/Banner.js +1 -1
  21. package/dist/components/Button/Button.js +1 -1
  22. package/dist/components/Button/constants.js +2 -2
  23. package/dist/components/Button/constants.js.map +1 -1
  24. package/dist/components/ChartCard/ChartCard.d.ts +1 -4
  25. package/dist/components/ChartCard/ChartCard.js +2 -2
  26. package/dist/components/ChartCard/ChartCard.js.map +1 -1
  27. package/dist/components/ChartCard/ChartCardSkeleton.d.ts +1 -1
  28. package/dist/components/ChartCard/ChartCardSkeleton.js +37 -0
  29. package/dist/components/ChartCard/ChartCardSkeleton.js.map +1 -1
  30. package/dist/components/ChartLegend/ChartLegend.js +2 -2
  31. package/dist/components/ChartLegend/ChartLegendItemRenderer.js +2 -2
  32. package/dist/components/ChartLegend/ChartLegendItemRenderer.js.map +1 -1
  33. package/dist/components/Code/Code.utils.d.ts +3 -2
  34. package/dist/components/Code/Code.utils.js +7 -3
  35. package/dist/components/Code/Code.utils.js.map +1 -1
  36. package/dist/components/Code/CodeLanguageSelect.d.ts +7 -0
  37. package/dist/components/Code/CodeLanguageSelect.js +29 -0
  38. package/dist/components/Code/CodeLanguageSelect.js.map +1 -0
  39. package/dist/components/Code/CodeLite.js +3 -0
  40. package/dist/components/Code/CodeLite.js.map +1 -1
  41. package/dist/components/Code/CodeToolbar.d.ts +7 -0
  42. package/dist/components/Code/CodeToolbar.js +19 -0
  43. package/dist/components/Code/CodeToolbar.js.map +1 -0
  44. package/dist/components/Code/codeLanguages.d.ts +7 -0
  45. package/dist/components/Code/codeLanguages.js +59 -0
  46. package/dist/components/Code/codeLanguages.js.map +1 -0
  47. package/dist/components/Code/index.d.ts +15 -2
  48. package/dist/components/Code/index.js +70 -50
  49. package/dist/components/Code/index.js.map +1 -1
  50. package/dist/components/Code/types.d.ts +1 -1
  51. package/dist/components/Command/Command.d.ts +10 -13
  52. package/dist/components/Command/Command.js +7 -2
  53. package/dist/components/Command/Command.js.map +1 -1
  54. package/dist/components/Command/CommandMenu.d.ts +7 -1
  55. package/dist/components/Command/CommandMenu.js +17 -9
  56. package/dist/components/Command/CommandMenu.js.map +1 -1
  57. package/dist/components/ContextMenu/ContextMenu.d.ts +6 -0
  58. package/dist/components/ContextMenu/ContextMenu.js +3 -2
  59. package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
  60. package/dist/components/CopyButton/CopyButton.js +2 -2
  61. package/dist/components/Dialog/index.js +2 -2
  62. package/dist/components/DropdownMenu/DropdownMenu.d.ts +11 -0
  63. package/dist/components/DropdownMenu/DropdownMenu.js +5 -4
  64. package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
  65. package/dist/components/ErrorMessage/ErrorMessage.js +1 -1
  66. package/dist/components/GroupedTabs/GroupedTabs.d.ts +5 -2
  67. package/dist/components/GroupedTabs/GroupedTabs.js +33 -26
  68. package/dist/components/GroupedTabs/GroupedTabs.js.map +1 -1
  69. package/dist/components/IconButton/IconButton.js +2 -2
  70. package/dist/components/Input/Input.js +1 -1
  71. package/dist/components/LineChart/LineChart.d.ts +2 -2
  72. package/dist/components/LineChart/LineChart.js +3 -1
  73. package/dist/components/LineChart/LineChart.js.map +1 -1
  74. package/dist/components/LineChart/LineChart.types.d.ts +16 -0
  75. package/dist/components/LineChart/LineChartPlot.d.ts +3 -2
  76. package/dist/components/LineChart/LineChartPlot.js +8 -1
  77. package/dist/components/LineChart/LineChartPlot.js.map +1 -1
  78. package/dist/components/LineChart/LineChartVerticalMarkers.d.ts +8 -0
  79. package/dist/components/LineChart/LineChartVerticalMarkers.js +47 -0
  80. package/dist/components/LineChart/LineChartVerticalMarkers.js.map +1 -0
  81. package/dist/components/LineChart/index.d.ts +1 -1
  82. package/dist/components/Logo/index.js +11 -6
  83. package/dist/components/Logo/index.js.map +1 -1
  84. package/dist/components/MetricChart/MetricChart.d.ts +2 -0
  85. package/dist/components/MetricChart/MetricChart.js +15 -4
  86. package/dist/components/MetricChart/MetricChart.js.map +1 -1
  87. package/dist/components/MetricChart/index.d.ts +1 -1
  88. package/dist/components/Pane/Pane.js +2 -2
  89. package/dist/components/SankeyChart/AnimatedSankeyLink.d.ts +17 -0
  90. package/dist/components/SankeyChart/AnimatedSankeyLink.js +44 -0
  91. package/dist/components/SankeyChart/AnimatedSankeyLink.js.map +1 -0
  92. package/dist/components/SankeyChart/AnimatedSankeyNode.d.ts +16 -0
  93. package/dist/components/SankeyChart/AnimatedSankeyNode.js +42 -0
  94. package/dist/components/SankeyChart/AnimatedSankeyNode.js.map +1 -0
  95. package/dist/components/SankeyChart/SankeyChart.d.ts +42 -0
  96. package/dist/components/SankeyChart/SankeyChart.js +185 -0
  97. package/dist/components/SankeyChart/SankeyChart.js.map +1 -0
  98. package/dist/components/SankeyChart/SankeyChart.types.d.ts +90 -0
  99. package/dist/components/SankeyChart/SankeyChart.types.js +0 -0
  100. package/dist/components/SankeyChart/SankeyChart.utils.d.ts +21 -0
  101. package/dist/components/SankeyChart/SankeyChart.utils.js +299 -0
  102. package/dist/components/SankeyChart/SankeyChart.utils.js.map +1 -0
  103. package/dist/components/SankeyChart/SankeyNodeLabel.d.ts +10 -0
  104. package/dist/components/SankeyChart/SankeyNodeLabel.js +30 -0
  105. package/dist/components/SankeyChart/SankeyNodeLabel.js.map +1 -0
  106. package/dist/components/SankeyChart/SankeyNodeLabel.utils.d.ts +9 -0
  107. package/dist/components/SankeyChart/SankeyNodeLabel.utils.js +29 -0
  108. package/dist/components/SankeyChart/SankeyNodeLabel.utils.js.map +1 -0
  109. package/dist/components/SankeyChart/constants.d.ts +22 -0
  110. package/dist/components/SankeyChart/constants.js +27 -0
  111. package/dist/components/SankeyChart/constants.js.map +1 -0
  112. package/dist/components/SankeyChart/index.d.ts +5 -0
  113. package/dist/components/SankeyChart/index.js +4 -0
  114. package/dist/components/Select/Select.js +5 -5
  115. package/dist/components/Select/Select.js.map +1 -1
  116. package/dist/components/Select/SelectPrimitive.d.ts +6 -0
  117. package/dist/components/Select/SelectPrimitive.js +3 -2
  118. package/dist/components/Select/SelectPrimitive.js.map +1 -1
  119. package/dist/components/Slider/Slider.js +10 -3
  120. package/dist/components/Slider/Slider.js.map +1 -1
  121. package/dist/components/SplitViewPane/SplitViewPane.d.ts +2 -1
  122. package/dist/components/SplitViewPane/SplitViewPane.js +113 -219
  123. package/dist/components/SplitViewPane/SplitViewPane.js.map +1 -1
  124. package/dist/components/SplitViewPane/SplitViewPaneHeader.js +2 -2
  125. package/dist/components/SplitViewPane/useShowChildren.d.ts +5 -0
  126. package/dist/components/SplitViewPane/useShowChildren.js +14 -0
  127. package/dist/components/SplitViewPane/useShowChildren.js.map +1 -0
  128. package/dist/components/SplitViewPane/useSplitViewPaneResize.d.ts +21 -0
  129. package/dist/components/SplitViewPane/useSplitViewPaneResize.js +145 -0
  130. package/dist/components/SplitViewPane/useSplitViewPaneResize.js.map +1 -0
  131. package/dist/components/Textarea/Textarea.d.ts +4 -3
  132. package/dist/components/Textarea/Textarea.js +7 -21
  133. package/dist/components/Textarea/Textarea.js.map +1 -1
  134. package/dist/components/ThinkingState/LoadingIndicator.d.ts +1 -0
  135. package/dist/components/ThinkingState/LoadingIndicator.js +1 -1
  136. package/dist/components/ThinkingState/ThinkingState.d.ts +1 -0
  137. package/dist/components/ThinkingState/ThinkingState.js +5 -4
  138. package/dist/components/ThinkingState/ThinkingState.js.map +1 -1
  139. package/dist/components/ThinkingState/index.js +1 -1
  140. package/dist/components/Toast/index.js +33 -28
  141. package/dist/components/Toast/index.js.map +1 -1
  142. package/dist/components/Tooltip/Tooltip.js +2 -2
  143. package/dist/components/Typeahead/Typeahead.js +18 -8
  144. package/dist/components/Typeahead/Typeahead.js.map +1 -1
  145. package/dist/components/Typeahead/Typeahead.types.d.ts +2 -0
  146. package/dist/components/Typeahead/TypeaheadParts.d.ts +3 -1
  147. package/dist/components/Typeahead/TypeaheadParts.js +7 -6
  148. package/dist/components/Typeahead/TypeaheadParts.js.map +1 -1
  149. package/dist/components/Typeahead/TypeaheadView.js +19 -13
  150. package/dist/components/Typeahead/TypeaheadView.js.map +1 -1
  151. package/dist/components/Typeahead/useTypeaheadDomSync.d.ts +1 -1
  152. package/dist/components/Typeahead/useTypeaheadDomSync.js +14 -8
  153. package/dist/components/Typeahead/useTypeaheadDomSync.js.map +1 -1
  154. package/dist/components/Typeahead/useTypeaheadUncontrolledInput.d.ts +2 -1
  155. package/dist/components/Typeahead/useTypeaheadUncontrolledInput.js +10 -9
  156. package/dist/components/Typeahead/useTypeaheadUncontrolledInput.js.map +1 -1
  157. package/dist/components/UnsavedChangesDialog.js +2 -2
  158. package/dist/components/index.d.ts +3 -1
  159. package/dist/components/index.js +7 -5
  160. package/dist/components.css +22 -18
  161. package/dist/hooks/useDebouncedCommit.d.ts +14 -0
  162. package/dist/hooks/useDebouncedCommit.js +35 -0
  163. package/dist/hooks/useDebouncedCommit.js.map +1 -0
  164. package/dist/icons/LongTailPhosphorIcons.js +1 -1
  165. package/dist/icons/PaddedPhosphorIcons.d.ts +1 -0
  166. package/dist/icons/PaddedPhosphorIcons.js +4 -2
  167. package/dist/icons/PaddedPhosphorIcons.js.map +1 -1
  168. package/dist/icons/WeightedPhosphorIcons.d.ts +1 -0
  169. package/dist/icons/WeightedPhosphorIcons.js +3 -1
  170. package/dist/icons/WeightedPhosphorIcons.js.map +1 -1
  171. package/dist/icons/index.js +3 -3
  172. package/dist/index.js +7 -5
  173. package/dist/utilities.css +1 -1
  174. package/dist/utils/chartColors.d.ts +2 -1
  175. package/dist/utils/chartColors.js +2 -1
  176. package/dist/utils/chartColors.js.map +1 -1
  177. package/dist/utils/componentSizes.d.ts +0 -1
  178. package/dist/utils/componentSizes.js.map +1 -1
  179. package/dist/utils/lazy-codemirror-loader.d.ts +0 -2
  180. package/dist/utils/lazy-codemirror-loader.js +1 -3
  181. package/dist/utils/lazy-codemirror-loader.js.map +1 -1
  182. package/docs/DESIGN.md +17 -0
  183. package/docs/STYLES.md +4 -1
  184. package/package.json +21 -8
  185. package/dist/_chunks/LoadingIndicator-DgtU9aqD.js.map +0 -1
@@ -0,0 +1,42 @@
1
+ import { type HTMLAttributes } from 'react';
2
+ import { type ChartLegendProps } from '../ChartLegend/index.js';
3
+ import type { SankeyChartAlignment, SankeyChartInteractionProps, SankeyChartLayoutLink, SankeyChartLayoutNode, SankeyChartLink, SankeyChartNode, SankeyChartSlots } from './SankeyChart.types.js';
4
+ export type SankeyChartProps = Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'aria-label'> & SankeyChartInteractionProps & {
5
+ nodes: readonly SankeyChartNode[];
6
+ links: readonly SankeyChartLink[];
7
+ /** Column assignment strategy. Defaults to `justified`. */
8
+ alignment?: SankeyChartAlignment;
9
+ /** Vertical gap between nodes in one column, in SVG pixels. Defaults to 12. */
10
+ nodePadding?: number;
11
+ /** Controlled legend filter. An empty set renders every node. */
12
+ selectedIds?: ReadonlySet<string>;
13
+ /** Emphasizes one node and the links touching it; dims the rest. */
14
+ activeNodeId?: string | null;
15
+ /** Emphasizes one link and its endpoint nodes; dims the rest. */
16
+ activeLinkId?: string | null;
17
+ /** Emphasizes marks represented by one external legend item. Built-in legends set this automatically. */
18
+ activeLegendItemId?: string | null;
19
+ /** Minimum plot width before scrolling. Defaults to 160; 0 allows smaller plots. Stage spacing is always preserved. */
20
+ minimumPlotWidth?: number;
21
+ /** Animates the diagram unless reduced motion is preferred. Defaults to true. */
22
+ shouldAnimate?: boolean;
23
+ /** Set false to drop the marks while a parent is actively resizing. Defaults to true. */
24
+ isRendering?: boolean;
25
+ /** Defaults to true when the chart has more than one node. */
26
+ showLegend?: boolean;
27
+ /** Forwarded to the rendered `ChartLegend`. Inert when there is no legend. */
28
+ legendProps?: Omit<ChartLegendProps, 'items'>;
29
+ slots?: SankeyChartSlots;
30
+ 'aria-label'?: string;
31
+ 'aria-describedby'?: string;
32
+ /** Overrides the node's accessible name. Defaults to its ariaLabel, text label, then ID. */
33
+ getNodeAriaLabel?: (node: SankeyChartLayoutNode) => string | undefined;
34
+ /** Names a link and makes it a keyboard target. Actionable/focusable links default to endpoints and value. */
35
+ getLinkAriaLabel?: (link: SankeyChartLayoutLink) => string | undefined;
36
+ };
37
+ /**
38
+ * Renders weighted flows with automatic columns and source-colored links.
39
+ * Consumers own data, value formatting, tooltips, and navigation; compose with
40
+ * ChartCard, ChartTooltip, and ChartLegend. Slots customize SVG labels and overlays.
41
+ */
42
+ export declare const SankeyChart: ({ nodes, links, alignment, nodePadding, selectedIds, activeNodeId, activeLinkId, activeLegendItemId, minimumPlotWidth, shouldAnimate, isRendering, showLegend, legendProps, slots, className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, getNodeAriaLabel, getLinkAriaLabel, onNodePointerMove, onNodePointerOut, onNodeActivate, onNodeFocus, onNodeBlur, onLinkPointerMove, onLinkPointerOut, onLinkActivate, onLinkFocus, onLinkBlur, ...rest }: SankeyChartProps) => import("react").JSX.Element;
@@ -0,0 +1,185 @@
1
+ import { cn } from "../../utils/cn.js";
2
+ import { getCategoricalFillChartColor } from "../../utils/chartColors.js";
3
+ import { getAccessibleText } from "../ChartLegend/utils.js";
4
+ import { ChartLegend } from "../ChartLegend/ChartLegend.js";
5
+ import "./constants.js";
6
+ import { getSankeyChartLayout } from "./SankeyChart.utils.js";
7
+ import { AnimatedSankeyLink } from "./AnimatedSankeyLink.js";
8
+ import { AnimatedSankeyNode } from "./AnimatedSankeyNode.js";
9
+ import { SankeyNodeLabel } from "./SankeyNodeLabel.js";
10
+ import { getSankeyNodeLabels } from "./SankeyNodeLabel.utils.js";
11
+ import { useMemo, useState } from "react";
12
+ import { jsx, jsxs } from "react/jsx-runtime";
13
+ import { useReducedMotion, useSpring } from "@react-spring/web";
14
+ import { useResizeObserver } from "@mantine/hooks";
15
+ //#region packages/components/src/components/SankeyChart/SankeyChart.tsx
16
+ /**
17
+ * Renders weighted flows with automatic columns and source-colored links.
18
+ * Consumers own data, value formatting, tooltips, and navigation; compose with
19
+ * ChartCard, ChartTooltip, and ChartLegend. Slots customize SVG labels and overlays.
20
+ */
21
+ var SankeyChart = ({ nodes, links, alignment = "justified", nodePadding, selectedIds, activeNodeId, activeLinkId, activeLegendItemId, minimumPlotWidth = 160, shouldAnimate = true, isRendering = true, showLegend, legendProps, slots, className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, getNodeAriaLabel, getLinkAriaLabel, onNodePointerMove, onNodePointerOut, onNodeActivate, onNodeFocus, onNodeBlur, onLinkPointerMove, onLinkPointerOut, onLinkActivate, onLinkFocus, onLinkBlur, ...rest }) => {
22
+ const [containerRef, dimensions] = useResizeObserver();
23
+ const [activeBuiltInLegendItemId, setActiveBuiltInLegendItemId] = useState(null);
24
+ const isReducedMotion = (useReducedMotion() ?? false) || !shouldAnimate;
25
+ const normalizedNodes = useMemo(() => nodes.map((node, index) => ({
26
+ ...node,
27
+ color: node.color ?? getCategoricalFillChartColor(index)
28
+ })), [nodes]);
29
+ const hasLabels = dimensions.width >= 480;
30
+ const chartMargin = {
31
+ top: 8,
32
+ right: (hasLabels ? 128 : 0) + 8,
33
+ bottom: 8,
34
+ left: (hasLabels ? 128 : 0) + 8
35
+ };
36
+ const innerWidth = dimensions.width === 0 ? 0 : Math.max(0, minimumPlotWidth, dimensions.width - chartMargin.left - chartMargin.right);
37
+ const innerHeight = Math.max(0, dimensions.height - chartMargin.top - chartMargin.bottom);
38
+ const hasData = nodes.length > 0;
39
+ const layout = useMemo(() => {
40
+ const selectedNodes = normalizedNodes.filter((node) => selectedIds?.has(node.id));
41
+ return getSankeyChartLayout({
42
+ nodes: selectedNodes.length > 0 ? selectedNodes : normalizedNodes,
43
+ links,
44
+ innerWidth,
45
+ innerHeight,
46
+ alignment,
47
+ nodePadding
48
+ });
49
+ }, [
50
+ normalizedNodes,
51
+ selectedIds,
52
+ links,
53
+ innerWidth,
54
+ innerHeight,
55
+ alignment,
56
+ nodePadding
57
+ ]);
58
+ const chartWidth = dimensions.width === 0 ? 0 : layout.innerWidth + chartMargin.left + chartMargin.right;
59
+ const chartHeight = Math.max(dimensions.height, layout.innerHeight + chartMargin.top + chartMargin.bottom);
60
+ const animationKey = JSON.stringify([layout.nodes.map((node) => [
61
+ node.id,
62
+ node.x,
63
+ node.y0,
64
+ node.y1
65
+ ]), layout.links.map((link) => [
66
+ link.id,
67
+ link.sourceId,
68
+ link.targetId,
69
+ link.value,
70
+ link.width,
71
+ link.y0,
72
+ link.y1
73
+ ])]);
74
+ const [animation] = useSpring(() => ({
75
+ from: { progress: 0 },
76
+ to: { progress: hasData && isRendering ? 1 : 0 },
77
+ reset: true,
78
+ immediate: isReducedMotion
79
+ }), [
80
+ animationKey,
81
+ hasData,
82
+ isRendering,
83
+ isReducedMotion
84
+ ]);
85
+ const drawnNodeIds = new Set(layout.nodes.map((node) => node.id));
86
+ const nodeLabels = getSankeyNodeLabels(layout.nodes, alignment);
87
+ const legendItems = normalizedNodes.map((node) => ({
88
+ id: node.id,
89
+ label: node.label,
90
+ "aria-label": node.ariaLabel,
91
+ markerColor: node.color,
92
+ selected: selectedIds?.has(node.id) ?? false
93
+ }));
94
+ const hasLegend = (showLegend ?? legendItems.length > 1) && legendItems.length > 0;
95
+ const requestedActiveId = (hasLegend ? activeBuiltInLegendItemId : null) ?? activeLegendItemId;
96
+ const activeId = requestedActiveId != null && drawnNodeIds.has(requestedActiveId) ? requestedActiveId : activeNodeId != null && drawnNodeIds.has(activeNodeId) ? activeNodeId : null;
97
+ const activeLink = activeLinkId == null ? null : layout.links.find((link) => link.id === activeLinkId) ?? null;
98
+ const isLinkDimmed = (link) => activeId != null ? link.sourceId !== activeId && link.targetId !== activeId : activeLink != null && link.id !== activeLink.id;
99
+ const isNodeDimmed = (node) => activeId != null ? node.id !== activeId : activeLink != null && node.id !== activeLink.sourceId && node.id !== activeLink.targetId;
100
+ const canDraw = dimensions.width > 0 && dimensions.height > 0 && hasData;
101
+ const plot = /* @__PURE__ */ jsx("div", {
102
+ ref: containerRef,
103
+ className: "relative min-h-0 min-w-0 flex-1 overflow-auto",
104
+ children: /* @__PURE__ */ jsx("div", {
105
+ style: {
106
+ width: chartWidth,
107
+ height: chartHeight
108
+ },
109
+ children: /* @__PURE__ */ jsx("svg", {
110
+ width: chartWidth,
111
+ height: chartHeight,
112
+ role: hasData ? "graphics-document group" : "img",
113
+ "aria-label": ariaLabel,
114
+ "aria-labelledby": ariaLabelledBy,
115
+ "aria-describedby": ariaDescribedBy,
116
+ className: "block size-full",
117
+ children: canDraw && isRendering && /* @__PURE__ */ jsxs("g", {
118
+ transform: `translate(${chartMargin.left}, ${chartMargin.top})`,
119
+ children: [
120
+ layout.links.map((link) => /* @__PURE__ */ jsx(AnimatedSankeyLink, {
121
+ link,
122
+ animationProgress: animation.progress,
123
+ ariaLabel: getLinkAriaLabel?.(link) ?? (onLinkActivate != null || onLinkFocus != null ? `${link.source.ariaLabel ?? getAccessibleText(link.source.label) ?? link.sourceId} to ${link.target.ariaLabel ?? getAccessibleText(link.target.label) ?? link.targetId}: ${link.value}` : void 0),
124
+ isDimmed: isLinkDimmed(link),
125
+ isEmphasized: activeLink?.id === link.id || activeId != null && (link.sourceId === activeId || link.targetId === activeId),
126
+ onPointerMove: onLinkPointerMove,
127
+ onPointerOut: onLinkPointerOut,
128
+ onActivate: onLinkActivate,
129
+ onFocus: onLinkFocus,
130
+ onBlur: onLinkBlur
131
+ }, link.id)),
132
+ layout.nodes.map((node) => /* @__PURE__ */ jsx(AnimatedSankeyNode, {
133
+ node,
134
+ animationProgress: animation.progress,
135
+ ariaLabel: getNodeAriaLabel?.(node) ?? node.ariaLabel ?? getAccessibleText(node.label) ?? node.id,
136
+ isDimmed: isNodeDimmed(node),
137
+ onPointerMove: onNodePointerMove,
138
+ onPointerOut: onNodePointerOut,
139
+ onActivate: onNodeActivate,
140
+ onFocus: onNodeFocus,
141
+ onBlur: onNodeBlur
142
+ }, node.id)),
143
+ hasLabels && nodeLabels.map(({ node, isVisible, ...bounds }) => slots?.nodeLabel != null ? /* @__PURE__ */ jsx("g", { children: slots.nodeLabel({
144
+ node,
145
+ alignment,
146
+ ...bounds
147
+ }) }, `label:${node.id}`) : isVisible ? /* @__PURE__ */ jsx(SankeyNodeLabel, {
148
+ node,
149
+ isDimmed: isNodeDimmed(node),
150
+ isActive: activeId === node.id,
151
+ ...bounds
152
+ }, `label:${node.id}`) : null),
153
+ slots?.overlay?.({
154
+ nodes: layout.nodes,
155
+ links: layout.links,
156
+ innerWidth: layout.innerWidth,
157
+ innerHeight: layout.innerHeight
158
+ })
159
+ ]
160
+ })
161
+ })
162
+ })
163
+ });
164
+ const legend = /* @__PURE__ */ jsx(ChartLegend, {
165
+ "aria-label": ariaLabel == null ? void 0 : `${ariaLabel} legend`,
166
+ ...legendProps,
167
+ items: legendItems,
168
+ onItemActiveChange: (item) => {
169
+ setActiveBuiltInLegendItemId(item?.id ?? null);
170
+ legendProps?.onItemActiveChange?.(item);
171
+ }
172
+ });
173
+ return /* @__PURE__ */ jsxs("div", {
174
+ className: cn("flex size-full min-h-0 min-w-0 flex-col gap-space-2 @container", className),
175
+ ...rest,
176
+ children: [plot, hasLegend && /* @__PURE__ */ jsx("div", {
177
+ className: "shrink-0",
178
+ children: legend
179
+ })]
180
+ });
181
+ };
182
+ //#endregion
183
+ export { SankeyChart };
184
+
185
+ //# sourceMappingURL=SankeyChart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SankeyChart.js","names":[],"sources":["../../../src/components/SankeyChart/SankeyChart.tsx"],"sourcesContent":["import { useMemo, useState, type HTMLAttributes } from 'react';\n\nimport { useResizeObserver } from '@mantine/hooks';\nimport { useReducedMotion, useSpring } from '@react-spring/web';\n\nimport { getCategoricalFillChartColor } from '../../utils/chartColors';\nimport { cn } from '../../utils/cn';\nimport {\n ChartLegend,\n getAccessibleText,\n type ChartLegendItem,\n type ChartLegendProps,\n} from '../ChartLegend';\nimport { AnimatedSankeyLink } from './AnimatedSankeyLink';\nimport { AnimatedSankeyNode } from './AnimatedSankeyNode';\nimport {\n SANKEY_MINIMUM_PLOT_WIDTH,\n SANKEY_NODE_LABEL_WIDTH,\n} from './constants';\nimport type {\n SankeyChartAlignment,\n SankeyChartInteractionProps,\n SankeyChartLayoutLink,\n SankeyChartLayoutNode,\n SankeyChartLink,\n SankeyChartNode,\n SankeyChartSlots,\n} from './SankeyChart.types';\nimport { getSankeyChartLayout } from './SankeyChart.utils';\nimport { SankeyNodeLabel } from './SankeyNodeLabel';\nimport { getSankeyNodeLabels } from './SankeyNodeLabel.utils';\n\nexport type SankeyChartProps = Omit<\n HTMLAttributes<HTMLDivElement>,\n 'children' | 'aria-label'\n> &\n SankeyChartInteractionProps & {\n nodes: readonly SankeyChartNode[];\n links: readonly SankeyChartLink[];\n /** Column assignment strategy. Defaults to `justified`. */\n alignment?: SankeyChartAlignment;\n /** Vertical gap between nodes in one column, in SVG pixels. Defaults to 12. */\n nodePadding?: number;\n /** Controlled legend filter. An empty set renders every node. */\n selectedIds?: ReadonlySet<string>;\n /** Emphasizes one node and the links touching it; dims the rest. */\n activeNodeId?: string | null;\n /** Emphasizes one link and its endpoint nodes; dims the rest. */\n activeLinkId?: string | null;\n /** Emphasizes marks represented by one external legend item. Built-in legends set this automatically. */\n activeLegendItemId?: string | null;\n /** Minimum plot width before scrolling. Defaults to 160; 0 allows smaller plots. Stage spacing is always preserved. */\n minimumPlotWidth?: number;\n /** Animates the diagram unless reduced motion is preferred. Defaults to true. */\n shouldAnimate?: boolean;\n /** Set false to drop the marks while a parent is actively resizing. Defaults to true. */\n isRendering?: boolean;\n /** Defaults to true when the chart has more than one node. */\n showLegend?: boolean;\n /** Forwarded to the rendered `ChartLegend`. Inert when there is no legend. */\n legendProps?: Omit<ChartLegendProps, 'items'>;\n slots?: SankeyChartSlots;\n 'aria-label'?: string;\n 'aria-describedby'?: string;\n /** Overrides the node's accessible name. Defaults to its ariaLabel, text label, then ID. */\n getNodeAriaLabel?: (node: SankeyChartLayoutNode) => string | undefined;\n /** Names a link and makes it a keyboard target. Actionable/focusable links default to endpoints and value. */\n getLinkAriaLabel?: (link: SankeyChartLayoutLink) => string | undefined;\n };\n\n/**\n * Renders weighted flows with automatic columns and source-colored links.\n * Consumers own data, value formatting, tooltips, and navigation; compose with\n * ChartCard, ChartTooltip, and ChartLegend. Slots customize SVG labels and overlays.\n */\nexport const SankeyChart = ({\n nodes,\n links,\n alignment = 'justified',\n nodePadding,\n selectedIds,\n activeNodeId,\n activeLinkId,\n activeLegendItemId,\n minimumPlotWidth = SANKEY_MINIMUM_PLOT_WIDTH,\n shouldAnimate = true,\n isRendering = true,\n showLegend,\n legendProps,\n slots,\n className,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n getNodeAriaLabel,\n getLinkAriaLabel,\n onNodePointerMove,\n onNodePointerOut,\n onNodeActivate,\n onNodeFocus,\n onNodeBlur,\n onLinkPointerMove,\n onLinkPointerOut,\n onLinkActivate,\n onLinkFocus,\n onLinkBlur,\n ...rest\n}: SankeyChartProps) => {\n const [containerRef, dimensions] = useResizeObserver();\n const [activeBuiltInLegendItemId, setActiveBuiltInLegendItemId] = useState<\n string | null\n >(null);\n const isReducedMotion = (useReducedMotion() ?? false) || !shouldAnimate;\n\n const normalizedNodes = useMemo(\n () =>\n nodes.map((node, index) => ({\n ...node,\n color: node.color ?? getCategoricalFillChartColor(index),\n })),\n [nodes]\n );\n // Labels sit beside the node rectangles: right of them for every column but\n // the last, which flips left. Narrow containers skip the built-in labels\n // entirely — the legend still names every node — so the plot keeps its width.\n const hasLabels = dimensions.width >= 480;\n const chartMargin = {\n top: 8,\n right: (hasLabels ? SANKEY_NODE_LABEL_WIDTH : 0) + 8,\n bottom: 8,\n left: (hasLabels ? SANKEY_NODE_LABEL_WIDTH : 0) + 8,\n };\n const innerWidth =\n dimensions.width === 0\n ? 0\n : Math.max(\n 0,\n minimumPlotWidth,\n dimensions.width - chartMargin.left - chartMargin.right\n );\n const innerHeight = Math.max(\n 0,\n dimensions.height - chartMargin.top - chartMargin.bottom\n );\n const hasData = nodes.length > 0;\n const layout = useMemo(() => {\n const selectedNodes = normalizedNodes.filter((node) =>\n selectedIds?.has(node.id)\n );\n // Empty or stale selections show every node; the layout drops dangling links.\n return getSankeyChartLayout({\n nodes: selectedNodes.length > 0 ? selectedNodes : normalizedNodes,\n links,\n innerWidth,\n innerHeight,\n alignment,\n nodePadding,\n });\n }, [\n normalizedNodes,\n selectedIds,\n links,\n innerWidth,\n innerHeight,\n alignment,\n nodePadding,\n ]);\n const chartWidth =\n dimensions.width === 0\n ? 0\n : layout.innerWidth + chartMargin.left + chartMargin.right;\n const chartHeight = Math.max(\n dimensions.height,\n layout.innerHeight + chartMargin.top + chartMargin.bottom\n );\n const animationKey = JSON.stringify([\n layout.nodes.map((node) => [node.id, node.x, node.y0, node.y1]),\n layout.links.map((link) => [\n link.id,\n link.sourceId,\n link.targetId,\n link.value,\n link.width,\n link.y0,\n link.y1,\n ]),\n ]);\n const [animation] = useSpring(\n () => ({\n from: { progress: 0 },\n to: { progress: hasData && isRendering ? 1 : 0 },\n reset: true,\n immediate: isReducedMotion,\n }),\n [animationKey, hasData, isRendering, isReducedMotion]\n );\n\n const drawnNodeIds = new Set(layout.nodes.map((node) => node.id));\n const nodeLabels = getSankeyNodeLabels(layout.nodes, alignment);\n\n const legendItems: readonly ChartLegendItem[] = normalizedNodes.map(\n (node) => ({\n id: node.id,\n label: node.label,\n 'aria-label': node.ariaLabel,\n markerColor: node.color,\n selected: selectedIds?.has(node.id) ?? false,\n })\n );\n const hasLegend =\n (showLegend ?? legendItems.length > 1) && legendItems.length > 0;\n\n const requestedActiveId =\n (hasLegend ? activeBuiltInLegendItemId : null) ?? activeLegendItemId;\n const activeId =\n requestedActiveId != null && drawnNodeIds.has(requestedActiveId)\n ? requestedActiveId\n : activeNodeId != null && drawnNodeIds.has(activeNodeId)\n ? activeNodeId\n : null;\n const activeLink =\n activeLinkId == null\n ? null\n : (layout.links.find((link) => link.id === activeLinkId) ?? null);\n\n const isLinkDimmed = (link: SankeyChartLayoutLink) =>\n activeId != null\n ? link.sourceId !== activeId && link.targetId !== activeId\n : activeLink != null && link.id !== activeLink.id;\n\n const isNodeDimmed = (node: SankeyChartLayoutNode) =>\n activeId != null\n ? node.id !== activeId\n : activeLink != null &&\n node.id !== activeLink.sourceId &&\n node.id !== activeLink.targetId;\n\n const canDraw = dimensions.width > 0 && dimensions.height > 0 && hasData;\n\n const plot = (\n <div\n ref={containerRef}\n className=\"relative min-h-0 min-w-0 flex-1 overflow-auto\"\n >\n <div style={{ width: chartWidth, height: chartHeight }}>\n <svg\n width={chartWidth}\n height={chartHeight}\n role={hasData ? 'graphics-document group' : 'img'}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={ariaDescribedBy}\n className=\"block size-full\"\n >\n {canDraw && isRendering && (\n <g transform={`translate(${chartMargin.left}, ${chartMargin.top})`}>\n {layout.links.map((link) => (\n <AnimatedSankeyLink\n key={link.id}\n link={link}\n animationProgress={animation.progress}\n ariaLabel={\n getLinkAriaLabel?.(link) ??\n (onLinkActivate != null || onLinkFocus != null\n ? `${link.source.ariaLabel ?? getAccessibleText(link.source.label) ?? link.sourceId} to ${link.target.ariaLabel ?? getAccessibleText(link.target.label) ?? link.targetId}: ${link.value}`\n : undefined)\n }\n isDimmed={isLinkDimmed(link)}\n isEmphasized={\n activeLink?.id === link.id ||\n (activeId != null &&\n (link.sourceId === activeId ||\n link.targetId === activeId))\n }\n onPointerMove={onLinkPointerMove}\n onPointerOut={onLinkPointerOut}\n onActivate={onLinkActivate}\n onFocus={onLinkFocus}\n onBlur={onLinkBlur}\n />\n ))}\n {layout.nodes.map((node) => (\n <AnimatedSankeyNode\n key={node.id}\n node={node}\n animationProgress={animation.progress}\n ariaLabel={\n getNodeAriaLabel?.(node) ??\n node.ariaLabel ??\n getAccessibleText(node.label) ??\n node.id\n }\n isDimmed={isNodeDimmed(node)}\n onPointerMove={onNodePointerMove}\n onPointerOut={onNodePointerOut}\n onActivate={onNodeActivate}\n onFocus={onNodeFocus}\n onBlur={onNodeBlur}\n />\n ))}\n {hasLabels &&\n nodeLabels.map(({ node, isVisible, ...bounds }) =>\n slots?.nodeLabel != null ? (\n <g key={`label:${node.id}`}>\n {slots.nodeLabel({\n node,\n alignment,\n ...bounds,\n })}\n </g>\n ) : isVisible ? (\n <SankeyNodeLabel\n key={`label:${node.id}`}\n node={node}\n isDimmed={isNodeDimmed(node)}\n isActive={activeId === node.id}\n {...bounds}\n />\n ) : null\n )}\n {slots?.overlay?.({\n nodes: layout.nodes,\n links: layout.links,\n innerWidth: layout.innerWidth,\n innerHeight: layout.innerHeight,\n })}\n </g>\n )}\n </svg>\n </div>\n </div>\n );\n\n const legend = (\n <ChartLegend\n aria-label={ariaLabel == null ? undefined : `${ariaLabel} legend`}\n {...legendProps}\n items={legendItems}\n onItemActiveChange={(item) => {\n setActiveBuiltInLegendItemId(item?.id ?? null);\n legendProps?.onItemActiveChange?.(item);\n }}\n />\n );\n\n return (\n <div\n className={cn(\n 'flex size-full min-h-0 min-w-0 flex-col gap-space-2 @container',\n className\n )}\n {...rest}\n >\n {plot}\n {hasLegend && <div className=\"shrink-0\">{legend}</div>}\n </div>\n );\n};\n"],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ import type { ReactNode } from 'react';
2
+ export type SankeyChartNode = {
3
+ /** Stable ID. Must be unique within the chart. */
4
+ id: string;
5
+ label: ReactNode;
6
+ /** Plain-text name for assistive technology. Defaults to `label` when it is text, then `id`. */
7
+ ariaLabel?: string;
8
+ /** Use a design-system CSS chart color token. Defaults to a categorical fill by node order. */
9
+ color?: string;
10
+ };
11
+ export type SankeyChartLink = {
12
+ /** Unique ID. Defaults to `${sourceId}->${targetId}`, with numeric suffixes for collisions.
13
+ * Supply an ID to preserve a parallel link's identity across reordering. */
14
+ id?: string;
15
+ sourceId: string;
16
+ targetId: string;
17
+ value: number;
18
+ /** Use a design-system CSS chart color token. Defaults to the source node color. */
19
+ color?: string;
20
+ };
21
+ export type SankeyChartLayoutNode = {
22
+ id: string;
23
+ label: ReactNode;
24
+ ariaLabel?: string;
25
+ color: string;
26
+ /** Zero-based column, derived from the graph topology and alignment. */
27
+ depth: number;
28
+ /** Larger inflow/outflow total, capped at Number.MAX_VALUE on numeric overflow. */
29
+ value: number;
30
+ x: number;
31
+ y0: number;
32
+ y1: number;
33
+ };
34
+ export type SankeyChartLayoutLink = {
35
+ id: string;
36
+ sourceId: string;
37
+ targetId: string;
38
+ value: number;
39
+ color: string;
40
+ /** Link thickness in SVG pixels. */
41
+ width: number;
42
+ /** Vertical center of the link where it leaves the source node. */
43
+ y0: number;
44
+ /** Vertical center of the link where it enters the target node. */
45
+ y1: number;
46
+ source: SankeyChartLayoutNode;
47
+ target: SankeyChartLayoutNode;
48
+ };
49
+ export type SankeyChartLayout = {
50
+ nodes: readonly SankeyChartLayoutNode[];
51
+ links: readonly SankeyChartLayoutLink[];
52
+ /** Required plot width, expanded to keep adjacent stages apart. */
53
+ innerWidth: number;
54
+ /** Required plot height, expanded when minimum node heights cannot fit. */
55
+ innerHeight: number;
56
+ };
57
+ export type SankeyChartAlignment = 'justified' | 'center' | 'left' | 'right';
58
+ /** Side of the node rectangle its label renders on. */
59
+ export type SankeyChartLabelSide = 'right' | 'left';
60
+ export type SankeyChartRenderProps = {
61
+ nodes: readonly SankeyChartLayoutNode[];
62
+ links: readonly SankeyChartLayoutLink[];
63
+ innerWidth: number;
64
+ innerHeight: number;
65
+ };
66
+ export type SankeyChartSlots = {
67
+ /** Renders SVG-compatible content above the links, nodes, and labels. */
68
+ overlay?: (props: SankeyChartRenderProps) => ReactNode;
69
+ /** Replaces the built-in node labels. Return SVG-compatible content. */
70
+ nodeLabel?: (props: {
71
+ node: SankeyChartLayoutNode;
72
+ alignment: SankeyChartAlignment;
73
+ side: SankeyChartLabelSide;
74
+ /** Available label bounds in plot coordinates. */
75
+ x: number;
76
+ width: number;
77
+ }) => ReactNode;
78
+ };
79
+ export type SankeyChartInteractionProps = {
80
+ onNodePointerMove?: (node: SankeyChartLayoutNode) => void;
81
+ onNodePointerOut?: () => void;
82
+ onNodeActivate?: (node: SankeyChartLayoutNode) => void;
83
+ onNodeFocus?: (node: SankeyChartLayoutNode) => void;
84
+ onNodeBlur?: () => void;
85
+ onLinkPointerMove?: (link: SankeyChartLayoutLink) => void;
86
+ onLinkPointerOut?: () => void;
87
+ onLinkActivate?: (link: SankeyChartLayoutLink) => void;
88
+ onLinkFocus?: (link: SankeyChartLayoutLink) => void;
89
+ onLinkBlur?: () => void;
90
+ };
@@ -0,0 +1,21 @@
1
+ import type { SankeyChartAlignment, SankeyChartLayout, SankeyChartLink, SankeyChartNode } from './SankeyChart.types.js';
2
+ /**
3
+ * Assigns columns, scales flow, and relaxes positions toward connected nodes.
4
+ * Nodes use the larger of inflow and outflow; crowded plots expand to fit.
5
+ */
6
+ export declare const getSankeyChartLayout: ({ nodes, links, innerWidth: requestedInnerWidth, innerHeight: requestedInnerHeight, alignment, nodePadding, }: {
7
+ nodes: readonly SankeyChartNode[];
8
+ links: readonly SankeyChartLink[];
9
+ innerWidth: number;
10
+ innerHeight: number;
11
+ alignment?: SankeyChartAlignment;
12
+ nodePadding?: number;
13
+ }) => SankeyChartLayout;
14
+ /** Cubic bezier flow ribbon between a link's node edges. */
15
+ export declare const getSankeyLinkPath: (link: {
16
+ sourceX: number;
17
+ targetX: number;
18
+ y0: number;
19
+ y1: number;
20
+ width: number;
21
+ }) => string;