@bagelink/vue 1.9.192 → 1.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/AddressSearch.vue.d.ts.map +1 -1
- package/dist/components/Pagination.vue.d.ts +1 -1
- package/dist/components/Pagination.vue.d.ts.map +1 -1
- package/dist/components/Swiper.vue.d.ts +3 -9
- package/dist/components/Swiper.vue.d.ts.map +1 -1
- package/dist/components/calendar/CalendarPopover.vue.d.ts.map +1 -1
- package/dist/components/form/FieldArray.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/Upload/upload.d.ts +1 -1
- package/dist/form-flow/FormFlow.vue.d.ts.map +1 -1
- package/dist/form-flow/MultiStepForm.vue.d.ts +2 -2
- package/dist/form-flow/form-flow.d.ts.map +1 -1
- package/dist/index.cjs +98 -98
- package/dist/index.mjs +17079 -17812
- package/dist/plugins/bagel.d.ts.map +1 -1
- package/dist/style.css +1 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/calendar/dateUtils.d.ts +3 -72
- package/dist/utils/calendar/dateUtils.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/form-flow/FormFlow.vue +5 -4
- package/src/form-flow/form-flow.ts +3 -5
- package/src/plugins/bagel.ts +13 -0
- package/src/types/index.ts +0 -1
- package/src/utils/calendar/dateUtils.ts +42 -374
|
@@ -1,63 +1,9 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import
|
|
1
|
+
import type { TimeUnit } from '../../types/timeAgoT'
|
|
2
|
+
import { timeDelta, formatDate, fmtDate, handleTimezone, getDatePartsMap } from '@bagelink/utils'
|
|
3
3
|
import { getI18n } from '../../i18n'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Hour?: number
|
|
8
|
-
Minute?: number
|
|
9
|
-
Second?: number
|
|
10
|
-
Week?: number
|
|
11
|
-
Month?: number
|
|
12
|
-
Year?: number
|
|
13
|
-
days?: number
|
|
14
|
-
hours?: number
|
|
15
|
-
minutes?: number
|
|
16
|
-
seconds?: number
|
|
17
|
-
weeks?: number
|
|
18
|
-
months?: number
|
|
19
|
-
years?: number
|
|
20
|
-
day?: number
|
|
21
|
-
hour?: number
|
|
22
|
-
minute?: number
|
|
23
|
-
second?: number
|
|
24
|
-
week?: number
|
|
25
|
-
month?: number
|
|
26
|
-
year?: number
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function timeDelta(date: string | Date, options: TimeDeltaOptions) {
|
|
30
|
-
date = new Date(date)
|
|
31
|
-
const day = options.Day || options.day || options.days || 0
|
|
32
|
-
const hour = options.Hour || options.hour || options.hours || 0
|
|
33
|
-
const minute = options.Minute || options.minute || options.minutes || 0
|
|
34
|
-
const second = options.Second || options.second || options.seconds || 0
|
|
35
|
-
const week = options.Week || options.week || options.weeks || 0
|
|
36
|
-
const month = options.Month || options.month || options.months || 0
|
|
37
|
-
const year = options.Year || options.year || options.years || 0
|
|
38
|
-
if (day) {
|
|
39
|
-
date.setDate(date.getDate() + day)
|
|
40
|
-
}
|
|
41
|
-
if (hour) {
|
|
42
|
-
date.setHours(date.getHours() + hour)
|
|
43
|
-
}
|
|
44
|
-
if (minute) {
|
|
45
|
-
date.setMinutes(date.getMinutes() + minute)
|
|
46
|
-
}
|
|
47
|
-
if (second) {
|
|
48
|
-
date.setSeconds(date.getSeconds() + second)
|
|
49
|
-
}
|
|
50
|
-
if (week) {
|
|
51
|
-
date.setDate(date.getDate() + week * 7)
|
|
52
|
-
}
|
|
53
|
-
if (month) {
|
|
54
|
-
date.setMonth(date.getMonth() + month)
|
|
55
|
-
}
|
|
56
|
-
if (year) {
|
|
57
|
-
date.setFullYear(date.getFullYear() + year)
|
|
58
|
-
}
|
|
59
|
-
return date
|
|
60
|
-
}
|
|
5
|
+
export { fmtDate, formatDate, getDatePartsMap, handleTimezone, timeDelta }
|
|
6
|
+
export type { DateTimeAcceptedFormats, FormatDateOptions } from '@bagelink/utils'
|
|
61
7
|
|
|
62
8
|
type TimeAgoLang = 'en' | 'es' | 'fr' | 'he' | 'it' | 'ru'
|
|
63
9
|
|
|
@@ -74,61 +20,36 @@ interface TimeAgoTranslations {
|
|
|
74
20
|
justNow: string
|
|
75
21
|
}
|
|
76
22
|
|
|
77
|
-
/**
|
|
78
|
-
* Get timeAgo translations from i18n instance
|
|
79
|
-
*/
|
|
80
23
|
function getTimeAgoTranslations(lang: TimeAgoLang): TimeAgoTranslations {
|
|
24
|
+
const fallback: TimeAgoTranslations = {
|
|
25
|
+
year: 'year',
|
|
26
|
+
month: 'month',
|
|
27
|
+
week: 'week',
|
|
28
|
+
day: 'day',
|
|
29
|
+
hour: 'hour',
|
|
30
|
+
minute: 'minute',
|
|
31
|
+
second: 'second',
|
|
32
|
+
ago: 'ago',
|
|
33
|
+
in: 'in',
|
|
34
|
+
justNow: 'Just now',
|
|
35
|
+
}
|
|
81
36
|
try {
|
|
82
37
|
const i18n = getI18n()
|
|
83
38
|
const messages = i18n.global.messages as Record<string, { timeAgo?: TimeAgoTranslations }>
|
|
84
39
|
const localeMessages = messages[lang] || messages.en
|
|
85
|
-
|
|
86
|
-
return localeMessages.timeAgo
|
|
87
|
-
}
|
|
88
|
-
// Fallback to English if timeAgo not found
|
|
89
|
-
return {
|
|
90
|
-
year: 'year',
|
|
91
|
-
month: 'month',
|
|
92
|
-
week: 'week',
|
|
93
|
-
day: 'day',
|
|
94
|
-
hour: 'hour',
|
|
95
|
-
minute: 'minute',
|
|
96
|
-
second: 'second',
|
|
97
|
-
ago: 'ago',
|
|
98
|
-
in: 'in',
|
|
99
|
-
justNow: 'Just now',
|
|
100
|
-
}
|
|
40
|
+
return localeMessages?.timeAgo ?? fallback
|
|
101
41
|
} catch {
|
|
102
|
-
|
|
103
|
-
return {
|
|
104
|
-
year: 'year',
|
|
105
|
-
month: 'month',
|
|
106
|
-
week: 'week',
|
|
107
|
-
day: 'day',
|
|
108
|
-
hour: 'hour',
|
|
109
|
-
minute: 'minute',
|
|
110
|
-
second: 'second',
|
|
111
|
-
ago: 'ago',
|
|
112
|
-
in: 'in',
|
|
113
|
-
justNow: 'Just now',
|
|
114
|
-
}
|
|
42
|
+
return fallback
|
|
115
43
|
}
|
|
116
44
|
}
|
|
117
45
|
|
|
118
|
-
/**
|
|
119
|
-
* Get current locale from i18n instance
|
|
120
|
-
*/
|
|
121
46
|
function getCurrentLocale(): TimeAgoLang {
|
|
122
47
|
try {
|
|
123
48
|
const i18n = getI18n()
|
|
124
49
|
const { locale } = i18n.global
|
|
125
50
|
const lang = typeof locale === 'string' ? locale : locale.value
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (supportedLangs.includes(lang as TimeAgoLang)) {
|
|
129
|
-
return lang as TimeAgoLang
|
|
130
|
-
}
|
|
131
|
-
return 'en'
|
|
51
|
+
const supported: TimeAgoLang[] = ['en', 'es', 'fr', 'he', 'it', 'ru']
|
|
52
|
+
return supported.includes(lang as TimeAgoLang) ? lang as TimeAgoLang : 'en'
|
|
132
53
|
} catch {
|
|
133
54
|
return 'en'
|
|
134
55
|
}
|
|
@@ -138,21 +59,16 @@ export function timeAgo(
|
|
|
138
59
|
date: string | Date,
|
|
139
60
|
langOrConfig?: TimeAgoLang | { lang?: TimeAgoLang, mode?: 'relative' | 'absolute' }
|
|
140
61
|
) {
|
|
141
|
-
if (!date)
|
|
142
|
-
if (typeof date === 'string')
|
|
62
|
+
if (!date) return ''
|
|
63
|
+
if (typeof date === 'string') date = new Date(date)
|
|
143
64
|
|
|
144
|
-
// Parse config - use global i18n locale if no lang specified
|
|
145
65
|
const lang = typeof langOrConfig === 'string'
|
|
146
66
|
? langOrConfig
|
|
147
67
|
: (langOrConfig?.lang || getCurrentLocale())
|
|
148
68
|
const mode = typeof langOrConfig === 'object' ? (langOrConfig.mode || 'relative') : 'relative'
|
|
149
69
|
const isRelative = mode === 'relative'
|
|
150
70
|
|
|
151
|
-
const
|
|
152
|
-
const nowNumber = now.getTime()
|
|
153
|
-
const dateNumber = date.getTime()
|
|
154
|
-
const seconds = Math.floor((dateNumber - nowNumber) / 1000)
|
|
155
|
-
|
|
71
|
+
const seconds = Math.floor((date.getTime() - Date.now()) / 1000)
|
|
156
72
|
const intervals = [
|
|
157
73
|
{ label: 'year', seconds: 31536000 },
|
|
158
74
|
{ label: 'month', seconds: 2592000 },
|
|
@@ -160,293 +76,45 @@ export function timeAgo(
|
|
|
160
76
|
{ label: 'day', seconds: 86400 },
|
|
161
77
|
{ label: 'hour', seconds: 3600 },
|
|
162
78
|
{ label: 'minute', seconds: 60 },
|
|
163
|
-
{ label: 'second', seconds: 1 }
|
|
79
|
+
{ label: 'second', seconds: 1 },
|
|
164
80
|
]
|
|
165
81
|
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
// Helper to get time unit translation
|
|
169
|
-
const getTimeUnit = (label: string): string | TimeUnit => {
|
|
170
|
-
const key = label as keyof TimeAgoTranslations
|
|
171
|
-
return selectedLang[key] as string | TimeUnit
|
|
172
|
-
}
|
|
82
|
+
const t = getTimeAgoTranslations(lang)
|
|
83
|
+
const getUnit = (label: string): string | TimeUnit => t[label as keyof TimeAgoTranslations] as string | TimeUnit
|
|
173
84
|
|
|
174
85
|
for (const interval of intervals) {
|
|
175
86
|
const count = Math.floor(Math.abs(seconds) / interval.seconds)
|
|
176
87
|
if (count >= 1) {
|
|
177
|
-
const suffix = isRelative && seconds < 0 ? ` ${
|
|
178
|
-
const prefix = isRelative && seconds > 0 &&
|
|
88
|
+
const suffix = isRelative && seconds < 0 ? ` ${t.ago}` : ''
|
|
89
|
+
const prefix = isRelative && seconds > 0 && t.in !== 'in' ? `${t.in} ` : ''
|
|
179
90
|
|
|
180
|
-
// Handle Hebrew plural forms
|
|
181
91
|
if (lang === 'he') {
|
|
182
|
-
const
|
|
183
|
-
const form = count === 1 ?
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const hebrewPrefix = isRelative
|
|
187
|
-
? (seconds < 0 ? `${selectedLang.ago} ` : (seconds > 0 ? `${selectedLang.in} ` : ''))
|
|
92
|
+
const unit = getUnit(interval.label) as TimeUnit
|
|
93
|
+
const form = count === 1 ? unit.singular : unit.plural
|
|
94
|
+
const hePrefix = isRelative
|
|
95
|
+
? (seconds < 0 ? `${t.ago} ` : (seconds > 0 ? `${t.in} ` : ''))
|
|
188
96
|
: ''
|
|
189
97
|
|
|
190
98
|
if (interval.label === 'day' && seconds > 0) {
|
|
191
99
|
const hours = Math.floor((Math.abs(seconds) % 86400) / 3600)
|
|
192
|
-
const hourUnit =
|
|
100
|
+
const hourUnit = t.hour as TimeUnit
|
|
193
101
|
const hourForm = hours === 1 ? hourUnit.singular : hourUnit.plural
|
|
194
|
-
const
|
|
195
|
-
const
|
|
196
|
-
return `${
|
|
102
|
+
const main = count === 1 ? form : `${count} ${form}`
|
|
103
|
+
const hourPart = hours > 0 ? (hours === 1 ? ` ${hourForm}` : ` ${hours} ${hourForm}`) : ''
|
|
104
|
+
return `${hePrefix}${main}${hourPart}`
|
|
197
105
|
}
|
|
198
|
-
return `${
|
|
106
|
+
return `${hePrefix}${count === 1 ? form : `${count} ${form}`}`
|
|
199
107
|
}
|
|
200
108
|
|
|
201
|
-
|
|
202
|
-
const intervalLabel = getTimeUnit(interval.label) as string
|
|
109
|
+
const label = getUnit(interval.label) as string
|
|
203
110
|
if (interval.label === 'day' && seconds > 0) {
|
|
204
111
|
const hours = Math.floor((Math.abs(seconds) % 86400) / 3600)
|
|
205
|
-
const hourLabel = hours > 1 ? `${
|
|
206
|
-
return `${prefix}${count} ${
|
|
112
|
+
const hourLabel = hours > 1 ? `${t.hour}s` : t.hour as string
|
|
113
|
+
return `${prefix}${count} ${label}${hours > 0 ? ` ${hours} ${hourLabel}` : ''}${suffix}`
|
|
207
114
|
}
|
|
208
|
-
return `${prefix}${count} ${
|
|
115
|
+
return `${prefix}${count} ${label}${suffix}`
|
|
209
116
|
}
|
|
210
117
|
}
|
|
211
118
|
|
|
212
|
-
return
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
function getBrowserNavigatorLocale(): string {
|
|
216
|
-
if (typeof navigator !== 'object') { return 'en-US' }
|
|
217
|
-
return navigator.languages && navigator.languages.length
|
|
218
|
-
? navigator.languages[0]
|
|
219
|
-
: navigator.language
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Returns the active i18n locale if initialized, otherwise falls back to
|
|
224
|
-
* the browser's navigator locale. Used as the default for formatDate.
|
|
225
|
-
*/
|
|
226
|
-
function getActiveLocale(): string {
|
|
227
|
-
try {
|
|
228
|
-
const { locale } = getI18n().global
|
|
229
|
-
return typeof locale === 'string' ? locale : locale.value
|
|
230
|
-
} catch {
|
|
231
|
-
return getBrowserNavigatorLocale()
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Adjust a date for a specific timezone
|
|
237
|
-
* @param date The date to adjust
|
|
238
|
-
* @param timeZone The timezone to use (e.g., 'UTC', 'America/New_York')
|
|
239
|
-
* @returns Date parts with timezone adjustment applied
|
|
240
|
-
*/
|
|
241
|
-
export function handleTimezone(date: Date, intFmtOpt: Intl.DateTimeFormatOptions): Date {
|
|
242
|
-
// If timeZone is UTC, convert to UTC directly
|
|
243
|
-
if (intFmtOpt.timeZone === 'UTC') {
|
|
244
|
-
const utcDate = new Date(date.getTime())
|
|
245
|
-
utcDate.setMinutes(utcDate.getMinutes() + date.getTimezoneOffset())
|
|
246
|
-
return utcDate
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// For other timezones, use the Intl API
|
|
250
|
-
try {
|
|
251
|
-
// Always use en-US locale for parsing date parts to ensure Latin numerals
|
|
252
|
-
const formatter = new Intl.DateTimeFormat('en-US', {
|
|
253
|
-
...intFmtOpt,
|
|
254
|
-
month: 'numeric' // Force numeric month format
|
|
255
|
-
})
|
|
256
|
-
|
|
257
|
-
// Format the date in the target timezone
|
|
258
|
-
const formattedParts = formatter.formatToParts(date)
|
|
259
|
-
|
|
260
|
-
// Extract date components from formatted parts
|
|
261
|
-
const parts: Record<string, number> = {}
|
|
262
|
-
|
|
263
|
-
formattedParts.forEach((part) => {
|
|
264
|
-
if (part.type !== 'literal' && part.type !== 'timeZoneName') {
|
|
265
|
-
parts[part.type] = Number.parseInt(part.value, 10)
|
|
266
|
-
}
|
|
267
|
-
})
|
|
268
|
-
|
|
269
|
-
// Create a new date with these components
|
|
270
|
-
const adjustedDate = new Date(
|
|
271
|
-
parts.year,
|
|
272
|
-
(parts.month || 1) - 1, // Month is 0-based in JS
|
|
273
|
-
parts.day,
|
|
274
|
-
parts.hour || 0,
|
|
275
|
-
parts.minute || 0,
|
|
276
|
-
parts.second || 0
|
|
277
|
-
)
|
|
278
|
-
|
|
279
|
-
return adjustedDate
|
|
280
|
-
} catch (error) {
|
|
281
|
-
console.warn(`Error handling timezone ${intFmtOpt.timeZone}:`, error)
|
|
282
|
-
return date // Return original date on error
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
export function getDatePartsMap(date: Date, locale: Intl.LocalesArgument, intFmtOpt?: Intl.DateTimeFormatOptions) {
|
|
287
|
-
// Apply timezone adjustment if specified
|
|
288
|
-
const d = intFmtOpt?.timeZone ? handleTimezone(date, intFmtOpt) : date
|
|
289
|
-
|
|
290
|
-
// Use numeric formatting for year to ensure consistency across locales
|
|
291
|
-
const year = d.getFullYear().toString()
|
|
292
|
-
|
|
293
|
-
/// keep-sorted
|
|
294
|
-
return {
|
|
295
|
-
AmPm: d.toLocaleString(locale, { hour: 'numeric', hour12: true, minute: 'numeric' }).split(' ')[1],
|
|
296
|
-
DD: String(d.getDate()).padStart(2, '0'),
|
|
297
|
-
DDD: d.toLocaleString(locale, { weekday: 'short' }),
|
|
298
|
-
DDDD: d.toLocaleString(locale, { weekday: 'long' }),
|
|
299
|
-
HH: String(d.getHours()).padStart(2, '0'),
|
|
300
|
-
mm: String(d.getMinutes()).padStart(2, '0'),
|
|
301
|
-
MM: String(d.getMonth() + 1).padStart(2, '0'),
|
|
302
|
-
MMM: d.toLocaleString(locale, { month: 'short' }),
|
|
303
|
-
MMMM: d.toLocaleString(locale, { month: 'long' }),
|
|
304
|
-
ss: String(d.getSeconds()).padStart(2, '0'),
|
|
305
|
-
sss: String(d.getMilliseconds()).padStart(3, '0'),
|
|
306
|
-
|
|
307
|
-
// Always use Latin numerals for year to ensure consistency
|
|
308
|
-
YY: year.slice(-2),
|
|
309
|
-
YYYY: year,
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
// ? Avoid creating the date parts map on every call
|
|
314
|
-
const _datePartsMapNow = getDatePartsMap(new Date(), getBrowserNavigatorLocale())
|
|
315
|
-
|
|
316
|
-
// Sort tokens by length (longest first) to avoid partial replacements
|
|
317
|
-
const _orderedDateTokens = (
|
|
318
|
-
Object.keys(_datePartsMapNow).sort((a, b) => b.length - a.length)
|
|
319
|
-
) as (keyof typeof _datePartsMapNow)[]
|
|
320
|
-
|
|
321
|
-
// ? Avoid creating the token regex pattern on every call
|
|
322
|
-
// ? no longer creating the Regex Objs it in a loop
|
|
323
|
-
const _tokenRegExPattern = new RegExp(_orderedDateTokens.map(token => token).join('|'), 'g')
|
|
324
|
-
|
|
325
|
-
export interface FormatDateOptions extends Partial<Pick<Intl.DateTimeFormatOptions, 'hour12'>> {
|
|
326
|
-
format?: DateTimeAcceptedFormats
|
|
327
|
-
locale?: Intl.LocalesArgument
|
|
328
|
-
tz?: string
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Formats a date based on the provided format string, locale, and timezone.
|
|
333
|
-
* @param date The date to format (string or Date object).
|
|
334
|
-
* @param format The format string (default is 'DD.MM.YY').
|
|
335
|
-
* @returns Formatted date string.
|
|
336
|
-
*/
|
|
337
|
-
export function formatDate(date?: DateLike, format?: DateTimeAcceptedFormats): string
|
|
338
|
-
|
|
339
|
-
/**
|
|
340
|
-
* Formats a date based on the provided options.
|
|
341
|
-
* @param date The date to format (string or Date object).
|
|
342
|
-
* @param opts Options for formatting the date.
|
|
343
|
-
* @param opts.format The format string (default is 'DD.MM.YY').
|
|
344
|
-
* @param opts.locale The locale to use for formatting (default is browser's locale).
|
|
345
|
-
* @param opts.tz The timezone to use for formatting (default is local timezone).
|
|
346
|
-
* @returns Formatted date string.
|
|
347
|
-
*/
|
|
348
|
-
export function formatDate(date?: DateLike, opts?: FormatDateOptions): string
|
|
349
|
-
|
|
350
|
-
/**
|
|
351
|
-
* Formats a date based on the provided format string, locale, and timezone.
|
|
352
|
-
* @param date The date to format (string or Date object).
|
|
353
|
-
* @param formatOrOpts The format string or options object.
|
|
354
|
-
* @returns Formatted date string.
|
|
355
|
-
*/
|
|
356
|
-
export function formatDate(
|
|
357
|
-
date?: DateLike,
|
|
358
|
-
formatOrOpts?: DateTimeAcceptedFormats | FormatDateOptions,
|
|
359
|
-
): string {
|
|
360
|
-
let format: DateTimeAcceptedFormats | undefined
|
|
361
|
-
let locale: Intl.LocalesArgument | undefined
|
|
362
|
-
let timeZone: string | undefined
|
|
363
|
-
let rest: Partial<Pick<Intl.DateTimeFormatOptions, 'hour12'>> = {}
|
|
364
|
-
// Handle both overloads
|
|
365
|
-
if (typeof formatOrOpts === 'string') {
|
|
366
|
-
// First overload: format string directly
|
|
367
|
-
format = formatOrOpts
|
|
368
|
-
} else if (formatOrOpts && typeof formatOrOpts === 'object') {
|
|
369
|
-
// Second overload: options object
|
|
370
|
-
format = formatOrOpts.format
|
|
371
|
-
locale = formatOrOpts.locale
|
|
372
|
-
timeZone = formatOrOpts.tz
|
|
373
|
-
rest = formatOrOpts
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
if (!date) { return '' }
|
|
377
|
-
|
|
378
|
-
// Handle named format shortcuts before token replacement
|
|
379
|
-
if (format === 'ISO' || format === 'ISO8601') {
|
|
380
|
-
const d = typeof date === 'string' || typeof date === 'number' ? new Date(date) : date
|
|
381
|
-
return Number.isNaN(d.getTime()) ? '' : d.toISOString()
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
format = format || 'DD.MM.YY'
|
|
385
|
-
|
|
386
|
-
locale = locale || getActiveLocale()
|
|
387
|
-
try {
|
|
388
|
-
// Validate the date
|
|
389
|
-
const d = typeof date === 'string' || typeof date === 'number' ? new Date(date) : date
|
|
390
|
-
|
|
391
|
-
// Check if date is valid
|
|
392
|
-
if (Number.isNaN(d.getTime())) {
|
|
393
|
-
console.warn('Invalid date provided to formatDate:', date)
|
|
394
|
-
return ''
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// For more complex formats that need localization, use Intl.DateTimeFormat
|
|
398
|
-
/// keep-sorted
|
|
399
|
-
const intFmtOpt: Intl.DateTimeFormatOptions = {
|
|
400
|
-
day: 'numeric',
|
|
401
|
-
hour: '2-digit',
|
|
402
|
-
|
|
403
|
-
// Set default hour12 to true if not explicitly set
|
|
404
|
-
// hour12: true,
|
|
405
|
-
hour12: rest.hour12 === undefined ? true : rest.hour12,
|
|
406
|
-
minute: '2-digit',
|
|
407
|
-
month: 'long',
|
|
408
|
-
second: '2-digit',
|
|
409
|
-
timeZone, // Add timeZone if provided
|
|
410
|
-
weekday: 'long',
|
|
411
|
-
year: 'numeric',
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
const datePartsMap = getDatePartsMap(d, locale, intFmtOpt)
|
|
415
|
-
|
|
416
|
-
const formatter = new Intl.DateTimeFormat(locale, intFmtOpt)
|
|
417
|
-
|
|
418
|
-
const formattedParts = formatter.formatToParts(d)
|
|
419
|
-
const partsMap: Partial<Record<Intl.DateTimeFormatPartTypes, string>> = {}
|
|
420
|
-
|
|
421
|
-
formattedParts.forEach((part) => {
|
|
422
|
-
if (part.type !== 'literal') {
|
|
423
|
-
partsMap[part.type] = part.value
|
|
424
|
-
}
|
|
425
|
-
})
|
|
426
|
-
|
|
427
|
-
// Add localized formats to our map
|
|
428
|
-
if (partsMap.month) {
|
|
429
|
-
datePartsMap.MMM = partsMap.month.substring(0, 3)
|
|
430
|
-
datePartsMap.MMMM = partsMap.month
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
if (partsMap.weekday) {
|
|
434
|
-
datePartsMap.DDD = partsMap.weekday.substring(0, 3)
|
|
435
|
-
datePartsMap.DDDD = partsMap.weekday
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
if (partsMap.dayPeriod) {
|
|
439
|
-
datePartsMap.AmPm = partsMap.dayPeriod
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
// Process the format string by replacing each token with its value
|
|
443
|
-
return format.replace(
|
|
444
|
-
_tokenRegExPattern,
|
|
445
|
-
match => datePartsMap[match as keyof typeof datePartsMap]
|
|
446
|
-
)
|
|
447
|
-
} catch (error) {
|
|
448
|
-
console.warn(`Error formatting date: ${date} with format: ${format}`, error)
|
|
449
|
-
return ''
|
|
450
|
-
}
|
|
119
|
+
return t.justNow as string
|
|
451
120
|
}
|
|
452
|
-
export const fmtDate = formatDate
|