@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
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { positionTooltipSurface } from "../feedback/tooltip-position";
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export function isChartDatum(value) {
|
|
7
|
-
return object(value) && Number.isInteger(value.index) && typeof value.index === "number" && value.index >= 0 && (value.seriesIndex === undefined || typeof value.seriesIndex === "number" && Number.isInteger(value.seriesIndex) && value.seriesIndex >= 0) && typeof value.role === "string" && roles.has(value.role) && pair(value.anchor) && (value.grid === undefined || pair(value.grid)) && (value.label === undefined || typeof value.label === "string") && Array.isArray(value.values) && value.values.every(field => object(field) && typeof field.key === "string" && (typeof field.value === "string" || typeof field.value === "number" && Number.isFinite(field.value)) && (field.formatted === undefined || typeof field.formatted === "string"));
|
|
8
|
-
}
|
|
2
|
+
export { isChartDatum, sameChartDatum } from "../charts/core/inspection";
|
|
3
|
+
import { isChartDatum, sameChartDatum } from "../charts/core/inspection";
|
|
4
|
+
|
|
5
|
+
/** Host policy for inspecting an overflowing drawing. */
|
|
9
6
|
|
|
10
7
|
/** Adds or removes only the tooltip id, keeping descriptions the host put on the container. */
|
|
11
8
|
const describe = (container, id, on) => {
|
|
@@ -14,6 +11,13 @@ const describe = (container, id, on) => {
|
|
|
14
11
|
if (ids.length) container.setAttribute("aria-describedby", ids.join(" "));else container.removeAttribute("aria-describedby");
|
|
15
12
|
};
|
|
16
13
|
|
|
14
|
+
/** Mark roles that stand for a whole category: hovering anywhere in its column (or row) inspects it. */
|
|
15
|
+
const rowLayout = container => Boolean(container?.querySelector('svg[data-bar-layout="rows"]'));
|
|
16
|
+
const categoryRoles = {
|
|
17
|
+
bar: "item",
|
|
18
|
+
histogram: "bin",
|
|
19
|
+
boxplot: "box"
|
|
20
|
+
};
|
|
17
21
|
/** Enhances existing SVG nodes. Pointer/focus changes never rebuild the chart. */
|
|
18
22
|
export function createChartInspector(options) {
|
|
19
23
|
const source = Symbol("chart cursor");
|
|
@@ -58,7 +62,7 @@ export function createChartInspector(options) {
|
|
|
58
62
|
// Read the actual paint before applying inspection styles, including
|
|
59
63
|
// custom series and threshold colors. Invisible points use their line.
|
|
60
64
|
const point = item.element.querySelector(".stdlib-chart-inspection-point");
|
|
61
|
-
const source = point ? options.container()?.querySelector(options.kind() === "line" ? `.stdlib-chart-line.stdlib-chart-series-${(item.datum.seriesIndex ?? 0) % 8}` : ".stdlib-chart-sparkline, .stdlib-chart-stat-sparkline") : item.element.querySelector(".stdlib-chart-bar-gauge-fill, .stdlib-chart-gauge-fill, .stdlib-chart-stat-value") ?? item.element.querySelector("rect, path, circle");
|
|
65
|
+
const source = point ? options.container()?.querySelector(options.kind() === "line" ? `.stdlib-chart-line.stdlib-chart-series-${(item.datum.seriesIndex ?? 0) % 8}` : ".stdlib-chart-sparkline, .stdlib-chart-stat-sparkline") : item.element.querySelector(".stdlib-chart-bar-gauge-fill, .stdlib-chart-gauge-fill, .stdlib-chart-stat-value") ?? item.element.querySelector(":is(rect, path, circle):not(.k2b-chart-category-band)");
|
|
62
66
|
const paint = source ? source.ownerDocument.defaultView?.getComputedStyle(source) : undefined;
|
|
63
67
|
const color = (point || item.element.hasAttribute("data-chart-reference") ? paint?.stroke : paint?.fill) || `var(--stdlib-chart-c${(item.datum.seriesIndex ?? 0) % 8 + 1})`;
|
|
64
68
|
return `color-mix(in srgb, ${color} 72%, var(--k2b-chart-highlight-mix))`;
|
|
@@ -107,7 +111,22 @@ export function createChartInspector(options) {
|
|
|
107
111
|
});
|
|
108
112
|
};
|
|
109
113
|
const rawX = entry => entry.datum.values.find(field => field.key === "x")?.value;
|
|
110
|
-
const
|
|
114
|
+
const category = entry => options.kind() === "area" ? entry.datum.index : rawX(entry);
|
|
115
|
+
const seriesChart = () => options.kind() === "line" || options.kind() === "area" || options.kind() === "sparkline";
|
|
116
|
+
const updateLegend = items => {
|
|
117
|
+
const root = options.legend?.() ?? options.container();
|
|
118
|
+
for (const node of root?.querySelectorAll("[data-chart-legend-value]") ?? []) {
|
|
119
|
+
if (!items) {
|
|
120
|
+
node.textContent = node.getAttribute("data-default") ?? "";
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const series = Number(node.getAttribute("data-series-index"));
|
|
124
|
+
const field = items.find(item => item.datum.seriesIndex === series)?.datum.values.find(field => field.key === node.getAttribute("data-field"));
|
|
125
|
+
node.textContent = field ? field.formatted ?? (typeof field.value === "number" ? new Intl.NumberFormat(options.locale?.() ?? "en", {
|
|
126
|
+
maximumFractionDigits: 6
|
|
127
|
+
}).format(field.value) : field.value) : "—";
|
|
128
|
+
}
|
|
129
|
+
};
|
|
111
130
|
const clearHighlight = () => {
|
|
112
131
|
for (const entry of highlighted) {
|
|
113
132
|
entry.element.removeAttribute("data-inspected");
|
|
@@ -123,11 +142,17 @@ export function createChartInspector(options) {
|
|
|
123
142
|
options.container()?.removeAttribute("data-cursor-source");
|
|
124
143
|
pinned = false;
|
|
125
144
|
active = undefined;
|
|
145
|
+
updateLegend(undefined);
|
|
126
146
|
clearHighlight();
|
|
127
147
|
const container = options.container(),
|
|
128
148
|
id = options.tooltip()?.id;
|
|
129
149
|
if (container && id) describe(container, id, false);
|
|
130
150
|
options.container()?.removeAttribute("data-inspecting");
|
|
151
|
+
const inspected = options.container();
|
|
152
|
+
if (inspected) {
|
|
153
|
+
for (const name of ["left", "top", "width", "height"]) inspected.style.removeProperty(`--k2b-chart-band-${name}`);
|
|
154
|
+
if (!inspected.getAttribute("style")) inspected.removeAttribute("style");
|
|
155
|
+
}
|
|
131
156
|
const tooltip = options.tooltip();
|
|
132
157
|
if (tooltip) {
|
|
133
158
|
try {
|
|
@@ -157,14 +182,15 @@ export function createChartInspector(options) {
|
|
|
157
182
|
anchor = options.anchor(),
|
|
158
183
|
container = options.container();
|
|
159
184
|
if (!tooltip || !anchor || !container || !options.enabled()) return;
|
|
160
|
-
if (active === entry && tooltip.matches(":popover-open")) return;
|
|
185
|
+
if ((active === entry || seriesChart() && active && category(active) === category(entry)) && tooltip.matches(":popover-open")) return;
|
|
161
186
|
clearHighlight();
|
|
162
187
|
active = entry;
|
|
163
|
-
highlighted = options.kind() === "line" ? records().filter(candidate =>
|
|
188
|
+
highlighted = options.kind() === "line" || options.kind() === "area" ? records().filter(candidate => category(candidate) === category(entry)) : [entry];
|
|
164
189
|
for (const item of highlighted) {
|
|
165
190
|
item.element.style.setProperty("--k2b-chart-inspection-color", highlightColor(item));
|
|
166
191
|
item.element.setAttribute("data-inspected", "true");
|
|
167
192
|
}
|
|
193
|
+
updateLegend(highlighted);
|
|
168
194
|
const document = tooltip.ownerDocument;
|
|
169
195
|
const contents = highlighted.map(item => ({
|
|
170
196
|
item,
|
|
@@ -190,6 +216,7 @@ export function createChartInspector(options) {
|
|
|
190
216
|
}
|
|
191
217
|
contents.sort((a, b) => (a.item.datum.seriesIndex ?? 0) - (b.item.datum.seriesIndex ?? 0));
|
|
192
218
|
}
|
|
219
|
+
if (options.kind() === "area") contents.reverse();
|
|
193
220
|
tooltip.replaceChildren();
|
|
194
221
|
const sharedTitle = typeof x === "number" ? options.cursor?.()?.formatX?.(x) : undefined;
|
|
195
222
|
const commonTitle = sharedTitle ?? (contents.every(({
|
|
@@ -215,10 +242,10 @@ export function createChartInspector(options) {
|
|
|
215
242
|
for (const row of content.rows) {
|
|
216
243
|
const line = document.createElement("span");
|
|
217
244
|
line.className = "k2b-chart__tooltip-row";
|
|
218
|
-
if (options.kind() === "line") {
|
|
245
|
+
if (options.kind() === "line" || options.kind() === "area") {
|
|
219
246
|
const swatch = document.createElement("i");
|
|
220
247
|
swatch.setAttribute("aria-hidden", "true");
|
|
221
|
-
const series = container.querySelector(`.stdlib-chart-line.stdlib-chart-series-${(item.datum.seriesIndex ?? 0) % 8}`);
|
|
248
|
+
const series = container.querySelector(`.stdlib-chart-line.stdlib-chart-series-${(item.datum.seriesIndex ?? 0) % 8}, .k2b-area-edge-${(item.datum.seriesIndex ?? 0) % 8}`);
|
|
222
249
|
swatch.style.background = series ? getComputedStyle(series).stroke : `var(--stdlib-chart-c${(item.datum.seriesIndex ?? 0) % 8 + 1})`;
|
|
223
250
|
line.append(swatch);
|
|
224
251
|
}
|
|
@@ -230,13 +257,38 @@ export function createChartInspector(options) {
|
|
|
230
257
|
tooltip.append(line);
|
|
231
258
|
}
|
|
232
259
|
}
|
|
260
|
+
if (options.kind() === "area") {
|
|
261
|
+
const total = entry.datum.values.find(field => field.key === "total");
|
|
262
|
+
const totalLabel = container.querySelector("svg[data-chart-total-label]")?.getAttribute("data-chart-total-label");
|
|
263
|
+
if (total && totalLabel) {
|
|
264
|
+
const line = document.createElement("span");
|
|
265
|
+
line.className = "k2b-chart__tooltip-row";
|
|
266
|
+
const label = document.createElement("span");
|
|
267
|
+
label.textContent = `${totalLabel}: `;
|
|
268
|
+
const value = document.createElement("b");
|
|
269
|
+
value.textContent = total.formatted ?? String(total.value);
|
|
270
|
+
line.append(label, value);
|
|
271
|
+
tooltip.append(line);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
233
274
|
const rect = container.getBoundingClientRect(),
|
|
234
275
|
point = screenPoint(entry);
|
|
235
|
-
|
|
236
|
-
|
|
276
|
+
const slot = categoryBands().find(candidate => candidate.entry === entry);
|
|
277
|
+
// A renderer that draws its own band inside the category's mark keeps it; the overlay only fills the others.
|
|
278
|
+
const band = slot && !entry.element.querySelector(".k2b-chart-category-band") ? slot : undefined;
|
|
279
|
+
const rows = rowLayout(container);
|
|
280
|
+
// A column's tooltip waits at the top of the plot, so it stays put while the pointer moves within the column.
|
|
281
|
+
anchor.style.left = `${(slot && !rows ? (slot.left + slot.right) / 2 : point.x) - rect.left + container.scrollLeft}px`;
|
|
282
|
+
anchor.style.top = `${(slot && !rows ? slot.top : point.y) - rect.top + container.scrollTop}px`;
|
|
237
283
|
updatePlotBounds();
|
|
238
|
-
container.style.setProperty("--k2b-chart-inspection-x", `${point.x - rect.left}px`);
|
|
239
|
-
|
|
284
|
+
container.style.setProperty("--k2b-chart-inspection-x", `${point.x - rect.left + container.scrollLeft}px`);
|
|
285
|
+
if (band) {
|
|
286
|
+
container.style.setProperty("--k2b-chart-band-left", `${band.left - rect.left + container.scrollLeft}px`);
|
|
287
|
+
container.style.setProperty("--k2b-chart-band-top", `${band.top - rect.top + container.scrollTop}px`);
|
|
288
|
+
container.style.setProperty("--k2b-chart-band-width", `${band.right - band.left}px`);
|
|
289
|
+
container.style.setProperty("--k2b-chart-band-height", `${band.bottom - band.top}px`);
|
|
290
|
+
}
|
|
291
|
+
container.setAttribute("data-inspecting", seriesChart() ? "series" : band ? "category" : "datum");
|
|
240
292
|
describe(container, tooltip.id, true);
|
|
241
293
|
try {
|
|
242
294
|
if (!tooltip.matches(":popover-open")) tooltip.showPopover();
|
|
@@ -245,6 +297,50 @@ export function createChartInspector(options) {
|
|
|
245
297
|
/* SVG titles remain available without the Popover API. */
|
|
246
298
|
}
|
|
247
299
|
};
|
|
300
|
+
/**
|
|
301
|
+
* The screen slot of every category, halfway to its neighbours. A light band fills the inspected slot instead of
|
|
302
|
+
* dimming other marks or outlining a bar, and the pointer anywhere in a slot keeps the same category.
|
|
303
|
+
*/
|
|
304
|
+
const categoryBands = () => {
|
|
305
|
+
const role = categoryRoles[options.kind()];
|
|
306
|
+
const container = options.container();
|
|
307
|
+
if (!role || !container) return [];
|
|
308
|
+
const rows = rowLayout(container);
|
|
309
|
+
const slots = records().filter(entry => entry.datum.role === role).map(entry => ({
|
|
310
|
+
entry,
|
|
311
|
+
rect: entry.element.getBoundingClientRect()
|
|
312
|
+
}));
|
|
313
|
+
if (!slots.length) return [];
|
|
314
|
+
const guides = Array.from(container.querySelectorAll(".stdlib-chart-grid, .stdlib-chart-axis")).map(node => node.getBoundingClientRect());
|
|
315
|
+
// The band spans the plot across the categories: grid lines and every mark, so rows without value ticks, whose
|
|
316
|
+
// only guide is one vertical baseline, still get a band from the baseline to the longest bar.
|
|
317
|
+
const spans = [...guides, ...slots.map(slot => slot.rect)];
|
|
318
|
+
const start = Math.min(...spans.map(rect => rows ? rect.left : rect.top));
|
|
319
|
+
const end = Math.max(...spans.map(rect => rows ? rect.right : rect.bottom));
|
|
320
|
+
const center = rect => rows ? rect.top + rect.height / 2 : rect.left + rect.width / 2;
|
|
321
|
+
slots.sort((a, b) => center(a.rect) - center(b.rect));
|
|
322
|
+
return slots.map((slot, index) => {
|
|
323
|
+
const middle = center(slot.rect);
|
|
324
|
+
const previous = slots[index - 1],
|
|
325
|
+
next = slots[index + 1];
|
|
326
|
+
const half = previous || next ? Math.abs(center((next ?? previous).rect) - middle) / 2 : (rows ? slot.rect.height : slot.rect.width) * 0.75;
|
|
327
|
+
const low = previous ? (center(previous.rect) + middle) / 2 : middle - half;
|
|
328
|
+
const high = next ? (center(next.rect) + middle) / 2 : middle + half;
|
|
329
|
+
return rows ? {
|
|
330
|
+
entry: slot.entry,
|
|
331
|
+
left: start,
|
|
332
|
+
right: end,
|
|
333
|
+
top: low,
|
|
334
|
+
bottom: high
|
|
335
|
+
} : {
|
|
336
|
+
entry: slot.entry,
|
|
337
|
+
left: low,
|
|
338
|
+
right: high,
|
|
339
|
+
top: start,
|
|
340
|
+
bottom: end
|
|
341
|
+
};
|
|
342
|
+
});
|
|
343
|
+
};
|
|
248
344
|
const updatePlotBounds = () => {
|
|
249
345
|
const container = options.container();
|
|
250
346
|
if (!container) return;
|
|
@@ -293,6 +389,27 @@ export function createChartInspector(options) {
|
|
|
293
389
|
const direct = target?.closest("[data-chart-datum]");
|
|
294
390
|
const hit = direct ? byElement.get(direct) : undefined;
|
|
295
391
|
if (hit && nodes.includes(hit)) return hit;
|
|
392
|
+
const bands = categoryBands();
|
|
393
|
+
if (bands.length) {
|
|
394
|
+
// Marks of their own inside a category, such as box-plot outliers, keep their forgiving hit radius.
|
|
395
|
+
const role = categoryRoles[options.kind()];
|
|
396
|
+
let loose,
|
|
397
|
+
gap = 24;
|
|
398
|
+
for (const entry of nodes) {
|
|
399
|
+
if (entry.datum.role === role) continue;
|
|
400
|
+
const point = screenPoint(entry);
|
|
401
|
+
const distance = Math.hypot(point.x - x, point.y - y);
|
|
402
|
+
if (distance <= gap) {
|
|
403
|
+
gap = distance;
|
|
404
|
+
loose = entry;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
if (loose) return loose;
|
|
408
|
+
const rows = rowLayout(options.container());
|
|
409
|
+
const frame = options.container()?.getBoundingClientRect();
|
|
410
|
+
const inside = frame && x >= frame.left && x <= frame.right && y >= frame.top && y <= frame.bottom;
|
|
411
|
+
return inside ? bands.find(band => rows ? y >= band.top && y <= band.bottom : x >= band.left && x <= band.right)?.entry : undefined;
|
|
412
|
+
}
|
|
296
413
|
if (seriesChart()) {
|
|
297
414
|
const plot = updatePlotBounds();
|
|
298
415
|
// SVG transforms and DOM rectangles can round the same painted edge
|
|
@@ -367,14 +484,20 @@ export function createChartInspector(options) {
|
|
|
367
484
|
} else close();
|
|
368
485
|
});
|
|
369
486
|
};
|
|
487
|
+
let pointerFocusing = false;
|
|
370
488
|
const down = event => {
|
|
489
|
+
pointerFocusing = true;
|
|
371
490
|
pointerStart = {
|
|
372
491
|
x: event.clientX,
|
|
373
492
|
y: event.clientY
|
|
374
493
|
};
|
|
375
494
|
moved = false;
|
|
376
495
|
};
|
|
496
|
+
const up = () => {
|
|
497
|
+
pointerFocusing = false;
|
|
498
|
+
};
|
|
377
499
|
const click = event => {
|
|
500
|
+
pointerFocusing = false;
|
|
378
501
|
if (!options.enabled() || moved || event.target instanceof Element && event.target.closest("button,a")) return;
|
|
379
502
|
const entry = nearest(event.clientX, event.clientY, event.target instanceof Element ? event.target : null);
|
|
380
503
|
if (!entry) {
|
|
@@ -390,8 +513,12 @@ export function createChartInspector(options) {
|
|
|
390
513
|
};
|
|
391
514
|
const focus = event => {
|
|
392
515
|
if (event.target !== options.container() || !options.enabled()) return;
|
|
516
|
+
if (pointerFocusing && options.nav?.()?.pointer === false) {
|
|
517
|
+
pointerFocusing = false;
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
393
520
|
const nodes = visibleRecords();
|
|
394
|
-
const first = options.kind() === "line" ? sortedPoints.at(-1) : nodes[0];
|
|
521
|
+
const first = options.nav?.()?.last ? nodes.at(-1) : options.kind() === "line" ? sortedPoints.at(-1) : nodes[0];
|
|
395
522
|
if (first) show(first);
|
|
396
523
|
};
|
|
397
524
|
const key = event => {
|
|
@@ -422,10 +549,10 @@ export function createChartInspector(options) {
|
|
|
422
549
|
if (!["Home", "End", "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"].includes(event.key)) return false;
|
|
423
550
|
let nodes = visibleRecords();
|
|
424
551
|
if (seriesChart()) nodes = [...nodes].sort((a, b) => a.datum.anchor[0] - b.datum.anchor[0]);
|
|
425
|
-
if (options.kind() === "line") {
|
|
552
|
+
if (options.kind() === "line" || options.kind() === "area") {
|
|
426
553
|
const seen = new Set();
|
|
427
554
|
nodes = nodes.filter(entry => {
|
|
428
|
-
const x =
|
|
555
|
+
const x = category(entry);
|
|
429
556
|
if (seen.has(x)) return false;
|
|
430
557
|
seen.add(x);
|
|
431
558
|
return true;
|
|
@@ -434,7 +561,7 @@ export function createChartInspector(options) {
|
|
|
434
561
|
if (!nodes.length) return false;
|
|
435
562
|
event.preventDefault();
|
|
436
563
|
pinned = false;
|
|
437
|
-
let index = active ? options.kind() === "line" ? nodes.findIndex(entry =>
|
|
564
|
+
let index = active ? options.kind() === "line" || options.kind() === "area" ? nodes.findIndex(entry => category(entry) === category(active)) : nodes.indexOf(active) : -1;
|
|
438
565
|
if (event.key === "Home") index = 0;else if (event.key === "End") index = nodes.length - 1;else if (active?.datum.grid && ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(event.key)) {
|
|
439
566
|
const [x, y] = active.datum.grid;
|
|
440
567
|
const dx = event.key === "ArrowLeft" ? -1 : event.key === "ArrowRight" ? 1 : 0;
|
|
@@ -442,7 +569,9 @@ export function createChartInspector(options) {
|
|
|
442
569
|
const next = nodes.filter(entry => entry.datum.grid && (dx ? entry.datum.grid[1] === y && (entry.datum.grid[0] - x) * dx > 0 : entry.datum.grid[0] === x && (entry.datum.grid[1] - y) * dy > 0)).sort((a, b) => Math.abs(a.datum.grid[0] - x) + Math.abs(a.datum.grid[1] - y) - Math.abs(b.datum.grid[0] - x) - Math.abs(b.datum.grid[1] - y))[0];
|
|
443
570
|
if (next) index = nodes.indexOf(next);
|
|
444
571
|
} else index += event.key === "ArrowLeft" || event.key === "ArrowUp" ? -1 : 1;
|
|
445
|
-
|
|
572
|
+
const next = nodes[Math.max(0, Math.min(nodes.length - 1, index))];
|
|
573
|
+
options.nav?.()?.reveal?.(next.element);
|
|
574
|
+
show(next);
|
|
446
575
|
return true;
|
|
447
576
|
};
|
|
448
577
|
return {
|
|
@@ -452,6 +581,7 @@ export function createChartInspector(options) {
|
|
|
452
581
|
destroy: () => close(false),
|
|
453
582
|
move,
|
|
454
583
|
down,
|
|
584
|
+
up,
|
|
455
585
|
click,
|
|
456
586
|
focus,
|
|
457
587
|
key,
|
|
@@ -469,6 +599,7 @@ export function closeChartInspectionOnOutside(options) {
|
|
|
469
599
|
if (event.target instanceof Node && !options.container()?.contains(event.target)) options.close();
|
|
470
600
|
};
|
|
471
601
|
const scroll = event => {
|
|
602
|
+
if (event.target === options.container() && options.keepScroll?.()) return;
|
|
472
603
|
if (event.target instanceof Node && options.tooltip()?.contains(event.target)) return;
|
|
473
604
|
options.close();
|
|
474
605
|
};
|
|
@@ -502,25 +633,27 @@ export function inspectChart(container, options) {
|
|
|
502
633
|
if (addedTabindex) container.setAttribute("tabindex", "0");
|
|
503
634
|
const inspector = createChartInspector({
|
|
504
635
|
container: () => container,
|
|
636
|
+
locale: () => options.locale ?? "en",
|
|
637
|
+
legend: () => options.legend,
|
|
505
638
|
cursor: () => options.cursor,
|
|
506
639
|
tooltip: () => tooltip,
|
|
507
640
|
anchor: () => anchor,
|
|
508
641
|
kind: () => options.kind,
|
|
642
|
+
nav: () => options.nav,
|
|
509
643
|
enabled: () => true,
|
|
510
644
|
format: options.format,
|
|
511
645
|
select: selection => options.select?.(selection)
|
|
512
646
|
});
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
container.addEventListener("focusout", inspector.close);
|
|
519
|
-
container.addEventListener("keydown", inspector.key);
|
|
647
|
+
const listen = (name, listener) => {
|
|
648
|
+
container.addEventListener(name, listener);
|
|
649
|
+
return () => container.removeEventListener(name, listener);
|
|
650
|
+
};
|
|
651
|
+
const removeListeners = [listen("pointerdown", inspector.down), listen("pointerup", inspector.up), listen("pointercancel", inspector.up), listen("pointermove", inspector.move), listen("click", inspector.click), listen("pointerleave", inspector.leave), listen("focusin", inspector.focus), listen("focusout", inspector.close), listen("keydown", inspector.key)];
|
|
520
652
|
const removeOutside = closeChartInspectionOnOutside({
|
|
521
653
|
container: () => container,
|
|
522
654
|
tooltip: () => tooltip,
|
|
523
|
-
close: inspector.close
|
|
655
|
+
close: inspector.close,
|
|
656
|
+
keepScroll: () => options.nav?.keepScroll
|
|
524
657
|
});
|
|
525
658
|
const unlinkCursor = inspector.linkCursor(options.cursor);
|
|
526
659
|
let destroyed = false;
|
|
@@ -534,13 +667,7 @@ export function inspectChart(container, options) {
|
|
|
534
667
|
destroy() {
|
|
535
668
|
if (destroyed) return;
|
|
536
669
|
destroyed = true;
|
|
537
|
-
|
|
538
|
-
container.removeEventListener("pointermove", inspector.move);
|
|
539
|
-
container.removeEventListener("click", inspector.click);
|
|
540
|
-
container.removeEventListener("pointerleave", inspector.leave);
|
|
541
|
-
container.removeEventListener("focusin", inspector.focus);
|
|
542
|
-
container.removeEventListener("focusout", inspector.close);
|
|
543
|
-
container.removeEventListener("keydown", inspector.key);
|
|
670
|
+
for (const remove of removeListeners) remove();
|
|
544
671
|
removeOutside();
|
|
545
672
|
unlinkCursor();
|
|
546
673
|
inspector.destroy();
|