@nomideusz/svelte-calendar 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -95,7 +95,7 @@ import { wrapAdapterWithTimezone, toZonedTime, fromZonedTime } from "../core/tim
95
95
  import { isReadOnlyError, isNotFoundError } from "../adapters/errors.js";
96
96
  /** Breakpoint (px) at which auto-mobile activates */
97
97
  const MOBILE_BREAKPOINT = 768;
98
- let { adapter, views = defaultViews, view: activeViewId, theme = auto, autoTheme, mondayStart = true, height: heightProp = 600, borderRadius = 12, dir, locale, labels: labelsProp, readOnly = false, visibleHours, initialDate, snapInterval = 15, minColumnWidth = 110, showModePills = true, showNavigation = true, equalDays = false, showDates = true, hideDays, currentDate, blockedSlots, days, minDuration, maxDuration, disabledDates, compact = false, columns = false, mobile: mobileProp = "auto", event: eventSnippet, empty: emptySnippet, dayHeader: dayHeaderSnippet, header: headerSnippet, navigation: navigationSnippet, oneventclick, oneventcreate, onexternaldrop, oneventmove, onviewchange, ondatechange, oneventhover, ondayclick, onerror, timezone } = $props();
98
+ let { adapter, views = defaultViews, view: activeViewId, theme = auto, autoTheme, mondayStart = true, height: heightProp = 600, borderRadius = 0, dir, locale, labels: labelsProp, readOnly = false, visibleHours, initialDate, snapInterval = 15, minColumnWidth = 110, showModePills = true, showNavigation = true, equalDays = false, showDates = true, hideDays, currentDate, blockedSlots, days, minDuration, maxDuration, disabledDates, compact = false, columns = false, mobile: mobileProp = "auto", event: eventSnippet, empty: emptySnippet, dayHeader: dayHeaderSnippet, header: headerSnippet, navigation: navigationSnippet, oneventclick, oneventcreate, onexternaldrop, oneventmove, onviewchange, ondatechange, oneventhover, ondayclick, onerror, timezone } = $props();
99
99
  // In readOnly mode, suppress mutation callbacks. With a timezone, the
100
100
  // drag plane is zoned wall-clock — hosts always receive real instants.
101
101
  const unzone = (d) => timezone ? fromZonedTime(d, timezone) : d;
