@k2b/ui 0.49.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/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/inputs/DatePicker.js +5 -4
- package/dist/browser/inputs/DatePicker.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 +7 -1
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/surfaces/BudgetList.js +281 -0
- package/dist/browser/surfaces/BudgetList.js.map +1 -0
- 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/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/inputs/DatePicker.js +5 -4
- package/dist/ssr/inputs/DatePicker.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 +7 -1
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/surfaces/BudgetList.js +170 -0
- package/dist/ssr/surfaces/BudgetList.js.map +1 -0
- 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/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 +5 -0
- package/dist/types/surfaces/BudgetList.d.ts +42 -0
- package/dist/types/surfaces/ProgressBar.d.ts +38 -2
- package/dist/types/surfaces/StatCell.d.ts +35 -2
- package/dist/types/surfaces/StatGrid.d.ts +3 -1
- package/dist/types/surfaces/budget-messages.d.ts +30 -0
- package/dist/types/surfaces/delta-badge.d.ts +10 -0
- package/dist/types/surfaces/index.d.ts +4 -3
- package/dist/types/surfaces/person-color.d.ts +2 -2
- package/dist/types/surfaces/stat-cell-messages.d.ts +19 -0
- package/dist/types/widgets/Dashboard.d.ts +42 -0
- package/dist/types/widgets/index.d.ts +1 -0
- package/package.json +7 -1
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
|
|
2
|
+
import { ssr as _$ssr } from "solid-js/web";
|
|
3
|
+
import { createComponent as _$createComponent } from "solid-js/web";
|
|
4
|
+
import { escape as _$escape } from "solid-js/web";
|
|
5
|
+
var _tmpl$ = ["<ul class=\"k2b-budget__list\">", "</ul>"],
|
|
6
|
+
_tmpl$2 = ["<li><span class=\"k2b-budget__swatch\" data-pattern=\"hatched\"></span>", "</li>"],
|
|
7
|
+
_tmpl$3 = ["<li><span class=\"k2b-budget__swatch\" data-pattern=\"over\"></span>", "</li>"],
|
|
8
|
+
_tmpl$4 = ["<ul class=\"k2b-budget__legend\" aria-hidden=\"true\"><li><span class=\"k2b-budget__swatch\" data-pattern=\"solid\"></span>", "</li>", "", "</ul>"],
|
|
9
|
+
_tmpl$5 = ["<div class=\"", "\">", "</div>"],
|
|
10
|
+
_tmpl$6 = ["<p class=\"k2b-budget__empty\">", "</p>"],
|
|
11
|
+
_tmpl$7 = ["<span class=\"k2b-budget__label\">", "</span>"],
|
|
12
|
+
_tmpl$8 = ["<span class=\"k2b-budget__amount\">", " <span>", "</span></span>"],
|
|
13
|
+
_tmpl$9 = ["<i", " aria-hidden=\"true\"></i>"],
|
|
14
|
+
_tmpl$0 = ["<span class=\"k2b-budget__hint\">", "", "</span>"],
|
|
15
|
+
_tmpl$1 = ["<li class=\"k2b-budget__row\"", ">", "</li>"],
|
|
16
|
+
_tmpl$10 = ["<span>", " <b>", "</b></span>"],
|
|
17
|
+
_tmpl$11 = ["<span class=\"k2b-budget__tip\"><b>", "</b><span>", " <b>", "</b></span>", "<span>", " <b>", "</b></span><span>", " <b>", "</b></span></span>"];
|
|
18
|
+
import { For, Show } from "solid-js";
|
|
19
|
+
import { Tooltip } from "../feedback/Tooltip";
|
|
20
|
+
import { useLocale } from "../intl/locale";
|
|
21
|
+
import { useBudgetMessages } from "./budget-messages";
|
|
22
|
+
import { budgetOverrun, budgetRatio, ProgressBar } from "./ProgressBar";
|
|
23
|
+
|
|
24
|
+
/** One budget: `used` is booked, `expected` comes on top; over the budget is `used + expected - limit`. */
|
|
25
|
+
|
|
26
|
+
/** "near" from 80 % of the budget, "over" beyond it. */
|
|
27
|
+
|
|
28
|
+
/** The figures of one budget row; the share counts booked and expected together. */
|
|
29
|
+
export const budgetState = item => {
|
|
30
|
+
const used = Number.isFinite(item.used) ? Math.max(0, item.used) : 0;
|
|
31
|
+
const expected = item.expected !== undefined && Number.isFinite(item.expected) ? Math.max(0, item.expected) : 0;
|
|
32
|
+
const limit = Number.isFinite(item.limit) ? Math.max(0, item.limit) : 0;
|
|
33
|
+
const total = used + expected;
|
|
34
|
+
const over = budgetOverrun(total, limit);
|
|
35
|
+
const ratio = budgetRatio(total, limit);
|
|
36
|
+
// The same float tolerance as the overrun: 0.7 + 0.1 of 1 is exactly 80 %.
|
|
37
|
+
const level = over > 0 ? "over" : ratio >= 0.8 - 1e-9 ? "near" : "ok";
|
|
38
|
+
return {
|
|
39
|
+
used,
|
|
40
|
+
expected,
|
|
41
|
+
limit,
|
|
42
|
+
total,
|
|
43
|
+
over,
|
|
44
|
+
free: over > 0 ? 0 : Math.max(0, limit - total),
|
|
45
|
+
ratio,
|
|
46
|
+
level
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Budgets as rows: label and "spent of budget", a bar with booked (solid), expected (hatched) and over the budget
|
|
52
|
+
* (red, with a mark at the limit), and a hint that turns amber from 80 % and red beyond the budget.
|
|
53
|
+
*/
|
|
54
|
+
export function BudgetList(props) {
|
|
55
|
+
const locale = useLocale();
|
|
56
|
+
const t = useBudgetMessages(() => props.locale);
|
|
57
|
+
const money = value => new Intl.NumberFormat(props.locale ?? locale(), {
|
|
58
|
+
style: "currency",
|
|
59
|
+
currency: props.currency,
|
|
60
|
+
minimumFractionDigits: props.decimals ?? 0,
|
|
61
|
+
maximumFractionDigits: props.decimals ?? 0
|
|
62
|
+
}).format(value);
|
|
63
|
+
const states = () => props.items.map(item => ({
|
|
64
|
+
item,
|
|
65
|
+
state: budgetState(item)
|
|
66
|
+
}));
|
|
67
|
+
const anyExpected = () => states().some(({
|
|
68
|
+
state
|
|
69
|
+
}) => state.expected > 0);
|
|
70
|
+
const anyOver = () => states().some(({
|
|
71
|
+
state
|
|
72
|
+
}) => state.over > 0);
|
|
73
|
+
return _$ssr(_tmpl$5, `k2b-budget ${_$escape(props.class ?? "", true)}`, _$escape(_$createComponent(Show, {
|
|
74
|
+
get when() {
|
|
75
|
+
return props.items.length;
|
|
76
|
+
},
|
|
77
|
+
get fallback() {
|
|
78
|
+
return _$ssr(_tmpl$6, _$escape(props.empty));
|
|
79
|
+
},
|
|
80
|
+
get children() {
|
|
81
|
+
return [_$ssr(_tmpl$, _$escape(_$createComponent(For, {
|
|
82
|
+
get each() {
|
|
83
|
+
return states();
|
|
84
|
+
},
|
|
85
|
+
children: ({
|
|
86
|
+
item,
|
|
87
|
+
state
|
|
88
|
+
}) => _$ssr(_tmpl$1, _$ssrAttribute("data-level", _$escape(state.level, true), false), _$escape(_$createComponent(Tooltip.Anchor, {
|
|
89
|
+
"class": "k2b-budget__anchor",
|
|
90
|
+
tabIndex: 0,
|
|
91
|
+
get content() {
|
|
92
|
+
return _$ssr(_tmpl$11, _$escape(item.label), _$escape(t().used), _$escape(money(state.used)), _$escape(_$createComponent(Show, {
|
|
93
|
+
get when() {
|
|
94
|
+
return state.expected > 0;
|
|
95
|
+
},
|
|
96
|
+
get children() {
|
|
97
|
+
return _$ssr(_tmpl$10, _$escape(t().expected), _$escape(money(state.expected)));
|
|
98
|
+
}
|
|
99
|
+
})), _$escape(t().budget), _$escape(money(state.limit)), state.over > 0 ? _$escape(t().overBy) : _$escape(t().left), _$escape(money(state.over > 0 ? state.over : state.free)));
|
|
100
|
+
},
|
|
101
|
+
get children() {
|
|
102
|
+
return [_$ssr(_tmpl$7, _$escape(item.label)), _$ssr(_tmpl$8, _$escape(money(state.total)), _$escape(t().of({
|
|
103
|
+
limit: money(state.limit)
|
|
104
|
+
}))), _$createComponent(ProgressBar, {
|
|
105
|
+
"class": "k2b-budget__bar",
|
|
106
|
+
size: "sm",
|
|
107
|
+
get label() {
|
|
108
|
+
return item.label;
|
|
109
|
+
},
|
|
110
|
+
get segments() {
|
|
111
|
+
return [{
|
|
112
|
+
value: state.used
|
|
113
|
+
}, {
|
|
114
|
+
value: state.expected,
|
|
115
|
+
pattern: "hatched"
|
|
116
|
+
}];
|
|
117
|
+
},
|
|
118
|
+
get limit() {
|
|
119
|
+
return state.limit;
|
|
120
|
+
},
|
|
121
|
+
get valueText() {
|
|
122
|
+
return t().valueText({
|
|
123
|
+
used: money(state.used),
|
|
124
|
+
expected: state.expected > 0 ? money(state.expected) : undefined,
|
|
125
|
+
limit: money(state.limit)
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}), _$ssr(_tmpl$0, _$escape(_$createComponent(Show, {
|
|
129
|
+
get when() {
|
|
130
|
+
return state.level !== "ok";
|
|
131
|
+
},
|
|
132
|
+
get children() {
|
|
133
|
+
return _$ssr(_tmpl$9, _$ssrAttribute("class", state.level === "over" ? "ti ti-alert-circle" : "ti ti-alert-triangle", false));
|
|
134
|
+
}
|
|
135
|
+
})), state.level === "over" ? _$escape(t().over({
|
|
136
|
+
amount: money(state.over)
|
|
137
|
+
})) : state.level === "near" ? _$escape(t().near({
|
|
138
|
+
amount: money(state.free)
|
|
139
|
+
})) : _$escape(t().free({
|
|
140
|
+
amount: money(state.free)
|
|
141
|
+
})))];
|
|
142
|
+
}
|
|
143
|
+
})))
|
|
144
|
+
}))), _$createComponent(Show, {
|
|
145
|
+
get when() {
|
|
146
|
+
return props.legend !== false;
|
|
147
|
+
},
|
|
148
|
+
get children() {
|
|
149
|
+
return _$ssr(_tmpl$4, _$escape(t().used), _$escape(_$createComponent(Show, {
|
|
150
|
+
get when() {
|
|
151
|
+
return anyExpected();
|
|
152
|
+
},
|
|
153
|
+
get children() {
|
|
154
|
+
return _$ssr(_tmpl$2, _$escape(t().expected));
|
|
155
|
+
}
|
|
156
|
+
})), _$escape(_$createComponent(Show, {
|
|
157
|
+
get when() {
|
|
158
|
+
return anyOver();
|
|
159
|
+
},
|
|
160
|
+
get children() {
|
|
161
|
+
return _$ssr(_tmpl$3, _$escape(t().overLegend));
|
|
162
|
+
}
|
|
163
|
+
})));
|
|
164
|
+
}
|
|
165
|
+
})];
|
|
166
|
+
}
|
|
167
|
+
})));
|
|
168
|
+
}
|
|
169
|
+
export default BudgetList;
|
|
170
|
+
//# sourceMappingURL=BudgetList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["surfaces/BudgetList.tsx"],"sourcesContent":["import { For, type JSX, Show } from \"solid-js\";\nimport { Tooltip } from \"../feedback/Tooltip\";\nimport { useLocale } from \"../intl/locale\";\nimport { useBudgetMessages } from \"./budget-messages\";\nimport { budgetOverrun, budgetRatio, ProgressBar } from \"./ProgressBar\";\n\n/** One budget: `used` is booked, `expected` comes on top; over the budget is `used + expected - limit`. */\nexport type BudgetItem = { id?: string; label: string; used: number; expected?: number; limit: number };\n\nexport type BudgetListProps = {\n items: readonly BudgetItem[];\n /** ISO 4217 currency code, e.g. `\"EUR\"`. */\n currency: string;\n /** Explicit locale override; defaults to the inherited render locale. */\n locale?: string;\n /** Fixed fraction digits. Defaults to 0. */\n decimals?: number;\n /** The sentence shown when there is no budget. */\n empty?: string;\n /** Hides the legend under the rows when the host explains the colours elsewhere. */\n legend?: boolean;\n class?: string;\n};\n\n/** \"near\" from 80 % of the budget, \"over\" beyond it. */\nexport type BudgetLevel = \"ok\" | \"near\" | \"over\";\n\n/** The figures of one budget row; the share counts booked and expected together. */\nexport const budgetState = (item: Pick<BudgetItem, \"used\" | \"expected\" | \"limit\">) => {\n const used = Number.isFinite(item.used) ? Math.max(0, item.used) : 0;\n const expected = item.expected !== undefined && Number.isFinite(item.expected) ? Math.max(0, item.expected) : 0;\n const limit = Number.isFinite(item.limit) ? Math.max(0, item.limit) : 0;\n const total = used + expected;\n const over = budgetOverrun(total, limit);\n const ratio = budgetRatio(total, limit);\n // The same float tolerance as the overrun: 0.7 + 0.1 of 1 is exactly 80 %.\n const level: BudgetLevel = over > 0 ? \"over\" : ratio >= 0.8 - 1e-9 ? \"near\" : \"ok\";\n return { used, expected, limit, total, over, free: over > 0 ? 0 : Math.max(0, limit - total), ratio, level };\n};\n\n/**\n * Budgets as rows: label and \"spent of budget\", a bar with booked (solid), expected (hatched) and over the budget\n * (red, with a mark at the limit), and a hint that turns amber from 80 % and red beyond the budget.\n */\nexport function BudgetList(props: BudgetListProps): JSX.Element {\n const locale = useLocale();\n const t = useBudgetMessages(() => props.locale);\n const money = (value: number) =>\n new Intl.NumberFormat(props.locale ?? locale(), {\n style: \"currency\",\n currency: props.currency,\n minimumFractionDigits: props.decimals ?? 0,\n maximumFractionDigits: props.decimals ?? 0,\n }).format(value);\n const states = () => props.items.map((item) => ({ item, state: budgetState(item) }));\n const anyExpected = () => states().some(({ state }) => state.expected > 0);\n const anyOver = () => states().some(({ state }) => state.over > 0);\n return (\n <div class={`k2b-budget ${props.class ?? \"\"}`}>\n <Show when={props.items.length} fallback={<p class=\"k2b-budget__empty\">{props.empty}</p>}>\n <ul class=\"k2b-budget__list\">\n <For each={states()}>\n {({ item, state }) => (\n <li class=\"k2b-budget__row\" data-level={state.level}>\n <Tooltip.Anchor\n class=\"k2b-budget__anchor\"\n tabIndex={0}\n content={\n <span class=\"k2b-budget__tip\">\n <b>{item.label}</b>\n <span>\n {t().used} <b>{money(state.used)}</b>\n </span>\n <Show when={state.expected > 0}>\n <span>\n {t().expected} <b>{money(state.expected)}</b>\n </span>\n </Show>\n <span>\n {t().budget} <b>{money(state.limit)}</b>\n </span>\n <span>\n {state.over > 0 ? t().overBy : t().left} <b>{money(state.over > 0 ? state.over : state.free)}</b>\n </span>\n </span>\n }\n >\n <span class=\"k2b-budget__label\">{item.label}</span>\n <span class=\"k2b-budget__amount\">\n {money(state.total)} <span>{t().of({ limit: money(state.limit) })}</span>\n </span>\n <ProgressBar\n class=\"k2b-budget__bar\"\n size=\"sm\"\n label={item.label}\n segments={[{ value: state.used }, { value: state.expected, pattern: \"hatched\" }]}\n limit={state.limit}\n valueText={t().valueText({\n used: money(state.used),\n expected: state.expected > 0 ? money(state.expected) : undefined,\n limit: money(state.limit),\n })}\n />\n <span class=\"k2b-budget__hint\">\n <Show when={state.level !== \"ok\"}>\n <i class={state.level === \"over\" ? \"ti ti-alert-circle\" : \"ti ti-alert-triangle\"} aria-hidden=\"true\" />\n </Show>\n {state.level === \"over\"\n ? t().over({ amount: money(state.over) })\n : state.level === \"near\"\n ? t().near({ amount: money(state.free) })\n : t().free({ amount: money(state.free) })}\n </span>\n </Tooltip.Anchor>\n </li>\n )}\n </For>\n </ul>\n <Show when={props.legend !== false}>\n <ul class=\"k2b-budget__legend\" aria-hidden=\"true\">\n <li>\n <span class=\"k2b-budget__swatch\" data-pattern=\"solid\" />\n {t().used}\n </li>\n <Show when={anyExpected()}>\n <li>\n <span class=\"k2b-budget__swatch\" data-pattern=\"hatched\" />\n {t().expected}\n </li>\n </Show>\n <Show when={anyOver()}>\n <li>\n <span class=\"k2b-budget__swatch\" data-pattern=\"over\" />\n {t().overLegend}\n </li>\n </Show>\n </ul>\n </Show>\n </Show>\n </div>\n );\n}\n\nexport default BudgetList;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,13 +1,104 @@
|
|
|
1
|
-
import { ssr as _$ssr } from "solid-js/web";
|
|
2
1
|
import { ssrStyle as _$ssrStyle } from "solid-js/web";
|
|
2
|
+
import { ssr as _$ssr } from "solid-js/web";
|
|
3
|
+
import { createComponent as _$createComponent } from "solid-js/web";
|
|
3
4
|
import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
|
|
4
5
|
import { escape as _$escape } from "solid-js/web";
|
|
5
|
-
var _tmpl$ = ["<div class=\"", "\"", "><div class=\"k2b-progress__track\" role=\"progressbar\"", " aria-valuemin=\"0\" aria-valuemax=\"100\"", "
|
|
6
|
-
_tmpl$2 = ["<
|
|
6
|
+
var _tmpl$ = ["<div class=\"", "\"", "><div class=\"k2b-progress__track\" role=\"progressbar\"", " aria-valuemin=\"0\" aria-valuemax=\"100\"", ">", "</div>", "</div>"],
|
|
7
|
+
_tmpl$2 = ["<div class=\"k2b-progress__value\" style=\"", "\"></div>"],
|
|
8
|
+
_tmpl$3 = ["<span class=\"k2b-progress__limit\" aria-hidden=\"true\" style=\"", "\"></span>"],
|
|
9
|
+
_tmpl$4 = ["<div class=\"k2b-progress__segment\"", " style=\"", "\"></div>"],
|
|
10
|
+
_tmpl$5 = ["<span class=\"k2b-progress__percent\">", "</span>"];
|
|
11
|
+
import { For, Show } from "solid-js";
|
|
12
|
+
|
|
13
|
+
/** One part of a segmented bar, in the unit of `limit`. `"hatched"` marks an expected, not yet booked part. */
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Sum minus limit, without float residue: `0.1 + 0.2` against `0.3` is not over. Amounts within a billionth of the
|
|
17
|
+
* larger of both count as equal.
|
|
18
|
+
*/
|
|
19
|
+
export const budgetOverrun = (total, limit) => {
|
|
20
|
+
const over = total - limit;
|
|
21
|
+
return over > Math.max(1, Math.abs(total), Math.abs(limit)) * 1e-9 ? over : 0;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/** Sum over limit; an empty budget with spending is infinitely full. */
|
|
25
|
+
export const budgetRatio = (total, limit) => limit > 0 ? total / limit : total > 0 ? Number.POSITIVE_INFINITY : 0;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The drawn parts of a segmented bar, each as a percent of the track. The track spans the larger of the limit and the
|
|
29
|
+
* sum, so an overrun stays visible: segments fill up to the limit in order, the rest is one "over" part, and `mark`
|
|
30
|
+
* places the limit line (only when the sum goes beyond it). Without `limit` the segments fill the track; a limit of 0,
|
|
31
|
+
* below 0 or not finite is an empty budget, so any spending is over it.
|
|
32
|
+
*/
|
|
33
|
+
export const progressBarParts = (segments, limit) => {
|
|
34
|
+
const values = segments.map(segment => ({
|
|
35
|
+
pattern: segment.pattern ?? "solid",
|
|
36
|
+
value: Number.isFinite(segment.value) ? Math.max(0, segment.value) : 0
|
|
37
|
+
}));
|
|
38
|
+
const total = values.reduce((sum, segment) => sum + segment.value, 0);
|
|
39
|
+
const budget = limit === undefined ? total : Number.isFinite(limit) ? Math.max(0, limit) : 0;
|
|
40
|
+
const scale = Math.max(budget, total);
|
|
41
|
+
if (scale <= 0) return {
|
|
42
|
+
parts: [],
|
|
43
|
+
total,
|
|
44
|
+
over: 0,
|
|
45
|
+
mark: null,
|
|
46
|
+
ratio: 0
|
|
47
|
+
};
|
|
48
|
+
const parts = [];
|
|
49
|
+
let filled = 0;
|
|
50
|
+
for (const segment of values) {
|
|
51
|
+
const inside = Math.max(0, Math.min(segment.value, budget - filled));
|
|
52
|
+
if (inside > 0) parts.push({
|
|
53
|
+
pattern: segment.pattern,
|
|
54
|
+
width: inside / scale * 100
|
|
55
|
+
});
|
|
56
|
+
filled += segment.value;
|
|
57
|
+
}
|
|
58
|
+
const over = budgetOverrun(total, budget);
|
|
59
|
+
if (over > 0) parts.push({
|
|
60
|
+
pattern: "over",
|
|
61
|
+
width: over / scale * 100
|
|
62
|
+
});
|
|
63
|
+
return {
|
|
64
|
+
parts,
|
|
65
|
+
total,
|
|
66
|
+
over,
|
|
67
|
+
mark: over > 0 ? budget / scale * 100 : null,
|
|
68
|
+
ratio: budgetRatio(total, budget)
|
|
69
|
+
};
|
|
70
|
+
};
|
|
7
71
|
const clamp = value => Number.isFinite(value) ? Math.max(0, Math.min(100, Math.round(value))) : 0;
|
|
8
72
|
export function ProgressBar(props) {
|
|
9
|
-
const
|
|
10
|
-
|
|
73
|
+
const segmented = () => props.segments ? progressBarParts(props.segments, props.limit) : null;
|
|
74
|
+
// With segments the share always comes from them; `value` only drives the plain bar.
|
|
75
|
+
const percent = () => {
|
|
76
|
+
const bar = segmented();
|
|
77
|
+
if (!bar) return clamp(props.value ?? 0);
|
|
78
|
+
return Number.isFinite(bar.ratio) ? Math.max(0, Math.round(bar.ratio * 100)) : null;
|
|
79
|
+
};
|
|
80
|
+
const shown = () => percent() ?? 100;
|
|
81
|
+
return _$ssr(_tmpl$, `k2b-progress ${_$escape(props.class ?? "", true)}`, _$ssrAttribute("data-size", _$escape(props.size ?? "md", true), false) + _$ssrAttribute("data-tone", _$escape(props.tone ?? "info", true), false) + _$ssrAttribute("data-segmented", segmented() ? "" : _$escape(undefined, true), false), _$ssrAttribute("aria-label", _$escape(props.label, true), false), _$ssrAttribute("aria-valuenow", _$escape(Math.min(100, shown()), true), false) + _$ssrAttribute("aria-valuetext", _$escape(props.valueText ?? (segmented() ? percent() === null ? "∞" : `${percent()}%` : undefined), true), false), _$escape(_$createComponent(Show, {
|
|
82
|
+
get when() {
|
|
83
|
+
return segmented();
|
|
84
|
+
},
|
|
85
|
+
get fallback() {
|
|
86
|
+
return _$ssr(_tmpl$2, _$ssrStyle(`width: ${shown()}%`));
|
|
87
|
+
},
|
|
88
|
+
children: bar => [_$createComponent(For, {
|
|
89
|
+
get each() {
|
|
90
|
+
return bar().parts;
|
|
91
|
+
},
|
|
92
|
+
children: part => _$ssr(_tmpl$4, _$ssrAttribute("data-pattern", _$escape(part.pattern, true), false), _$ssrStyle(`width: ${part.width.toFixed(3)}%`))
|
|
93
|
+
}), _$createComponent(Show, {
|
|
94
|
+
get when() {
|
|
95
|
+
return bar().mark !== null;
|
|
96
|
+
},
|
|
97
|
+
get children() {
|
|
98
|
+
return _$ssr(_tmpl$3, _$ssrStyle(`left: ${(bar().mark ?? 0).toFixed(3)}%`));
|
|
99
|
+
}
|
|
100
|
+
})]
|
|
101
|
+
})), props.showValue ? _$ssr(_tmpl$5, percent() === null ? "∞" : `${_$escape(percent())}%`) : _$escape(null));
|
|
11
102
|
}
|
|
12
103
|
export default ProgressBar;
|
|
13
104
|
//# sourceMappingURL=ProgressBar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["surfaces/ProgressBar.tsx"],"sourcesContent":["import type
|
|
1
|
+
{"version":3,"names":[],"sources":["surfaces/ProgressBar.tsx"],"sourcesContent":["import { For, type JSX, Show } from \"solid-js\";\nimport type { IntentTone } from \"../semantics\";\n\nexport type ProgressBarTone = Extract<IntentTone, \"info\" | \"success\" | \"warning\" | \"danger\">;\n\n/** One part of a segmented bar, in the unit of `limit`. `\"hatched\"` marks an expected, not yet booked part. */\nexport type ProgressBarSegment = { value: number; pattern?: \"solid\" | \"hatched\" };\n\nexport type ProgressBarProps = {\n /** Percent from 0 to 100. With `segments`, the share of `limit` the segments fill. */\n value?: number;\n size?: \"xs\" | \"sm\" | \"md\";\n tone?: ProgressBarTone;\n showValue?: boolean;\n label: string;\n /** Parts drawn in order, such as booked and expected spending. Negative and non-finite values count as 0. */\n segments?: readonly ProgressBarSegment[];\n /** The budget the segments fill. What goes beyond it is drawn red, with a mark at the limit. */\n limit?: number;\n /** Spoken value, such as \"1,240 € of 1,500 €\"; defaults to the percent. */\n valueText?: string;\n class?: string;\n};\n\nexport type ProgressBarPart = { pattern: \"solid\" | \"hatched\" | \"over\"; width: number };\n\n/**\n * Sum minus limit, without float residue: `0.1 + 0.2` against `0.3` is not over. Amounts within a billionth of the\n * larger of both count as equal.\n */\nexport const budgetOverrun = (total: number, limit: number): number => {\n const over = total - limit;\n return over > Math.max(1, Math.abs(total), Math.abs(limit)) * 1e-9 ? over : 0;\n};\n\n/** Sum over limit; an empty budget with spending is infinitely full. */\nexport const budgetRatio = (total: number, limit: number): number => (limit > 0 ? total / limit : total > 0 ? Number.POSITIVE_INFINITY : 0);\n\n/**\n * The drawn parts of a segmented bar, each as a percent of the track. The track spans the larger of the limit and the\n * sum, so an overrun stays visible: segments fill up to the limit in order, the rest is one \"over\" part, and `mark`\n * places the limit line (only when the sum goes beyond it). Without `limit` the segments fill the track; a limit of 0,\n * below 0 or not finite is an empty budget, so any spending is over it.\n */\nexport const progressBarParts = (\n segments: readonly ProgressBarSegment[],\n limit?: number,\n): { parts: ProgressBarPart[]; total: number; over: number; mark: number | null; ratio: number } => {\n const values = segments.map((segment) => ({\n pattern: segment.pattern ?? \"solid\",\n value: Number.isFinite(segment.value) ? Math.max(0, segment.value) : 0,\n }));\n const total = values.reduce((sum, segment) => sum + segment.value, 0);\n const budget = limit === undefined ? total : Number.isFinite(limit) ? Math.max(0, limit) : 0;\n const scale = Math.max(budget, total);\n if (scale <= 0) return { parts: [], total, over: 0, mark: null, ratio: 0 };\n const parts: ProgressBarPart[] = [];\n let filled = 0;\n for (const segment of values) {\n const inside = Math.max(0, Math.min(segment.value, budget - filled));\n if (inside > 0) parts.push({ pattern: segment.pattern, width: (inside / scale) * 100 });\n filled += segment.value;\n }\n const over = budgetOverrun(total, budget);\n if (over > 0) parts.push({ pattern: \"over\", width: (over / scale) * 100 });\n return { parts, total, over, mark: over > 0 ? (budget / scale) * 100 : null, ratio: budgetRatio(total, budget) };\n};\n\nconst clamp = (value: number) => (Number.isFinite(value) ? Math.max(0, Math.min(100, Math.round(value))) : 0);\n\nexport function ProgressBar(props: ProgressBarProps): JSX.Element {\n const segmented = () => (props.segments ? progressBarParts(props.segments, props.limit) : null);\n // With segments the share always comes from them; `value` only drives the plain bar.\n const percent = () => {\n const bar = segmented();\n if (!bar) return clamp(props.value ?? 0);\n return Number.isFinite(bar.ratio) ? Math.max(0, Math.round(bar.ratio * 100)) : null;\n };\n const shown = () => percent() ?? 100;\n return (\n <div\n class={`k2b-progress ${props.class ?? \"\"}`}\n data-size={props.size ?? \"md\"}\n data-tone={props.tone ?? \"info\"}\n data-segmented={segmented() ? \"\" : undefined}\n >\n <div\n class=\"k2b-progress__track\"\n role=\"progressbar\"\n aria-label={props.label}\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n aria-valuenow={Math.min(100, shown())}\n aria-valuetext={props.valueText ?? (segmented() ? (percent() === null ? \"∞\" : `${percent()}%`) : undefined)}\n >\n <Show when={segmented()} fallback={<div class=\"k2b-progress__value\" style={`width: ${shown()}%`} />}>\n {(bar) => (\n <>\n <For each={bar().parts}>\n {(part) => <div class=\"k2b-progress__segment\" data-pattern={part.pattern} style={`width: ${part.width.toFixed(3)}%`} />}\n </For>\n <Show when={bar().mark !== null}>\n <span class=\"k2b-progress__limit\" aria-hidden=\"true\" style={`left: ${(bar().mark ?? 0).toFixed(3)}%`} />\n </Show>\n </>\n )}\n </Show>\n </div>\n {props.showValue ? <span class=\"k2b-progress__percent\">{percent() === null ? \"∞\" : `${percent()}%`}</span> : null}\n </div>\n );\n}\n\nexport default ProgressBar;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,25 +1,46 @@
|
|
|
1
|
-
import { createComponent as _$createComponent } from "solid-js/web";
|
|
2
1
|
import { memo as _$memo } from "solid-js/web";
|
|
3
2
|
import { ssr as _$ssr } from "solid-js/web";
|
|
4
3
|
import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
|
|
5
4
|
import { escape as _$escape } from "solid-js/web";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
_tmpl$
|
|
9
|
-
_tmpl$
|
|
10
|
-
_tmpl$
|
|
11
|
-
_tmpl$
|
|
12
|
-
_tmpl$
|
|
13
|
-
_tmpl$
|
|
14
|
-
|
|
5
|
+
import { createComponent as _$createComponent } from "solid-js/web";
|
|
6
|
+
var _tmpl$ = ["<div class=\"k2b-stat-cell__head\">", "<span class=\"k2b-stat-cell__label\"", ">", "</span></div>"],
|
|
7
|
+
_tmpl$2 = "<span class=\"k2b-stat-cell__skeleton k2b-skeleton\" data-part=\"value\" aria-hidden=\"true\"></span>",
|
|
8
|
+
_tmpl$3 = ["<span class=\"k2b-sr-only\">", "</span>"],
|
|
9
|
+
_tmpl$4 = ["<span class=\"k2b-stat-cell__error\"><i class=\"ti ti-alert-circle\" aria-hidden=\"true\"></i>", "</span>"],
|
|
10
|
+
_tmpl$5 = ["<div class=\"k2b-stat-cell__main\">", "</div>"],
|
|
11
|
+
_tmpl$6 = "<span class=\"k2b-stat-cell__skeleton k2b-skeleton\" data-part=\"support\" aria-hidden=\"true\"></span>",
|
|
12
|
+
_tmpl$7 = ["<div class=\"k2b-stat-cell__support\">", "</div>"],
|
|
13
|
+
_tmpl$8 = ["<span class=\"k2b-stat-cell__icon k2b-icon-tile\"", " aria-hidden=\"true\"><i", "></i></span>"],
|
|
14
|
+
_tmpl$9 = ["<span class=\"", "\"", ">", "</span>"],
|
|
15
|
+
_tmpl$0 = ["<span class=\"k2b-stat-cell__sub\">", " ", "</span>"],
|
|
16
|
+
_tmpl$1 = ["<span class=\"k2b-stat-cell__sub\">", "</span>"],
|
|
17
|
+
_tmpl$10 = ["<i class=\"", "\"", " aria-hidden=\"true\"></i>"],
|
|
18
|
+
_tmpl$11 = ["<span class=\"k2b-stat-cell__accent\"", "><i", " aria-hidden=\"true\"></i>", "</span>"],
|
|
19
|
+
_tmpl$12 = ["<span class=\"k2b-stat-cell__stale\"><i class=\"ti ti-clock-exclamation\" aria-hidden=\"true\"></i>", "</span>"],
|
|
20
|
+
_tmpl$13 = ["<button type=\"button\" class=\"k2b-stat-cell__retry\">", "</button>"],
|
|
21
|
+
_tmpl$14 = ["<a", " class=\"k2b-stat-cell k2b-stat-cell--link\"", "><i class=\"ti ti-external-link k2b-stat-cell__link-icon\" aria-hidden=\"true\"></i>", "</a>"],
|
|
22
|
+
_tmpl$15 = ["<div class=\"k2b-stat-cell\"", ">", "</div>"];
|
|
23
|
+
import { Match, Show, Switch } from "solid-js";
|
|
15
24
|
import Chart from "../content/Chart";
|
|
16
25
|
import { useLocale } from "../intl/locale";
|
|
26
|
+
import { DeltaBadge } from "./delta-badge";
|
|
17
27
|
import { useStatGridSize, useStatGridSurface } from "./StatGrid";
|
|
28
|
+
import { useStatCellMessages } from "./stat-cell-messages";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The change against a comparison period. `unit: "ratio"` (default) reads `0.082` as `+8.2 %`; `"points"` is the
|
|
32
|
+
* difference of two shares in ratio units, so `0.031` reads `+3.1 pts`. Only with `better` does the badge carry a tone
|
|
33
|
+
* and say "better" or "worse"; without it the change stays unrated.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/** The value the change compares against, shown under the figure, such as "Last month 44,560". */
|
|
37
|
+
|
|
18
38
|
function Body(props) {
|
|
19
39
|
const gridSize = useStatGridSize();
|
|
20
40
|
const size = () => props.size ?? gridSize;
|
|
21
41
|
const accent = () => props.accent;
|
|
22
42
|
const locale = useLocale();
|
|
43
|
+
const t = useStatCellMessages();
|
|
23
44
|
const defaultTrendTooltip = ({
|
|
24
45
|
datum
|
|
25
46
|
}) => {
|
|
@@ -33,71 +54,156 @@ function Body(props) {
|
|
|
33
54
|
}]
|
|
34
55
|
};
|
|
35
56
|
};
|
|
36
|
-
|
|
57
|
+
const compareValue = () => {
|
|
58
|
+
const value = props.compare?.value;
|
|
59
|
+
return typeof value === "number" ? new Intl.NumberFormat(locale()).format(value) : value;
|
|
60
|
+
};
|
|
61
|
+
const empty = () => props.value === null || props.value === undefined || props.value === "";
|
|
62
|
+
return [_$ssr(_tmpl$, _$escape(_$createComponent(Show, {
|
|
37
63
|
get when() {
|
|
38
|
-
return
|
|
64
|
+
return props.icon;
|
|
65
|
+
},
|
|
66
|
+
children: icon => _$ssr(_tmpl$8, _$ssrAttribute("data-tone", _$escape(props.tone ?? "zinc", true), false), _$ssrAttribute("class", _$escape(icon(), true), false))
|
|
67
|
+
})), _$ssrAttribute("data-size", _$escape(size(), true), false), _$escape(props.label)), _$ssr(_tmpl$5, _$escape(_$createComponent(Switch, {
|
|
68
|
+
get fallback() {
|
|
69
|
+
return [_$ssr(_tmpl$9, `k2b-stat-cell__value ${_$escape(props.valueClass ?? "", true)}`, _$ssrAttribute("data-size", _$escape(size(), true), false) + _$ssrAttribute("data-empty", _$escape(empty() || undefined, true), false) + _$ssrAttribute("title", _$escape(props.title, true), false), empty() ? "–" : _$escape(props.value)), _$createComponent(Show, {
|
|
70
|
+
get when() {
|
|
71
|
+
return _$memo(() => !!!empty())() && props.delta;
|
|
72
|
+
},
|
|
73
|
+
children: delta => _$createComponent(DeltaBadge, {
|
|
74
|
+
get delta() {
|
|
75
|
+
return delta();
|
|
76
|
+
},
|
|
77
|
+
get compare() {
|
|
78
|
+
return props.compare;
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
})];
|
|
39
82
|
},
|
|
40
83
|
get children() {
|
|
41
|
-
return _$createComponent(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
interactiveChart: props.label
|
|
46
|
-
};
|
|
84
|
+
return [_$createComponent(Match, {
|
|
85
|
+
get when() {
|
|
86
|
+
return props.status === "loading";
|
|
47
87
|
},
|
|
48
|
-
get
|
|
49
|
-
return
|
|
88
|
+
get children() {
|
|
89
|
+
return [_$ssr(_tmpl$2), _$ssr(_tmpl$3, _$escape(t().loading))];
|
|
90
|
+
}
|
|
91
|
+
}), _$createComponent(Match, {
|
|
92
|
+
get when() {
|
|
93
|
+
return props.status === "error";
|
|
50
94
|
},
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
95
|
+
get children() {
|
|
96
|
+
return _$ssr(_tmpl$4, _$escape(t().notLoaded));
|
|
97
|
+
}
|
|
98
|
+
})];
|
|
99
|
+
}
|
|
100
|
+
}))), _$ssr(_tmpl$7, _$escape(_$createComponent(Switch, {
|
|
101
|
+
get fallback() {
|
|
102
|
+
return _$createComponent(Show, {
|
|
103
|
+
get when() {
|
|
104
|
+
return props.stale;
|
|
54
105
|
},
|
|
55
|
-
get
|
|
56
|
-
return
|
|
106
|
+
get fallback() {
|
|
107
|
+
return [_$createComponent(Show, {
|
|
108
|
+
get when() {
|
|
109
|
+
return props.compare;
|
|
110
|
+
},
|
|
111
|
+
children: compare => _$ssr(_tmpl$0, _$escape(compare().label), _$escape(compareValue()))
|
|
112
|
+
}), _$createComponent(Show, {
|
|
113
|
+
get when() {
|
|
114
|
+
return props.sub;
|
|
115
|
+
},
|
|
116
|
+
children: sub => _$ssr(_tmpl$1, _$escape(sub()))
|
|
117
|
+
}), _$createComponent(Show, {
|
|
118
|
+
get when() {
|
|
119
|
+
return accent();
|
|
120
|
+
},
|
|
121
|
+
children: value => _$createComponent(Show, {
|
|
122
|
+
get when() {
|
|
123
|
+
return value().text;
|
|
124
|
+
},
|
|
125
|
+
get fallback() {
|
|
126
|
+
return _$ssr(_tmpl$10, `${_$escape(value().icon, true)} k2b-stat-cell__accent-icon`, _$ssrAttribute("data-tone", _$escape(value().tone, true), false));
|
|
127
|
+
},
|
|
128
|
+
children: text => _$ssr(_tmpl$11, _$ssrAttribute("data-tone", _$escape(value().tone, true), false), _$ssrAttribute("class", _$escape(value().icon, true), false), _$escape(text()))
|
|
129
|
+
})
|
|
130
|
+
}), _$createComponent(Show, {
|
|
131
|
+
get when() {
|
|
132
|
+
return _$memo(() => !!(!empty() && props.trend))() && props.trend.length > 1;
|
|
133
|
+
},
|
|
134
|
+
get children() {
|
|
135
|
+
return _$createComponent(Chart, {
|
|
136
|
+
kind: "sparkline",
|
|
137
|
+
get labels() {
|
|
138
|
+
return {
|
|
139
|
+
interactiveChart: props.label
|
|
140
|
+
};
|
|
141
|
+
},
|
|
142
|
+
get tooltip() {
|
|
143
|
+
return props.trendTooltip ?? defaultTrendTooltip;
|
|
144
|
+
},
|
|
145
|
+
"class": "k2b-stat-cell__trend",
|
|
146
|
+
get data() {
|
|
147
|
+
return Array.from(props.trend ?? []);
|
|
148
|
+
},
|
|
149
|
+
showLast: true
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
})];
|
|
57
153
|
},
|
|
58
|
-
|
|
59
|
-
|
|
154
|
+
children: stale => [_$ssr(_tmpl$12, _$escape(stale())), _$createComponent(Show, {
|
|
155
|
+
get when() {
|
|
156
|
+
return props.onRetry;
|
|
157
|
+
},
|
|
158
|
+
children: retry => _$ssr(_tmpl$13, _$escape(t().reload))
|
|
159
|
+
})]
|
|
60
160
|
});
|
|
61
|
-
}
|
|
62
|
-
}), _$createComponent(Show, {
|
|
63
|
-
get when() {
|
|
64
|
-
return props.sub || accent();
|
|
65
161
|
},
|
|
66
162
|
get children() {
|
|
67
|
-
return _$
|
|
163
|
+
return [_$createComponent(Match, {
|
|
68
164
|
get when() {
|
|
69
|
-
return props.
|
|
165
|
+
return props.status === "loading";
|
|
70
166
|
},
|
|
71
|
-
children
|
|
72
|
-
|
|
167
|
+
get children() {
|
|
168
|
+
return _$ssr(_tmpl$6);
|
|
169
|
+
}
|
|
170
|
+
}), _$createComponent(Match, {
|
|
73
171
|
get when() {
|
|
74
|
-
return
|
|
172
|
+
return props.status === "error";
|
|
75
173
|
},
|
|
76
|
-
children
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
})));
|
|
174
|
+
get children() {
|
|
175
|
+
return _$createComponent(Show, {
|
|
176
|
+
get when() {
|
|
177
|
+
return props.onRetry;
|
|
178
|
+
},
|
|
179
|
+
children: retry => _$ssr(_tmpl$13, _$escape(t().retry))
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
})];
|
|
86
183
|
}
|
|
87
|
-
})];
|
|
184
|
+
})))];
|
|
88
185
|
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* One key figure as a framed tile: icon and label, the figure with its change, and a support line with the comparison
|
|
189
|
+
* and the trend. Each state (loading, error, stale, empty) keeps the tile's place and size.
|
|
190
|
+
*/
|
|
89
191
|
export function StatCell(props) {
|
|
90
192
|
const gridSize = useStatGridSize();
|
|
91
193
|
const size = () => props.size ?? gridSize;
|
|
92
194
|
const surface = useStatGridSurface();
|
|
93
|
-
return _$createComponent(Show
|
|
195
|
+
return _$createComponent(Show
|
|
196
|
+
// A tile that offers a retry is no link: the button must not sit inside it.
|
|
197
|
+
, {
|
|
94
198
|
get when() {
|
|
95
|
-
return props.href;
|
|
199
|
+
return _$memo(() => !!(props.href && !props.status))() && !(props.stale && props.onRetry);
|
|
96
200
|
},
|
|
97
201
|
get fallback() {
|
|
98
|
-
return _$ssr(_tmpl$
|
|
202
|
+
return _$ssr(_tmpl$15, _$ssrAttribute("data-size", _$escape(size(), true), false) + _$ssrAttribute("data-surface", _$escape(surface, true), false) + _$ssrAttribute("data-wrap", _$escape(props.wrap || undefined, true), false) + _$ssrAttribute("data-status", _$escape(props.status, true), false) + _$ssrAttribute("aria-busy", _$escape(props.status === "loading" || undefined, true), false), _$escape(_$createComponent(Body, props)));
|
|
99
203
|
},
|
|
100
|
-
children
|
|
204
|
+
get children() {
|
|
205
|
+
return _$ssr(_tmpl$14, _$ssrAttribute("href", _$escape(props.href, true), false), _$ssrAttribute("data-size", _$escape(size(), true), false) + _$ssrAttribute("data-surface", _$escape(surface, true), false) + _$ssrAttribute("data-wrap", _$escape(props.wrap || undefined, true), false), _$escape(_$createComponent(Body, props)));
|
|
206
|
+
}
|
|
101
207
|
});
|
|
102
208
|
}
|
|
103
209
|
export default StatCell;
|