klun-ui 0.1.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/LICENSE +21 -0
- package/README.md +106 -0
- package/dist/charts/index.cjs +160 -0
- package/dist/charts/index.cjs.map +1 -0
- package/dist/charts/index.d.cts +89 -0
- package/dist/charts/index.d.ts +89 -0
- package/dist/charts/index.js +154 -0
- package/dist/charts/index.js.map +1 -0
- package/dist/chunk-FTYQRXS5.cjs +10152 -0
- package/dist/chunk-FTYQRXS5.cjs.map +1 -0
- package/dist/chunk-T225J6LV.js +13 -0
- package/dist/chunk-T225J6LV.js.map +1 -0
- package/dist/chunk-TPGAXYFU.cjs +15 -0
- package/dist/chunk-TPGAXYFU.cjs.map +1 -0
- package/dist/chunk-XDAR7UMF.js +10009 -0
- package/dist/chunk-XDAR7UMF.js.map +1 -0
- package/dist/fonts/DMMono-Light.ttf +0 -0
- package/dist/fonts/DMMono-Medium.ttf +0 -0
- package/dist/fonts/DMMono-Regular.ttf +0 -0
- package/dist/fonts/InterDisplay-Bold.woff2 +0 -0
- package/dist/fonts/InterDisplay-Medium.woff2 +0 -0
- package/dist/fonts/InterDisplay-Regular.woff2 +0 -0
- package/dist/fonts/InterDisplay-SemiBold.woff2 +0 -0
- package/dist/fonts/InterVariable-Italic.woff2 +0 -0
- package/dist/fonts/InterVariable.woff2 +0 -0
- package/dist/index.cjs +581 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2701 -0
- package/dist/index.d.ts +2701 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +9137 -0
- package/dist/templates/index.cjs +1132 -0
- package/dist/templates/index.cjs.map +1 -0
- package/dist/templates/index.d.cts +43 -0
- package/dist/templates/index.d.ts +43 -0
- package/dist/templates/index.js +1120 -0
- package/dist/templates/index.js.map +1 -0
- package/package.json +95 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 klun-ui contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# klun-ui
|
|
2
|
+
|
|
3
|
+
A themeable **React + TypeScript** component library and design system — 84 components, light/dark modes, and five accent themes, all driven by a deep `--klun-*` CSS design-token layer.
|
|
4
|
+
|
|
5
|
+
- **Standard architecture** — every component is a thin `forwardRef` wrapper that maps props to CSS classes (`className` and `style` pass through, `displayName` set). Styling lives in one stylesheet driven by design tokens, so real `:hover` / `:focus-visible` / `:disabled` states work and consumers can override with their own CSS.
|
|
6
|
+
- **Dual ESM + CJS** with bundled type declarations.
|
|
7
|
+
- **No styling runtime** — import one stylesheet once; the JS is fully tree-shakeable.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm add klun-ui react react-dom
|
|
13
|
+
# npm i klun-ui react react-dom / yarn add klun-ui react react-dom
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
`react` and `react-dom` (>=18) are peer dependencies.
|
|
17
|
+
|
|
18
|
+
## Quick start
|
|
19
|
+
|
|
20
|
+
Import the stylesheet **once** at your app root, then use components:
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import "klun-ui/styles.css";
|
|
24
|
+
import { Button, Card, Badge, Input } from "klun-ui";
|
|
25
|
+
|
|
26
|
+
export function Example() {
|
|
27
|
+
return (
|
|
28
|
+
<Card variant="shadow">
|
|
29
|
+
<Badge color="green">Active</Badge>
|
|
30
|
+
<Input placeholder="Email" />
|
|
31
|
+
<Button variant="primary" appearance="filled" size="medium">
|
|
32
|
+
Save changes
|
|
33
|
+
</Button>
|
|
34
|
+
</Card>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Icons
|
|
40
|
+
|
|
41
|
+
Components accept icons as React nodes. The design system uses [Remix Icon](https://remixicon.com):
|
|
42
|
+
|
|
43
|
+
```html
|
|
44
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/remixicon@4.5.0/fonts/remixicon.css" />
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
<Button leadingIcon={<i className="ri-add-line" />}>Add item</Button>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Theming
|
|
52
|
+
|
|
53
|
+
`data-theme` (light/dark) and `data-mode` (accent + neutral ramp) compose on any ancestor — usually `<html>`. Components reference only semantic tokens, so they re-theme automatically.
|
|
54
|
+
|
|
55
|
+
```html
|
|
56
|
+
<html data-theme="dark"> <!-- dark mode -->
|
|
57
|
+
<html data-mode="purple"> <!-- purple accent (also: orange, green) -->
|
|
58
|
+
<html data-mode="slate"> <!-- cooler neutral ramp -->
|
|
59
|
+
<html data-theme="dark" data-mode="green"><!-- compose both -->
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
You can also override tokens directly:
|
|
63
|
+
|
|
64
|
+
```css
|
|
65
|
+
:root { --klun-primary-base: #7d52f4; }
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Components
|
|
69
|
+
|
|
70
|
+
| Group | Components |
|
|
71
|
+
|---|---|
|
|
72
|
+
| **Buttons** | Button, IconButton, CompactButton, LinkButton, ButtonGroup, FancyButton |
|
|
73
|
+
| **Forms** | Input, Textarea, Select, Checkbox, Radio, Switch, Slider, Label, Hint, DigitInput, FileUpload, ImageUpload, ColorPicker, ColorDot, ColorSlider, DatePicker, DateRangePicker, TimePicker, RichEditorToolbar, CharacterCounter, CheckboxCard, CompactSelect, CompactSelectForInput, InlineInput, InlineSelect, SelectMenu, CounterInput, PasswordStrength |
|
|
74
|
+
| **Data display** | Avatar, AvatarGroup, CompactAvatarGroup, Badge, Chip, Tag, ContentLabel, Tooltip, Table, Rating, Kbd, KeyIcon, PaymentIcon, StatCard, FileFormatIcon, ChatBubble, ChartLegend, ChartTooltip, IntegrationSwitch, PeriodRange |
|
|
75
|
+
| **Feedback** | Alert, Banner, InlineTip, Toast, NotificationItem, ProgressBar, GaugeBar, CircularProgress, SegmentedProgress, Spinner, Skeleton, EmptyState |
|
|
76
|
+
| **Navigation** | Tabs, SegmentedControl, Breadcrumb, Pagination, StepIndicator, Divider, ContentDivider, HorizontalFilter, PageHeader |
|
|
77
|
+
| **Overlays** | Modal, Drawer, Dropdown, Popover, CommandMenu |
|
|
78
|
+
| **Disclosure** | Accordion |
|
|
79
|
+
| **Layout** | Card, ContentCard, FeatureCard |
|
|
80
|
+
|
|
81
|
+
All components and their prop types are named exports; a `cx` classnames helper is exported too.
|
|
82
|
+
|
|
83
|
+
## Templates
|
|
84
|
+
|
|
85
|
+
Full-screen example compositions are available from the `klun-ui/templates` subpath — copy-and-go starting points built entirely from klun-ui components:
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
import "klun-ui/styles.css";
|
|
89
|
+
import { DashboardTemplate, AIAssistantTemplate, CryptoTemplate, MarketingTemplate } from "klun-ui/templates";
|
|
90
|
+
|
|
91
|
+
export default function App() {
|
|
92
|
+
return <DashboardTemplate />;
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## TypeScript
|
|
97
|
+
|
|
98
|
+
Types ship with the package. Every component exports its `*Props` interface:
|
|
99
|
+
|
|
100
|
+
```tsx
|
|
101
|
+
import type { ButtonProps, BadgeColor } from "klun-ui";
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
MIT
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkTPGAXYFU_cjs = require('../chunk-TPGAXYFU.cjs');
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var recharts = require('recharts');
|
|
6
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
+
|
|
8
|
+
var CHART_INTENT = {
|
|
9
|
+
primary: "var(--klun-primary-base)",
|
|
10
|
+
success: "var(--klun-state-success-base)",
|
|
11
|
+
danger: "var(--klun-state-error-base)",
|
|
12
|
+
warning: "var(--klun-state-warning-base)",
|
|
13
|
+
info: "var(--klun-state-information-base)"
|
|
14
|
+
};
|
|
15
|
+
var CHART_TOOLTIP_STYLE = {
|
|
16
|
+
background: "var(--klun-bg-white-0)",
|
|
17
|
+
border: "1px solid var(--klun-stroke-soft-200)",
|
|
18
|
+
borderRadius: "8px",
|
|
19
|
+
padding: "6px 10px",
|
|
20
|
+
fontSize: "12px",
|
|
21
|
+
color: "var(--klun-text-strong-950)"
|
|
22
|
+
};
|
|
23
|
+
var AreaChart = react.forwardRef(function AreaChart2({ data = [], width = 320, height = 96, color = "primary", fill = true, strokeWidth = 2, padding = 6, className, style }, ref) {
|
|
24
|
+
const gid = "klun-area-" + react.useId().replace(/:/g, "");
|
|
25
|
+
const stroke = CHART_INTENT[color] ?? CHART_INTENT.primary;
|
|
26
|
+
const series = data.map((v, i) => ({ i, v }));
|
|
27
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: chunkTPGAXYFU_cjs.cx("klun-area-chart", className), style: { width, height, ...style }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.AreaChart, { data: series, margin: { top: padding, right: padding, bottom: padding, left: padding }, children: [
|
|
28
|
+
/* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: gid, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
29
|
+
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: stroke, stopOpacity: 0.24 }),
|
|
30
|
+
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: stroke, stopOpacity: 0 })
|
|
31
|
+
] }) }),
|
|
32
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
33
|
+
recharts.Area,
|
|
34
|
+
{
|
|
35
|
+
type: "monotone",
|
|
36
|
+
dataKey: "v",
|
|
37
|
+
stroke,
|
|
38
|
+
strokeWidth,
|
|
39
|
+
strokeLinecap: "round",
|
|
40
|
+
fill: fill ? `url(#${gid})` : "none",
|
|
41
|
+
fillOpacity: 1,
|
|
42
|
+
dot: false,
|
|
43
|
+
isAnimationActive: false
|
|
44
|
+
}
|
|
45
|
+
)
|
|
46
|
+
] }) }) });
|
|
47
|
+
});
|
|
48
|
+
AreaChart.displayName = "AreaChart";
|
|
49
|
+
var BarChart = react.forwardRef(function BarChart2({ data = [], height = 140, color = "primary", gap = 8, showValues = false, className, style }, ref) {
|
|
50
|
+
const fill = CHART_INTENT[color] ?? CHART_INTENT.primary;
|
|
51
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: chunkTPGAXYFU_cjs.cx("klun-bar-chart", className), style: { width: "100%", height, ...style }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.BarChart, { data, margin: { top: showValues ? 18 : 6, right: 6, bottom: 0, left: 6 }, barCategoryGap: gap, children: [
|
|
52
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
53
|
+
recharts.XAxis,
|
|
54
|
+
{
|
|
55
|
+
dataKey: "label",
|
|
56
|
+
tickLine: false,
|
|
57
|
+
axisLine: false,
|
|
58
|
+
tick: { fontSize: 11, fill: "var(--klun-text-sub-600)" }
|
|
59
|
+
}
|
|
60
|
+
),
|
|
61
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { cursor: { fill: "var(--klun-bg-weak-50)" }, contentStyle: CHART_TOOLTIP_STYLE }),
|
|
62
|
+
/* @__PURE__ */ jsxRuntime.jsxs(recharts.Bar, { dataKey: "value", fill, radius: [4, 4, 0, 0], isAnimationActive: false, children: [
|
|
63
|
+
showValues ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
64
|
+
recharts.LabelList,
|
|
65
|
+
{
|
|
66
|
+
dataKey: "value",
|
|
67
|
+
position: "top",
|
|
68
|
+
style: { fontSize: 11, fontWeight: 600, fill: "var(--klun-text-sub-600)" }
|
|
69
|
+
}
|
|
70
|
+
) : null,
|
|
71
|
+
data.map((d, i) => /* @__PURE__ */ jsxRuntime.jsx(recharts.Cell, { fill: d.color || fill }, i))
|
|
72
|
+
] })
|
|
73
|
+
] }) }) });
|
|
74
|
+
});
|
|
75
|
+
BarChart.displayName = "BarChart";
|
|
76
|
+
var PALETTE = [
|
|
77
|
+
"var(--klun-primary-base)",
|
|
78
|
+
"var(--klun-state-success-base)",
|
|
79
|
+
"var(--klun-state-warning-base)",
|
|
80
|
+
"var(--klun-state-error-base)",
|
|
81
|
+
"var(--klun-state-information-base)",
|
|
82
|
+
"var(--klun-icon-disabled-300)"
|
|
83
|
+
];
|
|
84
|
+
var Donut = react.forwardRef(function Donut2({ data = [], size = 160, thickness = 22, centerLabel, centerValue, className, style }, ref) {
|
|
85
|
+
const total = data.reduce((s, d) => s + (d.value || 0), 0) || 1;
|
|
86
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
87
|
+
"div",
|
|
88
|
+
{
|
|
89
|
+
ref,
|
|
90
|
+
className: chunkTPGAXYFU_cjs.cx("klun-donut", className),
|
|
91
|
+
style: { display: "inline-flex", alignItems: "center", gap: 18, ...style },
|
|
92
|
+
children: [
|
|
93
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", width: size, height: size, flexShrink: 0 }, children: [
|
|
94
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.PieChart, { width: size, height: size, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
95
|
+
recharts.Pie,
|
|
96
|
+
{
|
|
97
|
+
data,
|
|
98
|
+
dataKey: "value",
|
|
99
|
+
cx: "50%",
|
|
100
|
+
cy: "50%",
|
|
101
|
+
innerRadius: size / 2 - thickness,
|
|
102
|
+
outerRadius: size / 2,
|
|
103
|
+
startAngle: 90,
|
|
104
|
+
endAngle: -270,
|
|
105
|
+
stroke: "none",
|
|
106
|
+
isAnimationActive: false,
|
|
107
|
+
children: data.map((d, i) => /* @__PURE__ */ jsxRuntime.jsx(recharts.Cell, { fill: d.color || PALETTE[i % PALETTE.length] }, i))
|
|
108
|
+
}
|
|
109
|
+
) }),
|
|
110
|
+
centerLabel || centerValue ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
111
|
+
"div",
|
|
112
|
+
{
|
|
113
|
+
style: {
|
|
114
|
+
position: "absolute",
|
|
115
|
+
inset: 0,
|
|
116
|
+
display: "flex",
|
|
117
|
+
flexDirection: "column",
|
|
118
|
+
alignItems: "center",
|
|
119
|
+
justifyContent: "center",
|
|
120
|
+
pointerEvents: "none"
|
|
121
|
+
},
|
|
122
|
+
children: [
|
|
123
|
+
centerValue ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 22, fontWeight: 700, color: "var(--klun-text-strong-950)" }, children: centerValue }) : null,
|
|
124
|
+
centerLabel ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 11, color: "var(--klun-text-sub-600)" }, children: centerLabel }) : null
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
) : null
|
|
128
|
+
] }),
|
|
129
|
+
data.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: data.map((d, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, fontSize: 12 }, children: [
|
|
130
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
131
|
+
"span",
|
|
132
|
+
{
|
|
133
|
+
style: {
|
|
134
|
+
width: 10,
|
|
135
|
+
height: 10,
|
|
136
|
+
borderRadius: 3,
|
|
137
|
+
background: d.color || PALETTE[i % PALETTE.length],
|
|
138
|
+
flexShrink: 0
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
),
|
|
142
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--klun-text-sub-600)" }, children: d.label }),
|
|
143
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: { marginLeft: "auto", fontWeight: 600, color: "var(--klun-text-strong-950)" }, children: [
|
|
144
|
+
Math.round((d.value || 0) / total * 100),
|
|
145
|
+
"%"
|
|
146
|
+
] })
|
|
147
|
+
] }, i)) }) : null
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
);
|
|
151
|
+
});
|
|
152
|
+
Donut.displayName = "Donut";
|
|
153
|
+
|
|
154
|
+
exports.AreaChart = AreaChart;
|
|
155
|
+
exports.BarChart = BarChart;
|
|
156
|
+
exports.CHART_INTENT = CHART_INTENT;
|
|
157
|
+
exports.CHART_TOOLTIP_STYLE = CHART_TOOLTIP_STYLE;
|
|
158
|
+
exports.Donut = Donut;
|
|
159
|
+
//# sourceMappingURL=index.cjs.map
|
|
160
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/charts/AreaChart.tsx","../../src/charts/BarChart.tsx","../../src/charts/Donut.tsx"],"names":["forwardRef","AreaChart","useId","jsx","cx","ResponsiveContainer","jsxs","RAreaChart","Area","BarChart","RBarChart","XAxis","Tooltip","Bar","LabelList","Cell","Donut","PieChart","Pie"],"mappings":"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","file":"index.cjs","sourcesContent":["import { forwardRef, useId, type CSSProperties } from \"react\";\nimport { Area, AreaChart as RAreaChart, ResponsiveContainer } from \"recharts\";\nimport { cx } from \"../utils/cx\";\n\n/** Chart color intent — resolves to a klun state token, so charts follow the\n * active theme (including the Metronic skin) automatically. */\nexport type ChartIntent = \"primary\" | \"success\" | \"danger\" | \"warning\" | \"info\";\n\nexport const CHART_INTENT: Record<ChartIntent, string> = {\n primary: \"var(--klun-primary-base)\",\n success: \"var(--klun-state-success-base)\",\n danger: \"var(--klun-state-error-base)\",\n warning: \"var(--klun-state-warning-base)\",\n info: \"var(--klun-state-information-base)\",\n};\n\n/** Shared klun-token styling for recharts tooltips. */\nexport const CHART_TOOLTIP_STYLE: CSSProperties = {\n background: \"var(--klun-bg-white-0)\",\n border: \"1px solid var(--klun-stroke-soft-200)\",\n borderRadius: \"8px\",\n padding: \"6px 10px\",\n fontSize: \"12px\",\n color: \"var(--klun-text-strong-950)\",\n};\n\nexport interface AreaChartProps {\n /** A single numeric series. */\n data?: number[];\n /** Fixed pixel width. Default `320`. */\n width?: number;\n /** Fixed pixel height. Default `96`. */\n height?: number;\n /** Color intent. Default `\"primary\"`. */\n color?: ChartIntent;\n /** Render the gradient area fill under the line. Default `true`. */\n fill?: boolean;\n /** Line width. Default `2`. */\n strokeWidth?: number;\n /** Outer padding (recharts margin). Default `6`. */\n padding?: number;\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * AreaChart — smoothed single-series area / sparkline, built on recharts. Pass\n * `data` as an array of numbers. Colors resolve from klun tokens so the chart\n * follows the active theme. Requires the `recharts` peer dependency.\n */\nexport const AreaChart = forwardRef<HTMLDivElement, AreaChartProps>(function AreaChart(\n { data = [], width = 320, height = 96, color = \"primary\", fill = true, strokeWidth = 2, padding = 6, className, style },\n ref,\n) {\n const gid = \"klun-area-\" + useId().replace(/:/g, \"\");\n const stroke = CHART_INTENT[color] ?? CHART_INTENT.primary;\n const series = data.map((v, i) => ({ i, v }));\n\n return (\n <div ref={ref} className={cx(\"klun-area-chart\", className)} style={{ width, height, ...style }}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <RAreaChart data={series} margin={{ top: padding, right: padding, bottom: padding, left: padding }}>\n <defs>\n <linearGradient id={gid} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={stroke} stopOpacity={0.24} />\n <stop offset=\"100%\" stopColor={stroke} stopOpacity={0} />\n </linearGradient>\n </defs>\n <Area\n type=\"monotone\"\n dataKey=\"v\"\n stroke={stroke}\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n fill={fill ? `url(#${gid})` : \"none\"}\n fillOpacity={1}\n dot={false}\n isAnimationActive={false}\n />\n </RAreaChart>\n </ResponsiveContainer>\n </div>\n );\n});\n\nAreaChart.displayName = \"AreaChart\";\n","import { forwardRef, type CSSProperties, type ReactNode } from \"react\";\nimport { Bar, BarChart as RBarChart, Cell, LabelList, ResponsiveContainer, Tooltip, XAxis } from \"recharts\";\nimport { cx } from \"../utils/cx\";\nimport { CHART_INTENT, CHART_TOOLTIP_STYLE, type ChartIntent } from \"./AreaChart\";\n\nexport interface BarDatum {\n label?: ReactNode;\n value: number;\n /** Per-bar color override (any CSS color or `var(--klun-*)`). */\n color?: string;\n}\n\nexport interface BarChartProps {\n /** Single series of labelled bars. */\n data?: BarDatum[];\n /** Fixed pixel height. Default `140`. Width fills the container. */\n height?: number;\n /** Color intent for the bars. Default `\"primary\"`. */\n color?: ChartIntent;\n /** Category gap between bars. Default `8`. */\n gap?: number;\n /** Render the numeric value above each bar. Default `false`. */\n showValues?: boolean;\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * BarChart — single-series vertical bars, built on recharts. Colors resolve from\n * klun tokens so the chart follows the active theme. Requires the `recharts`\n * peer dependency.\n */\nexport const BarChart = forwardRef<HTMLDivElement, BarChartProps>(function BarChart(\n { data = [], height = 140, color = \"primary\", gap = 8, showValues = false, className, style },\n ref,\n) {\n const fill = CHART_INTENT[color] ?? CHART_INTENT.primary;\n return (\n <div ref={ref} className={cx(\"klun-bar-chart\", className)} style={{ width: \"100%\", height, ...style }}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <RBarChart data={data} margin={{ top: showValues ? 18 : 6, right: 6, bottom: 0, left: 6 }} barCategoryGap={gap}>\n <XAxis\n dataKey=\"label\"\n tickLine={false}\n axisLine={false}\n tick={{ fontSize: 11, fill: \"var(--klun-text-sub-600)\" }}\n />\n <Tooltip cursor={{ fill: \"var(--klun-bg-weak-50)\" }} contentStyle={CHART_TOOLTIP_STYLE} />\n <Bar dataKey=\"value\" fill={fill} radius={[4, 4, 0, 0]} isAnimationActive={false}>\n {showValues ? (\n <LabelList\n dataKey=\"value\"\n position=\"top\"\n style={{ fontSize: 11, fontWeight: 600, fill: \"var(--klun-text-sub-600)\" }}\n />\n ) : null}\n {data.map((d, i) => (\n <Cell key={i} fill={d.color || fill} />\n ))}\n </Bar>\n </RBarChart>\n </ResponsiveContainer>\n </div>\n );\n});\n\nBarChart.displayName = \"BarChart\";\n","import { forwardRef, type CSSProperties, type ReactNode } from \"react\";\nimport { Cell, Pie, PieChart } from \"recharts\";\nimport { cx } from \"../utils/cx\";\n\n/** Default donut palette — klun state tokens, so segments follow the theme. */\nconst PALETTE = [\n \"var(--klun-primary-base)\",\n \"var(--klun-state-success-base)\",\n \"var(--klun-state-warning-base)\",\n \"var(--klun-state-error-base)\",\n \"var(--klun-state-information-base)\",\n \"var(--klun-icon-disabled-300)\",\n];\n\nexport interface DonutDatum {\n label?: ReactNode;\n value: number;\n /** Per-segment color override (any CSS color or `var(--klun-*)`). */\n color?: string;\n}\n\nexport interface DonutProps {\n /** Segments. */\n data?: DonutDatum[];\n /** Outer diameter in px. Default `160`. */\n size?: number;\n /** Ring thickness in px. Default `22`. */\n thickness?: number;\n /** Small caption under the center value. */\n centerLabel?: ReactNode;\n /** Large value in the center. */\n centerValue?: ReactNode;\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * Donut — donut / pie chart with an optional center label and a percentage\n * legend, built on recharts. Colors resolve from klun tokens so the chart\n * follows the active theme. Requires the `recharts` peer dependency.\n */\nexport const Donut = forwardRef<HTMLDivElement, DonutProps>(function Donut(\n { data = [], size = 160, thickness = 22, centerLabel, centerValue, className, style },\n ref,\n) {\n const total = data.reduce((s, d) => s + (d.value || 0), 0) || 1;\n return (\n <div\n ref={ref}\n className={cx(\"klun-donut\", className)}\n style={{ display: \"inline-flex\", alignItems: \"center\", gap: 18, ...style }}\n >\n <div style={{ position: \"relative\", width: size, height: size, flexShrink: 0 }}>\n <PieChart width={size} height={size}>\n <Pie\n data={data}\n dataKey=\"value\"\n cx=\"50%\"\n cy=\"50%\"\n innerRadius={size / 2 - thickness}\n outerRadius={size / 2}\n startAngle={90}\n endAngle={-270}\n stroke=\"none\"\n isAnimationActive={false}\n >\n {data.map((d, i) => (\n <Cell key={i} fill={d.color || PALETTE[i % PALETTE.length]} />\n ))}\n </Pie>\n </PieChart>\n {centerLabel || centerValue ? (\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n pointerEvents: \"none\",\n }}\n >\n {centerValue ? (\n <span style={{ fontSize: 22, fontWeight: 700, color: \"var(--klun-text-strong-950)\" }}>{centerValue}</span>\n ) : null}\n {centerLabel ? (\n <span style={{ fontSize: 11, color: \"var(--klun-text-sub-600)\" }}>{centerLabel}</span>\n ) : null}\n </div>\n ) : null}\n </div>\n {data.length > 0 ? (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n {data.map((d, i) => (\n <div key={i} style={{ display: \"flex\", alignItems: \"center\", gap: 8, fontSize: 12 }}>\n <span\n style={{\n width: 10,\n height: 10,\n borderRadius: 3,\n background: d.color || PALETTE[i % PALETTE.length],\n flexShrink: 0,\n }}\n />\n <span style={{ color: \"var(--klun-text-sub-600)\" }}>{d.label}</span>\n <span style={{ marginLeft: \"auto\", fontWeight: 600, color: \"var(--klun-text-strong-950)\" }}>\n {Math.round(((d.value || 0) / total) * 100)}%\n </span>\n </div>\n ))}\n </div>\n ) : null}\n </div>\n );\n});\n\nDonut.displayName = \"Donut\";\n"]}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { CSSProperties, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/** Chart color intent — resolves to a klun state token, so charts follow the
|
|
5
|
+
* active theme (including the Metronic skin) automatically. */
|
|
6
|
+
type ChartIntent = "primary" | "success" | "danger" | "warning" | "info";
|
|
7
|
+
declare const CHART_INTENT: Record<ChartIntent, string>;
|
|
8
|
+
/** Shared klun-token styling for recharts tooltips. */
|
|
9
|
+
declare const CHART_TOOLTIP_STYLE: CSSProperties;
|
|
10
|
+
interface AreaChartProps {
|
|
11
|
+
/** A single numeric series. */
|
|
12
|
+
data?: number[];
|
|
13
|
+
/** Fixed pixel width. Default `320`. */
|
|
14
|
+
width?: number;
|
|
15
|
+
/** Fixed pixel height. Default `96`. */
|
|
16
|
+
height?: number;
|
|
17
|
+
/** Color intent. Default `"primary"`. */
|
|
18
|
+
color?: ChartIntent;
|
|
19
|
+
/** Render the gradient area fill under the line. Default `true`. */
|
|
20
|
+
fill?: boolean;
|
|
21
|
+
/** Line width. Default `2`. */
|
|
22
|
+
strokeWidth?: number;
|
|
23
|
+
/** Outer padding (recharts margin). Default `6`. */
|
|
24
|
+
padding?: number;
|
|
25
|
+
className?: string;
|
|
26
|
+
style?: CSSProperties;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* AreaChart — smoothed single-series area / sparkline, built on recharts. Pass
|
|
30
|
+
* `data` as an array of numbers. Colors resolve from klun tokens so the chart
|
|
31
|
+
* follows the active theme. Requires the `recharts` peer dependency.
|
|
32
|
+
*/
|
|
33
|
+
declare const AreaChart: react.ForwardRefExoticComponent<AreaChartProps & react.RefAttributes<HTMLDivElement>>;
|
|
34
|
+
|
|
35
|
+
interface BarDatum {
|
|
36
|
+
label?: ReactNode;
|
|
37
|
+
value: number;
|
|
38
|
+
/** Per-bar color override (any CSS color or `var(--klun-*)`). */
|
|
39
|
+
color?: string;
|
|
40
|
+
}
|
|
41
|
+
interface BarChartProps {
|
|
42
|
+
/** Single series of labelled bars. */
|
|
43
|
+
data?: BarDatum[];
|
|
44
|
+
/** Fixed pixel height. Default `140`. Width fills the container. */
|
|
45
|
+
height?: number;
|
|
46
|
+
/** Color intent for the bars. Default `"primary"`. */
|
|
47
|
+
color?: ChartIntent;
|
|
48
|
+
/** Category gap between bars. Default `8`. */
|
|
49
|
+
gap?: number;
|
|
50
|
+
/** Render the numeric value above each bar. Default `false`. */
|
|
51
|
+
showValues?: boolean;
|
|
52
|
+
className?: string;
|
|
53
|
+
style?: CSSProperties;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* BarChart — single-series vertical bars, built on recharts. Colors resolve from
|
|
57
|
+
* klun tokens so the chart follows the active theme. Requires the `recharts`
|
|
58
|
+
* peer dependency.
|
|
59
|
+
*/
|
|
60
|
+
declare const BarChart: react.ForwardRefExoticComponent<BarChartProps & react.RefAttributes<HTMLDivElement>>;
|
|
61
|
+
|
|
62
|
+
interface DonutDatum {
|
|
63
|
+
label?: ReactNode;
|
|
64
|
+
value: number;
|
|
65
|
+
/** Per-segment color override (any CSS color or `var(--klun-*)`). */
|
|
66
|
+
color?: string;
|
|
67
|
+
}
|
|
68
|
+
interface DonutProps {
|
|
69
|
+
/** Segments. */
|
|
70
|
+
data?: DonutDatum[];
|
|
71
|
+
/** Outer diameter in px. Default `160`. */
|
|
72
|
+
size?: number;
|
|
73
|
+
/** Ring thickness in px. Default `22`. */
|
|
74
|
+
thickness?: number;
|
|
75
|
+
/** Small caption under the center value. */
|
|
76
|
+
centerLabel?: ReactNode;
|
|
77
|
+
/** Large value in the center. */
|
|
78
|
+
centerValue?: ReactNode;
|
|
79
|
+
className?: string;
|
|
80
|
+
style?: CSSProperties;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Donut — donut / pie chart with an optional center label and a percentage
|
|
84
|
+
* legend, built on recharts. Colors resolve from klun tokens so the chart
|
|
85
|
+
* follows the active theme. Requires the `recharts` peer dependency.
|
|
86
|
+
*/
|
|
87
|
+
declare const Donut: react.ForwardRefExoticComponent<DonutProps & react.RefAttributes<HTMLDivElement>>;
|
|
88
|
+
|
|
89
|
+
export { AreaChart, type AreaChartProps, BarChart, type BarChartProps, type BarDatum, CHART_INTENT, CHART_TOOLTIP_STYLE, type ChartIntent, Donut, type DonutDatum, type DonutProps };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { CSSProperties, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/** Chart color intent — resolves to a klun state token, so charts follow the
|
|
5
|
+
* active theme (including the Metronic skin) automatically. */
|
|
6
|
+
type ChartIntent = "primary" | "success" | "danger" | "warning" | "info";
|
|
7
|
+
declare const CHART_INTENT: Record<ChartIntent, string>;
|
|
8
|
+
/** Shared klun-token styling for recharts tooltips. */
|
|
9
|
+
declare const CHART_TOOLTIP_STYLE: CSSProperties;
|
|
10
|
+
interface AreaChartProps {
|
|
11
|
+
/** A single numeric series. */
|
|
12
|
+
data?: number[];
|
|
13
|
+
/** Fixed pixel width. Default `320`. */
|
|
14
|
+
width?: number;
|
|
15
|
+
/** Fixed pixel height. Default `96`. */
|
|
16
|
+
height?: number;
|
|
17
|
+
/** Color intent. Default `"primary"`. */
|
|
18
|
+
color?: ChartIntent;
|
|
19
|
+
/** Render the gradient area fill under the line. Default `true`. */
|
|
20
|
+
fill?: boolean;
|
|
21
|
+
/** Line width. Default `2`. */
|
|
22
|
+
strokeWidth?: number;
|
|
23
|
+
/** Outer padding (recharts margin). Default `6`. */
|
|
24
|
+
padding?: number;
|
|
25
|
+
className?: string;
|
|
26
|
+
style?: CSSProperties;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* AreaChart — smoothed single-series area / sparkline, built on recharts. Pass
|
|
30
|
+
* `data` as an array of numbers. Colors resolve from klun tokens so the chart
|
|
31
|
+
* follows the active theme. Requires the `recharts` peer dependency.
|
|
32
|
+
*/
|
|
33
|
+
declare const AreaChart: react.ForwardRefExoticComponent<AreaChartProps & react.RefAttributes<HTMLDivElement>>;
|
|
34
|
+
|
|
35
|
+
interface BarDatum {
|
|
36
|
+
label?: ReactNode;
|
|
37
|
+
value: number;
|
|
38
|
+
/** Per-bar color override (any CSS color or `var(--klun-*)`). */
|
|
39
|
+
color?: string;
|
|
40
|
+
}
|
|
41
|
+
interface BarChartProps {
|
|
42
|
+
/** Single series of labelled bars. */
|
|
43
|
+
data?: BarDatum[];
|
|
44
|
+
/** Fixed pixel height. Default `140`. Width fills the container. */
|
|
45
|
+
height?: number;
|
|
46
|
+
/** Color intent for the bars. Default `"primary"`. */
|
|
47
|
+
color?: ChartIntent;
|
|
48
|
+
/** Category gap between bars. Default `8`. */
|
|
49
|
+
gap?: number;
|
|
50
|
+
/** Render the numeric value above each bar. Default `false`. */
|
|
51
|
+
showValues?: boolean;
|
|
52
|
+
className?: string;
|
|
53
|
+
style?: CSSProperties;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* BarChart — single-series vertical bars, built on recharts. Colors resolve from
|
|
57
|
+
* klun tokens so the chart follows the active theme. Requires the `recharts`
|
|
58
|
+
* peer dependency.
|
|
59
|
+
*/
|
|
60
|
+
declare const BarChart: react.ForwardRefExoticComponent<BarChartProps & react.RefAttributes<HTMLDivElement>>;
|
|
61
|
+
|
|
62
|
+
interface DonutDatum {
|
|
63
|
+
label?: ReactNode;
|
|
64
|
+
value: number;
|
|
65
|
+
/** Per-segment color override (any CSS color or `var(--klun-*)`). */
|
|
66
|
+
color?: string;
|
|
67
|
+
}
|
|
68
|
+
interface DonutProps {
|
|
69
|
+
/** Segments. */
|
|
70
|
+
data?: DonutDatum[];
|
|
71
|
+
/** Outer diameter in px. Default `160`. */
|
|
72
|
+
size?: number;
|
|
73
|
+
/** Ring thickness in px. Default `22`. */
|
|
74
|
+
thickness?: number;
|
|
75
|
+
/** Small caption under the center value. */
|
|
76
|
+
centerLabel?: ReactNode;
|
|
77
|
+
/** Large value in the center. */
|
|
78
|
+
centerValue?: ReactNode;
|
|
79
|
+
className?: string;
|
|
80
|
+
style?: CSSProperties;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Donut — donut / pie chart with an optional center label and a percentage
|
|
84
|
+
* legend, built on recharts. Colors resolve from klun tokens so the chart
|
|
85
|
+
* follows the active theme. Requires the `recharts` peer dependency.
|
|
86
|
+
*/
|
|
87
|
+
declare const Donut: react.ForwardRefExoticComponent<DonutProps & react.RefAttributes<HTMLDivElement>>;
|
|
88
|
+
|
|
89
|
+
export { AreaChart, type AreaChartProps, BarChart, type BarChartProps, type BarDatum, CHART_INTENT, CHART_TOOLTIP_STYLE, type ChartIntent, Donut, type DonutDatum, type DonutProps };
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { cx } from '../chunk-T225J6LV.js';
|
|
2
|
+
import { forwardRef, useId } from 'react';
|
|
3
|
+
import { ResponsiveContainer, AreaChart as AreaChart$1, Area, BarChart as BarChart$1, XAxis, Tooltip, Bar, LabelList, Cell, PieChart, Pie } from 'recharts';
|
|
4
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
var CHART_INTENT = {
|
|
7
|
+
primary: "var(--klun-primary-base)",
|
|
8
|
+
success: "var(--klun-state-success-base)",
|
|
9
|
+
danger: "var(--klun-state-error-base)",
|
|
10
|
+
warning: "var(--klun-state-warning-base)",
|
|
11
|
+
info: "var(--klun-state-information-base)"
|
|
12
|
+
};
|
|
13
|
+
var CHART_TOOLTIP_STYLE = {
|
|
14
|
+
background: "var(--klun-bg-white-0)",
|
|
15
|
+
border: "1px solid var(--klun-stroke-soft-200)",
|
|
16
|
+
borderRadius: "8px",
|
|
17
|
+
padding: "6px 10px",
|
|
18
|
+
fontSize: "12px",
|
|
19
|
+
color: "var(--klun-text-strong-950)"
|
|
20
|
+
};
|
|
21
|
+
var AreaChart = forwardRef(function AreaChart2({ data = [], width = 320, height = 96, color = "primary", fill = true, strokeWidth = 2, padding = 6, className, style }, ref) {
|
|
22
|
+
const gid = "klun-area-" + useId().replace(/:/g, "");
|
|
23
|
+
const stroke = CHART_INTENT[color] ?? CHART_INTENT.primary;
|
|
24
|
+
const series = data.map((v, i) => ({ i, v }));
|
|
25
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cx("klun-area-chart", className), style: { width, height, ...style }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(AreaChart$1, { data: series, margin: { top: padding, right: padding, bottom: padding, left: padding }, children: [
|
|
26
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: gid, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
27
|
+
/* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: stroke, stopOpacity: 0.24 }),
|
|
28
|
+
/* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: stroke, stopOpacity: 0 })
|
|
29
|
+
] }) }),
|
|
30
|
+
/* @__PURE__ */ jsx(
|
|
31
|
+
Area,
|
|
32
|
+
{
|
|
33
|
+
type: "monotone",
|
|
34
|
+
dataKey: "v",
|
|
35
|
+
stroke,
|
|
36
|
+
strokeWidth,
|
|
37
|
+
strokeLinecap: "round",
|
|
38
|
+
fill: fill ? `url(#${gid})` : "none",
|
|
39
|
+
fillOpacity: 1,
|
|
40
|
+
dot: false,
|
|
41
|
+
isAnimationActive: false
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
] }) }) });
|
|
45
|
+
});
|
|
46
|
+
AreaChart.displayName = "AreaChart";
|
|
47
|
+
var BarChart = forwardRef(function BarChart2({ data = [], height = 140, color = "primary", gap = 8, showValues = false, className, style }, ref) {
|
|
48
|
+
const fill = CHART_INTENT[color] ?? CHART_INTENT.primary;
|
|
49
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cx("klun-bar-chart", className), style: { width: "100%", height, ...style }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(BarChart$1, { data, margin: { top: showValues ? 18 : 6, right: 6, bottom: 0, left: 6 }, barCategoryGap: gap, children: [
|
|
50
|
+
/* @__PURE__ */ jsx(
|
|
51
|
+
XAxis,
|
|
52
|
+
{
|
|
53
|
+
dataKey: "label",
|
|
54
|
+
tickLine: false,
|
|
55
|
+
axisLine: false,
|
|
56
|
+
tick: { fontSize: 11, fill: "var(--klun-text-sub-600)" }
|
|
57
|
+
}
|
|
58
|
+
),
|
|
59
|
+
/* @__PURE__ */ jsx(Tooltip, { cursor: { fill: "var(--klun-bg-weak-50)" }, contentStyle: CHART_TOOLTIP_STYLE }),
|
|
60
|
+
/* @__PURE__ */ jsxs(Bar, { dataKey: "value", fill, radius: [4, 4, 0, 0], isAnimationActive: false, children: [
|
|
61
|
+
showValues ? /* @__PURE__ */ jsx(
|
|
62
|
+
LabelList,
|
|
63
|
+
{
|
|
64
|
+
dataKey: "value",
|
|
65
|
+
position: "top",
|
|
66
|
+
style: { fontSize: 11, fontWeight: 600, fill: "var(--klun-text-sub-600)" }
|
|
67
|
+
}
|
|
68
|
+
) : null,
|
|
69
|
+
data.map((d, i) => /* @__PURE__ */ jsx(Cell, { fill: d.color || fill }, i))
|
|
70
|
+
] })
|
|
71
|
+
] }) }) });
|
|
72
|
+
});
|
|
73
|
+
BarChart.displayName = "BarChart";
|
|
74
|
+
var PALETTE = [
|
|
75
|
+
"var(--klun-primary-base)",
|
|
76
|
+
"var(--klun-state-success-base)",
|
|
77
|
+
"var(--klun-state-warning-base)",
|
|
78
|
+
"var(--klun-state-error-base)",
|
|
79
|
+
"var(--klun-state-information-base)",
|
|
80
|
+
"var(--klun-icon-disabled-300)"
|
|
81
|
+
];
|
|
82
|
+
var Donut = forwardRef(function Donut2({ data = [], size = 160, thickness = 22, centerLabel, centerValue, className, style }, ref) {
|
|
83
|
+
const total = data.reduce((s, d) => s + (d.value || 0), 0) || 1;
|
|
84
|
+
return /* @__PURE__ */ jsxs(
|
|
85
|
+
"div",
|
|
86
|
+
{
|
|
87
|
+
ref,
|
|
88
|
+
className: cx("klun-donut", className),
|
|
89
|
+
style: { display: "inline-flex", alignItems: "center", gap: 18, ...style },
|
|
90
|
+
children: [
|
|
91
|
+
/* @__PURE__ */ jsxs("div", { style: { position: "relative", width: size, height: size, flexShrink: 0 }, children: [
|
|
92
|
+
/* @__PURE__ */ jsx(PieChart, { width: size, height: size, children: /* @__PURE__ */ jsx(
|
|
93
|
+
Pie,
|
|
94
|
+
{
|
|
95
|
+
data,
|
|
96
|
+
dataKey: "value",
|
|
97
|
+
cx: "50%",
|
|
98
|
+
cy: "50%",
|
|
99
|
+
innerRadius: size / 2 - thickness,
|
|
100
|
+
outerRadius: size / 2,
|
|
101
|
+
startAngle: 90,
|
|
102
|
+
endAngle: -270,
|
|
103
|
+
stroke: "none",
|
|
104
|
+
isAnimationActive: false,
|
|
105
|
+
children: data.map((d, i) => /* @__PURE__ */ jsx(Cell, { fill: d.color || PALETTE[i % PALETTE.length] }, i))
|
|
106
|
+
}
|
|
107
|
+
) }),
|
|
108
|
+
centerLabel || centerValue ? /* @__PURE__ */ jsxs(
|
|
109
|
+
"div",
|
|
110
|
+
{
|
|
111
|
+
style: {
|
|
112
|
+
position: "absolute",
|
|
113
|
+
inset: 0,
|
|
114
|
+
display: "flex",
|
|
115
|
+
flexDirection: "column",
|
|
116
|
+
alignItems: "center",
|
|
117
|
+
justifyContent: "center",
|
|
118
|
+
pointerEvents: "none"
|
|
119
|
+
},
|
|
120
|
+
children: [
|
|
121
|
+
centerValue ? /* @__PURE__ */ jsx("span", { style: { fontSize: 22, fontWeight: 700, color: "var(--klun-text-strong-950)" }, children: centerValue }) : null,
|
|
122
|
+
centerLabel ? /* @__PURE__ */ jsx("span", { style: { fontSize: 11, color: "var(--klun-text-sub-600)" }, children: centerLabel }) : null
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
) : null
|
|
126
|
+
] }),
|
|
127
|
+
data.length > 0 ? /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: data.map((d, i) => /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, fontSize: 12 }, children: [
|
|
128
|
+
/* @__PURE__ */ jsx(
|
|
129
|
+
"span",
|
|
130
|
+
{
|
|
131
|
+
style: {
|
|
132
|
+
width: 10,
|
|
133
|
+
height: 10,
|
|
134
|
+
borderRadius: 3,
|
|
135
|
+
background: d.color || PALETTE[i % PALETTE.length],
|
|
136
|
+
flexShrink: 0
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
),
|
|
140
|
+
/* @__PURE__ */ jsx("span", { style: { color: "var(--klun-text-sub-600)" }, children: d.label }),
|
|
141
|
+
/* @__PURE__ */ jsxs("span", { style: { marginLeft: "auto", fontWeight: 600, color: "var(--klun-text-strong-950)" }, children: [
|
|
142
|
+
Math.round((d.value || 0) / total * 100),
|
|
143
|
+
"%"
|
|
144
|
+
] })
|
|
145
|
+
] }, i)) }) : null
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
);
|
|
149
|
+
});
|
|
150
|
+
Donut.displayName = "Donut";
|
|
151
|
+
|
|
152
|
+
export { AreaChart, BarChart, CHART_INTENT, CHART_TOOLTIP_STYLE, Donut };
|
|
153
|
+
//# sourceMappingURL=index.js.map
|
|
154
|
+
//# sourceMappingURL=index.js.map
|