@@ -778,8 +778,8 @@ const navCtx = $derived({
778
778
  width: 100%;
779
779
  min-width: 0;
780
780
  height: var(--cal-h, 600px);
781
- background: var(--dt-bg, inherit);
782
- border-radius: var(--cal-r, 12px);
781
+ background: var(--dt-paper, none), var(--dt-bg, inherit);
782
+ border-radius: var(--cal-r, 0);
783
783
  overflow: clip;
784
784
  display: flex;
785
785
  flex-direction: column;
@@ -798,8 +798,8 @@ const navCtx = $derived({
798
798
  flex-wrap: wrap;
799
799
  align-items: center;
800
800
  gap: 8px;
801
- padding: 8px 12px;
802
- min-height: 48px;
801
+ padding: 6px 10px;
802
+ min-height: 44px;
803
803
  box-sizing: border-box;
804
804
  border-bottom: 1px solid var(--dt-border, rgba(0, 0, 0, 0.08));
805
805
  flex-shrink: 0;
@@ -818,7 +818,9 @@ const navCtx = $derived({
818
818
  }
819
819
 
820
820
  .cal-hd-title {
821
- font: 600 14px/1.2 var(--dt-sans, system-ui, sans-serif);
821
+ font: 500 16px/1.2 var(--dt-sans, system-ui, sans-serif);
822
+ font-variant-numeric: tabular-nums;
823
+ letter-spacing: -0.01em;
822
824
  color: var(--dt-text, rgba(0, 0, 0, 0.87));
823
825
  white-space: nowrap;
824
826
  overflow: hidden;
@@ -834,7 +836,7 @@ const navCtx = $derived({
834
836
  border: none;
835
837
  background: transparent;
836
838
  color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
837
- border-radius: 6px;
839
+ border-radius: 0;
838
840
  cursor: pointer;
839
841
  transition: background 120ms, color 120ms;
840
842
  }
@@ -853,11 +855,11 @@ const navCtx = $derived({
853
855
 
854
856
  .cal-hd-today {
855
857
  font: 500 12px/1 var(--dt-sans, system-ui, sans-serif);
856
- color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
858
+ color: var(--dt-text, rgba(0, 0, 0, 0.87));
857
859
  background: transparent;
858
- border: 1px solid var(--dt-border, rgba(0, 0, 0, 0.08));
859
- padding: 6px 10px;
860
- border-radius: 6px;
860
+ border: 1px solid var(--dt-border-day, var(--dt-border, rgba(0, 0, 0, 0.14)));
861
+ padding: 7px 10px;
862
+ border-radius: 0;
861
863
  cursor: pointer;
862
864
  white-space: nowrap;
863
865
  margin-right: 2px;
@@ -873,13 +875,10 @@ const navCtx = $derived({
873
875
  cursor: default;
874
876
  }
875
877
 
878
+ /* View switch: plain text tabs; the chosen one carries an ink rule. */
876
879
  .cal-pills {
877
880
  display: flex;
878
881
  gap: 2px;
879
- background: color-mix(in srgb, var(--dt-surface, var(--dt-bg, #ffffff)) 85%, transparent);
880
- border-radius: 8px;
881
- padding: 2px;
882
- border: 1px solid var(--dt-border, rgba(0, 0, 0, 0.08));
883
882
  flex-shrink: 0;
884
883
  }
885
884
 
@@ -888,10 +887,11 @@ const navCtx = $derived({
888
887
  background: transparent;
889
888
  color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
890
889
  cursor: pointer;
891
- font: 500 12px/1 var(--dt-sans, system-ui, sans-serif);
892
- padding: 5px 12px;
893
- border-radius: 6px;
894
- transition: background 100ms, color 100ms;
890
+ font: 500 13px/1 var(--dt-sans, system-ui, sans-serif);
891
+ padding: 8px 8px 7px;
892
+ border-radius: 0;
893
+ box-shadow: inset 0 -2px 0 transparent;
894
+ transition: box-shadow 100ms, color 100ms;
895
895
  }
896
896
 
897
897
  /* :not(--active) — the hover rule otherwise outranks the active color,
@@ -900,9 +900,10 @@ const navCtx = $derived({
900
900
  color: var(--dt-text, rgba(0, 0, 0, 0.87));
901
901
  }
902
902
 
903
+ /* Selected = ink text over an ink rule; the accent keeps its three jobs. */
903
904
  .cal-pill--active {
904
- background: var(--dt-accent, #2563eb);
905
- color: var(--dt-btn-text, #fff);
905
+ color: var(--dt-text, rgba(0, 0, 0, 0.87));
906
+ box-shadow: inset 0 -2px 0 var(--dt-text, rgba(0, 0, 0, 0.87));
906
907
  }
907
908
 
908
909
  .cal-body {
@@ -1024,10 +1025,6 @@ const navCtx = $derived({
1024
1025
  .cal-m-pills {
1025
1026
  display: flex;
1026
1027
  gap: 2px;
1027
- background: color-mix(in srgb, var(--dt-surface, var(--dt-bg, #ffffff)) 85%, transparent);
1028
- border-radius: 8px;
1029
- padding: 2px;
1030
- border: 1px solid var(--dt-border, rgba(0, 0, 0, 0.08));
1031
1028
  flex-shrink: 0;
1032
1029
  }
1033
1030
  .cal-m-pill {
@@ -1035,20 +1032,19 @@ const navCtx = $derived({
1035
1032
  background: transparent;
1036
1033
  color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
1037
1034
  cursor: pointer;
1038
- font: 600 12px / 1 var(--dt-sans, system-ui, sans-serif);
1039
- padding: 9px 12px;
1040
- border-radius: 6px;
1041
- letter-spacing: 0.04em;
1042
- text-transform: uppercase;
1043
- transition: background 100ms, color 100ms;
1035
+ font: 500 13px / 1 var(--dt-sans, system-ui, sans-serif);
1036
+ padding: 11px 10px 9px;
1037
+ border-radius: 0;
1038
+ box-shadow: inset 0 -2px 0 transparent;
1039
+ transition: box-shadow 100ms, color 100ms;
1044
1040
  -webkit-tap-highlight-color: transparent;
1045
1041
  }
1046
1042
  .cal-m-pill:hover:not(.cal-m-pill--active) {
1047
1043
  color: var(--dt-text, rgba(0, 0, 0, 0.87));
1048
1044
  }
1049
1045
  .cal-m-pill--active {
1050
- background: var(--dt-accent, #2563eb);
1051
- color: var(--dt-btn-text, #fff);
1046
+ color: var(--dt-text, rgba(0, 0, 0, 0.87));
1047
+ box-shadow: inset 0 -2px 0 var(--dt-text, rgba(0, 0, 0, 0.87));
1052
1048
  }
1053
1049
 
1054
1050
  .cal-m-title {
@@ -1063,33 +1059,31 @@ const navCtx = $derived({
1063
1059
  }
1064
1060
 
1065
1061
  .cal-m-today {
1066
- font: 600 12px / 1 var(--dt-sans, system-ui, sans-serif);
1067
- color: var(--dt-accent, #2563eb);
1068
- background: color-mix(in srgb, var(--dt-accent, #2563eb) 10%, transparent);
1069
- border: none;
1062
+ font: 600 13px / 1 var(--dt-sans, system-ui, sans-serif);
1063
+ color: var(--dt-text, rgba(0, 0, 0, 0.87));
1064
+ background: transparent;
1065
+ border: 1px solid var(--dt-border-day, rgba(0, 0, 0, 0.12));
1070
1066
  min-height: 40px;
1071
1067
  padding: 5px 12px;
1072
- border-radius: 6px;
1068
+ border-radius: 0;
1073
1069
  cursor: pointer;
1074
1070
  white-space: nowrap;
1075
- letter-spacing: 0.04em;
1076
- text-transform: uppercase;
1077
1071
  transition: background 120ms, color 120ms;
1078
1072
  -webkit-tap-highlight-color: transparent;
1079
1073
  flex-shrink: 0;
1080
1074
  }
1081
1075
  .cal-m-today:hover:not(:disabled) {
1082
- background: color-mix(in srgb, var(--dt-accent, #2563eb) 18%, transparent);
1076
+ border-color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
1083
1077
  }
1084
1078
  .cal-m-today:active:not(:disabled) {
1085
- background: color-mix(in srgb, var(--dt-accent, #2563eb) 25%, transparent);
1079
+ background: color-mix(in srgb, var(--dt-text, #000) 8%, transparent);
1086
1080
  }
1087
1081
  .cal-m-today:disabled {
1088
1082
  opacity: 0.45;
1089
1083
  cursor: default;
1090
1084
  }
1091
1085
  .cal-m-today:focus-visible {
1092
- outline: 2px solid color-mix(in srgb, var(--dt-accent, #2563eb) 55%, transparent);
1086
+ outline: 2px solid var(--dt-text, rgba(0, 0, 0, 0.87));
1093
1087
  outline-offset: 2px;
1094
1088
  }
1095
1089
  </style>
@@ -2,7 +2,7 @@ export { createClock } from './clock.svelte.js';
2
2
  export type { Clock } from './clock.svelte.js';
3
3
  export { DAY_MS, HOUR_MS, HOURS, sod, startOfWeek, addDaysMs, diffDays, pad, fractionalHour, fmtHM, fmtS, dayNum, dayOfWeek, isMultiDay, isAllDay, segmentForDay, } from './time.js';
4
4
  export type { DaySegment } from './time.js';
5
- export { setDefaultLocale, getDefaultLocale, is24HourLocale, fmtH, fmtTime, fmtDuration, weekdayShort, weekdayLong, monthShort, monthLong, dateShort, dateWithWeekday, fmtDay, fmtWeekRange, defaultLabels, setLabels, resetLabels, getLabels, } from './locale.js';
5
+ export { setDefaultLocale, getDefaultLocale, is24HourLocale, fmtH, fmtHParts, fmtTime, fmtDuration, weekdayShort, weekdayLong, monthShort, monthLong, dateShort, dateWithWeekday, fmtDay, fmtWeekRange, defaultLabels, setLabels, resetLabels, getLabels, } from './locale.js';
6
6
  export type { CalendarLabels } from './locale.js';
7
7
  export { toZonedTime, fromZonedTime, nowInZone, formatInTimeZone, } from './timezone.js';
8
8
  export type { TimelineEvent, BlockedSlot, EventStatus, } from './types.js';
@@ -4,7 +4,7 @@ export { createClock } from './clock.svelte.js';
4
4
  // Time constants & math
5
5
  export { DAY_MS, HOUR_MS, HOURS, sod, startOfWeek, addDaysMs, diffDays, pad, fractionalHour, fmtHM, fmtS, dayNum, dayOfWeek, isMultiDay, isAllDay, segmentForDay, } from './time.js';
6
6
  // Locale-aware formatting
7
- export { setDefaultLocale, getDefaultLocale, is24HourLocale, fmtH, fmtTime, fmtDuration, weekdayShort, weekdayLong, monthShort, monthLong, dateShort, dateWithWeekday, fmtDay, fmtWeekRange, defaultLabels, setLabels, resetLabels, getLabels, } from './locale.js';
7
+ export { setDefaultLocale, getDefaultLocale, is24HourLocale, fmtH, fmtHParts, fmtTime, fmtDuration, weekdayShort, weekdayLong, monthShort, monthLong, dateShort, dateWithWeekday, fmtDay, fmtWeekRange, defaultLabels, setLabels, resetLabels, getLabels, } from './locale.js';
8
8
  // Timezone utilities
9
9
  export { toZonedTime, fromZonedTime, nowInZone, formatInTimeZone, } from './timezone.js';
10
10
  // Palette
@@ -100,6 +100,11 @@ export declare function getDefaultLocale(): string;
100
100
  export declare function is24HourLocale(locale?: string): boolean;
101
101
  /** Format hour index (0-23) as compact label: 12h ("12a", "1p") or 24h ("0", "13") */
102
102
  export declare function fmtH(h: number, locale?: string): string;
103
+ /**
104
+ * Hour index (0-23) split for a timetable gutter: the numeral and the small
105
+ * part set beside it — `['13', '00']` in 24h locales, `['1', 'pm']` in 12h.
106
+ */
107
+ export declare function fmtHParts(h: number, locale?: string): [string, string];
103
108
  /** Short weekday name for a timestamp: "Mon", "Tue", etc. */
104
109
  export declare function weekdayShort(ms: number, locale?: string): string;
105
110
  /** Long weekday name for a timestamp: "Monday", "Tuesday", etc. */
@@ -117,6 +117,15 @@ export function fmtH(h, locale) {
117
117
  return '12p';
118
118
  return h < 12 ? h + 'a' : h - 12 + 'p';
119
119
  }
120
+ /**
121
+ * Hour index (0-23) split for a timetable gutter: the numeral and the small
122
+ * part set beside it — `['13', '00']` in 24h locales, `['1', 'pm']` in 12h.
123
+ */
124
+ export function fmtHParts(h, locale) {
125
+ if (is24HourLocale(locale))
126
+ return [String(h), '00'];
127
+ return [String(h % 12 || 12), h < 12 ? 'am' : 'pm'];
128
+ }
120
129
  /** Short weekday name for a timestamp: "Mon", "Tue", etc. */
121
130
  export function weekdayShort(ms, locale) {
122
131
  return new Date(ms).toLocaleDateString(locale ?? defaultLocale, { weekday: 'short' });
package/dist/index.d.ts CHANGED
@@ -10,7 +10,7 @@ export type { EventStore, ViewState, ViewStateOptions, CalendarViewId, BuiltInVi
10
10
  export { createMemoryAdapter, createRestAdapter, createRecurringAdapter, createMappedAdapter, createCompositeAdapter, createJmapAdapter, withInitialEvents } from './adapters/index.js';
11
11
  export { CalendarReadOnlyError, EventNotFoundError, isReadOnlyError, isNotFoundError } from './adapters/index.js';
12
12
  export type { CalendarAdapter, WritableCalendarAdapter, DateRange, MemoryAdapterOptions, RestAdapterOptions, RecurringEvent, RecurringAdapterOptions, FieldMapping, MappedAdapterOptions, MutationHandler, CompositeAdapterOptions, JmapClient, JmapCalendarAdapterOptions, } from './adapters/index.js';
13
- export { createClock, sod, startOfWeek, addDaysMs, diffDays, fmtH, fmtTime, fmtDuration, weekdayShort, weekdayLong, monthShort, monthLong, dateShort, dateWithWeekday, fmtDay, fmtWeekRange, setDefaultLocale, getDefaultLocale, is24HourLocale, defaultLabels, setLabels, resetLabels, getLabels, toZonedTime, fromZonedTime, nowInZone, formatInTimeZone, generatePalette, extractAccent, VIVID_PALETTE, isMultiDay, isAllDay, segmentForDay, } from './core/index.js';
13
+ export { createClock, sod, startOfWeek, addDaysMs, diffDays, fmtH, fmtHParts, fmtTime, fmtDuration, weekdayShort, weekdayLong, monthShort, monthLong, dateShort, dateWithWeekday, fmtDay, fmtWeekRange, setDefaultLocale, getDefaultLocale, is24HourLocale, defaultLabels, setLabels, resetLabels, getLabels, toZonedTime, fromZonedTime, nowInZone, formatInTimeZone, generatePalette, extractAccent, VIVID_PALETTE, isMultiDay, isAllDay, segmentForDay, } from './core/index.js';
14
14
  export type { Clock, TimelineEvent, BlockedSlot, DaySegment, CalendarLabels, EventStatus, } from './core/index.js';
15
15
  export { auto, neutral, midnight, presets } from './theme/index.js';
16
16
  export { probeHostTheme, observeHostTheme } from './theme/index.js';
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@ export { createEventStore, createViewState, createSelection, createDragState, }
13
13
  export { createMemoryAdapter, createRestAdapter, createRecurringAdapter, createMappedAdapter, createCompositeAdapter, createJmapAdapter, withInitialEvents } from './adapters/index.js';
14
14
  export { CalendarReadOnlyError, EventNotFoundError, isReadOnlyError, isNotFoundError } from './adapters/index.js';
15
15
  // ─── Core: clock, time, locale, types ───────────────────
16
- export { createClock, sod, startOfWeek, addDaysMs, diffDays, fmtH, fmtTime, fmtDuration, weekdayShort, weekdayLong, monthShort, monthLong, dateShort, dateWithWeekday, fmtDay, fmtWeekRange, setDefaultLocale, getDefaultLocale, is24HourLocale, defaultLabels, setLabels, resetLabels, getLabels, toZonedTime, fromZonedTime, nowInZone, formatInTimeZone, generatePalette, extractAccent, VIVID_PALETTE, isMultiDay, isAllDay, segmentForDay, } from './core/index.js';
16
+ export { createClock, sod, startOfWeek, addDaysMs, diffDays, fmtH, fmtHParts, fmtTime, fmtDuration, weekdayShort, weekdayLong, monthShort, monthLong, dateShort, dateWithWeekday, fmtDay, fmtWeekRange, setDefaultLocale, getDefaultLocale, is24HourLocale, defaultLabels, setLabels, resetLabels, getLabels, toZonedTime, fromZonedTime, nowInZone, formatInTimeZone, generatePalette, extractAccent, VIVID_PALETTE, isMultiDay, isAllDay, segmentForDay, } from './core/index.js';
17
17
  // ─── Themes ─────────────────────────────────────────────
18
18
  export { auto, neutral, midnight, presets } from './theme/index.js';
19
19
  export { probeHostTheme, observeHostTheme } from './theme/index.js';
@@ -77,7 +77,8 @@ function handleKeydown(e) {
77
77
  color: var(--dt-accent, #2563eb);
78
78
  }
79
79
  .es-range {
80
- font: 400 10px / 1 var(--dt-mono, 'SF Mono', monospace);
80
+ font: 400 10px / 1 var(--dt-sans, system-ui, sans-serif);
81
+ font-variant-numeric: tabular-nums;
81
82
  color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
82
83
  }
83
84
 
@@ -245,7 +245,8 @@ function handleKeydown(e) {
245
245
  white-space: nowrap;
246
246
  }
247
247
  .eb-card .eb-time {
248
- font: 400 10px / 1 var(--dt-mono, 'SF Mono', monospace);
248
+ font: 400 10px / 1 var(--dt-sans, system-ui, sans-serif);
249
+ font-variant-numeric: tabular-nums;
249
250
  color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
250
251
  }
251
252
  .eb-card .eb-dur {
@@ -270,7 +271,8 @@ function handleKeydown(e) {
270
271
  flex-shrink: 0;
271
272
  }
272
273
  .eb-row .eb-time {
273
- font: 400 10px / 1 var(--dt-mono, 'SF Mono', monospace);
274
+ font: 400 10px / 1 var(--dt-sans, system-ui, sans-serif);
275
+ font-variant-numeric: tabular-nums;
274
276
  color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
275
277
  flex-shrink: 0;
276
278
  width: 90px;
@@ -106,7 +106,8 @@ const colorVar = $derived(color ? `--ni-color: ${color}` : "");
106
106
  .ni-label {
107
107
  position: absolute;
108
108
  white-space: nowrap;
109
- font: 600 10px / 1 var(--dt-mono, 'SF Mono', 'Fira Code', monospace);
109
+ font: 600 10px / 1 var(--dt-sans, system-ui, sans-serif);
110
+ font-variant-numeric: tabular-nums;
110
111
  color: var(--dt-btn-text, #fff);
111
112
  background: var(--ni-color, var(--dt-accent, #2563eb));
112
113
  padding: 3px 6px;
@@ -61,7 +61,8 @@ const firstHour = $derived(hours[0] ?? 0);
61
61
  position: absolute;
62
62
  top: 4px;
63
63
  left: 6px;
64
- font: 400 9px / 1 var(--dt-mono, 'SF Mono', 'Fira Code', monospace);
64
+ font: 400 9px / 1 var(--dt-sans, system-ui, sans-serif);
65
+ font-variant-numeric: tabular-nums;
65
66
  color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
66
67
  white-space: nowrap;
67
68
  }
@@ -83,7 +84,8 @@ const firstHour = $derived(hours[0] ?? 0);
83
84
  border-top: 1px solid var(--dt-border, rgba(0, 0, 0, 0.08));
84
85
  }
85
86
  .tg-v .tg-label {
86
- font: 400 9px / 1 var(--dt-mono, 'SF Mono', 'Fira Code', monospace);
87
+ font: 400 9px / 1 var(--dt-sans, system-ui, sans-serif);
88
+ font-variant-numeric: tabular-nums;
87
89
  color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
88
90
  }
89
91
  </style>
package/dist/text-fit.js CHANGED
@@ -3,6 +3,9 @@
3
3
  // event handlers, never during SSR. `font` is a canvas font string, e.g.
4
4
  // "500 12px Inter" — name a real family; bare `system-ui` measures wrong on macOS.
5
5
  import { prepare, layout, prepareWithSegments, measureNaturalWidth } from '@chenglou/pretext';
6
+ // pretext needs Intl.Segmenter (Firefox < 125 has none): there the attachments
7
+ // leave the server's text as it is.
8
+ const canMeasure = typeof Intl !== 'undefined' && 'Segmenter' in Intl;
6
9
  export function lineCount(text, font, width, options) {
7
10
  return layout(prepare(text, font, options), width, 1).lineCount;
8
11
  }
@@ -71,6 +74,8 @@ export function fontOf(el) {
71
74
  */
72
75
  export function fitLabel(candidates, lines = 1) {
73
76
  return (el) => {
77
+ if (!canMeasure)
78
+ return;
74
79
  const font = fontOf(el);
75
80
  let width = 0;
76
81
  const apply = () => { el.textContent = pickFit(candidates, font, width, lines); };
@@ -179,7 +184,7 @@ export function breakLines(text, font, width) {
179
184
  */
180
185
  export function typeset(text) {
181
186
  return (el) => {
182
- if (getComputedStyle(el).whiteSpace !== 'normal')
187
+ if (!canMeasure || getComputedStyle(el).whiteSpace !== 'normal')
183
188
  return;
184
189
  const font = fontOf(el);
185
190
  let width = 0;
@@ -485,13 +485,13 @@ export function probeHostTheme(el, options = {}) {
485
485
  ? mix(calBg, [255, 255, 255], 0.04) // surface: lift from card
486
486
  : mix(calBg, [0, 0, 0], 0.02); // slightly darker stripe
487
487
  // ── Border colors ──
488
- const borderAlpha = isDark ? 0.07 : 0.08;
489
- const borderDayAlpha = isDark ? 0.14 : 0.14;
488
+ // Rules are drawn, not hinted: the grid reads as the calendar's structure.
489
+ const borderAlpha = isDark ? 0.16 : 0.3;
490
+ const borderDayAlpha = isDark ? 0.32 : 0.6;
490
491
  const borderRgb = isDark ? [148, 163, 184] : [0, 0, 0];
491
492
  // ── Accent derivatives ──
492
493
  const accentDim = isDark ? 0.15 : 0.12;
493
494
  const glow = isDark ? 0.30 : 0.25;
494
- const todayBg = isDark ? 0.07 : 0.07;
495
495
  // Ensure accent is readable on the background — adjust lightness if needed
496
496
  const accentL = isDark
497
497
  ? Math.max(aL, 0.45) // bright enough on dark
@@ -511,18 +511,21 @@ export function probeHostTheme(el, options = {}) {
511
511
  `--dt-surface: ${rgbStr(...surface)}`,
512
512
  `--dt-border: ${rgba(...borderRgb, borderAlpha)}`,
513
513
  `--dt-border-day: ${rgba(...borderRgb, borderDayAlpha)}`,
514
- `--dt-text: ${rgba(...textBase, isDark ? 0.87 : 0.87)}`,
515
- `--dt-text-2: ${rgba(...textBase, isDark ? 0.55 : 0.54)}`,
516
- `--dt-text-3: ${rgba(...textBase, isDark ? 0.38 : 0.38)}`,
514
+ `--dt-text: ${rgba(...textBase, isDark ? 0.92 : 1)}`,
515
+ `--dt-text-2: ${rgba(...textBase, isDark ? 0.62 : 0.66)}`,
516
+ `--dt-text-3: ${rgba(...textBase, isDark ? 0.46 : 0.54)}`,
517
517
  `--dt-accent: ${rgbStr(...accentAdj)}`,
518
518
  `--dt-accent-dim: ${rgba(...accentAdj, accentDim)}`,
519
519
  `--dt-glow: ${rgba(...accentAdj, glow)}`,
520
- `--dt-today-bg: ${rgba(...accentAdj, todayBg)}`,
520
+ // Today is marked by its number and the now line, never a column wash.
521
+ `--dt-today-bg: transparent`,
521
522
  `--dt-btn-text: ${btnText}`,
522
523
  `--dt-scrollbar: ${rgba(...borderRgb, scrollAlpha)}`,
523
524
  `--dt-success: ${rgba(...successRgb, 0.7)}`,
524
525
  `--dt-weekend-bg: ${rgba(...borderRgb, isDark ? 0.03 : 0.02)}`,
525
526
  `--dt-hover: ${rgba(...borderRgb, isDark ? 0.06 : 0.04)}`,
527
+ // Events are ink: the same colour as the text, so the accent keeps its three jobs.
528
+ `--dt-event: ${rgba(...textBase, isDark ? 0.92 : 1)}`,
526
529
  `--dt-sans: ${fonts.sans}`,
527
530
  `--dt-mono: ${fonts.mono}`,
528
531
  ];
@@ -23,17 +23,23 @@
23
23
  */
24
24
  export declare const auto = "";
25
25
  /**
26
- * Neutral — explicit light theme. White bg, blue accent, system font stack
27
- * (set --dt-sans on an ancestor or via CSS to use a custom font).
28
- * Use when embedding standalone without ancestor --dt-* vars.
26
+ * Neutral — explicit light theme: warm paper ground, ink text, hairline
27
+ * rules, one accent (the host's `--asini-accent`, else blue) for the all-day
28
+ * band, the now line and today. Events are marked in ink (`--dt-event`), so
29
+ * the accent keeps those three jobs. System font stack: set --dt-sans on an
30
+ * ancestor or via CSS to use a custom font. Use when embedding standalone
31
+ * without ancestor --dt-* vars.
32
+ *
33
+ * `--dt-paper` is an optional background-image layer (a paper texture) that
34
+ * every opaque calendar surface paints over `--dt-bg`; default none.
29
35
  */
30
- export declare const neutral = "\n\t--dt-stage-bg: #ffffff;\n\t--dt-bg: #ffffff;\n\t--dt-surface: #f9fafb;\n\t--dt-border: rgba(0, 0, 0, 0.08);\n\t--dt-border-day: rgba(0, 0, 0, 0.14);\n\t--dt-text: rgba(0, 0, 0, 0.87);\n\t--dt-text-2: rgba(0, 0, 0, 0.54);\n\t--dt-text-3: rgba(0, 0, 0, 0.38);\n\t--dt-accent: var(--asini-accent, #2563eb);\n\t--dt-accent-dim: color-mix(in srgb, var(--dt-accent) 12%, transparent);\n\t--dt-glow: color-mix(in srgb, var(--dt-accent) 25%, transparent);\n\t--dt-today-bg: color-mix(in srgb, var(--dt-accent) 7%, transparent);\n\t--dt-btn-text: #fff;\n\t--dt-scrollbar: rgba(0, 0, 0, 0.1);\n\t--dt-success: rgba(22, 163, 74, 0.7);\n\t--dt-weekend-bg: rgba(0, 0, 0, 0.02);\n\t--dt-hover: rgba(0, 0, 0, 0.04);\n\t--dt-mono: ui-monospace, 'SFMono-Regular', monospace;\n";
36
+ export declare const neutral = "\n\t--dt-stage-bg: #efebe9;\n\t--dt-bg: #efebe9;\n\t--dt-surface: #f4f1ee;\n\t--dt-border: rgba(15, 15, 15, 0.3);\n\t--dt-border-day: rgba(15, 15, 15, 0.6);\n\t--dt-text: #0f0f0f;\n\t--dt-text-2: rgba(15, 15, 15, 0.66);\n\t--dt-text-3: rgba(15, 15, 15, 0.54);\n\t--dt-accent: var(--asini-accent, #1d4fd7);\n\t--dt-accent-dim: color-mix(in srgb, var(--dt-accent) 12%, transparent);\n\t--dt-glow: color-mix(in srgb, var(--dt-accent) 25%, transparent);\n\t--dt-today-bg: transparent;\n\t--dt-btn-text: #fff;\n\t--dt-scrollbar: rgba(15, 15, 15, 0.18);\n\t--dt-weekend-bg: rgba(15, 15, 15, 0.035);\n\t--dt-hover: rgba(15, 15, 15, 0.05);\n\t--dt-event: var(--dt-text);\n\t--dt-paper: none;\n\t--dt-mono: ui-monospace, 'SFMono-Regular', monospace;\n";
31
37
  /** Midnight Industrial — dark charcoal + red accent, tech monitoring */
32
- export declare const midnight = "\n\t--dt-stage-bg: #080a0f;\n\t--dt-bg: #0b0e14;\n\t--dt-surface: #10141c;\n\t--dt-border: rgba(148, 163, 184, 0.07);\n\t--dt-border-day: rgba(148, 163, 184, 0.14);\n\t--dt-text: rgba(226, 232, 240, 0.85);\n\t--dt-text-2: rgba(148, 163, 184, 0.55);\n\t--dt-text-3: rgba(100, 116, 139, 0.55);\n\t--dt-accent: #ef4444;\n\t--dt-accent-dim: rgba(239, 68, 68, 0.18);\n\t--dt-glow: rgba(239, 68, 68, 0.35);\n\t--dt-today-bg: rgba(239, 68, 68, 0.07);\n\t--dt-btn-text: #fff;\n\t--dt-scrollbar: rgba(148, 163, 184, 0.12);\n\t--dt-success: rgba(74, 222, 128, 0.7);\n\t--dt-weekend-bg: rgba(148, 163, 184, 0.03);\n\t--dt-hover: rgba(148, 163, 184, 0.06);\n\t--dt-mono: ui-monospace, 'SFMono-Regular', monospace;\n";
38
+ export declare const midnight = "\n\t--dt-stage-bg: #080a0f;\n\t--dt-bg: #0b0e14;\n\t--dt-surface: #10141c;\n\t--dt-border: rgba(148, 163, 184, 0.07);\n\t--dt-border-day: rgba(148, 163, 184, 0.14);\n\t--dt-text: rgba(226, 232, 240, 0.85);\n\t--dt-text-2: rgba(148, 163, 184, 0.55);\n\t--dt-text-3: rgba(100, 116, 139, 0.55);\n\t--dt-accent: #ef4444;\n\t--dt-accent-dim: rgba(239, 68, 68, 0.18);\n\t--dt-glow: rgba(239, 68, 68, 0.35);\n\t--dt-today-bg: transparent;\n\t--dt-btn-text: #fff;\n\t--dt-scrollbar: rgba(148, 163, 184, 0.12);\n\t--dt-success: rgba(74, 222, 128, 0.7);\n\t--dt-weekend-bg: rgba(148, 163, 184, 0.03);\n\t--dt-hover: rgba(148, 163, 184, 0.06);\n\t--dt-event: var(--dt-text);\n\t--dt-paper: none;\n\t--dt-mono: ui-monospace, 'SFMono-Regular', monospace;\n";
33
39
  /** All available presets keyed by name */
34
40
  export declare const presets: {
35
41
  readonly auto: "";
36
- readonly neutral: "\n\t--dt-stage-bg: #ffffff;\n\t--dt-bg: #ffffff;\n\t--dt-surface: #f9fafb;\n\t--dt-border: rgba(0, 0, 0, 0.08);\n\t--dt-border-day: rgba(0, 0, 0, 0.14);\n\t--dt-text: rgba(0, 0, 0, 0.87);\n\t--dt-text-2: rgba(0, 0, 0, 0.54);\n\t--dt-text-3: rgba(0, 0, 0, 0.38);\n\t--dt-accent: var(--asini-accent, #2563eb);\n\t--dt-accent-dim: color-mix(in srgb, var(--dt-accent) 12%, transparent);\n\t--dt-glow: color-mix(in srgb, var(--dt-accent) 25%, transparent);\n\t--dt-today-bg: color-mix(in srgb, var(--dt-accent) 7%, transparent);\n\t--dt-btn-text: #fff;\n\t--dt-scrollbar: rgba(0, 0, 0, 0.1);\n\t--dt-success: rgba(22, 163, 74, 0.7);\n\t--dt-weekend-bg: rgba(0, 0, 0, 0.02);\n\t--dt-hover: rgba(0, 0, 0, 0.04);\n\t--dt-mono: ui-monospace, 'SFMono-Regular', monospace;\n";
37
- readonly midnight: "\n\t--dt-stage-bg: #080a0f;\n\t--dt-bg: #0b0e14;\n\t--dt-surface: #10141c;\n\t--dt-border: rgba(148, 163, 184, 0.07);\n\t--dt-border-day: rgba(148, 163, 184, 0.14);\n\t--dt-text: rgba(226, 232, 240, 0.85);\n\t--dt-text-2: rgba(148, 163, 184, 0.55);\n\t--dt-text-3: rgba(100, 116, 139, 0.55);\n\t--dt-accent: #ef4444;\n\t--dt-accent-dim: rgba(239, 68, 68, 0.18);\n\t--dt-glow: rgba(239, 68, 68, 0.35);\n\t--dt-today-bg: rgba(239, 68, 68, 0.07);\n\t--dt-btn-text: #fff;\n\t--dt-scrollbar: rgba(148, 163, 184, 0.12);\n\t--dt-success: rgba(74, 222, 128, 0.7);\n\t--dt-weekend-bg: rgba(148, 163, 184, 0.03);\n\t--dt-hover: rgba(148, 163, 184, 0.06);\n\t--dt-mono: ui-monospace, 'SFMono-Regular', monospace;\n";
42
+ readonly neutral: "\n\t--dt-stage-bg: #efebe9;\n\t--dt-bg: #efebe9;\n\t--dt-surface: #f4f1ee;\n\t--dt-border: rgba(15, 15, 15, 0.3);\n\t--dt-border-day: rgba(15, 15, 15, 0.6);\n\t--dt-text: #0f0f0f;\n\t--dt-text-2: rgba(15, 15, 15, 0.66);\n\t--dt-text-3: rgba(15, 15, 15, 0.54);\n\t--dt-accent: var(--asini-accent, #1d4fd7);\n\t--dt-accent-dim: color-mix(in srgb, var(--dt-accent) 12%, transparent);\n\t--dt-glow: color-mix(in srgb, var(--dt-accent) 25%, transparent);\n\t--dt-today-bg: transparent;\n\t--dt-btn-text: #fff;\n\t--dt-scrollbar: rgba(15, 15, 15, 0.18);\n\t--dt-weekend-bg: rgba(15, 15, 15, 0.035);\n\t--dt-hover: rgba(15, 15, 15, 0.05);\n\t--dt-event: var(--dt-text);\n\t--dt-paper: none;\n\t--dt-mono: ui-monospace, 'SFMono-Regular', monospace;\n";
43
+ readonly midnight: "\n\t--dt-stage-bg: #080a0f;\n\t--dt-bg: #0b0e14;\n\t--dt-surface: #10141c;\n\t--dt-border: rgba(148, 163, 184, 0.07);\n\t--dt-border-day: rgba(148, 163, 184, 0.14);\n\t--dt-text: rgba(226, 232, 240, 0.85);\n\t--dt-text-2: rgba(148, 163, 184, 0.55);\n\t--dt-text-3: rgba(100, 116, 139, 0.55);\n\t--dt-accent: #ef4444;\n\t--dt-accent-dim: rgba(239, 68, 68, 0.18);\n\t--dt-glow: rgba(239, 68, 68, 0.35);\n\t--dt-today-bg: transparent;\n\t--dt-btn-text: #fff;\n\t--dt-scrollbar: rgba(148, 163, 184, 0.12);\n\t--dt-success: rgba(74, 222, 128, 0.7);\n\t--dt-weekend-bg: rgba(148, 163, 184, 0.03);\n\t--dt-hover: rgba(148, 163, 184, 0.06);\n\t--dt-event: var(--dt-text);\n\t--dt-paper: none;\n\t--dt-mono: ui-monospace, 'SFMono-Regular', monospace;\n";
38
44
  };
39
45
  export type PresetName = keyof typeof presets;
@@ -23,28 +23,35 @@
23
23
  */
24
24
  export const auto = ``;
25
25
  /**
26
- * Neutral — explicit light theme. White bg, blue accent, system font stack
27
- * (set --dt-sans on an ancestor or via CSS to use a custom font).
28
- * Use when embedding standalone without ancestor --dt-* vars.
26
+ * Neutral — explicit light theme: warm paper ground, ink text, hairline
27
+ * rules, one accent (the host's `--asini-accent`, else blue) for the all-day
28
+ * band, the now line and today. Events are marked in ink (`--dt-event`), so
29
+ * the accent keeps those three jobs. System font stack: set --dt-sans on an
30
+ * ancestor or via CSS to use a custom font. Use when embedding standalone
31
+ * without ancestor --dt-* vars.
32
+ *
33
+ * `--dt-paper` is an optional background-image layer (a paper texture) that
34
+ * every opaque calendar surface paints over `--dt-bg`; default none.
29
35
  */
30
36
  export const neutral = `
31
- --dt-stage-bg: #ffffff;
32
- --dt-bg: #ffffff;
33
- --dt-surface: #f9fafb;
34
- --dt-border: rgba(0, 0, 0, 0.08);
35
- --dt-border-day: rgba(0, 0, 0, 0.14);
36
- --dt-text: rgba(0, 0, 0, 0.87);
37
- --dt-text-2: rgba(0, 0, 0, 0.54);
38
- --dt-text-3: rgba(0, 0, 0, 0.38);
39
- --dt-accent: var(--asini-accent, #2563eb);
37
+ --dt-stage-bg: #efebe9;
38
+ --dt-bg: #efebe9;
39
+ --dt-surface: #f4f1ee;
40
+ --dt-border: rgba(15, 15, 15, 0.3);
41
+ --dt-border-day: rgba(15, 15, 15, 0.6);
42
+ --dt-text: #0f0f0f;
43
+ --dt-text-2: rgba(15, 15, 15, 0.66);
44
+ --dt-text-3: rgba(15, 15, 15, 0.54);
45
+ --dt-accent: var(--asini-accent, #1d4fd7);
40
46
  --dt-accent-dim: color-mix(in srgb, var(--dt-accent) 12%, transparent);
41
47
  --dt-glow: color-mix(in srgb, var(--dt-accent) 25%, transparent);
42
- --dt-today-bg: color-mix(in srgb, var(--dt-accent) 7%, transparent);
48
+ --dt-today-bg: transparent;
43
49
  --dt-btn-text: #fff;
44
- --dt-scrollbar: rgba(0, 0, 0, 0.1);
45
- --dt-success: rgba(22, 163, 74, 0.7);
46
- --dt-weekend-bg: rgba(0, 0, 0, 0.02);
47
- --dt-hover: rgba(0, 0, 0, 0.04);
50
+ --dt-scrollbar: rgba(15, 15, 15, 0.18);
51
+ --dt-weekend-bg: rgba(15, 15, 15, 0.035);
52
+ --dt-hover: rgba(15, 15, 15, 0.05);
53
+ --dt-event: var(--dt-text);
54
+ --dt-paper: none;
48
55
  --dt-mono: ui-monospace, 'SFMono-Regular', monospace;
49
56
  `;
50
57
  /** Midnight Industrial — dark charcoal + red accent, tech monitoring */
@@ -60,12 +67,14 @@ export const midnight = `
60
67
  --dt-accent: #ef4444;
61
68
  --dt-accent-dim: rgba(239, 68, 68, 0.18);
62
69
  --dt-glow: rgba(239, 68, 68, 0.35);
63
- --dt-today-bg: rgba(239, 68, 68, 0.07);
70
+ --dt-today-bg: transparent;
64
71
  --dt-btn-text: #fff;
65
72
  --dt-scrollbar: rgba(148, 163, 184, 0.12);
66
73
  --dt-success: rgba(74, 222, 128, 0.7);
67
74
  --dt-weekend-bg: rgba(148, 163, 184, 0.03);
68
75
  --dt-hover: rgba(148, 163, 184, 0.06);
76
+ --dt-event: var(--dt-text);
77
+ --dt-paper: none;
69
78
  --dt-mono: ui-monospace, 'SFMono-Regular', monospace;
70
79
  `;
71
80
  /** All available presets keyed by name */