@nomideusz/svelte-calendar 0.6.3 → 0.6.5
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 +192 -10
- package/dist/adapters/composite.d.ts +15 -0
- package/dist/adapters/composite.js +65 -0
- package/dist/adapters/index.d.ts +5 -1
- package/dist/adapters/index.js +2 -0
- package/dist/adapters/mapped.d.ts +170 -0
- package/dist/adapters/mapped.js +343 -0
- package/dist/adapters/recurring.d.ts +4 -0
- package/dist/adapters/recurring.js +5 -10
- package/dist/adapters/types.d.ts +11 -2
- package/dist/assets/favicon.svg +9 -1
- package/dist/calendar/Calendar.svelte +161 -90
- package/dist/calendar/Calendar.svelte.d.ts +12 -0
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.js +2 -0
- package/dist/core/measure.d.ts +104 -0
- package/dist/core/measure.js +195 -0
- package/dist/core/time.js +2 -2
- package/dist/core/types.d.ts +32 -0
- package/dist/engine/event-store.svelte.js +22 -7
- package/dist/headless/create-agenda.svelte.d.ts +67 -0
- package/dist/headless/create-agenda.svelte.js +139 -0
- package/dist/headless/create-calendar.svelte.d.ts +2 -0
- package/dist/headless/create-calendar.svelte.js +380 -0
- package/dist/headless/index.d.ts +4 -0
- package/dist/headless/index.js +2 -0
- package/dist/headless/types.d.ts +219 -0
- package/dist/headless/types.js +1 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.js +4 -2
- package/dist/primitives/DayHeader.svelte +6 -6
- package/dist/primitives/EmptySlot.svelte +3 -3
- package/dist/primitives/EventBlock.svelte +99 -14
- package/dist/primitives/NowIndicator.svelte +5 -5
- package/dist/views/agenda/AgendaDay.svelte +215 -116
- package/dist/views/agenda/AgendaWeek.svelte +166 -113
- package/dist/views/mobile/MobileDay.svelte +45 -21
- package/dist/views/mobile/MobileWeek.svelte +85 -35
- package/dist/views/planner/PlannerDay.svelte +116 -60
- package/dist/views/planner/PlannerWeek.svelte +228 -166
- package/dist/views/shared/context.svelte.d.ts +47 -0
- package/dist/views/shared/context.svelte.js +47 -0
- package/dist/views/shared/format.d.ts +19 -0
- package/dist/views/shared/format.js +46 -0
- package/dist/views/shared/index.d.ts +4 -0
- package/dist/views/shared/index.js +2 -0
- package/package.json +9 -2
|
@@ -12,14 +12,16 @@
|
|
|
12
12
|
* Future day ("The Plan"):
|
|
13
13
|
* Clean numbered schedule list.
|
|
14
14
|
*/
|
|
15
|
-
import { getContext } from 'svelte';
|
|
16
15
|
import { createClock } from '../../core/clock.svelte.js';
|
|
17
16
|
import type { TimelineEvent } from '../../core/types.js';
|
|
18
17
|
import { sod, DAY_MS, isAllDay, isMultiDay } from '../../core/time.js';
|
|
19
|
-
import {
|
|
20
|
-
import
|
|
18
|
+
import { getLabels } from '../../core/locale.js';
|
|
19
|
+
import { useCalendarContext } from '../shared/context.svelte.js';
|
|
20
|
+
import { fmtTime, duration, timeUntilMs, progress, groupIntoSlots } from '../shared/format.js';
|
|
21
|
+
import type { TimeSlot } from '../shared/format.js';
|
|
21
22
|
|
|
22
23
|
const L = $derived(getLabels());
|
|
24
|
+
const ctx = useCalendarContext();
|
|
23
25
|
|
|
24
26
|
interface Props {
|
|
25
27
|
locale?: string;
|
|
@@ -43,17 +45,15 @@
|
|
|
43
45
|
}: Props = $props();
|
|
44
46
|
|
|
45
47
|
const clock = createClock();
|
|
46
|
-
const viewState =
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
const isMobile = $derived(mobileCtx?.current ?? false);
|
|
56
|
-
const autoHeight = $derived(autoHeightCtx?.current ?? false);
|
|
48
|
+
const viewState = $derived(ctx.viewState);
|
|
49
|
+
const showNav = $derived(ctx.showNav);
|
|
50
|
+
const equalDays = $derived(ctx.equalDays);
|
|
51
|
+
const showDates = $derived(ctx.showDates);
|
|
52
|
+
const isMobile = $derived(ctx.isMobile);
|
|
53
|
+
const autoHeight = $derived(ctx.autoHeight);
|
|
54
|
+
const compact = $derived(ctx.compact);
|
|
55
|
+
const oneventhover = $derived(ctx.oneventhover);
|
|
56
|
+
const disabledSet = $derived(ctx.disabledSet);
|
|
57
57
|
|
|
58
58
|
// ── Swipe navigation (mobile) ──────────────────────
|
|
59
59
|
let swipeStartX = 0;
|
|
@@ -76,65 +76,10 @@
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
// ──
|
|
80
|
-
const
|
|
81
|
-
const
|
|
82
|
-
const
|
|
83
|
-
const disabledDates = $derived(disabledDatesCtx?.current);
|
|
84
|
-
const disabledSet = $derived(new Set(disabledDates?.map(d => sod(d.getTime())) ?? []));
|
|
85
|
-
|
|
86
|
-
// ── Format helpers ──────────────────────────────────
|
|
87
|
-
function fmtTime(d: Date): string {
|
|
88
|
-
return _fmtTime(d, locale);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function duration(ev: TimelineEvent): string {
|
|
92
|
-
return fmtDuration(ev.start, ev.end);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function timeUntilMs(ms: number): string {
|
|
96
|
-
const diff = ms - clock.tick;
|
|
97
|
-
if (diff <= 0) return L.now;
|
|
98
|
-
const tMins = Math.floor(diff / 60000);
|
|
99
|
-
if (tMins < 60) return `in ${tMins}m`;
|
|
100
|
-
const hrs = Math.floor(tMins / 60);
|
|
101
|
-
const rm = tMins % 60;
|
|
102
|
-
if (hrs < 24) return rm > 0 ? `in ${hrs}h ${rm}m` : `in ${hrs}h`;
|
|
103
|
-
const days = Math.floor(hrs / 24);
|
|
104
|
-
return `in ${days}d`;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function progress(ev: TimelineEvent): number {
|
|
108
|
-
const s = ev.start.getTime();
|
|
109
|
-
const e = ev.end.getTime();
|
|
110
|
-
return Math.min(1, Math.max(0, (clock.tick - s) / (e - s)));
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// ── Overlap grouping ────────────────────────────────
|
|
114
|
-
interface TimeSlot {
|
|
115
|
-
startMs: number;
|
|
116
|
-
endMs: number;
|
|
117
|
-
events: TimelineEvent[];
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function groupIntoSlots(evts: TimelineEvent[]): TimeSlot[] {
|
|
121
|
-
const sorted = [...evts].sort((a, b) => a.start.getTime() - b.start.getTime());
|
|
122
|
-
const slots: TimeSlot[] = [];
|
|
123
|
-
for (const ev of sorted) {
|
|
124
|
-
const last = slots[slots.length - 1];
|
|
125
|
-
if (last && ev.start.getTime() < last.endMs) {
|
|
126
|
-
last.events.push(ev);
|
|
127
|
-
last.endMs = Math.max(last.endMs, ev.end.getTime());
|
|
128
|
-
} else {
|
|
129
|
-
slots.push({
|
|
130
|
-
startMs: ev.start.getTime(),
|
|
131
|
-
endMs: ev.end.getTime(),
|
|
132
|
-
events: [ev],
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
return slots;
|
|
137
|
-
}
|
|
79
|
+
// ── Format helpers (delegated to shared/format.ts) ──
|
|
80
|
+
const fmt = (d: Date) => fmtTime(d, locale);
|
|
81
|
+
const eta = (ms: number) => timeUntilMs(ms, clock.tick);
|
|
82
|
+
const prog = (ev: TimelineEvent) => progress(ev, clock.tick);
|
|
138
83
|
|
|
139
84
|
// ── Event handlers ──────────────────────────────────
|
|
140
85
|
function handleClick(ev: TimelineEvent): void {
|
|
@@ -244,7 +189,44 @@
|
|
|
244
189
|
</div>
|
|
245
190
|
{/if}
|
|
246
191
|
|
|
247
|
-
{#if
|
|
192
|
+
{#if compact}
|
|
193
|
+
<!-- ─── Compact: minimal text rows ─── -->
|
|
194
|
+
<div class="ag-compact-list">
|
|
195
|
+
{#if timedDayEvents.length === 0 && allDayBanner.length === 0}
|
|
196
|
+
<div class="ag-q-empty">{L.nothingScheduledYet}</div>
|
|
197
|
+
{:else}
|
|
198
|
+
{#each timedDayEvents as ev (ev.id)}
|
|
199
|
+
<div
|
|
200
|
+
class="ag-compact-row"
|
|
201
|
+
class:ag-compact-row--selected={selectedEventId === ev.id}
|
|
202
|
+
class:ag-compact-row--cancelled={ev.status === 'cancelled'}
|
|
203
|
+
class:ag-compact-row--tentative={ev.status === 'tentative'}
|
|
204
|
+
style:--ev-color={ev.color || 'var(--dt-accent)'}
|
|
205
|
+
role="button"
|
|
206
|
+
tabindex="0"
|
|
207
|
+
aria-label="{ev.title}, {fmt(ev.start)}, {duration(ev)}"
|
|
208
|
+
onclick={() => handleClick(ev)}
|
|
209
|
+
onpointerenter={() => oneventhover?.(ev)}
|
|
210
|
+
onkeydown={(e) => handleKeydown(e, ev)}
|
|
211
|
+
>
|
|
212
|
+
<span class="ag-compact-row-dot"></span>
|
|
213
|
+
<span class="ag-compact-row-time">{fmt(ev.start)}</span>
|
|
214
|
+
<span class="ag-compact-row-title">{ev.title}</span>
|
|
215
|
+
{#if ev.subtitle}
|
|
216
|
+
<span class="ag-compact-row-sub">{ev.subtitle}</span>
|
|
217
|
+
{/if}
|
|
218
|
+
{#if ev.tags?.length}
|
|
219
|
+
{#each ev.tags as tag}
|
|
220
|
+
<span class="ag-compact-row-tag">{tag}</span>
|
|
221
|
+
{/each}
|
|
222
|
+
{/if}
|
|
223
|
+
<span class="ag-compact-row-dur">{duration(ev)}</span>
|
|
224
|
+
</div>
|
|
225
|
+
{/each}
|
|
226
|
+
{/if}
|
|
227
|
+
</div>
|
|
228
|
+
|
|
229
|
+
{:else if isToday}
|
|
248
230
|
<!-- ─── Today: "The Queue" — upcoming is the hero ─── -->
|
|
249
231
|
<div class="ag-q">
|
|
250
232
|
<!-- NOW column: past events stacked above NOW strip -->
|
|
@@ -258,7 +240,7 @@
|
|
|
258
240
|
class:ag-q-done-item--selected={selectedEventId === ev.id}
|
|
259
241
|
role="button"
|
|
260
242
|
tabindex="0"
|
|
261
|
-
aria-label="{ev.title}, {L.completed}, {
|
|
243
|
+
aria-label="{ev.title}, {L.completed}, {fmt(ev.start)}"
|
|
262
244
|
onclick={() => handleClick(ev)}
|
|
263
245
|
onkeydown={(e) => handleKeydown(e, ev)}
|
|
264
246
|
>
|
|
@@ -278,14 +260,14 @@
|
|
|
278
260
|
style:--ev-color={ev.color || 'var(--dt-accent)'}
|
|
279
261
|
role="button"
|
|
280
262
|
tabindex="0"
|
|
281
|
-
aria-label="{ev.title}, {L.happeningNow}, {L.percentComplete(Math.round(
|
|
263
|
+
aria-label="{ev.title}, {L.happeningNow}, {L.percentComplete(Math.round(prog(ev) * 100))}"
|
|
282
264
|
onclick={() => handleClick(ev)} onpointerenter={() => oneventhover?.(ev)} onkeydown={(e) => handleKeydown(e, ev)}
|
|
283
265
|
>
|
|
284
266
|
<div class="ag-q-now-dot"></div>
|
|
285
267
|
<div class="ag-q-now-title">{ev.title}</div>
|
|
286
|
-
<div class="ag-q-now-time">{L.until} {
|
|
268
|
+
<div class="ag-q-now-time">{L.until} {fmt(ev.end)}</div>
|
|
287
269
|
<div class="ag-q-now-track">
|
|
288
|
-
<div class="ag-q-now-fill" style:width="{
|
|
270
|
+
<div class="ag-q-now-fill" style:width="{prog(ev) * 100}%"></div>
|
|
289
271
|
</div>
|
|
290
272
|
</div>
|
|
291
273
|
{/each}
|
|
@@ -312,7 +294,7 @@
|
|
|
312
294
|
style:--ev-color={ev.color || 'var(--dt-accent)'}
|
|
313
295
|
role="button"
|
|
314
296
|
tabindex="0"
|
|
315
|
-
aria-label="{ev.title}, {
|
|
297
|
+
aria-label="{ev.title}, {fmt(ev.start)}, {duration(ev)}"
|
|
316
298
|
onclick={() => handleClick(ev)}
|
|
317
299
|
onpointerenter={() => oneventhover?.(ev)}
|
|
318
300
|
onkeydown={(e) => handleKeydown(e, ev)}
|
|
@@ -320,13 +302,13 @@
|
|
|
320
302
|
<div class="ag-card-body">
|
|
321
303
|
<div class="ag-card-top">
|
|
322
304
|
<span class="ag-card-title">{ev.title}</span>
|
|
323
|
-
<span class="ag-card-eta">{
|
|
305
|
+
<span class="ag-card-eta">{eta(ev.start.getTime())}</span>
|
|
324
306
|
</div>
|
|
325
307
|
{#if ev.subtitle}
|
|
326
308
|
<span class="ag-card-sub">{ev.subtitle}</span>
|
|
327
309
|
{/if}
|
|
328
310
|
<div class="ag-card-meta">
|
|
329
|
-
{
|
|
311
|
+
{fmt(ev.start)} – {fmt(ev.end)}
|
|
330
312
|
<span class="ag-card-dur">{duration(ev)}</span>
|
|
331
313
|
</div>
|
|
332
314
|
{#if ev.tags?.length}
|
|
@@ -356,11 +338,11 @@
|
|
|
356
338
|
style:--ev-color={ev.color || 'var(--dt-accent)'}
|
|
357
339
|
role="button"
|
|
358
340
|
tabindex="0"
|
|
359
|
-
aria-label="{ev.title}, {
|
|
341
|
+
aria-label="{ev.title}, {fmt(ev.start)} to {fmt(ev.end)}"
|
|
360
342
|
onclick={() => handleClick(ev)} onpointerenter={() => oneventhover?.(ev)} onkeydown={(e) => handleKeydown(e, ev)}
|
|
361
343
|
>
|
|
362
344
|
<span class="ag-log-check">✓</span>
|
|
363
|
-
<span class="ag-log-time">{
|
|
345
|
+
<span class="ag-log-time">{fmt(ev.start)}</span>
|
|
364
346
|
<span class="ag-log-dot" style:background={ev.color || 'var(--dt-accent)'}></span>
|
|
365
347
|
<span class="ag-log-title">{ev.title}</span>
|
|
366
348
|
<span class="ag-log-dur">{duration(ev)}</span>
|
|
@@ -380,10 +362,14 @@
|
|
|
380
362
|
class="ag-card ag-card--plan"
|
|
381
363
|
class:ag-card--first={i === 0}
|
|
382
364
|
class:ag-card--selected={selectedEventId === ev.id}
|
|
365
|
+
class:ag-card--cancelled={ev.status === 'cancelled'}
|
|
366
|
+
class:ag-card--tentative={ev.status === 'tentative'}
|
|
367
|
+
class:ag-card--full={ev.status === 'full'}
|
|
368
|
+
class:ag-card--limited={ev.status === 'limited'}
|
|
383
369
|
style:--ev-color={ev.color || 'var(--dt-accent)'}
|
|
384
370
|
role="button"
|
|
385
371
|
tabindex="0"
|
|
386
|
-
aria-label="{ev.title}, {
|
|
372
|
+
aria-label="{ev.title}{ev.status === 'cancelled' ? ' (cancelled)' : ''}{ev.status === 'tentative' ? ' (tentative)' : ''}{ev.status === 'full' ? ' (full)' : ''}{ev.status === 'limited' ? ' (limited)' : ''}, {fmt(ev.start)} to {fmt(ev.end)}, {duration(ev)}"
|
|
387
373
|
onclick={() => handleClick(ev)} onpointerenter={() => oneventhover?.(ev)} onkeydown={(e) => handleKeydown(e, ev)}
|
|
388
374
|
>
|
|
389
375
|
<div class="ag-card-body">
|
|
@@ -394,8 +380,11 @@
|
|
|
394
380
|
{#if ev.subtitle}
|
|
395
381
|
<span class="ag-card-sub">{ev.subtitle}</span>
|
|
396
382
|
{/if}
|
|
383
|
+
{#if ev.location}
|
|
384
|
+
<span class="ag-card-loc">{ev.location}</span>
|
|
385
|
+
{/if}
|
|
397
386
|
<div class="ag-card-meta">
|
|
398
|
-
{
|
|
387
|
+
{fmt(ev.start)} – {fmt(ev.end)}
|
|
399
388
|
<span class="ag-card-dur">{duration(ev)}</span>
|
|
400
389
|
</div>
|
|
401
390
|
{#if ev.tags?.length}
|
|
@@ -455,11 +444,11 @@
|
|
|
455
444
|
left: 50%;
|
|
456
445
|
transform: translateX(-50%);
|
|
457
446
|
z-index: 20;
|
|
458
|
-
font: 600 11px/1 var(--dt-sans,
|
|
447
|
+
font: 600 11px/1 var(--dt-sans, system-ui, sans-serif);
|
|
459
448
|
letter-spacing: 0.04em;
|
|
460
449
|
text-transform: uppercase;
|
|
461
450
|
color: var(--dt-text, rgba(226, 232, 240, 0.85));
|
|
462
|
-
background: color-mix(in srgb, var(--dt-surface, #
|
|
451
|
+
background: color-mix(in srgb, var(--dt-surface, var(--dt-bg, #ffffff)) 85%, transparent);
|
|
463
452
|
backdrop-filter: blur(6px);
|
|
464
453
|
-webkit-backdrop-filter: blur(6px);
|
|
465
454
|
padding: 8px 16px;
|
|
@@ -477,7 +466,7 @@
|
|
|
477
466
|
z-index: 20;
|
|
478
467
|
display: flex;
|
|
479
468
|
gap: 2px;
|
|
480
|
-
background: color-mix(in srgb, var(--dt-surface, #
|
|
469
|
+
background: color-mix(in srgb, var(--dt-surface, var(--dt-bg, #ffffff)) 85%, transparent);
|
|
481
470
|
backdrop-filter: blur(6px);
|
|
482
471
|
-webkit-backdrop-filter: blur(6px);
|
|
483
472
|
border-radius: 8px;
|
|
@@ -489,7 +478,7 @@
|
|
|
489
478
|
background: transparent;
|
|
490
479
|
color: var(--dt-text-2, rgba(148, 163, 184, 0.55));
|
|
491
480
|
cursor: pointer;
|
|
492
|
-
font: 600 11px / 1 var(--dt-sans,
|
|
481
|
+
font: 600 11px / 1 var(--dt-sans, system-ui, sans-serif);
|
|
493
482
|
padding: 6px 12px;
|
|
494
483
|
border-radius: 6px;
|
|
495
484
|
letter-spacing: 0.04em;
|
|
@@ -516,7 +505,7 @@
|
|
|
516
505
|
pointer-events: none;
|
|
517
506
|
}
|
|
518
507
|
.ag-nav-pill:focus-visible {
|
|
519
|
-
outline: 2px solid color-mix(in srgb, var(--dt-accent, #
|
|
508
|
+
outline: 2px solid color-mix(in srgb, var(--dt-accent, #2563eb) 55%, transparent);
|
|
520
509
|
outline-offset: 2px;
|
|
521
510
|
}
|
|
522
511
|
|
|
@@ -528,6 +517,9 @@
|
|
|
528
517
|
display: flex;
|
|
529
518
|
flex-direction: column;
|
|
530
519
|
height: 100%;
|
|
520
|
+
width: 100%;
|
|
521
|
+
min-width: 0;
|
|
522
|
+
box-sizing: border-box;
|
|
531
523
|
color: var(--dt-text, rgba(255, 255, 255, 0.92));
|
|
532
524
|
font-family: var(--dt-sans, system-ui, sans-serif);
|
|
533
525
|
}
|
|
@@ -535,17 +527,24 @@
|
|
|
535
527
|
.ag--auto { height: auto; overflow: visible; }
|
|
536
528
|
|
|
537
529
|
.ag--disabled {
|
|
538
|
-
|
|
539
|
-
|
|
530
|
+
background-image: repeating-linear-gradient(
|
|
531
|
+
135deg,
|
|
532
|
+
transparent,
|
|
533
|
+
transparent 6px,
|
|
534
|
+
color-mix(in srgb, var(--dt-text, rgba(255, 255, 255, 0.92)) 4%, transparent) 6px,
|
|
535
|
+
color-mix(in srgb, var(--dt-text, rgba(255, 255, 255, 0.92)) 4%, transparent) 12px
|
|
536
|
+
);
|
|
540
537
|
}
|
|
541
538
|
|
|
542
539
|
/* ═══ Body ═══ */
|
|
543
540
|
.ag-body {
|
|
544
541
|
flex: 1;
|
|
545
542
|
min-height: 0;
|
|
543
|
+
min-width: 0;
|
|
546
544
|
display: flex;
|
|
547
545
|
flex-direction: column;
|
|
548
546
|
overflow-y: auto;
|
|
547
|
+
overflow-x: hidden;
|
|
549
548
|
padding-top: 44px;
|
|
550
549
|
scrollbar-width: thin;
|
|
551
550
|
scrollbar-color: var(--dt-border) transparent;
|
|
@@ -587,22 +586,22 @@
|
|
|
587
586
|
gap: 5px;
|
|
588
587
|
padding: 3px 10px;
|
|
589
588
|
border-radius: 6px;
|
|
590
|
-
background: color-mix(in srgb, var(--ev-color) 12%, var(--dt-surface, #
|
|
589
|
+
background: color-mix(in srgb, var(--ev-color) 12%, var(--dt-surface, var(--dt-bg, #ffffff)));
|
|
591
590
|
border: 1px solid color-mix(in srgb, var(--ev-color) 20%, transparent);
|
|
592
591
|
cursor: pointer;
|
|
593
592
|
transition: background 0.15s, border-color 0.15s;
|
|
594
593
|
}
|
|
595
594
|
.ag-allday-chip:hover {
|
|
596
|
-
background: color-mix(in srgb, var(--ev-color) 22%, var(--dt-surface, #
|
|
595
|
+
background: color-mix(in srgb, var(--ev-color) 22%, var(--dt-surface, var(--dt-bg, #ffffff)));
|
|
597
596
|
border-color: color-mix(in srgb, var(--ev-color) 35%, transparent);
|
|
598
597
|
}
|
|
599
598
|
.ag-allday-chip:focus-visible {
|
|
600
|
-
outline: 2px solid var(--dt-accent, #
|
|
599
|
+
outline: 2px solid var(--dt-accent, #2563eb);
|
|
601
600
|
outline-offset: 2px;
|
|
602
601
|
}
|
|
603
602
|
.ag-allday-chip--selected {
|
|
604
603
|
border-color: var(--ev-color);
|
|
605
|
-
background: color-mix(in srgb, var(--ev-color) 18%, var(--dt-surface, #
|
|
604
|
+
background: color-mix(in srgb, var(--ev-color) 18%, var(--dt-surface, var(--dt-bg, #ffffff)));
|
|
606
605
|
}
|
|
607
606
|
.ag-allday-dot {
|
|
608
607
|
width: 6px;
|
|
@@ -622,23 +621,40 @@
|
|
|
622
621
|
display: flex;
|
|
623
622
|
align-items: stretch;
|
|
624
623
|
border-radius: 10px;
|
|
625
|
-
background: color-mix(in srgb, var(--ev-color) 15%, var(--dt-surface, #
|
|
624
|
+
background: color-mix(in srgb, var(--ev-color) 15%, var(--dt-surface, var(--dt-bg, #ffffff)));
|
|
626
625
|
border: 1px solid color-mix(in srgb, var(--ev-color) 10%, var(--dt-border, rgba(255, 255, 255, 0.06)));
|
|
627
626
|
overflow: hidden;
|
|
628
627
|
cursor: pointer;
|
|
629
628
|
transition: background 150ms, border-color 150ms;
|
|
630
629
|
}
|
|
631
630
|
.ag-card:hover {
|
|
632
|
-
background: color-mix(in srgb, var(--ev-color) 25%, var(--dt-surface, #
|
|
631
|
+
background: color-mix(in srgb, var(--ev-color) 25%, var(--dt-surface, var(--dt-bg, #ffffff)));
|
|
633
632
|
border-color: color-mix(in srgb, var(--ev-color) 40%, transparent);
|
|
634
633
|
}
|
|
635
634
|
.ag-card:focus-visible {
|
|
636
|
-
outline: 2px solid var(--dt-accent, #
|
|
635
|
+
outline: 2px solid var(--dt-accent, #2563eb);
|
|
637
636
|
outline-offset: 2px;
|
|
638
637
|
}
|
|
639
638
|
.ag-card--selected {
|
|
640
639
|
border-color: var(--ev-color);
|
|
641
|
-
background: color-mix(in srgb, var(--ev-color) 22%, var(--dt-surface, #
|
|
640
|
+
background: color-mix(in srgb, var(--ev-color) 22%, var(--dt-surface, var(--dt-bg, #ffffff)));
|
|
641
|
+
}
|
|
642
|
+
.ag-card--cancelled {
|
|
643
|
+
opacity: 0.5;
|
|
644
|
+
}
|
|
645
|
+
.ag-card--cancelled .ag-card-title {
|
|
646
|
+
text-decoration: line-through;
|
|
647
|
+
}
|
|
648
|
+
.ag-card--tentative {
|
|
649
|
+
opacity: 0.65;
|
|
650
|
+
border-style: dashed;
|
|
651
|
+
}
|
|
652
|
+
.ag-card--full {
|
|
653
|
+
opacity: 0.55;
|
|
654
|
+
}
|
|
655
|
+
.ag-card--limited {
|
|
656
|
+
opacity: 0.65;
|
|
657
|
+
border-style: dashed;
|
|
642
658
|
}
|
|
643
659
|
.ag-card-body {
|
|
644
660
|
padding: 10px 12px;
|
|
@@ -653,15 +669,15 @@
|
|
|
653
669
|
justify-content: space-between;
|
|
654
670
|
align-items: flex-start;
|
|
655
671
|
gap: 8px;
|
|
672
|
+
min-width: 0;
|
|
656
673
|
}
|
|
657
674
|
.ag-card-title {
|
|
658
675
|
font-size: 13px;
|
|
659
676
|
font-weight: 600;
|
|
660
|
-
line-height: 1.
|
|
661
|
-
|
|
662
|
-
overflow: hidden;
|
|
663
|
-
text-overflow: ellipsis;
|
|
677
|
+
line-height: 1.3;
|
|
678
|
+
word-break: break-word;
|
|
664
679
|
flex: 1;
|
|
680
|
+
min-width: 0;
|
|
665
681
|
}
|
|
666
682
|
.ag-card-meta {
|
|
667
683
|
font-size: 11px;
|
|
@@ -678,6 +694,11 @@
|
|
|
678
694
|
color: var(--dt-text-2, rgba(255, 255, 255, 0.45));
|
|
679
695
|
line-height: 1;
|
|
680
696
|
}
|
|
697
|
+
.ag-card-loc {
|
|
698
|
+
font-size: 10px;
|
|
699
|
+
color: var(--dt-text-3, rgba(255, 255, 255, 0.35));
|
|
700
|
+
line-height: 1;
|
|
701
|
+
}
|
|
681
702
|
.ag-card-tags {
|
|
682
703
|
display: flex;
|
|
683
704
|
gap: 4px;
|
|
@@ -708,12 +729,12 @@
|
|
|
708
729
|
font-size: 9px;
|
|
709
730
|
font-weight: 600;
|
|
710
731
|
letter-spacing: 0.04em;
|
|
711
|
-
color: var(--dt-accent, #
|
|
732
|
+
color: var(--dt-accent, #2563eb);
|
|
712
733
|
flex-shrink: 0;
|
|
713
734
|
white-space: nowrap;
|
|
714
735
|
}
|
|
715
736
|
.ag-card--hero {
|
|
716
|
-
background: color-mix(in srgb, var(--ev-color) 22%, var(--dt-surface, #
|
|
737
|
+
background: color-mix(in srgb, var(--ev-color) 22%, var(--dt-surface, var(--dt-bg, #ffffff)));
|
|
717
738
|
border-color: color-mix(in srgb, var(--ev-color) 30%, transparent);
|
|
718
739
|
}
|
|
719
740
|
.ag-card--hero .ag-card-title {
|
|
@@ -722,7 +743,7 @@
|
|
|
722
743
|
}
|
|
723
744
|
.ag-card--hero .ag-card-eta {
|
|
724
745
|
font-size: 11px;
|
|
725
|
-
background: color-mix(in srgb, var(--dt-accent, #
|
|
746
|
+
background: color-mix(in srgb, var(--dt-accent, #2563eb) 18%, transparent);
|
|
726
747
|
padding: 2px 7px;
|
|
727
748
|
border-radius: 4px;
|
|
728
749
|
}
|
|
@@ -750,7 +771,7 @@
|
|
|
750
771
|
font-size: 14px;
|
|
751
772
|
}
|
|
752
773
|
.ag-card--first {
|
|
753
|
-
background: color-mix(in srgb, var(--ev-color) 20%, var(--dt-surface, #
|
|
774
|
+
background: color-mix(in srgb, var(--ev-color) 20%, var(--dt-surface, var(--dt-bg, #ffffff)));
|
|
754
775
|
border-color: color-mix(in srgb, var(--ev-color) 25%, transparent);
|
|
755
776
|
}
|
|
756
777
|
.ag-card--first .ag-card-title {
|
|
@@ -860,24 +881,24 @@
|
|
|
860
881
|
font-size: 10px;
|
|
861
882
|
font-weight: 600;
|
|
862
883
|
font-family: var(--dt-mono, monospace);
|
|
863
|
-
color: var(--dt-accent, #
|
|
884
|
+
color: var(--dt-accent, #2563eb);
|
|
864
885
|
margin-left: 4px;
|
|
865
886
|
}
|
|
866
887
|
.ag-q-now {
|
|
867
888
|
padding: 8px 10px;
|
|
868
889
|
border-radius: 8px;
|
|
869
|
-
background: color-mix(in srgb, var(--ev-color, var(--dt-accent)) 15%, var(--dt-surface, #
|
|
890
|
+
background: color-mix(in srgb, var(--ev-color, var(--dt-accent)) 15%, var(--dt-surface, var(--dt-bg, #ffffff)));
|
|
870
891
|
border: 1px solid color-mix(in srgb, var(--ev-color, var(--dt-accent)) 15%, transparent);
|
|
871
892
|
cursor: pointer;
|
|
872
893
|
transition: background 150ms, border-color 150ms;
|
|
873
894
|
margin-right: 10px;
|
|
874
895
|
}
|
|
875
896
|
.ag-q-now:hover {
|
|
876
|
-
background: color-mix(in srgb, var(--ev-color, var(--dt-accent)) 25%, var(--dt-surface, #
|
|
897
|
+
background: color-mix(in srgb, var(--ev-color, var(--dt-accent)) 25%, var(--dt-surface, var(--dt-bg, #ffffff)));
|
|
877
898
|
border-color: color-mix(in srgb, var(--ev-color, var(--dt-accent)) 35%, transparent);
|
|
878
899
|
}
|
|
879
900
|
.ag-q-now:focus-visible {
|
|
880
|
-
outline: 2px solid var(--dt-accent, #
|
|
901
|
+
outline: 2px solid var(--dt-accent, #2563eb);
|
|
881
902
|
outline-offset: 2px;
|
|
882
903
|
}
|
|
883
904
|
.ag-q-now--selected {
|
|
@@ -887,7 +908,7 @@
|
|
|
887
908
|
width: 6px;
|
|
888
909
|
height: 6px;
|
|
889
910
|
border-radius: 50%;
|
|
890
|
-
background: var(--ev-color, var(--dt-accent, #
|
|
911
|
+
background: var(--ev-color, var(--dt-accent, #2563eb));
|
|
891
912
|
margin-bottom: 6px;
|
|
892
913
|
animation: ag-pulse 2.5s ease-in-out infinite;
|
|
893
914
|
}
|
|
@@ -919,7 +940,7 @@
|
|
|
919
940
|
}
|
|
920
941
|
.ag-q-now-fill {
|
|
921
942
|
height: 100%;
|
|
922
|
-
background: var(--ev-color, var(--dt-accent, #
|
|
943
|
+
background: var(--ev-color, var(--dt-accent, #2563eb));
|
|
923
944
|
border-radius: 1px;
|
|
924
945
|
transition: width 1s linear;
|
|
925
946
|
}
|
|
@@ -959,7 +980,7 @@
|
|
|
959
980
|
opacity: 0.6;
|
|
960
981
|
}
|
|
961
982
|
.ag-q-done-item:focus-visible {
|
|
962
|
-
outline: 2px solid var(--dt-accent, #
|
|
983
|
+
outline: 2px solid var(--dt-accent, #2563eb);
|
|
963
984
|
outline-offset: 2px;
|
|
964
985
|
opacity: 0.6;
|
|
965
986
|
}
|
|
@@ -1009,7 +1030,7 @@
|
|
|
1009
1030
|
opacity: 1;
|
|
1010
1031
|
}
|
|
1011
1032
|
.ag-log-row:focus-visible {
|
|
1012
|
-
outline: 2px solid var(--dt-accent, #
|
|
1033
|
+
outline: 2px solid var(--dt-accent, #2563eb);
|
|
1013
1034
|
outline-offset: 2px;
|
|
1014
1035
|
}
|
|
1015
1036
|
.ag-log-row--selected {
|
|
@@ -1057,6 +1078,84 @@
|
|
|
1057
1078
|
flex-shrink: 0;
|
|
1058
1079
|
}
|
|
1059
1080
|
|
|
1081
|
+
/* ═══ Compact Day ═══ */
|
|
1082
|
+
.ag-compact-list {
|
|
1083
|
+
flex: 1;
|
|
1084
|
+
padding: 8px 20px 12px;
|
|
1085
|
+
overflow-y: auto;
|
|
1086
|
+
scrollbar-width: none;
|
|
1087
|
+
}
|
|
1088
|
+
.ag-compact-list::-webkit-scrollbar { display: none; }
|
|
1089
|
+
.ag-compact-row {
|
|
1090
|
+
display: flex;
|
|
1091
|
+
align-items: center;
|
|
1092
|
+
gap: 8px;
|
|
1093
|
+
padding: 4px 0;
|
|
1094
|
+
cursor: pointer;
|
|
1095
|
+
}
|
|
1096
|
+
.ag-compact-row--selected {
|
|
1097
|
+
background: color-mix(in srgb, var(--ev-color) 10%, transparent);
|
|
1098
|
+
border-radius: 4px;
|
|
1099
|
+
padding-left: 6px;
|
|
1100
|
+
padding-right: 6px;
|
|
1101
|
+
}
|
|
1102
|
+
.ag-compact-row:hover .ag-compact-row-title { color: var(--dt-text); }
|
|
1103
|
+
.ag-compact-row:focus-visible {
|
|
1104
|
+
outline: 2px solid var(--dt-accent, #2563eb);
|
|
1105
|
+
outline-offset: 2px;
|
|
1106
|
+
}
|
|
1107
|
+
.ag-compact-row-dot {
|
|
1108
|
+
width: 5px;
|
|
1109
|
+
height: 5px;
|
|
1110
|
+
border-radius: 50%;
|
|
1111
|
+
background: var(--ev-color, var(--dt-accent));
|
|
1112
|
+
flex-shrink: 0;
|
|
1113
|
+
}
|
|
1114
|
+
.ag-compact-row-time {
|
|
1115
|
+
font-size: 11px;
|
|
1116
|
+
font-family: var(--dt-mono, monospace);
|
|
1117
|
+
color: var(--dt-text-2, rgba(255, 255, 255, 0.5));
|
|
1118
|
+
min-width: 64px;
|
|
1119
|
+
flex-shrink: 0;
|
|
1120
|
+
}
|
|
1121
|
+
.ag-compact-row-title {
|
|
1122
|
+
font-size: 12px;
|
|
1123
|
+
font-weight: 500;
|
|
1124
|
+
color: var(--dt-text-2, rgba(255, 255, 255, 0.5));
|
|
1125
|
+
flex: 1;
|
|
1126
|
+
white-space: nowrap;
|
|
1127
|
+
overflow: hidden;
|
|
1128
|
+
text-overflow: ellipsis;
|
|
1129
|
+
transition: color 150ms;
|
|
1130
|
+
}
|
|
1131
|
+
.ag-compact-row-dur {
|
|
1132
|
+
font-size: 10px;
|
|
1133
|
+
font-family: var(--dt-mono, monospace);
|
|
1134
|
+
color: var(--dt-text-3, rgba(255, 255, 255, 0.3));
|
|
1135
|
+
flex-shrink: 0;
|
|
1136
|
+
}
|
|
1137
|
+
.ag-compact-row-sub {
|
|
1138
|
+
font-size: 10px;
|
|
1139
|
+
color: var(--dt-text-3, rgba(255, 255, 255, 0.35));
|
|
1140
|
+
flex-shrink: 0;
|
|
1141
|
+
}
|
|
1142
|
+
.ag-compact-row-tag {
|
|
1143
|
+
font: 500 8px / 1 var(--dt-sans, system-ui, sans-serif);
|
|
1144
|
+
color: var(--ev-color, var(--dt-accent));
|
|
1145
|
+
background: color-mix(in srgb, var(--ev-color, var(--dt-accent)) 12%, transparent);
|
|
1146
|
+
padding: 1px 4px;
|
|
1147
|
+
border-radius: 3px;
|
|
1148
|
+
white-space: nowrap;
|
|
1149
|
+
flex-shrink: 0;
|
|
1150
|
+
}
|
|
1151
|
+
.ag-compact-row--cancelled { opacity: 0.5; }
|
|
1152
|
+
.ag-compact-row--cancelled .ag-compact-row-title { text-decoration: line-through; }
|
|
1153
|
+
.ag-compact-row--tentative { opacity: 0.65; }
|
|
1154
|
+
/* Mobile: larger touch targets for compact rows */
|
|
1155
|
+
.ag--mobile .ag-compact-row { padding: 8px 0; }
|
|
1156
|
+
.ag--mobile .ag-compact-row-title { font-size: 14px; }
|
|
1157
|
+
.ag--mobile .ag-compact-row-time { font-size: 12px; }
|
|
1158
|
+
|
|
1060
1159
|
/* ═══ Future Day: "The Plan" ═══ */
|
|
1061
1160
|
.ag-plan {
|
|
1062
1161
|
flex: 1;
|