@getmicdrop/svelte-components 5.18.2 → 5.20.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/dist/base.css +18 -0
- package/dist/calendar/Calendar/MiniMonthCalendar.svelte +10 -8
- package/dist/calendar/Calendar/MiniMonthCalendar.svelte.d.ts.map +1 -1
- package/dist/components/Heading.svelte +8 -2
- package/dist/components/Heading.svelte.d.ts +1 -0
- package/dist/components/Heading.svelte.d.ts.map +1 -1
- package/dist/components/Text.svelte +13 -2
- package/dist/components/Text.svelte.d.ts +2 -1
- package/dist/components/Text.svelte.d.ts.map +1 -1
- package/dist/constants/formOptions.d.ts +2 -5
- package/dist/constants/formOptions.d.ts.map +1 -1
- package/dist/constants/formOptions.js +6 -6
- package/dist/constants/formOptions.spec.js +2 -7
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -2
- package/dist/patterns/forms/FormSection.svelte +2 -1
- package/dist/patterns/forms/FormSection.svelte.d.ts +2 -0
- package/dist/patterns/forms/FormSection.svelte.d.ts.map +1 -1
- package/dist/patterns/layout/SidebarTestWrapper.svelte.d.ts +1 -1
- package/dist/patterns/navigation/Header.svelte +3 -3
- package/dist/primitives/Input/Select.svelte +1 -1
- package/dist/primitives/Pagination/DotIndicator.svelte +66 -0
- package/dist/primitives/Pagination/DotIndicator.svelte.d.ts +18 -0
- package/dist/primitives/Pagination/DotIndicator.svelte.d.ts.map +1 -0
- package/dist/primitives/index.d.ts +1 -0
- package/dist/primitives/index.js +1 -0
- package/dist/recipes/inputs/phoneInput/CountrySelector.svelte +1 -1
- package/dist/recipes/modals/FeedbackModal.svelte +205 -0
- package/dist/recipes/modals/FeedbackModal.svelte.d.ts +24 -0
- package/dist/recipes/modals/FeedbackModal.svelte.d.ts.map +1 -0
- package/dist/recipes/modals/index.d.ts +1 -0
- package/dist/recipes/modals/index.js +1 -0
- package/dist/schemas/event.d.ts +4 -4
- package/dist/schemas/order.d.ts +2 -2
- package/dist/schemas/promo.d.ts +4 -4
- package/dist/services/event.service.d.ts +11 -0
- package/dist/services/event.service.d.ts.map +1 -0
- package/dist/services/event.service.js +64 -0
- package/dist/services/event.service.spec.d.ts +2 -0
- package/dist/services/event.service.spec.d.ts.map +1 -0
- package/dist/services/event.service.spec.js +168 -0
- package/dist/services/{ShowService.d.ts → show.service.d.ts} +1 -1
- package/dist/services/show.service.d.ts.map +1 -0
- package/dist/services/show.service.js +115 -0
- package/dist/services/show.service.spec.d.ts +2 -0
- package/dist/services/show.service.spec.d.ts.map +1 -0
- package/dist/services/show.service.spec.js +242 -0
- package/dist/tailwind/preset.cjs +5 -0
- package/dist/tailwind/preset.d.cts +2 -0
- package/dist/tailwind/preset.d.cts.map +1 -1
- package/dist/tokens/__tests__/spacing.test.js +2 -2
- package/dist/tokens/base-resets.css +124 -0
- package/dist/tokens/spacing.d.ts +2 -0
- package/dist/tokens/spacing.d.ts.map +1 -1
- package/dist/tokens/spacing.js +1 -0
- package/dist/tokens/tokens.css +1 -1
- package/dist/tokens/utilities.css +79 -2
- package/dist/utils/apiConfig.js +1 -1
- package/dist/utils/apiConfig.spec.js +34 -27
- package/dist/utils/assets.d.ts +3 -0
- package/dist/utils/assets.d.ts.map +1 -0
- package/dist/utils/assets.js +3 -0
- package/dist/utils/classNames.d.ts +10 -0
- package/dist/utils/classNames.d.ts.map +1 -0
- package/dist/utils/classNames.js +15 -0
- package/dist/utils/clickOutside.d.ts +4 -0
- package/dist/utils/clickOutside.d.ts.map +1 -0
- package/dist/utils/clickOutside.js +13 -0
- package/dist/utils/cookieHelpers.d.ts +40 -0
- package/dist/utils/cookieHelpers.d.ts.map +1 -0
- package/dist/utils/cookieHelpers.js +102 -0
- package/dist/utils/dateHelpers.d.ts +71 -0
- package/dist/utils/dateHelpers.d.ts.map +1 -0
- package/dist/utils/dateHelpers.js +253 -0
- package/dist/utils/eventFormatters.d.ts +9 -0
- package/dist/utils/eventFormatters.d.ts.map +1 -0
- package/dist/utils/eventFormatters.js +96 -0
- package/dist/utils/feedbackContext.d.ts +24 -0
- package/dist/utils/feedbackContext.d.ts.map +1 -0
- package/dist/utils/feedbackContext.js +19 -0
- package/dist/utils/fetchHelpers.d.ts +17 -0
- package/dist/utils/fetchHelpers.d.ts.map +1 -0
- package/dist/utils/fetchHelpers.js +45 -0
- package/dist/utils/focusTrap.d.ts +20 -0
- package/dist/utils/focusTrap.d.ts.map +1 -0
- package/dist/utils/focusTrap.js +130 -0
- package/dist/utils/formatters.d.ts +56 -0
- package/dist/utils/formatters.d.ts.map +1 -1
- package/dist/utils/formatters.js +121 -1
- package/dist/utils/formatters.spec.js +128 -1
- package/dist/utils/logger.d.ts +25 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +59 -1
- package/dist/utils/logger.spec.js +99 -1
- package/dist/utils/permissions.d.ts +9 -0
- package/dist/utils/permissions.d.ts.map +1 -0
- package/dist/utils/permissions.js +93 -0
- package/dist/utils/stringHelpers.d.ts +17 -0
- package/dist/utils/stringHelpers.d.ts.map +1 -0
- package/dist/utils/stringHelpers.js +38 -0
- package/dist/utils/transitions.d.ts +99 -1
- package/dist/utils/transitions.d.ts.map +1 -1
- package/dist/utils/transitions.js +144 -2
- package/dist/utils/utils/utils.d.ts +2 -73
- package/dist/utils/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils/utils.js +2 -2
- package/dist/utils/utils.d.ts +41 -98
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +58 -701
- package/package.json +16 -3
- package/dist/services/EventService.d.ts +0 -5
- package/dist/services/EventService.d.ts.map +0 -1
- package/dist/services/EventService.js +0 -79
- package/dist/services/EventService.spec.d.ts +0 -2
- package/dist/services/EventService.spec.d.ts.map +0 -1
- package/dist/services/EventService.spec.js +0 -217
- package/dist/services/ShowService.d.ts.map +0 -1
- package/dist/services/ShowService.js +0 -144
- package/dist/services/ShowService.spec.d.ts +0 -2
- package/dist/services/ShowService.spec.d.ts.map +0 -1
- package/dist/services/ShowService.spec.js +0 -345
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
// ============================================
|
|
2
|
+
// DATE/TIME FORMATTING UTILITIES
|
|
3
|
+
// ============================================
|
|
4
|
+
/**
|
|
5
|
+
* Convert a value to a date string using Date.toDateString().
|
|
6
|
+
* Returns null if the value is falsy.
|
|
7
|
+
*/
|
|
8
|
+
export function convertToDate(value) {
|
|
9
|
+
return value ? new Date(value).toDateString() : null;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Convert an ISO date string to a local Date using UTC components (date only, no time).
|
|
13
|
+
*/
|
|
14
|
+
export function convertToCustomDateFormat(isoString) {
|
|
15
|
+
const date = new Date(isoString);
|
|
16
|
+
const year = date.getUTCFullYear();
|
|
17
|
+
const month = date.getUTCMonth();
|
|
18
|
+
const day = date.getUTCDate();
|
|
19
|
+
return new Date(year, month, day);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Convert an ISO date string to a UTC Date preserving hours and minutes.
|
|
23
|
+
*/
|
|
24
|
+
export function convertToCustomDateTimeFormat(isoDateString) {
|
|
25
|
+
const date = new Date(isoDateString);
|
|
26
|
+
return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes()));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Format a date string's time as "H:MM AM/PM" using UTC hours.
|
|
30
|
+
*/
|
|
31
|
+
export function formatHour(dateString) {
|
|
32
|
+
const date = new Date(dateString);
|
|
33
|
+
const hour = date.getUTCHours();
|
|
34
|
+
const minutes = date.getUTCMinutes();
|
|
35
|
+
const suffix = hour >= 12 ? "PM" : "AM";
|
|
36
|
+
const displayHour = hour % 12 || 12;
|
|
37
|
+
const displayMinutes = minutes < 10 ? "0" + minutes : minutes;
|
|
38
|
+
return `${displayHour}:${displayMinutes} ${suffix}`;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Format a date as short form: "Thu, Oct 24".
|
|
42
|
+
*/
|
|
43
|
+
export function formattedDate(date) {
|
|
44
|
+
const options = {
|
|
45
|
+
weekday: "short",
|
|
46
|
+
month: "short",
|
|
47
|
+
day: "2-digit",
|
|
48
|
+
};
|
|
49
|
+
return new Date(date).toLocaleDateString("en-US", options);
|
|
50
|
+
}
|
|
51
|
+
/** Get the ordinal suffix (st, nd, rd, th) for a day of the month. */
|
|
52
|
+
function getOrdinalSuffix(day) {
|
|
53
|
+
if (day >= 11 && day <= 13)
|
|
54
|
+
return "th";
|
|
55
|
+
switch (day % 10) {
|
|
56
|
+
case 1:
|
|
57
|
+
return "st";
|
|
58
|
+
case 2:
|
|
59
|
+
return "nd";
|
|
60
|
+
case 3:
|
|
61
|
+
return "rd";
|
|
62
|
+
default:
|
|
63
|
+
return "th";
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Format a date as long form with ordinal: "Thursday, October 24th, 2024".
|
|
68
|
+
*/
|
|
69
|
+
export function formattedFullDate(date) {
|
|
70
|
+
const options = {
|
|
71
|
+
weekday: "long",
|
|
72
|
+
month: "long",
|
|
73
|
+
day: "numeric",
|
|
74
|
+
year: "numeric",
|
|
75
|
+
};
|
|
76
|
+
const formatted = new Date(date).toLocaleDateString("en-US", options);
|
|
77
|
+
const day = new Date(date).getDate();
|
|
78
|
+
const ordinalSuffix = getOrdinalSuffix(day);
|
|
79
|
+
return formatted.replace(/\d+/, day + ordinalSuffix);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Format a datetime string using Intl.DateTimeFormat with timezone support.
|
|
83
|
+
*/
|
|
84
|
+
export const formatDateTime = (dateTimeString, timeZone = "UTC") => {
|
|
85
|
+
const options = {
|
|
86
|
+
weekday: "short",
|
|
87
|
+
year: "numeric",
|
|
88
|
+
month: "short",
|
|
89
|
+
day: "numeric",
|
|
90
|
+
hour: "numeric",
|
|
91
|
+
minute: "numeric",
|
|
92
|
+
hour12: true,
|
|
93
|
+
timeZone: timeZone,
|
|
94
|
+
};
|
|
95
|
+
const date = new Date(dateTimeString);
|
|
96
|
+
return new Intl.DateTimeFormat("en-US", options).format(date);
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Format a start datetime as a single "H:MM AM/PM" time string (UTC).
|
|
100
|
+
*/
|
|
101
|
+
export const formatTimeline = (startDateTime) => {
|
|
102
|
+
const formatHourInternal = (date) => {
|
|
103
|
+
let hours = date.getUTCHours();
|
|
104
|
+
const minutes = date.getUTCMinutes();
|
|
105
|
+
const suffix = hours >= 12 ? "PM" : "AM";
|
|
106
|
+
hours = hours % 12 || 12;
|
|
107
|
+
return `${hours}:${minutes < 10 ? "0" + minutes : minutes} ${suffix}`;
|
|
108
|
+
};
|
|
109
|
+
const start = formatHourInternal(new Date(startDateTime));
|
|
110
|
+
return `${start}`;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Format a time range as "H:MM AM - H:MM PM" (UTC).
|
|
114
|
+
*/
|
|
115
|
+
export function formatTimeRange(startDate, endDate) {
|
|
116
|
+
const start = new Date(startDate);
|
|
117
|
+
const end = new Date(endDate);
|
|
118
|
+
function formatTime(date) {
|
|
119
|
+
let hours = date.getUTCHours();
|
|
120
|
+
const minutes = date.getUTCMinutes();
|
|
121
|
+
const ampm = hours >= 12 ? "PM" : "AM";
|
|
122
|
+
hours = hours % 12;
|
|
123
|
+
hours = hours ? hours : 12;
|
|
124
|
+
const minutesStr = minutes < 10 ? "0" + minutes : minutes;
|
|
125
|
+
return hours + ":" + minutesStr + " " + ampm;
|
|
126
|
+
}
|
|
127
|
+
const startTime = formatTime(start);
|
|
128
|
+
const endTime = formatTime(end);
|
|
129
|
+
return `${startTime} - ${endTime}`;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Get an array of date strings between two dates (inclusive), formatted as "YYYY-M-D".
|
|
133
|
+
*/
|
|
134
|
+
export function getDateRange(startDate, endDate) {
|
|
135
|
+
const start = new Date(startDate);
|
|
136
|
+
const end = new Date(endDate);
|
|
137
|
+
const dateArray = [];
|
|
138
|
+
const currentDate = new Date(start);
|
|
139
|
+
while (currentDate <= end) {
|
|
140
|
+
dateArray.push(`${currentDate.getUTCFullYear()}-${currentDate.getUTCMonth() + 1}-${currentDate.getUTCDate()}`);
|
|
141
|
+
currentDate.setUTCDate(currentDate.getUTCDate() + 1);
|
|
142
|
+
}
|
|
143
|
+
return dateArray;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Get abbreviated day of week from a date string (e.g., "Mon", "Tue").
|
|
147
|
+
*/
|
|
148
|
+
export const getDay = (dateString) => {
|
|
149
|
+
const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
150
|
+
const date = new Date(dateString);
|
|
151
|
+
return days[date.getUTCDay()];
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* Get abbreviated month from a date string (e.g., "Jan", "Feb").
|
|
155
|
+
*/
|
|
156
|
+
export const getMonth = (dateString) => {
|
|
157
|
+
const months = [
|
|
158
|
+
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
|
159
|
+
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
|
|
160
|
+
];
|
|
161
|
+
const date = new Date(dateString);
|
|
162
|
+
return months[date.getUTCMonth()];
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* Get the day of the month (1-31) from a date string.
|
|
166
|
+
*/
|
|
167
|
+
export const getDateOfMonth = (dateString) => {
|
|
168
|
+
const date = new Date(dateString);
|
|
169
|
+
return date.getUTCDate();
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* Relative time string (e.g., "5 minutes ago", "2 days ago").
|
|
173
|
+
*/
|
|
174
|
+
export function timeAgo(date) {
|
|
175
|
+
const now = new Date();
|
|
176
|
+
const seconds = Math.floor((now.getTime() - new Date(date).getTime()) / 1000);
|
|
177
|
+
const minutes = Math.floor(seconds / 60);
|
|
178
|
+
const hours = Math.floor(minutes / 60);
|
|
179
|
+
const days = Math.floor(hours / 24);
|
|
180
|
+
const months = Math.floor(days / 30);
|
|
181
|
+
const years = Math.floor(months / 12);
|
|
182
|
+
if (seconds < 60) {
|
|
183
|
+
return `${seconds} second${seconds !== 1 ? "s" : ""} ago`;
|
|
184
|
+
}
|
|
185
|
+
else if (minutes < 60) {
|
|
186
|
+
return `${minutes} minute${minutes !== 1 ? "s" : ""} ago`;
|
|
187
|
+
}
|
|
188
|
+
else if (hours < 24) {
|
|
189
|
+
return `${hours} hour${hours !== 1 ? "s" : ""} ago`;
|
|
190
|
+
}
|
|
191
|
+
else if (days < 30) {
|
|
192
|
+
return `${days} day${days !== 1 ? "s" : ""} ago`;
|
|
193
|
+
}
|
|
194
|
+
else if (months < 12) {
|
|
195
|
+
return `${months} month${months !== 1 ? "s" : ""} ago`;
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
return `${years} year${years !== 1 ? "s" : ""} ago`;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Get day options: weekdays if "weeks", or numbered days 1-31 with ordinal suffixes.
|
|
203
|
+
*/
|
|
204
|
+
export function getDays(params) {
|
|
205
|
+
if (params === "weeks") {
|
|
206
|
+
return [
|
|
207
|
+
{ value: "monday", label: "Monday" },
|
|
208
|
+
{ value: "tuesday", label: "Tuesday" },
|
|
209
|
+
{ value: "wednesday", label: "Wednesday" },
|
|
210
|
+
{ value: "thursday", label: "Thursday" },
|
|
211
|
+
{ value: "friday", label: "Friday" },
|
|
212
|
+
];
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
return Array.from({ length: 31 }, (_, i) => {
|
|
216
|
+
const day = i + 1;
|
|
217
|
+
const suffix = day % 10 === 1 && day !== 11
|
|
218
|
+
? "st"
|
|
219
|
+
: day % 10 === 2 && day !== 12
|
|
220
|
+
? "nd"
|
|
221
|
+
: day % 10 === 3 && day !== 13
|
|
222
|
+
? "rd"
|
|
223
|
+
: "th";
|
|
224
|
+
return {
|
|
225
|
+
value: day.toString(),
|
|
226
|
+
label: day + suffix,
|
|
227
|
+
};
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Get numeric options based on time unit: 12 for months, 10 for weeks, 31 for days.
|
|
233
|
+
*/
|
|
234
|
+
export function getDaysNumberOptions(timeUnit) {
|
|
235
|
+
if (timeUnit === "months") {
|
|
236
|
+
return Array.from({ length: 12 }, (_, i) => ({
|
|
237
|
+
value: (i + 1).toString(),
|
|
238
|
+
label: (i + 1).toString(),
|
|
239
|
+
}));
|
|
240
|
+
}
|
|
241
|
+
else if (timeUnit === "weeks") {
|
|
242
|
+
return Array.from({ length: 10 }, (_, i) => ({
|
|
243
|
+
value: (i + 1).toString(),
|
|
244
|
+
label: (i + 1).toString(),
|
|
245
|
+
}));
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
return Array.from({ length: 31 }, (_, i) => ({
|
|
249
|
+
value: (i + 1).toString(),
|
|
250
|
+
label: (i + 1).toString(),
|
|
251
|
+
}));
|
|
252
|
+
}
|
|
253
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const getRoleFromRoleOnStage: (roleOnStage: number | undefined) => string;
|
|
2
|
+
/**
|
|
3
|
+
* Format an event performer invite or event-performer join into a normalized show object.
|
|
4
|
+
* Handles both V1 (EventPerformer with event.Event) and V2 (PerformerInvite with event.event) shapes.
|
|
5
|
+
*/
|
|
6
|
+
export declare const formatEvent: (event: Record<string, any>) => Record<string, any>;
|
|
7
|
+
export declare const formatRosterEventPerformerInvite: (event: Record<string, any>) => Record<string, any>;
|
|
8
|
+
export declare const formatVenue: (event: Record<string, any>) => Record<string, any>;
|
|
9
|
+
//# sourceMappingURL=eventFormatters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eventFormatters.d.ts","sourceRoot":"","sources":["../../src/lib/utils/eventFormatters.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,sBAAsB,GAAI,aAAa,MAAM,GAAG,SAAS,KAAG,MAExE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CA4C1E,CAAC;AAEF,eAAO,MAAM,gCAAgC,GAAI,OAAO,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAc/F,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAmB1E,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { formatTimeRange, getDateRange } from "./dateHelpers";
|
|
2
|
+
// ============================================
|
|
3
|
+
// EVENT FORMATTING UTILITIES
|
|
4
|
+
// ============================================
|
|
5
|
+
/** Map roleOnStage numeric value to role name string. */
|
|
6
|
+
const ROLE_ON_STAGE_MAP = {
|
|
7
|
+
0: "Performer",
|
|
8
|
+
1: "Host",
|
|
9
|
+
2: "Headliner",
|
|
10
|
+
3: "Feature",
|
|
11
|
+
4: "Special Guest",
|
|
12
|
+
5: "Opener",
|
|
13
|
+
6: "Guest",
|
|
14
|
+
7: "Teacher",
|
|
15
|
+
8: "Assistant",
|
|
16
|
+
};
|
|
17
|
+
export const getRoleFromRoleOnStage = (roleOnStage) => {
|
|
18
|
+
return ROLE_ON_STAGE_MAP[roleOnStage] || "Performer";
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Format an event performer invite or event-performer join into a normalized show object.
|
|
22
|
+
* Handles both V1 (EventPerformer with event.Event) and V2 (PerformerInvite with event.event) shapes.
|
|
23
|
+
*/
|
|
24
|
+
export const formatEvent = (event) => {
|
|
25
|
+
// V2 uses lowercase "event", V1 uses uppercase "Event"
|
|
26
|
+
const eventData = event.event || event.Event;
|
|
27
|
+
// Get venue stage name (the physical stage at the venue, e.g., "Main Room", "Showroom")
|
|
28
|
+
// Not to be confused with performer's stage name (their performance alias)
|
|
29
|
+
const venueStageName = eventData?.stage?.name || eventData?.stage?.googleName || eventData?.googleName || "";
|
|
30
|
+
const venueAddress = eventData?.venue?.address || "";
|
|
31
|
+
const role = getRoleFromRoleOnStage(event.roleOnStage);
|
|
32
|
+
// Get custom booking notification message from venue (set in venue edit page)
|
|
33
|
+
const bookingMessage = eventData?.venue?.booking_notification || "No additional details available.";
|
|
34
|
+
// V2 returns "status" string, V1 returns numeric "acceptedState"
|
|
35
|
+
const status = event.status || (event.acceptedState !== undefined
|
|
36
|
+
? { 0: "invited", 2: "confirmed", 1: "declined", 3: "declined", 4: "cancelled" }[event.acceptedState]
|
|
37
|
+
: "unknown");
|
|
38
|
+
const setLength = event.setLength ?? 0;
|
|
39
|
+
return {
|
|
40
|
+
eventId: eventData?.ID,
|
|
41
|
+
venueId: eventData?.venue?.ID,
|
|
42
|
+
title: eventData?.title,
|
|
43
|
+
role: role,
|
|
44
|
+
startDateTime: eventData?.startDateTime,
|
|
45
|
+
status: status,
|
|
46
|
+
doorsOpenTime: eventData?.doorsOpenTime,
|
|
47
|
+
spotDuration: `${setLength} min spot`,
|
|
48
|
+
venueName: eventData?.venue?.name,
|
|
49
|
+
location: venueAddress,
|
|
50
|
+
id: event.invitationId || String(event.id || event.ID),
|
|
51
|
+
image: eventData?.image,
|
|
52
|
+
details: {
|
|
53
|
+
venue: eventData?.venue?.name,
|
|
54
|
+
stageName: venueStageName,
|
|
55
|
+
address: venueAddress,
|
|
56
|
+
setLength: `${setLength} min`,
|
|
57
|
+
eventDetails: bookingMessage,
|
|
58
|
+
},
|
|
59
|
+
lastUpdated: event.updatedAt || event.UpdatedAt,
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
export const formatRosterEventPerformerInvite = (event) => {
|
|
63
|
+
return {
|
|
64
|
+
venueId: event.venueId,
|
|
65
|
+
role: event.role || "Performer",
|
|
66
|
+
acceptedState: event.acceptedState,
|
|
67
|
+
name: event.Venue.name,
|
|
68
|
+
shortVenue: `${event.Venue.firstName} ${event.Venue.lastName} - ${event.Venue.role}`,
|
|
69
|
+
location: `${event.Venue.address}`,
|
|
70
|
+
id: event.invitationId,
|
|
71
|
+
lastUpdated: event.UpdatedAt,
|
|
72
|
+
image: event.Venue.image,
|
|
73
|
+
hasAvailability: true,
|
|
74
|
+
invitationAccepted: event.acceptedState === 2,
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
export const formatVenue = (event) => {
|
|
78
|
+
return {
|
|
79
|
+
venueId: event.Event.venueId,
|
|
80
|
+
name: event.Event.venue.name,
|
|
81
|
+
image: event.Event.venue.squareImageUrl || event.Event.venue.image,
|
|
82
|
+
location: `${event.Event.venue.address}`,
|
|
83
|
+
start: event.Event.startDateTime,
|
|
84
|
+
end: event.Event.endDateTime,
|
|
85
|
+
doorOpen: event.Event.doorsOpenTime,
|
|
86
|
+
email: event.Event.venue.email,
|
|
87
|
+
phone: event.Event.venue.phone,
|
|
88
|
+
description: event.Event.venue.description,
|
|
89
|
+
instagram: event.Event.venue.instagram,
|
|
90
|
+
facebook: event.Event.venue.facebook,
|
|
91
|
+
twitter: event.Event.venue.twitter,
|
|
92
|
+
lastUpdated: event.UpdatedAt,
|
|
93
|
+
timeRange: formatTimeRange(event.Event.startDateTime, event.Event.endDateTime),
|
|
94
|
+
dateRange: getDateRange(event.Event.startDateTime, event.Event.endDateTime),
|
|
95
|
+
};
|
|
96
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feedback Context Collector
|
|
3
|
+
* SSR-safe utility that gathers environment context for feedback submissions.
|
|
4
|
+
*/
|
|
5
|
+
export interface FeedbackLastError {
|
|
6
|
+
code: string;
|
|
7
|
+
message: string;
|
|
8
|
+
requestId?: string;
|
|
9
|
+
traceId?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface FeedbackContextData {
|
|
12
|
+
url: string;
|
|
13
|
+
app: string;
|
|
14
|
+
appVersion: string;
|
|
15
|
+
userAgent: string;
|
|
16
|
+
timestamp: string;
|
|
17
|
+
lastError?: FeedbackLastError;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Collect feedback context from the current environment.
|
|
21
|
+
* Safe to call in SSR — returns empty strings for browser-only values.
|
|
22
|
+
*/
|
|
23
|
+
export declare function collectFeedbackContext(app: string, appVersion: string, lastError?: FeedbackLastError | null): FeedbackContextData;
|
|
24
|
+
//# sourceMappingURL=feedbackContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feedbackContext.d.ts","sourceRoot":"","sources":["../../src/lib/utils/feedbackContext.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,iBAAiB,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,iBAAiB,GAAG,IAAI,GACnC,mBAAmB,CAWrB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feedback Context Collector
|
|
3
|
+
* SSR-safe utility that gathers environment context for feedback submissions.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Collect feedback context from the current environment.
|
|
7
|
+
* Safe to call in SSR — returns empty strings for browser-only values.
|
|
8
|
+
*/
|
|
9
|
+
export function collectFeedbackContext(app, appVersion, lastError) {
|
|
10
|
+
const isBrowser = typeof window !== 'undefined';
|
|
11
|
+
return {
|
|
12
|
+
url: isBrowser ? window.location.href : '',
|
|
13
|
+
app,
|
|
14
|
+
appVersion,
|
|
15
|
+
userAgent: isBrowser ? navigator.userAgent : '',
|
|
16
|
+
timestamp: new Date().toISOString(),
|
|
17
|
+
lastError: lastError || undefined,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
interface FetchResult<T = unknown> {
|
|
2
|
+
data: T | null;
|
|
3
|
+
error: string | null;
|
|
4
|
+
}
|
|
5
|
+
interface PostResult<T = unknown> extends FetchResult<T> {
|
|
6
|
+
ok: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Fetch data from an API endpoint with error handling.
|
|
10
|
+
*/
|
|
11
|
+
export declare function fetchData<T = unknown>(endpoint: string, options?: RequestInit): Promise<FetchResult<T>>;
|
|
12
|
+
/**
|
|
13
|
+
* Post JSON data to an API endpoint.
|
|
14
|
+
*/
|
|
15
|
+
export declare function postData<T = unknown>(endpoint: string, data: unknown): Promise<PostResult<T>>;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=fetchHelpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetchHelpers.d.ts","sourceRoot":"","sources":["../../src/lib/utils/fetchHelpers.ts"],"names":[],"mappings":"AAKA,UAAU,WAAW,CAAC,CAAC,GAAG,OAAO;IAC/B,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,UAAU,UAAU,CAAC,CAAC,GAAG,OAAO,CAAE,SAAQ,WAAW,CAAC,CAAC,CAAC;IACtD,EAAE,EAAE,OAAO,CAAC;CACb;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,CAAC,GAAG,OAAO,EACzC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAiBzB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,CAAC,GAAG,OAAO,EACxC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAkBxB"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/* global RequestInit */
|
|
2
|
+
// ============================================
|
|
3
|
+
// DATA FETCHING UTILITIES
|
|
4
|
+
// ============================================
|
|
5
|
+
/**
|
|
6
|
+
* Fetch data from an API endpoint with error handling.
|
|
7
|
+
*/
|
|
8
|
+
export async function fetchData(endpoint, options = {}) {
|
|
9
|
+
try {
|
|
10
|
+
const res = await fetch(endpoint, {
|
|
11
|
+
headers: { "Content-Type": "application/json", ...options.headers },
|
|
12
|
+
...options,
|
|
13
|
+
});
|
|
14
|
+
if (!res.ok) {
|
|
15
|
+
const errorText = await res.text().catch(() => "Unknown error");
|
|
16
|
+
throw new Error(errorText || `Request failed with status ${res.status}`);
|
|
17
|
+
}
|
|
18
|
+
const data = await res.json();
|
|
19
|
+
return { data, error: null };
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
return { data: null, error: err.message };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Post JSON data to an API endpoint.
|
|
27
|
+
*/
|
|
28
|
+
export async function postData(endpoint, data) {
|
|
29
|
+
try {
|
|
30
|
+
const res = await fetch(endpoint, {
|
|
31
|
+
method: "POST",
|
|
32
|
+
headers: { "Content-Type": "application/json" },
|
|
33
|
+
body: JSON.stringify(data),
|
|
34
|
+
});
|
|
35
|
+
const responseData = await res.json().catch(() => ({}));
|
|
36
|
+
return {
|
|
37
|
+
data: responseData,
|
|
38
|
+
error: res.ok ? null : (responseData?.message || "Request failed"),
|
|
39
|
+
ok: res.ok,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
return { data: null, error: err.message, ok: false };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Svelte action to trap focus within an element (for modals and dialogs).
|
|
3
|
+
* When used, focus will cycle between focusable elements within the container.
|
|
4
|
+
*
|
|
5
|
+
* @param {HTMLElement} node - The container element to trap focus within
|
|
6
|
+
* @param {Object} options - Configuration options
|
|
7
|
+
* @param {boolean} options.enabled - Whether the focus trap is active
|
|
8
|
+
* @param {HTMLElement} options.returnFocusTo - Element to return focus to when trap is disabled
|
|
9
|
+
* @returns {Object} Svelte action lifecycle methods
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* <div use:focusTrap={{ enabled: isOpen, returnFocusTo: triggerElement }}>
|
|
13
|
+
* ...modal content...
|
|
14
|
+
* </div>
|
|
15
|
+
*/
|
|
16
|
+
export function focusTrap(node: HTMLElement, options?: {
|
|
17
|
+
enabled: boolean;
|
|
18
|
+
returnFocusTo: HTMLElement;
|
|
19
|
+
}): Object;
|
|
20
|
+
//# sourceMappingURL=focusTrap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focusTrap.d.ts","sourceRoot":"","sources":["../../src/lib/utils/focusTrap.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,gCAXW,WAAW,YAEnB;IAAyB,OAAO,EAAxB,OAAO;IACc,aAAa,EAAlC,WAAW;CACnB,GAAU,MAAM,CAyHlB"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Svelte action to trap focus within an element (for modals and dialogs).
|
|
3
|
+
* When used, focus will cycle between focusable elements within the container.
|
|
4
|
+
*
|
|
5
|
+
* @param {HTMLElement} node - The container element to trap focus within
|
|
6
|
+
* @param {Object} options - Configuration options
|
|
7
|
+
* @param {boolean} options.enabled - Whether the focus trap is active
|
|
8
|
+
* @param {HTMLElement} options.returnFocusTo - Element to return focus to when trap is disabled
|
|
9
|
+
* @returns {Object} Svelte action lifecycle methods
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* <div use:focusTrap={{ enabled: isOpen, returnFocusTo: triggerElement }}>
|
|
13
|
+
* ...modal content...
|
|
14
|
+
* </div>
|
|
15
|
+
*/
|
|
16
|
+
export function focusTrap(node, options = {}) {
|
|
17
|
+
const FOCUSABLE_SELECTORS = [
|
|
18
|
+
'a[href]',
|
|
19
|
+
'area[href]',
|
|
20
|
+
'input:not([disabled]):not([type="hidden"])',
|
|
21
|
+
'select:not([disabled])',
|
|
22
|
+
'textarea:not([disabled])',
|
|
23
|
+
'button:not([disabled])',
|
|
24
|
+
'[tabindex]:not([tabindex="-1"])',
|
|
25
|
+
'[contenteditable]',
|
|
26
|
+
'audio[controls]',
|
|
27
|
+
'video[controls]',
|
|
28
|
+
'details>summary:first-of-type',
|
|
29
|
+
'details',
|
|
30
|
+
].join(',');
|
|
31
|
+
|
|
32
|
+
let enabled = options.enabled ?? true;
|
|
33
|
+
let returnFocusTo = options.returnFocusTo ?? null;
|
|
34
|
+
let previouslyFocused = null;
|
|
35
|
+
|
|
36
|
+
function getFocusableElements() {
|
|
37
|
+
const elements = Array.from(node.querySelectorAll(FOCUSABLE_SELECTORS));
|
|
38
|
+
return elements.filter(
|
|
39
|
+
el => !el.hasAttribute('disabled') && el.tabIndex !== -1 && isVisible(el)
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function isVisible(element) {
|
|
44
|
+
return !!(
|
|
45
|
+
element.offsetWidth ||
|
|
46
|
+
element.offsetHeight ||
|
|
47
|
+
element.getClientRects().length
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function handleKeydown(event) {
|
|
52
|
+
if (!enabled || event.key !== 'Tab') return;
|
|
53
|
+
|
|
54
|
+
const focusableElements = getFocusableElements();
|
|
55
|
+
if (focusableElements.length === 0) return;
|
|
56
|
+
|
|
57
|
+
const firstElement = focusableElements[0];
|
|
58
|
+
const lastElement = focusableElements[focusableElements.length - 1];
|
|
59
|
+
|
|
60
|
+
if (event.shiftKey) {
|
|
61
|
+
// Shift+Tab: going backwards
|
|
62
|
+
if (document.activeElement === firstElement) {
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
lastElement.focus();
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
// Tab: going forwards
|
|
68
|
+
if (document.activeElement === lastElement) {
|
|
69
|
+
event.preventDefault();
|
|
70
|
+
firstElement.focus();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function activate() {
|
|
76
|
+
if (!enabled) return;
|
|
77
|
+
|
|
78
|
+
// Store previously focused element
|
|
79
|
+
previouslyFocused = document.activeElement;
|
|
80
|
+
|
|
81
|
+
// Focus the first focusable element or the container itself
|
|
82
|
+
const focusableElements = getFocusableElements();
|
|
83
|
+
if (focusableElements.length > 0) {
|
|
84
|
+
// Use requestAnimationFrame to ensure DOM is ready
|
|
85
|
+
requestAnimationFrame(() => {
|
|
86
|
+
focusableElements[0].focus();
|
|
87
|
+
});
|
|
88
|
+
} else {
|
|
89
|
+
// If no focusable elements, make the container focusable
|
|
90
|
+
node.setAttribute('tabindex', '-1');
|
|
91
|
+
node.focus();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
document.addEventListener('keydown', handleKeydown);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function deactivate() {
|
|
98
|
+
document.removeEventListener('keydown', handleKeydown);
|
|
99
|
+
|
|
100
|
+
// Return focus to the specified element or the previously focused element
|
|
101
|
+
const focusTarget = returnFocusTo || previouslyFocused;
|
|
102
|
+
if (focusTarget && typeof focusTarget.focus === 'function') {
|
|
103
|
+
focusTarget.focus();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Initialize
|
|
108
|
+
if (enabled) {
|
|
109
|
+
activate();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
update(newOptions) {
|
|
114
|
+
const newEnabled = newOptions.enabled ?? true;
|
|
115
|
+
returnFocusTo = newOptions.returnFocusTo ?? null;
|
|
116
|
+
|
|
117
|
+
if (newEnabled !== enabled) {
|
|
118
|
+
enabled = newEnabled;
|
|
119
|
+
if (enabled) {
|
|
120
|
+
activate();
|
|
121
|
+
} else {
|
|
122
|
+
deactivate();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
destroy() {
|
|
127
|
+
deactivate();
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|