@getmicdrop/svelte-components 2.0.13 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/__LIB_STORES__.js +30 -2
  2. package/dist/components/AboutShow/AboutShow.svelte +278 -0
  3. package/dist/components/AboutShow/AboutShow.svelte.d.ts +43 -0
  4. package/dist/components/AboutShow/AboutShow.svelte.d.ts.map +1 -0
  5. package/dist/components/Calendar/MiniMonthCalendar.svelte +1446 -0
  6. package/dist/components/Calendar/{Calendar.svelte.d.ts → MiniMonthCalendar.svelte.d.ts} +20 -21
  7. package/dist/components/Calendar/MiniMonthCalendar.svelte.d.ts.map +1 -0
  8. package/dist/components/DarkModeToggle.svelte +3 -1
  9. package/dist/components/DarkModeToggle.svelte.d.ts.map +1 -1
  10. package/dist/components/FAQs/FAQs.svelte +49 -0
  11. package/dist/components/{Calendar/QuarterView.svelte.d.ts → FAQs/FAQs.svelte.d.ts} +10 -10
  12. package/dist/components/FAQs/FAQs.svelte.d.ts.map +1 -0
  13. package/dist/components/Input/Input.svelte +100 -12
  14. package/dist/components/Input/Input.svelte.d.ts +12 -0
  15. package/dist/components/Input/Input.svelte.d.ts.map +1 -1
  16. package/dist/components/Input/OTPInput.svelte +1 -1
  17. package/dist/components/MonthSwitcher/MonthSwitcher.svelte +206 -0
  18. package/dist/components/MonthSwitcher/MonthSwitcher.svelte.d.ts +37 -0
  19. package/dist/components/MonthSwitcher/MonthSwitcher.svelte.d.ts.map +1 -0
  20. package/dist/components/OrderSummary/OrderSummary.svelte +553 -0
  21. package/dist/components/OrderSummary/OrderSummary.svelte.d.ts +65 -0
  22. package/dist/components/OrderSummary/OrderSummary.svelte.d.ts.map +1 -0
  23. package/dist/components/PublicCard/PublicCard.svelte +267 -0
  24. package/dist/components/{pages/performers/AvailabilityCalendarModal.svelte.d.ts → PublicCard/PublicCard.svelte.d.ts} +12 -14
  25. package/dist/components/PublicCard/PublicCard.svelte.d.ts.map +1 -0
  26. package/dist/components/ShowCard/ShowCard.svelte +240 -0
  27. package/dist/components/ShowCard/ShowCard.svelte.d.ts +39 -0
  28. package/dist/components/ShowCard/ShowCard.svelte.d.ts.map +1 -0
  29. package/dist/components/ShowTimeCard/ShowTimeCard.svelte +92 -0
  30. package/dist/components/{Calendar/QuarterView.stories.svelte.d.ts → ShowTimeCard/ShowTimeCard.svelte.d.ts} +17 -21
  31. package/dist/components/ShowTimeCard/ShowTimeCard.svelte.d.ts.map +1 -0
  32. package/dist/components/Spinner/Spinner.svelte +73 -17
  33. package/dist/components/Spinner/Spinner.svelte.d.ts +5 -3
  34. package/dist/components/Spinner/Spinner.svelte.d.ts.map +1 -1
  35. package/dist/components/pages/performers/ShowDetails.svelte.d.ts +2 -2
  36. package/dist/components/pages/performers/ShowItemCard.svelte.d.ts +6 -6
  37. package/dist/components/pages/performers/VenueItemCard.svelte.d.ts +2 -2
  38. package/dist/components/pages/shows/TabNavigation.svelte +7 -8
  39. package/dist/index.d.ts +8 -3
  40. package/dist/index.js +12 -3
  41. package/dist/services/EventService.js +75 -75
  42. package/dist/services/EventService.spec.js +217 -217
  43. package/dist/services/ShowService.spec.js +342 -342
  44. package/package.json +160 -160
  45. package/dist/components/Calendar/Calendar.spec.d.ts +0 -2
  46. package/dist/components/Calendar/Calendar.spec.d.ts.map +0 -1
  47. package/dist/components/Calendar/Calendar.spec.js +0 -131
  48. package/dist/components/Calendar/Calendar.svelte +0 -1115
  49. package/dist/components/Calendar/Calendar.svelte.d.ts.map +0 -1
  50. package/dist/components/Calendar/QuarterView.spec.d.ts +0 -2
  51. package/dist/components/Calendar/QuarterView.spec.d.ts.map +0 -1
  52. package/dist/components/Calendar/QuarterView.spec.js +0 -394
  53. package/dist/components/Calendar/QuarterView.stories.svelte +0 -134
  54. package/dist/components/Calendar/QuarterView.stories.svelte.d.ts.map +0 -1
  55. package/dist/components/Calendar/QuarterView.svelte +0 -736
  56. package/dist/components/Calendar/QuarterView.svelte.d.ts.map +0 -1
  57. package/dist/components/pages/performers/AvailabilityCalendarModal.svelte +0 -632
  58. package/dist/components/pages/performers/AvailabilityCalendarModal.svelte.d.ts.map +0 -1
