@webamoki/web-svelte 0.1.1 → 0.3.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/README.md +4 -55
- package/dist/components/form/FieldWrapper.svelte +6 -0
- package/dist/components/form/FieldWrapper.svelte.d.ts +5 -0
- package/dist/components/form/fields/ChoiceField.svelte +44 -0
- package/dist/components/form/fields/ChoiceField.svelte.d.ts +27 -0
- package/dist/components/form/fields/ChoiceMultiField.svelte +46 -0
- package/dist/components/form/fields/ChoiceMultiField.svelte.d.ts +27 -0
- package/dist/components/form/fields/WeekdayChoiceField.svelte +41 -0
- package/dist/components/form/fields/WeekdayChoiceField.svelte.d.ts +27 -0
- package/dist/components/form/fields/WeekdayChoiceMultiField.svelte +41 -0
- package/dist/components/form/fields/WeekdayChoiceMultiField.svelte.d.ts +27 -0
- package/dist/components/index.d.ts +7 -1
- package/dist/components/index.js +7 -1
- package/dist/components/showcase/CodeBlock.svelte +52 -0
- package/dist/components/showcase/CodeBlock.svelte.d.ts +30 -0
- package/dist/components/showcase/Container.svelte +13 -0
- package/dist/components/showcase/Container.svelte.d.ts +24 -0
- package/dist/components/showcase/Preview.svelte +6 -0
- package/dist/components/showcase/Preview.svelte.d.ts +26 -0
- package/dist/components/showcase/Sidebar.svelte +6 -0
- package/dist/components/showcase/Sidebar.svelte.d.ts +26 -0
- package/dist/components/showcase/SidebarLink.svelte +7 -0
- package/dist/components/showcase/SidebarLink.svelte.d.ts +20 -0
- package/dist/components/ui/choice/Choice.svelte +27 -0
- package/dist/components/ui/choice/Choice.svelte.d.ts +29 -0
- package/dist/components/ui/choice/ChoiceInternal.svelte +57 -0
- package/dist/components/ui/choice/ChoiceInternal.svelte.d.ts +34 -0
- package/dist/components/ui/choice/ChoiceMulti.svelte +55 -0
- package/dist/components/ui/choice/ChoiceMulti.svelte.d.ts +30 -0
- package/dist/components/ui/choice/WeekdayChoice.svelte +28 -0
- package/dist/components/ui/choice/WeekdayChoice.svelte.d.ts +13 -0
- package/dist/components/ui/choice/WeekdayChoiceMulti.svelte +29 -0
- package/dist/components/ui/choice/WeekdayChoiceMulti.svelte.d.ts +14 -0
- package/dist/highlight.d.ts +1 -0
- package/dist/highlight.js +9 -0
- package/dist/utils/datetime/index.d.ts +168 -0
- package/dist/utils/datetime/index.js +322 -0
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +1 -2
- package/package.json +7 -3
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { CalendarDate, DateFormatter, getDayOfWeek, getLocalTimeZone, startOfMonth, Time, toCalendarDate, today, toTime, ZonedDateTime } from '@internationalized/date';
|
|
2
|
+
import { type } from 'arktype';
|
|
3
|
+
import { map, range } from 'ramda';
|
|
4
|
+
const DEFAULT_TIME_ZONE = 'Europe/London';
|
|
5
|
+
const DEFAULT_LOCALE = 'en-GB';
|
|
6
|
+
// Day of the week
|
|
7
|
+
export const Days = [
|
|
8
|
+
'Monday',
|
|
9
|
+
'Tuesday',
|
|
10
|
+
'Wednesday',
|
|
11
|
+
'Thursday',
|
|
12
|
+
'Friday',
|
|
13
|
+
'Saturday',
|
|
14
|
+
'Sunday'
|
|
15
|
+
];
|
|
16
|
+
export const Day = type.enumerated(...Days);
|
|
17
|
+
const DayIndex = Object.fromEntries(Days.map((day, index) => [day, index]));
|
|
18
|
+
/** Gets the day index of the date */
|
|
19
|
+
function getDayIndex(date) {
|
|
20
|
+
// Always start 0 on Monday
|
|
21
|
+
return getDayOfWeek(date, DEFAULT_LOCALE, 'mon');
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Gets the day of the week for a given date.
|
|
25
|
+
* @param date - The date to get the day of the week for.
|
|
26
|
+
* @returns The day of the week
|
|
27
|
+
*/
|
|
28
|
+
export function getDayOfDate(date) {
|
|
29
|
+
return Days[getDayIndex(date)];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Checks if a given date is a specific day of the week.
|
|
33
|
+
* @param date - The date to check.
|
|
34
|
+
* @param dayOfWeek - The day of the week to check against.
|
|
35
|
+
* @returns True if the date is the specified day, false otherwise.
|
|
36
|
+
*/
|
|
37
|
+
export function isDateDay(date, dayOfWeek) {
|
|
38
|
+
const dateDay = getDayOfDate(date);
|
|
39
|
+
return dateDay === dayOfWeek;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Checks if a given date is today.
|
|
43
|
+
* @param date - The date to check.
|
|
44
|
+
* @returns True if the date is today, false otherwise.
|
|
45
|
+
*/
|
|
46
|
+
export function isDateToday(date, timezone) {
|
|
47
|
+
return today(timezone).compare(date) === 0;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Calculates the age from a date of birth.
|
|
51
|
+
* @param dob - The date of birth.
|
|
52
|
+
* @returns The age in years.
|
|
53
|
+
* @throws Error if the date of birth is in the future.
|
|
54
|
+
*/
|
|
55
|
+
export function ageFromDob(dob, timezone) {
|
|
56
|
+
const todayDate = today(timezone);
|
|
57
|
+
if (todayDate.compare(dob) < 0) {
|
|
58
|
+
throw new Error('Date of birth is in the future');
|
|
59
|
+
}
|
|
60
|
+
let years = todayDate.year - dob.year;
|
|
61
|
+
const monthDiff = todayDate.month - dob.month;
|
|
62
|
+
const dayDiff = todayDate.day - dob.day;
|
|
63
|
+
// Adjust years down if birthday hasn't occurred this year
|
|
64
|
+
if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) {
|
|
65
|
+
years--;
|
|
66
|
+
}
|
|
67
|
+
return years;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Gets the date of the next occurrence of a day of the week.
|
|
71
|
+
* @param dayOfWeek - The day of the week to get the next occurrence for.
|
|
72
|
+
* @param startDate - The date to check from. Inclusive.
|
|
73
|
+
* @returns The date of the next occurrence of the specified day.
|
|
74
|
+
*/
|
|
75
|
+
export function getNextDateOfDay(dayOfWeek, startDate) {
|
|
76
|
+
const dayIndex = DayIndex[dayOfWeek];
|
|
77
|
+
const startIndex = getDayIndex(startDate);
|
|
78
|
+
// Already on the day
|
|
79
|
+
if (startIndex === dayIndex)
|
|
80
|
+
return startDate;
|
|
81
|
+
// Calculate how many days to add to get to the next occurrence
|
|
82
|
+
const addition = (dayIndex - startIndex + 7) % 7;
|
|
83
|
+
return startDate.add({ days: addition });
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Gets the most recent occurrence of a day of the week.
|
|
87
|
+
* @param dayOfWeek - The day of the week
|
|
88
|
+
* @param startDate - The date to check from. Inclusive.
|
|
89
|
+
* @returns The most recent date for the specified day.
|
|
90
|
+
* @throws An error if the day of the week is invalid.
|
|
91
|
+
*/
|
|
92
|
+
export function getLastDateOfDay(dayOfWeek, startDate) {
|
|
93
|
+
const dayIndex = DayIndex[dayOfWeek];
|
|
94
|
+
const startIndex = getDayIndex(startDate);
|
|
95
|
+
// Already on the day
|
|
96
|
+
if (startIndex === dayIndex)
|
|
97
|
+
return startDate;
|
|
98
|
+
// Calculate how many days to subtract to get to the previous occurrence
|
|
99
|
+
const subtraction = (startIndex + 7 - dayIndex) % 7;
|
|
100
|
+
return startDate.subtract({ days: subtraction });
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Gets an array of the last dates of the day of the week.
|
|
104
|
+
* @param dayOfWeek - The day of the week.
|
|
105
|
+
* @param count - The number of dates to get.
|
|
106
|
+
* @param startDate - The date to check from. Inclusive.
|
|
107
|
+
* @returns The array of dates from oldest to most recent.
|
|
108
|
+
* @throws An error if the day of the week is invalid.
|
|
109
|
+
*/
|
|
110
|
+
export function getLastDatesOfDay(dayOfWeek, count, startDate) {
|
|
111
|
+
// Set up the array of dates
|
|
112
|
+
if (count < 1)
|
|
113
|
+
return [];
|
|
114
|
+
// Get the most recent date
|
|
115
|
+
const latestDate = getLastDateOfDay(dayOfWeek, startDate);
|
|
116
|
+
// Calculate all dates subtracted, oldest -> most recent
|
|
117
|
+
return map((i) => latestDate.subtract({ weeks: count - 1 - i }), range(0, count));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Gets an array of dates of the last few months (first day) from a date.
|
|
121
|
+
* @param count - The number of months to get.
|
|
122
|
+
* @param startDate - The date to start from (defaults to today).
|
|
123
|
+
* @returns The array of dates from oldest to most recent.
|
|
124
|
+
*/
|
|
125
|
+
export function getLastMonths(count, startDate) {
|
|
126
|
+
if (count < 1)
|
|
127
|
+
return [];
|
|
128
|
+
// Get the most recent date
|
|
129
|
+
const latestDate = startOfMonth(startDate);
|
|
130
|
+
// Calculate the previous dates
|
|
131
|
+
return map((i) => latestDate.subtract({ months: count - 1 - i }), range(0, count));
|
|
132
|
+
}
|
|
133
|
+
/* Intervals */
|
|
134
|
+
/**
|
|
135
|
+
* Checks if two time ranges overlap, boundaries are not considered overlapping.
|
|
136
|
+
* @param start1 - The start time of the first range.
|
|
137
|
+
* @param end1 - The end time of the first range.
|
|
138
|
+
* @param start2 - The start time of the second range.
|
|
139
|
+
* @param end2 - The end time of the second range.
|
|
140
|
+
* @returns True if the ranges overlap, false otherwise.
|
|
141
|
+
*/
|
|
142
|
+
export function checkOverlap(start1, end1, start2, end2) {
|
|
143
|
+
return start1.compare(end2) < 0 && start2.compare(end1) < 0;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Determines if the given dates are within the given duration of each other.
|
|
147
|
+
* @param date1 - The first date in order.
|
|
148
|
+
* @param date2 - The second date in order.
|
|
149
|
+
* @param duration - The duration to check against. Inclusive of boundaries.
|
|
150
|
+
* @returns True if the dates are within duration, false otherwise.
|
|
151
|
+
*/
|
|
152
|
+
export function datesWithin(date1, date2, duration) {
|
|
153
|
+
// reject invalid order
|
|
154
|
+
if (date1.compare(date2) > 0)
|
|
155
|
+
return false;
|
|
156
|
+
return date1.add(duration).compare(date2) >= 0;
|
|
157
|
+
}
|
|
158
|
+
const msPerWeek = 7 * 24 * 60 * 60 * 1000;
|
|
159
|
+
/**
|
|
160
|
+
* Calculates the difference in weeks between two dates.
|
|
161
|
+
* @param date1 - The first date in order.
|
|
162
|
+
* @param date2 - The second date in order.
|
|
163
|
+
*/
|
|
164
|
+
export function dateDiffWeeks(date1, date2) {
|
|
165
|
+
const date1Abs = date1.toDate(DEFAULT_TIME_ZONE).getTime();
|
|
166
|
+
const date2Abs = date2.toDate(DEFAULT_TIME_ZONE).getTime();
|
|
167
|
+
return Math.floor((date2Abs - date1Abs) / msPerWeek);
|
|
168
|
+
}
|
|
169
|
+
/* Formatting */
|
|
170
|
+
/* Day of the week*/
|
|
171
|
+
/**
|
|
172
|
+
* Formats a day of the week.
|
|
173
|
+
* @param day - The day of the week to format.
|
|
174
|
+
* @example "Monday" -> "Mon"
|
|
175
|
+
* @returns Formatted string of the day of the week.
|
|
176
|
+
*/
|
|
177
|
+
export function formatDayShort(day) {
|
|
178
|
+
// Use the first three letters of the day
|
|
179
|
+
return day.slice(0, 3);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Formats a day of the week.
|
|
183
|
+
* @param day - The day of the week to format.
|
|
184
|
+
* @example "Monday" -> "M"
|
|
185
|
+
* @returns Formatted letter of the day of the week.
|
|
186
|
+
*/
|
|
187
|
+
export function formatDayLetter(day) {
|
|
188
|
+
// Use the first letters of the day
|
|
189
|
+
return day.slice(0, 1);
|
|
190
|
+
}
|
|
191
|
+
/* Calendar Dates */
|
|
192
|
+
const FullDateFormatter = new DateFormatter(DEFAULT_LOCALE, {
|
|
193
|
+
day: 'numeric',
|
|
194
|
+
month: 'short',
|
|
195
|
+
year: 'numeric'
|
|
196
|
+
});
|
|
197
|
+
const ShortDateFormatter = new DateFormatter(DEFAULT_LOCALE, {
|
|
198
|
+
month: 'short',
|
|
199
|
+
day: 'numeric'
|
|
200
|
+
});
|
|
201
|
+
const MonthFormatter = new DateFormatter(DEFAULT_LOCALE, {
|
|
202
|
+
month: 'short',
|
|
203
|
+
year: '2-digit'
|
|
204
|
+
});
|
|
205
|
+
const NumFormatter = new DateFormatter(DEFAULT_LOCALE, {
|
|
206
|
+
day: '2-digit',
|
|
207
|
+
month: '2-digit',
|
|
208
|
+
year: 'numeric'
|
|
209
|
+
});
|
|
210
|
+
function formatDate(date, formatter) {
|
|
211
|
+
const nativeDate = date.toDate(getLocalTimeZone());
|
|
212
|
+
return formatter.format(nativeDate);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* @param date The CalendarDate object to format.
|
|
216
|
+
* @returns string of date in shortened format
|
|
217
|
+
* @example "Oct 5"
|
|
218
|
+
*/
|
|
219
|
+
export function formatDateShort(date) {
|
|
220
|
+
return formatDate(date, ShortDateFormatter);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* @param date The CalendarDate object to format.
|
|
224
|
+
* @returns The formatted date string.
|
|
225
|
+
* @example "5 Oct 2023"
|
|
226
|
+
*/
|
|
227
|
+
export function formatDateFull(date) {
|
|
228
|
+
return formatDate(date, FullDateFormatter);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* ISO format
|
|
232
|
+
* @param date The CalendarDate object to format.
|
|
233
|
+
* @returns The formatted date string in YYYY-MM-DD format.
|
|
234
|
+
* @example "2023-10-05"
|
|
235
|
+
*/
|
|
236
|
+
export function formatDateISO(date) {
|
|
237
|
+
return date.toString();
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* @param date The CalendarDate object to format.
|
|
241
|
+
* @returns The formatted date string in dd/mm/yyyy format.
|
|
242
|
+
* @example "05/10/2023"
|
|
243
|
+
*/
|
|
244
|
+
export function formatDateNum(date) {
|
|
245
|
+
return formatDate(date, NumFormatter);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Formats the month only.
|
|
249
|
+
* @param date - The date to format.
|
|
250
|
+
* @returns The formatted month string.
|
|
251
|
+
* @example "Oct"
|
|
252
|
+
*/
|
|
253
|
+
export function formatMonth(date) {
|
|
254
|
+
return formatDate(date, MonthFormatter);
|
|
255
|
+
}
|
|
256
|
+
/* Times */
|
|
257
|
+
// Pad number with zeroes to the left
|
|
258
|
+
function padNum(num, len) {
|
|
259
|
+
if (isNaN(num)) {
|
|
260
|
+
return '0'.repeat(len);
|
|
261
|
+
}
|
|
262
|
+
return num.toString().padStart(len, '0');
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Gives time in HH:MM format
|
|
266
|
+
* @param time
|
|
267
|
+
* @returns string of time in that format
|
|
268
|
+
*/
|
|
269
|
+
export function formatTimeShort(time) {
|
|
270
|
+
const hours = padNum(time.hour, 2);
|
|
271
|
+
const minutes = padNum(time.minute, 2);
|
|
272
|
+
return `${hours}:${minutes}`;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Gives time in HH:MM:SS format
|
|
276
|
+
* @param time
|
|
277
|
+
* @returns string of time in that format
|
|
278
|
+
*/
|
|
279
|
+
export function formatTimeFull(time) {
|
|
280
|
+
const hours = padNum(time.hour, 2);
|
|
281
|
+
const minutes = padNum(time.minute, 2);
|
|
282
|
+
const seconds = padNum(time.second, 2);
|
|
283
|
+
return `${hours}:${minutes}:${seconds}`;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Calculates the end time given a starting time and duration.
|
|
287
|
+
* @param timeStart starting time
|
|
288
|
+
* @param durationMinutes duration in minutes
|
|
289
|
+
* @returns end time in HH:MM format
|
|
290
|
+
*/
|
|
291
|
+
export function formatTimeEnd(timeStart, durationMinutes) {
|
|
292
|
+
const timeEnd = timeStart.add({ minutes: durationMinutes });
|
|
293
|
+
return formatTimeShort(timeEnd);
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Formats a full date and time.
|
|
297
|
+
* @param datetime The ZonedDateTime object to format.
|
|
298
|
+
* @returns The formatted date and time string.
|
|
299
|
+
* @example "05/10/2023 14:30:00"
|
|
300
|
+
*/
|
|
301
|
+
export function formatAbsolute(datetime) {
|
|
302
|
+
const date = toCalendarDate(datetime);
|
|
303
|
+
const time = toTime(datetime);
|
|
304
|
+
return `${formatDateNum(date)} ${formatTimeFull(time)}`;
|
|
305
|
+
}
|
|
306
|
+
/* State handling */
|
|
307
|
+
/**
|
|
308
|
+
* Unfreezes a CalendarDate object from a snapshot.
|
|
309
|
+
* @param raw - The snapshot of the CalendarDate object.
|
|
310
|
+
* @returns The unfrozen CalendarDate object.
|
|
311
|
+
*/
|
|
312
|
+
export function unfreezeDate(raw) {
|
|
313
|
+
return new CalendarDate(raw.year, raw.month, raw.day);
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Unfreezes a Time object from a snapshot.
|
|
317
|
+
* @param raw - The snapshot of the Time object.
|
|
318
|
+
* @returns The unfrozen Time object.
|
|
319
|
+
*/
|
|
320
|
+
export function unfreezeTime(raw) {
|
|
321
|
+
return new Time(raw.hour, raw.minute, raw.second, raw.millisecond);
|
|
322
|
+
}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * from './datetime/index.js';
|
package/dist/utils/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// Reexport your entry utils here
|
|
1
|
+
export * from './datetime/index.js';
|
package/package.json
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.3.1",
|
|
7
|
+
"license": "MIT",
|
|
7
8
|
"files": [
|
|
8
9
|
"dist",
|
|
9
10
|
"!dist/**/*.test.*",
|
|
@@ -49,6 +50,7 @@
|
|
|
49
50
|
"@tailwindcss/vite": "^4.0.0",
|
|
50
51
|
"@types/node": "^22",
|
|
51
52
|
"@types/ramda": "^0.31.1",
|
|
53
|
+
"@types/sorted-array-functions": "^1.3.3",
|
|
52
54
|
"arktype": "^2.1.22",
|
|
53
55
|
"clsx": "^2.1.1",
|
|
54
56
|
"eslint": "^9.22.0",
|
|
@@ -59,7 +61,7 @@
|
|
|
59
61
|
"prettier-plugin-svelte": "^3.3.3",
|
|
60
62
|
"prettier-plugin-tailwindcss": "^0.6.11",
|
|
61
63
|
"publint": "^0.3.2",
|
|
62
|
-
"
|
|
64
|
+
"shiki": "^3.13.0",
|
|
63
65
|
"svelte": "^5.0.0",
|
|
64
66
|
"svelte-check": "^4.0.0",
|
|
65
67
|
"sveltekit-superforms": "^2.27.1",
|
|
@@ -76,7 +78,9 @@
|
|
|
76
78
|
"svelte"
|
|
77
79
|
],
|
|
78
80
|
"dependencies": {
|
|
79
|
-
"formsnap": "^2.0.1"
|
|
81
|
+
"formsnap": "^2.0.1",
|
|
82
|
+
"ramda": "^0.31.3",
|
|
83
|
+
"sorted-array-functions": "^1.3.0"
|
|
80
84
|
},
|
|
81
85
|
"scripts": {
|
|
82
86
|
"dev": "vite dev",
|