@k2b/ui 0.48.0 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base.css +40 -2
- package/dist/browser/actions/ContextMenu.js +3 -0
- package/dist/browser/actions/ContextMenu.js.map +1 -1
- package/dist/browser/actions/CopyButton.js +26 -18
- package/dist/browser/actions/CopyButton.js.map +1 -1
- package/dist/browser/charts/core/area.js +190 -0
- package/dist/browser/charts/core/area.js.map +1 -0
- package/dist/browser/charts/core/calendar.js +186 -0
- package/dist/browser/charts/core/calendar.js.map +1 -0
- package/dist/browser/charts/core/chart-map-data.js +9 -0
- package/dist/browser/charts/core/chart-map-data.js.map +1 -0
- package/dist/browser/charts/core/index.js +12 -0
- package/dist/browser/charts/core/index.js.map +1 -0
- package/dist/browser/charts/core/inspection.js +9 -0
- package/dist/browser/charts/core/inspection.js.map +1 -0
- package/dist/browser/charts/core/registry.js +28 -0
- package/dist/browser/charts/core/registry.js.map +1 -0
- package/dist/browser/charts/core/render.js +103 -0
- package/dist/browser/charts/core/render.js.map +1 -0
- package/dist/browser/charts/core/snapshot.js +65 -0
- package/dist/browser/charts/core/snapshot.js.map +1 -0
- package/dist/browser/charts/core/svg.js +2542 -0
- package/dist/browser/charts/core/svg.js.map +1 -0
- package/dist/browser/charts/core/termination.test-fixture.js +162 -0
- package/dist/browser/charts/core/termination.test-fixture.js.map +1 -0
- package/dist/browser/charts/core/text.js +13 -0
- package/dist/browser/charts/core/text.js.map +1 -0
- package/dist/browser/charts/core/types.js +8 -0
- package/dist/browser/charts/core/types.js.map +1 -0
- package/dist/browser/charts.js +4 -2
- package/dist/browser/charts.js.map +1 -1
- package/dist/browser/content/BalanceSummary.js +106 -0
- package/dist/browser/content/BalanceSummary.js.map +1 -0
- package/dist/browser/content/Chart.js +134 -115
- package/dist/browser/content/Chart.js.map +1 -1
- package/dist/browser/content/ChartExplorer.js +366 -122
- package/dist/browser/content/ChartExplorer.js.map +1 -1
- package/dist/browser/content/ChartSnapshotView.js +16 -9
- package/dist/browser/content/ChartSnapshotView.js.map +1 -1
- package/dist/browser/content/DataTable.js +676 -293
- package/dist/browser/content/DataTable.js.map +1 -1
- package/dist/browser/content/DataTableTools.js +119 -0
- package/dist/browser/content/DataTableTools.js.map +1 -0
- package/dist/browser/content/FlowAmount.js +82 -0
- package/dist/browser/content/FlowAmount.js.map +1 -0
- package/dist/browser/content/balance-summary-messages.js +26 -0
- package/dist/browser/content/balance-summary-messages.js.map +1 -0
- package/dist/browser/content/chart-bar.js +6 -6
- package/dist/browser/content/chart-bar.js.map +1 -1
- package/dist/browser/content/chart-calendar.js +43 -0
- package/dist/browser/content/chart-calendar.js.map +1 -0
- package/dist/browser/content/chart-inspection-core.js +164 -37
- package/dist/browser/content/chart-inspection-core.js.map +1 -1
- package/dist/browser/content/chart-inspection.js.map +1 -1
- package/dist/browser/content/chart-line-gaps.js +2 -2
- package/dist/browser/content/chart-line-gaps.js.map +1 -1
- package/dist/browser/content/chart-map-viewport.js.map +1 -1
- package/dist/browser/content/chart-message-catalog.js +164 -0
- package/dist/browser/content/chart-message-catalog.js.map +1 -0
- package/dist/browser/content/chart-messages.js +2 -138
- package/dist/browser/content/chart-messages.js.map +1 -1
- package/dist/browser/content/chart-snapshot.js +1 -62
- package/dist/browser/content/chart-snapshot.js.map +1 -1
- package/dist/browser/content/chart-state-timeline.js +1 -1
- package/dist/browser/content/chart-state-timeline.js.map +1 -1
- package/dist/browser/content/chart-svg.js +2 -1
- package/dist/browser/content/chart-svg.js.map +1 -1
- package/dist/browser/content/chart-time-axis.js +139 -0
- package/dist/browser/content/chart-time-axis.js.map +1 -0
- package/dist/browser/content/data-table-columns.js +160 -0
- package/dist/browser/content/data-table-columns.js.map +1 -0
- package/dist/browser/content/data-table-messages.js +38 -2
- package/dist/browser/content/data-table-messages.js.map +1 -1
- package/dist/browser/content/flow-amount-messages.js +26 -0
- package/dist/browser/content/flow-amount-messages.js.map +1 -0
- package/dist/browser/content/index.js +4 -0
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/feedback/prompt-confirm.js +7 -4
- package/dist/browser/feedback/prompt-confirm.js.map +1 -1
- package/dist/browser/feedback/prompts.js +3 -3
- package/dist/browser/feedback/prompts.js.map +1 -1
- package/dist/browser/inputs/DatePicker.js +5 -4
- package/dist/browser/inputs/DatePicker.js.map +1 -1
- package/dist/browser/inputs/NumberInput.js +17 -5
- package/dist/browser/inputs/NumberInput.js.map +1 -1
- package/dist/browser/inputs/SelectChip.js +50 -17
- package/dist/browser/inputs/SelectChip.js.map +1 -1
- package/dist/browser/inputs/date-picker.js +13 -0
- package/dist/browser/inputs/date-picker.js.map +1 -1
- package/dist/browser/intl/Format.js +31 -8
- package/dist/browser/intl/Format.js.map +1 -1
- package/dist/browser/layout/AppWorkspace.js +580 -522
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/MobileShell.js +26 -0
- package/dist/browser/layout/MobileShell.js.map +1 -1
- package/dist/browser/layout/index.js +1 -0
- package/dist/browser/layout/index.js.map +1 -1
- package/dist/browser/layout/sheet-handle.js +155 -0
- package/dist/browser/layout/sheet-handle.js.map +1 -0
- package/dist/browser/surfaces/BudgetList.js +281 -0
- package/dist/browser/surfaces/BudgetList.js.map +1 -0
- package/dist/browser/surfaces/NoticeCard.js +48 -29
- package/dist/browser/surfaces/NoticeCard.js.map +1 -1
- package/dist/browser/surfaces/ProgressBar.js +134 -21
- package/dist/browser/surfaces/ProgressBar.js.map +1 -1
- package/dist/browser/surfaces/StatCell.js +320 -144
- package/dist/browser/surfaces/StatCell.js.map +1 -1
- package/dist/browser/surfaces/StatGrid.js +75 -57
- package/dist/browser/surfaces/StatGrid.js.map +1 -1
- package/dist/browser/surfaces/budget-messages.js +64 -0
- package/dist/browser/surfaces/budget-messages.js.map +1 -0
- package/dist/browser/surfaces/delta-badge.js +65 -0
- package/dist/browser/surfaces/delta-badge.js.map +1 -0
- package/dist/browser/surfaces/index.js +2 -1
- package/dist/browser/surfaces/index.js.map +1 -1
- package/dist/browser/surfaces/person-color.js +2 -2
- package/dist/browser/surfaces/person-color.js.map +1 -1
- package/dist/browser/surfaces/stat-cell-messages.js +41 -0
- package/dist/browser/surfaces/stat-cell-messages.js.map +1 -0
- package/dist/browser/widgets/Dashboard.js +137 -0
- package/dist/browser/widgets/Dashboard.js.map +1 -0
- package/dist/browser/widgets/index.js +1 -0
- package/dist/browser/widgets/index.js.map +1 -1
- package/dist/ssr/actions/ContextMenu.js +3 -0
- package/dist/ssr/actions/ContextMenu.js.map +1 -1
- package/dist/ssr/actions/CopyButton.js +13 -8
- package/dist/ssr/actions/CopyButton.js.map +1 -1
- package/dist/ssr/charts/core/area.js +190 -0
- package/dist/ssr/charts/core/area.js.map +1 -0
- package/dist/ssr/charts/core/calendar.js +186 -0
- package/dist/ssr/charts/core/calendar.js.map +1 -0
- package/dist/ssr/charts/core/chart-map-data.js +9 -0
- package/dist/ssr/charts/core/chart-map-data.js.map +1 -0
- package/dist/ssr/charts/core/index.js +12 -0
- package/dist/ssr/charts/core/index.js.map +1 -0
- package/dist/ssr/charts/core/inspection.js +9 -0
- package/dist/ssr/charts/core/inspection.js.map +1 -0
- package/dist/ssr/charts/core/registry.js +28 -0
- package/dist/ssr/charts/core/registry.js.map +1 -0
- package/dist/ssr/charts/core/render.js +103 -0
- package/dist/ssr/charts/core/render.js.map +1 -0
- package/dist/ssr/charts/core/snapshot.js +65 -0
- package/dist/ssr/charts/core/snapshot.js.map +1 -0
- package/dist/ssr/charts/core/svg.js +2542 -0
- package/dist/ssr/charts/core/svg.js.map +1 -0
- package/dist/ssr/charts/core/termination.test-fixture.js +162 -0
- package/dist/ssr/charts/core/termination.test-fixture.js.map +1 -0
- package/dist/ssr/charts/core/text.js +13 -0
- package/dist/ssr/charts/core/text.js.map +1 -0
- package/dist/ssr/charts/core/types.js +8 -0
- package/dist/ssr/charts/core/types.js.map +1 -0
- package/dist/ssr/charts.js +4 -2
- package/dist/ssr/charts.js.map +1 -1
- package/dist/ssr/content/BalanceSummary.js +75 -0
- package/dist/ssr/content/BalanceSummary.js.map +1 -0
- package/dist/ssr/content/Chart.js +90 -95
- package/dist/ssr/content/Chart.js.map +1 -1
- package/dist/ssr/content/ChartExplorer.js +190 -46
- package/dist/ssr/content/ChartExplorer.js.map +1 -1
- package/dist/ssr/content/ChartSnapshotView.js +5 -1
- package/dist/ssr/content/ChartSnapshotView.js.map +1 -1
- package/dist/ssr/content/DataTable.js +287 -78
- package/dist/ssr/content/DataTable.js.map +1 -1
- package/dist/ssr/content/DataTableTools.js +106 -0
- package/dist/ssr/content/DataTableTools.js.map +1 -0
- package/dist/ssr/content/FlowAmount.js +58 -0
- package/dist/ssr/content/FlowAmount.js.map +1 -0
- package/dist/ssr/content/balance-summary-messages.js +26 -0
- package/dist/ssr/content/balance-summary-messages.js.map +1 -0
- package/dist/ssr/content/chart-bar.js +6 -6
- package/dist/ssr/content/chart-bar.js.map +1 -1
- package/dist/ssr/content/chart-calendar.js +43 -0
- package/dist/ssr/content/chart-calendar.js.map +1 -0
- package/dist/ssr/content/chart-inspection-core.js +164 -37
- package/dist/ssr/content/chart-inspection-core.js.map +1 -1
- package/dist/ssr/content/chart-inspection.js.map +1 -1
- package/dist/ssr/content/chart-line-gaps.js +2 -2
- package/dist/ssr/content/chart-line-gaps.js.map +1 -1
- package/dist/ssr/content/chart-map-viewport.js.map +1 -1
- package/dist/ssr/content/chart-message-catalog.js +164 -0
- package/dist/ssr/content/chart-message-catalog.js.map +1 -0
- package/dist/ssr/content/chart-messages.js +2 -138
- package/dist/ssr/content/chart-messages.js.map +1 -1
- package/dist/ssr/content/chart-snapshot.js +1 -62
- package/dist/ssr/content/chart-snapshot.js.map +1 -1
- package/dist/ssr/content/chart-state-timeline.js +1 -1
- package/dist/ssr/content/chart-state-timeline.js.map +1 -1
- package/dist/ssr/content/chart-svg.js +2 -1
- package/dist/ssr/content/chart-svg.js.map +1 -1
- package/dist/ssr/content/chart-time-axis.js +139 -0
- package/dist/ssr/content/chart-time-axis.js.map +1 -0
- package/dist/ssr/content/data-table-columns.js +160 -0
- package/dist/ssr/content/data-table-columns.js.map +1 -0
- package/dist/ssr/content/data-table-messages.js +38 -2
- package/dist/ssr/content/data-table-messages.js.map +1 -1
- package/dist/ssr/content/flow-amount-messages.js +26 -0
- package/dist/ssr/content/flow-amount-messages.js.map +1 -0
- package/dist/ssr/content/index.js +4 -0
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/feedback/prompt-confirm.js +7 -4
- package/dist/ssr/feedback/prompt-confirm.js.map +1 -1
- package/dist/ssr/feedback/prompts.js +3 -3
- package/dist/ssr/feedback/prompts.js.map +1 -1
- package/dist/ssr/inputs/DatePicker.js +5 -4
- package/dist/ssr/inputs/DatePicker.js.map +1 -1
- package/dist/ssr/inputs/NumberInput.js +17 -5
- package/dist/ssr/inputs/NumberInput.js.map +1 -1
- package/dist/ssr/inputs/SelectChip.js +26 -9
- package/dist/ssr/inputs/SelectChip.js.map +1 -1
- package/dist/ssr/inputs/date-picker.js +13 -0
- package/dist/ssr/inputs/date-picker.js.map +1 -1
- package/dist/ssr/intl/Format.js +22 -2
- package/dist/ssr/intl/Format.js.map +1 -1
- package/dist/ssr/layout/AppWorkspace.js +158 -114
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/MobileShell.js +26 -0
- package/dist/ssr/layout/MobileShell.js.map +1 -1
- package/dist/ssr/layout/index.js +1 -0
- package/dist/ssr/layout/index.js.map +1 -1
- package/dist/ssr/layout/sheet-handle.js +155 -0
- package/dist/ssr/layout/sheet-handle.js.map +1 -0
- package/dist/ssr/surfaces/BudgetList.js +170 -0
- package/dist/ssr/surfaces/BudgetList.js.map +1 -0
- package/dist/ssr/surfaces/NoticeCard.js +25 -10
- package/dist/ssr/surfaces/NoticeCard.js.map +1 -1
- package/dist/ssr/surfaces/ProgressBar.js +96 -5
- package/dist/ssr/surfaces/ProgressBar.js.map +1 -1
- package/dist/ssr/surfaces/StatCell.js +157 -51
- package/dist/ssr/surfaces/StatCell.js.map +1 -1
- package/dist/ssr/surfaces/StatGrid.js +24 -35
- package/dist/ssr/surfaces/StatGrid.js.map +1 -1
- package/dist/ssr/surfaces/budget-messages.js +64 -0
- package/dist/ssr/surfaces/budget-messages.js.map +1 -0
- package/dist/ssr/surfaces/delta-badge.js +41 -0
- package/dist/ssr/surfaces/delta-badge.js.map +1 -0
- package/dist/ssr/surfaces/index.js +2 -1
- package/dist/ssr/surfaces/index.js.map +1 -1
- package/dist/ssr/surfaces/person-color.js +2 -2
- package/dist/ssr/surfaces/person-color.js.map +1 -1
- package/dist/ssr/surfaces/stat-cell-messages.js +41 -0
- package/dist/ssr/surfaces/stat-cell-messages.js.map +1 -0
- package/dist/ssr/widgets/Dashboard.js +84 -0
- package/dist/ssr/widgets/Dashboard.js.map +1 -0
- package/dist/ssr/widgets/index.js +1 -0
- package/dist/ssr/widgets/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/charts/core/area.d.ts +62 -0
- package/dist/types/charts/core/calendar.d.ts +57 -0
- package/dist/types/charts/core/chart-map-data.d.ts +3 -0
- package/dist/types/charts/core/index.d.ts +11 -0
- package/dist/types/charts/core/inspection.d.ts +16 -0
- package/dist/types/charts/core/registry.d.ts +27 -0
- package/dist/types/charts/core/render.d.ts +40 -0
- package/dist/types/charts/core/snapshot.d.ts +27 -0
- package/dist/types/charts/core/svg.d.ts +714 -0
- package/dist/types/charts/core/termination.test-fixture.d.ts +1 -0
- package/dist/types/charts/core/text.d.ts +5 -0
- package/dist/types/charts/core/types.d.ts +31 -0
- package/dist/types/charts.d.ts +4 -2
- package/dist/types/content/BalanceSummary.d.ts +29 -0
- package/dist/types/content/Chart.d.ts +26 -36
- package/dist/types/content/ChartExplorer.d.ts +43 -2
- package/dist/types/content/ChartSnapshotView.d.ts +1 -0
- package/dist/types/content/DataTable.d.ts +28 -0
- package/dist/types/content/DataTableTools.d.ts +44 -0
- package/dist/types/content/FlowAmount.d.ts +28 -0
- package/dist/types/content/balance-summary-messages.d.ts +11 -0
- package/dist/types/content/chart-bar.d.ts +1 -1
- package/dist/types/content/chart-calendar.d.ts +4 -0
- package/dist/types/content/chart-inspection-core.d.ts +21 -16
- package/dist/types/content/chart-inspection.d.ts +5 -1
- package/dist/types/content/chart-map-viewport.d.ts +1 -1
- package/dist/types/content/chart-message-catalog.d.ts +84 -0
- package/dist/types/content/chart-messages.d.ts +2 -33
- package/dist/types/content/chart-snapshot.d.ts +1 -26
- package/dist/types/content/chart-svg.d.ts +1 -1
- package/dist/types/content/chart-time-axis.d.ts +26 -0
- package/dist/types/content/data-table-columns.d.ts +72 -0
- package/dist/types/content/data-table-messages.d.ts +18 -0
- package/dist/types/content/flow-amount-messages.d.ts +11 -0
- package/dist/types/content/index.d.ts +10 -2
- package/dist/types/feedback/prompt-confirm.d.ts +3 -1
- package/dist/types/feedback/prompts.d.ts +2 -2
- package/dist/types/inputs/NumberInput.d.ts +1 -1
- package/dist/types/inputs/SelectChip.d.ts +2 -0
- package/dist/types/inputs/date-picker.d.ts +6 -0
- package/dist/types/intl/Format.d.ts +5 -0
- package/dist/types/layout/AppWorkspace.d.ts +21 -1
- package/dist/types/layout/MobileShell.d.ts +5 -0
- package/dist/types/layout/index.d.ts +2 -1
- package/dist/types/layout/sheet-handle.d.ts +21 -0
- package/dist/types/surfaces/BudgetList.d.ts +42 -0
- package/dist/types/surfaces/NoticeCard.d.ts +5 -2
- package/dist/types/surfaces/ProgressBar.d.ts +38 -2
- package/dist/types/surfaces/StatCell.d.ts +35 -2
- package/dist/types/surfaces/StatGrid.d.ts +3 -1
- package/dist/types/surfaces/budget-messages.d.ts +30 -0
- package/dist/types/surfaces/delta-badge.d.ts +10 -0
- package/dist/types/surfaces/index.d.ts +4 -3
- package/dist/types/surfaces/person-color.d.ts +2 -2
- package/dist/types/surfaces/stat-cell-messages.d.ts +19 -0
- package/dist/types/widgets/Dashboard.d.ts +42 -0
- package/dist/types/widgets/index.d.ts +1 -0
- package/package.json +7 -1
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
// Draws every axis kind with values that the float spacing or the tick budget used to keep counting forever.
|
|
2
|
+
// termination.test.ts runs this file in a child process with a deadline, so a regression fails instead of hanging.
|
|
3
|
+
import { chartTimeStep, chartTimeTicks } from "../../content/chart-time-axis";
|
|
4
|
+
import { renderChartSvg } from "./render";
|
|
5
|
+
import { extendDomainToNice, stateTimeline } from "./svg";
|
|
6
|
+
|
|
7
|
+
// One value at 1e17 has a float spacing of 16, so its ±1 padding collapses to a zero range.
|
|
8
|
+
const big = 1e17;
|
|
9
|
+
const pair = (x, y) => [{
|
|
10
|
+
x,
|
|
11
|
+
y
|
|
12
|
+
}];
|
|
13
|
+
const cases = {
|
|
14
|
+
"line, auto y": () => renderChartSvg({
|
|
15
|
+
kind: "line",
|
|
16
|
+
series: [{
|
|
17
|
+
label: "A",
|
|
18
|
+
data: [...pair(0, big), ...pair(1, big)]
|
|
19
|
+
}]
|
|
20
|
+
}, 480, 280),
|
|
21
|
+
"line, nearly equal y": () => renderChartSvg({
|
|
22
|
+
kind: "line",
|
|
23
|
+
series: [{
|
|
24
|
+
label: "A",
|
|
25
|
+
data: [...pair(0, big), ...pair(1, big + 16)]
|
|
26
|
+
}]
|
|
27
|
+
}, 480, 280),
|
|
28
|
+
"line, auto x": () => renderChartSvg({
|
|
29
|
+
kind: "line",
|
|
30
|
+
series: [{
|
|
31
|
+
label: "A",
|
|
32
|
+
data: [...pair(big, 1), ...pair(big, 2)]
|
|
33
|
+
}]
|
|
34
|
+
}, 480, 280),
|
|
35
|
+
"line, fixed y with a tick target past the budget": () => renderChartSvg({
|
|
36
|
+
kind: "line",
|
|
37
|
+
series: [{
|
|
38
|
+
label: "A",
|
|
39
|
+
data: pair(0, 0.5)
|
|
40
|
+
}],
|
|
41
|
+
yAxis: {
|
|
42
|
+
domain: [0, 1],
|
|
43
|
+
ticks: 1e9
|
|
44
|
+
}
|
|
45
|
+
}, 480, 280),
|
|
46
|
+
"line, time x": () => renderChartSvg({
|
|
47
|
+
kind: "line",
|
|
48
|
+
series: [{
|
|
49
|
+
label: "A",
|
|
50
|
+
data: pair(big, 1)
|
|
51
|
+
}],
|
|
52
|
+
timeAxis: {
|
|
53
|
+
timeZone: "UTC"
|
|
54
|
+
}
|
|
55
|
+
}, 480, 280),
|
|
56
|
+
"scatter, auto x and y": () => renderChartSvg({
|
|
57
|
+
kind: "scatter",
|
|
58
|
+
series: [{
|
|
59
|
+
label: "A",
|
|
60
|
+
data: pair(big, big)
|
|
61
|
+
}]
|
|
62
|
+
}, 480, 280),
|
|
63
|
+
"histogram, auto x": () => renderChartSvg({
|
|
64
|
+
kind: "histogram",
|
|
65
|
+
data: [big, big, big]
|
|
66
|
+
}, 480, 280),
|
|
67
|
+
"boxplot, auto y": () => renderChartSvg({
|
|
68
|
+
kind: "boxplot",
|
|
69
|
+
groups: [{
|
|
70
|
+
label: "A",
|
|
71
|
+
values: [big, big, big]
|
|
72
|
+
}]
|
|
73
|
+
}, 480, 280),
|
|
74
|
+
"bar, auto y": () => renderChartSvg({
|
|
75
|
+
kind: "bar",
|
|
76
|
+
data: [{
|
|
77
|
+
label: "A",
|
|
78
|
+
value: -big
|
|
79
|
+
}]
|
|
80
|
+
}, 480, 280),
|
|
81
|
+
"bar, fixed y with a tick target past the budget": () => renderChartSvg({
|
|
82
|
+
kind: "bar",
|
|
83
|
+
data: [{
|
|
84
|
+
label: "A",
|
|
85
|
+
value: 0.5
|
|
86
|
+
}],
|
|
87
|
+
yAxis: {
|
|
88
|
+
domain: [0, 1],
|
|
89
|
+
ticks: 1e9
|
|
90
|
+
}
|
|
91
|
+
}, 480, 280),
|
|
92
|
+
"state timeline, time x": () => renderChartSvg({
|
|
93
|
+
kind: "stateTimeline",
|
|
94
|
+
rows: [{
|
|
95
|
+
label: "A",
|
|
96
|
+
intervals: [{
|
|
97
|
+
from: big,
|
|
98
|
+
to: big,
|
|
99
|
+
state: "on"
|
|
100
|
+
}]
|
|
101
|
+
}]
|
|
102
|
+
}, 480, 280),
|
|
103
|
+
"core state timeline, time x": () => stateTimeline({
|
|
104
|
+
width: 480,
|
|
105
|
+
height: 280,
|
|
106
|
+
rows: [{
|
|
107
|
+
label: "A",
|
|
108
|
+
intervals: [{
|
|
109
|
+
from: big,
|
|
110
|
+
to: big,
|
|
111
|
+
state: "on"
|
|
112
|
+
}]
|
|
113
|
+
}]
|
|
114
|
+
}),
|
|
115
|
+
"log y": () => renderChartSvg({
|
|
116
|
+
kind: "line",
|
|
117
|
+
series: [{
|
|
118
|
+
label: "A",
|
|
119
|
+
data: pair(0, 1)
|
|
120
|
+
}],
|
|
121
|
+
yAxis: {
|
|
122
|
+
scale: "log",
|
|
123
|
+
domain: [1e-300, 1e300]
|
|
124
|
+
}
|
|
125
|
+
}, 480, 280),
|
|
126
|
+
"nice ticks, step below the float spacing": () => extendDomainToNice(big, big, 1).ticks,
|
|
127
|
+
"nice ticks, step past the budget": () => extendDomainToNice(0, 1, 1e-9).ticks,
|
|
128
|
+
"nice ticks, negative step": () => extendDomainToNice(0, 10, -1).ticks,
|
|
129
|
+
"time ticks, instants past the Date range": () => chartTimeTicks([big, big + 86_400_000], "UTC", chartTimeStep(86_400_000, 5)),
|
|
130
|
+
"time ticks, a step below the float spacing": () => chartTimeTicks([Date.UTC(2026, 0, 1), Date.UTC(2026, 0, 2)], "UTC", {
|
|
131
|
+
unit: "hour",
|
|
132
|
+
size: 1e-20
|
|
133
|
+
}),
|
|
134
|
+
"time ticks, a step that repeats one minute": () => chartTimeTicks([Date.UTC(2026, 0, 1), Date.UTC(2026, 0, 2)], "UTC", {
|
|
135
|
+
unit: "hour",
|
|
136
|
+
size: 1e-9
|
|
137
|
+
}),
|
|
138
|
+
"time ticks, a zero year step": () => chartTimeTicks([Date.UTC(2026, 0, 1), Date.UTC(2036, 0, 1)], "UTC", {
|
|
139
|
+
unit: "year",
|
|
140
|
+
size: 0
|
|
141
|
+
}),
|
|
142
|
+
"time ticks, a negative step": () => chartTimeTicks([Date.UTC(2026, 0, 1), Date.UTC(2026, 0, 2)], "UTC", {
|
|
143
|
+
unit: "hour",
|
|
144
|
+
size: -1
|
|
145
|
+
})
|
|
146
|
+
};
|
|
147
|
+
for (const [name, draw] of Object.entries(cases)) {
|
|
148
|
+
const result = draw();
|
|
149
|
+
console.log(JSON.stringify({
|
|
150
|
+
name,
|
|
151
|
+
...(typeof result === "string" ? {
|
|
152
|
+
svg: result.length,
|
|
153
|
+
nan: /NaN/.test(result)
|
|
154
|
+
} : {
|
|
155
|
+
ticks: result
|
|
156
|
+
})
|
|
157
|
+
}));
|
|
158
|
+
}
|
|
159
|
+
console.log(JSON.stringify({
|
|
160
|
+
done: Object.keys(cases).length
|
|
161
|
+
}));
|
|
162
|
+
//# sourceMappingURL=termination.test-fixture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["line, auto y","line, nearly equal y","line, auto x","line, fixed y with a tick target past the budget","line, time x","scatter, auto x and y","histogram, auto x","boxplot, auto y","bar, auto y","bar, fixed y with a tick target past the budget","state timeline, time x","core state timeline, time x","log y","nice ticks, step below the float spacing","nice ticks, step past the budget","nice ticks, negative step","time ticks, instants past the Date range","time ticks, a step below the float spacing","time ticks, a step that repeats one minute","time ticks, a zero year step","time ticks, a negative step"],"sources":["charts/core/termination.test-fixture.ts"],"sourcesContent":["// Draws every axis kind with values that the float spacing or the tick budget used to keep counting forever.\n// termination.test.ts runs this file in a child process with a deadline, so a regression fails instead of hanging.\nimport { chartTimeStep, chartTimeTicks } from \"../../content/chart-time-axis\";\nimport { renderChartSvg } from \"./render\";\nimport { extendDomainToNice, stateTimeline } from \"./svg\";\n\n// One value at 1e17 has a float spacing of 16, so its ±1 padding collapses to a zero range.\nconst big = 1e17;\nconst pair = (x: number, y: number) => [{ x, y }];\nconst cases: Record<string, () => string | number[]> = {\n \"line, auto y\": () => renderChartSvg({ kind: \"line\", series: [{ label: \"A\", data: [...pair(0, big), ...pair(1, big)] }] }, 480, 280),\n \"line, nearly equal y\": () =>\n renderChartSvg({ kind: \"line\", series: [{ label: \"A\", data: [...pair(0, big), ...pair(1, big + 16)] }] }, 480, 280),\n \"line, auto x\": () => renderChartSvg({ kind: \"line\", series: [{ label: \"A\", data: [...pair(big, 1), ...pair(big, 2)] }] }, 480, 280),\n \"line, fixed y with a tick target past the budget\": () =>\n renderChartSvg({ kind: \"line\", series: [{ label: \"A\", data: pair(0, 0.5) }], yAxis: { domain: [0, 1], ticks: 1e9 } }, 480, 280),\n \"line, time x\": () =>\n renderChartSvg({ kind: \"line\", series: [{ label: \"A\", data: pair(big, 1) }], timeAxis: { timeZone: \"UTC\" } }, 480, 280),\n \"scatter, auto x and y\": () => renderChartSvg({ kind: \"scatter\", series: [{ label: \"A\", data: pair(big, big) }] }, 480, 280),\n \"histogram, auto x\": () => renderChartSvg({ kind: \"histogram\", data: [big, big, big] }, 480, 280),\n \"boxplot, auto y\": () => renderChartSvg({ kind: \"boxplot\", groups: [{ label: \"A\", values: [big, big, big] }] }, 480, 280),\n \"bar, auto y\": () => renderChartSvg({ kind: \"bar\", data: [{ label: \"A\", value: -big }] }, 480, 280),\n \"bar, fixed y with a tick target past the budget\": () =>\n renderChartSvg({ kind: \"bar\", data: [{ label: \"A\", value: 0.5 }], yAxis: { domain: [0, 1], ticks: 1e9 } }, 480, 280),\n \"state timeline, time x\": () =>\n renderChartSvg({ kind: \"stateTimeline\", rows: [{ label: \"A\", intervals: [{ from: big, to: big, state: \"on\" }] }] }, 480, 280),\n \"core state timeline, time x\": () =>\n stateTimeline({ width: 480, height: 280, rows: [{ label: \"A\", intervals: [{ from: big, to: big, state: \"on\" }] }] }),\n \"log y\": () =>\n renderChartSvg(\n { kind: \"line\", series: [{ label: \"A\", data: pair(0, 1) }], yAxis: { scale: \"log\", domain: [1e-300, 1e300] } },\n 480,\n 280,\n ),\n \"nice ticks, step below the float spacing\": () => extendDomainToNice(big, big, 1).ticks,\n \"nice ticks, step past the budget\": () => extendDomainToNice(0, 1, 1e-9).ticks,\n \"nice ticks, negative step\": () => extendDomainToNice(0, 10, -1).ticks,\n \"time ticks, instants past the Date range\": () => chartTimeTicks([big, big + 86_400_000], \"UTC\", chartTimeStep(86_400_000, 5)),\n \"time ticks, a step below the float spacing\": () =>\n chartTimeTicks([Date.UTC(2026, 0, 1), Date.UTC(2026, 0, 2)], \"UTC\", { unit: \"hour\", size: 1e-20 }),\n \"time ticks, a step that repeats one minute\": () =>\n chartTimeTicks([Date.UTC(2026, 0, 1), Date.UTC(2026, 0, 2)], \"UTC\", { unit: \"hour\", size: 1e-9 }),\n \"time ticks, a zero year step\": () => chartTimeTicks([Date.UTC(2026, 0, 1), Date.UTC(2036, 0, 1)], \"UTC\", { unit: \"year\", size: 0 }),\n \"time ticks, a negative step\": () => chartTimeTicks([Date.UTC(2026, 0, 1), Date.UTC(2026, 0, 2)], \"UTC\", { unit: \"hour\", size: -1 }),\n};\n\nfor (const [name, draw] of Object.entries(cases)) {\n const result = draw();\n console.log(\n JSON.stringify({ name, ...(typeof result === \"string\" ? { svg: result.length, nan: /NaN/.test(result) } : { ticks: result }) }),\n );\n}\nconsole.log(JSON.stringify({ done: Object.keys(cases).length }));\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Conservative proportional-font advances in em, shared by DOM-free SVG label layout.
|
|
2
|
+
* Wide glyphs retain their natural shape; fitting removes whole code points instead of stretching text.
|
|
3
|
+
*/
|
|
4
|
+
export function chartTextWidth(text, size) {
|
|
5
|
+
return Array.from(text).reduce((width, glyph) => width + (/\s/.test(glyph) ? 0.34 : /[ilI.,:;!|'`]/.test(glyph) ? 0.32 : /[MW@%&]/.test(glyph) ? 1 : /[A-Z0-9]/.test(glyph) ? 0.74 : /[a-zäöüßéèáàóúñç()-]/i.test(glyph) ? 0.64 : 1), 0) * size;
|
|
6
|
+
}
|
|
7
|
+
export function fitChartText(text, width, size) {
|
|
8
|
+
if (chartTextWidth(text, size) <= width) return text;
|
|
9
|
+
const glyphs = Array.from(text);
|
|
10
|
+
while (glyphs.length && chartTextWidth(glyphs.join("") + "…", size) > width) glyphs.pop();
|
|
11
|
+
return chartTextWidth("…", size) <= width ? glyphs.join("") + "…" : "";
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["charts/core/text.ts"],"sourcesContent":["/** Conservative proportional-font advances in em, shared by DOM-free SVG label layout.\n * Wide glyphs retain their natural shape; fitting removes whole code points instead of stretching text.\n */\nexport function chartTextWidth(text: string, size: number): number {\n return (\n Array.from(text).reduce(\n (width, glyph) =>\n width +\n (/\\s/.test(glyph)\n ? 0.34\n : /[ilI.,:;!|'`]/.test(glyph)\n ? 0.32\n : /[MW@%&]/.test(glyph)\n ? 1\n : /[A-Z0-9]/.test(glyph)\n ? 0.74\n : /[a-zäöüßéèáàóúñç()-]/i.test(glyph)\n ? 0.64\n : 1),\n 0,\n ) * size\n );\n}\n\nexport function fitChartText(text: string, width: number, size: number): string {\n if (chartTextWidth(text, size) <= width) return text;\n const glyphs = Array.from(text);\n while (glyphs.length && chartTextWidth(glyphs.join(\"\") + \"…\", size) > width) glyphs.pop();\n return chartTextWidth(\"…\", size) <= width ? glyphs.join(\"\") + \"…\" : \"\";\n}\n"],"mappings":"AAAA;AACA;AACA;AACA,OAAO,SAAS,cAAc,CAAC,IAAY,EAAE,IAAY,EAAU;EACjE,OACE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CACrB,CAAC,KAAK,EAAE,KAAK,KACX,KAAK,IACJ,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GACb,IAAI,GACJ,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,GACzB,IAAI,GACJ,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,GACnB,CAAC,GACD,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,GACpB,IAAI,GACJ,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,GACjC,IAAI,GACJ,CAAC,CAAC,EAChB,CACF,CAAC,GAAG,IAAI;AAEZ;AAEA,OAAO,SAAS,YAAY,CAAC,IAAY,EAAE,KAAa,EAAE,IAAY,EAAU;EAC9E,IAAI,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,EAAE,OAAO,IAAI;EACpD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;EAC/B,OAAO,MAAM,CAAC,MAAM,IAAI,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,IAAI,CAAC,GAAG,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;EACzF,OAAO,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,GAAG,EAAE;AACxE","ignoreList":[]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** UI-owned kind union, derived from the renderer registry. */
|
|
2
|
+
|
|
3
|
+
export const chartDatumRoles = ["point", "item", "bin", "box", "outlier", "value", "cell", "interval"];
|
|
4
|
+
|
|
5
|
+
/** Renderer metadata. Anchors use the containing SVG's coordinate space. */
|
|
6
|
+
|
|
7
|
+
/** Serializable number presentation, compatible with the editor's NumberFormat contract. */
|
|
8
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["charts/core/types.ts"],"sourcesContent":["import type { chartRenderers } from \"./registry\";\n\n/** UI-owned kind union, derived from the renderer registry. */\nexport type ChartKind = keyof typeof chartRenderers;\nexport const chartDatumRoles = [\"point\", \"item\", \"bin\", \"box\", \"outlier\", \"value\", \"cell\", \"interval\"] as const;\nexport type ChartDatumRole = (typeof chartDatumRoles)[number];\n\n/** Renderer metadata. Anchors use the containing SVG's coordinate space. */\nexport type ChartDatum = {\n index: number;\n seriesIndex?: number;\n role: ChartDatumRole;\n label?: string;\n anchor: [number, number];\n grid?: [number, number];\n values: { key: string; value: string | number; formatted?: string }[];\n};\n\n/** Serializable number presentation, compatible with the editor's NumberFormat contract. */\nexport type ChartNumberFormat = {\n style?: \"number\" | \"percent\" | \"currency\";\n currency?: string;\n unit?: string;\n decimals?: number;\n compact?: boolean;\n};\nexport type ChartDateFormat = { date: \"day\" | \"minute\" | \"second\" };\nexport type ChartFormat = ChartNumberFormat | ChartDateFormat;\n"],"mappings":"AAEA;;AAEA,OAAO,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAU;;AAG/G;;AAWA","ignoreList":[]}
|
package/dist/ssr/charts.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* SVG themselves, such as server previews and app frames.
|
|
2
|
+
* Drawing helpers and portable chart contracts. Import the Solid Chart component from `@k2b/ui`.
|
|
4
3
|
*/
|
|
4
|
+
|
|
5
|
+
export * from "./charts/core";
|
|
5
6
|
export { barChartLayout, renderBarChartSvg } from "./content/chart-bar";
|
|
7
|
+
export { calendarInspectionNavigation, mountCalendarScroll } from "./content/chart-calendar";
|
|
6
8
|
//# sourceMappingURL=charts.js.map
|
package/dist/ssr/charts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["charts.ts"],"sourcesContent":["/**\n *
|
|
1
|
+
{"version":3,"names":[],"sources":["charts.ts"],"sourcesContent":["/**\n * Drawing helpers and portable chart contracts. Import the Solid Chart component from `@k2b/ui`.\n */\n\nexport * from \"./charts/core\";\nexport type { ChartKindProps, ChartLabels, ChartProps, ChartRenderOptions } from \"./content/Chart\";\nexport { type BarChartLayout, type BarChartOptions, barChartLayout, renderBarChartSvg } from \"./content/chart-bar\";\n\nexport { calendarInspectionNavigation, mountCalendarScroll } from \"./content/chart-calendar\";\n"],"mappings":"AAAA;AACA;AACA;;AAEA,cAAc,eAAe;AAE7B,SAAoD,cAAc,EAAE,iBAAiB,QAAQ,qBAAqB;AAElH,SAAS,4BAA4B,EAAE,mBAAmB,QAAQ,0BAA0B","ignoreList":[]}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { ssr as _$ssr } from "solid-js/web";
|
|
2
|
+
import { createComponent as _$createComponent } from "solid-js/web";
|
|
3
|
+
import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
|
|
4
|
+
import { escape as _$escape } from "solid-js/web";
|
|
5
|
+
var _tmpl$ = ["<p", "><span class=\"k2b-balance__part\">", " <b>", "</b></span><span class=\"k2b-balance__op\" aria-hidden=\"true\">+</span>", "<span class=\"k2b-balance__op\" aria-hidden=\"true\">−</span>", "<span class=\"k2b-balance__op\" aria-hidden=\"true\">=</span><span class=\"k2b-balance__part\">", " <b>", "</b></span></p>"];
|
|
6
|
+
import { useLocale } from "../intl/locale";
|
|
7
|
+
import { useBalanceSummaryMessages } from "./balance-summary-messages";
|
|
8
|
+
import { FlowAmount } from "./FlowAmount";
|
|
9
|
+
/** A movement as an amount; a broken value stays broken, so it shows "—" and never a believable zero. */
|
|
10
|
+
const amount = value => Number.isFinite(value) ? Math.abs(value) : Number.NaN;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* One line from the start of a period to its end: "Start 18,800 € + ↙ 29,260 € − ↗ 29,520 € = End 18,540 €". In and
|
|
14
|
+
* out show their direction with `FlowAmount`; start and end are balances and keep their sign.
|
|
15
|
+
*/
|
|
16
|
+
export function BalanceSummary(props) {
|
|
17
|
+
const locale = useLocale();
|
|
18
|
+
const t = useBalanceSummaryMessages(() => props.locale);
|
|
19
|
+
const lang = () => props.locale ?? locale();
|
|
20
|
+
const start = () => props.start;
|
|
21
|
+
const end = () => start() + amount(props.in) - amount(props.out);
|
|
22
|
+
// Whole amounts read best, but the line is an equation: when the rounded parts would not add up, show cents.
|
|
23
|
+
const decimals = () => {
|
|
24
|
+
if (props.decimals !== undefined) return props.decimals;
|
|
25
|
+
const whole = value => Math.round(value);
|
|
26
|
+
const parts = [start(), amount(props.in), amount(props.out)];
|
|
27
|
+
if (!parts.every(Number.isFinite)) return 0;
|
|
28
|
+
return whole(start()) + whole(amount(props.in)) - whole(amount(props.out)) === whole(end()) ? 0 : 2;
|
|
29
|
+
};
|
|
30
|
+
const balance = value => !Number.isFinite(value) ? "—" : new Intl.NumberFormat(lang(), {
|
|
31
|
+
style: "currency",
|
|
32
|
+
currency: props.currency,
|
|
33
|
+
minimumFractionDigits: decimals(),
|
|
34
|
+
maximumFractionDigits: decimals()
|
|
35
|
+
}).format(value === 0 ? 0 : value);
|
|
36
|
+
return _$ssr(_tmpl$, _$ssrAttribute("class", props.class ? `k2b-balance ${_$escape(props.class, true)}` : "k2b-balance", false), _$escape(props.labels?.start ?? t().start), _$escape(balance(start())), _$escape(_$createComponent(FlowAmount, {
|
|
37
|
+
get value() {
|
|
38
|
+
return amount(props.in);
|
|
39
|
+
},
|
|
40
|
+
get currency() {
|
|
41
|
+
return props.currency;
|
|
42
|
+
},
|
|
43
|
+
get locale() {
|
|
44
|
+
return lang();
|
|
45
|
+
},
|
|
46
|
+
get decimals() {
|
|
47
|
+
return decimals();
|
|
48
|
+
},
|
|
49
|
+
get labels() {
|
|
50
|
+
return {
|
|
51
|
+
in: props.labels?.in ?? t().in
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
})), _$escape(_$createComponent(FlowAmount, {
|
|
55
|
+
get value() {
|
|
56
|
+
return -amount(props.out);
|
|
57
|
+
},
|
|
58
|
+
get currency() {
|
|
59
|
+
return props.currency;
|
|
60
|
+
},
|
|
61
|
+
get locale() {
|
|
62
|
+
return lang();
|
|
63
|
+
},
|
|
64
|
+
get decimals() {
|
|
65
|
+
return decimals();
|
|
66
|
+
},
|
|
67
|
+
get labels() {
|
|
68
|
+
return {
|
|
69
|
+
out: props.labels?.out ?? t().out
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
})), _$escape(props.labels?.end ?? t().end), _$escape(balance(end())));
|
|
73
|
+
}
|
|
74
|
+
export default BalanceSummary;
|
|
75
|
+
//# sourceMappingURL=BalanceSummary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["content/BalanceSummary.tsx"],"sourcesContent":["import type { JSX } from \"solid-js\";\nimport { useLocale } from \"../intl/locale\";\nimport { useBalanceSummaryMessages } from \"./balance-summary-messages\";\nimport { FlowAmount } from \"./FlowAmount\";\n\nexport type BalanceSummaryProps = {\n /** The balance at the start of the period. */\n start: number;\n /** Money that came in during the period, as an amount (the sign is ignored). */\n in: number;\n /** Money that went out during the period, as an amount (the sign is ignored). */\n out: number;\n /** ISO 4217 currency code, e.g. `\"EUR\"`. */\n currency: string;\n /** Explicit locale override; defaults to the inherited render locale. */\n locale?: string;\n /** Fixed fraction digits. Defaults to whole amounts, or cents when whole amounts would not add up. */\n decimals?: number;\n /** Replaces the words \"Start\", \"End\", \"in\" and \"out\". */\n labels?: { start?: string; end?: string; in?: string; out?: string };\n class?: string;\n};\n\n/** A movement as an amount; a broken value stays broken, so it shows \"—\" and never a believable zero. */\nconst amount = (value: number) => (Number.isFinite(value) ? Math.abs(value) : Number.NaN);\n\n/**\n * One line from the start of a period to its end: \"Start 18,800 € + ↙ 29,260 € − ↗ 29,520 € = End 18,540 €\". In and\n * out show their direction with `FlowAmount`; start and end are balances and keep their sign.\n */\nexport function BalanceSummary(props: BalanceSummaryProps): JSX.Element {\n const locale = useLocale();\n const t = useBalanceSummaryMessages(() => props.locale);\n const lang = () => props.locale ?? locale();\n const start = () => props.start;\n const end = () => start() + amount(props.in) - amount(props.out);\n // Whole amounts read best, but the line is an equation: when the rounded parts would not add up, show cents.\n const decimals = () => {\n if (props.decimals !== undefined) return props.decimals;\n const whole = (value: number) => Math.round(value);\n const parts = [start(), amount(props.in), amount(props.out)];\n if (!parts.every(Number.isFinite)) return 0;\n return whole(start()) + whole(amount(props.in)) - whole(amount(props.out)) === whole(end()) ? 0 : 2;\n };\n const balance = (value: number) =>\n !Number.isFinite(value)\n ? \"—\"\n : new Intl.NumberFormat(lang(), {\n style: \"currency\",\n currency: props.currency,\n minimumFractionDigits: decimals(),\n maximumFractionDigits: decimals(),\n }).format(value === 0 ? 0 : value);\n return (\n <p class={props.class ? `k2b-balance ${props.class}` : \"k2b-balance\"}>\n <span class=\"k2b-balance__part\">\n {props.labels?.start ?? t().start} <b>{balance(start())}</b>\n </span>\n <span class=\"k2b-balance__op\" aria-hidden=\"true\">\n +\n </span>\n <FlowAmount\n value={amount(props.in)}\n currency={props.currency}\n locale={lang()}\n decimals={decimals()}\n labels={{ in: props.labels?.in ?? t().in }}\n />\n <span class=\"k2b-balance__op\" aria-hidden=\"true\">\n −\n </span>\n <FlowAmount\n value={-amount(props.out)}\n currency={props.currency}\n locale={lang()}\n decimals={decimals()}\n labels={{ out: props.labels?.out ?? t().out }}\n />\n <span class=\"k2b-balance__op\" aria-hidden=\"true\">\n =\n </span>\n <span class=\"k2b-balance__part\">\n {props.labels?.end ?? t().end} <b>{balance(end())}</b>\n </span>\n </p>\n );\n}\n\nexport default BalanceSummary;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -9,26 +9,28 @@ var _tmpl$ = ["<i class=\"", "\" aria-hidden=\"true\"></i>"],
|
|
|
9
9
|
_tmpl$3 = ["<div class=\"k2b-chart__controls\">", "", "", "</div>"],
|
|
10
10
|
_tmpl$4 = ["<div class=\"", "\"", " data-interactive=\"true\" style=\"", "\" role=\"group\"", " tabindex=\"0\">", "<div class=\"k2b-chart__svg\"", " style=\"", "\">", "</div><span class=\"k2b-chart__anchor\" aria-hidden=\"true\"></span><span", " role=\"tooltip\" popover=\"manual\" data-instant=\"true\" class=\"k2b-tooltip k2b-chart__tooltip\"></span>", "</div>"],
|
|
11
11
|
_tmpl$5 = ["<div class=\"", "\" style=\"", "\">", "</div>"],
|
|
12
|
-
_tmpl$6 = ["<
|
|
13
|
-
|
|
14
|
-
import { createEffect, createMemo, createSignal, createUniqueId, For, onCleanup, onMount, Show, splitProps, untrack } from "solid-js";
|
|
12
|
+
_tmpl$6 = ["<b data-chart-legend-value", ">", "</b>"],
|
|
13
|
+
_tmpl$7 = ["<span class=\"k2b-chart__legend-item\"><svg class=\"", "\" viewBox=\"0 0 10 10\" width=\"10\" height=\"10\" aria-hidden=\"true\"><rect x=\"1\" y=\"1\" width=\"8\" height=\"8\" rx=\"2\" class=\"", "\" fill=\"", "\" stroke=\"none\"></rect></svg><span>", "</span>", "</span>"];
|
|
14
|
+
import { createEffect, createMemo, createSignal, createUniqueId, For, mergeProps, onCleanup, onMount, Show, splitProps, untrack } from "solid-js";
|
|
15
15
|
import { isServer } from "solid-js/web";
|
|
16
16
|
import { IconButton } from "../actions/Button";
|
|
17
|
+
import { calendarLayout } from "../charts/core/calendar";
|
|
18
|
+
import { chartKinds } from "../charts/core/registry";
|
|
19
|
+
import { chartRenderHeight, preservesAspectRatio, renderChartSvg } from "../charts/core/render";
|
|
17
20
|
import { suppressTextSelection } from "../internal/text-selection";
|
|
18
21
|
import { useLocale } from "../intl/locale";
|
|
19
22
|
import { useUiMessages } from "../intl/messages";
|
|
20
|
-
import {
|
|
23
|
+
import { calendarInspectionNavigation, mountCalendarScroll } from "./chart-calendar";
|
|
21
24
|
import { createChartInspection } from "./chart-inspection";
|
|
22
25
|
import { closeChartInspectionOnOutside } from "./chart-inspection-core";
|
|
23
|
-
import { lineGapsSvg } from "./chart-line-gaps";
|
|
24
26
|
import { DEFAULT_MAP_VIEWPORT, normalizeMapViewport, panMapViewport, zoomMapViewport } from "./chart-map-viewport";
|
|
25
|
-
import { useChartMessages } from "./chart-messages";
|
|
26
|
-
import { panStateTimelineViewport,
|
|
27
|
-
import {
|
|
27
|
+
import { resolveChartMessages, useChartMessages } from "./chart-messages";
|
|
28
|
+
import { panStateTimelineViewport, stateTimelineDomain, stateTimelineHeight, zoomStateTimelineViewport } from "./chart-state-timeline";
|
|
29
|
+
import { selectedChartSvg } from "./chart-svg";
|
|
28
30
|
import { useViewportMessages } from "./viewport-messages";
|
|
29
31
|
|
|
30
32
|
/**
|
|
31
|
-
* Chart —
|
|
33
|
+
* Chart — Solid interaction and sizing around the portable UI chart core.
|
|
32
34
|
*
|
|
33
35
|
* **Live-update story.** `charts.<kind>(opts)` returns an SVG string;
|
|
34
36
|
* Solid's `innerHTML` is reactive, so any time a prop (signal, store
|
|
@@ -46,15 +48,15 @@ import { useViewportMessages } from "./viewport-messages";
|
|
|
46
48
|
* from the row count and legend via `stateTimelineHeight()`.
|
|
47
49
|
*
|
|
48
50
|
* **Why so thin.** The props are a discriminated union over each
|
|
49
|
-
*
|
|
51
|
+
* registered core chart renderer — `kind: "line"` brings in exactly the params
|
|
50
52
|
* `charts.line` expects, `kind: "bar"` brings in `charts.bar`'s, etc.
|
|
51
|
-
* Options stay aligned with
|
|
53
|
+
* Options stay aligned with the core renderer without renaming. Every chart provides
|
|
52
54
|
* renderer-owned inspection, tooltips and optional selection by default.
|
|
53
55
|
* `interactive` adds bounded pan / zoom and reset controls to maps and state timelines.
|
|
54
|
-
*
|
|
56
|
+
* When a core renderer gains an option, it is automatically available at every
|
|
55
57
|
* callsite.
|
|
56
58
|
*
|
|
57
|
-
* **Theming.**
|
|
59
|
+
* **Theming.** The core renderers use `currentColor` for axes / ticks /
|
|
58
60
|
* tick labels — set the wrapping element's `color` and everything
|
|
59
61
|
* inherits. Series colors come from `--stdlib-chart-c1..c8` CSS
|
|
60
62
|
* custom properties; override on the parent for per-chart palettes.
|
|
@@ -72,7 +74,7 @@ import { useViewportMessages } from "./viewport-messages";
|
|
|
72
74
|
* ```
|
|
73
75
|
*/
|
|
74
76
|
|
|
75
|
-
/** All chart kinds
|
|
77
|
+
/** All registered chart kinds. */
|
|
76
78
|
|
|
77
79
|
/**
|
|
78
80
|
* Per-kind props: `kind` discriminator + the exact options that
|
|
@@ -82,80 +84,14 @@ import { useViewportMessages } from "./viewport-messages";
|
|
|
82
84
|
* get full type safety.
|
|
83
85
|
*/
|
|
84
86
|
|
|
85
|
-
|
|
87
|
+
export { chartRenderHeight, renderChartSvg } from "../charts/core/render";
|
|
86
88
|
|
|
87
|
-
/**
|
|
88
|
-
export const chartRenderHeight = props => {
|
|
89
|
-
if (props.kind === "stateTimeline") return stateTimelineHeight(props.rows.length, props.legend !== false);
|
|
90
|
-
if (props.kind === "bar") return barChartLayout(props).height;
|
|
91
|
-
if (props.kind === "barGauge") return Math.max(280, (props.title || props.subtitle ? 42 : 16) + props.data.length * 28 + 14);
|
|
92
|
-
return 280;
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Internal — strips wrapper-only keys from props and forwards the
|
|
97
|
-
* rest (plus logical size) to `charts[kind]`. The `any` is the
|
|
98
|
-
* price for dispatching one function call across 14 different option
|
|
99
|
-
* types; an explicit per-kind switch would type it but balloon the
|
|
100
|
-
* component for no runtime benefit.
|
|
101
|
-
*/
|
|
102
|
-
export const renderChartSvg = (props, width, height, mapViewport, timelineViewport) => {
|
|
103
|
-
const {
|
|
104
|
-
kind,
|
|
105
|
-
class: _class,
|
|
106
|
-
style: _style,
|
|
107
|
-
labels: _labels,
|
|
108
|
-
interactive: _interactive,
|
|
109
|
-
onSelect: _onSelect,
|
|
110
|
-
selected: _selected,
|
|
111
|
-
tooltip: _tooltip,
|
|
112
|
-
cursor: _cursor,
|
|
113
|
-
zoomFocus: _zoomFocus,
|
|
114
|
-
legendPlacement: _legendPlacement,
|
|
115
|
-
...opts
|
|
116
|
-
} = props;
|
|
117
|
-
if (kind === "stateTimeline") {
|
|
118
|
-
return responsiveChartSvg(renderStateTimelineSvg({
|
|
119
|
-
...opts,
|
|
120
|
-
width,
|
|
121
|
-
height,
|
|
122
|
-
viewport: timelineViewport,
|
|
123
|
-
interactive: true
|
|
124
|
-
}));
|
|
125
|
-
}
|
|
126
|
-
if (kind === "bar") return responsiveChartSvg(renderBarChartSvg({
|
|
127
|
-
...opts,
|
|
128
|
-
width,
|
|
129
|
-
height,
|
|
130
|
-
inspect: true
|
|
131
|
-
}));
|
|
132
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
133
|
-
let svg = charts[kind]({
|
|
134
|
-
...opts,
|
|
135
|
-
...(props.kind === "line" && props.legend && props.legendPlacement === "top-start" ? {
|
|
136
|
-
legend: false
|
|
137
|
-
} : {}),
|
|
138
|
-
...(kind === "map" ? {
|
|
139
|
-
viewport: DEFAULT_MAP_VIEWPORT
|
|
140
|
-
} : {}),
|
|
141
|
-
width,
|
|
142
|
-
height,
|
|
143
|
-
inspect: true
|
|
144
|
-
});
|
|
145
|
-
if (props.kind === "line" && props.maxGap !== undefined) {
|
|
146
|
-
if (props.area || props.errorBand) throw new Error("Chart maxGap does not support area or errorBand fills");
|
|
147
|
-
svg = lineGapsSvg(svg, props.maxGap, props);
|
|
148
|
-
}
|
|
149
|
-
if (props.kind === "map") return responsiveMapSvg(svg, width, height, normalizeMapViewport(mapViewport ?? props.viewport));
|
|
150
|
-
return preservesAspectRatio(kind) ? svg : responsiveChartSvg(svg);
|
|
151
|
-
};
|
|
152
|
-
const preservesAspectRatio = kind => kind === "map" || kind === "pie" || kind === "donut" || kind === "gauge";
|
|
153
|
-
|
|
154
|
-
/** Empty-data short-circuit. Kept per-kind because stdlib's payload
|
|
89
|
+
/** Empty-data short-circuit. Kept per-kind because each renderer's payload
|
|
155
90
|
* key differs (series vs data vs groups). We're conservative: only
|
|
156
91
|
* block on truly empty inputs; partially-filled series get rendered
|
|
157
|
-
* as-is and
|
|
92
|
+
* as-is and the core handles the gaps. */
|
|
158
93
|
const isEmpty = props => {
|
|
94
|
+
if (props.kind === "area") return !props.x.length || !props.series.length || props.x.every((_, i) => props.series.some(s => s.data[i] === null) || props.normalize && props.series.every(s => s.data[i] === 0));
|
|
159
95
|
if (props.kind === "line" || props.kind === "scatter") {
|
|
160
96
|
return !props.series?.length || props.series.every(s => !s.data.length);
|
|
161
97
|
}
|
|
@@ -173,8 +109,8 @@ const isEmpty = props => {
|
|
|
173
109
|
}
|
|
174
110
|
return false;
|
|
175
111
|
};
|
|
176
|
-
const
|
|
177
|
-
const [, drawingProps] = splitProps(props, ["selected", "onSelect", "tooltip", "cursor"]);
|
|
112
|
+
const ChartRoot = props => {
|
|
113
|
+
const [, drawingProps] = splitProps(props, ["class", "style", "labels", "interactive", "selected", "onSelect", "tooltip", "cursor"]);
|
|
178
114
|
const messages = useUiMessages();
|
|
179
115
|
const chartMessages = useChartMessages();
|
|
180
116
|
const viewportMessages = useViewportMessages();
|
|
@@ -184,12 +120,31 @@ const Chart = props => {
|
|
|
184
120
|
let lineAnchorRef;
|
|
185
121
|
// One deterministic coordinate space on the server and client. CSS fits the
|
|
186
122
|
// SVG to its box; hydration must never replace it with measured geometry.
|
|
123
|
+
const calendar = () => props.kind === "heatmap" && props.layout === "calendar" ? calendarLayout({
|
|
124
|
+
...props,
|
|
125
|
+
locale: props.locale ?? locale()
|
|
126
|
+
}) : undefined;
|
|
187
127
|
const size = () => ({
|
|
188
|
-
width: 480,
|
|
128
|
+
width: calendar()?.width ?? 480,
|
|
189
129
|
height: chartRenderHeight(props)
|
|
190
130
|
});
|
|
191
|
-
const topLegend = () => props.kind === "line" && props.legend === true && props.legendPlacement === "top-start";
|
|
192
|
-
const legendSeries = () => props.kind === "line" ? props.series : [];
|
|
131
|
+
const topLegend = () => props.kind === "area" ? props.legend !== false : props.kind === "line" && props.legend === true && props.legendPlacement === "top-start";
|
|
132
|
+
const legendSeries = () => props.kind === "line" || props.kind === "area" ? props.series : [];
|
|
133
|
+
const legendValue = index => {
|
|
134
|
+
if (props.kind !== "area") return "";
|
|
135
|
+
const last = props.x.length - 1;
|
|
136
|
+
const amount = props.series[index]?.data[last];
|
|
137
|
+
const values = props.series.map(s => s.data[last]);
|
|
138
|
+
const total = values.reduce((sum, value) => sum + (value ?? 0), 0);
|
|
139
|
+
if (amount == null || values.some(v => v == null) || props.normalize && total === 0) return "—";
|
|
140
|
+
return props.normalize ? new Intl.NumberFormat(locale(), {
|
|
141
|
+
style: "percent",
|
|
142
|
+
minimumFractionDigits: 1,
|
|
143
|
+
maximumFractionDigits: 1
|
|
144
|
+
}).format(amount / total) : props.format?.(amount) ?? new Intl.NumberFormat(locale(), {
|
|
145
|
+
maximumFractionDigits: 2
|
|
146
|
+
}).format(amount);
|
|
147
|
+
};
|
|
193
148
|
const dimensions = () => containerRef?.getBoundingClientRect() ?? size();
|
|
194
149
|
const initialMapViewport = props.kind === "map" ? normalizeMapViewport(props.viewport) : DEFAULT_MAP_VIEWPORT;
|
|
195
150
|
const [mapViewport, setMapViewport] = createSignal(initialMapViewport);
|
|
@@ -326,6 +281,7 @@ const Chart = props => {
|
|
|
326
281
|
pointerFrame = requestAnimationFrame(flushPointerMove);
|
|
327
282
|
};
|
|
328
283
|
const stopDragging = event => {
|
|
284
|
+
inspection.up();
|
|
329
285
|
if (pendingPointer?.pointerId === event.pointerId) flushPointerMove();
|
|
330
286
|
if (timelineDrag?.pointerId === event.pointerId) {
|
|
331
287
|
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
@@ -395,22 +351,35 @@ const Chart = props => {
|
|
|
395
351
|
};
|
|
396
352
|
const inspection = createChartInspection({
|
|
397
353
|
container: () => containerRef,
|
|
354
|
+
locale,
|
|
398
355
|
cursor: () => props.cursor,
|
|
399
356
|
tooltip: () => chartTooltipRef,
|
|
400
357
|
anchor: () => lineAnchorRef,
|
|
401
358
|
kind: () => props.kind,
|
|
359
|
+
nav: () => props.kind === "heatmap" && props.layout === "calendar" ? calendarInspectionNavigation : undefined,
|
|
402
360
|
enabled: () => !isEmpty(props),
|
|
403
361
|
select: selection => props.onSelect?.(selection),
|
|
404
362
|
format: selection => {
|
|
405
363
|
if (props.tooltip) return props.tooltip(selection);
|
|
406
|
-
const fields = chartMessages().chartFields;
|
|
364
|
+
const fields = props.kind === "heatmap" && props.layout === "calendar" ? resolveChartMessages(props.locale ?? locale()).chartFields : chartMessages().chartFields;
|
|
365
|
+
if (selection.kind === "area" && props.kind === "area") {
|
|
366
|
+
const amount = selection.datum.values.find(f => f.key === "value");
|
|
367
|
+
const share = selection.datum.values.find(f => f.key === "percent");
|
|
368
|
+
return {
|
|
369
|
+
title: selection.datum.values.find(f => f.key === "x")?.formatted ?? "",
|
|
370
|
+
rows: [{
|
|
371
|
+
label: selection.datum.label ?? chartMessages().series,
|
|
372
|
+
value: `${share ? `${share.formatted} · ` : ""}${amount.formatted}`
|
|
373
|
+
}]
|
|
374
|
+
};
|
|
375
|
+
}
|
|
407
376
|
const format = new Intl.NumberFormat(locale(), {
|
|
408
377
|
maximumFractionDigits: 6
|
|
409
378
|
});
|
|
410
379
|
return {
|
|
411
380
|
title: selection.datum.label ?? (selection.datum.seriesIndex !== undefined ? `${labels().series ?? chartMessages().series} ${selection.datum.seriesIndex + 1}` : undefined),
|
|
412
381
|
rows: selection.datum.values.map(field => ({
|
|
413
|
-
label: selection.kind === "line" && field.key === "y" ? selection.datum.label ?? labels().series ?? chartMessages().series : fields({
|
|
382
|
+
label: props.kind === "heatmap" && props.layout === "calendar" && field.key === "value" && props.label ? props.label : selection.kind === "line" && field.key === "y" ? selection.datum.label ?? labels().series ?? chartMessages().series : fields({
|
|
414
383
|
key: field.key
|
|
415
384
|
}),
|
|
416
385
|
value: field.formatted ?? (field.key === "upperInclusive" ? field.value === "true" ? messages().yes : messages().no : typeof field.value === "number" ? `${format.format(field.value)}${field.key === "percent" ? "%" : ""}` : field.value)
|
|
@@ -419,7 +388,10 @@ const Chart = props => {
|
|
|
419
388
|
}
|
|
420
389
|
});
|
|
421
390
|
const closeChartTooltip = () => inspection.close();
|
|
422
|
-
const svgMarkup = createMemo(() => renderChartSvg(
|
|
391
|
+
const svgMarkup = createMemo(() => renderChartSvg(props.kind === "heatmap" && props.layout === "calendar" ? {
|
|
392
|
+
...props,
|
|
393
|
+
locale: props.locale ?? locale()
|
|
394
|
+
} : drawingProps, size().width, size().height, interactiveMap() ? mapViewport() : undefined, interactiveTimeline() ? timelineViewport() : undefined, locale()));
|
|
423
395
|
createEffect(() => {
|
|
424
396
|
svgMarkup();
|
|
425
397
|
inspection.invalidate();
|
|
@@ -434,10 +406,12 @@ const Chart = props => {
|
|
|
434
406
|
});
|
|
435
407
|
onMount(() => {
|
|
436
408
|
if (!containerRef) return;
|
|
409
|
+
if (props.kind === "heatmap" && props.layout === "calendar") onCleanup(mountCalendarScroll(containerRef));
|
|
437
410
|
onCleanup(closeChartInspectionOnOutside({
|
|
438
411
|
container: () => containerRef,
|
|
439
412
|
tooltip: () => chartTooltipRef,
|
|
440
|
-
close: closeChartTooltip
|
|
413
|
+
close: closeChartTooltip,
|
|
414
|
+
keepScroll: () => props.kind === "heatmap" && props.layout === "calendar"
|
|
441
415
|
}));
|
|
442
416
|
});
|
|
443
417
|
const chartStyle = () => props.style ?? (props.kind === "stateTimeline" ? {
|
|
@@ -469,10 +443,17 @@ const Chart = props => {
|
|
|
469
443
|
get each() {
|
|
470
444
|
return legendSeries();
|
|
471
445
|
},
|
|
472
|
-
children: (series, index) => _$ssr(_tmpl$
|
|
446
|
+
children: (series, index) => _$ssr(_tmpl$7, `stdlib-chart k2b-chart__legend-swatch ${props.kind === "line" ? _$escape(props.className ?? "", true) : ""}`, `stdlib-chart-series-${_$escape(index(), true) % 8}`, `var(--stdlib-chart-c${_$escape(index(), true) % 8 + 1}, ${_$escape(["#2563eb", "#16a34a", "#d97706", "#dc2626", "#a855f7", "#0891b2", "#db2777", "#65a30d"][index() % 8], true)})`, series.label && series.label.length > 0 ? _$escape(series.label) : `${_$escape(chartMessages().series)} ${_$escape(index()) + 1}`, _$escape(_$createComponent(Show, {
|
|
447
|
+
get when() {
|
|
448
|
+
return props.kind === "area";
|
|
449
|
+
},
|
|
450
|
+
get children() {
|
|
451
|
+
return _$ssr(_tmpl$6, _$ssrAttribute("data-series-index", _$escape(index(), true), false) + _$ssrAttribute("data-field", props.kind === "area" && props.normalize ? "percent" : "value", false) + _$ssrAttribute("data-default", _$escape(legendValue(index()), true), false), _$escape(legendValue(index())));
|
|
452
|
+
}
|
|
453
|
+
})))
|
|
473
454
|
})));
|
|
474
455
|
}
|
|
475
|
-
})), _$ssrAttribute("data-stretch", !preservesAspectRatio(props.kind) ? "true" : _$escape(undefined, true), false), _$ssrStyleProperty("
|
|
456
|
+
})), _$ssrAttribute("data-stretch", !calendar() && !preservesAspectRatio(props.kind) ? "true" : _$escape(undefined, true), false), _$ssrStyleProperty("min-width:", calendar() ? `${_$escape(calendar().minWidth, true)}px` : _$escape(undefined, true)) + _$ssrStyleProperty(";--k2b-chart-width:", `${_$escape(size().width, true)}px`) + _$ssrStyleProperty(";--k2b-chart-height:", `${_$escape(size().height, true)}px`) + _$ssrStyleProperty(";aspect-ratio:", `${_$escape(size().width, true)} / ${_$escape(size().height, true)}`), isServer ? selectedChartSvg(svgMarkup(), props.selected) : svgMarkup(), _$ssrAttribute("id", _$escape(chartTooltipId, true), false), _$escape(_$createComponent(Show, {
|
|
476
457
|
get when() {
|
|
477
458
|
return draggable();
|
|
478
459
|
},
|
|
@@ -483,5 +464,19 @@ const Chart = props => {
|
|
|
483
464
|
}
|
|
484
465
|
});
|
|
485
466
|
};
|
|
467
|
+
// Add a renderer to charts/core/registry.ts; its key defines the namespace member and discriminator.
|
|
468
|
+
// Both entry styles share ChartRoot, preserving the same owner, markup and reactive props.
|
|
469
|
+
const chartComponent = kind => props =>
|
|
470
|
+
// Public namespace types correlate each discriminator with its options.
|
|
471
|
+
ChartRoot(mergeProps(props, {
|
|
472
|
+
kind
|
|
473
|
+
}));
|
|
474
|
+
const components = Object.fromEntries(Object.entries(chartKinds).map(([name, kind]) => [name, chartComponent(kind)]));
|
|
475
|
+
const Chart = Object.assign(ChartRoot, components, {
|
|
476
|
+
Calendar: props => ChartRoot(mergeProps(props, {
|
|
477
|
+
kind: "heatmap",
|
|
478
|
+
layout: "calendar"
|
|
479
|
+
}))
|
|
480
|
+
});
|
|
486
481
|
export default Chart;
|
|
487
482
|
//# sourceMappingURL=Chart.js.map
|