@nomideusz/svelte-calendar 1.3.0 → 1.4.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.
@@ -139,15 +139,18 @@ function collectData(raw, mappedKeys, include) {
139
139
  * ```
140
140
  */
141
141
  export function createMappedAdapter(sourceData, options = {}) {
142
- const { fields, mapEvent: customMapper, includeData = '*', autoColor = true, palette = VIVID_PALETTE, readOnly = true, } = options;
142
+ const { fields, mapEvent: customMapper, includeData = '*', autoColor = false, palette = autoColor ? VIVID_PALETTE : undefined, readOnly = true, } = options;
143
143
  // Build the internal event list
144
144
  const events = [];
145
145
  const colorAssignments = new Map();
146
146
  let colorIndex = 0;
147
147
  function resolveColor(ev) {
148
- // When autoColor is on, always assign from palette (ignore source color)
148
+ // autoColor: always assign from the palette (ignore source color).
149
+ // Otherwise keep the source color; fill only when a palette is given.
149
150
  if (!autoColor && ev.color)
150
151
  return ev.color;
152
+ if (!palette?.length)
153
+ return ev.color;
151
154
  const key = ev.category ?? ev.title;
152
155
  if (!colorAssignments.has(key)) {
153
156
  colorAssignments.set(key, palette[colorIndex % palette.length]);
@@ -2,21 +2,22 @@
2
2
  * In-memory adapter — the default for demos and testing.
3
3
  *
4
4
  * Events are stored in a plain array. No persistence across page loads.
5
- * Events without a `color` are auto-assigned one from a palette,
6
- * grouped by `category` or `title` so related events share a color.
5
+ * Events without a `color` stay uncoloured and draw in `--dt-event` (ink).
6
+ * Pass `palette` to auto-assign colours instead, grouped by `category` or
7
+ * `title` so related events share one.
7
8
  *
8
9
  * Usage:
9
10
  * import { createMemoryAdapter } from './';
10
11
  * const adapter = createMemoryAdapter(initialEvents);
11
- * const adapter = createMemoryAdapter(initialEvents, { palette: myColors });
12
+ * const adapter = createMemoryAdapter(initialEvents, { palette: VIVID_PALETTE });
12
13
  */
13
14
  import type { TimelineEvent } from '../core/types.js';
14
15
  import type { CalendarAdapter } from './types.js';
15
16
  export interface MemoryAdapterOptions {
16
17
  /**
17
- * Custom color palette for auto-coloring events.
18
- * Defaults to VIVID_PALETTE. Pass `generatePalette(accent)` to
19
- * make event colors adapt to your theme.
18
+ * Colour palette for auto-colouring events that have no `color`.
19
+ * Off by default (events draw in `--dt-event`). Pass `VIVID_PALETTE`
20
+ * for the pre-1.4 look, or `generatePalette(accent)` for theme-harmonious colours.
20
21
  */
21
22
  palette?: readonly string[];
22
23
  }
@@ -1,4 +1,3 @@
1
- import { VIVID_PALETTE } from '../core/palette.js';
2
1
  import { overlapsRange } from '../core/time.js';
3
2
  import { EventNotFoundError } from './errors.js';
4
3
  let counter = 0;
@@ -7,12 +6,12 @@ function uid() {
7
6
  }
8
7
  export function createMemoryAdapter(initial = [], options) {
9
8
  const events = [...initial];
10
- const palette = options?.palette ?? VIVID_PALETTE;
11
- // Auto-color: assign from vivid palette by category/title
9
+ const palette = options?.palette;
10
+ // Opt-in auto-color: assign from the palette by category/title
12
11
  const colorAssignments = new Map();
13
12
  let colorIndex = 0;
14
13
  function resolveColor(ev) {
15
- if (ev.color)
14
+ if (ev.color || !palette?.length)
16
15
  return ev.color;
17
16
  const key = ev.category ?? ev.title;
18
17
  if (!colorAssignments.has(key)) {
@@ -74,10 +74,10 @@ export interface RecurringAdapterOptions {
74
74
  /** Start weeks on Monday (default: true) */
75
75
  mondayStart?: boolean;
76
76
  /**
77
- * Custom color palette for auto-coloring events.
78
- * Pass `generatePalette('#yourAccent')` to get theme-harmonious colors,
79
- * or provide your own array of hex strings.
80
- * Defaults to the built-in vivid palette.
77
+ * Colour palette for auto-colouring events that have no `color`.
78
+ * Off by default (events draw in `--dt-event`). Pass `VIVID_PALETTE`
79
+ * for the pre-1.4 look, `generatePalette('#yourAccent')` for
80
+ * theme-harmonious colours, or your own array of colours.
81
81
  */
82
82
  palette?: readonly string[];
83
83
  /**
@@ -95,8 +95,8 @@ export interface RecurringAdapterOptions {
95
95
  * Create a CalendarAdapter that projects recurring events onto concrete
96
96
  * dates for whatever range the calendar requests.
97
97
  *
98
- * Events without a `color` are auto-assigned one from a vivid palette,
99
- * grouped by `category` or `title` so related events share a color.
98
+ * Events without a `color` draw in `--dt-event` (ink) unless `palette` is
99
+ * given; then they are auto-assigned one, grouped by `category` or `title`.
100
100
  *
101
101
  * Read-only by default — create/update/delete throw.
102
102
  */
@@ -1,5 +1,4 @@
1
1
  import { startOfWeek, addDaysMs, diffDays, DAY_MS, overlapsRange } from '../core/time.js';
2
- import { VIVID_PALETTE } from '../core/palette.js';
3
2
  import { CalendarReadOnlyError, EventNotFoundError } from './errors.js';
4
3
  // ── Helpers ─────────────────────────────────────────────
5
4
  /** Parse "HH:MM" into [hours, minutes] */
@@ -234,32 +233,31 @@ function projectMonthly(rec, range, startDate, effectiveUntil, out) {
234
233
  }
235
234
  }
236
235
  // ── Adapter factory ─────────────────────────────────────
237
- /** Default palette for auto-coloring */
238
- const PALETTE = VIVID_PALETTE;
239
236
  /**
240
237
  * Create a CalendarAdapter that projects recurring events onto concrete
241
238
  * dates for whatever range the calendar requests.
242
239
  *
243
- * Events without a `color` are auto-assigned one from a vivid palette,
244
- * grouped by `category` or `title` so related events share a color.
240
+ * Events without a `color` draw in `--dt-event` (ink) unless `palette` is
241
+ * given; then they are auto-assigned one, grouped by `category` or `title`.
245
242
  *
246
243
  * Read-only by default — create/update/delete throw.
247
244
  */
248
245
  export function createRecurringAdapter(schedule, options = {}) {
249
246
  const { mondayStart = true, palette, movable = false } = options;
250
- const colors = palette?.length ? palette : PALETTE;
247
+ const colors = palette?.length ? palette : undefined;
251
248
  // Auto-color: assign from palette by category/title
252
249
  const colorAssignments = new Map();
253
250
  let colorIndex = 0;
254
- for (const rec of schedule) {
255
- if (rec.color)
256
- continue;
257
- const key = rec.category ?? rec.title;
258
- if (!colorAssignments.has(key)) {
259
- colorAssignments.set(key, colors[colorIndex % colors.length]);
260
- colorIndex++;
251
+ if (colors)
252
+ for (const rec of schedule) {
253
+ if (rec.color)
254
+ continue;
255
+ const key = rec.category ?? rec.title;
256
+ if (!colorAssignments.has(key)) {
257
+ colorAssignments.set(key, colors[colorIndex % colors.length]);
258
+ colorIndex++;
259
+ }
261
260
  }
262
- }
263
261
  function resolveColor(rec) {
264
262
  if (rec.color)
265
263
  return rec.color;
@@ -376,6 +376,7 @@ setContext("calendar", {
376
376
  get labels() {
377
377
  return mergedLabels;
378
378
  },
379
+ announce,
379
380
  // Load range (read/write)
380
381
  get loadRange() {
381
382
  return viewLoadRange;
@@ -479,6 +480,17 @@ const dateLabel = $derived.by(() => {
479
480
  year: "numeric"
480
481
  });
481
482
  });
483
+ // ── Polite announcements (views say why an action did nothing) ──
484
+ // Shares the header's status line; a note lasts until the range changes.
485
+ let note = $state(null);
486
+ function announce(text) {
487
+ // A repeated message must change the text node to be read again.
488
+ note = {
489
+ text: note?.text === text ? `${text}\u00a0` : text,
490
+ label: dateLabel
491
+ };
492
+ }
493
+ const noteText = $derived(note && note.label === dateLabel ? note.text : "");
482
494
  // ── Period title (the built-in header's big line) ──
483
495
  // Names the month the user is looking at: "October 2026"; a week across two
484
496
  // months reads "Oct – Nov 2026"; a day gives its date. `dateLabel` keeps the
@@ -656,7 +668,7 @@ const navCtx = $derived({
656
668
  <div class="cal-hd" class:cal-hd--mobile={useMobile} class:cal-hd--stack={stackHeader}>
657
669
  <!-- The visible title names the month; the status line announces the exact range -->
658
670
  <span class="cal-hd-title" aria-hidden="true">{periodTitle}</span>
659
- <span class="cal-sr" role="status" aria-live="polite" aria-atomic="true">{dateLabel}</span>
671
+ <span class="cal-sr" role="status" aria-live="polite" aria-atomic="true">{noteText || dateLabel}</span>
660
672
  {#if showModePills && !useMobile && labelsForMode.length > 1}
661
673
  <!-- View-type switcher (e.g. Planner ↔ Agenda) for the current mode -->
662
674
  <div class="cal-pills cal-pills--labels" role="radiogroup" aria-label={L.viewMode}>
@@ -715,6 +727,10 @@ const navCtx = $derived({
715
727
  </div>
716
728
  {/if}
717
729
 
730
+ {#if headerSnippet || !(showNavigation || (showModePills && modes.length > 1) || dateLabel)}
731
+ <span class="cal-sr" role="status" aria-live="polite" aria-atomic="true">{noteText}</span>
732
+ {/if}
733
+
718
734
  <div class="cal-body">
719
735
  {#if activeView}
720
736
  {@const Comp = activeView.component}
@@ -755,7 +771,7 @@ const navCtx = $derived({
755
771
  overflow: clip;
756
772
  display: flex;
757
773
  flex-direction: column;
758
- border: 1px solid var(--dt-border, rgba(0, 0, 0, 0.08));
774
+ border: 1px solid var(--dt-border, rgba(15, 15, 15, 0.08));
759
775
  box-sizing: border-box;
760
776
  }
761
777
  .cal--auto {
@@ -775,11 +791,11 @@ const navCtx = $derived({
775
791
  align-items: center;
776
792
  gap: 10px 24px;
777
793
  padding: 14px 16px 12px;
778
- border-bottom: 1px solid var(--dt-border, rgba(0, 0, 0, 0.08));
794
+ border-bottom: 1px solid var(--dt-border, rgba(15, 15, 15, 0.08));
779
795
  flex-shrink: 0;
780
796
  box-sizing: border-box;
781
797
  font-family: var(--dt-sans, system-ui, sans-serif);
782
- color: var(--dt-text, rgba(0, 0, 0, 0.87));
798
+ color: var(--dt-text, rgba(15, 15, 15, 0.87));
783
799
  }
784
800
 
785
801
  .cal-hd-title {
@@ -819,10 +835,10 @@ const navCtx = $derived({
819
835
  .cal-hd-btn {
820
836
  box-sizing: border-box;
821
837
  height: var(--cal-ctl-h);
822
- border: 2px solid var(--dt-text, rgba(0, 0, 0, 0.87));
838
+ border: 2px solid var(--dt-text, rgba(15, 15, 15, 0.87));
823
839
  border-radius: var(--cal-ctl-r);
824
840
  background: transparent;
825
- color: var(--dt-text, rgba(0, 0, 0, 0.87));
841
+ color: var(--dt-text, rgba(15, 15, 15, 0.87));
826
842
  cursor: pointer;
827
843
  transition: background-color 120ms, opacity 120ms;
828
844
  -webkit-tap-highlight-color: transparent;
@@ -848,7 +864,7 @@ const navCtx = $derived({
848
864
  }
849
865
  .cal-hd-today:active:not(:disabled),
850
866
  .cal-hd-btn:active {
851
- background: color-mix(in srgb, var(--dt-text, #000) 12%, transparent);
867
+ background: color-mix(in srgb, var(--dt-text, #0f0f0f) 12%, transparent);
852
868
  }
853
869
  /* Today is already in view: the frame stays, quietly */
854
870
  .cal-hd-today:disabled {
@@ -859,7 +875,7 @@ const navCtx = $derived({
859
875
  .cal-hd-today:focus-visible,
860
876
  .cal-hd-btn:focus-visible,
861
877
  .cal-pill:focus-visible {
862
- outline: 2px solid var(--dt-text, rgba(0, 0, 0, 0.87));
878
+ outline: 2px solid var(--dt-text, rgba(15, 15, 15, 0.87));
863
879
  outline-offset: 2px;
864
880
  }
865
881
 
@@ -875,12 +891,12 @@ const navCtx = $derived({
875
891
  align-self: stretch;
876
892
  align-items: center;
877
893
  padding-inline-start: 24px;
878
- border-inline-start: 1px solid var(--dt-border, rgba(0, 0, 0, 0.12));
894
+ border-inline-start: 1px solid var(--dt-border, rgba(15, 15, 15, 0.12));
879
895
  }
880
896
  .cal-pill {
881
897
  border: none;
882
898
  background: transparent;
883
- color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
899
+ color: var(--dt-text-2, rgba(15, 15, 15, 0.54));
884
900
  cursor: pointer;
885
901
  font: 400 15px/1 var(--dt-sans, system-ui, sans-serif);
886
902
  min-height: var(--cal-ctl-h);
@@ -896,11 +912,11 @@ const navCtx = $derived({
896
912
  }
897
913
  /* :not(--active) — iOS keeps :hover stuck after a tap */
898
914
  .cal-pill:hover:not(.cal-pill--active) {
899
- color: var(--dt-text, rgba(0, 0, 0, 0.87));
900
- text-decoration-color: var(--dt-border-day, var(--dt-border, rgba(0, 0, 0, 0.3)));
915
+ color: var(--dt-text, rgba(15, 15, 15, 0.87));
916
+ text-decoration-color: var(--dt-border-day, var(--dt-border, rgba(15, 15, 15, 0.3)));
901
917
  }
902
918
  .cal-pill--active {
903
- color: var(--dt-text, rgba(0, 0, 0, 0.87));
919
+ color: var(--dt-text, rgba(15, 15, 15, 0.87));
904
920
  text-decoration-color: currentColor;
905
921
  }
906
922
 
@@ -962,7 +978,7 @@ const navCtx = $derived({
962
978
  justify-content: center;
963
979
  height: 100%;
964
980
  font: 400 13px / 1 var(--dt-sans, system-ui, sans-serif);
965
- color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
981
+ color: var(--dt-text-3, rgba(15, 15, 15, 0.38));
966
982
  }
967
983
 
968
984
  .cal-loading {
@@ -974,7 +990,7 @@ const navCtx = $derived({
974
990
  background: linear-gradient(
975
991
  90deg,
976
992
  transparent 0%,
977
- var(--dt-accent, #2563eb) 50%,
993
+ var(--dt-accent, #1d4fd7) 50%,
978
994
  transparent 100%
979
995
  );
980
996
  animation: cal-slide 1.2s ease-in-out infinite;
@@ -988,7 +1004,7 @@ const navCtx = $derived({
988
1004
  @media (prefers-reduced-motion: reduce) {
989
1005
  .cal-loading {
990
1006
  animation: none;
991
- background: var(--dt-accent-dim, rgba(37, 99, 235, 0.12));
1007
+ background: var(--dt-accent-dim, rgba(29, 79, 215, 0.12));
992
1008
  }
993
1009
  }
994
1010
 
@@ -69,7 +69,7 @@ export interface CalendarProps {
69
69
  mondayStart?: boolean;
70
70
  /** Total height. Use `'auto'` to let content determine height (ideal for Agenda views). */
71
71
  height?: number | 'auto';
72
- /** Border radius in px (default: 12). Set to 0 for no rounding. */
72
+ /** Border radius in px (default: 0, square-cut). */
73
73
  borderRadius?: number;
74
74
  /** Text direction: 'ltr' (default), 'rtl', or 'auto' */
75
75
  dir?: 'ltr' | 'rtl' | 'auto';
@@ -43,18 +43,18 @@ const dayNum = $derived(new Date(dayMs).getDate());
43
43
  font: 500 10px / 1 var(--dt-sans, system-ui, sans-serif);
44
44
  letter-spacing: 0.04em;
45
45
  text-transform: uppercase;
46
- color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
46
+ color: var(--dt-text-2, rgba(15, 15, 15, 0.54));
47
47
  }
48
48
  .dh-name-long {
49
49
  font-size: 12px;
50
50
  text-transform: none;
51
51
  letter-spacing: 0.01em;
52
- color: var(--dt-text, rgba(0, 0, 0, 0.87));
52
+ color: var(--dt-text, rgba(15, 15, 15, 0.87));
53
53
  }
54
54
 
55
55
  .dh-num {
56
56
  font: 600 14px / 1 var(--dt-sans, system-ui, sans-serif);
57
- color: var(--dt-text, rgba(0, 0, 0, 0.87));
57
+ color: var(--dt-text, rgba(15, 15, 15, 0.87));
58
58
  width: 28px;
59
59
  height: 28px;
60
60
  display: flex;
@@ -63,20 +63,20 @@ const dayNum = $derived(new Date(dayMs).getDate());
63
63
  border-radius: 50%;
64
64
  }
65
65
  .dh-num-today {
66
- background: var(--dt-accent, #2563eb);
66
+ background: var(--dt-accent, #1d4fd7);
67
67
  color: var(--dt-btn-text, #fff);
68
68
  }
69
69
 
70
70
  .dh-date {
71
71
  font: 400 10px / 1 var(--dt-sans, system-ui, sans-serif);
72
- color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
72
+ color: var(--dt-text-2, rgba(15, 15, 15, 0.54));
73
73
  }
74
74
 
75
75
  .dh-rel {
76
76
  font: 500 12px / 1.3 var(--dt-sans, system-ui, sans-serif);
77
- color: var(--dt-text, rgba(0, 0, 0, 0.87));
77
+ color: var(--dt-text, rgba(15, 15, 15, 0.87));
78
78
  }
79
79
  .dh-today .dh-rel {
80
- color: var(--dt-accent, #2563eb);
80
+ color: var(--dt-accent, #1d4fd7);
81
81
  }
82
82
  </style>
@@ -49,13 +49,13 @@ function handleKeydown(e) {
49
49
  min-height: 24px;
50
50
  }
51
51
  .es:hover {
52
- border-color: var(--dt-accent-dim, rgba(37, 99, 235, 0.12));
53
- background: var(--dt-accent-dim, rgba(37, 99, 235, 0.12));
52
+ border-color: var(--dt-accent-dim, rgba(29, 79, 215, 0.12));
53
+ background: var(--dt-accent-dim, rgba(29, 79, 215, 0.12));
54
54
  }
55
55
  .es:focus-visible {
56
- outline: 2px solid var(--dt-accent, #2563eb);
56
+ outline: 2px solid var(--dt-accent, #1d4fd7);
57
57
  outline-offset: 2px;
58
- border-color: var(--dt-accent-dim, rgba(37, 99, 235, 0.12));
58
+ border-color: var(--dt-accent-dim, rgba(29, 79, 215, 0.12));
59
59
  }
60
60
 
61
61
  .es-hint {
@@ -74,12 +74,12 @@ function handleKeydown(e) {
74
74
 
75
75
  .es-plus {
76
76
  font: 500 14px / 1 var(--dt-sans, system-ui, sans-serif);
77
- color: var(--dt-accent, #2563eb);
77
+ color: var(--dt-accent, #1d4fd7);
78
78
  }
79
79
  .es-range {
80
80
  font: 400 10px / 1 var(--dt-sans, system-ui, sans-serif);
81
81
  font-variant-numeric: tabular-nums;
82
- color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
82
+ color: var(--dt-text-2, rgba(15, 15, 15, 0.54));
83
83
  }
84
84
 
85
85
  .es-v {
@@ -14,7 +14,7 @@ import { getContext } from "svelte";
14
14
  const calendarCtx = getContext("calendar");
15
15
  const L = $derived(calendarCtx?.labels ?? getLabels());
16
16
  let { event, variant = "chip", active = false, past = false, showTime = false, showDuration = false, editable = false, onclick, children } = $props();
17
- const accentColor = $derived(event.color || "var(--dt-accent, #2563eb)");
17
+ const accentColor = $derived(event.color || "var(--dt-event, var(--dt-accent))");
18
18
  const isCancelled = $derived(event.status === "cancelled");
19
19
  const isTentative = $derived(event.status === "tentative");
20
20
  const isFull = $derived(event.status === "full");
@@ -145,7 +145,7 @@ function handleKeydown(e) {
145
145
 
146
146
  <style>
147
147
  .eb {
148
- --_color: var(--eb-color, var(--dt-accent, #2563eb));
148
+ --_color: var(--eb-color, var(--dt-accent, #1d4fd7));
149
149
  cursor: default;
150
150
  transition: opacity 120ms, transform 80ms;
151
151
  }
@@ -156,7 +156,7 @@ function handleKeydown(e) {
156
156
  transform: translateY(-1px);
157
157
  }
158
158
  .eb:focus-visible {
159
- outline: 2px solid var(--dt-accent, #2563eb);
159
+ outline: 2px solid var(--dt-accent, #1d4fd7);
160
160
  outline-offset: 2px;
161
161
  border-radius: 4px;
162
162
  }
@@ -195,7 +195,7 @@ function handleKeydown(e) {
195
195
  align-items: center;
196
196
  gap: 5px;
197
197
  font: 400 11px / 1 var(--dt-sans, system-ui, sans-serif);
198
- color: var(--dt-text, rgba(0, 0, 0, 0.87));
198
+ color: var(--dt-text, rgba(15, 15, 15, 0.87));
199
199
  white-space: nowrap;
200
200
  overflow: hidden;
201
201
  text-overflow: ellipsis;
@@ -221,8 +221,8 @@ function handleKeydown(e) {
221
221
  .eb-card {
222
222
  display: flex;
223
223
  border-radius: 8px;
224
- background: var(--dt-surface, var(--dt-bg, #ffffff));
225
- border: 1px solid var(--dt-border, rgba(0, 0, 0, 0.08));
224
+ background: var(--dt-surface, var(--dt-bg, #efebe9));
225
+ border: 1px solid var(--dt-border, rgba(15, 15, 15, 0.08));
226
226
  overflow: hidden;
227
227
  }
228
228
  .eb-card .eb-stripe {
@@ -239,7 +239,7 @@ function handleKeydown(e) {
239
239
  }
240
240
  .eb-card .eb-title {
241
241
  font: 500 12px / 1.3 var(--dt-sans, system-ui, sans-serif);
242
- color: var(--dt-text, rgba(0, 0, 0, 0.87));
242
+ color: var(--dt-text, rgba(15, 15, 15, 0.87));
243
243
  overflow: hidden;
244
244
  text-overflow: ellipsis;
245
245
  white-space: nowrap;
@@ -247,11 +247,11 @@ function handleKeydown(e) {
247
247
  .eb-card .eb-time {
248
248
  font: 400 10px / 1 var(--dt-sans, system-ui, sans-serif);
249
249
  font-variant-numeric: tabular-nums;
250
- color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
250
+ color: var(--dt-text-2, rgba(15, 15, 15, 0.54));
251
251
  }
252
252
  .eb-card .eb-dur {
253
253
  font: 300 10px / 1 var(--dt-sans, system-ui, sans-serif);
254
- color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
254
+ color: var(--dt-text-3, rgba(15, 15, 15, 0.38));
255
255
  }
256
256
 
257
257
  /* ── Row ── */
@@ -260,7 +260,7 @@ function handleKeydown(e) {
260
260
  align-items: center;
261
261
  gap: 10px;
262
262
  padding: 6px 12px;
263
- border-bottom: 1px solid var(--dt-border, rgba(0, 0, 0, 0.08));
263
+ border-bottom: 1px solid var(--dt-border, rgba(15, 15, 15, 0.08));
264
264
  }
265
265
  .eb-row .eb-stripe {
266
266
  width: 3px;
@@ -273,13 +273,13 @@ function handleKeydown(e) {
273
273
  .eb-row .eb-time {
274
274
  font: 400 10px / 1 var(--dt-sans, system-ui, sans-serif);
275
275
  font-variant-numeric: tabular-nums;
276
- color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
276
+ color: var(--dt-text-2, rgba(15, 15, 15, 0.54));
277
277
  flex-shrink: 0;
278
278
  width: 90px;
279
279
  }
280
280
  .eb-row .eb-title {
281
281
  font: 400 12px / 1.3 var(--dt-sans, system-ui, sans-serif);
282
- color: var(--dt-text, rgba(0, 0, 0, 0.87));
282
+ color: var(--dt-text, rgba(15, 15, 15, 0.87));
283
283
  flex: 1;
284
284
  overflow: hidden;
285
285
  text-overflow: ellipsis;
@@ -287,14 +287,14 @@ function handleKeydown(e) {
287
287
  }
288
288
  .eb-row .eb-dur {
289
289
  font: 300 10px / 1 var(--dt-sans, system-ui, sans-serif);
290
- color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
290
+ color: var(--dt-text-3, rgba(15, 15, 15, 0.38));
291
291
  flex-shrink: 0;
292
292
  }
293
293
 
294
294
  /* ── Shared ── */
295
295
  .eb-subtitle {
296
296
  font: 400 10px / 1.2 var(--dt-sans, system-ui, sans-serif);
297
- color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
297
+ color: var(--dt-text-2, rgba(15, 15, 15, 0.54));
298
298
  overflow: hidden;
299
299
  text-overflow: ellipsis;
300
300
  white-space: nowrap;
@@ -316,7 +316,7 @@ function handleKeydown(e) {
316
316
  }
317
317
  .eb-location {
318
318
  font: 400 9px / 1.2 var(--dt-sans, system-ui, sans-serif);
319
- color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
319
+ color: var(--dt-text-3, rgba(15, 15, 15, 0.38));
320
320
  overflow: hidden;
321
321
  text-overflow: ellipsis;
322
322
  white-space: nowrap;
@@ -332,16 +332,16 @@ function handleKeydown(e) {
332
332
  width: fit-content;
333
333
  }
334
334
  .eb-cancelled-badge {
335
- color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
336
- background: color-mix(in srgb, var(--dt-text-2, rgba(0, 0, 0, 0.54)) 15%, transparent);
335
+ color: var(--dt-text-2, rgba(15, 15, 15, 0.54));
336
+ background: color-mix(in srgb, var(--dt-text-2, rgba(15, 15, 15, 0.54)) 15%, transparent);
337
337
  }
338
338
  .eb-tentative-badge {
339
339
  color: var(--_color);
340
340
  background: color-mix(in srgb, var(--_color) 12%, transparent);
341
341
  }
342
342
  .eb-full-badge {
343
- color: var(--dt-accent, #2563eb);
344
- background: color-mix(in srgb, var(--dt-accent, #2563eb) 15%, transparent);
343
+ color: var(--dt-accent, #1d4fd7);
344
+ background: color-mix(in srgb, var(--dt-accent, #1d4fd7) 15%, transparent);
345
345
  }
346
346
  .eb-limited-badge {
347
347
  color: var(--_color);
@@ -211,8 +211,8 @@ function onKeydown(e) {
211
211
  max-height: calc(100vh - 16px);
212
212
  display: flex;
213
213
  flex-direction: column;
214
- background: var(--dt-surface, #fff);
215
- color: var(--dt-text, #111);
214
+ background: var(--dt-surface, #f4f1ee);
215
+ color: var(--dt-text, #0f0f0f);
216
216
  border: 1px solid var(--dt-border, #e2e2e2);
217
217
  border-radius: var(--dt-radius, 8px);
218
218
  box-shadow: var(--dt-shadow, 0 16px 48px rgba(0, 0, 0, 0.18));
@@ -252,8 +252,8 @@ function onKeydown(e) {
252
252
  cursor: pointer;
253
253
  }
254
254
  .fp-close:hover {
255
- background: var(--dt-hover, rgba(0, 0, 0, 0.06));
256
- color: var(--dt-text, #111);
255
+ background: var(--dt-hover, rgba(15, 15, 15, 0.06));
256
+ color: var(--dt-text, #0f0f0f);
257
257
  }
258
258
  .fp-body {
259
259
  /* A flex child defaults to min-height:auto and never shrinks below its
@@ -74,7 +74,7 @@ const colorVar = $derived(color ? `--ni-color: ${color}` : "");
74
74
  height: 0;
75
75
  }
76
76
  .ni-line-bar {
77
- background: var(--ni-color, var(--dt-accent, #2563eb));
77
+ background: var(--ni-color, var(--dt-accent, #1d4fd7));
78
78
  }
79
79
  .ni-line.vertical .ni-line-bar {
80
80
  width: 2px;
@@ -92,8 +92,8 @@ const colorVar = $derived(color ? `--ni-color: ${color}` : "");
92
92
  width: 10px;
93
93
  height: 10px;
94
94
  border-radius: 50%;
95
- background: var(--ni-color, var(--dt-accent, #2563eb));
96
- box-shadow: 0 0 6px var(--ni-color, var(--dt-glow, rgba(37, 99, 235, 0.25)));
95
+ background: var(--ni-color, var(--dt-accent, #1d4fd7));
96
+ box-shadow: 0 0 6px var(--ni-color, var(--dt-glow, rgba(29, 79, 215, 0.25)));
97
97
  }
98
98
  .ni-dot.vertical .ni-dot-circle {
99
99
  margin-left: -5px;
@@ -109,7 +109,7 @@ const colorVar = $derived(color ? `--ni-color: ${color}` : "");
109
109
  font: 600 10px / 1 var(--dt-sans, system-ui, sans-serif);
110
110
  font-variant-numeric: tabular-nums;
111
111
  color: var(--dt-btn-text, #fff);
112
- background: var(--ni-color, var(--dt-accent, #2563eb));
112
+ background: var(--ni-color, var(--dt-accent, #1d4fd7));
113
113
  padding: 3px 6px;
114
114
  border-radius: 4px;
115
115
  }
@@ -136,7 +136,7 @@ const colorVar = $derived(color ? `--ni-color: ${color}` : "");
136
136
  letter-spacing: 0.08em;
137
137
  text-transform: uppercase;
138
138
  color: var(--dt-btn-text, #fff);
139
- background: var(--ni-color, var(--dt-accent, #2563eb));
139
+ background: var(--ni-color, var(--dt-accent, #1d4fd7));
140
140
  padding: 2px 7px;
141
141
  border-radius: 3px;
142
142
  animation: ni-pulse 2s ease-in-out infinite;
@@ -51,7 +51,7 @@ const firstHour = $derived(hours[0] ?? 0);
51
51
  top: 0;
52
52
  bottom: 0;
53
53
  width: 0;
54
- border-left: 1px solid var(--dt-border, rgba(0, 0, 0, 0.08));
54
+ border-left: 1px solid var(--dt-border, rgba(15, 15, 15, 0.08));
55
55
  }
56
56
  .tg-tick-half {
57
57
  border-left-style: dashed;
@@ -63,7 +63,7 @@ const firstHour = $derived(hours[0] ?? 0);
63
63
  left: 6px;
64
64
  font: 400 9px / 1 var(--dt-sans, system-ui, sans-serif);
65
65
  font-variant-numeric: tabular-nums;
66
- color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
66
+ color: var(--dt-text-3, rgba(15, 15, 15, 0.38));
67
67
  white-space: nowrap;
68
68
  }
69
69
 
@@ -81,11 +81,11 @@ const firstHour = $derived(hours[0] ?? 0);
81
81
  align-items: flex-start;
82
82
  justify-content: flex-end;
83
83
  padding: 2px 8px 0 0;
84
- border-top: 1px solid var(--dt-border, rgba(0, 0, 0, 0.08));
84
+ border-top: 1px solid var(--dt-border, rgba(15, 15, 15, 0.08));
85
85
  }
86
86
  .tg-v .tg-label {
87
87
  font: 400 9px / 1 var(--dt-sans, system-ui, sans-serif);
88
88
  font-variant-numeric: tabular-nums;
89
- color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
89
+ color: var(--dt-text-3, rgba(15, 15, 15, 0.38));
90
90
  }
91
91
  </style>
@@ -14,6 +14,11 @@
14
14
  *
15
15
  * The Calendar component calls this automatically when theme is `auto` (empty string).
16
16
  */
17
+ /**
18
+ * Text colour for an accent fill (all-day band, now plate): white when it
19
+ * reaches 4.5:1 on the accent, else whichever of white / dark ink contrasts more.
20
+ */
21
+ export declare function accentTextFor(accent: [number, number, number]): '#ffffff' | '#0f0f0f';
17
22
  /** Options for fine-tuning auto-detection behavior. */
18
23
  export interface AutoThemeOptions {
19
24
  /**