@nomideusz/svelte-calendar 0.6.8 → 0.7.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/README.md +88 -2
- package/dist/calendar/Calendar.svelte +129 -47
- package/dist/primitives/DayHeader.svelte +5 -5
- package/dist/primitives/EmptySlot.svelte +4 -4
- package/dist/primitives/EventBlock.svelte +13 -13
- package/dist/primitives/NowIndicator.svelte +1 -1
- package/dist/primitives/TimeGutter.svelte +4 -4
- package/dist/views/agenda/AgendaDay.svelte +35 -157
- package/dist/views/agenda/AgendaWeek.svelte +20 -109
- package/dist/views/mobile/MobileDay.svelte +3 -3
- package/dist/views/mobile/MobileWeek.svelte +4 -4
- package/dist/views/planner/PlannerDay.svelte +21 -135
- package/dist/views/planner/PlannerWeek.svelte +39 -99
- package/dist/views/shared/context.svelte.d.ts +0 -1
- package/dist/views/shared/context.svelte.js +0 -1
- package/package.json +15 -15
- package/widget/svelte-calendar.css +2717 -1
- package/widget/widget.js +10605 -6
|
@@ -417,7 +417,7 @@
|
|
|
417
417
|
padding: 4px 8px;
|
|
418
418
|
overflow-x: auto;
|
|
419
419
|
scrollbar-width: none;
|
|
420
|
-
border-bottom: 1px solid var(--dt-border, rgba(0, 0, 0, 0.
|
|
420
|
+
border-bottom: 1px solid var(--dt-border, rgba(0, 0, 0, 0.08));
|
|
421
421
|
flex-shrink: 0;
|
|
422
422
|
align-items: center;
|
|
423
423
|
}
|
|
@@ -481,7 +481,7 @@
|
|
|
481
481
|
overflow-x: hidden;
|
|
482
482
|
-webkit-overflow-scrolling: touch;
|
|
483
483
|
scrollbar-width: thin;
|
|
484
|
-
scrollbar-color: var(--dt-scrollbar, rgba(0, 0, 0, 0.
|
|
484
|
+
scrollbar-color: var(--dt-scrollbar, rgba(0, 0, 0, 0.1)) transparent;
|
|
485
485
|
position: relative;
|
|
486
486
|
padding-top: 8px;
|
|
487
487
|
}
|
|
@@ -668,7 +668,7 @@
|
|
|
668
668
|
|
|
669
669
|
.mb-ev-loc {
|
|
670
670
|
font: 400 10px/1 var(--dt-sans, system-ui, sans-serif);
|
|
671
|
-
color: var(--dt-text-3, rgba(0, 0, 0, 0.
|
|
671
|
+
color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
|
|
672
672
|
white-space: nowrap;
|
|
673
673
|
overflow: hidden;
|
|
674
674
|
text-overflow: ellipsis;
|
|
@@ -295,7 +295,7 @@
|
|
|
295
295
|
overflow-y: auto;
|
|
296
296
|
-webkit-overflow-scrolling: touch;
|
|
297
297
|
scrollbar-width: thin;
|
|
298
|
-
scrollbar-color: var(--dt-scrollbar, rgba(0, 0, 0, 0.
|
|
298
|
+
scrollbar-color: var(--dt-scrollbar, rgba(0, 0, 0, 0.1)) transparent;
|
|
299
299
|
}
|
|
300
300
|
.mw--auto .mw-list { overflow-y: visible; }
|
|
301
301
|
|
|
@@ -311,7 +311,7 @@
|
|
|
311
311
|
text-align: left;
|
|
312
312
|
width: 100%;
|
|
313
313
|
-webkit-tap-highlight-color: transparent;
|
|
314
|
-
border-bottom: 1px solid var(--dt-border, rgba(0, 0, 0, 0.
|
|
314
|
+
border-bottom: 1px solid var(--dt-border, rgba(0, 0, 0, 0.08));
|
|
315
315
|
min-height: 56px;
|
|
316
316
|
}
|
|
317
317
|
.mw-row:last-child {
|
|
@@ -405,7 +405,7 @@
|
|
|
405
405
|
|
|
406
406
|
.mw-empty {
|
|
407
407
|
font: 400 12px/1 var(--dt-sans, system-ui, sans-serif);
|
|
408
|
-
color: var(--dt-text-3, rgba(0, 0, 0, 0.
|
|
408
|
+
color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
|
|
409
409
|
font-style: italic;
|
|
410
410
|
}
|
|
411
411
|
|
|
@@ -497,7 +497,7 @@
|
|
|
497
497
|
/* ─── Chevron ────────────────────────────────────── */
|
|
498
498
|
.mw-chevron {
|
|
499
499
|
flex-shrink: 0;
|
|
500
|
-
color: var(--dt-text-3, rgba(0, 0, 0, 0.
|
|
500
|
+
color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
|
|
501
501
|
position: relative;
|
|
502
502
|
z-index: 1;
|
|
503
503
|
pointer-events: none;
|
|
@@ -66,8 +66,6 @@
|
|
|
66
66
|
const commitDragCtx = $derived(ctx.commitDrag);
|
|
67
67
|
const viewState = $derived(ctx.viewState);
|
|
68
68
|
const loadRangeCtx = $derived(ctx.loadRange);
|
|
69
|
-
const showNav = $derived(ctx.showNav);
|
|
70
|
-
const showDates = $derived(ctx.showDates);
|
|
71
69
|
const blockedSlots = $derived(ctx.blockedSlots);
|
|
72
70
|
const dayHeaderSnippet = $derived(ctx.dayHeaderSnippet);
|
|
73
71
|
const minDuration = $derived(ctx.minDuration);
|
|
@@ -105,18 +103,6 @@
|
|
|
105
103
|
const hourCount = $derived(Math.max(1, endHour - startHour));
|
|
106
104
|
const DAY_GAP = 2;
|
|
107
105
|
|
|
108
|
-
const dateLabel = $derived(
|
|
109
|
-
showDates
|
|
110
|
-
? new Date(visibleDayMs).toLocaleDateString(locale ?? 'en-US', {
|
|
111
|
-
weekday: 'long',
|
|
112
|
-
month: 'long',
|
|
113
|
-
day: 'numeric',
|
|
114
|
-
})
|
|
115
|
-
: new Date(visibleDayMs).toLocaleDateString(locale ?? 'en-US', {
|
|
116
|
-
weekday: 'long',
|
|
117
|
-
})
|
|
118
|
-
);
|
|
119
|
-
|
|
120
106
|
const count = 1 + 2 * BUFFER_DAYS;
|
|
121
107
|
const origin = $derived(internalCenterMs - BUFFER_DAYS * DAY_MS);
|
|
122
108
|
|
|
@@ -346,7 +332,8 @@
|
|
|
346
332
|
lastExternalMs = ext;
|
|
347
333
|
internalCenterMs = ext;
|
|
348
334
|
visibleDayMs = ext;
|
|
349
|
-
|
|
335
|
+
// Landing on today (e.g. header "Today" button) resumes auto-follow.
|
|
336
|
+
following = ext === clock.today;
|
|
350
337
|
// After DOM update, recenter scroll on focus day.
|
|
351
338
|
tick().then(() => {
|
|
352
339
|
if (el) {
|
|
@@ -716,35 +703,6 @@
|
|
|
716
703
|
</div>
|
|
717
704
|
{/if}
|
|
718
705
|
|
|
719
|
-
<div class="fs-date-label">{dateLabel}</div>
|
|
720
|
-
|
|
721
|
-
{#if showNav}
|
|
722
|
-
<nav class="fs-nav" aria-label={L.dayNavigation}>
|
|
723
|
-
<button
|
|
724
|
-
class="fs-nav-pill fs-nav-today"
|
|
725
|
-
class:fs-nav-today--hidden={following}
|
|
726
|
-
onclick={() => { internalCenterMs = clock.today; lastExternalMs = clock.today; viewState?.goToday(); following = true; }}
|
|
727
|
-
aria-label={L.goToToday}
|
|
728
|
-
tabindex={following ? -1 : 0}
|
|
729
|
-
>
|
|
730
|
-
{L.today}
|
|
731
|
-
</button>
|
|
732
|
-
<button
|
|
733
|
-
class="fs-nav-pill"
|
|
734
|
-
onclick={() => { const prev = internalCenterMs - DAY_MS; internalCenterMs = prev; lastExternalMs = prev; viewState?.prev(); following = false; }}
|
|
735
|
-
aria-label={L.previousDay}
|
|
736
|
-
>
|
|
737
|
-
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="12" height="12" aria-hidden="true"><path d="M10 3 5 8l5 5"/></svg>
|
|
738
|
-
</button>
|
|
739
|
-
<button
|
|
740
|
-
class="fs-nav-pill"
|
|
741
|
-
onclick={() => { const next = internalCenterMs + DAY_MS; internalCenterMs = next; lastExternalMs = next; viewState?.next(); following = false; }}
|
|
742
|
-
aria-label={L.nextDay}
|
|
743
|
-
>
|
|
744
|
-
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="12" height="12" aria-hidden="true"><path d="M6 3l5 5-5 5"/></svg>
|
|
745
|
-
</button>
|
|
746
|
-
</nav>
|
|
747
|
-
{/if}
|
|
748
706
|
</div>
|
|
749
707
|
|
|
750
708
|
<style>
|
|
@@ -766,12 +724,12 @@
|
|
|
766
724
|
touch-action: pan-x;
|
|
767
725
|
cursor: default;
|
|
768
726
|
scrollbar-width: thin;
|
|
769
|
-
scrollbar-color: var(--dt-scrollbar, rgba(0, 0, 0, 0.
|
|
727
|
+
scrollbar-color: var(--dt-scrollbar, rgba(0, 0, 0, 0.1)) transparent;
|
|
770
728
|
}
|
|
771
729
|
.fs--auto .fs-scroll { height: auto; overflow: visible; }
|
|
772
730
|
.fs-scroll::-webkit-scrollbar { height: 5px; }
|
|
773
731
|
.fs-scroll::-webkit-scrollbar-thumb {
|
|
774
|
-
background: var(--dt-scrollbar, rgba(0, 0, 0, 0.
|
|
732
|
+
background: var(--dt-scrollbar, rgba(0, 0, 0, 0.1));
|
|
775
733
|
border-radius: 4px;
|
|
776
734
|
}
|
|
777
735
|
.fs-scroll::-webkit-scrollbar-track { background: transparent; }
|
|
@@ -788,11 +746,11 @@
|
|
|
788
746
|
position: absolute;
|
|
789
747
|
top: 0;
|
|
790
748
|
height: 100%;
|
|
791
|
-
border-left: 1px solid var(--dt-border-day, rgba(
|
|
749
|
+
border-left: 1px solid var(--dt-border-day, rgba(0, 0, 0, 0.14));
|
|
792
750
|
box-sizing: border-box;
|
|
793
751
|
}
|
|
794
752
|
.fs-day:first-of-type { border-left: none; }
|
|
795
|
-
.fs-today { background: var(--dt-today-bg, rgba(
|
|
753
|
+
.fs-today { background: var(--dt-today-bg, rgba(37, 99, 235, 0.04)); }
|
|
796
754
|
.fs-past { opacity: 0.7; }
|
|
797
755
|
|
|
798
756
|
/* ─── Disabled day ───────────────────────────────── */
|
|
@@ -802,8 +760,8 @@
|
|
|
802
760
|
45deg,
|
|
803
761
|
transparent,
|
|
804
762
|
transparent 6px,
|
|
805
|
-
var(--dt-border, rgba(
|
|
806
|
-
var(--dt-border, rgba(
|
|
763
|
+
var(--dt-border, rgba(0, 0, 0, 0.08)) 6px,
|
|
764
|
+
var(--dt-border, rgba(0, 0, 0, 0.08)) 7px
|
|
807
765
|
) !important;
|
|
808
766
|
}
|
|
809
767
|
|
|
@@ -815,8 +773,8 @@
|
|
|
815
773
|
z-index: 3;
|
|
816
774
|
background: repeating-linear-gradient(
|
|
817
775
|
-45deg,
|
|
818
|
-
color-mix(in srgb, var(--dt-text, rgba(
|
|
819
|
-
color-mix(in srgb, var(--dt-text, rgba(
|
|
776
|
+
color-mix(in srgb, var(--dt-text, rgba(0, 0, 0, 0.87)) 4%, transparent),
|
|
777
|
+
color-mix(in srgb, var(--dt-text, rgba(0, 0, 0, 0.87)) 4%, transparent) 4px,
|
|
820
778
|
transparent 4px,
|
|
821
779
|
transparent 8px
|
|
822
780
|
);
|
|
@@ -830,7 +788,7 @@
|
|
|
830
788
|
|
|
831
789
|
.fs-blocked-label {
|
|
832
790
|
font: 500 9px/1 var(--dt-sans, system-ui, sans-serif);
|
|
833
|
-
color: var(--dt-text-3, rgba(
|
|
791
|
+
color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
|
|
834
792
|
text-transform: uppercase;
|
|
835
793
|
letter-spacing: 0.04em;
|
|
836
794
|
white-space: nowrap;
|
|
@@ -860,14 +818,14 @@
|
|
|
860
818
|
top: 18px;
|
|
861
819
|
bottom: 0;
|
|
862
820
|
width: 1px;
|
|
863
|
-
background: var(--dt-border, rgba(
|
|
821
|
+
background: var(--dt-border, rgba(0, 0, 0, 0.08));
|
|
864
822
|
}
|
|
865
823
|
.fs-tick-lb {
|
|
866
824
|
position: absolute;
|
|
867
825
|
top: 2px;
|
|
868
826
|
left: 5px;
|
|
869
827
|
font: 500 10px/1 var(--dt-mono, ui-monospace, monospace);
|
|
870
|
-
color: var(--dt-text-3, rgba(
|
|
828
|
+
color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
|
|
871
829
|
white-space: nowrap;
|
|
872
830
|
pointer-events: none;
|
|
873
831
|
}
|
|
@@ -895,7 +853,7 @@
|
|
|
895
853
|
left: 0;
|
|
896
854
|
width: 2px;
|
|
897
855
|
background: var(--dt-accent, #2563eb);
|
|
898
|
-
box-shadow: 0 0 8px var(--dt-glow, rgba(
|
|
856
|
+
box-shadow: 0 0 8px var(--dt-glow, rgba(37, 99, 235, 0.25));
|
|
899
857
|
}
|
|
900
858
|
.fs-now-tag {
|
|
901
859
|
position: absolute;
|
|
@@ -904,7 +862,7 @@
|
|
|
904
862
|
font: 700 11px/1 var(--dt-mono, ui-monospace, monospace);
|
|
905
863
|
color: var(--dt-accent, #2563eb);
|
|
906
864
|
background: color-mix(in srgb, var(--dt-bg, #ffffff) 92%, var(--dt-accent, #2563eb));
|
|
907
|
-
border: 1px solid var(--dt-accent-dim, rgba(
|
|
865
|
+
border: 1px solid var(--dt-accent-dim, rgba(37, 99, 235, 0.12));
|
|
908
866
|
padding: 3px 6px;
|
|
909
867
|
border-radius: 4px;
|
|
910
868
|
white-space: nowrap;
|
|
@@ -916,78 +874,6 @@
|
|
|
916
874
|
font-size: 10px;
|
|
917
875
|
}
|
|
918
876
|
|
|
919
|
-
/* ─── Floating date label ────────────────────────── */
|
|
920
|
-
.fs-date-label {
|
|
921
|
-
position: absolute;
|
|
922
|
-
top: 22px;
|
|
923
|
-
left: 50%;
|
|
924
|
-
transform: translateX(-50%);
|
|
925
|
-
z-index: 20;
|
|
926
|
-
font: 600 11px/1 var(--dt-sans, system-ui, sans-serif);
|
|
927
|
-
letter-spacing: 0.04em;
|
|
928
|
-
text-transform: uppercase;
|
|
929
|
-
color: var(--dt-text, rgba(226, 232, 240, 0.85));
|
|
930
|
-
background: color-mix(in srgb, var(--dt-surface, var(--dt-bg, #ffffff)) 85%, transparent);
|
|
931
|
-
backdrop-filter: blur(6px);
|
|
932
|
-
-webkit-backdrop-filter: blur(6px);
|
|
933
|
-
padding: 8px 16px;
|
|
934
|
-
border-radius: 8px;
|
|
935
|
-
border: 1px solid var(--dt-border, rgba(148, 163, 184, 0.07));
|
|
936
|
-
pointer-events: none;
|
|
937
|
-
white-space: nowrap;
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
/* ─── Navigation pills ────────────────────────────── */
|
|
941
|
-
.fs-nav {
|
|
942
|
-
position: absolute;
|
|
943
|
-
top: 22px;
|
|
944
|
-
right: 14px;
|
|
945
|
-
z-index: 20;
|
|
946
|
-
display: flex;
|
|
947
|
-
gap: 2px;
|
|
948
|
-
background: color-mix(in srgb, var(--dt-surface, var(--dt-bg, #ffffff)) 85%, transparent);
|
|
949
|
-
backdrop-filter: blur(6px);
|
|
950
|
-
-webkit-backdrop-filter: blur(6px);
|
|
951
|
-
border-radius: 8px;
|
|
952
|
-
padding: 2px;
|
|
953
|
-
border: 1px solid var(--dt-border, rgba(148, 163, 184, 0.07));
|
|
954
|
-
}
|
|
955
|
-
.fs-nav-pill {
|
|
956
|
-
border: none;
|
|
957
|
-
background: transparent;
|
|
958
|
-
color: var(--dt-text-2, rgba(148, 163, 184, 0.55));
|
|
959
|
-
cursor: pointer;
|
|
960
|
-
font: 600 11px / 1 var(--dt-sans, system-ui, sans-serif);
|
|
961
|
-
padding: 6px 12px;
|
|
962
|
-
border-radius: 6px;
|
|
963
|
-
letter-spacing: 0.04em;
|
|
964
|
-
text-transform: uppercase;
|
|
965
|
-
transition: background 100ms, color 100ms;
|
|
966
|
-
display: inline-flex;
|
|
967
|
-
align-items: center;
|
|
968
|
-
justify-content: center;
|
|
969
|
-
}
|
|
970
|
-
.fs-nav-pill:hover {
|
|
971
|
-
color: var(--dt-text, rgba(226, 232, 240, 0.85));
|
|
972
|
-
}
|
|
973
|
-
.fs-nav-today {
|
|
974
|
-
max-width: 60px;
|
|
975
|
-
overflow: hidden;
|
|
976
|
-
white-space: nowrap;
|
|
977
|
-
transition: max-width 250ms ease, padding 250ms ease, opacity 200ms ease;
|
|
978
|
-
}
|
|
979
|
-
.fs-nav-today--hidden {
|
|
980
|
-
max-width: 0;
|
|
981
|
-
padding-left: 0;
|
|
982
|
-
padding-right: 0;
|
|
983
|
-
opacity: 0;
|
|
984
|
-
pointer-events: none;
|
|
985
|
-
}
|
|
986
|
-
.fs-nav-pill:focus-visible {
|
|
987
|
-
outline: 2px solid color-mix(in srgb, var(--dt-accent, #2563eb) 55%, transparent);
|
|
988
|
-
outline-offset: 2px;
|
|
989
|
-
}
|
|
990
|
-
|
|
991
877
|
/* ─── All-day strip ─────────────────────────────── */
|
|
992
878
|
.fs-allday {
|
|
993
879
|
position: absolute;
|
|
@@ -1039,7 +925,7 @@
|
|
|
1039
925
|
.fs-ad-title {
|
|
1040
926
|
font-size: 0.7rem;
|
|
1041
927
|
font-weight: 500;
|
|
1042
|
-
color: var(--dt-text,
|
|
928
|
+
color: var(--dt-text, rgba(0, 0, 0, 0.87));
|
|
1043
929
|
max-width: 120px;
|
|
1044
930
|
overflow: hidden;
|
|
1045
931
|
text-overflow: ellipsis;
|
|
@@ -1047,7 +933,7 @@
|
|
|
1047
933
|
|
|
1048
934
|
.fs-ad-span {
|
|
1049
935
|
font-size: 0.6rem;
|
|
1050
|
-
color: var(--dt-text-2, rgba(
|
|
936
|
+
color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
|
|
1051
937
|
flex-shrink: 0;
|
|
1052
938
|
}
|
|
1053
939
|
|
|
@@ -1143,7 +1029,7 @@
|
|
|
1143
1029
|
}
|
|
1144
1030
|
.fs-ev-title {
|
|
1145
1031
|
font: 600 13px/1.15 var(--dt-sans, system-ui, sans-serif);
|
|
1146
|
-
color: var(--dt-text, rgba(
|
|
1032
|
+
color: var(--dt-text, rgba(0, 0, 0, 0.87));
|
|
1147
1033
|
overflow: hidden;
|
|
1148
1034
|
text-overflow: ellipsis;
|
|
1149
1035
|
white-space: nowrap;
|
|
@@ -1152,14 +1038,14 @@
|
|
|
1152
1038
|
}
|
|
1153
1039
|
.fs-ev-time {
|
|
1154
1040
|
font: 400 10px/1 var(--dt-mono, ui-monospace, monospace);
|
|
1155
|
-
color: var(--dt-text-2, rgba(
|
|
1041
|
+
color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
|
|
1156
1042
|
opacity: 0.7;
|
|
1157
1043
|
white-space: nowrap;
|
|
1158
1044
|
flex-shrink: 0;
|
|
1159
1045
|
}
|
|
1160
1046
|
.fs-ev-sub {
|
|
1161
1047
|
font: 400 11px/1 var(--dt-sans, system-ui, sans-serif);
|
|
1162
|
-
color: var(--dt-text-2, rgba(
|
|
1048
|
+
color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
|
|
1163
1049
|
opacity: 0.6;
|
|
1164
1050
|
white-space: nowrap;
|
|
1165
1051
|
overflow: hidden;
|
|
@@ -1169,7 +1055,7 @@
|
|
|
1169
1055
|
}
|
|
1170
1056
|
.fs-ev-loc {
|
|
1171
1057
|
font: 400 10px/1 var(--dt-sans, system-ui, sans-serif);
|
|
1172
|
-
color: var(--dt-text-3, rgba(
|
|
1058
|
+
color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
|
|
1173
1059
|
white-space: nowrap;
|
|
1174
1060
|
overflow: hidden;
|
|
1175
1061
|
text-overflow: ellipsis;
|
|
@@ -55,7 +55,6 @@
|
|
|
55
55
|
const commitDragCtx = $derived(ctx.commitDrag);
|
|
56
56
|
const viewState = $derived(ctx.viewState);
|
|
57
57
|
const loadRangeCtx = $derived(ctx.loadRange);
|
|
58
|
-
const showNav = $derived(ctx.showNav);
|
|
59
58
|
const equalDays = $derived(ctx.equalDays);
|
|
60
59
|
const showDates = $derived(ctx.showDates);
|
|
61
60
|
const hideDays = $derived(ctx.hideDays);
|
|
@@ -79,7 +78,6 @@
|
|
|
79
78
|
let lastExternalMs = _initMs;
|
|
80
79
|
|
|
81
80
|
let el: HTMLDivElement;
|
|
82
|
-
let scrolled = $state(false);
|
|
83
81
|
|
|
84
82
|
function scrollWeekIntoContainer(targetMs?: number, behavior: ScrollBehavior = 'auto') {
|
|
85
83
|
if (!el) return;
|
|
@@ -231,24 +229,31 @@
|
|
|
231
229
|
if (ext !== lastExternalMs) {
|
|
232
230
|
lastExternalMs = ext;
|
|
233
231
|
internalFocusMs = ext;
|
|
234
|
-
tick().then(() => scrollWeekIntoContainer(ext
|
|
232
|
+
tick().then(() => scrollWeekIntoContainer(ext));
|
|
235
233
|
}
|
|
236
234
|
});
|
|
237
235
|
|
|
238
|
-
|
|
239
|
-
function
|
|
240
|
-
if (!el) return
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
236
|
+
/** Push the week at the viewport centre to viewState (drives the header label + Today button). */
|
|
237
|
+
function syncFocusFromScroll() {
|
|
238
|
+
if (!el || !viewState) return;
|
|
239
|
+
const centerY = el.scrollTop + el.clientHeight / 2;
|
|
240
|
+
const rows = el.querySelectorAll<HTMLElement>('[data-week]');
|
|
241
|
+
for (const row of rows) {
|
|
242
|
+
if (row.offsetTop + row.offsetHeight >= centerY) {
|
|
243
|
+
const ms = Number(row.dataset.week);
|
|
244
|
+
if (Number.isFinite(ms) && ms !== lastExternalMs) {
|
|
245
|
+
lastExternalMs = ms;
|
|
246
|
+
viewState.setFocusDate(new Date(ms));
|
|
247
|
+
}
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
246
251
|
}
|
|
247
252
|
|
|
248
253
|
let extending = false;
|
|
249
254
|
|
|
250
255
|
function handleUserScroll() {
|
|
251
|
-
|
|
256
|
+
syncFocusFromScroll();
|
|
252
257
|
if (!el || extending) return;
|
|
253
258
|
// Extend buffer when user scrolls near the edge
|
|
254
259
|
if (el.scrollTop < EDGE_PX) {
|
|
@@ -268,16 +273,6 @@
|
|
|
268
273
|
}
|
|
269
274
|
}
|
|
270
275
|
|
|
271
|
-
function jumpToday() {
|
|
272
|
-
internalFocusMs = clock.today;
|
|
273
|
-
lastExternalMs = clock.today;
|
|
274
|
-
viewState?.goToday();
|
|
275
|
-
scrolled = false;
|
|
276
|
-
tick().then(() => {
|
|
277
|
-
scrollWeekIntoContainer(clock.today, 'smooth');
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
|
|
281
276
|
function handleDayCellClick(ms: number, e: Event) {
|
|
282
277
|
const target = e.target as HTMLElement;
|
|
283
278
|
if (target.closest('.wg-ev')) return;
|
|
@@ -570,17 +565,6 @@
|
|
|
570
565
|
{/each}
|
|
571
566
|
</div>
|
|
572
567
|
|
|
573
|
-
{#if showNav && scrolled}
|
|
574
|
-
<nav class="wg-nav" aria-label={L.weekNavigation}>
|
|
575
|
-
<button
|
|
576
|
-
class="wg-nav-pill"
|
|
577
|
-
onclick={jumpToday}
|
|
578
|
-
aria-label={L.goToToday}
|
|
579
|
-
>
|
|
580
|
-
{L.today}
|
|
581
|
-
</button>
|
|
582
|
-
</nav>
|
|
583
|
-
{/if}
|
|
584
568
|
</div>
|
|
585
569
|
|
|
586
570
|
<style>
|
|
@@ -601,9 +585,8 @@
|
|
|
601
585
|
overflow-y: auto;
|
|
602
586
|
overflow-x: hidden;
|
|
603
587
|
box-sizing: border-box;
|
|
604
|
-
padding-top: 48px;
|
|
605
588
|
scrollbar-width: thin;
|
|
606
|
-
scrollbar-color: var(--dt-scrollbar, rgba(0, 0, 0, 0.
|
|
589
|
+
scrollbar-color: var(--dt-scrollbar, rgba(0, 0, 0, 0.1)) transparent;
|
|
607
590
|
}
|
|
608
591
|
.wg--auto .wg-body { overflow-y: visible; }
|
|
609
592
|
|
|
@@ -624,7 +607,7 @@
|
|
|
624
607
|
}
|
|
625
608
|
|
|
626
609
|
.wg-week--current {
|
|
627
|
-
background: var(--dt-today-bg, rgba(
|
|
610
|
+
background: var(--dt-today-bg, rgba(37, 99, 235, 0.04));
|
|
628
611
|
border: 2.5px solid var(--dt-accent, #2563eb);
|
|
629
612
|
box-shadow: 0 0 0 1px color-mix(in srgb, var(--dt-accent, #2563eb) 15%, transparent);
|
|
630
613
|
}
|
|
@@ -648,7 +631,7 @@
|
|
|
648
631
|
position: relative;
|
|
649
632
|
min-height: 170px;
|
|
650
633
|
padding: 4px 4px 8px;
|
|
651
|
-
border-right: 1px solid var(--dt-border, rgba(0, 0, 0, 0.
|
|
634
|
+
border-right: 1px solid var(--dt-border, rgba(0, 0, 0, 0.08));
|
|
652
635
|
cursor: pointer;
|
|
653
636
|
transition: background 0.15s;
|
|
654
637
|
}
|
|
@@ -656,8 +639,8 @@
|
|
|
656
639
|
.wg-cell:last-child { border-right: none; }
|
|
657
640
|
.wg-cell:hover { background: var(--dt-hover, rgba(0, 0, 0, 0.015)); }
|
|
658
641
|
|
|
659
|
-
.wg-cell--today { background: var(--dt-today-bg, rgba(
|
|
660
|
-
.wg-cell--today:hover { background:
|
|
642
|
+
.wg-cell--today { background: var(--dt-today-bg, rgba(37, 99, 235, 0.04)); }
|
|
643
|
+
.wg-cell--today:hover { background: color-mix(in srgb, var(--dt-accent, #2563eb) 6%, transparent); }
|
|
661
644
|
|
|
662
645
|
/* Dim all cells by default; current week overrides to full brightness */
|
|
663
646
|
.wg-cell { opacity: 0.55; }
|
|
@@ -676,8 +659,8 @@
|
|
|
676
659
|
45deg,
|
|
677
660
|
transparent,
|
|
678
661
|
transparent 6px,
|
|
679
|
-
var(--dt-border, rgba(0, 0, 0, 0.
|
|
680
|
-
var(--dt-border, rgba(0, 0, 0, 0.
|
|
662
|
+
var(--dt-border, rgba(0, 0, 0, 0.08)) 6px,
|
|
663
|
+
var(--dt-border, rgba(0, 0, 0, 0.08)) 7px
|
|
681
664
|
) !important;
|
|
682
665
|
}
|
|
683
666
|
|
|
@@ -690,8 +673,8 @@
|
|
|
690
673
|
border-radius: 3px;
|
|
691
674
|
background: repeating-linear-gradient(
|
|
692
675
|
-45deg,
|
|
693
|
-
color-mix(in srgb, var(--dt-text, rgba(0,0,0,0.
|
|
694
|
-
color-mix(in srgb, var(--dt-text, rgba(0,0,0,0.
|
|
676
|
+
color-mix(in srgb, var(--dt-text, rgba(0, 0, 0, 0.87)) 4%, transparent),
|
|
677
|
+
color-mix(in srgb, var(--dt-text, rgba(0, 0, 0, 0.87)) 4%, transparent) 3px,
|
|
695
678
|
transparent 3px,
|
|
696
679
|
transparent 6px
|
|
697
680
|
);
|
|
@@ -701,7 +684,7 @@
|
|
|
701
684
|
|
|
702
685
|
.wg-blocked-label {
|
|
703
686
|
font: 500 8px/1 var(--dt-sans, system-ui, sans-serif);
|
|
704
|
-
color: var(--dt-text-3, rgba(0, 0, 0, 0.
|
|
687
|
+
color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
|
|
705
688
|
text-transform: uppercase;
|
|
706
689
|
letter-spacing: 0.04em;
|
|
707
690
|
white-space: nowrap;
|
|
@@ -726,11 +709,11 @@
|
|
|
726
709
|
font: 400 10px / 1 var(--dt-sans, system-ui, sans-serif);
|
|
727
710
|
letter-spacing: 0.04em;
|
|
728
711
|
text-transform: uppercase;
|
|
729
|
-
color: var(--dt-text-3, rgba(0, 0, 0, 0.
|
|
712
|
+
color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
|
|
730
713
|
}
|
|
731
714
|
|
|
732
715
|
.wg-week--current .wg-day-wd {
|
|
733
|
-
color: var(--dt-text-2, rgba(0, 0, 0, 0.
|
|
716
|
+
color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
|
|
734
717
|
}
|
|
735
718
|
|
|
736
719
|
.wg-cell-hd--today .wg-day-wd {
|
|
@@ -740,11 +723,11 @@
|
|
|
740
723
|
|
|
741
724
|
.wg-day-num {
|
|
742
725
|
font: 700 14px / 1 var(--dt-sans, system-ui, sans-serif);
|
|
743
|
-
color: var(--dt-text, rgba(0, 0, 0, 0.
|
|
726
|
+
color: var(--dt-text, rgba(0, 0, 0, 0.87));
|
|
744
727
|
}
|
|
745
728
|
|
|
746
729
|
.wg-week--current .wg-day-num {
|
|
747
|
-
color: var(--dt-text, rgba(0, 0, 0, 0.
|
|
730
|
+
color: var(--dt-text, rgba(0, 0, 0, 0.87));
|
|
748
731
|
}
|
|
749
732
|
|
|
750
733
|
.wg-day-num--today {
|
|
@@ -762,13 +745,13 @@
|
|
|
762
745
|
font: 800 22px / 1 var(--dt-sans, system-ui, sans-serif);
|
|
763
746
|
letter-spacing: 0.02em;
|
|
764
747
|
text-transform: uppercase;
|
|
765
|
-
color: color-mix(in srgb, var(--dt-text, rgba(
|
|
748
|
+
color: color-mix(in srgb, var(--dt-text, rgba(0, 0, 0, 0.87)) 4%, transparent);
|
|
766
749
|
pointer-events: none;
|
|
767
750
|
white-space: nowrap;
|
|
768
751
|
}
|
|
769
752
|
|
|
770
753
|
.wg-week--current .wg-cell-month {
|
|
771
|
-
color: color-mix(in srgb, var(--dt-text, rgba(
|
|
754
|
+
color: color-mix(in srgb, var(--dt-text, rgba(0, 0, 0, 0.87)) 8%, transparent);
|
|
772
755
|
}
|
|
773
756
|
|
|
774
757
|
/* ─── All-day / multi-day events ─────────────────── */
|
|
@@ -826,7 +809,7 @@
|
|
|
826
809
|
|
|
827
810
|
.wg-ad-title {
|
|
828
811
|
font: 500 10px / 1.1 var(--dt-sans, system-ui, sans-serif);
|
|
829
|
-
color: var(--dt-text, rgba(0, 0, 0, 0.
|
|
812
|
+
color: var(--dt-text, rgba(0, 0, 0, 0.87));
|
|
830
813
|
white-space: nowrap;
|
|
831
814
|
overflow: hidden;
|
|
832
815
|
text-overflow: ellipsis;
|
|
@@ -915,14 +898,14 @@
|
|
|
915
898
|
|
|
916
899
|
.wg-ev-time {
|
|
917
900
|
font: 400 10px / 1 var(--dt-sans, system-ui, sans-serif);
|
|
918
|
-
color: var(--dt-text-3, rgba(0, 0, 0, 0.
|
|
901
|
+
color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
|
|
919
902
|
flex-shrink: 0;
|
|
920
903
|
white-space: nowrap;
|
|
921
904
|
}
|
|
922
905
|
|
|
923
906
|
.wg-ev-title {
|
|
924
907
|
font: 500 12px / 1.1 var(--dt-sans, system-ui, sans-serif);
|
|
925
|
-
color: var(--dt-text, rgba(0, 0, 0, 0.
|
|
908
|
+
color: var(--dt-text, rgba(0, 0, 0, 0.87));
|
|
926
909
|
white-space: nowrap;
|
|
927
910
|
overflow: hidden;
|
|
928
911
|
text-overflow: ellipsis;
|
|
@@ -930,7 +913,7 @@
|
|
|
930
913
|
|
|
931
914
|
.wg-ev-loc {
|
|
932
915
|
font: 400 9px / 1 var(--dt-sans, system-ui, sans-serif);
|
|
933
|
-
color: var(--dt-text-3, rgba(0, 0, 0, 0.
|
|
916
|
+
color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
|
|
934
917
|
white-space: nowrap;
|
|
935
918
|
overflow: hidden;
|
|
936
919
|
text-overflow: ellipsis;
|
|
@@ -939,56 +922,13 @@
|
|
|
939
922
|
|
|
940
923
|
.wg-ev-more {
|
|
941
924
|
font: 500 10px / 1 var(--dt-sans, system-ui, sans-serif);
|
|
942
|
-
color: var(--dt-text-3, rgba(0, 0, 0, 0.
|
|
925
|
+
color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
|
|
943
926
|
padding: 2px 8px;
|
|
944
927
|
cursor: pointer;
|
|
945
928
|
}
|
|
946
929
|
|
|
947
930
|
.wg-ev-more:hover {
|
|
948
|
-
color: var(--dt-text-2, rgba(0, 0, 0, 0.
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
/* ─── Navigation pill ────────────────────────────── */
|
|
952
|
-
.wg-nav {
|
|
953
|
-
position: absolute;
|
|
954
|
-
top: 22px;
|
|
955
|
-
right: 14px;
|
|
956
|
-
z-index: 20;
|
|
957
|
-
display: flex;
|
|
958
|
-
gap: 2px;
|
|
959
|
-
background: color-mix(in srgb, var(--dt-surface, var(--dt-bg, #ffffff)) 85%, transparent);
|
|
960
|
-
backdrop-filter: blur(6px);
|
|
961
|
-
-webkit-backdrop-filter: blur(6px);
|
|
962
|
-
border-radius: 8px;
|
|
963
|
-
padding: 2px;
|
|
964
|
-
border: 1px solid var(--dt-border, rgba(148, 163, 184, 0.07));
|
|
965
|
-
animation: wg-nav-in 200ms ease both;
|
|
966
|
-
}
|
|
967
|
-
@keyframes wg-nav-in {
|
|
968
|
-
from { opacity: 0; transform: translateY(-6px); }
|
|
969
|
-
to { opacity: 1; transform: translateY(0); }
|
|
970
|
-
}
|
|
971
|
-
.wg-nav-pill {
|
|
972
|
-
border: none;
|
|
973
|
-
background: transparent;
|
|
974
|
-
color: var(--dt-text-2, rgba(148, 163, 184, 0.55));
|
|
975
|
-
cursor: pointer;
|
|
976
|
-
font: 600 11px / 1 var(--dt-sans, system-ui, sans-serif);
|
|
977
|
-
padding: 6px 12px;
|
|
978
|
-
border-radius: 6px;
|
|
979
|
-
letter-spacing: 0.04em;
|
|
980
|
-
text-transform: uppercase;
|
|
981
|
-
transition: background 100ms, color 100ms;
|
|
982
|
-
display: inline-flex;
|
|
983
|
-
align-items: center;
|
|
984
|
-
justify-content: center;
|
|
985
|
-
}
|
|
986
|
-
.wg-nav-pill:hover {
|
|
987
|
-
color: var(--dt-text, rgba(226, 232, 240, 0.85));
|
|
988
|
-
}
|
|
989
|
-
.wg-nav-pill:focus-visible {
|
|
990
|
-
outline: 2px solid color-mix(in srgb, var(--dt-accent, #2563eb) 55%, transparent);
|
|
991
|
-
outline-offset: 2px;
|
|
931
|
+
color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
|
|
992
932
|
}
|
|
993
933
|
|
|
994
934
|
/* ─── Focus-visible ──────────────────────────────── */
|
|
@@ -7,7 +7,6 @@ export interface CalendarContext {
|
|
|
7
7
|
readonly drag: DragState | undefined;
|
|
8
8
|
readonly commitDrag: (() => void) | undefined;
|
|
9
9
|
readonly snapInterval: number;
|
|
10
|
-
readonly showNav: boolean;
|
|
11
10
|
readonly equalDays: boolean;
|
|
12
11
|
readonly showDates: boolean;
|
|
13
12
|
readonly hideDays: number[] | undefined;
|
|
@@ -18,7 +18,6 @@ export function useCalendarContext() {
|
|
|
18
18
|
get drag() { return raw?.drag; },
|
|
19
19
|
get commitDrag() { return raw?.commitDrag; },
|
|
20
20
|
get snapInterval() { return raw?.snapInterval ?? 15; },
|
|
21
|
-
get showNav() { return raw?.showNavigation ?? true; },
|
|
22
21
|
get equalDays() { return raw?.equalDays ?? false; },
|
|
23
22
|
get showDates() { return raw?.showDates ?? true; },
|
|
24
23
|
get hideDays() { return raw?.hideDays; },
|