diff --git a/src/components/Calendar.vue b/src/components/Calendar.vue
deleted file mode 100644
index 4f72b0b..0000000
--- a/src/components/Calendar.vue
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
diff --git a/src/components/CalendarDay.vue b/src/components/CalendarDay.vue
index 0052d35..27d29fd 100644
--- a/src/components/CalendarDay.vue
+++ b/src/components/CalendarDay.vue
@@ -81,37 +81,34 @@ const props = defineProps({
.cell.selected h1 {
color: var(--strong);
}
-
.lunar-phase {
position: absolute;
- top: 0.1em;
- right: 0.1em;
+ top: 0.5em;
+ right: 0.2em;
font-size: 0.8em;
opacity: 0.7;
}
-
.cell.holiday {
- /* Remove solid background & border color overrides; use gradient overlay instead */
- position: relative;
-}
-.cell.holiday::before {
- content: '';
- position: absolute;
- inset: 0;
- background: linear-gradient(
+ background-image: linear-gradient(
135deg,
- var(--holiday-grad-start, rgba(255, 255, 255, 0.1)) 0%,
+ var(--holiday-grad-start, rgba(255, 255, 255, 0.5)) 0%,
var(--holiday-grad-end, rgba(255, 255, 255, 0)) 70%
);
- pointer-events: none;
- mix-blend-mode: normal; /* can switch to 'overlay' or 'screen' if thematic */
+}
+@media (prefers-color-scheme: dark) {
+ .cell.holiday {
+ background-image: linear-gradient(
+ 135deg,
+ var(--holiday-grad-start, rgba(255, 255, 255, 0.1)) 0%,
+ var(--holiday-grad-end, rgba(255, 255, 255, 0)) 70%
+ );
+ }
}
.cell.holiday h1 {
/* Slight emphasis without forcing a specific hue */
color: var(--holiday);
text-shadow: 0 0 0.3em rgba(255, 255, 255, 0.4);
}
-
.holiday-info {
position: absolute;
bottom: 0.1em;
diff --git a/src/components/CalendarGrid.vue b/src/components/CalendarGrid.vue
deleted file mode 100644
index 08bbab2..0000000
--- a/src/components/CalendarGrid.vue
+++ /dev/null
@@ -1,176 +0,0 @@
-
-
-
-
-
-
diff --git a/src/components/CalendarHeader.vue b/src/components/CalendarHeader.vue
index 1ddb646..c414699 100644
--- a/src/components/CalendarHeader.vue
+++ b/src/components/CalendarHeader.vue
@@ -144,7 +144,6 @@ const weekdayNames = computed(() => {
.dow {
text-transform: uppercase;
text-align: center;
- padding: 0.5rem;
font-weight: 500;
}
.dow.weekend {
diff --git a/src/components/CalendarView.vue b/src/components/CalendarView.vue
index 8035000..7c567ef 100644
--- a/src/components/CalendarView.vue
+++ b/src/components/CalendarView.vue
@@ -3,6 +3,7 @@ import { ref, onMounted, onBeforeUnmount, computed, watch } from 'vue'
import { useCalendarStore } from '@/stores/CalendarStore'
import CalendarHeader from '@/components/CalendarHeader.vue'
import CalendarWeek from '@/components/CalendarWeek.vue'
+import HeaderControls from '@/components/HeaderControls.vue'
import Jogwheel from '@/components/Jogwheel.vue'
import SettingsDialog from '@/components/SettingsDialog.vue'
import {
@@ -13,7 +14,6 @@ import {
daysInclusive,
addDaysStr,
formatDateRange,
- formatTodayString,
getOccurrenceIndex,
getVirtualOccurrenceEndDate,
getISOWeek,
@@ -113,11 +113,6 @@ const selectedDateRange = computed(() => {
)
})
-const todayString = computed(() => {
- const d = new Date(calendarStore.now)
- return formatTodayString(d)
-})
-
// PERFORMANCE: Maintain a manual cache of computed weeks instead of relying on
// deep reactive tracking of every event & day object. We rebuild lazily when
// (a) scrolling changes the needed range or (b) eventsMutation counter bumps.
@@ -578,8 +573,8 @@ onMounted(() => {
viewportHeight.value = viewport.value.clientHeight
viewport.value.scrollTop = initialScrollTop.value
viewport.value.addEventListener('scroll', onScroll)
- // Capture mousedown in viewport to allow dragging via week label column
- viewport.value.addEventListener('mousedown', handleWeekColMouseDown, true)
+ // Capture mousedown in viewport to allow dragging via week label column
+ viewport.value.addEventListener('mousedown', handleWeekColMouseDown, true)
}
document.addEventListener('pointerlockchange', handlePointerLockChange)
@@ -704,44 +699,12 @@ window.addEventListener('resize', () => {
-
-
+
+
diff --git a/src/components/HeaderControls.vue b/src/components/HeaderControls.vue
new file mode 100644
index 0000000..98f5dda
--- /dev/null
+++ b/src/components/HeaderControls.vue
@@ -0,0 +1,225 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Jogwheel.vue b/src/components/Jogwheel.vue
index 3b0ec19..a47016f 100644
--- a/src/components/Jogwheel.vue
+++ b/src/components/Jogwheel.vue
@@ -1,6 +1,10 @@
@@ -11,7 +15,7 @@ const props = defineProps({
totalVirtualWeeks: { type: Number, required: true },
rowHeight: { type: Number, required: true },
viewportHeight: { type: Number, required: true },
- scrollTop: { type: Number, required: true }
+ scrollTop: { type: Number, required: true },
})
const emit = defineEmits(['scroll-to'])
@@ -42,10 +46,16 @@ function onDragMouseDown(e) {
mainStartScroll = props.scrollTop
accumDelta = 0
// Precompute scale between jogwheel scrollable range and main scrollable range
- const mainScrollable = Math.max(0, props.totalVirtualWeeks * props.rowHeight - props.viewportHeight)
+ const mainScrollable = Math.max(
+ 0,
+ props.totalVirtualWeeks * props.rowHeight - props.viewportHeight,
+ )
let jogScrollable = 0
if (jogwheelViewport.value && jogwheelContent.value) {
- jogScrollable = Math.max(0, jogwheelContent.value.scrollHeight - jogwheelViewport.value.clientHeight)
+ jogScrollable = Math.max(
+ 0,
+ jogwheelContent.value.scrollHeight - jogwheelViewport.value.clientHeight,
+ )
}
dragScale = jogScrollable > 0 ? mainScrollable / jogScrollable : 1
if (!isFinite(dragScale) || dragScale <= 0) dragScale = 1
@@ -105,19 +115,25 @@ onBeforeUnmount(() => {
const syncFromJogwheel = () => {
if (!jogwheelViewport.value || !jogwheelContent.value) return
-
+
syncLock.value = 'main'
-
- const jogScrollable = Math.max(0, jogwheelContent.value.scrollHeight - jogwheelViewport.value.clientHeight)
- const mainScrollable = Math.max(0, props.totalVirtualWeeks * props.rowHeight - props.viewportHeight)
-
+
+ const jogScrollable = Math.max(
+ 0,
+ jogwheelContent.value.scrollHeight - jogwheelViewport.value.clientHeight,
+ )
+ const mainScrollable = Math.max(
+ 0,
+ props.totalVirtualWeeks * props.rowHeight - props.viewportHeight,
+ )
+
if (jogScrollable > 0) {
const ratio = jogwheelViewport.value.scrollTop / jogScrollable
-
+
// Emit scroll event to parent to update main viewport
emit('scroll-to', ratio * mainScrollable)
}
-
+
setTimeout(() => {
if (syncLock.value === 'main') syncLock.value = null
}, 50)
@@ -126,29 +142,38 @@ const syncFromJogwheel = () => {
const syncFromMain = (mainScrollTop) => {
if (!jogwheelViewport.value || !jogwheelContent.value) return
if (syncLock.value === 'main') return
-
+
syncLock.value = 'jogwheel'
-
- const mainScrollable = Math.max(0, props.totalVirtualWeeks * props.rowHeight - props.viewportHeight)
- const jogScrollable = Math.max(0, jogwheelContent.value.scrollHeight - jogwheelViewport.value.clientHeight)
-
+
+ const mainScrollable = Math.max(
+ 0,
+ props.totalVirtualWeeks * props.rowHeight - props.viewportHeight,
+ )
+ const jogScrollable = Math.max(
+ 0,
+ jogwheelContent.value.scrollHeight - jogwheelViewport.value.clientHeight,
+ )
+
if (mainScrollable > 0) {
const ratio = mainScrollTop / mainScrollable
jogwheelViewport.value.scrollTop = ratio * jogScrollable
}
-
+
setTimeout(() => {
if (syncLock.value === 'jogwheel') syncLock.value = null
}, 50)
}
// Watch for main calendar scroll changes
-watch(() => props.scrollTop, (newScrollTop) => {
- syncFromMain(newScrollTop)
-})
+watch(
+ () => props.scrollTop,
+ (newScrollTop) => {
+ syncFromMain(newScrollTop)
+ },
+)
defineExpose({
- syncFromMain
+ syncFromMain,
})