@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
|
@@ -36,16 +36,26 @@ export function NumberInput(props) {
|
|
|
36
36
|
const messages = useUiMessages();
|
|
37
37
|
const inputMessages = useInputMessages();
|
|
38
38
|
const separator = createMemo(() => decimalSeparator(local.locale ?? contextLocale()));
|
|
39
|
-
// The visible text keeps the canonical number, only the decimal separator
|
|
40
|
-
// follows the effective locale; grouping is never rendered while editing.
|
|
41
|
-
const display = value => value == null ? "" : String(value).replace(".", separator());
|
|
42
|
-
const [raw, setRaw] = createSignal(display(value()));
|
|
43
39
|
const min = () => local.min ?? -Infinity;
|
|
44
40
|
const max = () => local.max ?? Infinity;
|
|
45
41
|
const step = () => local.step ?? 1;
|
|
46
42
|
// `step` and the accepted decimals never disagree: a fractional step implies
|
|
47
43
|
// its own precision unless the caller states `decimalPlaces` explicitly.
|
|
48
44
|
const places = () => Math.max(0, local.decimalPlaces ?? fractionDigits(step()));
|
|
45
|
+
// Keep ASCII digits and no grouping so display text round-trips through parse,
|
|
46
|
+
// including numbers that String/toFixed would write in exponential notation.
|
|
47
|
+
const formatter = createMemo(() => new Intl.NumberFormat("en", {
|
|
48
|
+
useGrouping: false,
|
|
49
|
+
minimumFractionDigits: places(),
|
|
50
|
+
maximumFractionDigits: places()
|
|
51
|
+
}));
|
|
52
|
+
const display = value => {
|
|
53
|
+
if (value == null) return "";
|
|
54
|
+
// Match normalize's rounding; toFixed switches to exponents at 1e21.
|
|
55
|
+
const text = Math.abs(value) < 1e21 ? value.toFixed(places()) : formatter().format(value);
|
|
56
|
+
return text.replace(".", separator());
|
|
57
|
+
};
|
|
58
|
+
const [raw, setRaw] = createSignal(display(value()));
|
|
49
59
|
const filter = input => {
|
|
50
60
|
let output = "";
|
|
51
61
|
let decimal = false;
|
|
@@ -89,7 +99,9 @@ export function NumberInput(props) {
|
|
|
89
99
|
};
|
|
90
100
|
createEffect(() => {
|
|
91
101
|
if (focused()) return;
|
|
92
|
-
|
|
102
|
+
// Synchronize display text: precision or locale can change
|
|
103
|
+
// without changing the controlled number. This effect never emits changes.
|
|
104
|
+
setRaw(display(value()));
|
|
93
105
|
});
|
|
94
106
|
// Enter already committed the current text, so leaving the field does not commit it twice.
|
|
95
107
|
let committedOnEnter = false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["inputs/NumberInput.tsx"],"sourcesContent":["import { createEffect, createMemo, createSignal, type JSX, Show, splitProps } from \"solid-js\";\nimport { createFieldMeta, Field, fieldControlAria } from \"../internal/field\";\nimport { decimalSeparator, useLocale } from \"../intl/locale\";\nimport { useUiMessages } from \"../intl/messages\";\nimport type { ValueFieldProps } from \"./field-contract\";\nimport { resolveMaybeAccessor } from \"./field-contract\";\nimport { useInputMessages } from \"./input-messages\";\nimport type { ChoiceAppearance } from \"./Select\";\n\nexport type NumberInputProps = Omit<\n JSX.InputHTMLAttributes<HTMLInputElement>,\n \"max\" | \"min\" | \"onChange\" | \"onInput\" | \"prefix\" | \"step\" | \"type\" | \"value\" | keyof ValueFieldProps<number | null>\n> &\n ValueFieldProps<number | null> & {\n max?: number;\n min?: number;\n /** Stepper increment and commit grid; defaults to `1`. A fractional step also sets the default `decimalPlaces`. */\n step?: number;\n /** Accepted fraction digits. Defaults to the fraction digits of `step` (`0.01` → `2`, `1` → `0`); an explicit value wins. */\n decimalPlaces?: number;\n allowNegative?: boolean;\n clearable?: boolean;\n onClear?: () => void;\n clearLabel?: string;\n increaseLabel?: string;\n decreaseLabel?: string;\n /** Explicit locale for the decimal separator; defaults to the inherited render locale. */\n locale?: string;\n showSteppers?: boolean;\n disableSteppers?: boolean;\n icon?: string;\n activeIcon?: string;\n prefix?: JSX.Element;\n suffix?: JSX.Element;\n /**\n * `plain` edits the value in place for property rows: no box and no steppers\n * or clear button. The field sizes to its text, Enter commits, Escape\n * restores the current value, and clearing the text clears the value. Focus\n * stays in the field.\n */\n appearance?: ChoiceAppearance;\n /**\n * Text for a set value while a plain field is not being edited, such as\n * `90` as \"1 h 30 min\". It also names the value for assistive technology.\n * The suffix then shows only while editing.\n */\n formatValue?: (value: number) => string;\n };\n\nfunction fractionDigits(value: number): number {\n if (!Number.isFinite(value)) return 0;\n const [mantissa = \"\", exponent = \"0\"] = String(value).split(\"e\");\n const fraction = mantissa.split(\".\")[1]?.length ?? 0;\n return Math.max(0, fraction - Number(exponent));\n}\n\nexport function NumberInput(props: NumberInputProps): JSX.Element {\n const [local, rest] = splitProps(props, [\n \"activeIcon\",\n \"appearance\",\n \"allowNegative\",\n \"aria-describedby\",\n \"aria-label\",\n \"class\",\n \"clearLabel\",\n \"clearable\",\n \"decimalPlaces\",\n \"decreaseLabel\",\n \"description\",\n \"disableSteppers\",\n \"error\",\n \"formatValue\",\n \"icon\",\n \"id\",\n \"increaseLabel\",\n \"label\",\n \"locale\",\n \"max\",\n \"min\",\n \"onClear\",\n \"onKeyDown\",\n \"onValueCommit\",\n \"onValueChange\",\n \"prefix\",\n \"required\",\n \"showSteppers\",\n \"step\",\n \"suffix\",\n \"value\",\n ]);\n const meta = createFieldMeta(local.id);\n const plain = () => local.appearance === \"plain\";\n let input: HTMLInputElement | undefined;\n const [focused, setFocused] = createSignal(false);\n const value = () => resolveMaybeAccessor(local.value);\n const error = () => resolveMaybeAccessor(local.error);\n const contextLocale = useLocale();\n const messages = useUiMessages();\n const inputMessages = useInputMessages();\n const separator = createMemo(() => decimalSeparator(local.locale ?? contextLocale()));\n // The visible text keeps the canonical number, only the decimal separator\n // follows the effective locale; grouping is never rendered while editing.\n const display = (value: number | null | undefined) => (value == null ? \"\" : String(value).replace(\".\", separator()));\n const [raw, setRaw] = createSignal(display(value()));\n const min = () => local.min ?? -Infinity;\n const max = () => local.max ?? Infinity;\n const step = () => local.step ?? 1;\n // `step` and the accepted decimals never disagree: a fractional step implies\n // its own precision unless the caller states `decimalPlaces` explicitly.\n const places = () => Math.max(0, local.decimalPlaces ?? fractionDigits(step()));\n\n const filter = (input: string) => {\n let output = \"\";\n let decimal = false;\n for (const character of input) {\n if (/\\d/.test(character)) output += character;\n else if (character === \"-\" && output === \"\" && (local.allowNegative ?? true)) output += character;\n else if ((character === \".\" || character === \",\" || character === separator()) && !decimal && places() > 0) {\n output += separator();\n decimal = true;\n }\n }\n if (decimal) {\n const [integer = \"\", fraction = \"\"] = output.split(separator());\n return `${integer}${separator()}${fraction.slice(0, places())}`;\n }\n return output;\n };\n const parse = (input: string) => {\n const canonical = input.replace(separator(), \".\");\n if (!canonical || canonical === \"-\" || canonical === \".\") return null;\n const number = places() === 0 ? Number.parseInt(canonical, 10) : Number(canonical);\n return Number.isFinite(number) ? number : null;\n };\n const normalize = (value: number | null) => {\n if (value === null) return null;\n const clamped = Math.max(min(), Math.min(max(), value));\n const anchor = Number.isFinite(min()) ? min() : 0;\n const snapped = step() > 0 ? Math.round((clamped - anchor) / step()) * step() + anchor : clamped;\n const bounded = Math.max(min(), Math.min(max(), snapped));\n return places() === 0 ? Math.round(bounded) : Number(bounded.toFixed(places()));\n };\n const emit = (value: number | null) => local.onValueChange?.(value);\n const commit = (value: number | null, changeAlreadyEmitted = false) => {\n const next = normalize(value);\n setRaw(display(next));\n if (!changeAlreadyEmitted || !Object.is(next, value)) emit(next);\n local.onValueCommit?.(next);\n };\n const stepBy = (direction: number) => {\n if (rest.disabled || local.disableSteppers) return;\n const seed = value() ?? (Number.isFinite(min()) ? min() : 0);\n commit(seed + direction * step());\n };\n\n createEffect(() => {\n if (focused()) return;\n if (parse(raw()) !== value()) setRaw(display(value()));\n });\n // Enter already committed the current text, so leaving the field does not commit it twice.\n let committedOnEnter = false;\n const onKeyDown: JSX.EventHandler<HTMLInputElement, KeyboardEvent> = (event) => {\n const handler = local.onKeyDown;\n if (typeof handler === \"function\") handler(event);\n else if (Array.isArray(handler)) handler[0](handler[1], event);\n if (!plain() || event.defaultPrevented) return;\n // Both keys keep focus in the field, so keyboard and screen reader users stay in place.\n if (event.key === \"Enter\") {\n event.preventDefault();\n commit(parse(raw()), true);\n committedOnEnter = true;\n } else if (event.key === \"Escape\" && parse(raw()) !== value()) {\n // Only an edit in progress swallows Escape; otherwise it reaches an enclosing panel.\n event.preventDefault();\n event.stopPropagation();\n setRaw(display(value()));\n }\n };\n const placeholderText = () => (typeof rest.placeholder === \"string\" ? rest.placeholder : \"\");\n /** What a plain field shows: the formatted value at rest, the text being edited while focused. */\n const shownText = () => {\n const current = value();\n if (!focused() && current != null && local.formatValue) return local.formatValue(current);\n return raw() || placeholderText();\n };\n const valueText = () => {\n if (rest[\"aria-valuetext\"] !== undefined) return rest[\"aria-valuetext\"];\n const current = focused() ? parse(raw()) : value();\n if (current == null) return undefined;\n if (local.formatValue) return local.formatValue(current);\n const unit = typeof local.suffix === \"string\" ? local.suffix : \"\";\n return unit ? `${display(current)} ${unit}` : undefined;\n };\n const control = () => (\n <input\n {...rest}\n ref={input}\n id={meta.controlId}\n class=\"k2b-input k2b-number-input__control\"\n data-filled={raw() ? \"true\" : undefined}\n type=\"text\"\n role=\"spinbutton\"\n inputmode={places() === 0 ? \"numeric\" : \"decimal\"}\n value={raw()}\n required={local.required}\n {...fieldControlAria(meta, local)}\n aria-valuemin={Number.isFinite(min()) ? min() : undefined}\n aria-valuemax={Number.isFinite(max()) ? max() : undefined}\n aria-valuenow={(focused() ? parse(raw()) : value()) ?? undefined}\n aria-valuetext={valueText()}\n // The plain sizer sets the width; the smallest intrinsic size keeps the input from widening it.\n size={plain() ? 1 : rest.size}\n onFocus={() => setFocused(true)}\n onKeyDown={onKeyDown}\n onInput={(event) => {\n const input = event.currentTarget;\n const current = input.value;\n const selectionStart = input.selectionStart;\n const selectionEnd = input.selectionEnd;\n const next = filter(current);\n // Only write back when the filter actually dropped something —\n // re-assigning an unchanged value moves the caret to the end.\n if (current !== next) {\n input.value = next;\n if (selectionStart !== null && selectionEnd !== null) {\n input.setSelectionRange(filter(current.slice(0, selectionStart)).length, filter(current.slice(0, selectionEnd)).length);\n }\n }\n setRaw(next);\n committedOnEnter = false;\n emit(parse(next));\n }}\n onBlur={() => {\n if (!committedOnEnter) commit(parse(raw()), true);\n committedOnEnter = false;\n setFocused(false);\n }}\n />\n );\n\n return (\n <Field\n class={local.class}\n label={local.label}\n description={local.description}\n error={error()}\n meta={meta}\n required={local.required}\n disabled={rest.disabled}\n >\n {/* biome-ignore lint/a11y/noStaticElementInteractions lint/a11y/useKeyWithClickEvents: the input inside is the keyboard target; a plain field's row only forwards a pointer click beside the text to it. */}\n <div\n class=\"k2b-input-shell k2b-number-input\"\n data-appearance={local.appearance ?? \"field\"}\n data-disabled={rest.disabled ? \"true\" : undefined}\n data-invalid={error() ? \"true\" : undefined}\n onClick={(event) => {\n if (plain() && event.target !== input && !rest.disabled) input?.focus();\n }}\n >\n <Show when={local.showSteppers ?? !plain()}>\n <button\n type=\"button\"\n class=\"k2b-number-input__step\"\n aria-label={local.decreaseLabel ?? inputMessages().decreaseValue}\n disabled={rest.disabled || local.disableSteppers || (value() !== null && value() !== undefined && value()! <= min())}\n onClick={() => stepBy(-1)}\n >\n <i class=\"ti ti-minus\" aria-hidden=\"true\" />\n </button>\n </Show>\n <div class=\"k2b-number-input__value\">\n <Show when={local.icon}>\n <span class=\"k2b-input-shell__icon k2b-text-input__icon\" aria-hidden=\"true\">\n <i class={local.icon} />\n <i class={local.activeIcon ?? local.icon} />\n </span>\n </Show>\n <Show when={local.prefix}>\n <span class=\"k2b-input-shell__affix\">{local.prefix}</span>\n </Show>\n <Show when={plain()} fallback={control()}>\n {/* The sizer shows the text in the input's grid cell, so the field is as wide as what it shows. At rest it is\n the visible value; while editing the input takes over. */}\n <span\n class=\"k2b-number-input__sizer\"\n data-value={shownText()}\n data-placeholder={raw() ? undefined : \"true\"}\n data-editing={focused() ? \"true\" : undefined}\n >\n {control()}\n </span>\n </Show>\n <Show when={local.suffix && (!plain() || (raw() && (focused() || !local.formatValue)))}>\n <span class=\"k2b-input-shell__affix\">{local.suffix}</span>\n </Show>\n <Show when={local.clearable && raw() && !rest.disabled && !rest.readOnly && !plain()}>\n <button\n type=\"button\"\n class=\"k2b-input-shell__clear k2b-input-clear-action\"\n aria-label={local.clearLabel ?? messages().clear}\n onClick={() => (local.onClear ? local.onClear() : commit(null))}\n >\n <i class=\"ti ti-x\" aria-hidden=\"true\" />\n </button>\n </Show>\n </div>\n <Show when={local.showSteppers ?? !plain()}>\n <button\n type=\"button\"\n class=\"k2b-number-input__step\"\n aria-label={local.increaseLabel ?? inputMessages().increaseValue}\n disabled={rest.disabled || local.disableSteppers || (value() !== null && value() !== undefined && value()! >= max())}\n onClick={() => stepBy(1)}\n >\n <i class=\"ti ti-plus\" aria-hidden=\"true\" />\n </button>\n </Show>\n </div>\n </Field>\n );\n}\n\nexport default NumberInput;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["inputs/NumberInput.tsx"],"sourcesContent":["import { createEffect, createMemo, createSignal, type JSX, Show, splitProps } from \"solid-js\";\nimport { createFieldMeta, Field, fieldControlAria } from \"../internal/field\";\nimport { decimalSeparator, useLocale } from \"../intl/locale\";\nimport { useUiMessages } from \"../intl/messages\";\nimport type { ValueFieldProps } from \"./field-contract\";\nimport { resolveMaybeAccessor } from \"./field-contract\";\nimport { useInputMessages } from \"./input-messages\";\nimport type { ChoiceAppearance } from \"./Select\";\n\nexport type NumberInputProps = Omit<\n JSX.InputHTMLAttributes<HTMLInputElement>,\n \"max\" | \"min\" | \"onChange\" | \"onInput\" | \"prefix\" | \"step\" | \"type\" | \"value\" | keyof ValueFieldProps<number | null>\n> &\n ValueFieldProps<number | null> & {\n max?: number;\n min?: number;\n /** Stepper increment and commit grid; defaults to `1`. A fractional step also sets the default `decimalPlaces`. */\n step?: number;\n /** Accepted and displayed fraction digits. Defaults to the fraction digits of `step` (`0.01` → `2`, `1` → `0`); an explicit value wins. */\n decimalPlaces?: number;\n allowNegative?: boolean;\n clearable?: boolean;\n onClear?: () => void;\n clearLabel?: string;\n increaseLabel?: string;\n decreaseLabel?: string;\n /** Explicit locale for the decimal separator; defaults to the inherited render locale. */\n locale?: string;\n showSteppers?: boolean;\n disableSteppers?: boolean;\n icon?: string;\n activeIcon?: string;\n prefix?: JSX.Element;\n suffix?: JSX.Element;\n /**\n * `plain` edits the value in place for property rows: no box and no steppers\n * or clear button. The field sizes to its text, Enter commits, Escape\n * restores the current value, and clearing the text clears the value. Focus\n * stays in the field.\n */\n appearance?: ChoiceAppearance;\n /**\n * Text for a set value while a plain field is not being edited, such as\n * `90` as \"1 h 30 min\". It also names the value for assistive technology.\n * The suffix then shows only while editing.\n */\n formatValue?: (value: number) => string;\n };\n\nfunction fractionDigits(value: number): number {\n if (!Number.isFinite(value)) return 0;\n const [mantissa = \"\", exponent = \"0\"] = String(value).split(\"e\");\n const fraction = mantissa.split(\".\")[1]?.length ?? 0;\n return Math.max(0, fraction - Number(exponent));\n}\n\nexport function NumberInput(props: NumberInputProps): JSX.Element {\n const [local, rest] = splitProps(props, [\n \"activeIcon\",\n \"appearance\",\n \"allowNegative\",\n \"aria-describedby\",\n \"aria-label\",\n \"class\",\n \"clearLabel\",\n \"clearable\",\n \"decimalPlaces\",\n \"decreaseLabel\",\n \"description\",\n \"disableSteppers\",\n \"error\",\n \"formatValue\",\n \"icon\",\n \"id\",\n \"increaseLabel\",\n \"label\",\n \"locale\",\n \"max\",\n \"min\",\n \"onClear\",\n \"onKeyDown\",\n \"onValueCommit\",\n \"onValueChange\",\n \"prefix\",\n \"required\",\n \"showSteppers\",\n \"step\",\n \"suffix\",\n \"value\",\n ]);\n const meta = createFieldMeta(local.id);\n const plain = () => local.appearance === \"plain\";\n let input: HTMLInputElement | undefined;\n const [focused, setFocused] = createSignal(false);\n const value = () => resolveMaybeAccessor(local.value);\n const error = () => resolveMaybeAccessor(local.error);\n const contextLocale = useLocale();\n const messages = useUiMessages();\n const inputMessages = useInputMessages();\n const separator = createMemo(() => decimalSeparator(local.locale ?? contextLocale()));\n const min = () => local.min ?? -Infinity;\n const max = () => local.max ?? Infinity;\n const step = () => local.step ?? 1;\n // `step` and the accepted decimals never disagree: a fractional step implies\n // its own precision unless the caller states `decimalPlaces` explicitly.\n const places = () => Math.max(0, local.decimalPlaces ?? fractionDigits(step()));\n // Keep ASCII digits and no grouping so display text round-trips through parse,\n // including numbers that String/toFixed would write in exponential notation.\n const formatter = createMemo(\n () =>\n new Intl.NumberFormat(\"en\", {\n useGrouping: false,\n minimumFractionDigits: places(),\n maximumFractionDigits: places(),\n }),\n );\n const display = (value: number | null | undefined) => {\n if (value == null) return \"\";\n // Match normalize's rounding; toFixed switches to exponents at 1e21.\n const text = Math.abs(value) < 1e21 ? value.toFixed(places()) : formatter().format(value);\n return text.replace(\".\", separator());\n };\n const [raw, setRaw] = createSignal(display(value()));\n\n const filter = (input: string) => {\n let output = \"\";\n let decimal = false;\n for (const character of input) {\n if (/\\d/.test(character)) output += character;\n else if (character === \"-\" && output === \"\" && (local.allowNegative ?? true)) output += character;\n else if ((character === \".\" || character === \",\" || character === separator()) && !decimal && places() > 0) {\n output += separator();\n decimal = true;\n }\n }\n if (decimal) {\n const [integer = \"\", fraction = \"\"] = output.split(separator());\n return `${integer}${separator()}${fraction.slice(0, places())}`;\n }\n return output;\n };\n const parse = (input: string) => {\n const canonical = input.replace(separator(), \".\");\n if (!canonical || canonical === \"-\" || canonical === \".\") return null;\n const number = places() === 0 ? Number.parseInt(canonical, 10) : Number(canonical);\n return Number.isFinite(number) ? number : null;\n };\n const normalize = (value: number | null) => {\n if (value === null) return null;\n const clamped = Math.max(min(), Math.min(max(), value));\n const anchor = Number.isFinite(min()) ? min() : 0;\n const snapped = step() > 0 ? Math.round((clamped - anchor) / step()) * step() + anchor : clamped;\n const bounded = Math.max(min(), Math.min(max(), snapped));\n return places() === 0 ? Math.round(bounded) : Number(bounded.toFixed(places()));\n };\n const emit = (value: number | null) => local.onValueChange?.(value);\n const commit = (value: number | null, changeAlreadyEmitted = false) => {\n const next = normalize(value);\n setRaw(display(next));\n if (!changeAlreadyEmitted || !Object.is(next, value)) emit(next);\n local.onValueCommit?.(next);\n };\n const stepBy = (direction: number) => {\n if (rest.disabled || local.disableSteppers) return;\n const seed = value() ?? (Number.isFinite(min()) ? min() : 0);\n commit(seed + direction * step());\n };\n\n createEffect(() => {\n if (focused()) return;\n // Synchronize display text: precision or locale can change\n // without changing the controlled number. This effect never emits changes.\n setRaw(display(value()));\n });\n // Enter already committed the current text, so leaving the field does not commit it twice.\n let committedOnEnter = false;\n const onKeyDown: JSX.EventHandler<HTMLInputElement, KeyboardEvent> = (event) => {\n const handler = local.onKeyDown;\n if (typeof handler === \"function\") handler(event);\n else if (Array.isArray(handler)) handler[0](handler[1], event);\n if (!plain() || event.defaultPrevented) return;\n // Both keys keep focus in the field, so keyboard and screen reader users stay in place.\n if (event.key === \"Enter\") {\n event.preventDefault();\n commit(parse(raw()), true);\n committedOnEnter = true;\n } else if (event.key === \"Escape\" && parse(raw()) !== value()) {\n // Only an edit in progress swallows Escape; otherwise it reaches an enclosing panel.\n event.preventDefault();\n event.stopPropagation();\n setRaw(display(value()));\n }\n };\n const placeholderText = () => (typeof rest.placeholder === \"string\" ? rest.placeholder : \"\");\n /** What a plain field shows: the formatted value at rest, the text being edited while focused. */\n const shownText = () => {\n const current = value();\n if (!focused() && current != null && local.formatValue) return local.formatValue(current);\n return raw() || placeholderText();\n };\n const valueText = () => {\n if (rest[\"aria-valuetext\"] !== undefined) return rest[\"aria-valuetext\"];\n const current = focused() ? parse(raw()) : value();\n if (current == null) return undefined;\n if (local.formatValue) return local.formatValue(current);\n const unit = typeof local.suffix === \"string\" ? local.suffix : \"\";\n return unit ? `${display(current)} ${unit}` : undefined;\n };\n const control = () => (\n <input\n {...rest}\n ref={input}\n id={meta.controlId}\n class=\"k2b-input k2b-number-input__control\"\n data-filled={raw() ? \"true\" : undefined}\n type=\"text\"\n role=\"spinbutton\"\n inputmode={places() === 0 ? \"numeric\" : \"decimal\"}\n value={raw()}\n required={local.required}\n {...fieldControlAria(meta, local)}\n aria-valuemin={Number.isFinite(min()) ? min() : undefined}\n aria-valuemax={Number.isFinite(max()) ? max() : undefined}\n aria-valuenow={(focused() ? parse(raw()) : value()) ?? undefined}\n aria-valuetext={valueText()}\n // The plain sizer sets the width; the smallest intrinsic size keeps the input from widening it.\n size={plain() ? 1 : rest.size}\n onFocus={() => setFocused(true)}\n onKeyDown={onKeyDown}\n onInput={(event) => {\n const input = event.currentTarget;\n const current = input.value;\n const selectionStart = input.selectionStart;\n const selectionEnd = input.selectionEnd;\n const next = filter(current);\n // Only write back when the filter actually dropped something —\n // re-assigning an unchanged value moves the caret to the end.\n if (current !== next) {\n input.value = next;\n if (selectionStart !== null && selectionEnd !== null) {\n input.setSelectionRange(filter(current.slice(0, selectionStart)).length, filter(current.slice(0, selectionEnd)).length);\n }\n }\n setRaw(next);\n committedOnEnter = false;\n emit(parse(next));\n }}\n onBlur={() => {\n if (!committedOnEnter) commit(parse(raw()), true);\n committedOnEnter = false;\n setFocused(false);\n }}\n />\n );\n\n return (\n <Field\n class={local.class}\n label={local.label}\n description={local.description}\n error={error()}\n meta={meta}\n required={local.required}\n disabled={rest.disabled}\n >\n {/* biome-ignore lint/a11y/noStaticElementInteractions lint/a11y/useKeyWithClickEvents: the input inside is the keyboard target; a plain field's row only forwards a pointer click beside the text to it. */}\n <div\n class=\"k2b-input-shell k2b-number-input\"\n data-appearance={local.appearance ?? \"field\"}\n data-disabled={rest.disabled ? \"true\" : undefined}\n data-invalid={error() ? \"true\" : undefined}\n onClick={(event) => {\n if (plain() && event.target !== input && !rest.disabled) input?.focus();\n }}\n >\n <Show when={local.showSteppers ?? !plain()}>\n <button\n type=\"button\"\n class=\"k2b-number-input__step\"\n aria-label={local.decreaseLabel ?? inputMessages().decreaseValue}\n disabled={rest.disabled || local.disableSteppers || (value() !== null && value() !== undefined && value()! <= min())}\n onClick={() => stepBy(-1)}\n >\n <i class=\"ti ti-minus\" aria-hidden=\"true\" />\n </button>\n </Show>\n <div class=\"k2b-number-input__value\">\n <Show when={local.icon}>\n <span class=\"k2b-input-shell__icon k2b-text-input__icon\" aria-hidden=\"true\">\n <i class={local.icon} />\n <i class={local.activeIcon ?? local.icon} />\n </span>\n </Show>\n <Show when={local.prefix}>\n <span class=\"k2b-input-shell__affix\">{local.prefix}</span>\n </Show>\n <Show when={plain()} fallback={control()}>\n {/* The sizer shows the text in the input's grid cell, so the field is as wide as what it shows. At rest it is\n the visible value; while editing the input takes over. */}\n <span\n class=\"k2b-number-input__sizer\"\n data-value={shownText()}\n data-placeholder={raw() ? undefined : \"true\"}\n data-editing={focused() ? \"true\" : undefined}\n >\n {control()}\n </span>\n </Show>\n <Show when={local.suffix && (!plain() || (raw() && (focused() || !local.formatValue)))}>\n <span class=\"k2b-input-shell__affix\">{local.suffix}</span>\n </Show>\n <Show when={local.clearable && raw() && !rest.disabled && !rest.readOnly && !plain()}>\n <button\n type=\"button\"\n class=\"k2b-input-shell__clear k2b-input-clear-action\"\n aria-label={local.clearLabel ?? messages().clear}\n onClick={() => (local.onClear ? local.onClear() : commit(null))}\n >\n <i class=\"ti ti-x\" aria-hidden=\"true\" />\n </button>\n </Show>\n </div>\n <Show when={local.showSteppers ?? !plain()}>\n <button\n type=\"button\"\n class=\"k2b-number-input__step\"\n aria-label={local.increaseLabel ?? inputMessages().increaseValue}\n disabled={rest.disabled || local.disableSteppers || (value() !== null && value() !== undefined && value()! >= max())}\n onClick={() => stepBy(1)}\n >\n <i class=\"ti ti-plus\" aria-hidden=\"true\" />\n </button>\n </Show>\n </div>\n </Field>\n );\n}\n\nexport default NumberInput;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -4,11 +4,13 @@ import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
|
|
|
4
4
|
import { escape as _$escape } from "solid-js/web";
|
|
5
5
|
import { createComponent as _$createComponent } from "solid-js/web";
|
|
6
6
|
import { memo as _$memo } from "solid-js/web";
|
|
7
|
-
var _tmpl$ = ["<span
|
|
8
|
-
_tmpl$2 = ["<
|
|
9
|
-
_tmpl$3 = ["<
|
|
10
|
-
_tmpl$4 = ["<
|
|
11
|
-
|
|
7
|
+
var _tmpl$ = ["<span>", "</span>"],
|
|
8
|
+
_tmpl$2 = ["<span", ">", "</span>"],
|
|
9
|
+
_tmpl$3 = ["<i", " aria-hidden=\"true\"></i>"],
|
|
10
|
+
_tmpl$4 = ["<img", " alt>"],
|
|
11
|
+
_tmpl$5 = ["<span aria-hidden=\"true\">", "</span>"],
|
|
12
|
+
_tmpl$6 = ["<input type=\"hidden\"", ">"];
|
|
13
|
+
import { createComputed, createEffect, createMemo, For, on, Show } from "solid-js";
|
|
12
14
|
import { Dropdown } from "../actions/Dropdown";
|
|
13
15
|
import { createFieldMeta, Field, fieldControlAria } from "../internal/field";
|
|
14
16
|
import { commitFieldValue, resolveMaybeAccessor } from "./field-contract";
|
|
@@ -136,16 +138,31 @@ export function SelectChip(props) {
|
|
|
136
138
|
get when() {
|
|
137
139
|
return selected()?.icon ?? props.icon;
|
|
138
140
|
},
|
|
139
|
-
children: icon => _$ssr(_tmpl$
|
|
141
|
+
children: icon => _$ssr(_tmpl$3, _$ssrAttribute("class", _$escape(icon(), true), false))
|
|
140
142
|
});
|
|
141
143
|
},
|
|
142
|
-
children: image => _$ssr(_tmpl$
|
|
144
|
+
children: image => _$ssr(_tmpl$4, _$ssrAttribute("src", _$escape(image(), true), false))
|
|
143
145
|
}), _$createComponent(Show, {
|
|
144
146
|
get when() {
|
|
145
147
|
return !props.iconOnly;
|
|
146
148
|
},
|
|
147
149
|
get children() {
|
|
148
|
-
return [_$ssr(_tmpl
|
|
150
|
+
return [_$ssr(_tmpl$2, _$ssrAttribute("data-placeholder", selected() ? _$escape(undefined, true) : "true", false) + _$ssrAttribute("data-stable-width", props.stableWidth ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
|
|
151
|
+
get when() {
|
|
152
|
+
return props.stableWidth;
|
|
153
|
+
},
|
|
154
|
+
get fallback() {
|
|
155
|
+
return selected()?.label ?? props.placeholder ?? "";
|
|
156
|
+
},
|
|
157
|
+
get children() {
|
|
158
|
+
return [_$ssr(_tmpl$, _$escape(selected()?.label ?? props.placeholder ?? "")), _$createComponent(For, {
|
|
159
|
+
get each() {
|
|
160
|
+
return props.options;
|
|
161
|
+
},
|
|
162
|
+
children: option => _$ssr(_tmpl$5, _$escape(option.label))
|
|
163
|
+
})];
|
|
164
|
+
}
|
|
165
|
+
}))), _$ssr(_tmpl$3, _$ssrAttribute("class", props.loading ? "ti ti-loader-2 k2b-spin" : "ti ti-chevron-down", false))];
|
|
149
166
|
}
|
|
150
167
|
})];
|
|
151
168
|
}
|
|
@@ -155,7 +172,7 @@ export function SelectChip(props) {
|
|
|
155
172
|
get when() {
|
|
156
173
|
return props.name;
|
|
157
174
|
},
|
|
158
|
-
children: name => _$ssr(_tmpl$
|
|
175
|
+
children: name => _$ssr(_tmpl$6, _$ssrAttribute("name", _$escape(name(), true), false) + _$ssrAttribute("value", _$escape(value(), true), false))
|
|
159
176
|
})];
|
|
160
177
|
}
|
|
161
178
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["inputs/SelectChip.tsx"],"sourcesContent":["import { createComputed, createEffect, createMemo, type JSX, on, Show } from \"solid-js\";\nimport type { ButtonSize } from \"../actions/Button\";\nimport { Dropdown, type DropdownItem, type DropdownPosition } from \"../actions/Dropdown\";\nimport { createFieldMeta, Field, fieldControlAria } from \"../internal/field\";\nimport type { MaybeAccessor, ValueFieldProps } from \"./field-contract\";\nimport { commitFieldValue, resolveMaybeAccessor } from \"./field-contract\";\nimport { useSelectMessages } from \"./select-messages\";\n\nexport type SelectChipOption<T extends string | number = string> = {\n value: T;\n label: string;\n description?: string;\n icon?: string;\n image?: string;\n disabled?: boolean;\n};\n\nexport type SelectChipProps<T extends string | number = string> = ValueFieldProps<T> & {\n value: MaybeAccessor<T>;\n options: SelectChipOption<T>[];\n icon?: string;\n iconOnly?: boolean;\n size?: ButtonSize;\n placeholder?: string;\n position?: DropdownPosition;\n /** Exact menu width as a CSS length. Without it the menu sizes to its options, at least `10rem`. */\n menuWidth?: string;\n name?: string;\n /** Shows that a change from this chip is saving: the chip stays in place with\n * its size, cannot be opened, is marked busy, and shows a spinner where its\n * chevron (or, icon-only, its icon) is. */\n loading?: boolean;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n};\n\nexport function SelectChip<T extends string | number = string>(props: SelectChipProps<T>): JSX.Element {\n const selectMessages = useSelectMessages();\n const meta = createFieldMeta(props.id);\n const value = () => resolveMaybeAccessor(props.value)!;\n const selected = () => props.options.find((option) => option.value === value());\n const disabled = createMemo(() => Boolean(props.disabled || props.loading));\n // A disabled button loses focus, so a chip disabled while a change saves (its own or one elsewhere) would leave\n // keyboard focus on the page. Focus returns to the chip once it is enabled again, unless it has moved on\n // meanwhile. The check runs as a computation, before the DOM update disables the button.\n let trigger: HTMLButtonElement | undefined;\n let refocus = false;\n createComputed(\n on(\n disabled,\n (isDisabled) => {\n if (isDisabled) refocus = trigger !== undefined && document.activeElement === trigger;\n },\n { defer: true },\n ),\n );\n createEffect(\n on(\n disabled,\n (isDisabled) => {\n if (isDisabled || !refocus) return;\n refocus = false;\n const active = document.activeElement;\n if (trigger?.isConnected && (active === null || active === document.body)) trigger.focus();\n },\n { defer: true },\n ),\n );\n const triggerLabel = () => props[\"aria-label\"] ?? (typeof props.label === \"string\" ? props.label : selectMessages().chooseOption);\n const items = createMemo<DropdownItem[]>(() =>\n props.options.map((option) => ({\n action: () => commitFieldValue(props, option.value),\n checked: () => option.value === value(),\n choice: \"radio\" as const,\n class: \"k2b-select-chip__option\",\n description: option.description,\n disabled: option.disabled,\n icon: option.icon,\n image: option.image,\n label: option.label,\n })),\n );\n\n return (\n <Field\n class={props.class}\n label={props.label}\n description={props.description}\n error={props.error}\n meta={meta}\n required={props.required}\n disabled={disabled()}\n >\n <Dropdown.Root\n // A controlled `open` cannot bypass a disabled or saving chip.\n open={props.open === undefined ? undefined : props.open && !disabled()}\n onOpenChange={props.onOpenChange}\n disabled={disabled()}\n position={props.position ?? \"bottom-right\"}\n /* Cloud opens this menu at `w-40`; the stylesheet keeps that as its floor. */\n width={props.menuWidth}\n menuClass=\"k2b-select-chip__menu\"\n label={triggerLabel()}\n items={items()}\n >\n <Dropdown.Trigger\n appearance={props.iconOnly ? \"button\" : \"plain\"}\n id={meta.controlId}\n ref={(element: HTMLButtonElement) => {\n trigger = element;\n }}\n class={props.iconOnly ? undefined : \"k2b-select-chip\"}\n disabled={disabled()}\n aria-busy={props.loading ? \"true\" : undefined}\n iconOnly={props.iconOnly}\n loading={props.iconOnly ? props.loading : undefined}\n label={triggerLabel()}\n size={props.iconOnly ? props.size : undefined}\n title={props.iconOnly ? triggerLabel() : undefined}\n {...fieldControlAria(meta, props)}\n >\n <Show\n when={selected()?.image}\n fallback={<Show when={selected()?.icon ?? props.icon}>{(icon) => <i class={icon()} aria-hidden=\"true\" />}</Show>}\n >\n {(image) => <img src={image()} alt=\"\" />}\n </Show>\n <Show when={!props.iconOnly}>\n <span data-placeholder={selected() ? undefined : \"true\"}>{selected()?.label ?? props.placeholder ?? \"\"}</span>\n {/* Both glyphs are one icon wide, so a saving chip keeps its size. */}\n <i class={props.loading ? \"ti ti-loader-2 k2b-spin\" : \"ti ti-chevron-down\"} aria-hidden=\"true\" />\n </Show>\n </Dropdown.Trigger>\n </Dropdown.Root>\n <Show when={props.name}>{(name) => <input type=\"hidden\" name={name()} value={value()} />}</Show>\n </Field>\n );\n}\n\nexport default SelectChip;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["inputs/SelectChip.tsx"],"sourcesContent":["import { createComputed, createEffect, createMemo, For, type JSX, on, Show } from \"solid-js\";\nimport type { ButtonSize } from \"../actions/Button\";\nimport { Dropdown, type DropdownItem, type DropdownPosition } from \"../actions/Dropdown\";\nimport { createFieldMeta, Field, fieldControlAria } from \"../internal/field\";\nimport type { MaybeAccessor, ValueFieldProps } from \"./field-contract\";\nimport { commitFieldValue, resolveMaybeAccessor } from \"./field-contract\";\nimport { useSelectMessages } from \"./select-messages\";\n\nexport type SelectChipOption<T extends string | number = string> = {\n value: T;\n label: string;\n description?: string;\n icon?: string;\n image?: string;\n disabled?: boolean;\n};\n\nexport type SelectChipProps<T extends string | number = string> = ValueFieldProps<T> & {\n value: MaybeAccessor<T>;\n options: SelectChipOption<T>[];\n icon?: string;\n iconOnly?: boolean;\n size?: ButtonSize;\n placeholder?: string;\n position?: DropdownPosition;\n /** Exact menu width as a CSS length. Without it the menu sizes to its options, at least `10rem`. */\n menuWidth?: string;\n name?: string;\n /** Shows that a change from this chip is saving: the chip stays in place with\n * its size, cannot be opened, is marked busy, and shows a spinner where its\n * chevron (or, icon-only, its icon) is. */\n loading?: boolean;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Keeps the width of the longest option label, so a new choice never moves what sits beside the chip. */\n stableWidth?: boolean;\n};\n\nexport function SelectChip<T extends string | number = string>(props: SelectChipProps<T>): JSX.Element {\n const selectMessages = useSelectMessages();\n const meta = createFieldMeta(props.id);\n const value = () => resolveMaybeAccessor(props.value)!;\n const selected = () => props.options.find((option) => option.value === value());\n const disabled = createMemo(() => Boolean(props.disabled || props.loading));\n // A disabled button loses focus, so a chip disabled while a change saves (its own or one elsewhere) would leave\n // keyboard focus on the page. Focus returns to the chip once it is enabled again, unless it has moved on\n // meanwhile. The check runs as a computation, before the DOM update disables the button.\n let trigger: HTMLButtonElement | undefined;\n let refocus = false;\n createComputed(\n on(\n disabled,\n (isDisabled) => {\n if (isDisabled) refocus = trigger !== undefined && document.activeElement === trigger;\n },\n { defer: true },\n ),\n );\n createEffect(\n on(\n disabled,\n (isDisabled) => {\n if (isDisabled || !refocus) return;\n refocus = false;\n const active = document.activeElement;\n if (trigger?.isConnected && (active === null || active === document.body)) trigger.focus();\n },\n { defer: true },\n ),\n );\n const triggerLabel = () => props[\"aria-label\"] ?? (typeof props.label === \"string\" ? props.label : selectMessages().chooseOption);\n const items = createMemo<DropdownItem[]>(() =>\n props.options.map((option) => ({\n action: () => commitFieldValue(props, option.value),\n checked: () => option.value === value(),\n choice: \"radio\" as const,\n class: \"k2b-select-chip__option\",\n description: option.description,\n disabled: option.disabled,\n icon: option.icon,\n image: option.image,\n label: option.label,\n })),\n );\n\n return (\n <Field\n class={props.class}\n label={props.label}\n description={props.description}\n error={props.error}\n meta={meta}\n required={props.required}\n disabled={disabled()}\n >\n <Dropdown.Root\n // A controlled `open` cannot bypass a disabled or saving chip.\n open={props.open === undefined ? undefined : props.open && !disabled()}\n onOpenChange={props.onOpenChange}\n disabled={disabled()}\n position={props.position ?? \"bottom-right\"}\n /* Cloud opens this menu at `w-40`; the stylesheet keeps that as its floor. */\n width={props.menuWidth}\n menuClass=\"k2b-select-chip__menu\"\n label={triggerLabel()}\n items={items()}\n >\n <Dropdown.Trigger\n appearance={props.iconOnly ? \"button\" : \"plain\"}\n id={meta.controlId}\n ref={(element: HTMLButtonElement) => {\n trigger = element;\n }}\n class={props.iconOnly ? undefined : \"k2b-select-chip\"}\n disabled={disabled()}\n aria-busy={props.loading ? \"true\" : undefined}\n iconOnly={props.iconOnly}\n loading={props.iconOnly ? props.loading : undefined}\n label={triggerLabel()}\n size={props.iconOnly ? props.size : undefined}\n title={props.iconOnly ? triggerLabel() : undefined}\n {...fieldControlAria(meta, props)}\n >\n <Show\n when={selected()?.image}\n fallback={<Show when={selected()?.icon ?? props.icon}>{(icon) => <i class={icon()} aria-hidden=\"true\" />}</Show>}\n >\n {(image) => <img src={image()} alt=\"\" />}\n </Show>\n <Show when={!props.iconOnly}>\n <span data-placeholder={selected() ? undefined : \"true\"} data-stable-width={props.stableWidth ? \"true\" : undefined}>\n <Show when={props.stableWidth} fallback={selected()?.label ?? props.placeholder ?? \"\"}>\n <span>{selected()?.label ?? props.placeholder ?? \"\"}</span>\n <For each={props.options}>{(option) => <span aria-hidden=\"true\">{option.label}</span>}</For>\n </Show>\n </span>\n {/* Both glyphs are one icon wide, so a saving chip keeps its size. */}\n <i class={props.loading ? \"ti ti-loader-2 k2b-spin\" : \"ti ti-chevron-down\"} aria-hidden=\"true\" />\n </Show>\n </Dropdown.Trigger>\n </Dropdown.Root>\n <Show when={props.name}>{(name) => <input type=\"hidden\" name={name()} value={value()} />}</Show>\n </Field>\n );\n}\n\nexport default SelectChip;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -121,6 +121,19 @@ export const toDateTimeValue = (date, time, context) => {
|
|
|
121
121
|
}
|
|
122
122
|
return local;
|
|
123
123
|
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* The value an applied draft commits. An untouched draft keeps the exact value: the panel shows minutes in the
|
|
127
|
+
* picker's zone, and a wall time that a daylight-saving change repeats names two instants, so rebuilding it could
|
|
128
|
+
* move the value by an hour or drop its seconds.
|
|
129
|
+
*/
|
|
130
|
+
export const draftDateTimeValue = (value, date, time, context) => {
|
|
131
|
+
if (value) {
|
|
132
|
+
const current = splitDateTime(value, context);
|
|
133
|
+
if (current.date === date && current.time === time) return value;
|
|
134
|
+
}
|
|
135
|
+
return toDateTimeValue(date, time, context);
|
|
136
|
+
};
|
|
124
137
|
export const formatDateTimeValue = (value, context) => value ? dates.formatDateTime(value, pickerContext(context)) : "";
|
|
125
138
|
export const normalizeTimeInput = value => {
|
|
126
139
|
const [hours = "", minutes = ""] = value.split(":");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["inputs/date-picker.ts"],"sourcesContent":["import { type DateContext, dates } from \"@k2b/stdlib\";\n\nexport type DateRangeValue = {\n start: string | null;\n end: string | null;\n};\n\nexport const pickerContext = (context?: DateContext): DateContext => ({\n weekStartsOn: 1,\n ...context,\n});\n\nexport const hasInstantOffset = (value: string): boolean => /[T\\s].*([zZ]|[+-]\\d{2}:?\\d{2})$/.test(value);\n\nexport const dateKey = (date: Date | string, context?: DateContext): string => dates.formatDateKey(date, pickerContext(context));\n\n/**\n * Short month names for the month panel. `dates.months()` only returns the long\n * form (\"September\"), which overflows the three-column month grid, so the short\n * form is derived here while staying locale aware.\n */\nexport const monthNames = (context?: DateContext): string[] => {\n const merged = pickerContext(context);\n const formatter = new Intl.DateTimeFormat(merged.locale, { month: \"short\", timeZone: \"UTC\" });\n return Array.from({ length: 12 }, (_, index) => formatter.format(Date.UTC(2024, index, 15)));\n};\n\n/**\n * Picks the roving-tabindex day for a rendered month grid. The preferred day is\n * used when the grid actually contains it, otherwise the first day of the\n * visible month keeps exactly one cell reachable by Tab.\n */\nexport const resolveFocusDay = (monthDayKeys: readonly string[], preferred: string | null | undefined): string | undefined =>\n preferred && monthDayKeys.includes(preferred) ? preferred : monthDayKeys[0];\n\nexport const yearMonth = (date: Date, context?: DateContext): { year: number; month: number } => {\n const [year = \"1970\", month = \"1\"] = dateKey(date, context).split(\"-\");\n return { year: Number(year), month: Number(month) - 1 };\n};\n\nexport const monthDate = (year: number, month: number, context?: DateContext): Date => {\n const value = `${year}-${String(month + 1).padStart(2, \"0\")}-01T12:00`;\n if (context?.timeZone) {\n return new Date(dates.zonedDateTimeToInstant(value, context.timeZone, { disambiguation: \"compatible\" }));\n }\n return new Date(year, month, 1, 12);\n};\n\n/**\n * Milliseconds from `now` until the next calendar day starts in the picker's\n * time zone, so a panel left open past midnight moves its today mark on time.\n * The next day's start is resolved from its date key: where a DST change skips\n * or repeats midnight, the day starts at its first existing instant.\n */\nexport const msUntilNextDay = (now: Date, context?: DateContext): number => {\n const merged = pickerContext(context);\n const { timeZone } = merged;\n const next = timeZone\n ? Date.parse(\n dates.zonedDateTimeToInstant(dates.addZoned(`${dateKey(now, merged)}T00:00`, { timeZone, days: 1 }), timeZone, {\n disambiguation: \"compatible\",\n }),\n )\n : dates.addDays(now, 1, merged).getTime();\n const delay = next - now.getTime();\n // The timer re-arms after every tick, so it must never fire at once. Should a\n // zone's rules still put the next day behind `now`, look again in a minute,\n // the finest unit the pickers show.\n return delay > 0 ? delay : 60_000;\n};\n\n/** Whether `value` is a date key such as `2026-10-24`, a date without a time. */\nexport const isDateKey = (value: string): boolean => /^\\d{4}-\\d{2}-\\d{2}$/.test(value);\n\nexport const parseDateValue = (value: string | null | undefined, context?: DateContext): Date => {\n if (!value) return dates.today(pickerContext(context));\n return dates.parseCalendarDate(value.slice(0, 10), pickerContext(context));\n};\n\n/** A date key names a calendar day, so it is formatted at noon UTC in UTC: no runtime or picker zone can move it. */\nexport const displayDate = (value: string | null | undefined, context?: DateContext): string =>\n value ? dates.formatDate(`${value.slice(0, 10)}T12:00:00.000Z`, { ...pickerContext(context), timeZone: \"UTC\" }) : \"\";\n\nconst localDateTimeInput = (value: string): string => {\n if (!hasInstantOffset(value)) return value.slice(0, 16);\n const date = new Date(value);\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, \"0\");\n const day = String(date.getDate()).padStart(2, \"0\");\n const hours = String(date.getHours()).padStart(2, \"0\");\n const minutes = String(date.getMinutes()).padStart(2, \"0\");\n return `${year}-${month}-${day}T${hours}:${minutes}`;\n};\n\nexport const dateTimeInput = (value: string | null | undefined, context?: DateContext): string => {\n if (!value) return \"\";\n if (context?.timeZone && hasInstantOffset(value)) return dates.instantToZonedInput(value, context.timeZone);\n return localDateTimeInput(value);\n};\n\nexport const splitDateTime = (value: string | null | undefined, context?: DateContext): { date: string; time: string } => {\n const input = dateTimeInput(value, context);\n const [date = \"\", time = \"\"] = input.split(\"T\");\n return { date, time: time.slice(0, 5) };\n};\n\nexport const isCompleteTime = (value: string): boolean => {\n if (!/^\\d{2}:\\d{2}$/.test(value)) return false;\n const [hours, minutes] = value.split(\":\").map(Number);\n return hours! >= 0 && hours! <= 23 && minutes! >= 0 && minutes! <= 59;\n};\n\nexport const toDateTimeValue = (date: string, time: string, context?: DateContext): string | null => {\n if (!date) return null;\n const resolvedTime = time || \"00:00\";\n if (!isCompleteTime(resolvedTime)) return null;\n const local = `${date}T${resolvedTime}`;\n if (context?.timeZone) {\n return dates.zonedDateTimeToInstant(local, context.timeZone, { disambiguation: \"compatible\" });\n }\n return local;\n};\n\nexport const formatDateTimeValue = (value: string | null | undefined, context?: DateContext): string =>\n value ? dates.formatDateTime(value, pickerContext(context)) : \"\";\n\nexport const normalizeTimeInput = (value: string): string => {\n const [hours = \"\", minutes = \"\"] = value.split(\":\");\n const hour = Math.max(0, Math.min(23, Number(hours || 0)));\n const minute = Math.max(0, Math.min(59, Number(minutes || 0)));\n return `${String(hour).padStart(2, \"0\")}:${String(minute).padStart(2, \"0\")}`;\n};\n\nexport const filterTimeInput = (value: string): string => {\n const digits = value.replace(/\\D/g, \"\").slice(0, 4);\n return digits.length <= 2 ? digits : `${digits.slice(0, 2)}:${digits.slice(2)}`;\n};\n\nexport const orderedRange = (start: string, end: string): DateRangeValue =>\n end.localeCompare(start) < 0 ? { start: end, end: start } : { start, end };\n\n/**\n * The range a click picks. A click starts a complete one-day range on its day, and it becomes the anchor; the next\n * click on another day extends the range from the anchor, whichever side it lies on. A click on the anchor keeps the\n * one-day range. After an extension, the next click starts a new one-day range.\n */\nexport const pickRangeDay = (\n range: DateRangeValue,\n anchor: string | null,\n day: string,\n): { range: DateRangeValue; anchor: string | null } => {\n if (rangeAnchor(range, anchor) && day !== anchor) return { range: orderedRange(anchor!, day), anchor: null };\n return { range: { start: day, end: day }, anchor: day };\n};\n\n/** The anchor that the next click extends from: only while the range is still the one-day range of its click. */\nexport const rangeAnchor = (range: DateRangeValue, anchor: string | null): string | null =>\n anchor && range.start === anchor && range.end === anchor ? anchor : null;\n\n/** The range shown while the pointer or focus rests on `preview`: the extension that a click there would pick. */\nexport const previewRange = (range: DateRangeValue, anchor: string | null, preview: string | null): DateRangeValue => {\n const from = rangeAnchor(range, anchor);\n return from && preview ? orderedRange(from, preview) : range;\n};\n\nexport const inRange = (day: string, range: DateRangeValue): boolean =>\n Boolean(range.start && range.end && day >= range.start && day <= range.end);\n\nexport const isRangeEdge = (day: string, range: DateRangeValue): boolean => day === range.start || day === range.end;\n\nexport const formatDateOnlyRangeDuration = (range: DateRangeValue, context?: DateContext): string => {\n if (!range.start || !range.end) return \"\";\n const start = Date.parse(`${dateKey(range.start, context)}T00:00:00.000Z`);\n const end = Date.parse(`${dateKey(range.end, context)}T00:00:00.000Z`);\n const days = Math.floor(Math.abs(end - start) / 86_400_000) + 1;\n return new Intl.NumberFormat(pickerContext(context).locale ?? \"en\", { style: \"unit\", unit: \"day\", unitDisplay: \"long\" }).format(days);\n};\n\n/**\n * The weekend bands of a week row: one band per run of adjacent weekend columns, as a zero-based start column and a\n * number of columns. Saturday and Sunday in a week from Monday are one band of two; in a week from Sunday they are\n * two bands at both ends.\n */\nexport const weekendBands = (weekend: readonly boolean[]): { start: number; span: number }[] => {\n const bands: { start: number; span: number }[] = [];\n weekend.forEach((isWeekend, column) => {\n if (!isWeekend) return;\n const last = bands.at(-1);\n if (last && last.start + last.span === column) last.span += 1;\n else bands.push({ start: column, span: 1 });\n });\n return bands;\n};\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["inputs/date-picker.ts"],"sourcesContent":["import { type DateContext, dates } from \"@k2b/stdlib\";\n\nexport type DateRangeValue = {\n start: string | null;\n end: string | null;\n};\n\nexport const pickerContext = (context?: DateContext): DateContext => ({\n weekStartsOn: 1,\n ...context,\n});\n\nexport const hasInstantOffset = (value: string): boolean => /[T\\s].*([zZ]|[+-]\\d{2}:?\\d{2})$/.test(value);\n\nexport const dateKey = (date: Date | string, context?: DateContext): string => dates.formatDateKey(date, pickerContext(context));\n\n/**\n * Short month names for the month panel. `dates.months()` only returns the long\n * form (\"September\"), which overflows the three-column month grid, so the short\n * form is derived here while staying locale aware.\n */\nexport const monthNames = (context?: DateContext): string[] => {\n const merged = pickerContext(context);\n const formatter = new Intl.DateTimeFormat(merged.locale, { month: \"short\", timeZone: \"UTC\" });\n return Array.from({ length: 12 }, (_, index) => formatter.format(Date.UTC(2024, index, 15)));\n};\n\n/**\n * Picks the roving-tabindex day for a rendered month grid. The preferred day is\n * used when the grid actually contains it, otherwise the first day of the\n * visible month keeps exactly one cell reachable by Tab.\n */\nexport const resolveFocusDay = (monthDayKeys: readonly string[], preferred: string | null | undefined): string | undefined =>\n preferred && monthDayKeys.includes(preferred) ? preferred : monthDayKeys[0];\n\nexport const yearMonth = (date: Date, context?: DateContext): { year: number; month: number } => {\n const [year = \"1970\", month = \"1\"] = dateKey(date, context).split(\"-\");\n return { year: Number(year), month: Number(month) - 1 };\n};\n\nexport const monthDate = (year: number, month: number, context?: DateContext): Date => {\n const value = `${year}-${String(month + 1).padStart(2, \"0\")}-01T12:00`;\n if (context?.timeZone) {\n return new Date(dates.zonedDateTimeToInstant(value, context.timeZone, { disambiguation: \"compatible\" }));\n }\n return new Date(year, month, 1, 12);\n};\n\n/**\n * Milliseconds from `now` until the next calendar day starts in the picker's\n * time zone, so a panel left open past midnight moves its today mark on time.\n * The next day's start is resolved from its date key: where a DST change skips\n * or repeats midnight, the day starts at its first existing instant.\n */\nexport const msUntilNextDay = (now: Date, context?: DateContext): number => {\n const merged = pickerContext(context);\n const { timeZone } = merged;\n const next = timeZone\n ? Date.parse(\n dates.zonedDateTimeToInstant(dates.addZoned(`${dateKey(now, merged)}T00:00`, { timeZone, days: 1 }), timeZone, {\n disambiguation: \"compatible\",\n }),\n )\n : dates.addDays(now, 1, merged).getTime();\n const delay = next - now.getTime();\n // The timer re-arms after every tick, so it must never fire at once. Should a\n // zone's rules still put the next day behind `now`, look again in a minute,\n // the finest unit the pickers show.\n return delay > 0 ? delay : 60_000;\n};\n\n/** Whether `value` is a date key such as `2026-10-24`, a date without a time. */\nexport const isDateKey = (value: string): boolean => /^\\d{4}-\\d{2}-\\d{2}$/.test(value);\n\nexport const parseDateValue = (value: string | null | undefined, context?: DateContext): Date => {\n if (!value) return dates.today(pickerContext(context));\n return dates.parseCalendarDate(value.slice(0, 10), pickerContext(context));\n};\n\n/** A date key names a calendar day, so it is formatted at noon UTC in UTC: no runtime or picker zone can move it. */\nexport const displayDate = (value: string | null | undefined, context?: DateContext): string =>\n value ? dates.formatDate(`${value.slice(0, 10)}T12:00:00.000Z`, { ...pickerContext(context), timeZone: \"UTC\" }) : \"\";\n\nconst localDateTimeInput = (value: string): string => {\n if (!hasInstantOffset(value)) return value.slice(0, 16);\n const date = new Date(value);\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, \"0\");\n const day = String(date.getDate()).padStart(2, \"0\");\n const hours = String(date.getHours()).padStart(2, \"0\");\n const minutes = String(date.getMinutes()).padStart(2, \"0\");\n return `${year}-${month}-${day}T${hours}:${minutes}`;\n};\n\nexport const dateTimeInput = (value: string | null | undefined, context?: DateContext): string => {\n if (!value) return \"\";\n if (context?.timeZone && hasInstantOffset(value)) return dates.instantToZonedInput(value, context.timeZone);\n return localDateTimeInput(value);\n};\n\nexport const splitDateTime = (value: string | null | undefined, context?: DateContext): { date: string; time: string } => {\n const input = dateTimeInput(value, context);\n const [date = \"\", time = \"\"] = input.split(\"T\");\n return { date, time: time.slice(0, 5) };\n};\n\nexport const isCompleteTime = (value: string): boolean => {\n if (!/^\\d{2}:\\d{2}$/.test(value)) return false;\n const [hours, minutes] = value.split(\":\").map(Number);\n return hours! >= 0 && hours! <= 23 && minutes! >= 0 && minutes! <= 59;\n};\n\nexport const toDateTimeValue = (date: string, time: string, context?: DateContext): string | null => {\n if (!date) return null;\n const resolvedTime = time || \"00:00\";\n if (!isCompleteTime(resolvedTime)) return null;\n const local = `${date}T${resolvedTime}`;\n if (context?.timeZone) {\n return dates.zonedDateTimeToInstant(local, context.timeZone, { disambiguation: \"compatible\" });\n }\n return local;\n};\n\n/**\n * The value an applied draft commits. An untouched draft keeps the exact value: the panel shows minutes in the\n * picker's zone, and a wall time that a daylight-saving change repeats names two instants, so rebuilding it could\n * move the value by an hour or drop its seconds.\n */\nexport const draftDateTimeValue = (value: string | null | undefined, date: string, time: string, context?: DateContext): string | null => {\n if (value) {\n const current = splitDateTime(value, context);\n if (current.date === date && current.time === time) return value;\n }\n return toDateTimeValue(date, time, context);\n};\n\nexport const formatDateTimeValue = (value: string | null | undefined, context?: DateContext): string =>\n value ? dates.formatDateTime(value, pickerContext(context)) : \"\";\n\nexport const normalizeTimeInput = (value: string): string => {\n const [hours = \"\", minutes = \"\"] = value.split(\":\");\n const hour = Math.max(0, Math.min(23, Number(hours || 0)));\n const minute = Math.max(0, Math.min(59, Number(minutes || 0)));\n return `${String(hour).padStart(2, \"0\")}:${String(minute).padStart(2, \"0\")}`;\n};\n\nexport const filterTimeInput = (value: string): string => {\n const digits = value.replace(/\\D/g, \"\").slice(0, 4);\n return digits.length <= 2 ? digits : `${digits.slice(0, 2)}:${digits.slice(2)}`;\n};\n\nexport const orderedRange = (start: string, end: string): DateRangeValue =>\n end.localeCompare(start) < 0 ? { start: end, end: start } : { start, end };\n\n/**\n * The range a click picks. A click starts a complete one-day range on its day, and it becomes the anchor; the next\n * click on another day extends the range from the anchor, whichever side it lies on. A click on the anchor keeps the\n * one-day range. After an extension, the next click starts a new one-day range.\n */\nexport const pickRangeDay = (\n range: DateRangeValue,\n anchor: string | null,\n day: string,\n): { range: DateRangeValue; anchor: string | null } => {\n if (rangeAnchor(range, anchor) && day !== anchor) return { range: orderedRange(anchor!, day), anchor: null };\n return { range: { start: day, end: day }, anchor: day };\n};\n\n/** The anchor that the next click extends from: only while the range is still the one-day range of its click. */\nexport const rangeAnchor = (range: DateRangeValue, anchor: string | null): string | null =>\n anchor && range.start === anchor && range.end === anchor ? anchor : null;\n\n/** The range shown while the pointer or focus rests on `preview`: the extension that a click there would pick. */\nexport const previewRange = (range: DateRangeValue, anchor: string | null, preview: string | null): DateRangeValue => {\n const from = rangeAnchor(range, anchor);\n return from && preview ? orderedRange(from, preview) : range;\n};\n\nexport const inRange = (day: string, range: DateRangeValue): boolean =>\n Boolean(range.start && range.end && day >= range.start && day <= range.end);\n\nexport const isRangeEdge = (day: string, range: DateRangeValue): boolean => day === range.start || day === range.end;\n\nexport const formatDateOnlyRangeDuration = (range: DateRangeValue, context?: DateContext): string => {\n if (!range.start || !range.end) return \"\";\n const start = Date.parse(`${dateKey(range.start, context)}T00:00:00.000Z`);\n const end = Date.parse(`${dateKey(range.end, context)}T00:00:00.000Z`);\n const days = Math.floor(Math.abs(end - start) / 86_400_000) + 1;\n return new Intl.NumberFormat(pickerContext(context).locale ?? \"en\", { style: \"unit\", unit: \"day\", unitDisplay: \"long\" }).format(days);\n};\n\n/**\n * The weekend bands of a week row: one band per run of adjacent weekend columns, as a zero-based start column and a\n * number of columns. Saturday and Sunday in a week from Monday are one band of two; in a week from Sunday they are\n * two bands at both ends.\n */\nexport const weekendBands = (weekend: readonly boolean[]): { start: number; span: number }[] => {\n const bands: { start: number; span: number }[] = [];\n weekend.forEach((isWeekend, column) => {\n if (!isWeekend) return;\n const last = bands.at(-1);\n if (last && last.start + last.span === column) last.span += 1;\n else bands.push({ start: column, span: 1 });\n });\n return bands;\n};\n"],"mappings":"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","ignoreList":[]}
|
package/dist/ssr/intl/Format.js
CHANGED
|
@@ -52,13 +52,33 @@ const FormatPercent = props => {
|
|
|
52
52
|
fallback: own.fallback
|
|
53
53
|
})), false);
|
|
54
54
|
};
|
|
55
|
+
|
|
56
|
+
/** A currency amount with an explicit sign rule; the same digits as `text.pprintCurrency`. */
|
|
57
|
+
const signedCurrency = (value, currency, options) => {
|
|
58
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return options.fallback ?? FALLBACK;
|
|
59
|
+
const decimals = options.decimals === undefined ? undefined : Number.isFinite(options.decimals) ? Math.min(20, Math.max(0, Math.trunc(options.decimals))) : 0;
|
|
60
|
+
return new Intl.NumberFormat(options.locale, {
|
|
61
|
+
style: "currency",
|
|
62
|
+
currency,
|
|
63
|
+
signDisplay: options.signDisplay,
|
|
64
|
+
...(decimals === undefined ? {} : {
|
|
65
|
+
minimumFractionDigits: decimals,
|
|
66
|
+
maximumFractionDigits: decimals
|
|
67
|
+
})
|
|
68
|
+
}).format(Object.is(value, -0) ? 0 : value);
|
|
69
|
+
};
|
|
55
70
|
const FormatCurrency = props => {
|
|
56
|
-
const [own, rest] = splitProps(props, ["value", "currency", "locale", "decimals", "fallback"]);
|
|
71
|
+
const [own, rest] = splitProps(props, ["value", "currency", "locale", "decimals", "fallback", "signDisplay"]);
|
|
57
72
|
const locale = useLocale();
|
|
58
|
-
return _$ssrElement("span", rest, _$escape(text.pprintCurrency(own.value, own.currency, {
|
|
73
|
+
return _$ssrElement("span", rest, own.signDisplay === undefined ? _$escape(text.pprintCurrency(own.value, own.currency, {
|
|
59
74
|
locale: own.locale ?? locale(),
|
|
60
75
|
decimals: own.decimals,
|
|
61
76
|
fallback: own.fallback
|
|
77
|
+
})) : _$escape(signedCurrency(own.value, own.currency, {
|
|
78
|
+
locale: own.locale ?? locale(),
|
|
79
|
+
decimals: own.decimals,
|
|
80
|
+
fallback: own.fallback,
|
|
81
|
+
signDisplay: own.signDisplay
|
|
62
82
|
})), false);
|
|
63
83
|
};
|
|
64
84
|
const FormatBytes = props => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["intl/Format.tsx"],"sourcesContent":["import { type ByteMode, dates, text } from \"@k2b/stdlib\";\nimport { type JSX, Show, splitProps } from \"solid-js\";\nimport { useLocale } from \"./locale\";\n\nconst FALLBACK = \"—\";\n\ntype SpanProps = JSX.HTMLAttributes<HTMLSpanElement>;\n// Temporal components render `<time>` for valid values and a `<span>` fallback\n// otherwise, so their native attributes are typed against the shared element\n// base; `ref` is excluded because its value form is element-specific. The\n// `datetime` attribute is owned by the component itself.\ntype TimeElementProps = Omit<JSX.HTMLAttributes<HTMLElement>, \"ref\">;\n\ntype LocaleProp = {\n /** Explicit locale override; defaults to the inherited render locale. */\n locale?: string;\n};\n\ntype FallbackProp = {\n /** Text rendered for null or invalid input. Defaults to `\"—\"`. */\n fallback?: string;\n};\n\nexport type FormatNumberProps = SpanProps &\n LocaleProp &\n FallbackProp & {\n value: number | null | undefined;\n /** Use deterministic compact suffixes (`k`, `M`, `B`, `T`). */\n compact?: boolean;\n /** Fixed fraction digits. */\n decimals?: number;\n };\n\nexport type FormatPercentProps = SpanProps &\n LocaleProp &\n FallbackProp & {\n /** Ratio input: `0.12` renders as `12%`. */\n value: number | null | undefined;\n /** Fixed fraction digits. Defaults to 0. */\n decimals?: number;\n /** Clamp the ratio to 0..1 before formatting. */\n clamp?: boolean;\n };\n\nexport type FormatCurrencyProps = SpanProps &\n LocaleProp &\n FallbackProp & {\n value: number | null | undefined;\n /** ISO 4217 currency code, e.g. `\"EUR\"` or `\"USD\"`. */\n currency: string;\n /** Fixed fraction digits. Defaults to the currency's standard digits. */\n decimals?: number;\n };\n\nexport type FormatBytesProps = SpanProps &\n LocaleProp &\n FallbackProp & {\n value: number | null | undefined;\n /** `\"iec\"` (default, 1024-base) or `\"si\"` (1000-base). */\n mode?: ByteMode;\n };\n\nexport type FormatDateProps = TimeElementProps &\n LocaleProp &\n FallbackProp & {\n value: Date | string | null | undefined;\n /** IANA timezone. Defaults to `\"UTC\"` so server and browser text agree. */\n timeZone?: string;\n };\n\nexport type FormatTimeProps = FormatDateProps;\nexport type FormatDateTimeProps = FormatDateProps;\n\nexport type FormatRelativeTimeProps = TimeElementProps &\n LocaleProp &\n FallbackProp & {\n value: Date | string | null | undefined;\n /** Deterministic base timestamp; defaults to now. */\n base?: Date | string;\n /** IANA timezone used to select calendar-relative labels. Defaults to `\"UTC\"`. */\n timeZone?: string;\n };\n\nexport type FormatRelativeDateProps = TimeElementProps &\n LocaleProp &\n FallbackProp & {\n /** A Gregorian calendar date in strict YYYY-MM-DD format, never timezone-shifted. */\n value: string | null | undefined;\n /** Calendar date, Date, or ISO timestamp with an explicit offset. Defaults to now. */\n base?: Date | string;\n /** Zone used to read the base instant as a calendar day. Defaults to UTC. */\n timeZone?: string;\n };\n\nexport type FormatDurationProps = TimeElementProps &\n LocaleProp &\n FallbackProp & {\n from: Date | string | null | undefined;\n to: Date | string | null | undefined;\n };\n\nexport type FormatDurationMsProps = TimeElementProps &\n LocaleProp &\n FallbackProp & {\n /** Duration in milliseconds. */\n value: number | null | undefined;\n };\n\nconst toDate = (value: Date | string | null | undefined): Date | null => {\n if (value == null) return null;\n const date = typeof value === \"string\" ? new Date(value) : value;\n return Number.isNaN(date.getTime()) ? null : date;\n};\n\n/** ISO 8601 duration for the `<time datetime>` attribute, e.g. `\"PT2H30M\"`. */\nconst isoDuration = (ms: number): string => {\n const totalMilliseconds = Math.round(ms);\n if (totalMilliseconds <= 0) return \"PT0S\";\n const totalSeconds = Math.floor(totalMilliseconds / 1000);\n const milliseconds = totalMilliseconds % 1000;\n const days = Math.floor(totalSeconds / 86_400);\n const hours = Math.floor((totalSeconds % 86_400) / 3_600);\n const minutes = Math.floor((totalSeconds % 3_600) / 60);\n const seconds = totalSeconds % 60;\n const fractionalSeconds = milliseconds ? `${seconds}.${String(milliseconds).padStart(3, \"0\").replace(/0+$/, \"\")}S` : \"\";\n const time = `${hours ? `${hours}H` : \"\"}${minutes ? `${minutes}M` : \"\"}${fractionalSeconds || (seconds ? `${seconds}S` : \"\")}`;\n return `P${days ? `${days}D` : \"\"}${time ? `T${time}` : \"\"}`;\n};\n\nconst FormatNumber = (props: FormatNumberProps): JSX.Element => {\n const [own, rest] = splitProps(props, [\"value\", \"locale\", \"compact\", \"decimals\", \"fallback\"]);\n const locale = useLocale();\n return (\n <span {...rest}>\n {text.pprintNumber(own.value, {\n locale: own.locale ?? locale(),\n compact: own.compact,\n decimals: own.decimals,\n fallback: own.fallback,\n })}\n </span>\n );\n};\n\nconst FormatPercent = (props: FormatPercentProps): JSX.Element => {\n const [own, rest] = splitProps(props, [\"value\", \"locale\", \"decimals\", \"clamp\", \"fallback\"]);\n const locale = useLocale();\n return (\n <span {...rest}>\n {text.pprintPercent(own.value, {\n locale: own.locale ?? locale(),\n decimals: own.decimals,\n clamp: own.clamp,\n fallback: own.fallback,\n })}\n </span>\n );\n};\n\nconst FormatCurrency = (props: FormatCurrencyProps): JSX.Element => {\n const [own, rest] = splitProps(props, [\"value\", \"currency\", \"locale\", \"decimals\", \"fallback\"]);\n const locale = useLocale();\n return (\n <span {...rest}>\n {text.pprintCurrency(own.value, own.currency, {\n locale: own.locale ?? locale(),\n decimals: own.decimals,\n fallback: own.fallback,\n })}\n </span>\n );\n};\n\nconst FormatBytes = (props: FormatBytesProps): JSX.Element => {\n const [own, rest] = splitProps(props, [\"value\", \"locale\", \"mode\", \"fallback\"]);\n const locale = useLocale();\n return (\n <span {...rest}>\n {typeof own.value === \"number\" && Number.isFinite(own.value)\n ? text.pprintBytes(own.value, { locale: own.locale ?? locale(), mode: own.mode })\n : (own.fallback ?? FALLBACK)}\n </span>\n );\n};\n\ntype TemporalFormatter = (date: Date, context: { locale: string; timeZone: string }) => string;\n\nconst temporalComponent =\n (format: TemporalFormatter) =>\n (props: FormatDateProps): JSX.Element => {\n const [own, rest] = splitProps(props, [\"value\", \"locale\", \"timeZone\", \"fallback\"]);\n const locale = useLocale();\n return (\n <Show when={toDate(own.value)} fallback={<span {...rest}>{own.fallback ?? FALLBACK}</span>}>\n {(date) => (\n <time {...rest} datetime={date().toISOString()}>\n {format(date(), { locale: own.locale ?? locale(), timeZone: own.timeZone ?? \"UTC\" })}\n </time>\n )}\n </Show>\n );\n };\n\nconst FormatDate = temporalComponent((date, context) => dates.formatDate(date, context));\nconst FormatTime = temporalComponent((date, context) => dates.formatTime(date, context));\nconst FormatDateTime = temporalComponent((date, context) => dates.formatDateTime(date, context));\n\nconst FormatRelativeTime = (props: FormatRelativeTimeProps): JSX.Element => {\n const [own, rest] = splitProps(props, [\"value\", \"locale\", \"base\", \"timeZone\", \"fallback\"]);\n const locale = useLocale();\n return (\n <Show when={toDate(own.value)} fallback={<span {...rest}>{own.fallback ?? FALLBACK}</span>}>\n {(date) => (\n <time {...rest} datetime={date().toISOString()}>\n {dates.formatTimeSpan(date(), { locale: own.locale ?? locale(), base: own.base, timeZone: own.timeZone ?? \"UTC\" })}\n </time>\n )}\n </Show>\n );\n};\n\n// Encode calendar dates as UTC day ordinals, not elapsed local-midnight time:\n// a calendar day remains one day across 23-hour and 25-hour DST transitions.\nconst calendarDay = (value: string | null | undefined): number | null => {\n if (!value || !/^\\d{4}-\\d{2}-\\d{2}$/.test(value) || value.startsWith(\"0000\")) return null;\n const instant = new Date(`${value}T00:00:00Z`);\n if (!Number.isFinite(instant.getTime()) || instant.toISOString().slice(0, 10) !== value) return null;\n return instant.getTime() / 86_400_000;\n};\n\nconst FormatRelativeDate = (props: FormatRelativeDateProps): JSX.Element => {\n const [own, rest] = splitProps(props, [\"value\", \"locale\", \"base\", \"timeZone\", \"fallback\"]);\n const locale = useLocale();\n const relative = () => {\n const targetDay = calendarDay(own.value);\n const zone = own.timeZone ?? \"UTC\";\n if (targetDay === null || !dates.isValidTimeZone(zone)) return null;\n const base = own.base ?? new Date();\n let baseDay: number | null;\n if (typeof base === \"string\" && /^\\d{4}-\\d{2}-\\d{2}$/.test(base)) {\n baseDay = calendarDay(base);\n } else {\n // Offsetless timestamps depend on the host timezone and cannot hydrate reliably.\n if (typeof base === \"string\" && !/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d+)?)?(?:Z|[+-]\\d{2}:\\d{2})$/.test(base)) return null;\n if (typeof base === \"string\" && calendarDay(base.slice(0, 10)) === null) return null;\n const instant = toDate(base);\n if (!instant) return null;\n const parts = new Intl.DateTimeFormat(\"en-US\", {\n calendar: \"gregory\",\n numberingSystem: \"latn\",\n timeZone: zone,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n era: \"short\",\n }).formatToParts(instant);\n const part = (type: Intl.DateTimeFormatPartTypes) => parts.find((item) => item.type === type)?.value;\n if (part(\"era\") !== \"AD\") return null;\n baseDay = calendarDay(`${part(\"year\")?.padStart(4, \"0\")}-${part(\"month\")}-${part(\"day\")}`);\n }\n if (baseDay === null) return null;\n return { label: new Intl.RelativeTimeFormat(own.locale ?? locale(), { numeric: \"auto\" }).format(targetDay - baseDay, \"day\") };\n };\n return (\n <Show when={relative()} fallback={<span {...rest}>{own.fallback ?? FALLBACK}</span>}>\n {(value) => (\n <time {...rest} datetime={own.value ?? undefined}>\n {value().label}\n </time>\n )}\n </Show>\n );\n};\n\nconst FormatDuration = (props: FormatDurationProps): JSX.Element => {\n const [own, rest] = splitProps(props, [\"from\", \"to\", \"locale\", \"fallback\"]);\n const locale = useLocale();\n const range = () => {\n const from = toDate(own.from);\n const to = toDate(own.to);\n return from && to ? { from, to } : null;\n };\n return (\n <Show when={range()} fallback={<span {...rest}>{own.fallback ?? FALLBACK}</span>}>\n {(value) => (\n <time {...rest} datetime={isoDuration(Math.abs(value().to.getTime() - value().from.getTime()))}>\n {dates.formatDuration(value().from, value().to, { locale: own.locale ?? locale() })}\n </time>\n )}\n </Show>\n );\n};\n\nconst FormatDurationMs = (props: FormatDurationMsProps): JSX.Element => {\n const [own, rest] = splitProps(props, [\"value\", \"locale\", \"fallback\"]);\n const locale = useLocale();\n // Wrapped in an object because a valid duration of 0ms is falsy.\n const valid = (): { ms: number } | null => {\n const value = own.value;\n return typeof value === \"number\" && Number.isFinite(value) && value >= 0 ? { ms: value } : null;\n };\n return (\n <Show when={valid()} fallback={<span {...rest}>{own.fallback ?? FALLBACK}</span>}>\n {(duration) => (\n <time {...rest} datetime={isoDuration(duration().ms)}>\n {text.pprintDurationMs(duration().ms, { locale: own.locale ?? locale() })}\n </time>\n )}\n </Show>\n );\n};\n\n/**\n * Unstyled semantic formatter components backed by `@k2b/stdlib`.\n *\n * Numeric components render a plain `<span>`; date/time components render\n * `<time>` with a canonical `datetime` attribute. All components inherit the\n * render locale (see `LocaleProvider` / `useLocale`) and accept an explicit\n * `locale` override. Date, Time, and DateTime format in UTC unless an\n * explicit `timeZone` is given, so server and browser output never diverge\n * with the runtime timezone.\n */\nexport const Format = {\n Number: FormatNumber,\n Percent: FormatPercent,\n Currency: FormatCurrency,\n Bytes: FormatBytes,\n Date: FormatDate,\n Time: FormatTime,\n DateTime: FormatDateTime,\n RelativeTime: FormatRelativeTime,\n RelativeDate: FormatRelativeDate,\n Duration: FormatDuration,\n DurationMs: FormatDurationMs,\n} as const;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["intl/Format.tsx"],"sourcesContent":["import { type ByteMode, dates, text } from \"@k2b/stdlib\";\nimport { type JSX, Show, splitProps } from \"solid-js\";\nimport { useLocale } from \"./locale\";\n\nconst FALLBACK = \"—\";\n\ntype SpanProps = JSX.HTMLAttributes<HTMLSpanElement>;\n// Temporal components render `<time>` for valid values and a `<span>` fallback\n// otherwise, so their native attributes are typed against the shared element\n// base; `ref` is excluded because its value form is element-specific. The\n// `datetime` attribute is owned by the component itself.\ntype TimeElementProps = Omit<JSX.HTMLAttributes<HTMLElement>, \"ref\">;\n\ntype LocaleProp = {\n /** Explicit locale override; defaults to the inherited render locale. */\n locale?: string;\n};\n\ntype FallbackProp = {\n /** Text rendered for null or invalid input. Defaults to `\"—\"`. */\n fallback?: string;\n};\n\nexport type FormatNumberProps = SpanProps &\n LocaleProp &\n FallbackProp & {\n value: number | null | undefined;\n /** Use deterministic compact suffixes (`k`, `M`, `B`, `T`). */\n compact?: boolean;\n /** Fixed fraction digits. */\n decimals?: number;\n };\n\nexport type FormatPercentProps = SpanProps &\n LocaleProp &\n FallbackProp & {\n /** Ratio input: `0.12` renders as `12%`. */\n value: number | null | undefined;\n /** Fixed fraction digits. Defaults to 0. */\n decimals?: number;\n /** Clamp the ratio to 0..1 before formatting. */\n clamp?: boolean;\n };\n\nexport type FormatCurrencyProps = SpanProps &\n LocaleProp &\n FallbackProp & {\n value: number | null | undefined;\n /** ISO 4217 currency code, e.g. `\"EUR\"` or `\"USD\"`. */\n currency: string;\n /** Fixed fraction digits. Defaults to the currency's standard digits. */\n decimals?: number;\n /**\n * When the sign shows, as in `Intl.NumberFormat`: `\"exceptZero\"` writes `+1.234,50 €` and `-80,00 €` for a\n * balance change or net amount, `\"never\"` drops it. Defaults to `\"auto\"` (only negative amounts carry a sign).\n */\n signDisplay?: Intl.NumberFormatOptions[\"signDisplay\"];\n };\n\nexport type FormatBytesProps = SpanProps &\n LocaleProp &\n FallbackProp & {\n value: number | null | undefined;\n /** `\"iec\"` (default, 1024-base) or `\"si\"` (1000-base). */\n mode?: ByteMode;\n };\n\nexport type FormatDateProps = TimeElementProps &\n LocaleProp &\n FallbackProp & {\n value: Date | string | null | undefined;\n /** IANA timezone. Defaults to `\"UTC\"` so server and browser text agree. */\n timeZone?: string;\n };\n\nexport type FormatTimeProps = FormatDateProps;\nexport type FormatDateTimeProps = FormatDateProps;\n\nexport type FormatRelativeTimeProps = TimeElementProps &\n LocaleProp &\n FallbackProp & {\n value: Date | string | null | undefined;\n /** Deterministic base timestamp; defaults to now. */\n base?: Date | string;\n /** IANA timezone used to select calendar-relative labels. Defaults to `\"UTC\"`. */\n timeZone?: string;\n };\n\nexport type FormatRelativeDateProps = TimeElementProps &\n LocaleProp &\n FallbackProp & {\n /** A Gregorian calendar date in strict YYYY-MM-DD format, never timezone-shifted. */\n value: string | null | undefined;\n /** Calendar date, Date, or ISO timestamp with an explicit offset. Defaults to now. */\n base?: Date | string;\n /** Zone used to read the base instant as a calendar day. Defaults to UTC. */\n timeZone?: string;\n };\n\nexport type FormatDurationProps = TimeElementProps &\n LocaleProp &\n FallbackProp & {\n from: Date | string | null | undefined;\n to: Date | string | null | undefined;\n };\n\nexport type FormatDurationMsProps = TimeElementProps &\n LocaleProp &\n FallbackProp & {\n /** Duration in milliseconds. */\n value: number | null | undefined;\n };\n\nconst toDate = (value: Date | string | null | undefined): Date | null => {\n if (value == null) return null;\n const date = typeof value === \"string\" ? new Date(value) : value;\n return Number.isNaN(date.getTime()) ? null : date;\n};\n\n/** ISO 8601 duration for the `<time datetime>` attribute, e.g. `\"PT2H30M\"`. */\nconst isoDuration = (ms: number): string => {\n const totalMilliseconds = Math.round(ms);\n if (totalMilliseconds <= 0) return \"PT0S\";\n const totalSeconds = Math.floor(totalMilliseconds / 1000);\n const milliseconds = totalMilliseconds % 1000;\n const days = Math.floor(totalSeconds / 86_400);\n const hours = Math.floor((totalSeconds % 86_400) / 3_600);\n const minutes = Math.floor((totalSeconds % 3_600) / 60);\n const seconds = totalSeconds % 60;\n const fractionalSeconds = milliseconds ? `${seconds}.${String(milliseconds).padStart(3, \"0\").replace(/0+$/, \"\")}S` : \"\";\n const time = `${hours ? `${hours}H` : \"\"}${minutes ? `${minutes}M` : \"\"}${fractionalSeconds || (seconds ? `${seconds}S` : \"\")}`;\n return `P${days ? `${days}D` : \"\"}${time ? `T${time}` : \"\"}`;\n};\n\nconst FormatNumber = (props: FormatNumberProps): JSX.Element => {\n const [own, rest] = splitProps(props, [\"value\", \"locale\", \"compact\", \"decimals\", \"fallback\"]);\n const locale = useLocale();\n return (\n <span {...rest}>\n {text.pprintNumber(own.value, {\n locale: own.locale ?? locale(),\n compact: own.compact,\n decimals: own.decimals,\n fallback: own.fallback,\n })}\n </span>\n );\n};\n\nconst FormatPercent = (props: FormatPercentProps): JSX.Element => {\n const [own, rest] = splitProps(props, [\"value\", \"locale\", \"decimals\", \"clamp\", \"fallback\"]);\n const locale = useLocale();\n return (\n <span {...rest}>\n {text.pprintPercent(own.value, {\n locale: own.locale ?? locale(),\n decimals: own.decimals,\n clamp: own.clamp,\n fallback: own.fallback,\n })}\n </span>\n );\n};\n\n/** A currency amount with an explicit sign rule; the same digits as `text.pprintCurrency`. */\nconst signedCurrency = (\n value: number | null | undefined,\n currency: string,\n options: { locale: string; decimals?: number; fallback?: string; signDisplay: NonNullable<FormatCurrencyProps[\"signDisplay\"]> },\n): string => {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return options.fallback ?? FALLBACK;\n const decimals =\n options.decimals === undefined\n ? undefined\n : Number.isFinite(options.decimals)\n ? Math.min(20, Math.max(0, Math.trunc(options.decimals)))\n : 0;\n return new Intl.NumberFormat(options.locale, {\n style: \"currency\",\n currency,\n signDisplay: options.signDisplay,\n ...(decimals === undefined ? {} : { minimumFractionDigits: decimals, maximumFractionDigits: decimals }),\n }).format(Object.is(value, -0) ? 0 : value);\n};\n\nconst FormatCurrency = (props: FormatCurrencyProps): JSX.Element => {\n const [own, rest] = splitProps(props, [\"value\", \"currency\", \"locale\", \"decimals\", \"fallback\", \"signDisplay\"]);\n const locale = useLocale();\n return (\n <span {...rest}>\n {own.signDisplay === undefined\n ? text.pprintCurrency(own.value, own.currency, {\n locale: own.locale ?? locale(),\n decimals: own.decimals,\n fallback: own.fallback,\n })\n : signedCurrency(own.value, own.currency, {\n locale: own.locale ?? locale(),\n decimals: own.decimals,\n fallback: own.fallback,\n signDisplay: own.signDisplay,\n })}\n </span>\n );\n};\n\nconst FormatBytes = (props: FormatBytesProps): JSX.Element => {\n const [own, rest] = splitProps(props, [\"value\", \"locale\", \"mode\", \"fallback\"]);\n const locale = useLocale();\n return (\n <span {...rest}>\n {typeof own.value === \"number\" && Number.isFinite(own.value)\n ? text.pprintBytes(own.value, { locale: own.locale ?? locale(), mode: own.mode })\n : (own.fallback ?? FALLBACK)}\n </span>\n );\n};\n\ntype TemporalFormatter = (date: Date, context: { locale: string; timeZone: string }) => string;\n\nconst temporalComponent =\n (format: TemporalFormatter) =>\n (props: FormatDateProps): JSX.Element => {\n const [own, rest] = splitProps(props, [\"value\", \"locale\", \"timeZone\", \"fallback\"]);\n const locale = useLocale();\n return (\n <Show when={toDate(own.value)} fallback={<span {...rest}>{own.fallback ?? FALLBACK}</span>}>\n {(date) => (\n <time {...rest} datetime={date().toISOString()}>\n {format(date(), { locale: own.locale ?? locale(), timeZone: own.timeZone ?? \"UTC\" })}\n </time>\n )}\n </Show>\n );\n };\n\nconst FormatDate = temporalComponent((date, context) => dates.formatDate(date, context));\nconst FormatTime = temporalComponent((date, context) => dates.formatTime(date, context));\nconst FormatDateTime = temporalComponent((date, context) => dates.formatDateTime(date, context));\n\nconst FormatRelativeTime = (props: FormatRelativeTimeProps): JSX.Element => {\n const [own, rest] = splitProps(props, [\"value\", \"locale\", \"base\", \"timeZone\", \"fallback\"]);\n const locale = useLocale();\n return (\n <Show when={toDate(own.value)} fallback={<span {...rest}>{own.fallback ?? FALLBACK}</span>}>\n {(date) => (\n <time {...rest} datetime={date().toISOString()}>\n {dates.formatTimeSpan(date(), { locale: own.locale ?? locale(), base: own.base, timeZone: own.timeZone ?? \"UTC\" })}\n </time>\n )}\n </Show>\n );\n};\n\n// Encode calendar dates as UTC day ordinals, not elapsed local-midnight time:\n// a calendar day remains one day across 23-hour and 25-hour DST transitions.\nconst calendarDay = (value: string | null | undefined): number | null => {\n if (!value || !/^\\d{4}-\\d{2}-\\d{2}$/.test(value) || value.startsWith(\"0000\")) return null;\n const instant = new Date(`${value}T00:00:00Z`);\n if (!Number.isFinite(instant.getTime()) || instant.toISOString().slice(0, 10) !== value) return null;\n return instant.getTime() / 86_400_000;\n};\n\nconst FormatRelativeDate = (props: FormatRelativeDateProps): JSX.Element => {\n const [own, rest] = splitProps(props, [\"value\", \"locale\", \"base\", \"timeZone\", \"fallback\"]);\n const locale = useLocale();\n const relative = () => {\n const targetDay = calendarDay(own.value);\n const zone = own.timeZone ?? \"UTC\";\n if (targetDay === null || !dates.isValidTimeZone(zone)) return null;\n const base = own.base ?? new Date();\n let baseDay: number | null;\n if (typeof base === \"string\" && /^\\d{4}-\\d{2}-\\d{2}$/.test(base)) {\n baseDay = calendarDay(base);\n } else {\n // Offsetless timestamps depend on the host timezone and cannot hydrate reliably.\n if (typeof base === \"string\" && !/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d+)?)?(?:Z|[+-]\\d{2}:\\d{2})$/.test(base)) return null;\n if (typeof base === \"string\" && calendarDay(base.slice(0, 10)) === null) return null;\n const instant = toDate(base);\n if (!instant) return null;\n const parts = new Intl.DateTimeFormat(\"en-US\", {\n calendar: \"gregory\",\n numberingSystem: \"latn\",\n timeZone: zone,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n era: \"short\",\n }).formatToParts(instant);\n const part = (type: Intl.DateTimeFormatPartTypes) => parts.find((item) => item.type === type)?.value;\n if (part(\"era\") !== \"AD\") return null;\n baseDay = calendarDay(`${part(\"year\")?.padStart(4, \"0\")}-${part(\"month\")}-${part(\"day\")}`);\n }\n if (baseDay === null) return null;\n return { label: new Intl.RelativeTimeFormat(own.locale ?? locale(), { numeric: \"auto\" }).format(targetDay - baseDay, \"day\") };\n };\n return (\n <Show when={relative()} fallback={<span {...rest}>{own.fallback ?? FALLBACK}</span>}>\n {(value) => (\n <time {...rest} datetime={own.value ?? undefined}>\n {value().label}\n </time>\n )}\n </Show>\n );\n};\n\nconst FormatDuration = (props: FormatDurationProps): JSX.Element => {\n const [own, rest] = splitProps(props, [\"from\", \"to\", \"locale\", \"fallback\"]);\n const locale = useLocale();\n const range = () => {\n const from = toDate(own.from);\n const to = toDate(own.to);\n return from && to ? { from, to } : null;\n };\n return (\n <Show when={range()} fallback={<span {...rest}>{own.fallback ?? FALLBACK}</span>}>\n {(value) => (\n <time {...rest} datetime={isoDuration(Math.abs(value().to.getTime() - value().from.getTime()))}>\n {dates.formatDuration(value().from, value().to, { locale: own.locale ?? locale() })}\n </time>\n )}\n </Show>\n );\n};\n\nconst FormatDurationMs = (props: FormatDurationMsProps): JSX.Element => {\n const [own, rest] = splitProps(props, [\"value\", \"locale\", \"fallback\"]);\n const locale = useLocale();\n // Wrapped in an object because a valid duration of 0ms is falsy.\n const valid = (): { ms: number } | null => {\n const value = own.value;\n return typeof value === \"number\" && Number.isFinite(value) && value >= 0 ? { ms: value } : null;\n };\n return (\n <Show when={valid()} fallback={<span {...rest}>{own.fallback ?? FALLBACK}</span>}>\n {(duration) => (\n <time {...rest} datetime={isoDuration(duration().ms)}>\n {text.pprintDurationMs(duration().ms, { locale: own.locale ?? locale() })}\n </time>\n )}\n </Show>\n );\n};\n\n/**\n * Unstyled semantic formatter components backed by `@k2b/stdlib`.\n *\n * Numeric components render a plain `<span>`; date/time components render\n * `<time>` with a canonical `datetime` attribute. All components inherit the\n * render locale (see `LocaleProvider` / `useLocale`) and accept an explicit\n * `locale` override. Date, Time, and DateTime format in UTC unless an\n * explicit `timeZone` is given, so server and browser output never diverge\n * with the runtime timezone.\n */\nexport const Format = {\n Number: FormatNumber,\n Percent: FormatPercent,\n Currency: FormatCurrency,\n Bytes: FormatBytes,\n Date: FormatDate,\n Time: FormatTime,\n DateTime: FormatDateTime,\n RelativeTime: FormatRelativeTime,\n RelativeDate: FormatRelativeDate,\n Duration: FormatDuration,\n DurationMs: FormatDurationMs,\n} as const;\n"],"mappings":"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","ignoreList":[]}
|