seblify 0.2.1 → 0.4.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/README.md +145 -49
- package/dist/components/AppShell.svelte +1 -1
- package/dist/components/Banner.svelte +3 -3
- package/dist/components/Button.svelte +4 -4
- package/dist/components/action/button/button/Button.svelte +1041 -0
- package/dist/components/action/button/button/Button.svelte.d.ts +28 -0
- package/dist/components/action/button/button-group/ButtonGroup.svelte +146 -0
- package/dist/components/action/button/button-group/ButtonGroup.svelte.d.ts +14 -0
- package/dist/components/action/button/floating-action-button/FloatingActionButton.svelte +1102 -0
- package/dist/components/action/button/floating-action-button/FloatingActionButton.svelte.d.ts +26 -0
- package/dist/components/action/button/icon-button/IconButton.svelte +954 -0
- package/dist/components/action/button/icon-button/IconButton.svelte.d.ts +22 -0
- package/dist/components/action/button/timed-button/TimedButton.svelte +1143 -0
- package/dist/components/action/button/timed-button/TimedButton.svelte.d.ts +32 -0
- package/dist/components/action/button/toggle-button/ToggleButton.svelte +1109 -0
- package/dist/components/action/button/toggle-button/ToggleButton.svelte.d.ts +28 -0
- package/dist/components/action/button/toggle-button-group/ToggleButtonGroup.svelte +242 -0
- package/dist/components/action/button/toggle-button-group/ToggleButtonGroup.svelte.d.ts +19 -0
- package/dist/components/action/button/toggle-button-group/ToggleButtonGroup.test.svelte +36 -0
- package/dist/components/action/button/toggle-button-group/ToggleButtonGroup.test.svelte.d.ts +11 -0
- package/dist/components/action/button/toggle-button-group/context.d.ts +8 -0
- package/dist/components/action/button/toggle-button-group/context.js +8 -0
- package/dist/components/action/input/field/pin-input/PinInput.svelte +4 -4
- package/dist/components/action/input/select/checkbox/Checkbox.svelte +4704 -25
- package/dist/components/action/input/select/checkbox/Checkbox.svelte.d.ts +28 -0
- package/dist/components/action/input/select/checkbox/checkbox-relations.svelte.d.ts +46 -0
- package/dist/components/action/input/select/checkbox/checkbox-relations.svelte.js +202 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/bounce.d.ts +1 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/bounce.html +27 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/bounce.js +13 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/bump.d.ts +1 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/bump.html +12 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/bump.js +13 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/draw.d.ts +1 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/draw.html +12 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/draw.js +12 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/fade.d.ts +1 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/fade.html +12 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/fade.js +12 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/pop.d.ts +1 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/pop.html +12 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/pop.js +13 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/rise.d.ts +1 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/rise.html +27 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/rise.js +13 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/scale.d.ts +1 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/scale.html +27 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/scale.js +13 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/visual-state.d.ts +1 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/visual-state.html +12 -0
- package/dist/components/action/input/select/checkbox/tests/visual-fixtures/visual-state.js +278 -0
- package/dist/components/action/input/select/{theme-switch/ThemeSwitch.svelte → color-mode-switch/ColorModeSwitch.svelte} +8 -8
- package/dist/components/action/input/select/color-mode-switch/ColorModeSwitch.svelte.d.ts +10 -0
- package/dist/components/action/input/select/segment-control/SegmentControl.svelte +2 -2
- package/dist/components/action/input/select/slider/Slider.svelte +1 -1
- package/dist/components/action/input/select/switch/Switch.svelte +1004 -99
- package/dist/components/action/input/select/switch/Switch.svelte.d.ts +8 -3
- package/dist/components/display/annotation/badge/Badge.svelte +732 -63
- package/dist/components/display/annotation/badge/Badge.svelte.d.ts +1 -1
- package/dist/components/display/annotation/tag/Tag.svelte +670 -58
- package/dist/components/display/annotation/tag/Tag.svelte.d.ts +3 -1
- package/dist/components/display/data-display/metric/date-time/DateTimeValue.svelte +59 -0
- package/dist/components/display/data-display/metric/date-time/DateTimeValue.svelte.d.ts +13 -0
- package/dist/components/display/data-display/metric/date-time/DateValue.svelte +52 -0
- package/dist/components/display/data-display/metric/date-time/DateValue.svelte.d.ts +11 -0
- package/dist/components/display/data-display/metric/date-time/TimeValue.svelte +55 -0
- package/dist/components/display/data-display/metric/date-time/TimeValue.svelte.d.ts +12 -0
- package/dist/components/display/data-display/metric/duration/Duration.svelte +64 -0
- package/dist/components/display/data-display/metric/duration/Duration.svelte.d.ts +16 -0
- package/dist/components/display/data-display/metric/relative-time/RelativeTime.svelte +121 -0
- package/dist/components/display/data-display/metric/relative-time/RelativeTime.svelte.d.ts +21 -0
- package/dist/components/display/data-display/metric/timestamp-card/TimestampCard.svelte +121 -0
- package/dist/components/display/data-display/metric/timestamp-card/TimestampCard.svelte.d.ts +25 -0
- package/dist/components/display/data-display/visual/timeline/TimelineItem.svelte +660 -51
- package/dist/components/display/data-display/visual/timeline/context.d.ts +1 -1
- package/dist/components/display/feedback/loading/loading-dots/LoadingDots.svelte +657 -48
- package/dist/components/display/feedback/loading/loading-dots/LoadingDots.svelte.d.ts +1 -1
- package/dist/components/display/feedback/loading/spinner/Spinner.svelte +657 -48
- package/dist/components/display/feedback/loading/spinner/Spinner.svelte.d.ts +1 -1
- package/dist/components/display/motion/collapse/Collapse.svelte +115 -0
- package/dist/components/display/motion/collapse/Collapse.svelte.d.ts +17 -0
- package/dist/components/display/typography/accordion/Accordion.svelte +347 -0
- package/dist/components/display/typography/accordion/Accordion.svelte.d.ts +13 -0
- package/dist/components/display/typography/accordion/AccordionGroup.svelte +132 -0
- package/dist/components/display/typography/accordion/AccordionGroup.svelte.d.ts +11 -0
- package/dist/components/display/typography/accordion/context.d.ts +8 -0
- package/dist/components/display/typography/accordion/context.js +8 -0
- package/dist/components/display/typography/code-snippet/CodeSnippet.svelte +3 -3
- package/dist/components/display/typography/eyebrow/Eyebrow.svelte +2 -2
- package/dist/components/display/typography/highlight/Highlight.svelte +719 -59
- package/dist/components/display/typography/highlight/Highlight.svelte.d.ts +1 -1
- package/dist/components/framework/layout/container/app-shell/AppShell.svelte +16 -2
- package/dist/components/framework/navigation/context/breadcrumb/Breadcrumb.svelte +1 -1
- package/dist/components/framework/navigation/sidebar/sidebar/Sidebar.svelte +35 -10
- package/dist/components/framework/navigation/sidebar/sidenav/Sidenav.svelte +5 -5
- package/dist/components/framework/overlay/tooltip/Tooltip.svelte +1011 -0
- package/dist/components/framework/overlay/tooltip/Tooltip.svelte.d.ts +31 -0
- package/dist/components/framework/surface/paper/Paper.svelte +730 -87
- package/dist/components/framework/surface/paper/Paper.svelte.d.ts +1 -1
- package/dist/components/utility/format/date-time/formatDateTime.d.ts +23 -0
- package/dist/components/utility/format/date-time/formatDateTime.js +33 -0
- package/dist/components/utility/format/duration/formatDuration.d.ts +15 -0
- package/dist/components/utility/format/duration/formatDuration.js +218 -0
- package/dist/components/utility/format/relative-time/formatRelativeTime.d.ts +42 -0
- package/dist/components/utility/format/relative-time/formatRelativeTime.js +530 -0
- package/dist/design-system/inheritance/tokens.js +6 -0
- package/dist/design-system/reserved-props/allowed-options.d.ts +9 -4
- package/dist/design-system/theme/tokens.d.ts +72 -2
- package/dist/design-system/theme/tokens.js +173 -134
- package/dist/icons/generated/check-thick.svelte +16 -0
- package/dist/icons/generated/check-thick.svelte.d.ts +7 -0
- package/dist/icons/generated/check.svelte +16 -0
- package/dist/icons/generated/check.svelte.d.ts +7 -0
- package/dist/icons/generated/close-thick.svelte +16 -0
- package/dist/icons/generated/close-thick.svelte.d.ts +7 -0
- package/dist/icons/generated/close.svelte +16 -0
- package/dist/icons/generated/close.svelte.d.ts +7 -0
- package/dist/icons/generated/index.d.ts +4 -0
- package/dist/icons/generated/index.js +4 -0
- package/dist/icons/generated/manifest.js +28 -0
- package/dist/index.d.ts +22 -2
- package/dist/index.js +22 -2
- package/dist/styles/tone-context.css +656 -46
- package/dist/theme.css +1 -161
- package/dist/themes/canopy.css +373 -0
- package/dist/themes/cobalt.css +373 -0
- package/dist/themes/iris.css +373 -0
- package/dist/themes/lumen.css +373 -0
- package/dist/themes/mono.css +373 -0
- package/dist/themes/moss.css +373 -0
- package/dist/themes/noir.css +373 -0
- package/dist/themes/plain.css +373 -0
- package/dist/themes/pulse.css +373 -0
- package/dist/themes/signal.css +373 -0
- package/dist/themes/slate.css +373 -0
- package/dist/themes/solar.css +373 -0
- package/dist/themes/sorbet.css +373 -0
- package/dist/themes/studio.css +369 -0
- package/dist/themes/vesper.css +373 -0
- package/package.json +32 -4
- package/dist/components/action/input/select/theme-switch/ThemeSwitch.svelte.d.ts +0 -10
|
@@ -2,7 +2,7 @@ import type { Snippet } from 'svelte';
|
|
|
2
2
|
type PaperElement = keyof HTMLElementTagNameMap;
|
|
3
3
|
type PaperPadding = 'none' | 'sm' | 'md' | 'lg';
|
|
4
4
|
type PaperRadius = 'sm' | 'md' | 'lg';
|
|
5
|
-
type PaperTone = 'neutral' | 'primary' | '
|
|
5
|
+
type PaperTone = 'neutral' | 'strong' | 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info';
|
|
6
6
|
type PaperVariant = 'solid' | 'soft' | 'tint' | 'plain';
|
|
7
7
|
declare const Paper: import("svelte").Component<{
|
|
8
8
|
as?: PaperElement | undefined;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type DateTimeInput = Date | number | string;
|
|
2
|
+
export type DateTimeDateStyle = 'short' | 'medium' | 'long' | 'full';
|
|
3
|
+
export type DateTimeTimeStyle = 'short' | 'medium' | 'long' | 'full';
|
|
4
|
+
export type DateTimeLocaleOptions = {
|
|
5
|
+
locale?: Intl.LocalesArgument;
|
|
6
|
+
timeZone?: string;
|
|
7
|
+
};
|
|
8
|
+
export type FormatDateOptions = DateTimeLocaleOptions & {
|
|
9
|
+
dateStyle?: DateTimeDateStyle;
|
|
10
|
+
};
|
|
11
|
+
export type FormatTimeOptions = DateTimeLocaleOptions & {
|
|
12
|
+
hour12?: boolean;
|
|
13
|
+
timeStyle?: DateTimeTimeStyle;
|
|
14
|
+
};
|
|
15
|
+
export type FormatDateTimeOptions = DateTimeLocaleOptions & {
|
|
16
|
+
dateStyle?: DateTimeDateStyle;
|
|
17
|
+
hour12?: boolean;
|
|
18
|
+
timeStyle?: DateTimeTimeStyle;
|
|
19
|
+
};
|
|
20
|
+
export declare function formatDate(timestamp: DateTimeInput, options?: FormatDateOptions): string;
|
|
21
|
+
export declare function formatTime(timestamp: DateTimeInput, options?: FormatTimeOptions): string;
|
|
22
|
+
export declare function formatDateTime(timestamp: DateTimeInput, options?: FormatDateTimeOptions): string;
|
|
23
|
+
export declare function dateTimeIsoString(timestamp: DateTimeInput): string;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export function formatDate(timestamp, options = {}) {
|
|
2
|
+
return new Intl.DateTimeFormat(options.locale, {
|
|
3
|
+
dateStyle: options.dateStyle ?? 'medium',
|
|
4
|
+
timeZone: options.timeZone,
|
|
5
|
+
}).format(toDate(timestamp));
|
|
6
|
+
}
|
|
7
|
+
export function formatTime(timestamp, options = {}) {
|
|
8
|
+
return new Intl.DateTimeFormat(options.locale, {
|
|
9
|
+
hour12: options.hour12,
|
|
10
|
+
timeStyle: options.timeStyle ?? 'short',
|
|
11
|
+
timeZone: options.timeZone,
|
|
12
|
+
}).format(toDate(timestamp));
|
|
13
|
+
}
|
|
14
|
+
export function formatDateTime(timestamp, options = {}) {
|
|
15
|
+
return new Intl.DateTimeFormat(options.locale, {
|
|
16
|
+
dateStyle: options.dateStyle ?? 'medium',
|
|
17
|
+
hour12: options.hour12,
|
|
18
|
+
timeStyle: options.timeStyle ?? 'short',
|
|
19
|
+
timeZone: options.timeZone,
|
|
20
|
+
}).format(toDate(timestamp));
|
|
21
|
+
}
|
|
22
|
+
export function dateTimeIsoString(timestamp) {
|
|
23
|
+
return toDate(timestamp).toISOString();
|
|
24
|
+
}
|
|
25
|
+
function toDate(timestamp) {
|
|
26
|
+
const date = timestamp instanceof Date
|
|
27
|
+
? new Date(timestamp.getTime())
|
|
28
|
+
: new Date(timestamp);
|
|
29
|
+
if (Number.isNaN(date.getTime())) {
|
|
30
|
+
throw new RangeError('Invalid date time timestamp.');
|
|
31
|
+
}
|
|
32
|
+
return date;
|
|
33
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type DurationFormat = 'unit' | 'clock';
|
|
2
|
+
export type DurationRounding = 'floor' | 'round' | 'ceil';
|
|
3
|
+
export type DurationUnit = 'year' | 'month' | 'week' | 'millisecond' | 'second' | 'minute' | 'hour' | 'day';
|
|
4
|
+
export type DurationStyle = 'long' | 'short' | 'narrow';
|
|
5
|
+
export type FormatDurationOptions = {
|
|
6
|
+
format?: DurationFormat;
|
|
7
|
+
largestUnit?: DurationUnit;
|
|
8
|
+
locale?: Intl.LocalesArgument;
|
|
9
|
+
minUnits?: number;
|
|
10
|
+
maxUnits?: number;
|
|
11
|
+
rounding?: DurationRounding;
|
|
12
|
+
smallestUnit?: DurationUnit;
|
|
13
|
+
style?: DurationStyle;
|
|
14
|
+
};
|
|
15
|
+
export declare function formatDuration(value: number, options?: FormatDurationOptions): string;
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
const MILLISECOND = 1;
|
|
2
|
+
const SECOND = 1000;
|
|
3
|
+
const MINUTE = 60 * SECOND;
|
|
4
|
+
const HOUR = 60 * MINUTE;
|
|
5
|
+
const DAY = 24 * HOUR;
|
|
6
|
+
const WEEK = 7 * DAY;
|
|
7
|
+
const YEAR = 365.25 * DAY;
|
|
8
|
+
const MONTH = YEAR / 12;
|
|
9
|
+
const UNITS = [
|
|
10
|
+
{ unit: 'year', milliseconds: YEAR },
|
|
11
|
+
{ unit: 'month', milliseconds: MONTH },
|
|
12
|
+
{ unit: 'week', milliseconds: WEEK },
|
|
13
|
+
{ unit: 'day', milliseconds: DAY },
|
|
14
|
+
{ unit: 'hour', milliseconds: HOUR },
|
|
15
|
+
{ unit: 'minute', milliseconds: MINUTE },
|
|
16
|
+
{ unit: 'second', milliseconds: SECOND },
|
|
17
|
+
{ unit: 'millisecond', milliseconds: MILLISECOND },
|
|
18
|
+
];
|
|
19
|
+
export function formatDuration(value, options = {}) {
|
|
20
|
+
const milliseconds = toDurationMilliseconds(value);
|
|
21
|
+
if (options.format === 'clock') {
|
|
22
|
+
return formatClockDuration(milliseconds, options);
|
|
23
|
+
}
|
|
24
|
+
return formatUnitDuration(milliseconds, options);
|
|
25
|
+
}
|
|
26
|
+
function toDurationMilliseconds(value) {
|
|
27
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
28
|
+
throw new RangeError('Invalid duration value.');
|
|
29
|
+
}
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
function formatUnitDuration(milliseconds, options) {
|
|
33
|
+
const largestUnit = options.largestUnit ?? 'day';
|
|
34
|
+
const smallestUnit = options.smallestUnit ?? 'second';
|
|
35
|
+
const maxUnits = getMaxUnits(options.maxUnits);
|
|
36
|
+
const minUnits = getMinUnits(options.minUnits, maxUnits);
|
|
37
|
+
const unitConfigs = getUnitConfigs(largestUnit, smallestUnit);
|
|
38
|
+
const parts = maxUnits === 1
|
|
39
|
+
? selectSingleUnitPart(milliseconds, unitConfigs, options)
|
|
40
|
+
: selectUnitParts(milliseconds, unitConfigs, maxUnits, minUnits, options);
|
|
41
|
+
const formattedParts = parts.map((part) => formatUnit(part.amount, part.unit, options));
|
|
42
|
+
return new Intl.ListFormat(options.locale, {
|
|
43
|
+
style: options.style ?? 'long',
|
|
44
|
+
type: 'unit',
|
|
45
|
+
}).format(formattedParts);
|
|
46
|
+
}
|
|
47
|
+
function getMaxUnits(maxUnits) {
|
|
48
|
+
if (maxUnits === undefined) {
|
|
49
|
+
return 2;
|
|
50
|
+
}
|
|
51
|
+
if (!Number.isFinite(maxUnits) || maxUnits < 1) {
|
|
52
|
+
throw new RangeError('Invalid duration maxUnits.');
|
|
53
|
+
}
|
|
54
|
+
return Math.floor(maxUnits);
|
|
55
|
+
}
|
|
56
|
+
function getMinUnits(minUnits, maxUnits) {
|
|
57
|
+
if (minUnits === undefined) {
|
|
58
|
+
return 1;
|
|
59
|
+
}
|
|
60
|
+
if (!Number.isFinite(minUnits) || minUnits < 1 || minUnits > maxUnits) {
|
|
61
|
+
throw new RangeError('Invalid duration minUnits.');
|
|
62
|
+
}
|
|
63
|
+
return Math.floor(minUnits);
|
|
64
|
+
}
|
|
65
|
+
function getUnitConfigs(largestUnit, smallestUnit) {
|
|
66
|
+
const startIndex = UNITS.findIndex((config) => config.unit === largestUnit);
|
|
67
|
+
const endIndex = UNITS.findIndex((config) => config.unit === smallestUnit);
|
|
68
|
+
if (startIndex === -1) {
|
|
69
|
+
throw new RangeError('Invalid duration largestUnit.');
|
|
70
|
+
}
|
|
71
|
+
if (endIndex === -1) {
|
|
72
|
+
throw new RangeError('Invalid duration smallestUnit.');
|
|
73
|
+
}
|
|
74
|
+
if (startIndex > endIndex) {
|
|
75
|
+
throw new RangeError('Duration largestUnit must be larger than smallestUnit.');
|
|
76
|
+
}
|
|
77
|
+
return [...UNITS.slice(startIndex, endIndex + 1)];
|
|
78
|
+
}
|
|
79
|
+
function selectSingleUnitPart(milliseconds, unitConfigs, options) {
|
|
80
|
+
const smallestUnit = unitConfigs[unitConfigs.length - 1];
|
|
81
|
+
const selectedUnit = unitConfigs.find((config) => milliseconds >= config.milliseconds) ??
|
|
82
|
+
smallestUnit;
|
|
83
|
+
const rounding = options.rounding ?? 'round';
|
|
84
|
+
const amount = milliseconds < smallestUnit.milliseconds
|
|
85
|
+
? 0
|
|
86
|
+
: roundToTenths(milliseconds / selectedUnit.milliseconds, rounding);
|
|
87
|
+
return [
|
|
88
|
+
{
|
|
89
|
+
amount,
|
|
90
|
+
unit: selectedUnit.unit,
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
function selectUnitParts(milliseconds, unitConfigs, maxUnits, minUnits, options) {
|
|
95
|
+
const smallestUnit = unitConfigs[unitConfigs.length - 1];
|
|
96
|
+
let remainingMilliseconds = roundToUnit(milliseconds, smallestUnit.milliseconds, options.rounding ?? 'floor');
|
|
97
|
+
const decomposedParts = [];
|
|
98
|
+
for (const config of unitConfigs) {
|
|
99
|
+
const amount = Math.floor(remainingMilliseconds / config.milliseconds);
|
|
100
|
+
decomposedParts.push({
|
|
101
|
+
amount,
|
|
102
|
+
unit: config.unit,
|
|
103
|
+
});
|
|
104
|
+
remainingMilliseconds -= amount * config.milliseconds;
|
|
105
|
+
}
|
|
106
|
+
const firstNonZeroIndex = decomposedParts.findIndex((part) => part.amount !== 0);
|
|
107
|
+
if (firstNonZeroIndex === -1) {
|
|
108
|
+
return [
|
|
109
|
+
{
|
|
110
|
+
amount: 0,
|
|
111
|
+
unit: smallestUnit.unit,
|
|
112
|
+
},
|
|
113
|
+
];
|
|
114
|
+
}
|
|
115
|
+
if (minUnits > 1) {
|
|
116
|
+
const startIndex = Math.max(0, Math.min(firstNonZeroIndex, decomposedParts.length - minUnits));
|
|
117
|
+
return decomposedParts.slice(startIndex, startIndex + maxUnits);
|
|
118
|
+
}
|
|
119
|
+
const parts = decomposedParts.filter((part) => part.amount !== 0);
|
|
120
|
+
return parts.slice(0, maxUnits);
|
|
121
|
+
}
|
|
122
|
+
function formatUnit(amount, unit, options) {
|
|
123
|
+
return new Intl.NumberFormat(options.locale, {
|
|
124
|
+
maximumFractionDigits: 1,
|
|
125
|
+
style: 'unit',
|
|
126
|
+
unit,
|
|
127
|
+
unitDisplay: options.style ?? 'long',
|
|
128
|
+
}).format(amount);
|
|
129
|
+
}
|
|
130
|
+
function formatClockDuration(milliseconds, options) {
|
|
131
|
+
const largestUnit = options.largestUnit ?? 'day';
|
|
132
|
+
const smallestUnit = options.smallestUnit ?? 'second';
|
|
133
|
+
const unitConfigs = getUnitConfigs(largestUnit, smallestUnit);
|
|
134
|
+
const minUnits = getClockMinUnits(options.minUnits);
|
|
135
|
+
const smallestConfig = unitConfigs[unitConfigs.length - 1];
|
|
136
|
+
const visibleMilliseconds = roundToUnit(milliseconds, smallestConfig.milliseconds, options.rounding ?? 'floor');
|
|
137
|
+
const showMilliseconds = options.smallestUnit === 'millisecond';
|
|
138
|
+
const parts = decomposeDuration(visibleMilliseconds, unitConfigs);
|
|
139
|
+
const partByUnit = new Map(parts.map((part) => [part.unit, part.amount]));
|
|
140
|
+
const years = partByUnit.get('year') ?? 0;
|
|
141
|
+
const months = partByUnit.get('month') ?? 0;
|
|
142
|
+
const weeks = partByUnit.get('week') ?? 0;
|
|
143
|
+
const days = partByUnit.get('day') ?? 0;
|
|
144
|
+
const hours = partByUnit.get('hour') ?? 0;
|
|
145
|
+
const minutes = partByUnit.get('minute') ?? 0;
|
|
146
|
+
const seconds = partByUnit.get('second') ?? 0;
|
|
147
|
+
const prefixes = [
|
|
148
|
+
formatClockPrefix(years, 'y', includesUnit(unitConfigs, 'year'), minUnits >= 6),
|
|
149
|
+
formatClockPrefix(months, 'mo', includesUnit(unitConfigs, 'month'), minUnits >= 5),
|
|
150
|
+
formatClockPrefix(weeks, 'w', includesUnit(unitConfigs, 'week'), minUnits >= 5),
|
|
151
|
+
formatClockPrefix(days, 'd', includesUnit(unitConfigs, 'day'), minUnits >= 4),
|
|
152
|
+
].filter((part) => part !== undefined);
|
|
153
|
+
const showHours = hours > 0 ||
|
|
154
|
+
prefixes.length > 0 ||
|
|
155
|
+
largestUnit === 'hour' ||
|
|
156
|
+
minUnits >= 3;
|
|
157
|
+
const formattedHours = prefixes.length > 0 || minUnits >= 3
|
|
158
|
+
? pad(hours)
|
|
159
|
+
: hours.toString();
|
|
160
|
+
const clock = showHours
|
|
161
|
+
? `${formattedHours}:${pad(minutes)}:${pad(seconds)}`
|
|
162
|
+
: `${pad(minutes)}:${pad(seconds)}`;
|
|
163
|
+
const clockWithPrefixes = prefixes.length > 0 ? `${prefixes.join(' ')} ${clock}` : clock;
|
|
164
|
+
if (!showMilliseconds) {
|
|
165
|
+
return clockWithPrefixes;
|
|
166
|
+
}
|
|
167
|
+
return `${clockWithPrefixes}.${padMilliseconds(partByUnit.get('millisecond') ?? 0)}`;
|
|
168
|
+
}
|
|
169
|
+
function decomposeDuration(milliseconds, unitConfigs) {
|
|
170
|
+
let remainingMilliseconds = milliseconds;
|
|
171
|
+
return unitConfigs.map((config) => {
|
|
172
|
+
const amount = Math.floor(remainingMilliseconds / config.milliseconds);
|
|
173
|
+
remainingMilliseconds -= amount * config.milliseconds;
|
|
174
|
+
return {
|
|
175
|
+
amount,
|
|
176
|
+
unit: config.unit,
|
|
177
|
+
};
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
function includesUnit(unitConfigs, unit) {
|
|
181
|
+
return unitConfigs.some((config) => config.unit === unit);
|
|
182
|
+
}
|
|
183
|
+
function getClockMinUnits(minUnits) {
|
|
184
|
+
if (minUnits === undefined) {
|
|
185
|
+
return 2;
|
|
186
|
+
}
|
|
187
|
+
if (!Number.isFinite(minUnits) || minUnits < 1) {
|
|
188
|
+
throw new RangeError('Invalid duration minUnits.');
|
|
189
|
+
}
|
|
190
|
+
return Math.floor(minUnits);
|
|
191
|
+
}
|
|
192
|
+
function formatClockPrefix(amount, suffix, unitIsIncluded, force) {
|
|
193
|
+
if (!unitIsIncluded || (amount === 0 && !force)) {
|
|
194
|
+
return undefined;
|
|
195
|
+
}
|
|
196
|
+
return `${amount}${suffix}`;
|
|
197
|
+
}
|
|
198
|
+
function roundToTenths(value, rounding) {
|
|
199
|
+
return roundValue(value * 10, rounding) / 10;
|
|
200
|
+
}
|
|
201
|
+
function roundToUnit(milliseconds, unitMilliseconds, rounding) {
|
|
202
|
+
return roundValue(milliseconds / unitMilliseconds, rounding) * unitMilliseconds;
|
|
203
|
+
}
|
|
204
|
+
function roundValue(value, rounding) {
|
|
205
|
+
if (rounding === 'floor') {
|
|
206
|
+
return Math.floor(value);
|
|
207
|
+
}
|
|
208
|
+
if (rounding === 'ceil') {
|
|
209
|
+
return Math.ceil(value);
|
|
210
|
+
}
|
|
211
|
+
return Math.round(value);
|
|
212
|
+
}
|
|
213
|
+
function pad(value) {
|
|
214
|
+
return value.toString().padStart(2, '0');
|
|
215
|
+
}
|
|
216
|
+
function padMilliseconds(value) {
|
|
217
|
+
return value.toString().padStart(3, '0');
|
|
218
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { DurationRounding } from '../duration/formatDuration';
|
|
2
|
+
export type RelativeTimeInput = Date | number | string;
|
|
3
|
+
export type RelativeTimeLabel = {
|
|
4
|
+
label: string;
|
|
5
|
+
threshold?: number;
|
|
6
|
+
} | {
|
|
7
|
+
label?: string;
|
|
8
|
+
threshold: number;
|
|
9
|
+
};
|
|
10
|
+
export type RelativeTimePresentation = 'relative' | 'unit';
|
|
11
|
+
export type RelativeTimeMode = 'time' | 'calendar';
|
|
12
|
+
export type RelativeTimeRounding = DurationRounding;
|
|
13
|
+
export type RelativeTimeStyle = 'long' | 'short' | 'narrow';
|
|
14
|
+
export type RelativeTimeUnitSteps = 'detailed' | 'compact' | 'simple';
|
|
15
|
+
export type RelativeTimeUnit = 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year';
|
|
16
|
+
export type RelativeTimeDirection = 'past' | 'present' | 'future';
|
|
17
|
+
export type RelativeTimeState = {
|
|
18
|
+
amount: number;
|
|
19
|
+
direction: RelativeTimeDirection;
|
|
20
|
+
milliseconds: number;
|
|
21
|
+
label?: string;
|
|
22
|
+
signedAmount: number;
|
|
23
|
+
unit: RelativeTimeUnit;
|
|
24
|
+
updateInMilliseconds: number;
|
|
25
|
+
};
|
|
26
|
+
export type FormatRelativeTimeOptions = {
|
|
27
|
+
from?: RelativeTimeInput;
|
|
28
|
+
labels?: readonly RelativeTimeLabel[];
|
|
29
|
+
largestUnit?: RelativeTimeUnit;
|
|
30
|
+
locale?: Intl.LocalesArgument;
|
|
31
|
+
maxUnits?: number;
|
|
32
|
+
minUnits?: number;
|
|
33
|
+
mode?: RelativeTimeMode;
|
|
34
|
+
presentation?: RelativeTimePresentation;
|
|
35
|
+
rounding?: RelativeTimeRounding;
|
|
36
|
+
smallestUnit?: RelativeTimeUnit;
|
|
37
|
+
style?: RelativeTimeStyle;
|
|
38
|
+
unitSteps?: RelativeTimeUnitSteps;
|
|
39
|
+
};
|
|
40
|
+
export declare function formatRelativeTime(value: RelativeTimeInput, options?: FormatRelativeTimeOptions): string;
|
|
41
|
+
export declare function getRelativeTimeState(value: RelativeTimeInput, options?: FormatRelativeTimeOptions): RelativeTimeState;
|
|
42
|
+
export declare function relativeTimeDateTime(value: RelativeTimeInput): string;
|