@andrilla/mado-ui 1.0.2 → 1.0.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/dist/{client.cjs → client/components/index.js} +915 -1511
- package/dist/client/graphics/index.js +463 -0
- package/dist/{client.esm.js → client.js} +1044 -490
- package/dist/{index.cjs → components/index.js} +915 -1511
- package/dist/graphics/index.js +462 -0
- package/dist/hooks/index.js +174 -0
- package/dist/{mado-ui.esm.js → index.js} +1044 -490
- package/dist/types/index.ts +0 -0
- package/dist/utils/index.js +664 -0
- package/package.json +34 -8
|
File without changes
|
|
@@ -0,0 +1,664 @@
|
|
|
1
|
+
import { extendTailwindMerge } from "tailwind-merge";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/class-management.ts
|
|
4
|
+
/**
|
|
5
|
+
* ### Has Class
|
|
6
|
+
* - Returns a boolean based on whether the specified element has the specified class
|
|
7
|
+
* @param {HTMLElement} element Any HTML Element
|
|
8
|
+
* @param {string} className A string of any class to check for
|
|
9
|
+
* @returns {boolean} true if the specified element has the specified class, else false
|
|
10
|
+
*/
|
|
11
|
+
function hasClass(element, className) {
|
|
12
|
+
return element.classList.contains(className);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* ### Add Class
|
|
16
|
+
* - Adds the specified classes to the specified elements
|
|
17
|
+
* @param {Element|HTMLElement|HTMLElement[]|NodeList|string|undefined} elements An HTML Element, an array of HTML Elements, a Node List, a string (as a selector for a querySelector)
|
|
18
|
+
* @param {string|string[]} classList A string or an array of classes to add to each element
|
|
19
|
+
*/
|
|
20
|
+
function addClass(elements, classList) {
|
|
21
|
+
const elementsType = elements.constructor.name, elementsIsString = typeof elements === "string", classListType = classList.constructor.name, classListIsString = typeof classList === "string";
|
|
22
|
+
let elementList, classListGroup;
|
|
23
|
+
switch (elementsType) {
|
|
24
|
+
case "String":
|
|
25
|
+
if (elementsIsString) elementList = Array.from(document.querySelectorAll(elements));
|
|
26
|
+
break;
|
|
27
|
+
case "NodeList":
|
|
28
|
+
if (!elementsIsString) elementList = Array.from(elements);
|
|
29
|
+
break;
|
|
30
|
+
case "Array":
|
|
31
|
+
if (!elementsIsString) elementList = elements;
|
|
32
|
+
break;
|
|
33
|
+
default: if (elementsType.startsWith("HTML") && !elementsIsString) elementList = [elements];
|
|
34
|
+
}
|
|
35
|
+
switch (classListType) {
|
|
36
|
+
case "String":
|
|
37
|
+
if (classListIsString) if (classList.split(" ").length >= 2) classListGroup = classList.split(" ");
|
|
38
|
+
else classListGroup = [classList];
|
|
39
|
+
break;
|
|
40
|
+
case "Array":
|
|
41
|
+
if (!classListIsString) classListGroup = classList;
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
if (!elementList || elementList.length < 1) throw new Error(`Elements are invalid or undefined. elements: ${elements} → elementList: ${elementList}`);
|
|
45
|
+
if (!classListGroup || classListGroup.length < 1) throw new Error(`Class List is invalid or undefined. classList: ${classList} → classListGroup: ${classListGroup}`);
|
|
46
|
+
elementList.forEach((element) => classListGroup.forEach((classItem) => {
|
|
47
|
+
if (hasClass(element, classItem)) return;
|
|
48
|
+
element.classList.add(classItem);
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* ### Remove Class
|
|
53
|
+
* - Removes the specified classes from the specified elements
|
|
54
|
+
* @param {HTMLElement|HTMLElement[]|NodeList|string|undefined} elements An HTML Element, an array of HTML Elements, a Node List, a string (as a selector for a querySelector)
|
|
55
|
+
* @param {string|string[]} classList A string or an array of classes to remove from each element
|
|
56
|
+
*/
|
|
57
|
+
function removeClass(elements, classList) {
|
|
58
|
+
const elementsType = elements.constructor.name, elementsIsString = typeof elements === "string", classListType = classList.constructor.name, classListIsString = typeof classList === "string";
|
|
59
|
+
let elementList, classListGroup;
|
|
60
|
+
switch (elementsType) {
|
|
61
|
+
case "String":
|
|
62
|
+
if (elementsIsString) elementList = Array.from(document.querySelectorAll(elements));
|
|
63
|
+
break;
|
|
64
|
+
case "NodeList":
|
|
65
|
+
if (!elementsIsString) elementList = Array.from(elements);
|
|
66
|
+
break;
|
|
67
|
+
case "Array":
|
|
68
|
+
if (!elementsIsString) elementList = elements;
|
|
69
|
+
break;
|
|
70
|
+
default: if (elementsType.startsWith("HTML") && !elementsIsString) elementList = [elements];
|
|
71
|
+
}
|
|
72
|
+
switch (classListType) {
|
|
73
|
+
case "String":
|
|
74
|
+
if (classListIsString) if (classList.split(" ").length >= 2) classListGroup = classList.split(" ");
|
|
75
|
+
else classListGroup = [classList];
|
|
76
|
+
break;
|
|
77
|
+
case "Array":
|
|
78
|
+
if (!classListIsString) classListGroup = classList;
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
if (!elementList || elementList.length < 1) throw new Error(`Elements are invalid or undefined. elements: ${elements} → elementList: ${elementList}`);
|
|
82
|
+
if (!classListGroup || classListGroup.length < 1) throw new Error(`Class List is invalid or undefined. classList: ${classList} → classListGroup: ${classListGroup}`);
|
|
83
|
+
elementList.forEach((element) => classListGroup.forEach((classItem) => {
|
|
84
|
+
if (!hasClass(element, classItem)) return;
|
|
85
|
+
element.classList.remove(classItem);
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* ### Toggle Class
|
|
90
|
+
* - Toggles the specified classes on the specified elements
|
|
91
|
+
* @param {HTMLElement|HTMLElement[]|NodeList|string|undefined} elements An HTML Element, an array of HTML Elements, a Node List, a string (as a selector for a querySelector)
|
|
92
|
+
* @param {string|string[]} classList A string or an array of classes to toggle on each element
|
|
93
|
+
*/
|
|
94
|
+
function toggleClass(elements, classList) {
|
|
95
|
+
const elementsType = elements.constructor.name, elementsIsString = typeof elements === "string", classListType = classList.constructor.name, classListIsString = typeof classList === "string";
|
|
96
|
+
let elementList, classListGroup;
|
|
97
|
+
switch (elementsType) {
|
|
98
|
+
case "String":
|
|
99
|
+
if (elementsIsString) elementList = Array.from(document.querySelectorAll(elements));
|
|
100
|
+
break;
|
|
101
|
+
case "NodeList":
|
|
102
|
+
if (!elementsIsString) elementList = Array.from(elements);
|
|
103
|
+
break;
|
|
104
|
+
case "Array":
|
|
105
|
+
if (!elementsIsString) elementList = elements;
|
|
106
|
+
break;
|
|
107
|
+
default: if (elementsType.startsWith("HTML") && !elementsIsString) elementList = [elements];
|
|
108
|
+
}
|
|
109
|
+
switch (classListType) {
|
|
110
|
+
case "String":
|
|
111
|
+
if (classListIsString) if (classList.split(" ").length >= 2) classListGroup = classList.split(" ");
|
|
112
|
+
else classListGroup = [classList];
|
|
113
|
+
break;
|
|
114
|
+
case "Array":
|
|
115
|
+
if (!classListIsString) classListGroup = classList;
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
if (!elementList || elementList.length < 1) throw new Error(`Elements are invalid or undefined. elements: ${elements} → elementList: ${elementList}`);
|
|
119
|
+
if (!classListGroup || classListGroup.length < 1) throw new Error(`Class List is invalid or undefined. classList: ${classList} → classListGroup: ${classListGroup}`);
|
|
120
|
+
elementList.forEach((element) => classListGroup.forEach((classItem) => {
|
|
121
|
+
element.classList.toggle(classItem);
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region src/utils/custom-tailwind-merge.ts
|
|
127
|
+
const integerList = Array.from({ length: 100 }, (_, i) => `${i + 1}`);
|
|
128
|
+
const twMerge = extendTailwindMerge({ extend: { classGroups: {
|
|
129
|
+
animate: [{ animate: [
|
|
130
|
+
"bounce",
|
|
131
|
+
"double-spin",
|
|
132
|
+
"drop-in",
|
|
133
|
+
"flip",
|
|
134
|
+
"flip-again",
|
|
135
|
+
"grid-rows",
|
|
136
|
+
"heartbeat",
|
|
137
|
+
"ping",
|
|
138
|
+
"pulse",
|
|
139
|
+
"slide-up",
|
|
140
|
+
"spin",
|
|
141
|
+
"wave"
|
|
142
|
+
] }],
|
|
143
|
+
"animation-direction": [{ "animation-direction": [
|
|
144
|
+
"normal",
|
|
145
|
+
"reverse",
|
|
146
|
+
"alternate",
|
|
147
|
+
"alternate-reverse"
|
|
148
|
+
] }],
|
|
149
|
+
"animation-fill": [{ "animation-fill": [
|
|
150
|
+
"none",
|
|
151
|
+
"forwards",
|
|
152
|
+
"backwards",
|
|
153
|
+
"both"
|
|
154
|
+
] }],
|
|
155
|
+
"animation-iteration": [{ "animation-iteration": [...integerList, "infinite"] }],
|
|
156
|
+
"animation-state": [{ "animation-state": ["running", "paused"] }],
|
|
157
|
+
"grid-cols": [{ "grid-cols": ["0fr", "1fr"] }],
|
|
158
|
+
"grid-rows": [{ "grid-rows": ["0fr", "1fr"] }],
|
|
159
|
+
transition: ["transition-rows"]
|
|
160
|
+
} } });
|
|
161
|
+
function extendMadoTailwindMerge(configExtension) {
|
|
162
|
+
const extend = configExtension.extend || {};
|
|
163
|
+
const theme = extend.theme || {};
|
|
164
|
+
const color = "color" in theme ? theme.color : [];
|
|
165
|
+
const classGroups = extend.classGroups || {};
|
|
166
|
+
const themeRest = { ...theme };
|
|
167
|
+
if ("color" in themeRest) delete themeRest.color;
|
|
168
|
+
const extendRest = { ...extend };
|
|
169
|
+
delete extendRest.theme;
|
|
170
|
+
delete extendRest.classGroups;
|
|
171
|
+
return extendTailwindMerge({
|
|
172
|
+
extend: {
|
|
173
|
+
theme: {
|
|
174
|
+
color: [{ ui: [
|
|
175
|
+
"red",
|
|
176
|
+
"orange",
|
|
177
|
+
"yellow",
|
|
178
|
+
"green",
|
|
179
|
+
"sky-blue",
|
|
180
|
+
"blue",
|
|
181
|
+
"violet",
|
|
182
|
+
"magenta",
|
|
183
|
+
"purple",
|
|
184
|
+
"brown",
|
|
185
|
+
"grey",
|
|
186
|
+
"pink"
|
|
187
|
+
] }, ...color],
|
|
188
|
+
...themeRest
|
|
189
|
+
},
|
|
190
|
+
classGroups: {
|
|
191
|
+
animate: [{ animate: [
|
|
192
|
+
"bounce",
|
|
193
|
+
"double-spin",
|
|
194
|
+
"drop-in",
|
|
195
|
+
"flip",
|
|
196
|
+
"flip-again",
|
|
197
|
+
"grid-rows",
|
|
198
|
+
"heartbeat",
|
|
199
|
+
"ping",
|
|
200
|
+
"pulse",
|
|
201
|
+
"slide-up",
|
|
202
|
+
"spin",
|
|
203
|
+
"wave"
|
|
204
|
+
] }],
|
|
205
|
+
"animation-direction": [{ "animation-direction": [
|
|
206
|
+
"normal",
|
|
207
|
+
"reverse",
|
|
208
|
+
"alternate",
|
|
209
|
+
"alternate-reverse"
|
|
210
|
+
] }],
|
|
211
|
+
"animation-fill": [{ "animation-fill": [
|
|
212
|
+
"none",
|
|
213
|
+
"forwards",
|
|
214
|
+
"backwards",
|
|
215
|
+
"both"
|
|
216
|
+
] }],
|
|
217
|
+
"animation-iteration": [{ "animation-iteration": [...integerList, "infinite"] }],
|
|
218
|
+
"animation-state": [{ "animation-state": ["running", "paused"] }],
|
|
219
|
+
"grid-cols": [{ "grid-cols": ["0fr", "1fr"] }],
|
|
220
|
+
"grid-rows": [{ "grid-rows": ["0fr", "1fr"] }],
|
|
221
|
+
transition: ["transition-rows"],
|
|
222
|
+
...classGroups
|
|
223
|
+
},
|
|
224
|
+
...extendRest
|
|
225
|
+
},
|
|
226
|
+
...configExtension
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
//#endregion
|
|
231
|
+
//#region src/utils/get-date.ts
|
|
232
|
+
/** The current date as a Date object */
|
|
233
|
+
const d = /* @__PURE__ */ new Date();
|
|
234
|
+
/** The current minute of the current hour */
|
|
235
|
+
const minutes = d.getMinutes();
|
|
236
|
+
/** The current year */
|
|
237
|
+
const year = d.getFullYear();
|
|
238
|
+
/** An array of the names of month in order */
|
|
239
|
+
const monthNamesList = [
|
|
240
|
+
"January",
|
|
241
|
+
"February",
|
|
242
|
+
"March",
|
|
243
|
+
"April",
|
|
244
|
+
"May",
|
|
245
|
+
"June",
|
|
246
|
+
"July",
|
|
247
|
+
"August",
|
|
248
|
+
"September",
|
|
249
|
+
"October",
|
|
250
|
+
"November",
|
|
251
|
+
"December"
|
|
252
|
+
];
|
|
253
|
+
/** An array of the names of the days of the week in order */
|
|
254
|
+
const weekdayNamesList = [
|
|
255
|
+
"Sunday",
|
|
256
|
+
"Monday",
|
|
257
|
+
"Tuesday",
|
|
258
|
+
"Wednesday",
|
|
259
|
+
"Thursday",
|
|
260
|
+
"Friday",
|
|
261
|
+
"Saturday"
|
|
262
|
+
];
|
|
263
|
+
/** The name of the current month */
|
|
264
|
+
const currentMonthName = getMonthName();
|
|
265
|
+
/** The name of the current day of the week */
|
|
266
|
+
const currentWeekdayName = getWeekdayName();
|
|
267
|
+
/**
|
|
268
|
+
* ### Days In Month
|
|
269
|
+
* - Returns the number of days in the specified month.
|
|
270
|
+
* @param {Date} date A Date object representing the month to get the number of days for. (Preset to the current date)
|
|
271
|
+
* @returns {number} The number of days in the specified month.
|
|
272
|
+
*/
|
|
273
|
+
function daysInMonth(date = d) {
|
|
274
|
+
const selectedYear = date.getFullYear(), selectedMonth = date.getMonth() + 1;
|
|
275
|
+
return new Date(selectedYear, selectedMonth, 0).getDate();
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* ### First of Month
|
|
279
|
+
* - Returns the first day of the specified month.
|
|
280
|
+
* @param {Date} date A Date object representing the month to get the first day for. (Preset to current date)
|
|
281
|
+
* @returns {Date} A Date object of the given month, with the first day.
|
|
282
|
+
*/
|
|
283
|
+
function firstOfMonth(date = d) {
|
|
284
|
+
return new Date(date.getFullYear(), date.getMonth(), 1);
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* ### Get Date
|
|
288
|
+
* - Returns the date with two digits
|
|
289
|
+
* @param {number|Date} date The date to get date
|
|
290
|
+
* @returns {string} The date with two digits
|
|
291
|
+
*/
|
|
292
|
+
function getDate(date = d) {
|
|
293
|
+
if (typeof date !== "number") date = date.getDate();
|
|
294
|
+
let formattedDate = date.toString();
|
|
295
|
+
if (formattedDate.length === 1) formattedDate = `0${formattedDate}`;
|
|
296
|
+
return formattedDate;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* ### Get Hours
|
|
300
|
+
* - Returns the hours with two digits
|
|
301
|
+
* @param {number|Date} hours The date to get hours
|
|
302
|
+
* @returns {string} The hours with two digits
|
|
303
|
+
*/
|
|
304
|
+
function getHours(hours = d) {
|
|
305
|
+
if (typeof hours !== "number") hours = hours.getHours();
|
|
306
|
+
let formattedHours = hours.toString();
|
|
307
|
+
if (formattedHours.length === 1) formattedHours = `0${formattedHours}`;
|
|
308
|
+
return formattedHours;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* ### Get Hours in 12
|
|
312
|
+
* - Returns the hour based on the specified 24 hour value in a 12 hour format
|
|
313
|
+
* @param {number|Date} hour The hour to be converted to 12 hour format
|
|
314
|
+
* @returns {number} The hour in a 12 hour format
|
|
315
|
+
*/
|
|
316
|
+
function getHoursIn12(hour = d) {
|
|
317
|
+
if (typeof hour !== "number") hour = hour.getHours();
|
|
318
|
+
if (hour > 12) return hour - 12;
|
|
319
|
+
return hour;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* ### Get Meridian from Hour
|
|
323
|
+
* - Returns either 'pm' or 'am' based on the specified 24 hour value
|
|
324
|
+
* @param {number|Date} hour The hour to get the meridian from
|
|
325
|
+
* @returns {'am'|'pm'} The meridian for the given hour
|
|
326
|
+
*/
|
|
327
|
+
function getMeridianFromHour(hour = d) {
|
|
328
|
+
if (typeof hour !== "number") hour = hour.getHours();
|
|
329
|
+
if (hour >= 12) return "pm";
|
|
330
|
+
return "am";
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* ### Get Milliseconds
|
|
334
|
+
* - Returns the milliseconds with two digits
|
|
335
|
+
* @param {number|Date} milliseconds The date to get milliseconds
|
|
336
|
+
* @returns {string} The milliseconds with two digits
|
|
337
|
+
*/
|
|
338
|
+
function getMilliseconds(milliseconds = d) {
|
|
339
|
+
if (typeof milliseconds !== "number") milliseconds = milliseconds.getMilliseconds();
|
|
340
|
+
let formattedMilliseconds = minutes.toString();
|
|
341
|
+
if (formattedMilliseconds.length === 1) formattedMilliseconds = `0${formattedMilliseconds}`;
|
|
342
|
+
return formattedMilliseconds;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* ### Get Minutes
|
|
346
|
+
* - Returns the minutes with two digits
|
|
347
|
+
* @param {number|Date} minutes The date to get minutes
|
|
348
|
+
* @returns {string} The minutes with two digits
|
|
349
|
+
*/
|
|
350
|
+
function getMinutes(minutes = d) {
|
|
351
|
+
if (typeof minutes !== "number") minutes = minutes.getMinutes();
|
|
352
|
+
let formattedMinutes = minutes.toString();
|
|
353
|
+
if (formattedMinutes.length === 1) formattedMinutes = `0${formattedMinutes}`;
|
|
354
|
+
return formattedMinutes;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* ### Get Month
|
|
358
|
+
* - Returns the month with two digits
|
|
359
|
+
* @param {number|Date} month The date to get month
|
|
360
|
+
* @returns {string} The month with two digits
|
|
361
|
+
*/
|
|
362
|
+
function getMonth(month = d) {
|
|
363
|
+
if (typeof month !== "number") month = month.getMonth() + 1;
|
|
364
|
+
let formattedMonth = month.toString();
|
|
365
|
+
if (formattedMonth.length === 1) formattedMonth = `0${formattedMonth}`;
|
|
366
|
+
return formattedMonth;
|
|
367
|
+
}
|
|
368
|
+
function getMonthIndexFromName(name) {
|
|
369
|
+
return monthNamesList.findIndex((monthName) => monthName === name);
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* ### Get Month Name
|
|
373
|
+
* - Returns the name of the specified month
|
|
374
|
+
* @param {Date} date A Date object representing the month to get the name of the month from. (Preset to the current date)
|
|
375
|
+
* @returns {MonthName} The name of the specified month
|
|
376
|
+
*/
|
|
377
|
+
function getMonthName(date = d) {
|
|
378
|
+
if (typeof date === "number") return monthNamesList[date];
|
|
379
|
+
return monthNamesList[date.getMonth()];
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* ### Get Next Month
|
|
383
|
+
* - Returns the number of the following month from the specified month
|
|
384
|
+
* @param {Date} date The Date object representing the month to get the following month from (Preset to current date)
|
|
385
|
+
* @returns {number} The indexed month of the following month
|
|
386
|
+
*/
|
|
387
|
+
function getNextMonth(date = d) {
|
|
388
|
+
const givenMonth = date.getMonth();
|
|
389
|
+
return givenMonth === 11 ? 0 : givenMonth + 1;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* ### Get Previous Month
|
|
393
|
+
* - Returns the number of the previous month from the specified month
|
|
394
|
+
* @param {Date} date The Date object representing the month to get the previous month from (Preset to current date)
|
|
395
|
+
* @returns {number} The indexed month of the previous month
|
|
396
|
+
*/
|
|
397
|
+
function getPreviousMonth(date = d) {
|
|
398
|
+
const givenMonth = date.getMonth();
|
|
399
|
+
return givenMonth === 0 ? 11 : givenMonth - 1;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* ### Get Seconds
|
|
403
|
+
* - Returns the seconds with two digits
|
|
404
|
+
* @param {number|Date} seconds The date to get seconds
|
|
405
|
+
* @returns {string} The seconds with two digits
|
|
406
|
+
*/
|
|
407
|
+
function getSeconds(seconds = d) {
|
|
408
|
+
if (typeof seconds !== "number") seconds = seconds.getSeconds();
|
|
409
|
+
let formattedSeconds = seconds.toString();
|
|
410
|
+
if (formattedSeconds.length === 1) formattedSeconds = `0${formattedSeconds}`;
|
|
411
|
+
return formattedSeconds;
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* ### Get User Readable Date
|
|
415
|
+
* - Returns a string of the current date in a user-friendly way
|
|
416
|
+
* - Includes `'Yesterday'`, '`Today'`, and `'Tomorrow'`
|
|
417
|
+
* @param date (default: `new Date()`)
|
|
418
|
+
* @returns {'Today'|'Tomorrow'|'Yesterday'|string} `'weekday, month day, year'` | `'Yesterday'` | `'Today'` | `'Tomorrow'`
|
|
419
|
+
*/
|
|
420
|
+
function getUserReadableDate(date = d) {
|
|
421
|
+
const dateTime = date.getTime();
|
|
422
|
+
const today = /* @__PURE__ */ new Date();
|
|
423
|
+
if (dateTime === today.getTime()) return "Today";
|
|
424
|
+
if (dateTime === (/* @__PURE__ */ new Date(today.getDate() - 1)).getTime()) return "Yesterday";
|
|
425
|
+
if (dateTime === new Date(today.getDate() + 1).getTime()) return "Tomorrow";
|
|
426
|
+
const thisYear = today.getFullYear();
|
|
427
|
+
return toFullDateString(date, {
|
|
428
|
+
weekday: "code",
|
|
429
|
+
year: !(date.getFullYear() === thisYear)
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* ### Get Weekday Name
|
|
434
|
+
* - Returns the weekday name of the specified day
|
|
435
|
+
* @param {number | Date} weekday A Date object or number representing the day to get the weekday name from. (Preset to the current date)
|
|
436
|
+
* @returns {WeekdayName} The name of the specified weekday
|
|
437
|
+
*/
|
|
438
|
+
function getWeekdayName(weekday = d) {
|
|
439
|
+
if (typeof weekday === "number") return weekdayNamesList[weekday];
|
|
440
|
+
return weekdayNamesList[weekday.getDay()];
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* ### Get Years in Range
|
|
444
|
+
* - Returns an array of years in between the specified minimum and maximum years
|
|
445
|
+
* @param {number} minYear The minimum year
|
|
446
|
+
* @param {number} maxYear The maximum year
|
|
447
|
+
* @returns {number[]} Array of years
|
|
448
|
+
*/
|
|
449
|
+
function getYearsInRange(minYear = 0, maxYear = year) {
|
|
450
|
+
const yearList = [];
|
|
451
|
+
for (let selectedYear = minYear; selectedYear <= maxYear; selectedYear++) yearList.push(selectedYear);
|
|
452
|
+
return yearList;
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* ### To Full Date String
|
|
456
|
+
* - Returns a formatted string to display the date
|
|
457
|
+
* @param {Date} date (default: `new Date()`)
|
|
458
|
+
* @param {ToFullDateStringOptionsProps} options Change how to display the weekday, month name, day of the month, and year.
|
|
459
|
+
* @returns {string} '`weekday`, `month` `day`, `year`'
|
|
460
|
+
*/
|
|
461
|
+
function toFullDateString(date = d, options) {
|
|
462
|
+
let weekdayName = getWeekdayName(date), monthName = getMonthName(date), dayOfMonth = date.getDate(), year = date.getFullYear().toString();
|
|
463
|
+
if (options) {
|
|
464
|
+
const includesWeekday = options.weekday !== false, includesDay = options.day !== false, includesMonth = options.month !== false, includesYear = options.year !== false;
|
|
465
|
+
if (includesWeekday) {
|
|
466
|
+
if (options.weekday === "code") weekdayName = weekdayName.slice(0, 3);
|
|
467
|
+
if (includesMonth || includesDay || includesYear) weekdayName += ", ";
|
|
468
|
+
} else weekdayName = "";
|
|
469
|
+
if (includesMonth) {
|
|
470
|
+
if (options.month === "code") monthName = monthName.slice(0, 3);
|
|
471
|
+
if (includesDay) monthName += " ";
|
|
472
|
+
} else monthName = "";
|
|
473
|
+
if (!includesDay) dayOfMonth = "";
|
|
474
|
+
if (includesYear) {
|
|
475
|
+
if (options.year === "code") year = year.slice(-2);
|
|
476
|
+
if (includesMonth || includesDay) year = ", " + year;
|
|
477
|
+
} else year = "";
|
|
478
|
+
}
|
|
479
|
+
return weekdayName + monthName + dayOfMonth + year;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* ### Get User Readable Date From Timestampz
|
|
483
|
+
* - Returns a string of the current date in a user-friendly way
|
|
484
|
+
* - Includes `'Yesterday'`, '`Today'`, and `'Tomorrow'`
|
|
485
|
+
* @param string
|
|
486
|
+
* @returns {'Today'|'Tomorrow'|'Yesterday'|string} `'weekday, month day, year'` | `'Yesterday'` | `'Today'` | `'Tomorrow'`
|
|
487
|
+
*/
|
|
488
|
+
function getUserReadableDateFromTimestampz(timestampz) {
|
|
489
|
+
const [date, time] = timestampz.split("T") || [];
|
|
490
|
+
const [year, month, day] = date?.split("-").map((string) => Number(string)) || [];
|
|
491
|
+
const [hms, _timezone] = time?.includes("+") ? time?.split("+") : time?.split("-") || [];
|
|
492
|
+
const [hours, minutes, seconds] = hms?.split(":").map((string) => Number(string)) || [];
|
|
493
|
+
return getUserReadableDate(new Date(year, month - 1, day, hours, minutes, seconds));
|
|
494
|
+
}
|
|
495
|
+
function getLocalTime(time) {
|
|
496
|
+
const date = /* @__PURE__ */ new Date(), [hours, minutes] = typeof time === "string" ? time.split(":") : time;
|
|
497
|
+
const timezone = getTimezone();
|
|
498
|
+
console.log(timezone);
|
|
499
|
+
date.setUTCHours(Number(hours));
|
|
500
|
+
date.setMinutes(Number(minutes));
|
|
501
|
+
return date.toLocaleTimeString([], {
|
|
502
|
+
hour: "numeric",
|
|
503
|
+
minute: "2-digit",
|
|
504
|
+
hour12: true
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
function getTimezone() {
|
|
508
|
+
const date = /* @__PURE__ */ new Date();
|
|
509
|
+
const timezonePart = Intl.DateTimeFormat("en-US", { timeZoneName: "short" }).formatToParts(date).find((part) => part.type === "timeZoneName");
|
|
510
|
+
return timezonePart ? timezonePart.value : "";
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
//#endregion
|
|
514
|
+
//#region src/utils/math.ts
|
|
515
|
+
function easeOutExpo(time, start, end, duration) {
|
|
516
|
+
return time == duration ? start + end : end * (-Math.pow(2, -10 * time / duration) + 1) + start;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
//#endregion
|
|
520
|
+
//#region src/utils/regex.ts
|
|
521
|
+
const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
|
522
|
+
/**
|
|
523
|
+
* # Is Email
|
|
524
|
+
* Checks whether the specified string is in email format
|
|
525
|
+
*/
|
|
526
|
+
function isEmail(email) {
|
|
527
|
+
return emailRegex.test(email);
|
|
528
|
+
}
|
|
529
|
+
const telRegex = /(?:\+1\s|1\s|)?\d{3}\.\d{3}\.\d{4}|(?:\+1\s|1\s|)?\d{3}-\d{3}-\d{4}|(?:\+1\s|1\s|)?\(\d{3}\) \d{3}-\d{4}|(?:\+1\s|1\s|\+1|1|)?\d{10}/;
|
|
530
|
+
/**
|
|
531
|
+
* # Is Phone Number
|
|
532
|
+
* Checks whether the specified string is in phone number format
|
|
533
|
+
*/
|
|
534
|
+
function isPhoneNumber(tel) {
|
|
535
|
+
return telRegex.test(tel);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
//#endregion
|
|
539
|
+
//#region src/utils/string-manipulation.ts
|
|
540
|
+
/**
|
|
541
|
+
* # Format Phone Number
|
|
542
|
+
* Converts any string containing at least 10 numbers to a formatted phone number
|
|
543
|
+
* @param {string} phoneNumber
|
|
544
|
+
* @param options
|
|
545
|
+
* @property {string} `countryCode`
|
|
546
|
+
* @property {'continuous' | 'dot' | 'hyphenated' | 'none' | 'space' | 'standard'} `format`
|
|
547
|
+
*
|
|
548
|
+
* Input: a555b555c5555d
|
|
549
|
+
*
|
|
550
|
+
* @example
|
|
551
|
+
* format: 'continuous'
|
|
552
|
+
* countryCode: '1'
|
|
553
|
+
* returns: +1 5555555555
|
|
554
|
+
*
|
|
555
|
+
* @example
|
|
556
|
+
* format: 'dot'
|
|
557
|
+
* returns: 555.555.5555
|
|
558
|
+
*
|
|
559
|
+
* @example
|
|
560
|
+
* format: 'hyphenated'
|
|
561
|
+
* returns: 555-555-5555
|
|
562
|
+
*
|
|
563
|
+
* @example
|
|
564
|
+
* format: 'none'
|
|
565
|
+
* countryCode: '1'
|
|
566
|
+
* returns: +1 a555b555c5555d
|
|
567
|
+
*
|
|
568
|
+
* @example
|
|
569
|
+
* format: 'space'
|
|
570
|
+
* returns: 555 555 5555
|
|
571
|
+
*
|
|
572
|
+
* @example
|
|
573
|
+
* format: 'standard' (default)
|
|
574
|
+
* returns: (555) 555-5555
|
|
575
|
+
*
|
|
576
|
+
* @returns {string} string formatted
|
|
577
|
+
*/
|
|
578
|
+
function formatPhoneNumber(phoneNumber, options) {
|
|
579
|
+
const format = options?.format || "standard";
|
|
580
|
+
if (format !== "none") phoneNumber = phoneNumber.replace(/\D/g, "").slice(-10);
|
|
581
|
+
switch (format) {
|
|
582
|
+
case "dot":
|
|
583
|
+
phoneNumber = phoneNumber.split("").map((char, index) => {
|
|
584
|
+
if (index === 2) return `${char}.`;
|
|
585
|
+
if (index === 5) return `${char}.`;
|
|
586
|
+
return char;
|
|
587
|
+
}).join("");
|
|
588
|
+
break;
|
|
589
|
+
case "hyphenated":
|
|
590
|
+
phoneNumber = phoneNumber.split("").map((char, index) => {
|
|
591
|
+
if (index === 2) return `${char}-`;
|
|
592
|
+
if (index === 5) return `${char}-`;
|
|
593
|
+
return char;
|
|
594
|
+
}).join("");
|
|
595
|
+
break;
|
|
596
|
+
case "space":
|
|
597
|
+
phoneNumber = phoneNumber.split("").map((char, index) => {
|
|
598
|
+
if (index === 2) return `${char} `;
|
|
599
|
+
if (index === 5) return `${char} `;
|
|
600
|
+
return char;
|
|
601
|
+
}).join("");
|
|
602
|
+
break;
|
|
603
|
+
case "standard": phoneNumber = phoneNumber.split("").map((char, index) => {
|
|
604
|
+
if (index === 0) return `(${char}`;
|
|
605
|
+
if (index === 2) return `${char}) `;
|
|
606
|
+
if (index === 5) return `${char}-`;
|
|
607
|
+
return char;
|
|
608
|
+
}).join("");
|
|
609
|
+
}
|
|
610
|
+
return `${options?.countryCode ? `+${options?.countryCode} ` : ""}` + phoneNumber;
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* ### Split Camel Case
|
|
614
|
+
* - Separates a camel case string with a joiner (default: ' ')
|
|
615
|
+
* @param {string} string
|
|
616
|
+
* @returns {string} string
|
|
617
|
+
*/
|
|
618
|
+
function splitCamelCase(string, joiner = " ") {
|
|
619
|
+
if (string[0].match(/[A-Z0-9]/) || string.includes(" ")) return string;
|
|
620
|
+
let lastChar = "";
|
|
621
|
+
return string.split("").map((char) => {
|
|
622
|
+
let returnedString = char;
|
|
623
|
+
if (char.match(/[A-Z0-9]/)) returnedString = ` ${char}`;
|
|
624
|
+
if (lastChar.match(/[0-9]/) && char.match(/[0-9]/)) returnedString = char;
|
|
625
|
+
lastChar = char;
|
|
626
|
+
return returnedString;
|
|
627
|
+
}).join(joiner);
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* ### To Camel Case
|
|
631
|
+
* - Converts any string to camel case based on spaces
|
|
632
|
+
* - Eliminates no letter-number characters
|
|
633
|
+
* @param {string} string
|
|
634
|
+
* @returns {string} string
|
|
635
|
+
*/
|
|
636
|
+
function toCamelCase(string, delimiter = " ") {
|
|
637
|
+
if (typeof string !== "string") return string;
|
|
638
|
+
return string.toLowerCase().replace(/[^a-z0-9]/gi, delimiter).split(delimiter).map((str, index) => index === 0 ? str : str.substring(0, 1).toUpperCase() + str.substring(1, str.length).toLowerCase()).join("");
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* # To Lower Case
|
|
642
|
+
* Converts a string to lowercase, and offers easy string replacements for creating snake case, kebab case, or your own.
|
|
643
|
+
* @param str - The string to convert to lowercase.
|
|
644
|
+
* @param options - Configuration options.
|
|
645
|
+
* @param options[0] - The delimiter to split the string. Defaults to space.
|
|
646
|
+
* @param options[1] - The string to join the parts back together. Defaults to space.
|
|
647
|
+
* @returns The lowercase version of the input string, with the replacements, if provided.
|
|
648
|
+
*/
|
|
649
|
+
function toLowerCase(str, [delimiter, joiner]) {
|
|
650
|
+
return str.toLowerCase().replaceAll(delimiter || " ", joiner || " ");
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* ### To Title Case
|
|
654
|
+
* - Converts any string to title case based on spaces
|
|
655
|
+
* @param {string} string
|
|
656
|
+
* @returns {string} string
|
|
657
|
+
*/
|
|
658
|
+
function toTitleCase(string, delimiter = " ") {
|
|
659
|
+
if (typeof string !== "string") return string;
|
|
660
|
+
return string.toLowerCase().split(delimiter).map((str) => str.substring(0, 1).toUpperCase() + str.substring(1, str.length).toLowerCase()).join(" ");
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
//#endregion
|
|
664
|
+
export { addClass, currentMonthName, currentWeekdayName, daysInMonth, easeOutExpo, emailRegex, extendMadoTailwindMerge, firstOfMonth, formatPhoneNumber, getDate, getHours, getHoursIn12, getLocalTime, getMeridianFromHour, getMilliseconds, getMinutes, getMonth, getMonthIndexFromName, getMonthName, getNextMonth, getPreviousMonth, getSeconds, getTimezone, getUserReadableDate, getUserReadableDateFromTimestampz, getWeekdayName, getYearsInRange, hasClass, isEmail, isPhoneNumber, monthNamesList, removeClass, splitCamelCase, telRegex, toCamelCase, toFullDateString, toLowerCase, toTitleCase, toggleClass, twMerge, weekdayNamesList };
|