@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
package/dist/base.css
CHANGED
|
@@ -35,6 +35,14 @@
|
|
|
35
35
|
--stdlib-chart-c6: #06b6d4;
|
|
36
36
|
--stdlib-chart-c7: #84cc16;
|
|
37
37
|
--stdlib-chart-c8: #f97316;
|
|
38
|
+
/* Money with a direction, as in the full stylesheet: turquoise comes in, violet goes out. */
|
|
39
|
+
--k2b-flow-in-text: light-dark(#0e7490, #67e8f9);
|
|
40
|
+
--k2b-flow-in-surface: light-dark(#ecfeff, rgb(8 51 68 / 0.55));
|
|
41
|
+
--k2b-flow-in-ring: light-dark(#a5f3fc, #155e75);
|
|
42
|
+
--k2b-flow-in-mark: light-dark(#0891b2, #22d3ee);
|
|
43
|
+
--k2b-flow-out-text: light-dark(#6d28d9, #c4b5fd);
|
|
44
|
+
--k2b-flow-out-surface: light-dark(#f5f3ff, rgb(46 16 101 / 0.55));
|
|
45
|
+
--k2b-flow-out-mark: light-dark(#8b5cf6, #a78bfa);
|
|
38
46
|
|
|
39
47
|
--k2b-surface: light-dark(#ffffff, #11151b);
|
|
40
48
|
--k2b-surface-canvas: light-dark(#fafafa, #090d12);
|
|
@@ -1070,11 +1078,37 @@
|
|
|
1070
1078
|
pointer-events: none;
|
|
1071
1079
|
}
|
|
1072
1080
|
|
|
1073
|
-
|
|
1081
|
+
/* Calm hover: nothing else dims. A single mark gets a thin outline; a column or row of a category chart gets a
|
|
1082
|
+
light band behind it instead (data-inspecting="category"). */
|
|
1083
|
+
.k2b-chart:not([data-chart-kind="bar"], [data-chart-kind="histogram"], [data-chart-kind="boxplot"]) [data-inspected]:not([data-chart-role="value"]) > :is(rect, path, circle) {
|
|
1074
1084
|
stroke: var(--k2b-chart-inspection-color);
|
|
1075
|
-
stroke-width: 2px;
|
|
1076
1085
|
vector-effect: non-scaling-stroke;
|
|
1077
1086
|
}
|
|
1087
|
+
.k2b-chart:not([data-chart-kind="bar"], [data-chart-kind="histogram"], [data-chart-kind="boxplot"]) [data-inspected]:not([data-chart-role="value"]) > :is(rect, path) {
|
|
1088
|
+
stroke-width: 1.5px;
|
|
1089
|
+
}
|
|
1090
|
+
/* Points keep a 2 px ring: a tiny point is hit through its stroke, so a thinner ring would let the drawing take the pointer. */
|
|
1091
|
+
.k2b-chart:not([data-chart-kind="bar"], [data-chart-kind="histogram"], [data-chart-kind="boxplot"]) [data-inspected]:not([data-chart-role="value"]) > circle {
|
|
1092
|
+
stroke-width: 2px;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
/* The band sits behind the marks without positioning the drawing, which would change what lies on top. */
|
|
1096
|
+
.k2b-chart[data-inspecting="category"] {
|
|
1097
|
+
isolation: isolate;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
.k2b-chart[data-inspecting="category"]::before {
|
|
1101
|
+
content: "";
|
|
1102
|
+
position: absolute;
|
|
1103
|
+
left: var(--k2b-chart-band-left);
|
|
1104
|
+
top: var(--k2b-chart-band-top);
|
|
1105
|
+
width: var(--k2b-chart-band-width);
|
|
1106
|
+
height: var(--k2b-chart-band-height);
|
|
1107
|
+
z-index: -1;
|
|
1108
|
+
border-radius: 3px;
|
|
1109
|
+
background: color-mix(in srgb, currentColor 7%, transparent);
|
|
1110
|
+
pointer-events: none;
|
|
1111
|
+
}
|
|
1078
1112
|
|
|
1079
1113
|
.k2b-chart [data-inspected] > .stdlib-chart-inspection-point {
|
|
1080
1114
|
fill: var(--k2b-chart-inspection-color);
|
|
@@ -1277,3 +1311,7 @@
|
|
|
1277
1311
|
}
|
|
1278
1312
|
}
|
|
1279
1313
|
}
|
|
1314
|
+
|
|
1315
|
+
@layer k2b-base {
|
|
1316
|
+
.k2b-chart[data-chart-kind="area"] [data-selected] > .k2b-area-inspection-point { opacity: 1; stroke-width: 1.5px; }
|
|
1317
|
+
}
|
|
@@ -110,6 +110,9 @@ export function ContextMenuBase(props) {
|
|
|
110
110
|
const close = () => {
|
|
111
111
|
detachOpenListeners();
|
|
112
112
|
if (!isOpen()) return;
|
|
113
|
+
// An activated entry closes the menu before its action runs: focus goes back to where the menu opened from, as
|
|
114
|
+
// Escape returns it, so the keyboard never lands on the page body.
|
|
115
|
+
if (menu?.contains(document.activeElement)) returnFocus(opener?.isConnected ? opener : host, hostRing);
|
|
113
116
|
setPosition();
|
|
114
117
|
if (closeActiveContextMenu === close) closeActiveContextMenu = undefined;
|
|
115
118
|
props.onClose?.();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["actions/ContextMenu.tsx"],"sourcesContent":["import { createMemo, createSignal, createUniqueId, type JSX, onCleanup, onMount, Show } from \"solid-js\";\nimport { Portal } from \"solid-js/web\";\nimport { returnFocus, ringOnReturn } from \"../internal/focus-return\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { type DropdownItem, DropdownItems, type DropdownPosition, dropdownPosition } from \"./Dropdown\";\nimport { focusRowSegment } from \"./menu-rows\";\n\nexport type ContextMenuProps = {\n items: readonly DropdownItem[];\n children: JSX.Element;\n class?: string | ((isOpen: boolean) => string);\n /** Tab order of the context-menu host. Descendant-focused composite widgets use -1. */\n tabIndex?: number;\n disabled?: boolean;\n onClose?: () => void;\n onOpen?: () => void;\n id?: string;\n label?: string;\n /**\n * Links, form fields, editable text, and selected text inside the host keep the browser's own menu, with its Copy,\n * Paste, and Open link. Use it where the host wraps readable content rather than one row.\n */\n keepNativeMenu?: boolean;\n};\n\nconst NATIVE_MENU_TARGETS = \"a[href], input, textarea, select, [contenteditable]:not([contenteditable='false'])\";\n\nlet closeActiveContextMenu: (() => void) | undefined;\n\nconst focusableItems = (menu: HTMLElement | undefined): HTMLElement[] =>\n menu\n ? Array.from(\n menu.querySelectorAll<HTMLElement>(\n [\n \"[role='menuitem']:not([aria-disabled='true'])\",\n \"[role='menuitemcheckbox']:not([aria-disabled='true'])\",\n \"[role='menuitemradio']:not([aria-disabled='true'])\",\n ].join(\", \"),\n ),\n )\n : [];\n\n/** Right-click menu with keyboard invocation, one-open-at-a-time behavior, and viewport clamping. */\nexport function ContextMenu(props: ContextMenuProps): JSX.Element {\n return ContextMenuBase(props);\n}\n\n/**\n * Package-internal, not exported from the package index: `openAt` lets GestureMenu open the menu at a held finger, and\n * `title` names what was pressed above the entries, since the finger covers it.\n */\nexport function ContextMenuBase(\n props: ContextMenuProps & {\n openAt?: (open: (x: number, y: number) => void) => void;\n title?: string;\n closeWith?: (close: () => void) => void;\n },\n): JSX.Element {\n const messages = useUiMessages();\n const generatedId = `k2b-context-${createUniqueId()}`;\n const menuId = `${generatedId}-menu`;\n const [position, setPosition] = createSignal<{ x: number; y: number }>();\n let host: HTMLDivElement | undefined;\n let menu: HTMLDivElement | undefined;\n let listenersAttached = false;\n let hostRing = true;\n /** The element inside the host that had focus as the menu opened, such as a row or a day of a composite widget. */\n let opener: HTMLElement | undefined;\n let anchor = { x: 0, y: 0 };\n let viewport = { width: 0, height: 0 };\n let resizeObserver: ResizeObserver | undefined;\n\n const isOpen = () => position() !== undefined;\n const keepsNativeMenu = (target: EventTarget | null): boolean => {\n if (!props.keepNativeMenu || !(target instanceof Node)) return false;\n const element = target instanceof Element ? target : target.parentElement;\n const native = element?.closest(NATIVE_MENU_TARGETS);\n if (native && host?.contains(native)) return true;\n const selection = window.getSelection();\n return Boolean(selection && !selection.isCollapsed && selection.toString().trim() && selection.containsNode(target, true));\n };\n const hostClass = createMemo(() => (typeof props.class === \"function\" ? props.class(isOpen()) : props.class));\n const items = createMemo<readonly DropdownItem[]>(() => props.items);\n\n const dismiss = (event: PointerEvent) => {\n if (menu?.contains(event.target as Node)) return;\n close();\n };\n const closeOnScroll = (event: Event) => {\n const target = event.target;\n if (target instanceof Node && menu?.contains(target)) return;\n close();\n };\n // A resize event may leave the viewport's size unchanged; headless Chromium\n // was seen to fire one on a fresh page. The clamped menu is still in place.\n const closeOnResize = () => {\n if (window.innerWidth === viewport.width && window.innerHeight === viewport.height) return;\n close();\n };\n const attachOpenListeners = () => {\n if (listenersAttached) return;\n listenersAttached = true;\n document.addEventListener(\"pointerdown\", dismiss);\n document.addEventListener(\"keydown\", keyDown);\n window.addEventListener(\"resize\", closeOnResize);\n window.addEventListener(\"scroll\", closeOnScroll, true);\n };\n const detachOpenListeners = () => {\n if (!listenersAttached) return;\n listenersAttached = false;\n document.removeEventListener(\"pointerdown\", dismiss);\n document.removeEventListener(\"keydown\", keyDown);\n window.removeEventListener(\"resize\", closeOnResize);\n window.removeEventListener(\"scroll\", closeOnScroll, true);\n resizeObserver?.disconnect();\n };\n /** Clamps the rendered menu into the viewport beside the point that opened it. */\n const place = () => {\n if (!isOpen() || !menu?.isConnected) return;\n const point = dropdownPosition(\n new DOMRect(anchor.x, anchor.y, 0, 0),\n menu.getBoundingClientRect(),\n \"bottom-right\" satisfies DropdownPosition,\n { width: window.innerWidth, height: window.innerHeight },\n 0,\n );\n setPosition({ x: point.left, y: point.top });\n };\n const close = () => {\n detachOpenListeners();\n if (!isOpen()) return;\n setPosition();\n if (closeActiveContextMenu === close) closeActiveContextMenu = undefined;\n props.onClose?.();\n };\n const focusItem = (index: number) => {\n const items = focusableItems(menu);\n if (items.length === 0) return;\n items[(index + items.length) % items.length]?.focus();\n };\n const open = (x: number, y: number) => {\n if (props.disabled) return;\n closeActiveContextMenu?.();\n // Focus may sit on a descendant of the host, as in composite widgets; Escape returns it there.\n const focused = document.activeElement;\n opener = focused instanceof HTMLElement && focused !== host && host?.contains(focused) ? focused : undefined;\n hostRing = ringOnReturn(focused);\n anchor = { x, y };\n viewport = { width: window.innerWidth, height: window.innerHeight };\n setPosition({ x, y });\n closeActiveContextMenu = close;\n attachOpenListeners();\n props.onOpen?.();\n // The menu sizes to its entries, so it is measured once rendered and\n // clamped into the viewport before the next paint, and again whenever its\n // entries change its size while it is open.\n queueMicrotask(() => {\n if (!isOpen() || !menu?.isConnected) return;\n place();\n if (typeof ResizeObserver !== \"undefined\") {\n resizeObserver ??= new ResizeObserver(place);\n resizeObserver.observe(menu);\n }\n focusItem(0);\n });\n };\n const keyDown = (event: KeyboardEvent) => {\n if (!isOpen()) return;\n const items = focusableItems(menu);\n const current = items.indexOf(document.activeElement as HTMLElement);\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n focusItem(current + (event.key === \"ArrowDown\" ? 1 : -1));\n } else if (focusRowSegment(items, event.key)) {\n event.preventDefault();\n } else if (event.key === \"Home\" || event.key === \"End\") {\n event.preventDefault();\n focusItem(event.key === \"Home\" ? 0 : -1);\n } else if (event.key === \"Escape\") {\n event.preventDefault();\n close();\n returnFocus(opener?.isConnected ? opener : host, hostRing);\n } else if (event.key === \"Tab\") {\n close();\n }\n };\n\n props.openAt?.(open);\n // A close from outside, such as a drag taking over the press, returns focus that sits in the menu to where it came from.\n props.closeWith?.(() => {\n if (isOpen() && menu?.contains(document.activeElement)) returnFocus(opener?.isConnected ? opener : host, hostRing);\n close();\n });\n\n onMount(() => {\n onCleanup(() => {\n detachOpenListeners();\n if (closeActiveContextMenu === close) closeActiveContextMenu = undefined;\n });\n });\n\n return (\n <>\n {/* biome-ignore lint/a11y/useAriaPropsSupportedByRole: the named group owns the context-menu relationship without pretending arbitrary children form one button. */}\n <div\n ref={host}\n id={props.id ?? generatedId}\n class={hostClass()}\n role=\"group\"\n tabIndex={props.disabled ? undefined : (props.tabIndex ?? 0)}\n aria-label={props.label ?? messages().contextMenu}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen()}\n aria-controls={isOpen() ? menuId : undefined}\n aria-disabled={props.disabled ? \"true\" : undefined}\n onContextMenu={(event) => {\n if (props.disabled) return;\n // An enclosing context menu must not take over the browser's own either.\n if (keepsNativeMenu(event.target)) return void event.stopPropagation();\n event.preventDefault();\n event.stopPropagation();\n open(event.clientX, event.clientY);\n }}\n onKeyDown={(event) => {\n if (props.disabled || (event.key !== \"ContextMenu\" && !(event.shiftKey && event.key === \"F10\"))) return;\n // A nested context menu already opened its own; a field keeps the browser's.\n if (\n event.defaultPrevented ||\n (props.keepNativeMenu && event.target instanceof Element && event.target.closest(NATIVE_MENU_TARGETS))\n )\n return;\n event.preventDefault();\n // Beside the focused element, such as a row of a composite widget, rather than the corner of the whole host.\n const focused = document.activeElement;\n const rect = (focused instanceof HTMLElement && host?.contains(focused) ? focused : host)?.getBoundingClientRect();\n if (rect) open(rect.left + 12, rect.top + 12);\n }}\n >\n {props.children}\n </div>\n <Show when={position()}>\n {(point) => (\n <Portal>\n <div\n ref={menu}\n id={menuId}\n class=\"k2b-ui k2b-context-menu\"\n role=\"menu\"\n aria-label={props.label ?? messages().contextMenu}\n style={{ left: `${point().x}px`, top: `${point().y}px` }}\n onPointerDown={(event) => event.stopPropagation()}\n >\n {/* The menu carries the same name for assistive technology. */}\n <Show when={props.title}>\n <div class=\"k2b-context-menu__title\" aria-hidden=\"true\">\n {props.title}\n </div>\n </Show>\n <DropdownItems items={items()} close={close} />\n </div>\n </Portal>\n )}\n </Show>\n </>\n );\n}\n\nexport default ContextMenu;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["actions/ContextMenu.tsx"],"sourcesContent":["import { createMemo, createSignal, createUniqueId, type JSX, onCleanup, onMount, Show } from \"solid-js\";\nimport { Portal } from \"solid-js/web\";\nimport { returnFocus, ringOnReturn } from \"../internal/focus-return\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { type DropdownItem, DropdownItems, type DropdownPosition, dropdownPosition } from \"./Dropdown\";\nimport { focusRowSegment } from \"./menu-rows\";\n\nexport type ContextMenuProps = {\n items: readonly DropdownItem[];\n children: JSX.Element;\n class?: string | ((isOpen: boolean) => string);\n /** Tab order of the context-menu host. Descendant-focused composite widgets use -1. */\n tabIndex?: number;\n disabled?: boolean;\n onClose?: () => void;\n onOpen?: () => void;\n id?: string;\n label?: string;\n /**\n * Links, form fields, editable text, and selected text inside the host keep the browser's own menu, with its Copy,\n * Paste, and Open link. Use it where the host wraps readable content rather than one row.\n */\n keepNativeMenu?: boolean;\n};\n\nconst NATIVE_MENU_TARGETS = \"a[href], input, textarea, select, [contenteditable]:not([contenteditable='false'])\";\n\nlet closeActiveContextMenu: (() => void) | undefined;\n\nconst focusableItems = (menu: HTMLElement | undefined): HTMLElement[] =>\n menu\n ? Array.from(\n menu.querySelectorAll<HTMLElement>(\n [\n \"[role='menuitem']:not([aria-disabled='true'])\",\n \"[role='menuitemcheckbox']:not([aria-disabled='true'])\",\n \"[role='menuitemradio']:not([aria-disabled='true'])\",\n ].join(\", \"),\n ),\n )\n : [];\n\n/** Right-click menu with keyboard invocation, one-open-at-a-time behavior, and viewport clamping. */\nexport function ContextMenu(props: ContextMenuProps): JSX.Element {\n return ContextMenuBase(props);\n}\n\n/**\n * Package-internal, not exported from the package index: `openAt` lets GestureMenu open the menu at a held finger, and\n * `title` names what was pressed above the entries, since the finger covers it.\n */\nexport function ContextMenuBase(\n props: ContextMenuProps & {\n openAt?: (open: (x: number, y: number) => void) => void;\n title?: string;\n closeWith?: (close: () => void) => void;\n },\n): JSX.Element {\n const messages = useUiMessages();\n const generatedId = `k2b-context-${createUniqueId()}`;\n const menuId = `${generatedId}-menu`;\n const [position, setPosition] = createSignal<{ x: number; y: number }>();\n let host: HTMLDivElement | undefined;\n let menu: HTMLDivElement | undefined;\n let listenersAttached = false;\n let hostRing = true;\n /** The element inside the host that had focus as the menu opened, such as a row or a day of a composite widget. */\n let opener: HTMLElement | undefined;\n let anchor = { x: 0, y: 0 };\n let viewport = { width: 0, height: 0 };\n let resizeObserver: ResizeObserver | undefined;\n\n const isOpen = () => position() !== undefined;\n const keepsNativeMenu = (target: EventTarget | null): boolean => {\n if (!props.keepNativeMenu || !(target instanceof Node)) return false;\n const element = target instanceof Element ? target : target.parentElement;\n const native = element?.closest(NATIVE_MENU_TARGETS);\n if (native && host?.contains(native)) return true;\n const selection = window.getSelection();\n return Boolean(selection && !selection.isCollapsed && selection.toString().trim() && selection.containsNode(target, true));\n };\n const hostClass = createMemo(() => (typeof props.class === \"function\" ? props.class(isOpen()) : props.class));\n const items = createMemo<readonly DropdownItem[]>(() => props.items);\n\n const dismiss = (event: PointerEvent) => {\n if (menu?.contains(event.target as Node)) return;\n close();\n };\n const closeOnScroll = (event: Event) => {\n const target = event.target;\n if (target instanceof Node && menu?.contains(target)) return;\n close();\n };\n // A resize event may leave the viewport's size unchanged; headless Chromium\n // was seen to fire one on a fresh page. The clamped menu is still in place.\n const closeOnResize = () => {\n if (window.innerWidth === viewport.width && window.innerHeight === viewport.height) return;\n close();\n };\n const attachOpenListeners = () => {\n if (listenersAttached) return;\n listenersAttached = true;\n document.addEventListener(\"pointerdown\", dismiss);\n document.addEventListener(\"keydown\", keyDown);\n window.addEventListener(\"resize\", closeOnResize);\n window.addEventListener(\"scroll\", closeOnScroll, true);\n };\n const detachOpenListeners = () => {\n if (!listenersAttached) return;\n listenersAttached = false;\n document.removeEventListener(\"pointerdown\", dismiss);\n document.removeEventListener(\"keydown\", keyDown);\n window.removeEventListener(\"resize\", closeOnResize);\n window.removeEventListener(\"scroll\", closeOnScroll, true);\n resizeObserver?.disconnect();\n };\n /** Clamps the rendered menu into the viewport beside the point that opened it. */\n const place = () => {\n if (!isOpen() || !menu?.isConnected) return;\n const point = dropdownPosition(\n new DOMRect(anchor.x, anchor.y, 0, 0),\n menu.getBoundingClientRect(),\n \"bottom-right\" satisfies DropdownPosition,\n { width: window.innerWidth, height: window.innerHeight },\n 0,\n );\n setPosition({ x: point.left, y: point.top });\n };\n const close = () => {\n detachOpenListeners();\n if (!isOpen()) return;\n // An activated entry closes the menu before its action runs: focus goes back to where the menu opened from, as\n // Escape returns it, so the keyboard never lands on the page body.\n if (menu?.contains(document.activeElement)) returnFocus(opener?.isConnected ? opener : host, hostRing);\n setPosition();\n if (closeActiveContextMenu === close) closeActiveContextMenu = undefined;\n props.onClose?.();\n };\n const focusItem = (index: number) => {\n const items = focusableItems(menu);\n if (items.length === 0) return;\n items[(index + items.length) % items.length]?.focus();\n };\n const open = (x: number, y: number) => {\n if (props.disabled) return;\n closeActiveContextMenu?.();\n // Focus may sit on a descendant of the host, as in composite widgets; Escape returns it there.\n const focused = document.activeElement;\n opener = focused instanceof HTMLElement && focused !== host && host?.contains(focused) ? focused : undefined;\n hostRing = ringOnReturn(focused);\n anchor = { x, y };\n viewport = { width: window.innerWidth, height: window.innerHeight };\n setPosition({ x, y });\n closeActiveContextMenu = close;\n attachOpenListeners();\n props.onOpen?.();\n // The menu sizes to its entries, so it is measured once rendered and\n // clamped into the viewport before the next paint, and again whenever its\n // entries change its size while it is open.\n queueMicrotask(() => {\n if (!isOpen() || !menu?.isConnected) return;\n place();\n if (typeof ResizeObserver !== \"undefined\") {\n resizeObserver ??= new ResizeObserver(place);\n resizeObserver.observe(menu);\n }\n focusItem(0);\n });\n };\n const keyDown = (event: KeyboardEvent) => {\n if (!isOpen()) return;\n const items = focusableItems(menu);\n const current = items.indexOf(document.activeElement as HTMLElement);\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n focusItem(current + (event.key === \"ArrowDown\" ? 1 : -1));\n } else if (focusRowSegment(items, event.key)) {\n event.preventDefault();\n } else if (event.key === \"Home\" || event.key === \"End\") {\n event.preventDefault();\n focusItem(event.key === \"Home\" ? 0 : -1);\n } else if (event.key === \"Escape\") {\n event.preventDefault();\n close();\n returnFocus(opener?.isConnected ? opener : host, hostRing);\n } else if (event.key === \"Tab\") {\n close();\n }\n };\n\n props.openAt?.(open);\n // A close from outside, such as a drag taking over the press, returns focus that sits in the menu to where it came from.\n props.closeWith?.(() => {\n if (isOpen() && menu?.contains(document.activeElement)) returnFocus(opener?.isConnected ? opener : host, hostRing);\n close();\n });\n\n onMount(() => {\n onCleanup(() => {\n detachOpenListeners();\n if (closeActiveContextMenu === close) closeActiveContextMenu = undefined;\n });\n });\n\n return (\n <>\n {/* biome-ignore lint/a11y/useAriaPropsSupportedByRole: the named group owns the context-menu relationship without pretending arbitrary children form one button. */}\n <div\n ref={host}\n id={props.id ?? generatedId}\n class={hostClass()}\n role=\"group\"\n tabIndex={props.disabled ? undefined : (props.tabIndex ?? 0)}\n aria-label={props.label ?? messages().contextMenu}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen()}\n aria-controls={isOpen() ? menuId : undefined}\n aria-disabled={props.disabled ? \"true\" : undefined}\n onContextMenu={(event) => {\n if (props.disabled) return;\n // An enclosing context menu must not take over the browser's own either.\n if (keepsNativeMenu(event.target)) return void event.stopPropagation();\n event.preventDefault();\n event.stopPropagation();\n open(event.clientX, event.clientY);\n }}\n onKeyDown={(event) => {\n if (props.disabled || (event.key !== \"ContextMenu\" && !(event.shiftKey && event.key === \"F10\"))) return;\n // A nested context menu already opened its own; a field keeps the browser's.\n if (\n event.defaultPrevented ||\n (props.keepNativeMenu && event.target instanceof Element && event.target.closest(NATIVE_MENU_TARGETS))\n )\n return;\n event.preventDefault();\n // Beside the focused element, such as a row of a composite widget, rather than the corner of the whole host.\n const focused = document.activeElement;\n const rect = (focused instanceof HTMLElement && host?.contains(focused) ? focused : host)?.getBoundingClientRect();\n if (rect) open(rect.left + 12, rect.top + 12);\n }}\n >\n {props.children}\n </div>\n <Show when={position()}>\n {(point) => (\n <Portal>\n <div\n ref={menu}\n id={menuId}\n class=\"k2b-ui k2b-context-menu\"\n role=\"menu\"\n aria-label={props.label ?? messages().contextMenu}\n style={{ left: `${point().x}px`, top: `${point().y}px` }}\n onPointerDown={(event) => event.stopPropagation()}\n >\n {/* The menu carries the same name for assistive technology. */}\n <Show when={props.title}>\n <div class=\"k2b-context-menu__title\" aria-hidden=\"true\">\n {props.title}\n </div>\n </Show>\n <DropdownItems items={items()} close={close} />\n </div>\n </Portal>\n )}\n </Show>\n </>\n );\n}\n\nexport default ContextMenu;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { template as _$template } from "solid-js/web";
|
|
2
|
-
import {
|
|
2
|
+
import { setAttribute as _$setAttribute } from "solid-js/web";
|
|
3
3
|
import { createComponent as _$createComponent } from "solid-js/web";
|
|
4
4
|
import { mergeProps as _$mergeProps } from "solid-js/web";
|
|
5
5
|
import { className as _$className } from "solid-js/web";
|
|
6
6
|
import { effect as _$effect } from "solid-js/web";
|
|
7
7
|
import { getNextElement as _$getNextElement } from "solid-js/web";
|
|
8
|
+
import { insert as _$insert } from "solid-js/web";
|
|
8
9
|
import { memo as _$memo } from "solid-js/web";
|
|
9
|
-
var _tmpl$ = /*#__PURE__*/_$template(`<
|
|
10
|
-
_tmpl$2 = /*#__PURE__*/_$template(`<
|
|
11
|
-
_tmpl$3 = /*#__PURE__*/_$template(`<span class=k2b-
|
|
10
|
+
var _tmpl$ = /*#__PURE__*/_$template(`<span class=k2b-sr-only aria-live=polite>`),
|
|
11
|
+
_tmpl$2 = /*#__PURE__*/_$template(`<i aria-hidden=true>`),
|
|
12
|
+
_tmpl$3 = /*#__PURE__*/_$template(`<span class=k2b-copy-button__label><span>`);
|
|
12
13
|
import { copyToClipboard } from "@k2b/stdlib/browser";
|
|
13
14
|
import { createSignal, onCleanup, splitProps } from "solid-js";
|
|
14
15
|
import { useUiMessages } from "../intl/messages";
|
|
@@ -44,9 +45,21 @@ export function CopyButton(props) {
|
|
|
44
45
|
if (resetTimer) clearTimeout(resetTimer);
|
|
45
46
|
resetTimer = setTimeout(() => setCopied(false), local.resetAfter ?? 2000);
|
|
46
47
|
};
|
|
47
|
-
const
|
|
48
|
+
const copyLabel = () => local.label ?? messages().copy;
|
|
49
|
+
const copiedLabel = () => local.copiedLabel ?? messages().copied;
|
|
50
|
+
const visibleLabel = () => copied() ? copiedLabel() : copyLabel();
|
|
48
51
|
const icon = () => copied() ? "ti ti-check" : "ti ti-copy";
|
|
49
52
|
const iconOnly = () => local.iconOnly ?? local.label === undefined;
|
|
53
|
+
// Copied often flashes into a row next to a field; the other label, drawn hidden by CSS, keeps the button's width.
|
|
54
|
+
const hiddenLabel = () => copied() ? copyLabel() : copiedLabel();
|
|
55
|
+
const announcement = () => (() => {
|
|
56
|
+
var _el$ = _$getNextElement(_tmpl$);
|
|
57
|
+
_$insert(_el$, (() => {
|
|
58
|
+
var _c$ = _$memo(() => !!copied());
|
|
59
|
+
return () => _c$() ? visibleLabel() : "";
|
|
60
|
+
})());
|
|
61
|
+
return _el$;
|
|
62
|
+
})();
|
|
50
63
|
const button = tooltip => _$createComponent(Button, _$mergeProps(rest, {
|
|
51
64
|
tooltip: tooltip,
|
|
52
65
|
get disabled() {
|
|
@@ -76,24 +89,19 @@ export function CopyButton(props) {
|
|
|
76
89
|
onClick: copy,
|
|
77
90
|
get children() {
|
|
78
91
|
return [(() => {
|
|
79
|
-
var _el$ = _$getNextElement(_tmpl$);
|
|
80
|
-
_$effect(() => _$className(_el$, icon()));
|
|
81
|
-
return _el$;
|
|
82
|
-
})(), _$memo(() => _$memo(() => !!!iconOnly())() && (() => {
|
|
83
92
|
var _el$2 = _$getNextElement(_tmpl$2);
|
|
84
|
-
_$
|
|
93
|
+
_$effect(() => _$className(_el$2, icon()));
|
|
85
94
|
return _el$2;
|
|
95
|
+
})(), _$memo(() => _$memo(() => !!!iconOnly())() && (() => {
|
|
96
|
+
var _el$3 = _$getNextElement(_tmpl$3),
|
|
97
|
+
_el$4 = _el$3.firstChild;
|
|
98
|
+
_$insert(_el$4, visibleLabel);
|
|
99
|
+
_$effect(() => _$setAttribute(_el$3, "data-reserve", hiddenLabel()));
|
|
100
|
+
return _el$3;
|
|
86
101
|
})())];
|
|
87
102
|
}
|
|
88
103
|
}));
|
|
89
|
-
return
|
|
90
|
-
var _el$3 = _$getNextElement(_tmpl$3);
|
|
91
|
-
_$insert(_el$3, (() => {
|
|
92
|
-
var _c$ = _$memo(() => !!copied());
|
|
93
|
-
return () => _c$() ? visibleLabel() : "";
|
|
94
|
-
})());
|
|
95
|
-
return _el$3;
|
|
96
|
-
})()] : button(undefined);
|
|
104
|
+
return [_$memo(() => button(iconOnly() ? visibleLabel() : undefined)), _$memo(announcement)];
|
|
97
105
|
}
|
|
98
106
|
export default CopyButton;
|
|
99
107
|
//# sourceMappingURL=CopyButton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["actions/CopyButton.tsx"],"sourcesContent":["import { copyToClipboard } from \"@k2b/stdlib/browser\";\nimport { createSignal, type JSX, onCleanup, splitProps } from \"solid-js\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { Button, type ButtonProps } from \"./Button\";\n\nexport type CopyButtonValue = { text: string; value?: string } | { text?: string; value: string };\n\nexport type CopyButtonProps = CopyButtonValue &\n Omit<ButtonProps, \"children\" | \"onClick\"> & {\n label?: string;\n copiedLabel?: string;\n iconOnly?: boolean;\n onCopied?: () => void;\n onCopyError?: (error: unknown) => void;\n resetAfter?: number;\n };\n\nexport async function copyText(\n text: string,\n onCopyError?: (error: unknown) => void,\n copy: (text: string) => Promise<void> = copyToClipboard,\n): Promise<void> {\n try {\n await copy(text);\n } catch (error) {\n onCopyError?.(error);\n throw error;\n }\n}\n\nexport function CopyButton(props: CopyButtonProps): JSX.Element {\n const messages = useUiMessages();\n const [local, rest] = splitProps(props, [\n \"class\",\n \"copiedLabel\",\n \"disabled\",\n \"iconOnly\",\n \"label\",\n \"loading\",\n \"loadingLabel\",\n \"onCopied\",\n \"onCopyError\",\n \"resetAfter\",\n \"size\",\n \"text\",\n \"type\",\n \"value\",\n \"variant\",\n ]);\n const [copied, setCopied] = createSignal(false);\n let resetTimer: ReturnType<typeof setTimeout> | undefined;\n\n onCleanup(() => {\n if (resetTimer) clearTimeout(resetTimer);\n });\n\n const copy = async () => {\n // `copyText` reports through `onCopyError` and then rethrows so direct\n // callers can await it. The click handler is not awaited by anyone, so it\n // has to absorb the rejection here — otherwise a denied clipboard\n // permission surfaces as an unhandled rejection despite `onCopyError`.\n try {\n await copyText(local.text ?? local.value ?? \"\", local.onCopyError);\n } catch {\n return;\n }\n setCopied(true);\n local.onCopied?.();\n if (resetTimer) clearTimeout(resetTimer);\n resetTimer = setTimeout(() => setCopied(false), local.resetAfter ?? 2000);\n };\n\n const
|
|
1
|
+
{"version":3,"names":[],"sources":["actions/CopyButton.tsx"],"sourcesContent":["import { copyToClipboard } from \"@k2b/stdlib/browser\";\nimport { createSignal, type JSX, onCleanup, splitProps } from \"solid-js\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { Button, type ButtonProps } from \"./Button\";\n\nexport type CopyButtonValue = { text: string; value?: string } | { text?: string; value: string };\n\nexport type CopyButtonProps = CopyButtonValue &\n Omit<ButtonProps, \"children\" | \"onClick\"> & {\n label?: string;\n copiedLabel?: string;\n iconOnly?: boolean;\n onCopied?: () => void;\n onCopyError?: (error: unknown) => void;\n resetAfter?: number;\n };\n\nexport async function copyText(\n text: string,\n onCopyError?: (error: unknown) => void,\n copy: (text: string) => Promise<void> = copyToClipboard,\n): Promise<void> {\n try {\n await copy(text);\n } catch (error) {\n onCopyError?.(error);\n throw error;\n }\n}\n\nexport function CopyButton(props: CopyButtonProps): JSX.Element {\n const messages = useUiMessages();\n const [local, rest] = splitProps(props, [\n \"class\",\n \"copiedLabel\",\n \"disabled\",\n \"iconOnly\",\n \"label\",\n \"loading\",\n \"loadingLabel\",\n \"onCopied\",\n \"onCopyError\",\n \"resetAfter\",\n \"size\",\n \"text\",\n \"type\",\n \"value\",\n \"variant\",\n ]);\n const [copied, setCopied] = createSignal(false);\n let resetTimer: ReturnType<typeof setTimeout> | undefined;\n\n onCleanup(() => {\n if (resetTimer) clearTimeout(resetTimer);\n });\n\n const copy = async () => {\n // `copyText` reports through `onCopyError` and then rethrows so direct\n // callers can await it. The click handler is not awaited by anyone, so it\n // has to absorb the rejection here — otherwise a denied clipboard\n // permission surfaces as an unhandled rejection despite `onCopyError`.\n try {\n await copyText(local.text ?? local.value ?? \"\", local.onCopyError);\n } catch {\n return;\n }\n setCopied(true);\n local.onCopied?.();\n if (resetTimer) clearTimeout(resetTimer);\n resetTimer = setTimeout(() => setCopied(false), local.resetAfter ?? 2000);\n };\n\n const copyLabel = () => local.label ?? messages().copy;\n const copiedLabel = () => local.copiedLabel ?? messages().copied;\n const visibleLabel = () => (copied() ? copiedLabel() : copyLabel());\n const icon = () => (copied() ? \"ti ti-check\" : \"ti ti-copy\");\n const iconOnly = () => local.iconOnly ?? local.label === undefined;\n // Copied often flashes into a row next to a field; the other label, drawn hidden by CSS, keeps the button's width.\n const hiddenLabel = () => (copied() ? copyLabel() : copiedLabel());\n const announcement = () => (\n <span class=\"k2b-sr-only\" aria-live=\"polite\">\n {copied() ? visibleLabel() : \"\"}\n </span>\n );\n const button = (tooltip?: string) => (\n <Button\n {...rest}\n tooltip={tooltip}\n disabled={local.disabled}\n loading={local.loading}\n loadingLabel={local.loadingLabel}\n type={local.type ?? \"button\"}\n class={`k2b-copy-button ${local.class ?? \"\"}`}\n size={local.size ?? \"sm\"}\n variant={local.variant ?? \"ghost\"}\n aria-label={iconOnly() ? visibleLabel() : undefined}\n onClick={copy}\n >\n <i class={icon()} aria-hidden=\"true\" />\n {!iconOnly() && (\n <span class=\"k2b-copy-button__label\" data-reserve={hiddenLabel()}>\n <span>{visibleLabel()}</span>\n </span>\n )}\n </Button>\n );\n\n return (\n <>\n {button(iconOnly() ? visibleLabel() : undefined)}\n {announcement()}\n </>\n );\n}\n\nexport default CopyButton;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { chartMessages } from "../../content/chart-message-catalog";
|
|
2
|
+
import { chartDatumSvg, escapeXml, niceStep } from "./svg";
|
|
3
|
+
/** Missing observations interrupt the entire stack; zero-sum columns are gaps only in normalized mode. */
|
|
4
|
+
export function areaLayout(spec, size) {
|
|
5
|
+
if (![size.width, size.height].every(v => Number.isFinite(v) && v > 0)) throw new RangeError("Invalid area size");
|
|
6
|
+
if (spec.x.some(x => typeof x === "number" && !Number.isFinite(x))) throw new RangeError("Area X values must be finite");
|
|
7
|
+
if (spec.series.some(s => s.data.length !== spec.x.length)) throw new RangeError("Area series must match x length");
|
|
8
|
+
const totals = spec.x.map((_, i) => {
|
|
9
|
+
let total = 0,
|
|
10
|
+
missing = false;
|
|
11
|
+
for (const series of spec.series) {
|
|
12
|
+
const value = series.data[i];
|
|
13
|
+
if (value === null) {
|
|
14
|
+
missing = true;
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) throw new RangeError("Area values must be nonnegative finite numbers or null");
|
|
18
|
+
total += value;
|
|
19
|
+
}
|
|
20
|
+
if (!Number.isFinite(total)) throw new RangeError("Area totals must be finite");
|
|
21
|
+
return missing || spec.normalize && total === 0 ? null : total;
|
|
22
|
+
});
|
|
23
|
+
const layers = spec.series.map(() => []);
|
|
24
|
+
totals.forEach((total, index) => {
|
|
25
|
+
let lower = 0;
|
|
26
|
+
spec.series.forEach((series, s) => {
|
|
27
|
+
const amount = series.data[index];
|
|
28
|
+
if (total === null || amount === null || amount === undefined) {
|
|
29
|
+
layers[s].push(null);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const share = total === 0 ? 0 : amount / total;
|
|
33
|
+
const upper = lower + (spec.normalize ? share : amount);
|
|
34
|
+
layers[s].push({
|
|
35
|
+
index,
|
|
36
|
+
amount,
|
|
37
|
+
share,
|
|
38
|
+
lower,
|
|
39
|
+
upper
|
|
40
|
+
});
|
|
41
|
+
lower = upper;
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
let rawMax = 0;
|
|
45
|
+
for (const total of totals) if (total !== null) rawMax = Math.max(rawMax, total);
|
|
46
|
+
const step = spec.normalize ? 0.25 : niceStep(rawMax || 1, 5);
|
|
47
|
+
const max = spec.normalize ? 1 : Math.ceil((rawMax || 1) / step) * step;
|
|
48
|
+
if (!(step > 0) || !Number.isFinite(max)) throw new RangeError("Area values cannot form a finite axis; rescale them first");
|
|
49
|
+
const ticks = Array.from({
|
|
50
|
+
length: Math.round(max / step) + 1
|
|
51
|
+
}, (_, i) => i * step);
|
|
52
|
+
const format = spec.format ?? new Intl.NumberFormat(spec.locale ?? "en", {
|
|
53
|
+
maximumFractionDigits: 2
|
|
54
|
+
}).format;
|
|
55
|
+
const percent = new Intl.NumberFormat(spec.locale ?? "en", {
|
|
56
|
+
style: "percent",
|
|
57
|
+
minimumFractionDigits: 1,
|
|
58
|
+
maximumFractionDigits: 1
|
|
59
|
+
}).format;
|
|
60
|
+
const axisFormat = spec.normalize ? new Intl.NumberFormat(spec.locale ?? "en", {
|
|
61
|
+
style: "percent",
|
|
62
|
+
maximumFractionDigits: 0
|
|
63
|
+
}).format : format;
|
|
64
|
+
const numericX = new Intl.NumberFormat(spec.locale ?? "en", {
|
|
65
|
+
useGrouping: "min2",
|
|
66
|
+
maximumFractionDigits: 6
|
|
67
|
+
}).format;
|
|
68
|
+
const xFormat = value => typeof value === "number" ? numericX(value) : value;
|
|
69
|
+
const displayWidth = spec.displayWidth ?? 296;
|
|
70
|
+
if (!Number.isFinite(displayWidth) || displayWidth <= 0) throw new RangeError("Invalid area display width");
|
|
71
|
+
const ratio = size.width / displayWidth;
|
|
72
|
+
const left = Math.min(size.width * 0.6, Math.max(44, ...ticks.map(v => axisFormat(v).length * 7 + 12)) * ratio);
|
|
73
|
+
const right = size.width - 12,
|
|
74
|
+
top = (spec.title || spec.subtitle ? 50 : 16) + (spec.legend === false ? 0 : spec.series.length <= 2 ? 20 : 40);
|
|
75
|
+
const bottom = Math.max(top + 1, size.height - 30);
|
|
76
|
+
const projectX = index => spec.x.length < 2 ? (left + right) / 2 : left + index / (spec.x.length - 1) * (right - left);
|
|
77
|
+
const projectY = value => bottom - value / max * (bottom - top);
|
|
78
|
+
return {
|
|
79
|
+
layers,
|
|
80
|
+
totals,
|
|
81
|
+
max,
|
|
82
|
+
ticks,
|
|
83
|
+
format,
|
|
84
|
+
percent,
|
|
85
|
+
axisFormat,
|
|
86
|
+
xFormat,
|
|
87
|
+
ratio,
|
|
88
|
+
left,
|
|
89
|
+
right,
|
|
90
|
+
top,
|
|
91
|
+
bottom,
|
|
92
|
+
projectX,
|
|
93
|
+
projectY
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const f = value => String(Math.round(value * 100) / 100);
|
|
97
|
+
const text = (x, y, label, anchor = "middle", extra = "") => `<text x="${f(x)}" y="${f(y)}" text-anchor="${anchor}" fill="currentColor" stroke="none" font-family="var(--k2b-font-sans, sans-serif)" font-size="11" ${extra}>${escapeXml(label)}</text>`;
|
|
98
|
+
export function renderAreaSvg(spec) {
|
|
99
|
+
const g = areaLayout(spec, spec),
|
|
100
|
+
parts = [];
|
|
101
|
+
if (spec.title) parts.push(text(spec.width / 2, 16, spec.title));
|
|
102
|
+
if (spec.subtitle) parts.push(text(spec.width / 2, spec.title ? 32 : 16, spec.subtitle));
|
|
103
|
+
for (const tick of g.ticks) {
|
|
104
|
+
const y = g.projectY(tick);
|
|
105
|
+
parts.push(`<line x1="${f(g.left)}" x2="${f(g.right)}" y1="${f(y)}" y2="${f(y)}" stroke="currentColor" stroke-opacity="${tick === 0 ? 0.25 : 0.09}"/>`, text(g.left - 8, y + 4, g.axisFormat(tick), "end", 'class="stdlib-chart-tick-label"'));
|
|
106
|
+
}
|
|
107
|
+
parts.push(`<line class="stdlib-chart-axis" x1="${f(g.left)}" x2="${f(g.right)}" y1="${f(g.bottom)}" y2="${f(g.bottom)}" stroke="none"/><line class="stdlib-chart-axis" x1="${f(g.left)}" x2="${f(g.left)}" y1="${f(g.top)}" y2="${f(g.bottom)}" stroke="none"/>`);
|
|
108
|
+
const palette = ["#2563eb", "#16a34a", "#d97706", "#dc2626", "#a855f7", "#0891b2", "#db2777", "#65a30d"];
|
|
109
|
+
if (spec.legend !== false) {
|
|
110
|
+
const entries = spec.series.slice(0, 4);
|
|
111
|
+
const columns = 2;
|
|
112
|
+
const cell = spec.width / columns;
|
|
113
|
+
entries.forEach((series, i) => {
|
|
114
|
+
const x = i % columns * cell + 4,
|
|
115
|
+
y = g.top - (entries.length <= 2 ? 11 : 28) + Math.floor(i / columns) * 17;
|
|
116
|
+
const color = i === 3 && spec.series.length > 4 ? "var(--k2b-text-muted, #8b8b93)" : `var(--stdlib-chart-c${i % 8 + 1}, ${palette[i % 8]})`;
|
|
117
|
+
const point = g.layers[i]?.at(-1);
|
|
118
|
+
const value = point ? spec.normalize ? g.percent(point.share) : g.format(point.amount) : "—";
|
|
119
|
+
const room = Math.floor(cell * (1 / g.ratio) / 6) - 4;
|
|
120
|
+
const showValue = value.length + 3 < room;
|
|
121
|
+
const maxChars = Math.max(1, room - (showValue ? value.length + 1 : 0));
|
|
122
|
+
const label = series.label.length > maxChars ? series.label.slice(0, maxChars - 1) + "…" : series.label;
|
|
123
|
+
const full = i === 3 && spec.series.length > 4 ? spec.series.slice(3).map(s => s.label).join(", ") : series.label;
|
|
124
|
+
const shown = i === 3 && spec.series.length > 4 ? `+${new Intl.NumberFormat(spec.locale ?? "en").format(spec.series.length - 3)}` : label;
|
|
125
|
+
const valueSvg = showValue && !(i === 3 && spec.series.length > 4) ? `<tspan dx="6" font-weight="600" data-chart-legend-value data-series-index="${i}" data-field="${spec.normalize ? "percent" : "value"}" data-default="${escapeXml(value)}">${escapeXml(value)}</tspan>` : "";
|
|
126
|
+
const labelSvg = text(x + 12, y, shown, "start").replace("</text>", `${valueSvg}</text>`);
|
|
127
|
+
parts.push(`<g><title>${escapeXml(full)}</title><rect x="${f(x)}" y="${f(y - 8)}" width="8" height="8" rx="2" fill="${color}" stroke="none"/>${labelSvg}</g>`);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
g.layers.forEach((layer, s) => {
|
|
131
|
+
const color = `var(--stdlib-chart-c${s % 8 + 1}, ${palette[s % 8]})`;
|
|
132
|
+
let run = [];
|
|
133
|
+
const flush = () => {
|
|
134
|
+
if (!run.length) return;
|
|
135
|
+
const halfSlot = Math.min(10 * g.ratio, (g.right - g.left) / Math.max(2, spec.x.length * 2));
|
|
136
|
+
const upper = run.length === 1 ? [[Math.max(g.left, g.projectX(run[0].index) - halfSlot), g.projectY(run[0].upper)], [Math.min(g.right, g.projectX(run[0].index) + halfSlot), g.projectY(run[0].upper)]] : run.map(p => [g.projectX(p.index), g.projectY(p.upper)]);
|
|
137
|
+
const lower = run.length === 1 ? [[upper[1][0], g.projectY(run[0].lower)], [upper[0][0], g.projectY(run[0].lower)]] : run.toReversed().map(p => [g.projectX(p.index), g.projectY(p.lower)]);
|
|
138
|
+
const points = [...upper, ...lower].map(([x, y]) => `${f(x)},${f(y)}`);
|
|
139
|
+
parts.push(`<polygon class="k2b-area-layer" points="${points.join(" ")}" fill="color-mix(in srgb, ${color} 55%, var(--k2b-surface, #ffffff))" stroke="none"/>`, `<polyline class="k2b-area-edge k2b-area-edge-${s % 8}" points="${upper.map(([x, y]) => `${f(x)},${f(y)}`).join(" ")}" fill="none" stroke="${color}" stroke-width="1.5"/>`);
|
|
140
|
+
run = [];
|
|
141
|
+
};
|
|
142
|
+
for (const point of layer) {
|
|
143
|
+
if (point) run.push(point);else flush();
|
|
144
|
+
}
|
|
145
|
+
flush();
|
|
146
|
+
layer.forEach(point => {
|
|
147
|
+
if (!point) return;
|
|
148
|
+
const x = g.projectX(point.index),
|
|
149
|
+
y = g.projectY((point.lower + point.upper) / 2);
|
|
150
|
+
const circle = `<circle class="k2b-area-inspection-point" cx="${f(x)}" cy="${f(y)}" r="3" fill="${color}" opacity="0" stroke="none"/>`;
|
|
151
|
+
parts.push(chartDatumSvg(circle, {
|
|
152
|
+
role: "point",
|
|
153
|
+
index: point.index,
|
|
154
|
+
seriesIndex: s,
|
|
155
|
+
label: spec.series[s].label,
|
|
156
|
+
anchor: [x, g.top],
|
|
157
|
+
values: [{
|
|
158
|
+
key: "x",
|
|
159
|
+
value: spec.x[point.index],
|
|
160
|
+
formatted: g.xFormat(spec.x[point.index])
|
|
161
|
+
}, {
|
|
162
|
+
key: "value",
|
|
163
|
+
value: point.amount,
|
|
164
|
+
formatted: g.format(point.amount)
|
|
165
|
+
}, {
|
|
166
|
+
key: "total",
|
|
167
|
+
value: g.totals[point.index],
|
|
168
|
+
formatted: g.format(g.totals[point.index])
|
|
169
|
+
}, ...(spec.normalize ? [{
|
|
170
|
+
key: "percent",
|
|
171
|
+
value: point.share * 100,
|
|
172
|
+
formatted: g.percent(point.share)
|
|
173
|
+
}] : [])]
|
|
174
|
+
}, spec.inspect ?? false));
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
const slot = (g.right - g.left) / Math.max(1, spec.x.length) * (1 / g.ratio);
|
|
178
|
+
const labelWidth = Math.max(1, ...spec.x.map(x => Math.min(24, String(x).length))) * 6;
|
|
179
|
+
const stride = Math.max(1, Math.ceil(labelWidth / Math.max(1, slot)));
|
|
180
|
+
spec.x.forEach((value, i) => {
|
|
181
|
+
if (i % stride !== 0) return;
|
|
182
|
+
const label = g.xFormat(value);
|
|
183
|
+
parts.push(text(g.projectX(i), g.bottom + 20, label.length > 24 ? label.slice(0, 23) + "…" : label, i === 0 ? "start" : i === spec.x.length - 1 ? "end" : "middle", 'class="stdlib-chart-tick-label"'));
|
|
184
|
+
});
|
|
185
|
+
const totalLabel = chartMessages.resolve([spec.locale ?? "en"]).t.chartFields({
|
|
186
|
+
key: "areaTotal"
|
|
187
|
+
});
|
|
188
|
+
return `<svg data-chart-total-label="${escapeXml(totalLabel)}" xmlns="http://www.w3.org/2000/svg" class="stdlib-chart k2b-area ${escapeXml(spec.className ?? "")}" width="${spec.width}" height="${spec.height}" viewBox="0 0 ${spec.width} ${spec.height}" aria-hidden="true" focusable="false">${parts.join("")}</svg>`;
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=area.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["charts/core/area.ts"],"sourcesContent":["import { chartMessages } from \"../../content/chart-message-catalog\";\nimport { chartDatumSvg, escapeXml, niceStep } from \"./svg\";\n\nexport type AreaOptions = {\n layout: \"stacked\";\n normalize?: boolean;\n x: (string | number)[];\n series: { label: string; data: (number | null)[] }[];\n title?: string;\n subtitle?: string;\n className?: string;\n legend?: boolean;\n format?: (value: number) => string;\n locale?: string;\n /** Narrowest displayed width in CSS pixels; measured hosts pass their actual width. */\n displayWidth?: number;\n};\nexport type AreaPoint = { index: number; amount: number; share: number; lower: number; upper: number };\n\n/** Missing observations interrupt the entire stack; zero-sum columns are gaps only in normalized mode. */\nexport function areaLayout(spec: AreaOptions, size: { width: number; height: number }) {\n if (![size.width, size.height].every((v) => Number.isFinite(v) && v > 0)) throw new RangeError(\"Invalid area size\");\n if (spec.x.some((x) => typeof x === \"number\" && !Number.isFinite(x))) throw new RangeError(\"Area X values must be finite\");\n if (spec.series.some((s) => s.data.length !== spec.x.length)) throw new RangeError(\"Area series must match x length\");\n const totals = spec.x.map((_, i) => {\n let total = 0,\n missing = false;\n for (const series of spec.series) {\n const value = series.data[i];\n if (value === null) {\n missing = true;\n continue;\n }\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0)\n throw new RangeError(\"Area values must be nonnegative finite numbers or null\");\n total += value;\n }\n if (!Number.isFinite(total)) throw new RangeError(\"Area totals must be finite\");\n return missing || (spec.normalize && total === 0) ? null : total;\n });\n const layers: (AreaPoint | null)[][] = spec.series.map(() => []);\n totals.forEach((total, index) => {\n let lower = 0;\n spec.series.forEach((series, s) => {\n const amount = series.data[index];\n if (total === null || amount === null || amount === undefined) {\n layers[s]!.push(null);\n return;\n }\n const share = total === 0 ? 0 : amount / total;\n const upper = lower + (spec.normalize ? share : amount);\n layers[s]!.push({ index, amount, share, lower, upper });\n lower = upper;\n });\n });\n let rawMax = 0;\n for (const total of totals) if (total !== null) rawMax = Math.max(rawMax, total);\n const step = spec.normalize ? 0.25 : niceStep(rawMax || 1, 5);\n const max = spec.normalize ? 1 : Math.ceil((rawMax || 1) / step) * step;\n if (!(step > 0) || !Number.isFinite(max)) throw new RangeError(\"Area values cannot form a finite axis; rescale them first\");\n const ticks = Array.from({ length: Math.round(max / step) + 1 }, (_, i) => i * step);\n const format = spec.format ?? new Intl.NumberFormat(spec.locale ?? \"en\", { maximumFractionDigits: 2 }).format;\n const percent = new Intl.NumberFormat(spec.locale ?? \"en\", { style: \"percent\", minimumFractionDigits: 1, maximumFractionDigits: 1 })\n .format;\n const axisFormat = spec.normalize\n ? new Intl.NumberFormat(spec.locale ?? \"en\", { style: \"percent\", maximumFractionDigits: 0 }).format\n : format;\n const numericX = new Intl.NumberFormat(spec.locale ?? \"en\", { useGrouping: \"min2\", maximumFractionDigits: 6 }).format;\n const xFormat = (value: string | number) => (typeof value === \"number\" ? numericX(value) : value);\n const displayWidth = spec.displayWidth ?? 296;\n if (!Number.isFinite(displayWidth) || displayWidth <= 0) throw new RangeError(\"Invalid area display width\");\n const ratio = size.width / displayWidth;\n const left = Math.min(size.width * 0.6, Math.max(44, ...ticks.map((v) => axisFormat(v).length * 7 + 12)) * ratio);\n const right = size.width - 12,\n top = (spec.title || spec.subtitle ? 50 : 16) + (spec.legend === false ? 0 : spec.series.length <= 2 ? 20 : 40);\n const bottom = Math.max(top + 1, size.height - 30);\n const projectX = (index: number) => (spec.x.length < 2 ? (left + right) / 2 : left + (index / (spec.x.length - 1)) * (right - left));\n const projectY = (value: number) => bottom - (value / max) * (bottom - top);\n return { layers, totals, max, ticks, format, percent, axisFormat, xFormat, ratio, left, right, top, bottom, projectX, projectY };\n}\nconst f = (value: number) => String(Math.round(value * 100) / 100);\nconst text = (x: number, y: number, label: string, anchor = \"middle\", extra = \"\") =>\n `<text x=\"${f(x)}\" y=\"${f(y)}\" text-anchor=\"${anchor}\" fill=\"currentColor\" stroke=\"none\" font-family=\"var(--k2b-font-sans, sans-serif)\" font-size=\"11\" ${extra}>${escapeXml(label)}</text>`;\n\nexport function renderAreaSvg(spec: AreaOptions & { width: number; height: number; inspect?: boolean }): string {\n const g = areaLayout(spec, spec),\n parts: string[] = [];\n if (spec.title) parts.push(text(spec.width / 2, 16, spec.title));\n if (spec.subtitle) parts.push(text(spec.width / 2, spec.title ? 32 : 16, spec.subtitle));\n for (const tick of g.ticks) {\n const y = g.projectY(tick);\n parts.push(\n `<line x1=\"${f(g.left)}\" x2=\"${f(g.right)}\" y1=\"${f(y)}\" y2=\"${f(y)}\" stroke=\"currentColor\" stroke-opacity=\"${tick === 0 ? 0.25 : 0.09}\"/>`,\n text(g.left - 8, y + 4, g.axisFormat(tick), \"end\", 'class=\"stdlib-chart-tick-label\"'),\n );\n }\n parts.push(\n `<line class=\"stdlib-chart-axis\" x1=\"${f(g.left)}\" x2=\"${f(g.right)}\" y1=\"${f(g.bottom)}\" y2=\"${f(g.bottom)}\" stroke=\"none\"/><line class=\"stdlib-chart-axis\" x1=\"${f(g.left)}\" x2=\"${f(g.left)}\" y1=\"${f(g.top)}\" y2=\"${f(g.bottom)}\" stroke=\"none\"/>`,\n );\n const palette = [\"#2563eb\", \"#16a34a\", \"#d97706\", \"#dc2626\", \"#a855f7\", \"#0891b2\", \"#db2777\", \"#65a30d\"];\n if (spec.legend !== false) {\n const entries = spec.series.slice(0, 4);\n const columns = 2;\n const cell = spec.width / columns;\n entries.forEach((series, i) => {\n const x = (i % columns) * cell + 4,\n y = g.top - (entries.length <= 2 ? 11 : 28) + Math.floor(i / columns) * 17;\n const color =\n i === 3 && spec.series.length > 4 ? \"var(--k2b-text-muted, #8b8b93)\" : `var(--stdlib-chart-c${(i % 8) + 1}, ${palette[i % 8]})`;\n const point = g.layers[i]?.at(-1);\n const value = point ? (spec.normalize ? g.percent(point.share) : g.format(point.amount)) : \"—\";\n const room = Math.floor((cell * (1 / g.ratio)) / 6) - 4;\n const showValue = value.length + 3 < room;\n const maxChars = Math.max(1, room - (showValue ? value.length + 1 : 0));\n const label = series.label.length > maxChars ? series.label.slice(0, maxChars - 1) + \"…\" : series.label;\n const full =\n i === 3 && spec.series.length > 4\n ? spec.series\n .slice(3)\n .map((s) => s.label)\n .join(\", \")\n : series.label;\n const shown =\n i === 3 && spec.series.length > 4 ? `+${new Intl.NumberFormat(spec.locale ?? \"en\").format(spec.series.length - 3)}` : label;\n const valueSvg =\n showValue && !(i === 3 && spec.series.length > 4)\n ? `<tspan dx=\"6\" font-weight=\"600\" data-chart-legend-value data-series-index=\"${i}\" data-field=\"${spec.normalize ? \"percent\" : \"value\"}\" data-default=\"${escapeXml(value)}\">${escapeXml(value)}</tspan>`\n : \"\";\n const labelSvg = text(x + 12, y, shown, \"start\").replace(\"</text>\", `${valueSvg}</text>`);\n parts.push(\n `<g><title>${escapeXml(full)}</title><rect x=\"${f(x)}\" y=\"${f(y - 8)}\" width=\"8\" height=\"8\" rx=\"2\" fill=\"${color}\" stroke=\"none\"/>${labelSvg}</g>`,\n );\n });\n }\n g.layers.forEach((layer, s) => {\n const color = `var(--stdlib-chart-c${(s % 8) + 1}, ${palette[s % 8]})`;\n let run: AreaPoint[] = [];\n const flush = () => {\n if (!run.length) return;\n const halfSlot = Math.min(10 * g.ratio, (g.right - g.left) / Math.max(2, spec.x.length * 2));\n const upper =\n run.length === 1\n ? [\n [Math.max(g.left, g.projectX(run[0]!.index) - halfSlot), g.projectY(run[0]!.upper)],\n [Math.min(g.right, g.projectX(run[0]!.index) + halfSlot), g.projectY(run[0]!.upper)],\n ]\n : run.map((p) => [g.projectX(p.index), g.projectY(p.upper)]);\n const lower =\n run.length === 1\n ? [\n [upper[1]![0]!, g.projectY(run[0]!.lower)],\n [upper[0]![0]!, g.projectY(run[0]!.lower)],\n ]\n : run.toReversed().map((p) => [g.projectX(p.index), g.projectY(p.lower)]);\n const points = [...upper, ...lower].map(([x, y]) => `${f(x!)},${f(y!)}`);\n parts.push(\n `<polygon class=\"k2b-area-layer\" points=\"${points.join(\" \")}\" fill=\"color-mix(in srgb, ${color} 55%, var(--k2b-surface, #ffffff))\" stroke=\"none\"/>`,\n `<polyline class=\"k2b-area-edge k2b-area-edge-${s % 8}\" points=\"${upper.map(([x, y]) => `${f(x!)},${f(y!)}`).join(\" \")}\" fill=\"none\" stroke=\"${color}\" stroke-width=\"1.5\"/>`,\n );\n run = [];\n };\n for (const point of layer) {\n if (point) run.push(point);\n else flush();\n }\n flush();\n layer.forEach((point) => {\n if (!point) return;\n const x = g.projectX(point.index),\n y = g.projectY((point.lower + point.upper) / 2);\n const circle = `<circle class=\"k2b-area-inspection-point\" cx=\"${f(x)}\" cy=\"${f(y)}\" r=\"3\" fill=\"${color}\" opacity=\"0\" stroke=\"none\"/>`;\n parts.push(\n chartDatumSvg(\n circle,\n {\n role: \"point\",\n index: point.index,\n seriesIndex: s,\n label: spec.series[s]!.label,\n anchor: [x, g.top],\n values: [\n {\n key: \"x\",\n value: spec.x[point.index]!,\n formatted: g.xFormat(spec.x[point.index]!),\n },\n { key: \"value\", value: point.amount, formatted: g.format(point.amount) },\n { key: \"total\", value: g.totals[point.index]!, formatted: g.format(g.totals[point.index]!) },\n ...(spec.normalize ? [{ key: \"percent\", value: point.share * 100, formatted: g.percent(point.share) }] : []),\n ],\n },\n spec.inspect ?? false,\n ),\n );\n });\n });\n const slot = ((g.right - g.left) / Math.max(1, spec.x.length)) * (1 / g.ratio);\n const labelWidth = Math.max(1, ...spec.x.map((x) => Math.min(24, String(x).length))) * 6;\n const stride = Math.max(1, Math.ceil(labelWidth / Math.max(1, slot)));\n spec.x.forEach((value, i) => {\n if (i % stride !== 0) return;\n const label = g.xFormat(value);\n parts.push(\n text(\n g.projectX(i),\n g.bottom + 20,\n label.length > 24 ? label.slice(0, 23) + \"…\" : label,\n i === 0 ? \"start\" : i === spec.x.length - 1 ? \"end\" : \"middle\",\n 'class=\"stdlib-chart-tick-label\"',\n ),\n );\n });\n const totalLabel = chartMessages.resolve([spec.locale ?? \"en\"]).t.chartFields({ key: \"areaTotal\" });\n return `<svg data-chart-total-label=\"${escapeXml(totalLabel)}\" xmlns=\"http://www.w3.org/2000/svg\" class=\"stdlib-chart k2b-area ${escapeXml(spec.className ?? \"\")}\" width=\"${spec.width}\" height=\"${spec.height}\" viewBox=\"0 0 ${spec.width} ${spec.height}\" aria-hidden=\"true\" focusable=\"false\">${parts.join(\"\")}</svg>`;\n}\n"],"mappings":"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","ignoreList":[]}
|