@odx/foundation 1.0.0-rc.3 → 1.0.0-rc.4
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/CHANGELOG.md +6 -0
- package/dist/lib/breakpoints.d.ts +49 -49
- package/dist/lib/breakpoints.js +141 -122
- package/dist/lib/format.d.ts +51 -50
- package/dist/lib/format.js +52 -50
- package/dist/lib/localization.d.ts +14 -11
- package/dist/lib/localization.js +15 -15
- package/dist/lib/models.d.ts +5 -39
- package/dist/lib/signals.d.ts +16 -13
- package/dist/lib/signals.js +37 -32
- package/dist/lib/theming.d.ts +16 -13
- package/dist/lib/theming.js +21 -24
- package/dist/lib/utils/shared-media-observer.js +33 -35
- package/dist/main.d.ts +7 -7
- package/dist/main.js +6 -5
- package/dist/styles.css +908 -1
- package/package.json +9 -15
- package/dist/lib/models.js +0 -34
- package/dist/lib/utils/breakpoint.d.ts +0 -38
- package/dist/lib/utils/breakpoint.js +0 -103
- package/dist/lib/utils/shared-media-observer.d.ts +0 -4
- package/dist/oss-licenses.json +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
import { Signal } from
|
|
1
|
+
import { Signal } from "./signals.js";
|
|
2
|
+
|
|
3
|
+
//#region src/lib/breakpoints.d.ts
|
|
2
4
|
declare global {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
5
|
+
namespace ODX.Breakpoints {
|
|
6
|
+
interface Config {
|
|
7
|
+
sm: true;
|
|
8
|
+
md: true;
|
|
9
|
+
lg: true;
|
|
10
|
+
xl: true;
|
|
11
|
+
xxl: true;
|
|
11
12
|
}
|
|
13
|
+
}
|
|
12
14
|
}
|
|
13
|
-
type FilteredKeys<T extends object> = {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
max: number;
|
|
21
|
-
customQuery?: string;
|
|
15
|
+
type FilteredKeys<T extends object> = { [K in keyof T as T[K] extends true ? K : never]: T[K] };
|
|
16
|
+
type BreakpointOperator = '<' | '<=' | '>=' | '>';
|
|
17
|
+
interface BreakpointConfig {
|
|
18
|
+
name: keyof FilteredKeys<ODX.Breakpoints.Config>;
|
|
19
|
+
min: number;
|
|
20
|
+
max: number;
|
|
21
|
+
customQuery?: string;
|
|
22
22
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
interface Breakpoint extends BreakpointConfig {
|
|
24
|
+
id: BreakpointConfig['name'] | `${BreakpointOperator}${BreakpointConfig['name']}`;
|
|
25
|
+
query: string;
|
|
26
|
+
operator?: BreakpointOperator;
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
declare const registeredBreakpoints: ReadonlyMap<Breakpoint['id'], Breakpoint>;
|
|
29
|
+
declare const breakpointAttribute = "odx-breakpoint";
|
|
30
|
+
declare const defaultBreakpoints: [{
|
|
31
|
+
readonly name: "sm";
|
|
32
|
+
readonly min: 0;
|
|
33
|
+
readonly max: 479.98;
|
|
34
34
|
}, {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
readonly name: "md";
|
|
36
|
+
readonly min: 480;
|
|
37
|
+
readonly max: 768.98;
|
|
38
38
|
}, {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
readonly name: "lg";
|
|
40
|
+
readonly min: 769;
|
|
41
|
+
readonly max: 990.98;
|
|
42
42
|
}, {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
readonly name: "xl";
|
|
44
|
+
readonly min: 991;
|
|
45
|
+
readonly max: 1280.98;
|
|
46
46
|
}, {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
readonly name: "xxl";
|
|
48
|
+
readonly min: 1352;
|
|
49
|
+
readonly max: number;
|
|
50
50
|
}];
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
declare function buildBreakpoint(breakpoint: BreakpointConfig, operator?: BreakpointOperator): Breakpoint;
|
|
52
|
+
declare function expandBreakpoints(...breakpoints: BreakpointConfig[]): Breakpoint[];
|
|
53
|
+
declare function observeBreakpoint(id: Breakpoint['id'], initialValue?: boolean): Signal<Breakpoint & {
|
|
54
|
+
matches: boolean;
|
|
55
55
|
}>;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
declare function setupBreakpoints(breakpointsConfig?: BreakpointConfig[]): () => void;
|
|
57
|
+
declare function createBreakpointUpdater(breakpoints: Breakpoint[], update?: (target: HTMLElement, change: Breakpoint & {
|
|
58
|
+
matches: boolean;
|
|
59
59
|
}) => void): () => void;
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
//#endregion
|
|
61
|
+
export { Breakpoint, BreakpointConfig, BreakpointOperator, breakpointAttribute, buildBreakpoint, createBreakpointUpdater, defaultBreakpoints, expandBreakpoints, observeBreakpoint, registeredBreakpoints, setupBreakpoints };
|
package/dist/lib/breakpoints.js
CHANGED
|
@@ -1,139 +1,158 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { observeMedia } from
|
|
3
|
-
|
|
4
|
-
const operators = [
|
|
1
|
+
import { effect, signal } from "./signals.js";
|
|
2
|
+
import { observeMedia } from "./utils/shared-media-observer.js";
|
|
3
|
+
//#region src/lib/breakpoints.ts
|
|
4
|
+
const operators = [
|
|
5
|
+
"<",
|
|
6
|
+
"<=",
|
|
7
|
+
">=",
|
|
8
|
+
">"
|
|
9
|
+
];
|
|
5
10
|
const registeredBreakpoints = /* @__PURE__ */ new Map();
|
|
6
11
|
const breakpointAttribute = "odx-breakpoint";
|
|
7
12
|
const defaultBreakpoints = [
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
{
|
|
14
|
+
name: "sm",
|
|
15
|
+
min: 0,
|
|
16
|
+
max: 479.98
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: "md",
|
|
20
|
+
min: 480,
|
|
21
|
+
max: 768.98
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: "lg",
|
|
25
|
+
min: 769,
|
|
26
|
+
max: 990.98
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: "xl",
|
|
30
|
+
min: 991,
|
|
31
|
+
max: 1280.98
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: "xxl",
|
|
35
|
+
min: 1352,
|
|
36
|
+
max: Number.MAX_SAFE_INTEGER
|
|
37
|
+
}
|
|
13
38
|
];
|
|
14
39
|
function buildBreakpoint(breakpoint, operator) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
40
|
+
const id = operator ? `${operator}${breakpoint.name}` : breakpoint.name;
|
|
41
|
+
let query = `(min-width: ${breakpoint.min}px) and (max-width: ${breakpoint.max}px)`;
|
|
42
|
+
switch (operator) {
|
|
43
|
+
case "<":
|
|
44
|
+
query = `(max-width: ${breakpoint.min - .02}px)`;
|
|
45
|
+
break;
|
|
46
|
+
case "<=":
|
|
47
|
+
query = `(max-width: ${breakpoint.max}px)`;
|
|
48
|
+
break;
|
|
49
|
+
case ">=":
|
|
50
|
+
query = `(min-width: ${breakpoint.min}px)`;
|
|
51
|
+
break;
|
|
52
|
+
case ">":
|
|
53
|
+
query = `(min-width: ${breakpoint.max + .02}px)`;
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
...breakpoint,
|
|
58
|
+
id,
|
|
59
|
+
operator,
|
|
60
|
+
query: [query, breakpoint.customQuery].filter(Boolean).join(" and ")
|
|
61
|
+
};
|
|
32
62
|
}
|
|
33
63
|
function expandBreakpoints(...breakpoints) {
|
|
34
|
-
|
|
64
|
+
return breakpoints.flatMap((breakpoint) => [void 0, ...operators].map((operator) => buildBreakpoint(breakpoint, operator)));
|
|
35
65
|
}
|
|
36
66
|
function observeBreakpoint(id, initialValue = false) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
67
|
+
const breakpoint = registeredBreakpoints.get(id);
|
|
68
|
+
let unobserveMedia;
|
|
69
|
+
const state = signal({
|
|
70
|
+
...breakpoint,
|
|
71
|
+
matches: initialValue
|
|
72
|
+
}, {
|
|
73
|
+
watched() {
|
|
74
|
+
if (!breakpoint) return;
|
|
75
|
+
unobserveMedia = observeMedia(breakpoint.query, ({ matches }) => {
|
|
76
|
+
state.set({
|
|
77
|
+
...breakpoint,
|
|
78
|
+
matches
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
},
|
|
82
|
+
unwatched() {
|
|
83
|
+
unobserveMedia?.();
|
|
84
|
+
unobserveMedia = void 0;
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
return state;
|
|
55
88
|
}
|
|
56
89
|
function setupBreakpoints(breakpointsConfig = []) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
globalThis.addEventListener("DOMContentLoaded", initBreakpoints, { once: true });
|
|
80
|
-
} else {
|
|
81
|
-
initBreakpoints();
|
|
82
|
-
}
|
|
83
|
-
return destroyBreakpoints;
|
|
90
|
+
const directiveUpdater = createBreakpointUpdater(expandBreakpoints(...defaultBreakpoints, ...breakpointsConfig));
|
|
91
|
+
let mutationObserver;
|
|
92
|
+
let unobserveBreakpoints = () => {};
|
|
93
|
+
function initBreakpoints() {
|
|
94
|
+
destroyBreakpoints();
|
|
95
|
+
mutationObserver = new MutationObserver(directiveUpdater);
|
|
96
|
+
mutationObserver.observe(document.documentElement, {
|
|
97
|
+
attributes: true,
|
|
98
|
+
subtree: true,
|
|
99
|
+
childList: true,
|
|
100
|
+
attributeFilter: [breakpointAttribute]
|
|
101
|
+
});
|
|
102
|
+
unobserveBreakpoints = effect(directiveUpdater);
|
|
103
|
+
}
|
|
104
|
+
function destroyBreakpoints() {
|
|
105
|
+
unobserveBreakpoints();
|
|
106
|
+
mutationObserver?.disconnect();
|
|
107
|
+
globalThis.removeEventListener("DOMContentLoaded", initBreakpoints);
|
|
108
|
+
}
|
|
109
|
+
if (document.readyState === "loading") globalThis.addEventListener("DOMContentLoaded", initBreakpoints, { once: true });
|
|
110
|
+
else initBreakpoints();
|
|
111
|
+
return destroyBreakpoints;
|
|
84
112
|
}
|
|
85
113
|
function updateHostElement(host, active) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
host.slot = initialSlot;
|
|
108
|
-
} else {
|
|
109
|
-
host.slot = "_odx_breakpoint_hidden";
|
|
110
|
-
}
|
|
114
|
+
const attributeName = "data-odx-breakpoint-slot";
|
|
115
|
+
const classNames = host.getAttribute("odx-breakpoint-class");
|
|
116
|
+
if (classNames) {
|
|
117
|
+
for (const className of classNames.split(" ")) host.classList.toggle(className, active);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
host.hidden = !active;
|
|
121
|
+
let initialSlot = host.getAttribute(attributeName);
|
|
122
|
+
if (initialSlot == null) {
|
|
123
|
+
initialSlot = host.slot;
|
|
124
|
+
host.setAttribute(attributeName, initialSlot);
|
|
125
|
+
}
|
|
126
|
+
if (active) {
|
|
127
|
+
host.removeAttribute(attributeName);
|
|
128
|
+
if (initialSlot === "") {
|
|
129
|
+
host.removeAttribute("slot");
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
host.slot = "";
|
|
133
|
+
host.slot = initialSlot;
|
|
134
|
+
} else host.slot = "_odx_breakpoint_hidden";
|
|
111
135
|
}
|
|
112
136
|
function createBreakpointUpdater(breakpoints, update) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
breakpointCache.set(element, change.matches);
|
|
133
|
-
updateHostElement(element, change.matches);
|
|
134
|
-
update?.(element, change);
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
+
for (const breakpoint of breakpoints) registeredBreakpoints.set(breakpoint.id, breakpoint);
|
|
138
|
+
const breakpointCache = /* @__PURE__ */ new WeakMap();
|
|
139
|
+
const breakpointObservers = breakpoints.map((breakpoint) => observeBreakpoint(breakpoint.id, false));
|
|
140
|
+
return () => {
|
|
141
|
+
const elements = document.querySelectorAll(`[${breakpointAttribute}]`);
|
|
142
|
+
const changes = breakpointObservers.reduce((breakpoints, breakpoint) => {
|
|
143
|
+
breakpoints[breakpoint.get().id] = breakpoint.get();
|
|
144
|
+
return breakpoints;
|
|
145
|
+
}, {});
|
|
146
|
+
let i = elements.length;
|
|
147
|
+
while (i--) {
|
|
148
|
+
const element = elements[i];
|
|
149
|
+
const change = changes[element.getAttribute("odx-breakpoint") || ""];
|
|
150
|
+
if (!change || change.matches === breakpointCache.get(element)) continue;
|
|
151
|
+
breakpointCache.set(element, change.matches);
|
|
152
|
+
updateHostElement(element, change.matches);
|
|
153
|
+
update?.(element, change);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
137
156
|
}
|
|
138
|
-
|
|
157
|
+
//#endregion
|
|
139
158
|
export { breakpointAttribute, buildBreakpoint, createBreakpointUpdater, defaultBreakpoints, expandBreakpoints, observeBreakpoint, registeredBreakpoints, setupBreakpoints };
|
package/dist/lib/format.d.ts
CHANGED
|
@@ -1,58 +1,59 @@
|
|
|
1
|
-
import { UnitIdentifier } from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { UnitIdentifier } from "./models.js";
|
|
2
|
+
|
|
3
|
+
//#region src/lib/format.d.ts
|
|
4
|
+
interface FormatOptions {
|
|
5
|
+
dateTimeFormatOptions?: DateTimeFormatOptions;
|
|
6
|
+
numberFormatOptions?: NumberFormatOptions;
|
|
7
|
+
listFormatOptions?: ListFormatOptions;
|
|
8
|
+
relativeTimeFormatOptions?: RelativeTimeFormatOptions;
|
|
7
9
|
}
|
|
8
10
|
interface BaseFormatOptions {
|
|
9
|
-
|
|
11
|
+
locale?: Intl.Locale | Intl.UnicodeBCP47LocaleIdentifier;
|
|
10
12
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
interface DateTimeFormatOptions extends Omit<Intl.DateTimeFormatOptions, 'dateStyle'>, BaseFormatOptions {
|
|
14
|
+
dateStyle?: 'iso8601' | Intl.DateTimeFormatOptions['dateStyle'];
|
|
13
15
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
declare function parseDate(value: number | string | Date): Date | null;
|
|
17
|
+
declare function formatDate(input: number | string | Date, options?: DateTimeFormatOptions): string;
|
|
18
|
+
interface NumberFormatOptions extends Intl.NumberFormatOptions, BaseFormatOptions {
|
|
19
|
+
unit?: UnitIdentifier;
|
|
18
20
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
export declare function formatList(input: string[], options?: ListFormatOptions): string;
|
|
21
|
+
declare function formatNumber(input: number | string, options?: NumberFormatOptions): string;
|
|
22
|
+
interface ListFormatOptions extends Intl.ListFormatOptions, BaseFormatOptions {}
|
|
23
|
+
declare function formatList(input: string[], options?: ListFormatOptions): string;
|
|
23
24
|
declare const TIME_UNIT_MAP: {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
25
|
+
readonly second: {
|
|
26
|
+
readonly max: 59000;
|
|
27
|
+
readonly value: 1000;
|
|
28
|
+
};
|
|
29
|
+
readonly minute: {
|
|
30
|
+
readonly max: 2760000;
|
|
31
|
+
readonly value: 60000;
|
|
32
|
+
};
|
|
33
|
+
readonly hour: {
|
|
34
|
+
readonly max: 72000000;
|
|
35
|
+
readonly value: 3600000;
|
|
36
|
+
};
|
|
37
|
+
readonly day: {
|
|
38
|
+
readonly max: 518400000;
|
|
39
|
+
readonly value: 86400000;
|
|
40
|
+
};
|
|
41
|
+
readonly week: {
|
|
42
|
+
readonly max: 2419200000;
|
|
43
|
+
readonly value: 604800000;
|
|
44
|
+
};
|
|
45
|
+
readonly month: {
|
|
46
|
+
readonly max: 28512000000;
|
|
47
|
+
readonly value: 2592000000;
|
|
48
|
+
};
|
|
49
|
+
readonly year: {
|
|
50
|
+
readonly max: number;
|
|
51
|
+
readonly value: 31536000000;
|
|
52
|
+
};
|
|
52
53
|
};
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
interface RelativeTimeFormatOptions extends Intl.RelativeTimeFormatOptions, BaseFormatOptions {
|
|
55
|
+
minUnit?: keyof typeof TIME_UNIT_MAP;
|
|
55
56
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
declare function formatRelativeTime(input: number | string | Date, options?: RelativeTimeFormatOptions): string;
|
|
58
|
+
//#endregion
|
|
59
|
+
export { DateTimeFormatOptions, FormatOptions, ListFormatOptions, NumberFormatOptions, RelativeTimeFormatOptions, formatDate, formatList, formatNumber, formatRelativeTime, parseDate };
|
package/dist/lib/format.js
CHANGED
|
@@ -1,63 +1,65 @@
|
|
|
1
|
+
//#region src/lib/format.ts
|
|
1
2
|
function parseDate(value) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
if (Number.isNaN(date.getTime()) && typeof value === "string") {
|
|
8
|
-
return createDate(Number(value));
|
|
9
|
-
}
|
|
10
|
-
return createDate(date.getTime());
|
|
3
|
+
const createDate = (value) => Number.isNaN(value) ? null : new Date(value);
|
|
4
|
+
if (value instanceof Date) return createDate(value.getTime());
|
|
5
|
+
const date = new Date(value);
|
|
6
|
+
if (Number.isNaN(date.getTime()) && typeof value === "string") return createDate(Number(value));
|
|
7
|
+
return createDate(date.getTime());
|
|
11
8
|
}
|
|
12
9
|
function formatDate(input, options) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
return new Intl.DateTimeFormat(options?.locale, options).format(value);
|
|
10
|
+
const value = parseDate(input);
|
|
11
|
+
if (!value) return "";
|
|
12
|
+
if (options?.dateStyle === "iso8601") return new Intl.DateTimeFormat("sv-SE", { dateStyle: "short" }).format(value);
|
|
13
|
+
return new Intl.DateTimeFormat(options?.locale, options).format(value);
|
|
19
14
|
}
|
|
20
15
|
function formatNumber(input, options) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
options.style = "unit";
|
|
27
|
-
}
|
|
28
|
-
return new Intl.NumberFormat(options?.locale, options).format(value);
|
|
16
|
+
const value = Number(input);
|
|
17
|
+
if (Number.isNaN(value)) return "";
|
|
18
|
+
if (options?.currency) options.style = "currency";
|
|
19
|
+
else if (options?.unit) options.style = "unit";
|
|
20
|
+
return new Intl.NumberFormat(options?.locale, options).format(value);
|
|
29
21
|
}
|
|
30
22
|
function formatList(input, options) {
|
|
31
|
-
|
|
32
|
-
|
|
23
|
+
if (input.length === 0) return "";
|
|
24
|
+
return new Intl.ListFormat(options?.locale, options).format(input);
|
|
33
25
|
}
|
|
34
26
|
const TIME_UNIT_MAP = {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
27
|
+
second: {
|
|
28
|
+
max: 59e3,
|
|
29
|
+
value: 1e3
|
|
30
|
+
},
|
|
31
|
+
minute: {
|
|
32
|
+
max: 276e4,
|
|
33
|
+
value: 6e4
|
|
34
|
+
},
|
|
35
|
+
hour: {
|
|
36
|
+
max: 72e6,
|
|
37
|
+
value: 36e5
|
|
38
|
+
},
|
|
39
|
+
day: {
|
|
40
|
+
max: 5184e5,
|
|
41
|
+
value: 864e5
|
|
42
|
+
},
|
|
43
|
+
week: {
|
|
44
|
+
max: 24192e5,
|
|
45
|
+
value: 6048e5
|
|
46
|
+
},
|
|
47
|
+
month: {
|
|
48
|
+
max: 28512e6,
|
|
49
|
+
value: 2592e6
|
|
50
|
+
},
|
|
51
|
+
year: {
|
|
52
|
+
max: Number.POSITIVE_INFINITY,
|
|
53
|
+
value: 31536e6
|
|
54
|
+
}
|
|
48
55
|
};
|
|
49
56
|
function formatRelativeTime(input, options) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
);
|
|
57
|
-
return new Intl.RelativeTimeFormat(options?.locale, options).format(
|
|
58
|
-
Math.round(relativeTime / unitConfig.value),
|
|
59
|
-
unit
|
|
60
|
-
);
|
|
57
|
+
const value = parseDate(input);
|
|
58
|
+
if (!value) return "";
|
|
59
|
+
const relativeTime = value.getTime() - Date.now();
|
|
60
|
+
const minUnit = options?.minUnit && TIME_UNIT_MAP[options.minUnit] || TIME_UNIT_MAP.second;
|
|
61
|
+
const [unit, unitConfig] = Object.entries(TIME_UNIT_MAP).find(([_, { value, max }]) => Math.abs(relativeTime) < max && minUnit.value <= value);
|
|
62
|
+
return new Intl.RelativeTimeFormat(options?.locale, options).format(Math.round(relativeTime / unitConfig.value), unit);
|
|
61
63
|
}
|
|
62
|
-
|
|
64
|
+
//#endregion
|
|
63
65
|
export { formatDate, formatList, formatNumber, formatRelativeTime, parseDate };
|