@mastra/playground-ui 41.0.0 → 41.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/dist/Composer.css +25 -0
- package/dist/components/Composer.cjs.js +101 -0
- package/dist/components/Composer.cjs.js.map +1 -0
- package/dist/components/Composer.d.ts +2 -0
- package/dist/components/Composer.es.js +93 -0
- package/dist/components/Composer.es.js.map +1 -0
- package/dist/components/SankeyChart.cjs.js +362 -0
- package/dist/components/SankeyChart.cjs.js.map +1 -0
- package/dist/components/SankeyChart.d.ts +2 -0
- package/dist/components/SankeyChart.es.js +352 -0
- package/dist/components/SankeyChart.es.js.map +1 -0
- package/dist/src/ds/components/Composer/composer.d.ts +10 -0
- package/dist/src/ds/components/Composer/composer.stories.d.ts +8 -0
- package/dist/src/ds/components/Composer/index.d.ts +2 -0
- package/dist/src/ds/components/SankeyChart/index.d.ts +6 -0
- package/dist/src/ds/components/SankeyChart/sankey-chart-utils.d.ts +39 -0
- package/dist/src/ds/components/SankeyChart/sankey-chart.d.ts +8 -0
- package/dist/src/ds/components/SankeyChart/sankey-chart.stories.d.ts +9 -0
- package/dist/src/ds/components/SankeyChart/sankey-context.d.ts +29 -0
- package/dist/src/ds/components/SankeyChart/sankeyColor.d.ts +6 -0
- package/dist/style.css +61 -0
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @mastra/playground-ui
|
|
2
2
|
|
|
3
|
+
## 41.1.0-alpha.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies:
|
|
8
|
+
- @mastra/core@1.51.1-alpha.1
|
|
9
|
+
- @mastra/client-js@1.32.1-alpha.1
|
|
10
|
+
- @mastra/react@1.2.6-alpha.1
|
|
11
|
+
|
|
12
|
+
## 41.1.0-alpha.0
|
|
13
|
+
|
|
14
|
+
### Minor Changes
|
|
15
|
+
|
|
16
|
+
- Added a composable Sankey provider and chart with customizable controls through the `useSankey` hook, curve selection metadata, deterministic node colors, gradient ribbons, and connected hover feedback. ([#19472](https://github.com/mastra-ai/mastra/pull/19472))
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Added reusable Composer compound components for building controlled chat inputs. ([#19470](https://github.com/mastra-ai/mastra/pull/19470))
|
|
21
|
+
|
|
22
|
+
- Updated dependencies [[`8a0d145`](https://github.com/mastra-ai/mastra/commit/8a0d145aadbdf7278665aceaaec364b35dd9bd94), [`bd2f1d2`](https://github.com/mastra-ai/mastra/commit/bd2f1d274d05e60e2366f005ea0d94d5cea0d5ff), [`21a0eb8`](https://github.com/mastra-ai/mastra/commit/21a0eb86746ba0b703acea360d4f84c6a5a493f2), [`de86fd7`](https://github.com/mastra-ai/mastra/commit/de86fd7119f0438381d1a642e3d258143c0b9c29), [`2fd1a51`](https://github.com/mastra-ai/mastra/commit/2fd1a510946ede90bd42de32c315f7586bfcfd20), [`2745031`](https://github.com/mastra-ai/mastra/commit/2745031d1d4a4978f037092da371428c32e2842a), [`db650ce`](https://github.com/mastra-ai/mastra/commit/db650ce490348914e85b93651d83acdf8f2a4c31), [`6354eeb`](https://github.com/mastra-ai/mastra/commit/6354eeb32efa9f5f68f51dda394e90e2ee76f1fb), [`21a0eb8`](https://github.com/mastra-ai/mastra/commit/21a0eb86746ba0b703acea360d4f84c6a5a493f2)]:
|
|
23
|
+
- @mastra/core@1.51.1-alpha.0
|
|
24
|
+
- @mastra/react@1.2.6-alpha.0
|
|
25
|
+
- @mastra/memory@1.23.1-alpha.0
|
|
26
|
+
- @mastra/client-js@1.32.1-alpha.0
|
|
27
|
+
|
|
3
28
|
## 41.0.0
|
|
4
29
|
|
|
5
30
|
### Minor Changes
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
@keyframes composer-sending {
|
|
2
|
+
0% {
|
|
3
|
+
transform: translate3d(0, 300%, 0);
|
|
4
|
+
opacity: 0;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
15% {
|
|
8
|
+
opacity: 0.35;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
85% {
|
|
12
|
+
opacity: 0.35;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
100% {
|
|
16
|
+
transform: translate3d(0, -200%, 0);
|
|
17
|
+
opacity: 0;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.composer-sending {
|
|
22
|
+
animation: composer-sending 900ms cubic-bezier(0.22, 1, 0.36, 1) both;
|
|
23
|
+
will-change: transform, opacity;
|
|
24
|
+
backface-visibility: hidden;
|
|
25
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
|
|
5
|
+
require('../Composer.css');const jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
const React = require('react');
|
|
7
|
+
const scrollArea = require('../scroll-area-C3deZ3yj.cjs');
|
|
8
|
+
const utils_cn = require('../cn-vA5sWo9W.cjs');
|
|
9
|
+
|
|
10
|
+
const Composer = React.forwardRef(({ children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("form", { ref, "data-slot": "composer", ...props, children }));
|
|
11
|
+
Composer.displayName = "Composer";
|
|
12
|
+
const ComposerBox = React.forwardRef(
|
|
13
|
+
({ children, className, sendingPulseKey = 0, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14
|
+
"div",
|
|
15
|
+
{
|
|
16
|
+
ref,
|
|
17
|
+
"data-slot": "composer-box",
|
|
18
|
+
className: utils_cn.cn(
|
|
19
|
+
"duration-normal @container relative mx-auto mt-auto w-full max-w-3xl overflow-hidden rounded-[22px] border border-border2/40 bg-surface3 transition-colors focus-within:border-border2",
|
|
20
|
+
className
|
|
21
|
+
),
|
|
22
|
+
...props,
|
|
23
|
+
children: [
|
|
24
|
+
/* @__PURE__ */ jsxRuntime.jsx(ComposerSendingPulse, { pulseKey: sendingPulseKey }),
|
|
25
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative z-10", children })
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
)
|
|
29
|
+
);
|
|
30
|
+
ComposerBox.displayName = "ComposerBox";
|
|
31
|
+
const ComposerAttachments = React.forwardRef(
|
|
32
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
33
|
+
"div",
|
|
34
|
+
{
|
|
35
|
+
ref,
|
|
36
|
+
role: "region",
|
|
37
|
+
"data-slot": "composer-attachments",
|
|
38
|
+
className: utils_cn.cn("mx-auto w-full max-w-3xl pb-2", className),
|
|
39
|
+
...props
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
);
|
|
43
|
+
ComposerAttachments.displayName = "ComposerAttachments";
|
|
44
|
+
const ComposerInput = React.forwardRef(
|
|
45
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(scrollArea.ScrollArea, { maxHeight: "212px", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
46
|
+
"textarea",
|
|
47
|
+
{
|
|
48
|
+
ref,
|
|
49
|
+
"data-slot": "composer-input",
|
|
50
|
+
className: utils_cn.cn(
|
|
51
|
+
"min-h-17 field-sizing-content w-full resize-none bg-transparent px-3 pt-3 pb-2 text-ui-lg leading-ui-lg text-neutral6 outline-hidden placeholder:text-neutral3 focus:outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
|
|
52
|
+
className
|
|
53
|
+
),
|
|
54
|
+
...props
|
|
55
|
+
}
|
|
56
|
+
) })
|
|
57
|
+
);
|
|
58
|
+
ComposerInput.displayName = "ComposerInput";
|
|
59
|
+
const ComposerActions = React.forwardRef(
|
|
60
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
61
|
+
"div",
|
|
62
|
+
{
|
|
63
|
+
ref,
|
|
64
|
+
role: "region",
|
|
65
|
+
"data-slot": "composer-actions",
|
|
66
|
+
className: utils_cn.cn("flex flex-wrap-reverse items-center justify-between gap-2 px-1.5 pb-1.5", className),
|
|
67
|
+
...props
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
);
|
|
71
|
+
ComposerActions.displayName = "ComposerActions";
|
|
72
|
+
const ComposerGradientColumn = ({ className }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils_cn.cn("flex size-full flex-col -space-y-3", className), children: [
|
|
73
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full flex-1 bg-accent1 blur-xl" }),
|
|
74
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full flex-1 bg-accent1Dark blur-xl" }),
|
|
75
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full flex-1 bg-accent1 blur-xl" }),
|
|
76
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full flex-1 bg-accent1Darker blur-xl" })
|
|
77
|
+
] });
|
|
78
|
+
const ComposerSendingPulse = ({ pulseKey }) => {
|
|
79
|
+
if (pulseKey === 0) return null;
|
|
80
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
81
|
+
"div",
|
|
82
|
+
{
|
|
83
|
+
"aria-hidden": "true",
|
|
84
|
+
"data-slot": "composer-sending-pulse",
|
|
85
|
+
className: "composer-sending pointer-events-none absolute top-0 left-[-10%] z-0 flex h-10 w-[120%] transform-gpu",
|
|
86
|
+
children: [
|
|
87
|
+
/* @__PURE__ */ jsxRuntime.jsx(ComposerGradientColumn, {}),
|
|
88
|
+
/* @__PURE__ */ jsxRuntime.jsx(ComposerGradientColumn, { className: "-translate-y-2" }),
|
|
89
|
+
/* @__PURE__ */ jsxRuntime.jsx(ComposerGradientColumn, {})
|
|
90
|
+
]
|
|
91
|
+
},
|
|
92
|
+
pulseKey
|
|
93
|
+
);
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
exports.Composer = Composer;
|
|
97
|
+
exports.ComposerActions = ComposerActions;
|
|
98
|
+
exports.ComposerAttachments = ComposerAttachments;
|
|
99
|
+
exports.ComposerBox = ComposerBox;
|
|
100
|
+
exports.ComposerInput = ComposerInput;
|
|
101
|
+
//# sourceMappingURL=Composer.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Composer.cjs.js","sources":["../../src/ds/components/Composer/composer.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef } from 'react';\nimport { forwardRef } from 'react';\n\nimport { ScrollArea } from '../ScrollArea';\nimport { cn } from '@/lib/utils';\n\nimport './composer-sending.css';\n\nexport type ComposerProps = ComponentPropsWithoutRef<'form'>;\n\nexport const Composer = forwardRef<HTMLFormElement, ComposerProps>(({ children, ...props }, ref) => (\n <form ref={ref} data-slot=\"composer\" {...props}>\n {children}\n </form>\n));\nComposer.displayName = 'Composer';\n\nexport interface ComposerBoxProps extends ComponentPropsWithoutRef<'div'> {\n sendingPulseKey?: number;\n}\n\nexport const ComposerBox = forwardRef<HTMLDivElement, ComposerBoxProps>(\n ({ children, className, sendingPulseKey = 0, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"composer-box\"\n className={cn(\n 'duration-normal @container relative mx-auto mt-auto w-full max-w-3xl overflow-hidden rounded-[22px] border border-border2/40 bg-surface3 transition-colors focus-within:border-border2',\n className,\n )}\n {...props}\n >\n <ComposerSendingPulse pulseKey={sendingPulseKey} />\n <div className=\"relative z-10\">{children}</div>\n </div>\n ),\n);\nComposerBox.displayName = 'ComposerBox';\n\nexport const ComposerAttachments = forwardRef<HTMLDivElement, ComponentPropsWithoutRef<'div'>>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n role=\"region\"\n data-slot=\"composer-attachments\"\n className={cn('mx-auto w-full max-w-3xl pb-2', className)}\n {...props}\n />\n ),\n);\nComposerAttachments.displayName = 'ComposerAttachments';\n\nexport const ComposerInput = forwardRef<HTMLTextAreaElement, ComponentPropsWithoutRef<'textarea'>>(\n ({ className, ...props }, ref) => (\n <ScrollArea maxHeight=\"212px\">\n <textarea\n ref={ref}\n data-slot=\"composer-input\"\n className={cn(\n 'min-h-17 field-sizing-content w-full resize-none bg-transparent px-3 pt-3 pb-2 text-ui-lg leading-ui-lg text-neutral6 outline-hidden placeholder:text-neutral3 focus:outline-hidden disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n {...props}\n />\n </ScrollArea>\n ),\n);\nComposerInput.displayName = 'ComposerInput';\n\nexport const ComposerActions = forwardRef<HTMLDivElement, ComponentPropsWithoutRef<'div'>>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n role=\"region\"\n data-slot=\"composer-actions\"\n className={cn('flex flex-wrap-reverse items-center justify-between gap-2 px-1.5 pb-1.5', className)}\n {...props}\n />\n ),\n);\nComposerActions.displayName = 'ComposerActions';\n\nconst ComposerGradientColumn = ({ className }: { className?: string }) => (\n <div className={cn('flex size-full flex-col -space-y-3', className)}>\n <div className=\"w-full flex-1 bg-accent1 blur-xl\" />\n <div className=\"w-full flex-1 bg-accent1Dark blur-xl\" />\n <div className=\"w-full flex-1 bg-accent1 blur-xl\" />\n <div className=\"w-full flex-1 bg-accent1Darker blur-xl\" />\n </div>\n);\n\nconst ComposerSendingPulse = ({ pulseKey }: { pulseKey: number }) => {\n if (pulseKey === 0) return null;\n\n return (\n <div\n key={pulseKey}\n aria-hidden=\"true\"\n data-slot=\"composer-sending-pulse\"\n className=\"composer-sending pointer-events-none absolute top-0 left-[-10%] z-0 flex h-10 w-[120%] transform-gpu\"\n >\n <ComposerGradientColumn />\n <ComposerGradientColumn className=\"-translate-y-2\" />\n <ComposerGradientColumn />\n </div>\n );\n};\n"],"names":["forwardRef","jsx","jsxs","cn","ScrollArea"],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import { S as ScrollArea } from '../scroll-area-DcY6f0GS.js';
|
|
4
|
+
import { c as cn } from '../cn-BakJzhuv.js';
|
|
5
|
+
|
|
6
|
+
import '../Composer.css';const Composer = forwardRef(({ children, ...props }, ref) => /* @__PURE__ */ jsx("form", { ref, "data-slot": "composer", ...props, children }));
|
|
7
|
+
Composer.displayName = "Composer";
|
|
8
|
+
const ComposerBox = forwardRef(
|
|
9
|
+
({ children, className, sendingPulseKey = 0, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
10
|
+
"div",
|
|
11
|
+
{
|
|
12
|
+
ref,
|
|
13
|
+
"data-slot": "composer-box",
|
|
14
|
+
className: cn(
|
|
15
|
+
"duration-normal @container relative mx-auto mt-auto w-full max-w-3xl overflow-hidden rounded-[22px] border border-border2/40 bg-surface3 transition-colors focus-within:border-border2",
|
|
16
|
+
className
|
|
17
|
+
),
|
|
18
|
+
...props,
|
|
19
|
+
children: [
|
|
20
|
+
/* @__PURE__ */ jsx(ComposerSendingPulse, { pulseKey: sendingPulseKey }),
|
|
21
|
+
/* @__PURE__ */ jsx("div", { className: "relative z-10", children })
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
);
|
|
26
|
+
ComposerBox.displayName = "ComposerBox";
|
|
27
|
+
const ComposerAttachments = forwardRef(
|
|
28
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
29
|
+
"div",
|
|
30
|
+
{
|
|
31
|
+
ref,
|
|
32
|
+
role: "region",
|
|
33
|
+
"data-slot": "composer-attachments",
|
|
34
|
+
className: cn("mx-auto w-full max-w-3xl pb-2", className),
|
|
35
|
+
...props
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
);
|
|
39
|
+
ComposerAttachments.displayName = "ComposerAttachments";
|
|
40
|
+
const ComposerInput = forwardRef(
|
|
41
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(ScrollArea, { maxHeight: "212px", children: /* @__PURE__ */ jsx(
|
|
42
|
+
"textarea",
|
|
43
|
+
{
|
|
44
|
+
ref,
|
|
45
|
+
"data-slot": "composer-input",
|
|
46
|
+
className: cn(
|
|
47
|
+
"min-h-17 field-sizing-content w-full resize-none bg-transparent px-3 pt-3 pb-2 text-ui-lg leading-ui-lg text-neutral6 outline-hidden placeholder:text-neutral3 focus:outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
|
|
48
|
+
className
|
|
49
|
+
),
|
|
50
|
+
...props
|
|
51
|
+
}
|
|
52
|
+
) })
|
|
53
|
+
);
|
|
54
|
+
ComposerInput.displayName = "ComposerInput";
|
|
55
|
+
const ComposerActions = forwardRef(
|
|
56
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
57
|
+
"div",
|
|
58
|
+
{
|
|
59
|
+
ref,
|
|
60
|
+
role: "region",
|
|
61
|
+
"data-slot": "composer-actions",
|
|
62
|
+
className: cn("flex flex-wrap-reverse items-center justify-between gap-2 px-1.5 pb-1.5", className),
|
|
63
|
+
...props
|
|
64
|
+
}
|
|
65
|
+
)
|
|
66
|
+
);
|
|
67
|
+
ComposerActions.displayName = "ComposerActions";
|
|
68
|
+
const ComposerGradientColumn = ({ className }) => /* @__PURE__ */ jsxs("div", { className: cn("flex size-full flex-col -space-y-3", className), children: [
|
|
69
|
+
/* @__PURE__ */ jsx("div", { className: "w-full flex-1 bg-accent1 blur-xl" }),
|
|
70
|
+
/* @__PURE__ */ jsx("div", { className: "w-full flex-1 bg-accent1Dark blur-xl" }),
|
|
71
|
+
/* @__PURE__ */ jsx("div", { className: "w-full flex-1 bg-accent1 blur-xl" }),
|
|
72
|
+
/* @__PURE__ */ jsx("div", { className: "w-full flex-1 bg-accent1Darker blur-xl" })
|
|
73
|
+
] });
|
|
74
|
+
const ComposerSendingPulse = ({ pulseKey }) => {
|
|
75
|
+
if (pulseKey === 0) return null;
|
|
76
|
+
return /* @__PURE__ */ jsxs(
|
|
77
|
+
"div",
|
|
78
|
+
{
|
|
79
|
+
"aria-hidden": "true",
|
|
80
|
+
"data-slot": "composer-sending-pulse",
|
|
81
|
+
className: "composer-sending pointer-events-none absolute top-0 left-[-10%] z-0 flex h-10 w-[120%] transform-gpu",
|
|
82
|
+
children: [
|
|
83
|
+
/* @__PURE__ */ jsx(ComposerGradientColumn, {}),
|
|
84
|
+
/* @__PURE__ */ jsx(ComposerGradientColumn, { className: "-translate-y-2" }),
|
|
85
|
+
/* @__PURE__ */ jsx(ComposerGradientColumn, {})
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
pulseKey
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export { Composer, ComposerActions, ComposerAttachments, ComposerBox, ComposerInput };
|
|
93
|
+
//# sourceMappingURL=Composer.es.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Composer.es.js","sources":["../../src/ds/components/Composer/composer.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef } from 'react';\nimport { forwardRef } from 'react';\n\nimport { ScrollArea } from '../ScrollArea';\nimport { cn } from '@/lib/utils';\n\nimport './composer-sending.css';\n\nexport type ComposerProps = ComponentPropsWithoutRef<'form'>;\n\nexport const Composer = forwardRef<HTMLFormElement, ComposerProps>(({ children, ...props }, ref) => (\n <form ref={ref} data-slot=\"composer\" {...props}>\n {children}\n </form>\n));\nComposer.displayName = 'Composer';\n\nexport interface ComposerBoxProps extends ComponentPropsWithoutRef<'div'> {\n sendingPulseKey?: number;\n}\n\nexport const ComposerBox = forwardRef<HTMLDivElement, ComposerBoxProps>(\n ({ children, className, sendingPulseKey = 0, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"composer-box\"\n className={cn(\n 'duration-normal @container relative mx-auto mt-auto w-full max-w-3xl overflow-hidden rounded-[22px] border border-border2/40 bg-surface3 transition-colors focus-within:border-border2',\n className,\n )}\n {...props}\n >\n <ComposerSendingPulse pulseKey={sendingPulseKey} />\n <div className=\"relative z-10\">{children}</div>\n </div>\n ),\n);\nComposerBox.displayName = 'ComposerBox';\n\nexport const ComposerAttachments = forwardRef<HTMLDivElement, ComponentPropsWithoutRef<'div'>>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n role=\"region\"\n data-slot=\"composer-attachments\"\n className={cn('mx-auto w-full max-w-3xl pb-2', className)}\n {...props}\n />\n ),\n);\nComposerAttachments.displayName = 'ComposerAttachments';\n\nexport const ComposerInput = forwardRef<HTMLTextAreaElement, ComponentPropsWithoutRef<'textarea'>>(\n ({ className, ...props }, ref) => (\n <ScrollArea maxHeight=\"212px\">\n <textarea\n ref={ref}\n data-slot=\"composer-input\"\n className={cn(\n 'min-h-17 field-sizing-content w-full resize-none bg-transparent px-3 pt-3 pb-2 text-ui-lg leading-ui-lg text-neutral6 outline-hidden placeholder:text-neutral3 focus:outline-hidden disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n {...props}\n />\n </ScrollArea>\n ),\n);\nComposerInput.displayName = 'ComposerInput';\n\nexport const ComposerActions = forwardRef<HTMLDivElement, ComponentPropsWithoutRef<'div'>>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n role=\"region\"\n data-slot=\"composer-actions\"\n className={cn('flex flex-wrap-reverse items-center justify-between gap-2 px-1.5 pb-1.5', className)}\n {...props}\n />\n ),\n);\nComposerActions.displayName = 'ComposerActions';\n\nconst ComposerGradientColumn = ({ className }: { className?: string }) => (\n <div className={cn('flex size-full flex-col -space-y-3', className)}>\n <div className=\"w-full flex-1 bg-accent1 blur-xl\" />\n <div className=\"w-full flex-1 bg-accent1Dark blur-xl\" />\n <div className=\"w-full flex-1 bg-accent1 blur-xl\" />\n <div className=\"w-full flex-1 bg-accent1Darker blur-xl\" />\n </div>\n);\n\nconst ComposerSendingPulse = ({ pulseKey }: { pulseKey: number }) => {\n if (pulseKey === 0) return null;\n\n return (\n <div\n key={pulseKey}\n aria-hidden=\"true\"\n data-slot=\"composer-sending-pulse\"\n className=\"composer-sending pointer-events-none absolute top-0 left-[-10%] z-0 flex h-10 w-[120%] transform-gpu\"\n >\n <ComposerGradientColumn />\n <ComposerGradientColumn className=\"-translate-y-2\" />\n <ComposerGradientColumn />\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
|
|
5
|
+
const jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
const React = require('react');
|
|
7
|
+
const recharts = require('recharts');
|
|
8
|
+
const spacings = require('../spacings-BP8L49kn.cjs');
|
|
9
|
+
const utils_cn = require('../cn-vA5sWo9W.cjs');
|
|
10
|
+
|
|
11
|
+
const EMPTY_GRAPH = { nodes: [], links: [] };
|
|
12
|
+
function getSankeyChartValue(value) {
|
|
13
|
+
if (typeof value === "string") {
|
|
14
|
+
const trimmedValue = value.trim();
|
|
15
|
+
return trimmedValue.length > 0 ? trimmedValue : void 0;
|
|
16
|
+
}
|
|
17
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
18
|
+
return void 0;
|
|
19
|
+
}
|
|
20
|
+
function reorderSankeyChartColumns(columns, startIndex, endIndex) {
|
|
21
|
+
if (startIndex === endIndex || startIndex < 0 || endIndex < 0 || startIndex >= columns.length || endIndex >= columns.length) {
|
|
22
|
+
return columns;
|
|
23
|
+
}
|
|
24
|
+
const reorderedColumns = [...columns];
|
|
25
|
+
const [movedColumn] = reorderedColumns.splice(startIndex, 1);
|
|
26
|
+
if (!movedColumn) return columns;
|
|
27
|
+
reorderedColumns.splice(endIndex, 0, movedColumn);
|
|
28
|
+
return reorderedColumns;
|
|
29
|
+
}
|
|
30
|
+
function buildSankeyChartGraph(data, columns) {
|
|
31
|
+
if (columns.length < 2 || data.length === 0) return EMPTY_GRAPH;
|
|
32
|
+
const nodes = [];
|
|
33
|
+
const nodeIndexes = /* @__PURE__ */ new Map();
|
|
34
|
+
const linksById = /* @__PURE__ */ new Map();
|
|
35
|
+
const getNode = (column, value) => {
|
|
36
|
+
const id = createNodeId(column.id, value);
|
|
37
|
+
const existingIndex = nodeIndexes.get(id);
|
|
38
|
+
const existingNode = existingIndex === void 0 ? void 0 : nodes[existingIndex];
|
|
39
|
+
if (existingIndex !== void 0 && existingNode) return { node: existingNode, index: existingIndex };
|
|
40
|
+
const node = { id, name: String(value), column, value };
|
|
41
|
+
const index = nodes.length;
|
|
42
|
+
nodes.push(node);
|
|
43
|
+
nodeIndexes.set(id, index);
|
|
44
|
+
return { node, index };
|
|
45
|
+
};
|
|
46
|
+
for (let columnIndex = 0; columnIndex < columns.length - 1; columnIndex += 1) {
|
|
47
|
+
const sourceColumn = columns[columnIndex];
|
|
48
|
+
const targetColumn = columns[columnIndex + 1];
|
|
49
|
+
if (!sourceColumn || !targetColumn) continue;
|
|
50
|
+
for (const record of data) {
|
|
51
|
+
const sourceValue = getSankeyChartValue(record[sourceColumn.id]);
|
|
52
|
+
const targetValue = getSankeyChartValue(record[targetColumn.id]);
|
|
53
|
+
if (sourceValue === void 0 || targetValue === void 0) continue;
|
|
54
|
+
const source = getNode(sourceColumn, sourceValue);
|
|
55
|
+
const target = getNode(targetColumn, targetValue);
|
|
56
|
+
const id = `${source.node.id}->${target.node.id}`;
|
|
57
|
+
const existingLink = linksById.get(id);
|
|
58
|
+
if (existingLink) {
|
|
59
|
+
existingLink.value += 1;
|
|
60
|
+
existingLink.records.push(record);
|
|
61
|
+
} else {
|
|
62
|
+
linksById.set(id, {
|
|
63
|
+
id,
|
|
64
|
+
source: source.index,
|
|
65
|
+
target: target.index,
|
|
66
|
+
value: 1,
|
|
67
|
+
sourceNode: source.node,
|
|
68
|
+
targetNode: target.node,
|
|
69
|
+
records: [record]
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return { nodes, links: [...linksById.values()] };
|
|
75
|
+
}
|
|
76
|
+
function getSankeyChartCurveSelection(link) {
|
|
77
|
+
return {
|
|
78
|
+
source: { column: link.sourceNode.column, value: link.sourceNode.value },
|
|
79
|
+
target: { column: link.targetNode.column, value: link.targetNode.value },
|
|
80
|
+
records: link.records
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function createNodeId(columnId, value) {
|
|
84
|
+
return JSON.stringify([columnId, typeof value, value]);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const MIN_HUE_DISTANCE = 26;
|
|
88
|
+
function normalizeHue(hue) {
|
|
89
|
+
return (hue % 360 + 360) % 360;
|
|
90
|
+
}
|
|
91
|
+
function hashHue(value) {
|
|
92
|
+
let hash = 2166136261;
|
|
93
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
94
|
+
hash ^= value.charCodeAt(index);
|
|
95
|
+
hash = Math.imul(hash, 16777619);
|
|
96
|
+
}
|
|
97
|
+
return normalizeHue(hash);
|
|
98
|
+
}
|
|
99
|
+
function supportsOklch() {
|
|
100
|
+
return typeof CSS !== "undefined" && CSS.supports?.("color", "oklch(62% 0.14 180)") === true;
|
|
101
|
+
}
|
|
102
|
+
function nodeColor(hue) {
|
|
103
|
+
const normalizedHue = normalizeHue(hue);
|
|
104
|
+
return supportsOklch() ? `oklch(68% 0.13 ${normalizedHue})` : `hsl(${normalizedHue} 42% 62%)`;
|
|
105
|
+
}
|
|
106
|
+
function nodeColorVivid(hue) {
|
|
107
|
+
const normalizedHue = normalizeHue(hue);
|
|
108
|
+
return supportsOklch() ? `oklch(74% 0.18 ${normalizedHue})` : `hsl(${normalizedHue} 55% 68%)`;
|
|
109
|
+
}
|
|
110
|
+
function buildSankeyHueMap(names) {
|
|
111
|
+
const entries = [...new Set(names)].map((name) => ({ name, hue: hashHue(name) })).sort((left, right) => left.hue - right.hue || left.name.localeCompare(right.name));
|
|
112
|
+
for (let pass = 0; pass < 3; pass += 1) {
|
|
113
|
+
for (let iteration = 0; iteration < entries.length * 8; iteration += 1) {
|
|
114
|
+
entries.sort((left, right) => left.hue - right.hue || left.name.localeCompare(right.name));
|
|
115
|
+
let adjusted = false;
|
|
116
|
+
for (let index = 0; index < entries.length; index += 1) {
|
|
117
|
+
const current = entries[index];
|
|
118
|
+
const next = entries[(index + 1) % entries.length];
|
|
119
|
+
if (!current || !next) continue;
|
|
120
|
+
const distance = normalizeHue(next.hue - current.hue);
|
|
121
|
+
if (distance >= MIN_HUE_DISTANCE - Number.EPSILON) continue;
|
|
122
|
+
const adjustment = (MIN_HUE_DISTANCE - distance) / 2;
|
|
123
|
+
current.hue = normalizeHue(current.hue - adjustment);
|
|
124
|
+
next.hue = normalizeHue(next.hue + adjustment);
|
|
125
|
+
adjusted = true;
|
|
126
|
+
}
|
|
127
|
+
if (!adjusted) break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return Object.fromEntries(entries.map(({ name, hue }) => [name, normalizeHue(hue)]));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const SankeyControlsContext = React.createContext(void 0);
|
|
134
|
+
const SankeyRenderContext = React.createContext(void 0);
|
|
135
|
+
function Sankey({
|
|
136
|
+
data,
|
|
137
|
+
columns,
|
|
138
|
+
children,
|
|
139
|
+
columnOrder,
|
|
140
|
+
onColumnOrderChange,
|
|
141
|
+
visibleColumnIds,
|
|
142
|
+
onVisibleColumnIdsChange
|
|
143
|
+
}) {
|
|
144
|
+
const columnIds = columns.map((column) => column.id);
|
|
145
|
+
const [internalOrder, setInternalOrder] = React.useState(columnIds);
|
|
146
|
+
const [internalVisibleIds, setInternalVisibleIds] = React.useState(columnIds);
|
|
147
|
+
const orderedColumns = orderColumns(columns, columnOrder ?? internalOrder);
|
|
148
|
+
const visibleIds = new Set(visibleColumnIds ?? internalVisibleIds);
|
|
149
|
+
const enabledColumns = orderedColumns.filter((column) => visibleIds.has(column.id));
|
|
150
|
+
const graph = buildSankeyChartGraph(data, enabledColumns);
|
|
151
|
+
const hueMap = buildSankeyHueMap(graph.nodes.map((node) => String(node.value)));
|
|
152
|
+
const setVisibleColumns = (nextIds) => {
|
|
153
|
+
if (visibleColumnIds === void 0) setInternalVisibleIds(nextIds);
|
|
154
|
+
onVisibleColumnIdsChange?.(nextIds);
|
|
155
|
+
};
|
|
156
|
+
const setColumnOrder = (nextOrder) => {
|
|
157
|
+
if (columnOrder === void 0) setInternalOrder(nextOrder);
|
|
158
|
+
onColumnOrderChange?.(nextOrder);
|
|
159
|
+
};
|
|
160
|
+
const toggleColumn = (columnId) => {
|
|
161
|
+
const nextIds = visibleIds.has(columnId) ? orderedColumns.filter((column) => visibleIds.has(column.id) && column.id !== columnId).map((column) => column.id) : orderedColumns.filter((column) => visibleIds.has(column.id) || column.id === columnId).map((column) => column.id);
|
|
162
|
+
setVisibleColumns(nextIds);
|
|
163
|
+
};
|
|
164
|
+
const reorderColumns = (sourceIndex, destinationIndex) => {
|
|
165
|
+
const reorderedEnabled = reorderSankeyChartColumns(enabledColumns, sourceIndex, destinationIndex);
|
|
166
|
+
const enabledIterator = reorderedEnabled[Symbol.iterator]();
|
|
167
|
+
const nextColumns = orderedColumns.map(
|
|
168
|
+
(column) => visibleIds.has(column.id) ? enabledIterator.next().value ?? column : column
|
|
169
|
+
);
|
|
170
|
+
setColumnOrder(nextColumns.map((column) => column.id));
|
|
171
|
+
};
|
|
172
|
+
const controlColumns = orderedColumns.map((column) => ({ ...column, visible: visibleIds.has(column.id) }));
|
|
173
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SankeyControlsContext.Provider, { value: { columns: controlColumns, toggleColumn, reorderColumns }, children: /* @__PURE__ */ jsxRuntime.jsx(SankeyRenderContext.Provider, { value: { graph, enabledColumns, hueMap }, children }) });
|
|
174
|
+
}
|
|
175
|
+
function useSankey() {
|
|
176
|
+
const context = React.useContext(SankeyControlsContext);
|
|
177
|
+
if (!context) throw new Error("useSankey must be used within Sankey");
|
|
178
|
+
return context;
|
|
179
|
+
}
|
|
180
|
+
function useSankeyRenderContext() {
|
|
181
|
+
const context = React.useContext(SankeyRenderContext);
|
|
182
|
+
if (!context) throw new Error("SankeyChart must be used within Sankey");
|
|
183
|
+
return context;
|
|
184
|
+
}
|
|
185
|
+
function orderColumns(columns, order) {
|
|
186
|
+
const positions = new Map(order.map((id, index) => [id, index]));
|
|
187
|
+
return [...columns].sort(
|
|
188
|
+
(left, right) => (positions.get(left.id) ?? columns.length) - (positions.get(right.id) ?? columns.length)
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function SankeyChart({ height = 320, className, onCurveClick }) {
|
|
193
|
+
const { graph, enabledColumns, hueMap } = useSankeyRenderContext();
|
|
194
|
+
const [hoveredSourceName, setHoveredSourceName] = React.useState();
|
|
195
|
+
const lastColumnId = enabledColumns.at(-1)?.id;
|
|
196
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: utils_cn.cn("min-w-0", className), children: graph.links.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
197
|
+
"div",
|
|
198
|
+
{
|
|
199
|
+
className: "flex items-center justify-center rounded-md border border-border1 text-ui-sm text-neutral3",
|
|
200
|
+
style: { height },
|
|
201
|
+
children: "Select at least two columns with data to display a flow"
|
|
202
|
+
}
|
|
203
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
204
|
+
recharts.ResponsiveContainer,
|
|
205
|
+
{
|
|
206
|
+
width: "100%",
|
|
207
|
+
height: "100%",
|
|
208
|
+
initialDimension: { width: 800, height: typeof height === "number" ? height : 320 },
|
|
209
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
210
|
+
recharts.Sankey,
|
|
211
|
+
{
|
|
212
|
+
data: graph,
|
|
213
|
+
nodeWidth: 7,
|
|
214
|
+
nodePadding: 18,
|
|
215
|
+
margin: { top: 40, right: 120, bottom: 12, left: 120 },
|
|
216
|
+
node: (props) => {
|
|
217
|
+
const node = graph.nodes[props.index];
|
|
218
|
+
const showColumnLabel = node ? graph.nodes.findIndex((candidate) => candidate.column.id === node.column.id) === props.index : false;
|
|
219
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
220
|
+
SankeyNode,
|
|
221
|
+
{
|
|
222
|
+
...props,
|
|
223
|
+
hueMap,
|
|
224
|
+
columnLabel: node?.column.label,
|
|
225
|
+
showColumnLabel,
|
|
226
|
+
isLastColumn: node?.column.id === lastColumnId,
|
|
227
|
+
onHoverChange: setHoveredSourceName
|
|
228
|
+
}
|
|
229
|
+
);
|
|
230
|
+
},
|
|
231
|
+
link: (props) => {
|
|
232
|
+
const link = graph.links[props.index];
|
|
233
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
234
|
+
SankeyLink,
|
|
235
|
+
{
|
|
236
|
+
...props,
|
|
237
|
+
hueMap,
|
|
238
|
+
highlighted: String(props.payload.source.name ?? "") === hoveredSourceName,
|
|
239
|
+
onHoverChange: setHoveredSourceName,
|
|
240
|
+
clickable: onCurveClick !== void 0,
|
|
241
|
+
onSelect: () => {
|
|
242
|
+
if (link) onCurveClick?.(getSankeyChartCurveSelection(link));
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
)
|
|
249
|
+
}
|
|
250
|
+
) }) });
|
|
251
|
+
}
|
|
252
|
+
function SankeyNode({
|
|
253
|
+
x,
|
|
254
|
+
y,
|
|
255
|
+
width,
|
|
256
|
+
height,
|
|
257
|
+
payload,
|
|
258
|
+
hueMap,
|
|
259
|
+
columnLabel,
|
|
260
|
+
showColumnLabel,
|
|
261
|
+
isLastColumn,
|
|
262
|
+
onHoverChange
|
|
263
|
+
}) {
|
|
264
|
+
const name = typeof payload.name === "string" || typeof payload.name === "number" ? String(payload.name) : "";
|
|
265
|
+
const value = typeof payload.value === "string" || typeof payload.value === "number" ? String(payload.value) : "";
|
|
266
|
+
const labelX = isLastColumn ? x - 8 : x + width + 8;
|
|
267
|
+
const textAnchor = isLastColumn ? "end" : "start";
|
|
268
|
+
const hue = hueMap[name] ?? 0;
|
|
269
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("g", { onMouseEnter: () => onHoverChange(name), onMouseLeave: () => onHoverChange(void 0), children: [
|
|
270
|
+
showColumnLabel && columnLabel ? /* @__PURE__ */ jsxRuntime.jsx("text", { x: x + width / 2, y: 18, textAnchor: "middle", fill: spacings.Colors.neutral5, fontSize: 12, fontWeight: 600, children: columnLabel }) : null,
|
|
271
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x, y, width, height, rx: 3, fill: nodeColor(hue) }),
|
|
272
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
273
|
+
"text",
|
|
274
|
+
{
|
|
275
|
+
x: labelX,
|
|
276
|
+
y: y + height / 2 - 4,
|
|
277
|
+
textAnchor,
|
|
278
|
+
fill: spacings.Colors.neutral5,
|
|
279
|
+
fontSize: 12.5,
|
|
280
|
+
fontFamily: "var(--font-mono)",
|
|
281
|
+
paintOrder: "stroke",
|
|
282
|
+
stroke: spacings.Colors.surface1,
|
|
283
|
+
strokeWidth: 3,
|
|
284
|
+
strokeLinejoin: "round",
|
|
285
|
+
children: name
|
|
286
|
+
}
|
|
287
|
+
),
|
|
288
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { x: labelX, y: y + height / 2 + 10, textAnchor, fill: spacings.Colors.neutral3, fontSize: 10.5, children: value })
|
|
289
|
+
] });
|
|
290
|
+
}
|
|
291
|
+
function SankeyLink({
|
|
292
|
+
sourceX,
|
|
293
|
+
targetX,
|
|
294
|
+
sourceY,
|
|
295
|
+
targetY,
|
|
296
|
+
sourceControlX,
|
|
297
|
+
targetControlX,
|
|
298
|
+
linkWidth,
|
|
299
|
+
index,
|
|
300
|
+
payload,
|
|
301
|
+
hueMap,
|
|
302
|
+
highlighted,
|
|
303
|
+
clickable,
|
|
304
|
+
onHoverChange,
|
|
305
|
+
onSelect
|
|
306
|
+
}) {
|
|
307
|
+
const halfWidth = Math.max(0, linkWidth) / 2;
|
|
308
|
+
const path = [
|
|
309
|
+
`M${sourceX},${sourceY - halfWidth}`,
|
|
310
|
+
`C${sourceControlX},${sourceY - halfWidth} ${targetControlX},${targetY - halfWidth} ${targetX},${targetY - halfWidth}`,
|
|
311
|
+
`L${targetX},${targetY + halfWidth}`,
|
|
312
|
+
`C${targetControlX},${targetY + halfWidth} ${sourceControlX},${sourceY + halfWidth} ${sourceX},${sourceY + halfWidth}`,
|
|
313
|
+
"Z"
|
|
314
|
+
].join(" ");
|
|
315
|
+
const sourceName = String(payload.source.name ?? "");
|
|
316
|
+
const targetName = String(payload.target.name ?? "");
|
|
317
|
+
const gradientId = `sankey-grad-${index}`;
|
|
318
|
+
const vividGradientId = `${gradientId}-vivid`;
|
|
319
|
+
const handleKeyDown = (event) => {
|
|
320
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
321
|
+
event.preventDefault();
|
|
322
|
+
onSelect();
|
|
323
|
+
};
|
|
324
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
|
|
325
|
+
/* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
|
|
326
|
+
/* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: gradientId, gradientUnits: "userSpaceOnUse", x1: sourceX, x2: targetX, children: [
|
|
327
|
+
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: nodeColor(hueMap[sourceName] ?? 0) }),
|
|
328
|
+
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: nodeColor(hueMap[targetName] ?? 0) })
|
|
329
|
+
] }),
|
|
330
|
+
/* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: vividGradientId, gradientUnits: "userSpaceOnUse", x1: sourceX, x2: targetX, children: [
|
|
331
|
+
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: nodeColorVivid(hueMap[sourceName] ?? 0) }),
|
|
332
|
+
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: nodeColorVivid(hueMap[targetName] ?? 0) })
|
|
333
|
+
] })
|
|
334
|
+
] }),
|
|
335
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
336
|
+
"path",
|
|
337
|
+
{
|
|
338
|
+
d: path,
|
|
339
|
+
fill: `url(#${highlighted ? vividGradientId : gradientId})`,
|
|
340
|
+
fillOpacity: highlighted ? 0.75 : 0.32,
|
|
341
|
+
stroke: "none",
|
|
342
|
+
role: clickable ? "button" : void 0,
|
|
343
|
+
tabIndex: clickable ? 0 : void 0,
|
|
344
|
+
"aria-label": clickable ? "Select Sankey curve" : void 0,
|
|
345
|
+
onClick: clickable ? onSelect : void 0,
|
|
346
|
+
onKeyDown: clickable ? handleKeyDown : void 0,
|
|
347
|
+
onMouseEnter: () => onHoverChange(sourceName),
|
|
348
|
+
onMouseLeave: () => onHoverChange(void 0),
|
|
349
|
+
style: { cursor: clickable ? "pointer" : void 0, transition: "fill-opacity 0.18s ease" }
|
|
350
|
+
}
|
|
351
|
+
)
|
|
352
|
+
] });
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
exports.Sankey = Sankey;
|
|
356
|
+
exports.SankeyChart = SankeyChart;
|
|
357
|
+
exports.buildSankeyChartGraph = buildSankeyChartGraph;
|
|
358
|
+
exports.getSankeyChartCurveSelection = getSankeyChartCurveSelection;
|
|
359
|
+
exports.getSankeyChartValue = getSankeyChartValue;
|
|
360
|
+
exports.reorderSankeyChartColumns = reorderSankeyChartColumns;
|
|
361
|
+
exports.useSankey = useSankey;
|
|
362
|
+
//# sourceMappingURL=SankeyChart.cjs.js.map
|