@resq-sw/helpers 0.1.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 +218 -0
- package/lib/browser/html-entities.d.ts +34 -0
- package/lib/browser/html-entities.d.ts.map +1 -0
- package/lib/browser/html-entities.js +63 -0
- package/lib/browser/html-entities.js.map +1 -0
- package/lib/browser/index.d.ts +3 -0
- package/lib/browser/index.js +3 -0
- package/lib/browser/platform.d.ts +252 -0
- package/lib/browser/platform.d.ts.map +1 -0
- package/lib/browser/platform.js +272 -0
- package/lib/browser/platform.js.map +1 -0
- package/lib/formatting/date.d.ts +80 -0
- package/lib/formatting/date.d.ts.map +1 -0
- package/lib/formatting/date.js +135 -0
- package/lib/formatting/date.js.map +1 -0
- package/lib/formatting/date.types.d.ts +35 -0
- package/lib/formatting/date.types.d.ts.map +1 -0
- package/lib/formatting/date.types.js +0 -0
- package/lib/formatting/index.d.ts +5 -0
- package/lib/formatting/index.js +4 -0
- package/lib/formatting/number.d.ts +22 -0
- package/lib/formatting/number.d.ts.map +1 -0
- package/lib/formatting/number.js +39 -0
- package/lib/formatting/number.js.map +1 -0
- package/lib/formatting/string.d.ts +22 -0
- package/lib/formatting/string.d.ts.map +1 -0
- package/lib/formatting/string.js +30 -0
- package/lib/formatting/string.js.map +1 -0
- package/lib/helpers.d.ts +142 -0
- package/lib/helpers.d.ts.map +1 -0
- package/lib/helpers.js +159 -0
- package/lib/helpers.js.map +1 -0
- package/lib/index.d.ts +11 -0
- package/lib/index.js +9 -0
- package/lib/parse-code-path.d.ts +85 -0
- package/lib/parse-code-path.d.ts.map +1 -0
- package/lib/parse-code-path.js +160 -0
- package/lib/parse-code-path.js.map +1 -0
- package/lib/task-exec.d.ts +26 -0
- package/lib/task-exec.d.ts.map +1 -0
- package/lib/task-exec.js +45 -0
- package/lib/task-exec.js.map +1 -0
- package/lib/task-exec.types.d.ts +23 -0
- package/lib/task-exec.types.d.ts.map +1 -0
- package/lib/task-exec.types.js +0 -0
- package/package.json +55 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
//#region src/browser/platform.ts
|
|
2
|
+
/**
|
|
3
|
+
* Copyright 2026 ResQ
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Detects if the current user agent is an iOS device (iPad, iPhone, iPod).
|
|
19
|
+
*
|
|
20
|
+
* @returns {boolean} True if the platform is iOS, otherwise false.
|
|
21
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* if (isIOS()) { console.log('Running on iOS'); }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
const isIOS = () => /iPad|iPhone|iPod/.test(navigator.userAgent) && !globalThis.window.MSStream;
|
|
28
|
+
/**
|
|
29
|
+
* Detects if the current user agent is an Android device.
|
|
30
|
+
*
|
|
31
|
+
* @returns {boolean} True if the platform is Android, otherwise false.
|
|
32
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* if (isAndroid()) { console.log('Running on Android'); }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
const isAndroid = () => /android/i.test(navigator.userAgent);
|
|
39
|
+
/**
|
|
40
|
+
* Detects if the current user agent is a macOS device.
|
|
41
|
+
*
|
|
42
|
+
* @returns {boolean} True if the platform is macOS, otherwise false.
|
|
43
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* if (isMacOS()) { console.log('Running on macOS'); }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
const isMacOS = () => /Macintosh|Mac|Mac OS|MacIntel|MacPPC|Mac68K/gi.test(navigator.userAgent);
|
|
50
|
+
/**
|
|
51
|
+
* Detects if the current user agent is a Windows device.
|
|
52
|
+
*
|
|
53
|
+
* @returns {boolean} True if the platform is Windows, otherwise false.
|
|
54
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* if (isWindows()) { console.log('Running on Windows'); }
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
const isWindows = () => /Win32|Win64|Windows|Windows NT|WinCE/gi.test(navigator.userAgent);
|
|
61
|
+
/**
|
|
62
|
+
* Detects if the current user agent is Chrome OS.
|
|
63
|
+
*
|
|
64
|
+
* @returns {boolean} True if the platform is Chrome OS, otherwise false.
|
|
65
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* if (isChromeOS()) { console.log('Running on Chrome OS'); }
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
const isChromeOS = () => /CrOS/gi.test(navigator.userAgent);
|
|
72
|
+
/**
|
|
73
|
+
* Retrieves the browser name based on the user agent string.
|
|
74
|
+
*
|
|
75
|
+
* @returns {string} The browser name: 'edge', 'chrome', 'firefox', 'safari', 'opera', 'android', 'iphone', or 'unknown'.
|
|
76
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent
|
|
77
|
+
* @throws {TypeError} Throws if navigator.userAgent is not accessible.
|
|
78
|
+
* @example
|
|
79
|
+
* ```ts
|
|
80
|
+
* const browser = getBrowser(); // 'chrome', 'firefox', etc.
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
const getBrowser = () => {
|
|
84
|
+
const { userAgent } = navigator;
|
|
85
|
+
if (/edg/i.test(userAgent)) return "edge";
|
|
86
|
+
if (/chrome|chromium|crios/i.test(userAgent)) return "chrome";
|
|
87
|
+
if (/firefox|fxios/i.test(userAgent)) return "firefox";
|
|
88
|
+
if (/safari/i.test(userAgent)) return "safari";
|
|
89
|
+
if (/opr\//i.test(userAgent)) return "opera";
|
|
90
|
+
if (/android/i.test(userAgent)) return "android";
|
|
91
|
+
if (/iphone/i.test(userAgent)) return "iphone";
|
|
92
|
+
return "unknown";
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Determines the device platform as a string: 'ios', 'android', 'macos', 'chromeos', 'windows', or 'unknown'.
|
|
96
|
+
*
|
|
97
|
+
* @returns {string} The detected platform.
|
|
98
|
+
* @see isIOS
|
|
99
|
+
* @see isAndroid
|
|
100
|
+
* @see isMacOS
|
|
101
|
+
* @see isChromeOS
|
|
102
|
+
* @see isWindows
|
|
103
|
+
* @example
|
|
104
|
+
* ```ts
|
|
105
|
+
* const platform = getPlatform(); // 'android', 'ios', etc.
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
const getPlatform = () => {
|
|
109
|
+
if (isIOS()) return "ios";
|
|
110
|
+
if (isAndroid()) return "android";
|
|
111
|
+
if (isMacOS()) return "macos";
|
|
112
|
+
if (isChromeOS()) return "chromeos";
|
|
113
|
+
if (isWindows()) return "windows";
|
|
114
|
+
return "unknown";
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Checks if the current device has a touchscreen capability.
|
|
118
|
+
*
|
|
119
|
+
* @returns {boolean} True if touch screen is supported, otherwise false.
|
|
120
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/maxTouchPoints
|
|
121
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia
|
|
122
|
+
* @example
|
|
123
|
+
* ```ts
|
|
124
|
+
* if (isTouchScreen()) { console.log('Device supports touch.'); }
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
const isTouchScreen = () => {
|
|
128
|
+
return navigator.maxTouchPoints && navigator.maxTouchPoints > 0 || globalThis.window.matchMedia?.("(any-pointer:coarse)").matches;
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* Determines if the current browser is Google Chrome.
|
|
132
|
+
*
|
|
133
|
+
* @returns {boolean} True if Chrome, otherwise false.
|
|
134
|
+
* @see getBrowser
|
|
135
|
+
*/
|
|
136
|
+
const isChrome = () => getBrowser() === "chrome";
|
|
137
|
+
/**
|
|
138
|
+
* Determines if the current browser is Mozilla Firefox.
|
|
139
|
+
*
|
|
140
|
+
* @returns {boolean} True if Firefox, otherwise false.
|
|
141
|
+
* @see getBrowser
|
|
142
|
+
*/
|
|
143
|
+
const isFirefox = () => getBrowser() === "firefox";
|
|
144
|
+
/**
|
|
145
|
+
* Determines if the current browser is Safari.
|
|
146
|
+
*
|
|
147
|
+
* @returns {boolean} True if Safari, otherwise false.
|
|
148
|
+
* @see getBrowser
|
|
149
|
+
*/
|
|
150
|
+
const isSafari = () => getBrowser() === "safari";
|
|
151
|
+
/**
|
|
152
|
+
* Determines if the current browser is Opera.
|
|
153
|
+
*
|
|
154
|
+
* @returns {boolean} True if Opera, otherwise false.
|
|
155
|
+
* @see getBrowser
|
|
156
|
+
*/
|
|
157
|
+
const isOpera = () => getBrowser() === "opera";
|
|
158
|
+
/**
|
|
159
|
+
* Determines if the current browser is Microsoft Edge.
|
|
160
|
+
*
|
|
161
|
+
* @returns {boolean} True if Edge, otherwise false.
|
|
162
|
+
* @see getBrowser
|
|
163
|
+
*/
|
|
164
|
+
const isEdge = () => getBrowser() === "edge";
|
|
165
|
+
/**
|
|
166
|
+
* Detects Safari running on iOS devices.
|
|
167
|
+
*
|
|
168
|
+
* @returns {boolean} True if iOS Safari, otherwise false.
|
|
169
|
+
* @see isIOS
|
|
170
|
+
* @see isSafari
|
|
171
|
+
*/
|
|
172
|
+
const isIOSSafari = () => getBrowser() === "safari" && isIOS();
|
|
173
|
+
/**
|
|
174
|
+
* Detects Chrome running on iOS devices.
|
|
175
|
+
*
|
|
176
|
+
* @returns {boolean} True if iOS Chrome, otherwise false.
|
|
177
|
+
* @see isIOS
|
|
178
|
+
* @see isChrome
|
|
179
|
+
*/
|
|
180
|
+
const isIOSChrome = () => getBrowser() === "chrome" && isIOS();
|
|
181
|
+
/**
|
|
182
|
+
* Detects Chrome running on Android devices.
|
|
183
|
+
*
|
|
184
|
+
* @returns {boolean} True if Android Chrome, otherwise false.
|
|
185
|
+
* @see isAndroid
|
|
186
|
+
* @see isChrome
|
|
187
|
+
*/
|
|
188
|
+
const isAndroidChrome = () => getBrowser() === "chrome" && isAndroid();
|
|
189
|
+
/**
|
|
190
|
+
* Detects Chrome running on macOS devices.
|
|
191
|
+
*
|
|
192
|
+
* @returns {boolean} True if macOS Chrome, otherwise false.
|
|
193
|
+
* @see isMacOS
|
|
194
|
+
* @see isChrome
|
|
195
|
+
*/
|
|
196
|
+
const isMacOSChrome = () => getBrowser() === "chrome" && isMacOS();
|
|
197
|
+
/**
|
|
198
|
+
* Detects Chrome running on Windows devices.
|
|
199
|
+
*
|
|
200
|
+
* @returns {boolean} True if Windows Chrome, otherwise false.
|
|
201
|
+
* @see isWindows
|
|
202
|
+
* @see isChrome
|
|
203
|
+
*/
|
|
204
|
+
const isWindowsChrome = () => getBrowser() === "chrome" && isWindows();
|
|
205
|
+
/**
|
|
206
|
+
* Detects Firefox running on iOS devices.
|
|
207
|
+
*
|
|
208
|
+
* @returns {boolean} True if iOS Firefox, otherwise false.
|
|
209
|
+
* @see isIOS
|
|
210
|
+
* @see isFirefox
|
|
211
|
+
*/
|
|
212
|
+
const isIOSFirefox = () => getBrowser() === "firefox" && isIOS();
|
|
213
|
+
/**
|
|
214
|
+
* Detects Firefox running on Android devices.
|
|
215
|
+
*
|
|
216
|
+
* @returns {boolean} True if Android Firefox, otherwise false.
|
|
217
|
+
* @see isAndroid
|
|
218
|
+
* @see isFirefox
|
|
219
|
+
*/
|
|
220
|
+
const isAndroidFirefox = () => getBrowser() === "firefox" && isAndroid();
|
|
221
|
+
/**
|
|
222
|
+
* Detects Edge running on iOS devices.
|
|
223
|
+
*
|
|
224
|
+
* @returns {boolean} True if iOS Edge, otherwise false.
|
|
225
|
+
* @see isIOS
|
|
226
|
+
* @see isEdge
|
|
227
|
+
*/
|
|
228
|
+
const isIOSEdge = () => getBrowser() === "edge" && isIOS();
|
|
229
|
+
/**
|
|
230
|
+
* Detects Edge running on Android devices.
|
|
231
|
+
*
|
|
232
|
+
* @returns {boolean} True if Android Edge, otherwise false.
|
|
233
|
+
* @see isAndroid
|
|
234
|
+
* @see isEdge
|
|
235
|
+
*/
|
|
236
|
+
const isAndroidEdge = () => getBrowser() === "edge" && isAndroid();
|
|
237
|
+
/**
|
|
238
|
+
* Detects Edge running on macOS devices.
|
|
239
|
+
*
|
|
240
|
+
* @returns {boolean} True if macOS Edge, otherwise false.
|
|
241
|
+
* @see isMacOS
|
|
242
|
+
* @see isEdge
|
|
243
|
+
*/
|
|
244
|
+
const isMacOSEdge = () => getBrowser() === "edge" && isMacOS();
|
|
245
|
+
/**
|
|
246
|
+
* Detects Edge running on Windows devices.
|
|
247
|
+
*
|
|
248
|
+
* @returns {boolean} True if Windows Edge, otherwise false.
|
|
249
|
+
* @see isWindows
|
|
250
|
+
* @see isEdge
|
|
251
|
+
*/
|
|
252
|
+
const isWindowsEdge = () => getBrowser() === "edge" && isWindows();
|
|
253
|
+
/**
|
|
254
|
+
* Detects Opera running on iOS devices.
|
|
255
|
+
*
|
|
256
|
+
* @returns {boolean} True if iOS Opera, otherwise false.
|
|
257
|
+
* @see isIOS
|
|
258
|
+
* @see isOpera
|
|
259
|
+
*/
|
|
260
|
+
const isIOSOpera = () => getBrowser() === "opera" && isIOS();
|
|
261
|
+
/**
|
|
262
|
+
* Detects Opera running on Android devices.
|
|
263
|
+
*
|
|
264
|
+
* @returns {boolean} True if Android Opera, otherwise false.
|
|
265
|
+
* @see isAndroid
|
|
266
|
+
* @see isOpera
|
|
267
|
+
*/
|
|
268
|
+
const isAndroidOpera = () => getBrowser() === "opera" && isAndroid();
|
|
269
|
+
//#endregion
|
|
270
|
+
export { getBrowser, getPlatform, isAndroid, isAndroidChrome, isAndroidEdge, isAndroidFirefox, isAndroidOpera, isChrome, isChromeOS, isEdge, isFirefox, isIOS, isIOSChrome, isIOSEdge, isIOSFirefox, isIOSOpera, isIOSSafari, isMacOS, isMacOSChrome, isMacOSEdge, isOpera, isSafari, isTouchScreen, isWindows, isWindowsChrome, isWindowsEdge };
|
|
271
|
+
|
|
272
|
+
//# sourceMappingURL=platform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.js","names":[],"sources":["../../src/browser/platform.ts"],"sourcesContent":["/**\n * Copyright 2026 ResQ\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Detects if the current user agent is an iOS device (iPad, iPhone, iPod).\n *\n * @returns {boolean} True if the platform is iOS, otherwise false.\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent\n * @example\n * ```ts\n * if (isIOS()) { console.log('Running on iOS'); }\n * ```\n */\nexport const isIOS = (): boolean =>\n /iPad|iPhone|iPod/.test(navigator.userAgent) && !(globalThis.window as any).MSStream;\n\n/**\n * Detects if the current user agent is an Android device.\n *\n * @returns {boolean} True if the platform is Android, otherwise false.\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent\n * @example\n * ```ts\n * if (isAndroid()) { console.log('Running on Android'); }\n * ```\n */\nexport const isAndroid = (): boolean => /android/i.test(navigator.userAgent);\n\n/**\n * Detects if the current user agent is a macOS device.\n *\n * @returns {boolean} True if the platform is macOS, otherwise false.\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent\n * @example\n * ```ts\n * if (isMacOS()) { console.log('Running on macOS'); }\n * ```\n */\nexport const isMacOS = (): boolean =>\n /Macintosh|Mac|Mac OS|MacIntel|MacPPC|Mac68K/gi.test(navigator.userAgent);\n\n/**\n * Detects if the current user agent is a Windows device.\n *\n * @returns {boolean} True if the platform is Windows, otherwise false.\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent\n * @example\n * ```ts\n * if (isWindows()) { console.log('Running on Windows'); }\n * ```\n */\nexport const isWindows = (): boolean =>\n /Win32|Win64|Windows|Windows NT|WinCE/gi.test(navigator.userAgent);\n\n/**\n * Detects if the current user agent is Chrome OS.\n *\n * @returns {boolean} True if the platform is Chrome OS, otherwise false.\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent\n * @example\n * ```ts\n * if (isChromeOS()) { console.log('Running on Chrome OS'); }\n * ```\n */\nexport const isChromeOS = (): boolean => /CrOS/gi.test(navigator.userAgent);\n\n/**\n * Retrieves the browser name based on the user agent string.\n *\n * @returns {string} The browser name: 'edge', 'chrome', 'firefox', 'safari', 'opera', 'android', 'iphone', or 'unknown'.\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent\n * @throws {TypeError} Throws if navigator.userAgent is not accessible.\n * @example\n * ```ts\n * const browser = getBrowser(); // 'chrome', 'firefox', etc.\n * ```\n */\nexport const getBrowser = (): string => {\n const { userAgent } = navigator;\n\n if (/edg/i.test(userAgent)) {\n return 'edge';\n }\n if (/chrome|chromium|crios/i.test(userAgent)) {\n return 'chrome';\n }\n if (/firefox|fxios/i.test(userAgent)) {\n return 'firefox';\n }\n if (/safari/i.test(userAgent)) {\n return 'safari';\n }\n if (/opr\\//i.test(userAgent)) {\n return 'opera';\n }\n if (/android/i.test(userAgent)) {\n return 'android';\n }\n if (/iphone/i.test(userAgent)) {\n return 'iphone';\n }\n return 'unknown';\n};\n\n/**\n * Determines the device platform as a string: 'ios', 'android', 'macos', 'chromeos', 'windows', or 'unknown'.\n *\n * @returns {string} The detected platform.\n * @see isIOS\n * @see isAndroid\n * @see isMacOS\n * @see isChromeOS\n * @see isWindows\n * @example\n * ```ts\n * const platform = getPlatform(); // 'android', 'ios', etc.\n * ```\n */\nexport const getPlatform = (): string => {\n if (isIOS()) {\n return 'ios';\n }\n if (isAndroid()) {\n return 'android';\n }\n if (isMacOS()) {\n return 'macos';\n }\n if (isChromeOS()) {\n return 'chromeos';\n }\n if (isWindows()) {\n return 'windows';\n }\n return 'unknown';\n};\n\n/**\n * Checks if the current device has a touchscreen capability.\n *\n * @returns {boolean} True if touch screen is supported, otherwise false.\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/maxTouchPoints\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia\n * @example\n * ```ts\n * if (isTouchScreen()) { console.log('Device supports touch.'); }\n * ```\n */\nexport const isTouchScreen = (): boolean => {\n return (\n (navigator.maxTouchPoints && navigator.maxTouchPoints > 0) ||\n globalThis.window.matchMedia?.('(any-pointer:coarse)').matches\n );\n};\n\n/**\n * Determines if the current browser is Google Chrome.\n *\n * @returns {boolean} True if Chrome, otherwise false.\n * @see getBrowser\n */\nexport const isChrome = (): boolean => getBrowser() === 'chrome';\n\n/**\n * Determines if the current browser is Mozilla Firefox.\n *\n * @returns {boolean} True if Firefox, otherwise false.\n * @see getBrowser\n */\nexport const isFirefox = (): boolean => getBrowser() === 'firefox';\n\n/**\n * Determines if the current browser is Safari.\n *\n * @returns {boolean} True if Safari, otherwise false.\n * @see getBrowser\n */\nexport const isSafari = (): boolean => getBrowser() === 'safari';\n\n/**\n * Determines if the current browser is Opera.\n *\n * @returns {boolean} True if Opera, otherwise false.\n * @see getBrowser\n */\nexport const isOpera = (): boolean => getBrowser() === 'opera';\n\n/**\n * Determines if the current browser is Microsoft Edge.\n *\n * @returns {boolean} True if Edge, otherwise false.\n * @see getBrowser\n */\nexport const isEdge = (): boolean => getBrowser() === 'edge';\n\n/**\n * Detects Safari running on iOS devices.\n *\n * @returns {boolean} True if iOS Safari, otherwise false.\n * @see isIOS\n * @see isSafari\n */\nexport const isIOSSafari = (): boolean => getBrowser() === 'safari' && isIOS();\n\n/**\n * Detects Chrome running on iOS devices.\n *\n * @returns {boolean} True if iOS Chrome, otherwise false.\n * @see isIOS\n * @see isChrome\n */\nexport const isIOSChrome = (): boolean => getBrowser() === 'chrome' && isIOS();\n\n/**\n * Detects Chrome running on Android devices.\n *\n * @returns {boolean} True if Android Chrome, otherwise false.\n * @see isAndroid\n * @see isChrome\n */\nexport const isAndroidChrome = (): boolean => getBrowser() === 'chrome' && isAndroid();\n\n/**\n * Detects Chrome running on macOS devices.\n *\n * @returns {boolean} True if macOS Chrome, otherwise false.\n * @see isMacOS\n * @see isChrome\n */\nexport const isMacOSChrome = (): boolean => getBrowser() === 'chrome' && isMacOS();\n\n/**\n * Detects Chrome running on Windows devices.\n *\n * @returns {boolean} True if Windows Chrome, otherwise false.\n * @see isWindows\n * @see isChrome\n */\nexport const isWindowsChrome = (): boolean => getBrowser() === 'chrome' && isWindows();\n\n/**\n * Detects Firefox running on iOS devices.\n *\n * @returns {boolean} True if iOS Firefox, otherwise false.\n * @see isIOS\n * @see isFirefox\n */\nexport const isIOSFirefox = (): boolean => getBrowser() === 'firefox' && isIOS();\n\n/**\n * Detects Firefox running on Android devices.\n *\n * @returns {boolean} True if Android Firefox, otherwise false.\n * @see isAndroid\n * @see isFirefox\n */\nexport const isAndroidFirefox = (): boolean => getBrowser() === 'firefox' && isAndroid();\n\n/**\n * Detects Edge running on iOS devices.\n *\n * @returns {boolean} True if iOS Edge, otherwise false.\n * @see isIOS\n * @see isEdge\n */\nexport const isIOSEdge = (): boolean => getBrowser() === 'edge' && isIOS();\n\n/**\n * Detects Edge running on Android devices.\n *\n * @returns {boolean} True if Android Edge, otherwise false.\n * @see isAndroid\n * @see isEdge\n */\nexport const isAndroidEdge = (): boolean => getBrowser() === 'edge' && isAndroid();\n\n/**\n * Detects Edge running on macOS devices.\n *\n * @returns {boolean} True if macOS Edge, otherwise false.\n * @see isMacOS\n * @see isEdge\n */\nexport const isMacOSEdge = (): boolean => getBrowser() === 'edge' && isMacOS();\n\n/**\n * Detects Edge running on Windows devices.\n *\n * @returns {boolean} True if Windows Edge, otherwise false.\n * @see isWindows\n * @see isEdge\n */\nexport const isWindowsEdge = (): boolean => getBrowser() === 'edge' && isWindows();\n\n/**\n * Detects Opera running on iOS devices.\n *\n * @returns {boolean} True if iOS Opera, otherwise false.\n * @see isIOS\n * @see isOpera\n */\nexport const isIOSOpera = (): boolean => getBrowser() === 'opera' && isIOS();\n\n/**\n * Detects Opera running on Android devices.\n *\n * @returns {boolean} True if Android Opera, otherwise false.\n * @see isAndroid\n * @see isOpera\n */\nexport const isAndroidOpera = (): boolean => getBrowser() === 'opera' && isAndroid();\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,MAAa,cACX,mBAAmB,KAAK,UAAU,UAAU,IAAI,CAAE,WAAW,OAAe;;;;;;;;;;;AAY9E,MAAa,kBAA2B,WAAW,KAAK,UAAU,UAAU;;;;;;;;;;;AAY5E,MAAa,gBACX,gDAAgD,KAAK,UAAU,UAAU;;;;;;;;;;;AAY3E,MAAa,kBACX,yCAAyC,KAAK,UAAU,UAAU;;;;;;;;;;;AAYpE,MAAa,mBAA4B,SAAS,KAAK,UAAU,UAAU;;;;;;;;;;;;AAa3E,MAAa,mBAA2B;CACtC,MAAM,EAAE,cAAc;AAEtB,KAAI,OAAO,KAAK,UAAU,CACxB,QAAO;AAET,KAAI,yBAAyB,KAAK,UAAU,CAC1C,QAAO;AAET,KAAI,iBAAiB,KAAK,UAAU,CAClC,QAAO;AAET,KAAI,UAAU,KAAK,UAAU,CAC3B,QAAO;AAET,KAAI,SAAS,KAAK,UAAU,CAC1B,QAAO;AAET,KAAI,WAAW,KAAK,UAAU,CAC5B,QAAO;AAET,KAAI,UAAU,KAAK,UAAU,CAC3B,QAAO;AAET,QAAO;;;;;;;;;;;;;;;;AAiBT,MAAa,oBAA4B;AACvC,KAAI,OAAO,CACT,QAAO;AAET,KAAI,WAAW,CACb,QAAO;AAET,KAAI,SAAS,CACX,QAAO;AAET,KAAI,YAAY,CACd,QAAO;AAET,KAAI,WAAW,CACb,QAAO;AAET,QAAO;;;;;;;;;;;;;AAcT,MAAa,sBAA+B;AAC1C,QACG,UAAU,kBAAkB,UAAU,iBAAiB,KACxD,WAAW,OAAO,aAAa,uBAAuB,CAAC;;;;;;;;AAU3D,MAAa,iBAA0B,YAAY,KAAK;;;;;;;AAQxD,MAAa,kBAA2B,YAAY,KAAK;;;;;;;AAQzD,MAAa,iBAA0B,YAAY,KAAK;;;;;;;AAQxD,MAAa,gBAAyB,YAAY,KAAK;;;;;;;AAQvD,MAAa,eAAwB,YAAY,KAAK;;;;;;;;AAStD,MAAa,oBAA6B,YAAY,KAAK,YAAY,OAAO;;;;;;;;AAS9E,MAAa,oBAA6B,YAAY,KAAK,YAAY,OAAO;;;;;;;;AAS9E,MAAa,wBAAiC,YAAY,KAAK,YAAY,WAAW;;;;;;;;AAStF,MAAa,sBAA+B,YAAY,KAAK,YAAY,SAAS;;;;;;;;AASlF,MAAa,wBAAiC,YAAY,KAAK,YAAY,WAAW;;;;;;;;AAStF,MAAa,qBAA8B,YAAY,KAAK,aAAa,OAAO;;;;;;;;AAShF,MAAa,yBAAkC,YAAY,KAAK,aAAa,WAAW;;;;;;;;AASxF,MAAa,kBAA2B,YAAY,KAAK,UAAU,OAAO;;;;;;;;AAS1E,MAAa,sBAA+B,YAAY,KAAK,UAAU,WAAW;;;;;;;;AASlF,MAAa,oBAA6B,YAAY,KAAK,UAAU,SAAS;;;;;;;;AAS9E,MAAa,sBAA+B,YAAY,KAAK,UAAU,WAAW;;;;;;;;AASlF,MAAa,mBAA4B,YAAY,KAAK,WAAW,OAAO;;;;;;;;AAS5E,MAAa,uBAAgC,YAAY,KAAK,WAAW,WAAW"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { DateFormatOptions } from "./date.types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/formatting/date.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Formats a date string to a consistent format to prevent hydration mismatches.
|
|
6
|
+
*
|
|
7
|
+
* @param {string | Date} date - The date to format (ISO string or Date object).
|
|
8
|
+
* @param {DateFormatOptions} [options] - Optional formatting options.
|
|
9
|
+
* @returns {string} The formatted date string.
|
|
10
|
+
* @throws {Error} If the date is invalid.
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* formatDate('2023-01-15T10:00:00Z', { month: 'short', year: 'numeric' })
|
|
14
|
+
* // Returns: "Jan 2023"
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
declare function formatDate(date: string | Date, options?: DateFormatOptions): string;
|
|
18
|
+
/**
|
|
19
|
+
* Formats a date period (start to end or start to present).
|
|
20
|
+
*
|
|
21
|
+
* @param {string | Date} startDate - The start date.
|
|
22
|
+
* @param {string | Date | null} [endDate] - The end date, or null for ongoing.
|
|
23
|
+
* @param {boolean} [isCurrent=false] - Whether the period is current/ongoing.
|
|
24
|
+
* @returns {string} The formatted date period string.
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* formatDatePeriod('2023-01-01', '2023-12-31')
|
|
28
|
+
* // Returns: "Jan 2023 - Dec 2023"
|
|
29
|
+
*
|
|
30
|
+
* formatDatePeriod('2023-01-01', null, true)
|
|
31
|
+
* // Returns: "Jan 2023 - Present"
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
declare function formatDatePeriod(startDate: string | Date, endDate?: string | Date | null, isCurrent?: boolean): string;
|
|
35
|
+
/**
|
|
36
|
+
* Formats a full date with time for display.
|
|
37
|
+
*
|
|
38
|
+
* @param {string | Date} date - The date to format.
|
|
39
|
+
* @returns {string} The formatted date and time string.
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* formatDateTime('2023-01-15T14:30:00Z')
|
|
43
|
+
* // Returns: "January 15, 2023, 02:30 PM"
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
declare function formatDateTime(date: string | Date): string;
|
|
47
|
+
/**
|
|
48
|
+
* Formats a date for display without time.
|
|
49
|
+
*
|
|
50
|
+
* @param {string | Date} date - The date to format.
|
|
51
|
+
* @returns {string} The formatted date string.
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* formatDateOnly('2023-01-15')
|
|
55
|
+
* // Returns: "January 15, 2023"
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
declare function formatDateOnly(date: string | Date): string;
|
|
59
|
+
/**
|
|
60
|
+
* Formats a month and year for display.
|
|
61
|
+
*
|
|
62
|
+
* @param {string | Date} date - The date to format.
|
|
63
|
+
* @returns {string} The formatted month and year string.
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* formatMonthYear('2023-01-15')
|
|
67
|
+
* // Returns: "Jan 2023"
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
declare function formatMonthYear(date: string | Date): string;
|
|
71
|
+
/**
|
|
72
|
+
* Formats a relative time string (e.g. "2 days ago").
|
|
73
|
+
*
|
|
74
|
+
* @param {string | Date} date - The date to format.
|
|
75
|
+
* @returns {string} The relative time string.
|
|
76
|
+
*/
|
|
77
|
+
declare function formatRelativeTime(date: Date | string): string;
|
|
78
|
+
//#endregion
|
|
79
|
+
export { formatDate, formatDateOnly, formatDatePeriod, formatDateTime, formatMonthYear, formatRelativeTime };
|
|
80
|
+
//# sourceMappingURL=date.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date.d.ts","names":[],"sources":["../../src/formatting/date.ts"],"mappings":";;;;;;;;;;;AAuGA;;;;;iBAxEgB,UAAA,CACd,IAAA,WAAe,IAAA,EACf,OAAA,GAGK,iBAAA;;;;;AA2GP;;;;;AAaA;;;;;;;iBAnFgB,gBAAA,CACd,SAAA,WAAoB,IAAA,EACpB,OAAA,YAAmB,IAAA,SACnB,SAAA;;;;;;;;;;;;iBA2Bc,cAAA,CAAe,IAAA,WAAe,IAAA;;;;;;;;;;;;iBAqB9B,cAAA,CAAe,IAAA,WAAe,IAAA;;;;;;;;;;;;iBAmB9B,eAAA,CAAgB,IAAA,WAAe,IAAA;;;;;;;iBAa/B,kBAAA,CAAmB,IAAA,EAAM,IAAA"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
//#region src/formatting/date.ts
|
|
2
|
+
/**
|
|
3
|
+
* Formats a date string to a consistent format to prevent hydration mismatches.
|
|
4
|
+
*
|
|
5
|
+
* @param {string | Date} date - The date to format (ISO string or Date object).
|
|
6
|
+
* @param {DateFormatOptions} [options] - Optional formatting options.
|
|
7
|
+
* @returns {string} The formatted date string.
|
|
8
|
+
* @throws {Error} If the date is invalid.
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* formatDate('2023-01-15T10:00:00Z', { month: 'short', year: 'numeric' })
|
|
12
|
+
* // Returns: "Jan 2023"
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
function formatDate(date, options = {
|
|
16
|
+
month: "short",
|
|
17
|
+
year: "numeric"
|
|
18
|
+
}) {
|
|
19
|
+
try {
|
|
20
|
+
const dateObj = typeof date === "string" ? new Date(date) : date;
|
|
21
|
+
if (Number.isNaN(dateObj.getTime())) return "Invalid date";
|
|
22
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
23
|
+
...options,
|
|
24
|
+
timeZone: "UTC"
|
|
25
|
+
}).format(dateObj);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.error("Error formatting date:", error);
|
|
28
|
+
return "Invalid date";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Formats a date period (start to end or start to present).
|
|
33
|
+
*
|
|
34
|
+
* @param {string | Date} startDate - The start date.
|
|
35
|
+
* @param {string | Date | null} [endDate] - The end date, or null for ongoing.
|
|
36
|
+
* @param {boolean} [isCurrent=false] - Whether the period is current/ongoing.
|
|
37
|
+
* @returns {string} The formatted date period string.
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* formatDatePeriod('2023-01-01', '2023-12-31')
|
|
41
|
+
* // Returns: "Jan 2023 - Dec 2023"
|
|
42
|
+
*
|
|
43
|
+
* formatDatePeriod('2023-01-01', null, true)
|
|
44
|
+
* // Returns: "Jan 2023 - Present"
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
function formatDatePeriod(startDate, endDate, isCurrent = false) {
|
|
48
|
+
const formattedStart = formatDate(startDate, {
|
|
49
|
+
month: "short",
|
|
50
|
+
year: "numeric"
|
|
51
|
+
});
|
|
52
|
+
if (isCurrent) return `${formattedStart} - Present`;
|
|
53
|
+
if (endDate) return `${formattedStart} - ${formatDate(endDate, {
|
|
54
|
+
month: "short",
|
|
55
|
+
year: "numeric"
|
|
56
|
+
})}`;
|
|
57
|
+
return `${formattedStart} - Present`;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Formats a full date with time for display.
|
|
61
|
+
*
|
|
62
|
+
* @param {string | Date} date - The date to format.
|
|
63
|
+
* @returns {string} The formatted date and time string.
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* formatDateTime('2023-01-15T14:30:00Z')
|
|
67
|
+
* // Returns: "January 15, 2023, 02:30 PM"
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
function formatDateTime(date) {
|
|
71
|
+
return formatDate(date, {
|
|
72
|
+
year: "numeric",
|
|
73
|
+
month: "long",
|
|
74
|
+
day: "numeric",
|
|
75
|
+
hour: "2-digit",
|
|
76
|
+
minute: "2-digit"
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Formats a date for display without time.
|
|
81
|
+
*
|
|
82
|
+
* @param {string | Date} date - The date to format.
|
|
83
|
+
* @returns {string} The formatted date string.
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* formatDateOnly('2023-01-15')
|
|
87
|
+
* // Returns: "January 15, 2023"
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
function formatDateOnly(date) {
|
|
91
|
+
return formatDate(date, {
|
|
92
|
+
year: "numeric",
|
|
93
|
+
month: "long",
|
|
94
|
+
day: "numeric"
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Formats a month and year for display.
|
|
99
|
+
*
|
|
100
|
+
* @param {string | Date} date - The date to format.
|
|
101
|
+
* @returns {string} The formatted month and year string.
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* formatMonthYear('2023-01-15')
|
|
105
|
+
* // Returns: "Jan 2023"
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
function formatMonthYear(date) {
|
|
109
|
+
return formatDate(date, {
|
|
110
|
+
month: "short",
|
|
111
|
+
year: "numeric"
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Formats a relative time string (e.g. "2 days ago").
|
|
116
|
+
*
|
|
117
|
+
* @param {string | Date} date - The date to format.
|
|
118
|
+
* @returns {string} The relative time string.
|
|
119
|
+
*/
|
|
120
|
+
function formatRelativeTime(date) {
|
|
121
|
+
const d = typeof date === "string" ? new Date(date) : date;
|
|
122
|
+
const diff = (/* @__PURE__ */ new Date()).getTime() - d.getTime();
|
|
123
|
+
const seconds = Math.floor(diff / 1e3);
|
|
124
|
+
const minutes = Math.floor(seconds / 60);
|
|
125
|
+
const hours = Math.floor(minutes / 60);
|
|
126
|
+
const days = Math.floor(hours / 24);
|
|
127
|
+
if (days > 0) return `${days} day${days > 1 ? "s" : ""} ago`;
|
|
128
|
+
if (hours > 0) return `${hours} hour${hours > 1 ? "s" : ""} ago`;
|
|
129
|
+
if (minutes > 0) return `${minutes} minute${minutes > 1 ? "s" : ""} ago`;
|
|
130
|
+
return "Just now";
|
|
131
|
+
}
|
|
132
|
+
//#endregion
|
|
133
|
+
export { formatDate, formatDateOnly, formatDatePeriod, formatDateTime, formatMonthYear, formatRelativeTime };
|
|
134
|
+
|
|
135
|
+
//# sourceMappingURL=date.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date.js","names":[],"sources":["../../src/formatting/date.ts"],"sourcesContent":["/**\n * Copyright 2026 ResQ\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { DateFormatOptions } from './date.types.js';\n\n/**\n * Formats a date string to a consistent format to prevent hydration mismatches.\n *\n * @param {string | Date} date - The date to format (ISO string or Date object).\n * @param {DateFormatOptions} [options] - Optional formatting options.\n * @returns {string} The formatted date string.\n * @throws {Error} If the date is invalid.\n * @example\n * ```ts\n * formatDate('2023-01-15T10:00:00Z', { month: 'short', year: 'numeric' })\n * // Returns: \"Jan 2023\"\n * ```\n */\nexport function formatDate(\n date: string | Date,\n options = {\n month: 'short',\n year: 'numeric',\n } as DateFormatOptions,\n): string {\n try {\n const dateObj = typeof date === 'string' ? new Date(date) : date;\n\n if (Number.isNaN(dateObj.getTime())) {\n return 'Invalid date';\n }\n\n const formatter = new Intl.DateTimeFormat('en-US', {\n ...options,\n timeZone: 'UTC',\n });\n\n return formatter.format(dateObj);\n } catch (error) {\n console.error('Error formatting date:', error);\n return 'Invalid date';\n }\n}\n\n/**\n * Formats a date period (start to end or start to present).\n *\n * @param {string | Date} startDate - The start date.\n * @param {string | Date | null} [endDate] - The end date, or null for ongoing.\n * @param {boolean} [isCurrent=false] - Whether the period is current/ongoing.\n * @returns {string} The formatted date period string.\n * @example\n * ```ts\n * formatDatePeriod('2023-01-01', '2023-12-31')\n * // Returns: \"Jan 2023 - Dec 2023\"\n *\n * formatDatePeriod('2023-01-01', null, true)\n * // Returns: \"Jan 2023 - Present\"\n * ```\n */\nexport function formatDatePeriod(\n startDate: string | Date,\n endDate?: string | Date | null,\n isCurrent: boolean = false,\n): string {\n const formattedStart = formatDate(startDate, { month: 'short', year: 'numeric' });\n\n if (isCurrent) {\n return `${formattedStart} - Present`;\n }\n\n if (endDate) {\n const formattedEnd = formatDate(endDate, { month: 'short', year: 'numeric' });\n return `${formattedStart} - ${formattedEnd}`;\n }\n\n return `${formattedStart} - Present`;\n}\n\n/**\n * Formats a full date with time for display.\n *\n * @param {string | Date} date - The date to format.\n * @returns {string} The formatted date and time string.\n * @example\n * ```ts\n * formatDateTime('2023-01-15T14:30:00Z')\n * // Returns: \"January 15, 2023, 02:30 PM\"\n * ```\n */\nexport function formatDateTime(date: string | Date): string {\n return formatDate(date, {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\n/**\n * Formats a date for display without time.\n *\n * @param {string | Date} date - The date to format.\n * @returns {string} The formatted date string.\n * @example\n * ```ts\n * formatDateOnly('2023-01-15')\n * // Returns: \"January 15, 2023\"\n * ```\n */\nexport function formatDateOnly(date: string | Date): string {\n return formatDate(date, {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n}\n\n/**\n * Formats a month and year for display.\n *\n * @param {string | Date} date - The date to format.\n * @returns {string} The formatted month and year string.\n * @example\n * ```ts\n * formatMonthYear('2023-01-15')\n * // Returns: \"Jan 2023\"\n * ```\n */\nexport function formatMonthYear(date: string | Date): string {\n return formatDate(date, {\n month: 'short',\n year: 'numeric',\n });\n}\n\n/**\n * Formats a relative time string (e.g. \"2 days ago\").\n *\n * @param {string | Date} date - The date to format.\n * @returns {string} The relative time string.\n */\nexport function formatRelativeTime(date: Date | string): string {\n const d = typeof date === 'string' ? new Date(date) : date;\n const now = new Date();\n const diff = now.getTime() - d.getTime();\n\n const seconds = Math.floor(diff / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) return `${days} day${days > 1 ? 's' : ''} ago`;\n if (hours > 0) return `${hours} hour${hours > 1 ? 's' : ''} ago`;\n if (minutes > 0) return `${minutes} minute${minutes > 1 ? 's' : ''} ago`;\n return 'Just now';\n}\n"],"mappings":";;;;;;;;;;;;;;AA+BA,SAAgB,WACd,MACA,UAAU;CACR,OAAO;CACP,MAAM;CACP,EACO;AACR,KAAI;EACF,MAAM,UAAU,OAAO,SAAS,WAAW,IAAI,KAAK,KAAK,GAAG;AAE5D,MAAI,OAAO,MAAM,QAAQ,SAAS,CAAC,CACjC,QAAO;AAQT,SALkB,IAAI,KAAK,eAAe,SAAS;GACjD,GAAG;GACH,UAAU;GACX,CAAC,CAEe,OAAO,QAAQ;UACzB,OAAO;AACd,UAAQ,MAAM,0BAA0B,MAAM;AAC9C,SAAO;;;;;;;;;;;;;;;;;;;AAoBX,SAAgB,iBACd,WACA,SACA,YAAqB,OACb;CACR,MAAM,iBAAiB,WAAW,WAAW;EAAE,OAAO;EAAS,MAAM;EAAW,CAAC;AAEjF,KAAI,UACF,QAAO,GAAG,eAAe;AAG3B,KAAI,QAEF,QAAO,GAAG,eAAe,KADJ,WAAW,SAAS;EAAE,OAAO;EAAS,MAAM;EAAW,CAAC;AAI/E,QAAO,GAAG,eAAe;;;;;;;;;;;;;AAc3B,SAAgB,eAAe,MAA6B;AAC1D,QAAO,WAAW,MAAM;EACtB,MAAM;EACN,OAAO;EACP,KAAK;EACL,MAAM;EACN,QAAQ;EACT,CAAC;;;;;;;;;;;;;AAcJ,SAAgB,eAAe,MAA6B;AAC1D,QAAO,WAAW,MAAM;EACtB,MAAM;EACN,OAAO;EACP,KAAK;EACN,CAAC;;;;;;;;;;;;;AAcJ,SAAgB,gBAAgB,MAA6B;AAC3D,QAAO,WAAW,MAAM;EACtB,OAAO;EACP,MAAM;EACP,CAAC;;;;;;;;AASJ,SAAgB,mBAAmB,MAA6B;CAC9D,MAAM,IAAI,OAAO,SAAS,WAAW,IAAI,KAAK,KAAK,GAAG;CAEtD,MAAM,wBADM,IAAI,MAAM,EACL,SAAS,GAAG,EAAE,SAAS;CAExC,MAAM,UAAU,KAAK,MAAM,OAAO,IAAK;CACvC,MAAM,UAAU,KAAK,MAAM,UAAU,GAAG;CACxC,MAAM,QAAQ,KAAK,MAAM,UAAU,GAAG;CACtC,MAAM,OAAO,KAAK,MAAM,QAAQ,GAAG;AAEnC,KAAI,OAAO,EAAG,QAAO,GAAG,KAAK,MAAM,OAAO,IAAI,MAAM,GAAG;AACvD,KAAI,QAAQ,EAAG,QAAO,GAAG,MAAM,OAAO,QAAQ,IAAI,MAAM,GAAG;AAC3D,KAAI,UAAU,EAAG,QAAO,GAAG,QAAQ,SAAS,UAAU,IAAI,MAAM,GAAG;AACnE,QAAO"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
//#region src/formatting/date.types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Copyright 2026 ResQ
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Format options for date display.
|
|
19
|
+
*
|
|
20
|
+
* @property {'short' | 'long' | 'numeric'} [month] - Month display format.
|
|
21
|
+
* @property {'numeric' | '2-digit'} [year] - Year display format.
|
|
22
|
+
* @property {'numeric' | '2-digit'} [day] - Day display format.
|
|
23
|
+
* @property {'numeric' | '2-digit'} [hour] - Hour display format.
|
|
24
|
+
* @property {'numeric' | '2-digit'} [minute] - Minute display format.
|
|
25
|
+
*/
|
|
26
|
+
interface DateFormatOptions {
|
|
27
|
+
month?: 'short' | 'long' | 'numeric';
|
|
28
|
+
year?: 'numeric' | '2-digit';
|
|
29
|
+
day?: 'numeric' | '2-digit';
|
|
30
|
+
hour?: 'numeric' | '2-digit';
|
|
31
|
+
minute?: 'numeric' | '2-digit';
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
export { DateFormatOptions };
|
|
35
|
+
//# sourceMappingURL=date.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date.types.d.ts","names":[],"sources":["../../src/formatting/date.types.ts"],"mappings":";;AAyBA;;;;;;;;;;;;;;;;;;;;;;;UAAiB,iBAAA;EACf,KAAA;EACA,IAAA;EACA,GAAA;EACA,IAAA;EACA,MAAA;AAAA"}
|
|
File without changes
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { DateFormatOptions } from "./date.types.js";
|
|
2
|
+
import { formatDate, formatDateOnly, formatDatePeriod, formatDateTime, formatMonthYear, formatRelativeTime } from "./date.js";
|
|
3
|
+
import { formatBytes, formatNumber, formatPercent } from "./number.js";
|
|
4
|
+
import { capitalize, slugify, truncate } from "./string.js";
|
|
5
|
+
export { DateFormatOptions, capitalize, formatBytes, formatDate, formatDateOnly, formatDatePeriod, formatDateTime, formatMonthYear, formatNumber, formatPercent, formatRelativeTime, slugify, truncate };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { formatDate, formatDateOnly, formatDatePeriod, formatDateTime, formatMonthYear, formatRelativeTime } from "./date.js";
|
|
2
|
+
import { formatBytes, formatNumber, formatPercent } from "./number.js";
|
|
3
|
+
import { capitalize, slugify, truncate } from "./string.js";
|
|
4
|
+
export { capitalize, formatBytes, formatDate, formatDateOnly, formatDatePeriod, formatDateTime, formatMonthYear, formatNumber, formatPercent, formatRelativeTime, slugify, truncate };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/formatting/number.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Copyright 2026 ResQ
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
declare function formatNumber(num: number): string;
|
|
18
|
+
declare function formatBytes(bytes: number): string;
|
|
19
|
+
declare function formatPercent(value: number): string;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { formatBytes, formatNumber, formatPercent };
|
|
22
|
+
//# sourceMappingURL=number.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"number.d.ts","names":[],"sources":["../../src/formatting/number.ts"],"mappings":";;AAgBA;;;;;AAIA;;;;;AAQA;;;;iBAZgB,YAAA,CAAa,GAAA;AAAA,iBAIb,WAAA,CAAY,KAAA;AAAA,iBAQZ,aAAA,CAAc,KAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//#region src/formatting/number.ts
|
|
2
|
+
/**
|
|
3
|
+
* Copyright 2026 ResQ
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
function formatNumber(num) {
|
|
18
|
+
return new Intl.NumberFormat("en-US").format(num);
|
|
19
|
+
}
|
|
20
|
+
function formatBytes(bytes) {
|
|
21
|
+
if (bytes === 0) return "0 Bytes";
|
|
22
|
+
const k = 1024;
|
|
23
|
+
const sizes = [
|
|
24
|
+
"Bytes",
|
|
25
|
+
"KB",
|
|
26
|
+
"MB",
|
|
27
|
+
"GB",
|
|
28
|
+
"TB"
|
|
29
|
+
];
|
|
30
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
31
|
+
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + " " + sizes[i];
|
|
32
|
+
}
|
|
33
|
+
function formatPercent(value) {
|
|
34
|
+
return `${(value * 100).toFixed(1)}%`;
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { formatBytes, formatNumber, formatPercent };
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=number.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"number.js","names":[],"sources":["../../src/formatting/number.ts"],"sourcesContent":["/**\n * Copyright 2026 ResQ\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport function formatNumber(num: number): string {\n return new Intl.NumberFormat('en-US').format(num)\n}\n\nexport function formatBytes(bytes: number): string {\n if (bytes === 0) return '0 Bytes'\n const k = 1024\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i]\n}\n\nexport function formatPercent(value: number): string {\n return `${(value * 100).toFixed(1)}%`\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,SAAgB,aAAa,KAAqB;AAChD,QAAO,IAAI,KAAK,aAAa,QAAQ,CAAC,OAAO,IAAI;;AAGnD,SAAgB,YAAY,OAAuB;AACjD,KAAI,UAAU,EAAG,QAAO;CACxB,MAAM,IAAI;CACV,MAAM,QAAQ;EAAC;EAAS;EAAM;EAAM;EAAM;EAAK;CAC/C,MAAM,IAAI,KAAK,MAAM,KAAK,IAAI,MAAM,GAAG,KAAK,IAAI,EAAE,CAAC;AACnD,QAAO,KAAK,MAAO,QAAQ,KAAK,IAAI,GAAG,EAAE,GAAI,IAAI,GAAG,MAAM,MAAM,MAAM;;AAGxE,SAAgB,cAAc,OAAuB;AACnD,QAAO,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC"}
|