@@ -1,736 +0,0 @@
1
- <script>
2
- import Icon from "../Icons/Icon.svelte";
3
- import { getDay, getDaysInMonth, startOfMonth } from "date-fns";
4
- import { writable } from "svelte/store";
5
- import { fly } from "svelte/transition";
6
- import { cubicOut } from "svelte/easing";
7
- import Button from "../Button/Button.svelte";
8
-
9
- export let currentevents = [];
10
- export let selectedDates;
11
- export let saveStatus = "";
12
-
13
- let currentDate = new Date();
14
- let currentYear = writable(currentDate.getUTCFullYear());
15
- let currentMonth = writable(currentDate.getUTCMonth());
16
-
17
- // Track slide direction for animations
18
- let slideDirection = 0; // -1 for left (prev), 1 for right (next), 0 for no animation
19
-
20
- let events = {};
21
-
22
- // Process `currentevents` into a dictionary
23
- $: {
24
- const newEvents = {};
25
- currentevents.forEach((event) => {
26
- // event.date is already in YYYY-MM-DD format from normalizeDate
27
- newEvents[event.date] = true;
28
- });
29
- events = newEvents;
30
- }
31
-
32
- // Check if a day is an event
33
- function isEvent(year, month, day) {
34
- const dateKey = `${year}-${String(month + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
35
- return events[dateKey];
36
- }
37
-
38
- // Haptic feedback helper - iOS Safari compatible
39
- function triggerHaptic(style = 'light') {
40
- // Try iOS Haptic Engine first (iOS 13+)
41
- if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.haptic) {
42
- window.webkit.messageHandlers.haptic.postMessage(style);
43
- return;
44
- }
45
-
46
- // Try Taptic Engine (older method)
47
- if (window.TapticEngine) {
48
- if (style === 'light') {
49
- window.TapticEngine.impact({ style: 'light' });
50
- } else if (style === 'medium') {
51
- window.TapticEngine.impact({ style: 'medium' });
52
- } else if (style === 'success') {
53
- window.TapticEngine.notification({ type: 'success' });
54
- }
55
- return;
56
- }
57
-
58
- // Fallback to Vibration API (Android)
59
- if (navigator.vibrate) {
60
- const duration = style === 'light' ? 10 : style === 'medium' ? 20 : [10, 50, 10];
61
- navigator.vibrate(duration);
62
- }
63
- }
64
-
65
- // Toggle selection of an event day with optimistic update
66
- function toggleDateSelection(year, month, day) {
67
- if (isSwiping) return;
68
-
69
- const dateKey = `${year}-${String(month + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
70
-
71
- // Determine if selecting or deselecting for haptic feedback
72
- const isCurrentlySelected = $selectedDates.includes(dateKey);
73
-
74
- selectedDates.update((dates) => {
75
- if (dates.includes(dateKey)) {
76
- // Deselecting - medium haptic
77
- triggerHaptic('medium');
78
- return dates.filter((date) => date !== dateKey);
79
- } else {
80
- // Selecting - light haptic
81
- triggerHaptic('light');
82
- return [...dates, dateKey];
83
- }
84
- });
85
- }
86
-
87
- // Check if a day is in the past
88
- function isPastDate(year, month, day) {
89
- const today = new Date();
90
- const date = new Date(year, month, day);
91
- return date < today.setHours(0, 0, 0, 0);
92
- }
93
-
94
- let prevAnimating = false;
95
- let nextAnimating = false;
96
- let todayButtonPressed = false;
97
-
98
- // Touch swipe detection
99
- let touchStartX = 0;
100
- let touchStartY = 0;
101
- let touchStartTime = 0;
102
- let isSwiping = false;
103
-
104
- function handleTouchStart(e) {
105
- touchStartX = e.touches[0].clientX;
106
- touchStartY = e.touches[0].clientY;
107
- touchStartTime = Date.now();
108
- isSwiping = false;
109
- }
110
-
111
- function handleTouchMove(e) {
112
- if (!touchStartX) return;
113
-
114
- const touchCurrentX = e.touches[0].clientX;
115
- const touchCurrentY = e.touches[0].clientY;
116
- const diffX = touchStartX - touchCurrentX;
117
- const diffY = touchStartY - touchCurrentY;
118
-
119
- // If horizontal movement is greater than vertical, it's a swipe
120
- if (Math.abs(diffX) > Math.abs(diffY) && Math.abs(diffX) > 10) {
121
- isSwiping = true;
122
- }
123
- }
124
-
125
- function handleTouchEnd(e) {
126
- if (!touchStartX || !isSwiping) {
127
- touchStartX = 0;
128
- touchStartY = 0;
129
- isSwiping = false;
130
- return;
131
- }
132
-
133
- const touchEndX = e.changedTouches[0].clientX;
134
- const touchEndY = e.changedTouches[0].clientY;
135
- const diffX = touchStartX - touchEndX;
136
- const diffY = touchStartY - touchEndY;
137
- const diffTime = Date.now() - touchStartTime;
138
-
139
- // Swipe detection: horizontal movement > 50px, mostly horizontal, and quick (< 300ms)
140
- if (Math.abs(diffX) > 50 && Math.abs(diffX) > Math.abs(diffY) * 2 && diffTime < 300) {
141
- if (diffX > 0) {
142
- // Swiped left -> go to next month
143
- handleNext(true); // Pass true to indicate swipe
144
- } else {
145
- // Swiped right -> go to previous month
146
- handlePrev(true); // Pass true to indicate swipe
147
- }
148
- }
149
-
150
- touchStartX = 0;
151
- touchStartY = 0;
152
- isSwiping = false;
153
- }
154
-
155
- function handleNext(isSwipe = false) {
156
- if (nextAnimating) return;
157
- if (!isSwipe) nextAnimating = true; // Only animate chevron on button click
158
-
159
- // Haptic feedback for month navigation
160
- triggerHaptic('medium');
161
-
162
- slideDirection = 1; // Slide from right
163
- currentMonth.update((month) => {
164
- if (month === 11) {
165
- currentYear.update((year) => year + 1);
166
- return 0;
167
- }
168
- return month + 1;
169
- });
170
- setTimeout(() => {
171
- nextAnimating = false;
172
- slideDirection = 0;
173
- }, 300);
174
- }
175
-
176
- function handlePrev(isSwipe = false) {
177
- if (prevAnimating) return;
178
- if (!isSwipe) prevAnimating = true; // Only animate chevron on button click
179
-
180
- // Haptic feedback for month navigation
181
- triggerHaptic('medium');
182
-
183
- slideDirection = -1; // Slide from left
184
- currentMonth.update((month) => {
185
- if (month === 0) {
186
- currentYear.update((year) => year - 1);
187
- return 11;
188
- }
189
- return month - 1;
190
- });
191
- setTimeout(() => {
192
- prevAnimating = false;
193
- slideDirection = 0;
194
- }, 300);
195
- }
196
-
197
- // Add all available event dates to the selection
198
- function setAllAvailable() {
199
- const year = $currentYear;
200
- const month = $currentMonth;
201
-
202
- selectedDates.update((dates) => {
203
- const newDates = [...dates];
204
- for (let day = 1; day <= getDaysInMonth(new Date(year, month)); day++) {
205
- const dateKey = `${year}-${String(month + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
206
- if (isEvent(year, month, day) && !newDates.includes(dateKey)) {
207
- newDates.push(dateKey);
208
- }
209
- }
210
- return newDates;
211
- });
212
- }
213
-
214
- // Remove all event dates from the selection
215
- function setAllUnavailable() {
216
- const year = $currentYear;
217
- const month = $currentMonth;
218
-
219
- selectedDates.update((dates) =>
220
- dates.filter((dateKey) => {
221
- const [y, m, d] = dateKey.split("-").map(Number);
222
- return !(y === year && m === month + 1 && isEvent(year, month, d));
223
- }),
224
- );
225
- }
226
-
227
- // Handle Today button touch start
228
- function handleTodayTouchStart() {
229
- if (isSwiping) return;
230
- todayButtonPressed = true;
231
- triggerHaptic('light');
232
- }
233
-
234
- // Handle Today button touch end
235
- function handleTodayTouchEnd() {
236
- todayButtonPressed = false;
237
- }
238
-
239
- // Navigate to today's month with animation
240
- function goToToday(event) {
241
- // Prevent action if user is swiping
242
- if (isSwiping) return;
243
-
244
- // Remove focus/hover state from button immediately on mobile
245
- if (event?.target) {
246
- event.target.blur();
247
- }
248
-
249
- const today = new Date();
250
- const todayYear = today.getUTCFullYear();
251
- const todayMonth = today.getUTCMonth();
252
-
253
- const currentYearVal = $currentYear;
254
- const currentMonthVal = $currentMonth;
255
-
256
- // Calculate if we're going forward or backward in time
257
- const currentDate = new Date(currentYearVal, currentMonthVal, 1);
258
- const targetDate = new Date(todayYear, todayMonth, 1);
259
-
260
- if (targetDate > currentDate) {
261
- // Going forward in time - slide from right
262
- slideDirection = 1;
263
- } else if (targetDate < currentDate) {
264
- // Going backward in time - slide from left
265
- slideDirection = -1;
266
- } else {
267
- // Already on today's month - no animation needed
268
- return;
269
- }
270
-
271
- currentYear.set(todayYear);
272
- currentMonth.set(todayMonth);
273
-
274
- // Reset slide direction after animation
275
- setTimeout(() => {
276
- slideDirection = 0;
277
- }, 300);
278
- }
279
- </script>
280
-
281
- <div class="calendar-container">
282
- <!-- Month Navigation -->
283
- <header class="calendar-header sticky top-0 bg-bg-primary z-10">
284
- <button
285
- on:click={handlePrev}
286
- class="nav-btn"
287
- class:animating={prevAnimating}
288
- aria-label="Previous month"
289
- >
290
- <Icon name="ChevronLeft" size="16" />
291
- </button>
292
-
293
- <div class="month-display">
294
- {#key `${$currentYear}-${$currentMonth}`}
295
- <div class="month-content-wrapper" in:fly={{ x: slideDirection * 100, duration: 250, easing: cubicOut, opacity: 0 }} out:fly={{ x: slideDirection * -100, duration: 250, easing: cubicOut, opacity: 0 }}>
296
- <div class="month-content">
297
- <h2 class="month-title">
298
- {new Intl.DateTimeFormat("en", { month: "long" }).format(
299
- new Date($currentYear, $currentMonth),
300
- )}
301
- </h2>
302
- <span class="year-text">{$currentYear}</span>
303
- </div>
304
- {#if saveStatus}
305
- <div class="save-indicator-overlay">
306
- {#if saveStatus === "saving"}
307
- <span class="animate-spin text-green-500">
308
- <Icon name="Reload" size="20" />
309
- </span>
310
- {:else if saveStatus === "saved"}
311
- <span class="text-green-500">
312
- <Icon name="CheckCircle" size="20" />
313
- </span>
314
- {/if}
315
- </div>
316
- {/if}
317
- </div>
318
- {/key}
319
- </div>
320
-
321
- <button
322
- on:click={handleNext}
323
- class="nav-btn"
324
- class:animating={nextAnimating}
325
- aria-label="Next month"
326
- >
327
- <Icon name="ChevronRight" size="16" />
328
- </button>
329
- </header>
330
-
331
- <!-- Calendar Grid -->
332
- <div class="calendar-grid-wrapper">
333
- {#key `${$currentYear}-${$currentMonth}-${Object.keys(events).length}`}
334
- <div
335
- class="calendar-grid"
336
- on:touchstart={handleTouchStart}
337
- on:touchmove={handleTouchMove}
338
- on:touchend={handleTouchEnd}
339
- in:fly={{ x: slideDirection * 100, duration: 250, easing: cubicOut }}
340
- out:fly={{ x: slideDirection * -100, duration: 250, easing: cubicOut }}
341
- >
342
- {#each ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] as dayName}
343
- <div class="day-header">{dayName}</div>
344
- {/each}
345
-
346
- {#each Array(getDay(startOfMonth(new Date($currentYear, $currentMonth)))) as _}
347
- <div class="empty-day"></div>
348
- {/each}
349
-
350
- {#each Array(getDaysInMonth(new Date($currentYear, $currentMonth)))
351
- .fill()
352
- .map((_, i) => i + 1) as day}
353
- {@const isPast = isPastDate($currentYear, $currentMonth, day)}
354
- {@const isDisabled = !isEvent($currentYear, $currentMonth, day) || isPast}
355
- {@const isSelected = $selectedDates.includes(
356
- `${$currentYear}-${String($currentMonth + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`
357
- )}
358
- {@const isPastSelected = isPast && isSelected}
359
-
360
- <button
361
- class="day-cell"
362
- class:disabled={isDisabled}
363
- class:selected={isSelected && !isPast}
364
- class:past-selected={isPastSelected}
365
- on:click={() => !isDisabled && toggleDateSelection($currentYear, $currentMonth, day)}
366
- disabled={isDisabled}
367
- aria-label="Day {day}"
368
- aria-pressed={isSelected}
369
- >
370
- <span class="day-number">
371
- {day}
372
- </span>
373
- </button>
374
- {/each}
375
-
376
- <!-- Fill remaining cells in the last row to maintain grid structure -->
377
- {#each Array((7 - ((getDay(startOfMonth(new Date($currentYear, $currentMonth))) + getDaysInMonth(new Date($currentYear, $currentMonth))) % 7)) % 7) as _}
378
- <div class="empty-day"></div>
379
- {/each}
380
- </div>
381
- {/key}
382
- </div>
383
-
384
- <!-- Quick Actions -->
385
- <div class="action-buttons" class:swiping={isSwiping}>
386
- <div
387
- class="today-button-wrapper"
388
- class:pressed={todayButtonPressed}
389
- on:touchstart={handleTodayTouchStart}
390
- on:touchend={handleTodayTouchEnd}
391
- on:touchcancel={handleTodayTouchEnd}
392
- >
393
- <Button
394
- variant="blue-outline"
395
- type="button"
396
- size="lg"
397
- on:click={goToToday}
398
- >
399
- Today
400
- </Button>
401
- </div>
402
- </div>
403
- </div>
404
-
405
- <style>
406
- .calendar-container {
407
- margin-left: auto;
408
- margin-right: auto;
409
- width: 100%;
410
- max-width: 28rem;
411
- text-align: center;
412
- touch-action: manipulation;
413
- }
414
-
415
- .calendar-header {
416
- margin-bottom: 1.5rem;
417
- padding-left: 0.5rem;
418
- padding-right: 0.5rem;
419
- display: grid;
420
- grid-template-columns: 40px minmax(0, 1fr) 40px;
421
- align-items: center;
422
- gap: 8px;
423
- position: relative;
424
- isolation: isolate;
425
- -moz-user-select: none;
426
- user-select: none;
427
- -webkit-user-select: none;
428
- -webkit-touch-callout: none;
429
- }
430
-
431
- .nav-btn {
432
- display: flex;
433
- height: 2.5rem;
434
- width: 2.5rem;
435
- align-items: center;
436
- justify-content: center;
437
- border-radius: 0.5rem;
438
- border-width: 1px;
439
- --tw-border-opacity: 1;
440
- border-color: rgb(29 78 216 / var(--tw-border-opacity, 1));
441
- background-color: hsl(var(--BG-Primary));
442
- padding: 0.75rem;
443
- --tw-text-opacity: 1;
444
- color: rgb(29 78 216 / var(--tw-text-opacity, 1));
445
- transition: opacity 0.15s ease;
446
- -webkit-tap-highlight-color: transparent;
447
- touch-action: manipulation;
448
- -moz-user-select: none;
449
- user-select: none;
450
- -webkit-user-select: none;
451
- -webkit-touch-callout: none;
452
- }
453
-
454
- .nav-btn.animating {
455
- opacity: 0.4;
456
- }
457
-
458
- .month-display {
459
- position: relative;
460
- min-height: 48px;
461
- overflow: hidden;
462
- display: flex;
463
- align-items: center;
464
- justify-content: center;
465
- min-width: 0;
466
- }
467
-
468
- .month-content-wrapper {
469
- position: absolute;
470
- top: 0;
471
- bottom: 0;
472
- left: 0;
473
- right: 0;
474
- display: flex;
475
- align-items: center;
476
- justify-content: center;
477
- /* GPU acceleration */
478
- transform: translateZ(0);
479
- backface-visibility: hidden;
480
- will-change: transform;
481
- }
482
-
483
- .month-content {
484
- display: flex;
485
- flex-direction: column;
486
- align-items: center;
487
- white-space: nowrap;
488
- }
489
-
490
- .month-title {
491
- font-size: 1.125rem;
492
- line-height: 1.75rem;
493
- font-weight: 500;
494
- color: hsl(var(--Text-Primary));
495
- line-height: 1.2;
496
- }
497
-
498
- .year-text {
499
- font-size: 0.75rem;
500
- line-height: 1rem;
501
- font-weight: 400;
502
- color: hsl(var(--Text-Tartiary));
503
- line-height: 1;
504
- margin-top: 2px;
505
- }
506
-
507
- .save-indicator-overlay {
508
- position: absolute;
509
- left: 50%;
510
- top: 50%;
511
- transform: translate(50px, -50%);
512
- display: flex;
513
- align-items: center;
514
- justify-content: center;
515
- width: 24px;
516
- height: 24px;
517
- z-index: 1;
518
- }
519
-
520
- .calendar-grid-wrapper {
521
- position: relative;
522
- overflow: hidden;
523
- /* Set min-height for typical calendar (most months are 5-6 weeks) */
524
- min-height: 410px;
525
- }
526
-
527
- .calendar-grid {
528
- display: grid;
529
- grid-template-columns: repeat(7, minmax(0, 1fr));
530
- grid-auto-rows: minmax(56px, auto);
531
- /* GPU acceleration for smooth grid sliding */
532
- transform: translateZ(0);
533
- backface-visibility: hidden;
534
- will-change: transform;
535
- position: absolute;
536
- width: 100%;
537
- top: 0;
538
- left: 0;
539
- border-width: 1px;
540
- border-color: hsl(var(--Stroke-Secondary));
541
- border-radius: 8px;
542
- overflow: hidden;
543
- }
544
-
545
- .day-header {
546
- border-bottom-width: 1px;
547
- border-right-width: 1px;
548
- border-color: hsl(var(--Stroke-Secondary));
549
- background-color: hsl(var(--BG-Primary));
550
- padding-top: 0.75rem;
551
- padding-bottom: 0.75rem;
552
- font-size: 0.875rem;
553
- line-height: 1.25rem;
554
- font-weight: 500;
555
- color: hsl(var(--Text-Tartiary));
556
- -moz-user-select: none;
557
- user-select: none;
558
- -webkit-user-select: none;
559
- -webkit-touch-callout: none;
560
- }
561
-
562
- /* Top-left corner */
563
- .day-header:nth-child(1) {
564
- border-top-left-radius: 8px;
565
- }
566
-
567
- /* Top-right corner */
568
- .day-header:nth-child(7) {
569
- border-top-right-radius: 8px;
570
- border-right: none;
571
- }
572
-
573
- .day-header:nth-child(7n) {
574
- border-right: none;
575
- }
576
-
577
- .empty-day {
578
- height: 3.5rem;
579
- border-bottom-width: 1px;
580
- border-right-width: 1px;
581
- border-color: hsl(var(--Stroke-Secondary));
582
- background-color: hsl(var(--BG-Primary));
583
- }
584
-
585
- .empty-day:nth-child(7n) {
586
- border-right: none;
587
- }
588
-
589
- /* Bottom-left corner - target last row, first column */
590
- .empty-day:last-child:nth-child(7n+1) {
591
- border-bottom-left-radius: 8px;
592
- }
593
-
594
- /* Bottom-right corner - target last row, last column */
595
- .empty-day:last-child:nth-child(7n) {
596
- border-bottom-right-radius: 8px;
597
- }
598
-
599
- .day-cell {
600
- display: flex;
601
- height: 3.5rem;
602
- cursor: pointer;
603
- align-items: center;
604
- justify-content: center;
605
- border-bottom-width: 1px;
606
- border-right-width: 1px;
607
- border-color: hsl(var(--Stroke-Secondary));
608
- background-color: hsl(var(--BG-Primary));
609
- padding: 0.25rem;
610
- transition: background-color 0.1s ease;
611
- -webkit-tap-highlight-color: transparent;
612
- touch-action: manipulation;
613
- -moz-user-select: none;
614
- user-select: none;
615
- -webkit-user-select: none;
616
- -webkit-touch-callout: none;
617
- }
618
-
619
- .day-cell:nth-child(7n) {
620
- border-right: none;
621
- }
622
-
623
- /* Bottom-left corner - target last row, first column for day cells */
624
- .day-cell:last-child:nth-child(7n+1) {
625
- border-bottom-left-radius: 8px;
626
- }
627
-
628
- /* Bottom-right corner - target last row, last column for day cells */
629
- .day-cell:last-child:nth-child(7n) {
630
- border-bottom-right-radius: 8px;
631
- }
632
-
633
- .day-number {
634
- display: flex;
635
- height: 2rem;
636
- width: 2rem;
637
- align-items: center;
638
- justify-content: center;
639
- border-radius: 0.375rem;
640
- font-size: 0.875rem;
641
- line-height: 1.25rem;
642
- font-weight: 500;
643
- transition: all 0.15s ease;
644
- -moz-user-select: none;
645
- user-select: none;
646
- -webkit-user-select: none;
647
- -webkit-touch-callout: none;
648
- }
649
-
650
- .day-cell:not(.disabled):not(.selected) .day-number {
651
- color: hsl(var(--Text-Primary));
652
- }
653
-
654
- .day-cell:not(.disabled):not(.selected):active .day-number {
655
- --tw-bg-opacity: 1;
656
- background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1));
657
- transform: scale(0.95);
658
- box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2);
659
- }
660
-
661
- .day-cell.selected .day-number {
662
- --tw-bg-opacity: 1;
663
- background-color: rgb(29 78 216 / var(--tw-bg-opacity, 1));
664
- --tw-text-opacity: 1;
665
- color: rgb(255 255 255 / var(--tw-text-opacity, 1));
666
- }
667
-
668
- .day-cell.selected:active .day-number {
669
- transform: scale(0.95);
670
- box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.3);
671
- }
672
-
673
- .day-cell.past-selected .day-number {
674
- background-color: hsl(var(--BG-Quaternary));
675
- color: hsl(var(--Text-Tartiary));
676
- }
677
-
678
- .day-cell.disabled {
679
- background-color: hsl(var(--BG-Secondary) / 0.5);
680
- }
681
-
682
- .day-cell.disabled .day-number {
683
- pointer-events: none;
684
- color: hsl(var(--Text-Tartiary) / 0.5);
685
- }
686
-
687
- .action-buttons {
688
- display: flex;
689
- justify-content: center;
690
- }
691
-
692
- .action-buttons.swiping {
693
- pointer-events: none;
694
- touch-action: none;
695
- }
696
-
697
- .today-button-wrapper {
698
- transition: all 0.15s ease;
699
- -webkit-tap-highlight-color: transparent;
700
- -moz-user-select: none;
701
- user-select: none;
702
- -webkit-user-select: none;
703
- -webkit-touch-callout: none;
704
- }
705
-
706
- .today-button-wrapper.pressed :global(button) {
707
- background-color: rgba(99, 102, 241, 0.1) !important;
708
- transform: scale(0.95);
709
- box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2);
710
- }
711
-
712
- /* Prevent hover state from sticking on mobile */
713
- .action-buttons :global(button) {
714
- -webkit-tap-highlight-color: transparent;
715
- transition: all 0.15s ease;
716
- -moz-user-select: none;
717
- user-select: none;
718
- -webkit-user-select: none;
719
- -webkit-touch-callout: none;
720
- }
721
-
722
- @media (hover: none) {
723
- .action-buttons :global(button:hover) {
724
- /* Disable hover styles on touch devices */
725
- background-color: transparent !important;
726
- }
727
- }
728
-
729
- @media (prefers-reduced-motion: reduce) {
730
- .nav-btn,
731
- .day-number,
732
- .day-cell {
733
- transition: none;
734
- }
735
- }
736
- </style>