@k2b/ui 0.48.0 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base.css +40 -2
- package/dist/browser/actions/ContextMenu.js +3 -0
- package/dist/browser/actions/ContextMenu.js.map +1 -1
- package/dist/browser/actions/CopyButton.js +26 -18
- package/dist/browser/actions/CopyButton.js.map +1 -1
- package/dist/browser/charts/core/area.js +190 -0
- package/dist/browser/charts/core/area.js.map +1 -0
- package/dist/browser/charts/core/calendar.js +186 -0
- package/dist/browser/charts/core/calendar.js.map +1 -0
- package/dist/browser/charts/core/chart-map-data.js +9 -0
- package/dist/browser/charts/core/chart-map-data.js.map +1 -0
- package/dist/browser/charts/core/index.js +12 -0
- package/dist/browser/charts/core/index.js.map +1 -0
- package/dist/browser/charts/core/inspection.js +9 -0
- package/dist/browser/charts/core/inspection.js.map +1 -0
- package/dist/browser/charts/core/registry.js +28 -0
- package/dist/browser/charts/core/registry.js.map +1 -0
- package/dist/browser/charts/core/render.js +103 -0
- package/dist/browser/charts/core/render.js.map +1 -0
- package/dist/browser/charts/core/snapshot.js +65 -0
- package/dist/browser/charts/core/snapshot.js.map +1 -0
- package/dist/browser/charts/core/svg.js +2542 -0
- package/dist/browser/charts/core/svg.js.map +1 -0
- package/dist/browser/charts/core/termination.test-fixture.js +162 -0
- package/dist/browser/charts/core/termination.test-fixture.js.map +1 -0
- package/dist/browser/charts/core/text.js +13 -0
- package/dist/browser/charts/core/text.js.map +1 -0
- package/dist/browser/charts/core/types.js +8 -0
- package/dist/browser/charts/core/types.js.map +1 -0
- package/dist/browser/charts.js +4 -2
- package/dist/browser/charts.js.map +1 -1
- package/dist/browser/content/BalanceSummary.js +106 -0
- package/dist/browser/content/BalanceSummary.js.map +1 -0
- package/dist/browser/content/Chart.js +134 -115
- package/dist/browser/content/Chart.js.map +1 -1
- package/dist/browser/content/ChartExplorer.js +366 -122
- package/dist/browser/content/ChartExplorer.js.map +1 -1
- package/dist/browser/content/ChartSnapshotView.js +16 -9
- package/dist/browser/content/ChartSnapshotView.js.map +1 -1
- package/dist/browser/content/DataTable.js +676 -293
- package/dist/browser/content/DataTable.js.map +1 -1
- package/dist/browser/content/DataTableTools.js +119 -0
- package/dist/browser/content/DataTableTools.js.map +1 -0
- package/dist/browser/content/FlowAmount.js +82 -0
- package/dist/browser/content/FlowAmount.js.map +1 -0
- package/dist/browser/content/balance-summary-messages.js +26 -0
- package/dist/browser/content/balance-summary-messages.js.map +1 -0
- package/dist/browser/content/chart-bar.js +6 -6
- package/dist/browser/content/chart-bar.js.map +1 -1
- package/dist/browser/content/chart-calendar.js +43 -0
- package/dist/browser/content/chart-calendar.js.map +1 -0
- package/dist/browser/content/chart-inspection-core.js +164 -37
- package/dist/browser/content/chart-inspection-core.js.map +1 -1
- package/dist/browser/content/chart-inspection.js.map +1 -1
- package/dist/browser/content/chart-line-gaps.js +2 -2
- package/dist/browser/content/chart-line-gaps.js.map +1 -1
- package/dist/browser/content/chart-map-viewport.js.map +1 -1
- package/dist/browser/content/chart-message-catalog.js +164 -0
- package/dist/browser/content/chart-message-catalog.js.map +1 -0
- package/dist/browser/content/chart-messages.js +2 -138
- package/dist/browser/content/chart-messages.js.map +1 -1
- package/dist/browser/content/chart-snapshot.js +1 -62
- package/dist/browser/content/chart-snapshot.js.map +1 -1
- package/dist/browser/content/chart-state-timeline.js +1 -1
- package/dist/browser/content/chart-state-timeline.js.map +1 -1
- package/dist/browser/content/chart-svg.js +2 -1
- package/dist/browser/content/chart-svg.js.map +1 -1
- package/dist/browser/content/chart-time-axis.js +139 -0
- package/dist/browser/content/chart-time-axis.js.map +1 -0
- package/dist/browser/content/data-table-columns.js +160 -0
- package/dist/browser/content/data-table-columns.js.map +1 -0
- package/dist/browser/content/data-table-messages.js +38 -2
- package/dist/browser/content/data-table-messages.js.map +1 -1
- package/dist/browser/content/flow-amount-messages.js +26 -0
- package/dist/browser/content/flow-amount-messages.js.map +1 -0
- package/dist/browser/content/index.js +4 -0
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/feedback/prompt-confirm.js +7 -4
- package/dist/browser/feedback/prompt-confirm.js.map +1 -1
- package/dist/browser/feedback/prompts.js +3 -3
- package/dist/browser/feedback/prompts.js.map +1 -1
- package/dist/browser/inputs/DatePicker.js +5 -4
- package/dist/browser/inputs/DatePicker.js.map +1 -1
- package/dist/browser/inputs/NumberInput.js +17 -5
- package/dist/browser/inputs/NumberInput.js.map +1 -1
- package/dist/browser/inputs/SelectChip.js +50 -17
- package/dist/browser/inputs/SelectChip.js.map +1 -1
- package/dist/browser/inputs/date-picker.js +13 -0
- package/dist/browser/inputs/date-picker.js.map +1 -1
- package/dist/browser/intl/Format.js +31 -8
- package/dist/browser/intl/Format.js.map +1 -1
- package/dist/browser/layout/AppWorkspace.js +580 -522
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/MobileShell.js +26 -0
- package/dist/browser/layout/MobileShell.js.map +1 -1
- package/dist/browser/layout/index.js +1 -0
- package/dist/browser/layout/index.js.map +1 -1
- package/dist/browser/layout/sheet-handle.js +155 -0
- package/dist/browser/layout/sheet-handle.js.map +1 -0
- package/dist/browser/surfaces/BudgetList.js +281 -0
- package/dist/browser/surfaces/BudgetList.js.map +1 -0
- package/dist/browser/surfaces/NoticeCard.js +48 -29
- package/dist/browser/surfaces/NoticeCard.js.map +1 -1
- package/dist/browser/surfaces/ProgressBar.js +134 -21
- package/dist/browser/surfaces/ProgressBar.js.map +1 -1
- package/dist/browser/surfaces/StatCell.js +320 -144
- package/dist/browser/surfaces/StatCell.js.map +1 -1
- package/dist/browser/surfaces/StatGrid.js +75 -57
- package/dist/browser/surfaces/StatGrid.js.map +1 -1
- package/dist/browser/surfaces/budget-messages.js +64 -0
- package/dist/browser/surfaces/budget-messages.js.map +1 -0
- package/dist/browser/surfaces/delta-badge.js +65 -0
- package/dist/browser/surfaces/delta-badge.js.map +1 -0
- package/dist/browser/surfaces/index.js +2 -1
- package/dist/browser/surfaces/index.js.map +1 -1
- package/dist/browser/surfaces/person-color.js +2 -2
- package/dist/browser/surfaces/person-color.js.map +1 -1
- package/dist/browser/surfaces/stat-cell-messages.js +41 -0
- package/dist/browser/surfaces/stat-cell-messages.js.map +1 -0
- package/dist/browser/widgets/Dashboard.js +137 -0
- package/dist/browser/widgets/Dashboard.js.map +1 -0
- package/dist/browser/widgets/index.js +1 -0
- package/dist/browser/widgets/index.js.map +1 -1
- package/dist/ssr/actions/ContextMenu.js +3 -0
- package/dist/ssr/actions/ContextMenu.js.map +1 -1
- package/dist/ssr/actions/CopyButton.js +13 -8
- package/dist/ssr/actions/CopyButton.js.map +1 -1
- package/dist/ssr/charts/core/area.js +190 -0
- package/dist/ssr/charts/core/area.js.map +1 -0
- package/dist/ssr/charts/core/calendar.js +186 -0
- package/dist/ssr/charts/core/calendar.js.map +1 -0
- package/dist/ssr/charts/core/chart-map-data.js +9 -0
- package/dist/ssr/charts/core/chart-map-data.js.map +1 -0
- package/dist/ssr/charts/core/index.js +12 -0
- package/dist/ssr/charts/core/index.js.map +1 -0
- package/dist/ssr/charts/core/inspection.js +9 -0
- package/dist/ssr/charts/core/inspection.js.map +1 -0
- package/dist/ssr/charts/core/registry.js +28 -0
- package/dist/ssr/charts/core/registry.js.map +1 -0
- package/dist/ssr/charts/core/render.js +103 -0
- package/dist/ssr/charts/core/render.js.map +1 -0
- package/dist/ssr/charts/core/snapshot.js +65 -0
- package/dist/ssr/charts/core/snapshot.js.map +1 -0
- package/dist/ssr/charts/core/svg.js +2542 -0
- package/dist/ssr/charts/core/svg.js.map +1 -0
- package/dist/ssr/charts/core/termination.test-fixture.js +162 -0
- package/dist/ssr/charts/core/termination.test-fixture.js.map +1 -0
- package/dist/ssr/charts/core/text.js +13 -0
- package/dist/ssr/charts/core/text.js.map +1 -0
- package/dist/ssr/charts/core/types.js +8 -0
- package/dist/ssr/charts/core/types.js.map +1 -0
- package/dist/ssr/charts.js +4 -2
- package/dist/ssr/charts.js.map +1 -1
- package/dist/ssr/content/BalanceSummary.js +75 -0
- package/dist/ssr/content/BalanceSummary.js.map +1 -0
- package/dist/ssr/content/Chart.js +90 -95
- package/dist/ssr/content/Chart.js.map +1 -1
- package/dist/ssr/content/ChartExplorer.js +190 -46
- package/dist/ssr/content/ChartExplorer.js.map +1 -1
- package/dist/ssr/content/ChartSnapshotView.js +5 -1
- package/dist/ssr/content/ChartSnapshotView.js.map +1 -1
- package/dist/ssr/content/DataTable.js +287 -78
- package/dist/ssr/content/DataTable.js.map +1 -1
- package/dist/ssr/content/DataTableTools.js +106 -0
- package/dist/ssr/content/DataTableTools.js.map +1 -0
- package/dist/ssr/content/FlowAmount.js +58 -0
- package/dist/ssr/content/FlowAmount.js.map +1 -0
- package/dist/ssr/content/balance-summary-messages.js +26 -0
- package/dist/ssr/content/balance-summary-messages.js.map +1 -0
- package/dist/ssr/content/chart-bar.js +6 -6
- package/dist/ssr/content/chart-bar.js.map +1 -1
- package/dist/ssr/content/chart-calendar.js +43 -0
- package/dist/ssr/content/chart-calendar.js.map +1 -0
- package/dist/ssr/content/chart-inspection-core.js +164 -37
- package/dist/ssr/content/chart-inspection-core.js.map +1 -1
- package/dist/ssr/content/chart-inspection.js.map +1 -1
- package/dist/ssr/content/chart-line-gaps.js +2 -2
- package/dist/ssr/content/chart-line-gaps.js.map +1 -1
- package/dist/ssr/content/chart-map-viewport.js.map +1 -1
- package/dist/ssr/content/chart-message-catalog.js +164 -0
- package/dist/ssr/content/chart-message-catalog.js.map +1 -0
- package/dist/ssr/content/chart-messages.js +2 -138
- package/dist/ssr/content/chart-messages.js.map +1 -1
- package/dist/ssr/content/chart-snapshot.js +1 -62
- package/dist/ssr/content/chart-snapshot.js.map +1 -1
- package/dist/ssr/content/chart-state-timeline.js +1 -1
- package/dist/ssr/content/chart-state-timeline.js.map +1 -1
- package/dist/ssr/content/chart-svg.js +2 -1
- package/dist/ssr/content/chart-svg.js.map +1 -1
- package/dist/ssr/content/chart-time-axis.js +139 -0
- package/dist/ssr/content/chart-time-axis.js.map +1 -0
- package/dist/ssr/content/data-table-columns.js +160 -0
- package/dist/ssr/content/data-table-columns.js.map +1 -0
- package/dist/ssr/content/data-table-messages.js +38 -2
- package/dist/ssr/content/data-table-messages.js.map +1 -1
- package/dist/ssr/content/flow-amount-messages.js +26 -0
- package/dist/ssr/content/flow-amount-messages.js.map +1 -0
- package/dist/ssr/content/index.js +4 -0
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/feedback/prompt-confirm.js +7 -4
- package/dist/ssr/feedback/prompt-confirm.js.map +1 -1
- package/dist/ssr/feedback/prompts.js +3 -3
- package/dist/ssr/feedback/prompts.js.map +1 -1
- package/dist/ssr/inputs/DatePicker.js +5 -4
- package/dist/ssr/inputs/DatePicker.js.map +1 -1
- package/dist/ssr/inputs/NumberInput.js +17 -5
- package/dist/ssr/inputs/NumberInput.js.map +1 -1
- package/dist/ssr/inputs/SelectChip.js +26 -9
- package/dist/ssr/inputs/SelectChip.js.map +1 -1
- package/dist/ssr/inputs/date-picker.js +13 -0
- package/dist/ssr/inputs/date-picker.js.map +1 -1
- package/dist/ssr/intl/Format.js +22 -2
- package/dist/ssr/intl/Format.js.map +1 -1
- package/dist/ssr/layout/AppWorkspace.js +158 -114
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/MobileShell.js +26 -0
- package/dist/ssr/layout/MobileShell.js.map +1 -1
- package/dist/ssr/layout/index.js +1 -0
- package/dist/ssr/layout/index.js.map +1 -1
- package/dist/ssr/layout/sheet-handle.js +155 -0
- package/dist/ssr/layout/sheet-handle.js.map +1 -0
- package/dist/ssr/surfaces/BudgetList.js +170 -0
- package/dist/ssr/surfaces/BudgetList.js.map +1 -0
- package/dist/ssr/surfaces/NoticeCard.js +25 -10
- package/dist/ssr/surfaces/NoticeCard.js.map +1 -1
- package/dist/ssr/surfaces/ProgressBar.js +96 -5
- package/dist/ssr/surfaces/ProgressBar.js.map +1 -1
- package/dist/ssr/surfaces/StatCell.js +157 -51
- package/dist/ssr/surfaces/StatCell.js.map +1 -1
- package/dist/ssr/surfaces/StatGrid.js +24 -35
- package/dist/ssr/surfaces/StatGrid.js.map +1 -1
- package/dist/ssr/surfaces/budget-messages.js +64 -0
- package/dist/ssr/surfaces/budget-messages.js.map +1 -0
- package/dist/ssr/surfaces/delta-badge.js +41 -0
- package/dist/ssr/surfaces/delta-badge.js.map +1 -0
- package/dist/ssr/surfaces/index.js +2 -1
- package/dist/ssr/surfaces/index.js.map +1 -1
- package/dist/ssr/surfaces/person-color.js +2 -2
- package/dist/ssr/surfaces/person-color.js.map +1 -1
- package/dist/ssr/surfaces/stat-cell-messages.js +41 -0
- package/dist/ssr/surfaces/stat-cell-messages.js.map +1 -0
- package/dist/ssr/widgets/Dashboard.js +84 -0
- package/dist/ssr/widgets/Dashboard.js.map +1 -0
- package/dist/ssr/widgets/index.js +1 -0
- package/dist/ssr/widgets/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/charts/core/area.d.ts +62 -0
- package/dist/types/charts/core/calendar.d.ts +57 -0
- package/dist/types/charts/core/chart-map-data.d.ts +3 -0
- package/dist/types/charts/core/index.d.ts +11 -0
- package/dist/types/charts/core/inspection.d.ts +16 -0
- package/dist/types/charts/core/registry.d.ts +27 -0
- package/dist/types/charts/core/render.d.ts +40 -0
- package/dist/types/charts/core/snapshot.d.ts +27 -0
- package/dist/types/charts/core/svg.d.ts +714 -0
- package/dist/types/charts/core/termination.test-fixture.d.ts +1 -0
- package/dist/types/charts/core/text.d.ts +5 -0
- package/dist/types/charts/core/types.d.ts +31 -0
- package/dist/types/charts.d.ts +4 -2
- package/dist/types/content/BalanceSummary.d.ts +29 -0
- package/dist/types/content/Chart.d.ts +26 -36
- package/dist/types/content/ChartExplorer.d.ts +43 -2
- package/dist/types/content/ChartSnapshotView.d.ts +1 -0
- package/dist/types/content/DataTable.d.ts +28 -0
- package/dist/types/content/DataTableTools.d.ts +44 -0
- package/dist/types/content/FlowAmount.d.ts +28 -0
- package/dist/types/content/balance-summary-messages.d.ts +11 -0
- package/dist/types/content/chart-bar.d.ts +1 -1
- package/dist/types/content/chart-calendar.d.ts +4 -0
- package/dist/types/content/chart-inspection-core.d.ts +21 -16
- package/dist/types/content/chart-inspection.d.ts +5 -1
- package/dist/types/content/chart-map-viewport.d.ts +1 -1
- package/dist/types/content/chart-message-catalog.d.ts +84 -0
- package/dist/types/content/chart-messages.d.ts +2 -33
- package/dist/types/content/chart-snapshot.d.ts +1 -26
- package/dist/types/content/chart-svg.d.ts +1 -1
- package/dist/types/content/chart-time-axis.d.ts +26 -0
- package/dist/types/content/data-table-columns.d.ts +72 -0
- package/dist/types/content/data-table-messages.d.ts +18 -0
- package/dist/types/content/flow-amount-messages.d.ts +11 -0
- package/dist/types/content/index.d.ts +10 -2
- package/dist/types/feedback/prompt-confirm.d.ts +3 -1
- package/dist/types/feedback/prompts.d.ts +2 -2
- package/dist/types/inputs/NumberInput.d.ts +1 -1
- package/dist/types/inputs/SelectChip.d.ts +2 -0
- package/dist/types/inputs/date-picker.d.ts +6 -0
- package/dist/types/intl/Format.d.ts +5 -0
- package/dist/types/layout/AppWorkspace.d.ts +21 -1
- package/dist/types/layout/MobileShell.d.ts +5 -0
- package/dist/types/layout/index.d.ts +2 -1
- package/dist/types/layout/sheet-handle.d.ts +21 -0
- package/dist/types/surfaces/BudgetList.d.ts +42 -0
- package/dist/types/surfaces/NoticeCard.d.ts +5 -2
- package/dist/types/surfaces/ProgressBar.d.ts +38 -2
- package/dist/types/surfaces/StatCell.d.ts +35 -2
- package/dist/types/surfaces/StatGrid.d.ts +3 -1
- package/dist/types/surfaces/budget-messages.d.ts +30 -0
- package/dist/types/surfaces/delta-badge.d.ts +10 -0
- package/dist/types/surfaces/index.d.ts +4 -3
- package/dist/types/surfaces/person-color.d.ts +2 -2
- package/dist/types/surfaces/stat-cell-messages.d.ts +19 -0
- package/dist/types/widgets/Dashboard.d.ts +42 -0
- package/dist/types/widgets/index.d.ts +1 -0
- package/package.json +7 -1
|
@@ -0,0 +1 @@
|
|
|
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":[]}
|
|
@@ -7,11 +7,14 @@ import { createComponent as _$createComponent } from "solid-js/web";
|
|
|
7
7
|
var _tmpl$ = ["<div class=\"", "\">", "</div>"],
|
|
8
8
|
_tmpl$2 = ["<div", ">", "", "", "</div>"],
|
|
9
9
|
_tmpl$3 = ["<i class=\"", "\" aria-hidden=\"true\"></i>"],
|
|
10
|
-
_tmpl$4 = ["<
|
|
11
|
-
_tmpl$5 = ["<
|
|
12
|
-
_tmpl$6 = ["<
|
|
13
|
-
_tmpl$7 = ["<
|
|
10
|
+
_tmpl$4 = ["<span class=\"k2b-sr-only\">", "</span>"],
|
|
11
|
+
_tmpl$5 = ["<div", "><p", ">", "</p>", "</div>"],
|
|
12
|
+
_tmpl$6 = ["<span", ">", "</span>"],
|
|
13
|
+
_tmpl$7 = ["<p", ">", "</p>"],
|
|
14
|
+
_tmpl$8 = ["<div class=\"", "\"", ">", "</div>"];
|
|
14
15
|
import { children, For, Show, splitProps } from "solid-js";
|
|
16
|
+
import { dialogToneIcon, dialogToneLabel } from "../feedback/dialog-tone";
|
|
17
|
+
import { useUiMessages } from "../intl/messages";
|
|
15
18
|
export const NOTICE_CARD_CLASSES = {
|
|
16
19
|
root: "k2b-notice-card",
|
|
17
20
|
icon: "k2b-notice-card__icon",
|
|
@@ -27,6 +30,18 @@ function NoticeCardComponent(props) {
|
|
|
27
30
|
// Children that render nothing, such as a Show whose condition is false, add no body and no gap.
|
|
28
31
|
const body = children(() => local.children);
|
|
29
32
|
const hasBody = () => body.toArray().some(node => node != null && node !== false && node !== "");
|
|
33
|
+
const messages = useUiMessages();
|
|
34
|
+
/** The tone a dialog also knows, so `icon` true shows the same icon and word; info and neutral have no word. */
|
|
35
|
+
const dialogTone = () => local.tone === "success" || local.tone === "warning" || local.tone === "danger" ? local.tone : undefined;
|
|
36
|
+
const icon = () => {
|
|
37
|
+
if (local.icon !== true) return local.icon;
|
|
38
|
+
const tone = dialogTone();
|
|
39
|
+
return tone ? dialogToneIcon(tone) : "ti ti-info-circle";
|
|
40
|
+
};
|
|
41
|
+
const toneWord = () => {
|
|
42
|
+
const tone = local.icon === true ? dialogTone() : undefined;
|
|
43
|
+
return tone ? `${dialogToneLabel(messages(), tone)}: ` : undefined;
|
|
44
|
+
};
|
|
30
45
|
return _$ssrElement("article", _$mergeProps(articleProps, {
|
|
31
46
|
get ["class"]() {
|
|
32
47
|
return `${NOTICE_CARD_CLASSES.root} ${local.class ?? ""}`;
|
|
@@ -38,24 +53,24 @@ function NoticeCardComponent(props) {
|
|
|
38
53
|
"data-icon": ""
|
|
39
54
|
} : {}), [_$escape(_$createComponent(Show, {
|
|
40
55
|
get when() {
|
|
41
|
-
return
|
|
56
|
+
return icon();
|
|
42
57
|
},
|
|
43
|
-
children: icon => _$ssr(_tmpl$3, `${_$escape(icon(), true)} ${_$escape(NOTICE_CARD_CLASSES.icon, true)}`)
|
|
58
|
+
children: icon => [_$ssr(_tmpl$3, `${_$escape(icon(), true)} ${_$escape(NOTICE_CARD_CLASSES.icon, true)}`), toneWord() ? _$ssr(_tmpl$4, _$escape(toneWord())) : null]
|
|
44
59
|
})), _$ssr(_tmpl$2, _$ssrAttribute("class", _$escape(NOTICE_CARD_CLASSES.content, true), false), _$escape(_$createComponent(Show, {
|
|
45
60
|
get when() {
|
|
46
61
|
return local.title;
|
|
47
62
|
},
|
|
48
|
-
children: title => _$ssr(_tmpl$
|
|
63
|
+
children: title => _$ssr(_tmpl$5, _$ssrAttribute("class", _$escape(NOTICE_CARD_CLASSES.head, true), false), _$ssrAttribute("class", _$escape(NOTICE_CARD_CLASSES.title, true), false), _$escape(title()), _$escape(_$createComponent(Show, {
|
|
49
64
|
get when() {
|
|
50
65
|
return local.meta;
|
|
51
66
|
},
|
|
52
|
-
children: meta => _$ssr(_tmpl$
|
|
67
|
+
children: meta => _$ssr(_tmpl$6, _$ssrAttribute("class", _$escape(NOTICE_CARD_CLASSES.meta, true), false), _$escape(meta()))
|
|
53
68
|
})))
|
|
54
69
|
})), _$escape(_$createComponent(Show, {
|
|
55
70
|
get when() {
|
|
56
71
|
return local.detail;
|
|
57
72
|
},
|
|
58
|
-
children: detail => _$ssr(_tmpl$
|
|
73
|
+
children: detail => _$ssr(_tmpl$7, _$ssrAttribute("class", _$escape(NOTICE_CARD_CLASSES.description, true), false), _$escape(detail()))
|
|
59
74
|
})), _$escape(_$createComponent(Show, {
|
|
60
75
|
get when() {
|
|
61
76
|
return hasBody();
|
|
@@ -72,7 +87,7 @@ function NoticeGrid(props) {
|
|
|
72
87
|
return props.items.length > 0;
|
|
73
88
|
},
|
|
74
89
|
get children() {
|
|
75
|
-
return _$ssr(_tmpl$
|
|
90
|
+
return _$ssr(_tmpl$8, `k2b-notice-grid ${_$escape(props.class ?? "", true)}`, _$ssrAttribute("data-columns", _$escape(columns(), true), false), _$escape(_$createComponent(For, {
|
|
76
91
|
get each() {
|
|
77
92
|
return props.items;
|
|
78
93
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["surfaces/NoticeCard.tsx"],"sourcesContent":["import { children, For, type JSX, Show, splitProps } from \"solid-js\";\nimport type { IntentTone } from \"../semantics\";\n\nexport type NoticeTone = Extract<IntentTone, \"neutral\" | \"info\" | \"success\" | \"warning\" | \"danger\">;\n\ntype NoticeCardContentProps =\n | { title: JSX.Element; detail?: JSX.Element; meta?: JSX.Element; children?: JSX.Element }\n | { title?: never; detail?: never; meta?: never; children: JSX.Element };\n\nexport type NoticeCardProps = Omit<JSX.HTMLAttributes<HTMLElement>, \"children\" | \"class\" | \"title\"> &\n NoticeCardContentProps & {\n tone?: NoticeTone;\n
|
|
1
|
+
{"version":3,"names":[],"sources":["surfaces/NoticeCard.tsx"],"sourcesContent":["import { children, For, type JSX, Show, splitProps } from \"solid-js\";\nimport { dialogToneIcon, dialogToneLabel } from \"../feedback/dialog-tone\";\nimport { useUiMessages } from \"../intl/messages\";\nimport type { IntentTone } from \"../semantics\";\n\nexport type NoticeTone = Extract<IntentTone, \"neutral\" | \"info\" | \"success\" | \"warning\" | \"danger\">;\n\ntype NoticeCardContentProps =\n | { title: JSX.Element; detail?: JSX.Element; meta?: JSX.Element; children?: JSX.Element }\n | { title?: never; detail?: never; meta?: never; children: JSX.Element };\n\nexport type NoticeCardProps = Omit<JSX.HTMLAttributes<HTMLElement>, \"children\" | \"class\" | \"title\"> &\n NoticeCardContentProps & {\n tone?: NoticeTone;\n /**\n * A Tabler icon class. Turns the notice into a compact status line whose icon and text take the tone colour. `true`\n * takes the tone's own icon, the one a toned dialog shows, and names the tone for screen readers.\n */\n icon?: string | true;\n class?: string;\n bodyClass?: string;\n };\n\nexport const NOTICE_CARD_CLASSES = {\n root: \"k2b-notice-card\",\n icon: \"k2b-notice-card__icon\",\n content: \"k2b-notice-card__content\",\n head: \"k2b-notice-card__head\",\n title: \"k2b-notice-card__title\",\n meta: \"k2b-notice-card__meta\",\n description: \"k2b-notice-card__description\",\n body: \"k2b-notice-card__body\",\n} as const;\n\nfunction NoticeCardComponent(props: NoticeCardProps): JSX.Element {\n const [local, articleProps] = splitProps(props, [\"tone\", \"icon\", \"title\", \"detail\", \"meta\", \"children\", \"class\", \"bodyClass\"]);\n // Children that render nothing, such as a Show whose condition is false, add no body and no gap.\n const body = children(() => local.children);\n const hasBody = () => body.toArray().some((node) => node != null && node !== false && node !== \"\");\n const messages = useUiMessages();\n /** The tone a dialog also knows, so `icon` true shows the same icon and word; info and neutral have no word. */\n const dialogTone = () => (local.tone === \"success\" || local.tone === \"warning\" || local.tone === \"danger\" ? local.tone : undefined);\n const icon = () => {\n if (local.icon !== true) return local.icon;\n const tone = dialogTone();\n return tone ? dialogToneIcon(tone) : \"ti ti-info-circle\";\n };\n const toneWord = () => {\n const tone = local.icon === true ? dialogTone() : undefined;\n return tone ? `${dialogToneLabel(messages(), tone)}: ` : undefined;\n };\n return (\n <article\n {...articleProps}\n class={`${NOTICE_CARD_CLASSES.root} ${local.class ?? \"\"}`}\n data-tone={local.tone ?? \"neutral\"}\n {...(local.icon ? { \"data-icon\": \"\" } : {})}\n >\n <Show when={icon()}>\n {(icon) => (\n <>\n <i class={`${icon()} ${NOTICE_CARD_CLASSES.icon}`} aria-hidden=\"true\" />\n {/* Inside the icon's branch, so a notice without one keeps its markup. */}\n {toneWord() ? <span class=\"k2b-sr-only\">{toneWord()}</span> : null}\n </>\n )}\n </Show>\n <div class={NOTICE_CARD_CLASSES.content}>\n <Show when={local.title}>\n {(title) => (\n <div class={NOTICE_CARD_CLASSES.head}>\n <p class={NOTICE_CARD_CLASSES.title}>{title()}</p>\n <Show when={local.meta}>{(meta) => <span class={NOTICE_CARD_CLASSES.meta}>{meta()}</span>}</Show>\n </div>\n )}\n </Show>\n <Show when={local.detail}>{(detail) => <p class={NOTICE_CARD_CLASSES.description}>{detail()}</p>}</Show>\n <Show when={hasBody()}>\n <div class={`${NOTICE_CARD_CLASSES.body} ${local.bodyClass ?? \"\"}`}>{body()}</div>\n </Show>\n </div>\n </article>\n );\n}\n\nexport type NoticeGridProps<T> = {\n items: readonly T[];\n children: (item: T) => JSX.Element;\n class?: string;\n};\n\nfunction NoticeGrid<T>(props: NoticeGridProps<T>): JSX.Element {\n const columns = () => (props.items.length <= 1 ? \"one\" : props.items.length === 2 ? \"two\" : \"three\");\n return (\n <Show when={props.items.length > 0}>\n <div class={`k2b-notice-grid ${props.class ?? \"\"}`} data-columns={columns()}>\n <For each={props.items}>{(item) => props.children(item)}</For>\n </div>\n </Show>\n );\n}\n\nexport const NoticeCard = Object.assign(NoticeCardComponent, { Grid: NoticeGrid });\nexport default NoticeCard;\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;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["surfaces/StatCell.tsx"],"sourcesContent":["import { type JSX, Show } from \"solid-js\";\nimport Chart from \"../content/Chart\";\nimport type { ChartTooltipFormatter } from \"../content/chart-inspection-core\";\nimport { useLocale } from \"../intl/locale\";\nimport type { AccentColor } from \"../semantics\";\nimport { type StatGridSize, useStatGridSize, useStatGridSurface } from \"./StatGrid\";\n\nexport type StatCellTone = AccentColor;\n\nexport type StatCellAccent = {\n tone: StatCellTone;\n icon: string;\n text?: string;\n};\n\nexport type StatCellProps = {\n label: string;\n value: string | number | JSX.Element;\n sub?: string;\n valueClass?: string;\n accent?: StatCellAccent;\n href?: string;\n title?: string;\n trend?: readonly number[];\n /**\n * Replaces the default trend tooltip in browser code, for example with a period title or a unit.\n * `selection.datum.index` is the source index into `trend`.\n */\n trendTooltip?: ChartTooltipFormatter;\n size?: StatGridSize;\n /**\n * Wraps the label, value and support line instead of truncating them. Use it for a cell whose height nothing\n * reserves, such as one figure on its own; cells compared in a row keep one line each.\n */\n wrap?: boolean;\n};\n\nfunction Body(props: StatCellProps): JSX.Element {\n const gridSize = useStatGridSize();\n const size = () => props.size ?? gridSize;\n const accent = () => props.accent;\n const locale = useLocale();\n const defaultTrendTooltip: ChartTooltipFormatter = ({ datum }) => {\n const y = datum.values.find((field) => field.key === \"y\")?.value ?? \"\";\n return {\n rows: [\n { label: props.label, value: typeof y === \"number\" ? new Intl.NumberFormat(locale(), { maximumFractionDigits: 6 }).format(y) : y },\n ],\n };\n };\n return (\n <>\n <span class=\"k2b-stat-cell__label\" data-size={size()}>\n {props.label}\n </span>\n <span class={`k2b-stat-cell__value ${props.valueClass ?? \"\"}`} data-size={size()} title={props.title}>\n {props.value}\n </span>\n <Show when={props.trend && props.trend.length > 1}>\n <Chart\n kind=\"sparkline\"\n labels={{ interactiveChart: props.label }}\n tooltip={props.trendTooltip ?? defaultTrendTooltip}\n class=\"k2b-stat-cell__trend\"\n style={{ height: \"32px\" }}\n data={Array.from(props.trend ?? [])}\n showLast\n showMinMax\n />\n </Show>\n <Show when={props.sub || accent()}>\n <div class=\"k2b-stat-cell__support\">\n <Show when={props.sub}>{(sub) => <span class=\"k2b-stat-cell__sub\">{sub()}</span>}</Show>\n <Show when={accent()}>\n {(value) => (\n <Show\n when={value().text}\n fallback={<i class={`${value().icon} k2b-stat-cell__accent-icon`} data-tone={value().tone} aria-hidden=\"true\" />}\n >\n {(text) => (\n <span class=\"k2b-stat-cell__accent\" data-tone={value().tone}>\n <i class={value().icon} aria-hidden=\"true\" />\n {text()}\n </span>\n )}\n </Show>\n )}\n </Show>\n </div>\n </Show>\n </>\n );\n}\n\nexport function StatCell(props: StatCellProps): JSX.Element {\n const gridSize = useStatGridSize();\n const size = () => props.size ?? gridSize;\n const surface = useStatGridSurface();\n return (\n <Show\n when={props.href}\n fallback={\n <div class=\"k2b-stat-cell\" data-size={size()} data-surface={surface} data-wrap={props.wrap || undefined}>\n <Body {...props} />\n </div>\n }\n >\n {(href) => (\n <a\n href={href()}\n class=\"k2b-stat-cell k2b-stat-cell--link\"\n data-size={size()}\n data-surface={surface}\n data-wrap={props.wrap || undefined}\n >\n <i class=\"ti ti-external-link k2b-stat-cell__link-icon\" aria-hidden=\"true\" />\n <Body {...props} />\n </a>\n )}\n </Show>\n );\n}\n\nexport default StatCell;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["surfaces/StatCell.tsx"],"sourcesContent":["import { type JSX, Match, Show, Switch } from \"solid-js\";\nimport Chart from \"../content/Chart\";\nimport type { ChartTooltipFormatter } from \"../content/chart-inspection-core\";\nimport { useLocale } from \"../intl/locale\";\nimport type { AccentColor } from \"../semantics\";\nimport { DeltaBadge } from \"./delta-badge\";\nimport { type StatGridSize, useStatGridSize, useStatGridSurface } from \"./StatGrid\";\nimport { useStatCellMessages } from \"./stat-cell-messages\";\n\nexport type StatCellTone = AccentColor;\n\nexport type StatCellAccent = {\n tone: StatCellTone;\n icon: string;\n text?: string;\n};\n\n/**\n * The change against a comparison period. `unit: \"ratio\"` (default) reads `0.082` as `+8.2 %`; `\"points\"` is the\n * difference of two shares in ratio units, so `0.031` reads `+3.1 pts`. Only with `better` does the badge carry a tone\n * and say \"better\" or \"worse\"; without it the change stays unrated.\n */\nexport type StatCellDelta = {\n value: number;\n unit?: \"ratio\" | \"points\";\n better?: \"up\" | \"down\";\n};\n\n/** The value the change compares against, shown under the figure, such as \"Last month 44,560\". */\nexport type StatCellCompare = {\n label: string;\n value: string | number;\n};\n\nexport type StatCellSize = StatGridSize;\n\nexport type StatCellProps = {\n label: string;\n /** The figure. `null` shows the empty dash; `sub` then says why. */\n value: string | number | JSX.Element | null;\n sub?: string;\n valueClass?: string;\n /** An icon in a chip before the label, in `tone`. `\"in\"` and `\"out\"` are the money colours of `FlowAmount`. */\n icon?: string;\n /** The chip colour of `icon`. Defaults to zinc. */\n tone?: StatCellTone | \"in\" | \"out\";\n accent?: StatCellAccent;\n delta?: StatCellDelta;\n compare?: StatCellCompare;\n href?: string;\n title?: string;\n trend?: readonly number[];\n /**\n * Replaces the default trend tooltip in browser code, for example with a period title or a unit.\n * `selection.datum.index` is the source index into `trend`.\n */\n trendTooltip?: ChartTooltipFormatter;\n size?: StatCellSize;\n /**\n * Wraps the label, value and support line instead of truncating them. Use it for a cell whose height nothing\n * reserves, such as one figure on its own; cells compared in a row keep one line each.\n */\n wrap?: boolean;\n /** `\"loading\"` keeps the tile's size with placeholders; `\"error\"` says the figure did not load. */\n status?: \"loading\" | \"error\";\n /** Offers \"Try again\" after an error and \"Reload\" beside `stale`. */\n onRetry?: () => void;\n /** The figure is not current: a short note such as \"As of 09:12 · not current\" replaces the support line. */\n stale?: string;\n};\n\nfunction Body(props: StatCellProps): JSX.Element {\n const gridSize = useStatGridSize();\n const size = () => props.size ?? gridSize;\n const accent = () => props.accent;\n const locale = useLocale();\n const t = useStatCellMessages();\n const defaultTrendTooltip: ChartTooltipFormatter = ({ datum }) => {\n const y = datum.values.find((field) => field.key === \"y\")?.value ?? \"\";\n return {\n rows: [\n { label: props.label, value: typeof y === \"number\" ? new Intl.NumberFormat(locale(), { maximumFractionDigits: 6 }).format(y) : y },\n ],\n };\n };\n const compareValue = () => {\n const value = props.compare?.value;\n return typeof value === \"number\" ? new Intl.NumberFormat(locale()).format(value) : value;\n };\n const empty = () => props.value === null || props.value === undefined || props.value === \"\";\n return (\n <>\n <div class=\"k2b-stat-cell__head\">\n <Show when={props.icon}>\n {(icon) => (\n <span class=\"k2b-stat-cell__icon k2b-icon-tile\" data-tone={props.tone ?? \"zinc\"} aria-hidden=\"true\">\n <i class={icon()} />\n </span>\n )}\n </Show>\n <span class=\"k2b-stat-cell__label\" data-size={size()}>\n {props.label}\n </span>\n </div>\n <div class=\"k2b-stat-cell__main\">\n <Switch\n fallback={\n <>\n <span\n class={`k2b-stat-cell__value ${props.valueClass ?? \"\"}`}\n data-size={size()}\n data-empty={empty() || undefined}\n title={props.title}\n >\n {empty() ? \"–\" : props.value}\n </span>\n <Show when={!empty() && props.delta}>{(delta) => <DeltaBadge delta={delta()} compare={props.compare} />}</Show>\n </>\n }\n >\n <Match when={props.status === \"loading\"}>\n <span class=\"k2b-stat-cell__skeleton k2b-skeleton\" data-part=\"value\" aria-hidden=\"true\" />\n <span class=\"k2b-sr-only\">{t().loading}</span>\n </Match>\n <Match when={props.status === \"error\"}>\n <span class=\"k2b-stat-cell__error\">\n <i class=\"ti ti-alert-circle\" aria-hidden=\"true\" />\n {t().notLoaded}\n </span>\n </Match>\n </Switch>\n </div>\n <div class=\"k2b-stat-cell__support\">\n <Switch\n fallback={\n <Show\n when={props.stale}\n fallback={\n <>\n <Show when={props.compare}>\n {(compare) => (\n <span class=\"k2b-stat-cell__sub\">\n {compare().label} {compareValue()}\n </span>\n )}\n </Show>\n <Show when={props.sub}>{(sub) => <span class=\"k2b-stat-cell__sub\">{sub()}</span>}</Show>\n <Show when={accent()}>\n {(value) => (\n <Show\n when={value().text}\n fallback={<i class={`${value().icon} k2b-stat-cell__accent-icon`} data-tone={value().tone} aria-hidden=\"true\" />}\n >\n {(text) => (\n <span class=\"k2b-stat-cell__accent\" data-tone={value().tone}>\n <i class={value().icon} aria-hidden=\"true\" />\n {text()}\n </span>\n )}\n </Show>\n )}\n </Show>\n {/* No figure, no trend: an empty tile says why in `sub` and keeps the size of its other states. */}\n <Show when={!empty() && props.trend && props.trend.length > 1}>\n <Chart\n kind=\"sparkline\"\n labels={{ interactiveChart: props.label }}\n tooltip={props.trendTooltip ?? defaultTrendTooltip}\n class=\"k2b-stat-cell__trend\"\n data={Array.from(props.trend ?? [])}\n showLast\n />\n </Show>\n </>\n }\n >\n {(stale) => (\n <>\n <span class=\"k2b-stat-cell__stale\">\n <i class=\"ti ti-clock-exclamation\" aria-hidden=\"true\" />\n {stale()}\n </span>\n <Show when={props.onRetry}>\n {(retry) => (\n <button type=\"button\" class=\"k2b-stat-cell__retry\" onClick={() => retry()()}>\n {t().reload}\n </button>\n )}\n </Show>\n </>\n )}\n </Show>\n }\n >\n <Match when={props.status === \"loading\"}>\n <span class=\"k2b-stat-cell__skeleton k2b-skeleton\" data-part=\"support\" aria-hidden=\"true\" />\n </Match>\n <Match when={props.status === \"error\"}>\n <Show when={props.onRetry}>\n {(retry) => (\n <button type=\"button\" class=\"k2b-stat-cell__retry\" onClick={() => retry()()}>\n {t().retry}\n </button>\n )}\n </Show>\n </Match>\n </Switch>\n </div>\n </>\n );\n}\n\n/**\n * One key figure as a framed tile: icon and label, the figure with its change, and a support line with the comparison\n * and the trend. Each state (loading, error, stale, empty) keeps the tile's place and size.\n */\nexport function StatCell(props: StatCellProps): JSX.Element {\n const gridSize = useStatGridSize();\n const size = () => props.size ?? gridSize;\n const surface = useStatGridSurface();\n return (\n <Show\n // A tile that offers a retry is no link: the button must not sit inside it.\n when={props.href && !props.status && !(props.stale && props.onRetry)}\n fallback={\n <div\n class=\"k2b-stat-cell\"\n data-size={size()}\n data-surface={surface}\n data-wrap={props.wrap || undefined}\n data-status={props.status}\n aria-busy={props.status === \"loading\" || undefined}\n >\n <Body {...props} />\n </div>\n }\n >\n <a\n href={props.href}\n class=\"k2b-stat-cell k2b-stat-cell--link\"\n data-size={size()}\n data-surface={surface}\n data-wrap={props.wrap || undefined}\n >\n <i class=\"ti ti-external-link k2b-stat-cell__link-icon\" aria-hidden=\"true\" />\n <Body {...props} />\n </a>\n </Show>\n );\n}\n\nexport default StatCell;\n"],"mappings":"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","ignoreList":[]}
|