@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.
@@ -21,7 +21,7 @@ import { createClock } from "../../core/clock.svelte.js";
21
21
  import { fitParts } from "../../text-fit.js";
22
22
  import { HOUR_MS, sod, addDaysMs, diffDays } from "../../core/time.js";
23
23
  import { startOfWeek as sowFn, isAllDay, segmentForDay } from "../../core/time.js";
24
- import { fmtH, fmtTime, fmtDuration, weekdayShort, weekdayLong } from "../../core/locale.js";
24
+ import { fmtHParts, fmtTime, fmtDuration, weekdayShort, weekdayLong } from "../../core/locale.js";
25
25
  let { mode = "week", mondayStart = true, locale, height = 520, events = [], style = "", focusDate, oneventclick, oneventcreate, onexternaldrop, selectedEventId = null, readOnly = false, visibleHours } = $props();
26
26
  // ── Context ────────────────────────────────────────
27
27
  const ctx = useCalendarContext();
@@ -78,8 +78,8 @@ function inAllDayStrip(ev) {
78
78
  return isAllDay(ev) || ev.end.getTime() >= addDaysMs(ev.start.getTime(), 1);
79
79
  }
80
80
  // ── Config ─────────────────────────────────────────
81
- const HOUR_H = 48;
82
- const GUTTER_W = 48;
81
+ const HOUR_H = 64;
82
+ const GUTTER_W = 60;
83
83
  const MIN_COL_W = $derived(ctx.minColumnWidth);
84
84
  const ALLDAY_MAX = 3;
85
85
  const startHour = $derived(visibleHours?.[0] ?? 0);
@@ -802,14 +802,14 @@ function onWindowKeydown(e) {
802
802
  onpointerenter={() => oneventhover?.(seg.ev)}
803
803
  >
804
804
  {#if !seg.isStart}
805
- <span class="tw-ad-cont" aria-hidden="true">◂</span>
805
+ <span class="tw-ad-cont" aria-hidden="true"><svg viewBox="0 0 8 8" width="8" height="8"><path d="M5.5 1.5 2.5 4l3 2.5" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" /></svg></span>
806
806
  {/if}
807
807
  <span class="tw-ad-title">{seg.ev.title}</span>
808
808
  {#if seg.totalDays > 1}
809
809
  <span class="tw-ad-span" aria-hidden="true">{seg.dayIndex}/{seg.totalDays}</span>
810
810
  {/if}
811
811
  {#if !seg.isEnd && seg.totalDays > 1}
812
- <span class="tw-ad-arrow" aria-hidden="true">▸</span>
812
+ <span class="tw-ad-arrow" aria-hidden="true"><svg viewBox="0 0 8 8" width="8" height="8"><path d="M2.5 1.5 5.5 4l-3 2.5" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" /></svg></span>
813
813
  {/if}
814
814
  </button>
815
815
  {/snippet}
@@ -887,7 +887,12 @@ function onWindowKeydown(e) {
887
887
  <div class="tw-gutter" style:width="{GUTTER_W}px" aria-hidden="true">
888
888
  {#each { length: hourCount } as _, i}
889
889
  {#if i > 0}
890
- <span class="tw-gutter-lb" style:top="{i * HOUR_H}px">{fmtH(startHour + i, locale)}</span>
890
+ {@const [hNum, hSuf] = fmtHParts(startHour + i, locale)}
891
+ <!-- an hour the now plate would half-cover gives way to it -->
892
+ <span
893
+ class="tw-gutter-lb"
894
+ class:tw-gutter-lb--under={nowY !== null && weekHasToday && Math.abs(i * HOUR_H - nowY) < 18}
895
+ style:top="{i * HOUR_H}px">{hNum}<small>{hSuf}</small></span>
891
896
  {/if}
892
897
  {/each}
893
898
  {#if axisGhost}
@@ -918,6 +923,10 @@ function onWindowKeydown(e) {
918
923
  <div class="tw-line" style:top="{i * HOUR_H}px"></div>
919
924
  <div class="tw-line tw-line--half" style:top="{i * HOUR_H + HOUR_H / 2}px"></div>
920
925
  {/each}
926
+ {#if nowY !== null && weekHasToday}
927
+ <!-- now, ruled across the whole week; today's column draws it solid -->
928
+ <div class="tw-now-week" style:top="{nowY}px"></div>
929
+ {/if}
921
930
  </div>
922
931
 
923
932
  {#each dayCols as day (day.ms)}
@@ -976,7 +985,7 @@ function onWindowKeydown(e) {
976
985
  style:height="{p.height}px"
977
986
  style:left="calc({(p.col / p.totalCols) * 100}% + 1px)"
978
987
  style:width="calc({100 / p.totalCols}% - {p.totalCols > 1 ? 3 : 8}px)"
979
- style:--ev-color={p.ev.color ?? 'var(--dt-accent)'}
988
+ style:--ev-color={p.ev.color ?? 'var(--dt-event, var(--dt-accent))'}
980
989
  role="button"
981
990
  tabindex="0"
982
991
  title={p.ev.title}
@@ -990,7 +999,7 @@ function onWindowKeydown(e) {
990
999
  <div class="tw-ev-body">
991
1000
  <EventContent event={p.ev}>
992
1001
  {@const parts = blockParts(p.ev, p.height)}
993
- <span class="tw-ev-time">{fmtTime(p.ev.start, locale)} – {fmtTime(p.ev.end, locale)}</span>
1002
+ <span class="tw-ev-time">{fmtTime(p.ev.start, locale)}<span class="tw-ev-end">{` – ${fmtTime(p.ev.end, locale)}`}</span></span>
994
1003
  <span class="tw-ev-title">{p.ev.title}</span>
995
1004
  {#if parts.room}
996
1005
  <span class="tw-ev-loc">{p.ev.location}</span>
@@ -1072,7 +1081,7 @@ function onWindowKeydown(e) {
1072
1081
  overflow: hidden;
1073
1082
  user-select: none;
1074
1083
  font-variant-numeric: tabular-nums;
1075
- background: var(--dt-bg, #ffffff);
1084
+ background: var(--dt-paper, none), var(--dt-bg, #ffffff);
1076
1085
  -webkit-tap-highlight-color: transparent;
1077
1086
  }
1078
1087
  .tw--auto { overflow: visible; }
@@ -1110,7 +1119,7 @@ function onWindowKeydown(e) {
1110
1119
  position: sticky;
1111
1120
  top: 0;
1112
1121
  z-index: 30;
1113
- background: var(--dt-bg, #ffffff);
1122
+ background: var(--dt-paper, none), var(--dt-bg, #ffffff);
1114
1123
  border-bottom: 1px solid var(--dt-border, rgba(0, 0, 0, 0.08));
1115
1124
  }
1116
1125
 
@@ -1124,7 +1133,7 @@ function onWindowKeydown(e) {
1124
1133
  position: sticky;
1125
1134
  left: 0;
1126
1135
  z-index: 2;
1127
- background: var(--dt-bg, #ffffff);
1136
+ background: var(--dt-paper, none), var(--dt-bg, #ffffff);
1128
1137
  }
1129
1138
 
1130
1139
  .tw-hd {
@@ -1133,36 +1142,34 @@ function onWindowKeydown(e) {
1133
1142
  display: flex;
1134
1143
  flex-direction: column;
1135
1144
  align-items: center;
1136
- gap: 2px;
1137
- padding: 8px 4px 6px;
1145
+ gap: 4px;
1146
+ padding: 14px 4px 12px;
1138
1147
  border-left: 1px solid var(--dt-border, rgba(0, 0, 0, 0.08));
1139
1148
  }
1140
1149
 
1141
1150
  .tw-hd-wd {
1142
- font: 500 10px/1 var(--dt-sans, system-ui, sans-serif);
1143
- letter-spacing: 0.06em;
1151
+ font: 500 12px/1 var(--dt-sans, system-ui, sans-serif);
1152
+ letter-spacing: 0.08em;
1144
1153
  text-transform: uppercase;
1145
- color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
1154
+ color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
1146
1155
  }
1147
1156
  .tw-hd--today .tw-hd-wd {
1148
1157
  color: var(--dt-accent, #2563eb);
1149
- font-weight: 600;
1150
1158
  }
1151
1159
 
1160
+ /* The day number is the typography of the grid: large, regular weight. */
1152
1161
  .tw-hd-num {
1153
1162
  display: inline-flex;
1154
1163
  align-items: center;
1155
1164
  justify-content: center;
1156
- min-width: 26px;
1157
- height: 26px;
1158
- border-radius: 50%;
1159
- font: 600 14px/1 var(--dt-sans, system-ui, sans-serif);
1165
+ font: 400 40px/1 var(--dt-sans, system-ui, sans-serif);
1166
+ font-stretch: 90%;
1167
+ letter-spacing: -0.02em;
1160
1168
  color: var(--dt-text, rgba(0, 0, 0, 0.87));
1161
1169
  }
1170
+ /* Today: the numeral in the accent, nothing else. */
1162
1171
  .tw-hd-num--today {
1163
- background: var(--dt-accent, #2563eb);
1164
- color: var(--dt-accent-fg, var(--dt-btn-text, #ffffff));
1165
- font-weight: 700;
1172
+ color: var(--dt-accent, #2563eb);
1166
1173
  }
1167
1174
 
1168
1175
  .tw-hd-custom {
@@ -1181,11 +1188,11 @@ function onWindowKeydown(e) {
1181
1188
  position: sticky;
1182
1189
  left: 0;
1183
1190
  z-index: 2;
1184
- background: var(--dt-bg, #ffffff);
1191
+ background: var(--dt-paper, none), var(--dt-bg, #ffffff);
1185
1192
  display: flex;
1186
1193
  align-items: flex-start;
1187
1194
  justify-content: flex-end;
1188
- padding: 4px 6px 4px 0;
1195
+ padding: 6px 8px 6px 0;
1189
1196
  }
1190
1197
  .tw-ad-gutter-lb {
1191
1198
  font: 500 10px/1.2 var(--dt-sans, system-ui, sans-serif);
@@ -1199,7 +1206,7 @@ function onWindowKeydown(e) {
1199
1206
  display: flex;
1200
1207
  flex-direction: column;
1201
1208
  gap: 2px;
1202
- padding: 3px 3px 4px;
1209
+ padding: 4px 0 5px;
1203
1210
  border-left: 1px solid var(--dt-border, rgba(0, 0, 0, 0.08));
1204
1211
  }
1205
1212
  .tw-ad-cell--today { background: var(--dt-today-bg, rgba(37, 99, 235, 0.04)); }
@@ -1208,42 +1215,46 @@ function onWindowKeydown(e) {
1208
1215
  appearance: none;
1209
1216
  display: flex;
1210
1217
  align-items: center;
1211
- gap: 3px;
1212
- padding: 2px 6px;
1213
- min-height: 18px;
1218
+ gap: 4px;
1219
+ padding: 0 10px;
1220
+ min-height: 36px;
1214
1221
  border: none;
1215
- border-radius: 3px;
1216
- background: color-mix(in srgb, var(--ev-color) 22%, var(--dt-surface, var(--dt-bg, #ffffff)));
1217
- border-left: 2.5px solid var(--ev-color);
1222
+ border-radius: 0;
1223
+ /* The paper's grain runs through the band (multiply keeps the colour). */
1224
+ background: var(--dt-paper, none) var(--ev-color);
1225
+ background-blend-mode: multiply;
1226
+ color: var(--dt-btn-text, #fff);
1218
1227
  cursor: pointer;
1219
1228
  overflow: hidden;
1220
1229
  text-align: left;
1221
- transition: background 0.12s;
1230
+ transition: filter 0.12s;
1222
1231
  -webkit-tap-highlight-color: transparent;
1223
1232
  }
1224
1233
  .tw-ad:hover {
1225
- background: color-mix(in srgb, var(--ev-color) 32%, var(--dt-surface, var(--dt-bg, #ffffff)));
1234
+ filter: brightness(1.08);
1226
1235
  }
1236
+ /* A span continues across its days as one band: no edge between segments. */
1227
1237
  .tw-ad--mid,
1228
1238
  .tw-ad--end:not(.tw-ad--start) {
1229
- border-left: 1px dashed color-mix(in srgb, var(--ev-color) 40%, transparent);
1230
- border-radius: 0 3px 3px 0;
1239
+ margin-left: -1px;
1231
1240
  }
1232
1241
  .tw-ad--selected {
1233
- box-shadow: 0 0 0 1.5px var(--ev-color);
1242
+ box-shadow: inset 0 0 0 2px var(--dt-btn-text, #fff);
1234
1243
  }
1235
1244
  .tw-ad--cancelled .tw-ad-title {
1236
1245
  text-decoration: line-through;
1237
- color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
1246
+ }
1247
+ .tw-ad--cancelled {
1248
+ background: color-mix(in srgb, var(--ev-color) 55%, var(--dt-bg, #fff));
1238
1249
  }
1239
1250
  .tw-ad:focus-visible {
1240
1251
  outline: none;
1241
- box-shadow: 0 0 0 2px var(--dt-accent, #2563eb);
1252
+ box-shadow: inset 0 0 0 2px var(--dt-btn-text, #fff), 0 0 0 2px var(--dt-accent, #2563eb);
1242
1253
  }
1243
1254
 
1244
1255
  .tw-ad-title {
1245
- font: 500 11px/1.2 var(--dt-sans, system-ui, sans-serif);
1246
- color: var(--dt-text, rgba(0, 0, 0, 0.87));
1256
+ font: 500 13.5px/1.2 var(--dt-sans, system-ui, sans-serif);
1257
+ color: inherit;
1247
1258
  white-space: nowrap;
1248
1259
  overflow: hidden;
1249
1260
  text-overflow: ellipsis;
@@ -1251,16 +1262,29 @@ function onWindowKeydown(e) {
1251
1262
  min-width: 0;
1252
1263
  }
1253
1264
  .tw-ad-span {
1254
- font: 400 10px/1 var(--dt-sans, system-ui, sans-serif);
1255
- color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
1265
+ font: 400 11px/1 var(--dt-sans, system-ui, sans-serif);
1266
+ font-variant-numeric: tabular-nums;
1267
+ color: inherit;
1268
+ opacity: 0.75;
1256
1269
  flex-shrink: 0;
1257
1270
  }
1271
+ .tw-ad--mid .tw-ad-title,
1272
+ .tw-ad--end:not(.tw-ad--start) .tw-ad-title {
1273
+ visibility: hidden;
1274
+ }
1275
+ .tw-ad-gutter + .tw-ad-cell .tw-ad-title {
1276
+ visibility: visible;
1277
+ }
1278
+ .tw-ad-span,
1258
1279
  .tw-ad-cont,
1259
1280
  .tw-ad-arrow {
1260
- font-size: 10px;
1261
- color: var(--ev-color);
1281
+ display: none;
1282
+ }
1283
+ .tw-ad-arrow {
1284
+ display: none;
1285
+ color: inherit;
1286
+ opacity: 0.75;
1262
1287
  flex-shrink: 0;
1263
- line-height: 1;
1264
1288
  }
1265
1289
  .tw-ad-arrow { margin-left: auto; }
1266
1290
 
@@ -1295,18 +1319,46 @@ function onWindowKeydown(e) {
1295
1319
  position: sticky;
1296
1320
  left: 0;
1297
1321
  z-index: 20;
1298
- background: var(--dt-bg, #ffffff);
1322
+ background: var(--dt-paper, none), var(--dt-bg, #ffffff);
1299
1323
  border-right: 1px solid var(--dt-border, rgba(0, 0, 0, 0.08));
1300
1324
  }
1301
1325
 
1326
+ /* Timetable hour: the numeral carries the rank, the suffix sits raised
1327
+ and small beside it. */
1302
1328
  .tw-gutter-lb {
1303
1329
  position: absolute;
1304
- right: 6px;
1330
+ left: 6px;
1331
+ right: 0;
1305
1332
  transform: translateY(-50%);
1306
- font: 500 11px/1 var(--dt-mono, ui-monospace, monospace);
1307
- color: var(--dt-text-3, rgba(0, 0, 0, 0.38));
1333
+ display: flex;
1334
+ align-items: flex-start;
1335
+ gap: 2px;
1336
+ font: 400 26px/1 var(--dt-sans, system-ui, sans-serif);
1337
+ font-stretch: 85%;
1338
+ font-variant-numeric: tabular-nums;
1339
+ letter-spacing: -0.02em;
1340
+ color: var(--dt-text, rgba(0, 0, 0, 0.87));
1308
1341
  white-space: nowrap;
1309
1342
  }
1343
+ .tw-gutter-lb::after {
1344
+ content: '';
1345
+ flex: 1;
1346
+ min-width: 6px;
1347
+ height: 1px;
1348
+ margin-left: 5px;
1349
+ align-self: center;
1350
+ background: var(--dt-border-day, rgba(0, 0, 0, 0.3));
1351
+ }
1352
+ .tw-gutter-lb--under {
1353
+ visibility: hidden;
1354
+ }
1355
+ .tw-gutter-lb small {
1356
+ font-size: 10px;
1357
+ font-weight: 500;
1358
+ line-height: 1;
1359
+ letter-spacing: 0;
1360
+ color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
1361
+ }
1310
1362
 
1311
1363
  /* The clock beside the now line, and the drag's edges while it lasts —
1312
1364
  both sit on the surface so they cover the hour label beneath. */
@@ -1315,18 +1367,19 @@ function onWindowKeydown(e) {
1315
1367
  position: absolute;
1316
1368
  right: 3px;
1317
1369
  transform: translateY(-50%);
1318
- padding: 1px 3px;
1319
- border-radius: 3px;
1370
+ padding: 2px 4px;
1371
+ border-radius: 0;
1320
1372
  background: var(--dt-surface, var(--dt-bg, #fff));
1321
- font: 600 10px/1.2 var(--dt-mono, ui-monospace, monospace);
1373
+ font: 500 11px/1.2 var(--dt-sans, system-ui, sans-serif);
1374
+ font-variant-numeric: tabular-nums;
1322
1375
  color: var(--dt-accent, #2563eb);
1323
1376
  white-space: nowrap;
1324
1377
  z-index: 2;
1325
1378
  }
1379
+ /* The clock is a reversed plate on the accent, like a board's live time. */
1326
1380
  .tw-gutter-now {
1327
- opacity: 0.75;
1328
- transform: translateY(-50%);
1329
- z-index: 2;
1381
+ background: var(--dt-accent, #2563eb);
1382
+ color: var(--dt-btn-text, #ffffff);
1330
1383
  }
1331
1384
 
1332
1385
  /* ─── Columns wrapper ────────────────────────────── */
@@ -1353,6 +1406,15 @@ function onWindowKeydown(e) {
1353
1406
  background: var(--dt-border, rgba(0, 0, 0, 0.08));
1354
1407
  }
1355
1408
  .tw-line--half { opacity: 0.4; }
1409
+ .tw-now-week {
1410
+ position: absolute;
1411
+ left: 0;
1412
+ right: 0;
1413
+ height: 0;
1414
+ border-top: 2px solid var(--dt-accent, #2563eb);
1415
+ opacity: 0.85;
1416
+ transform: translateY(-1px);
1417
+ }
1356
1418
 
1357
1419
  /* ─── Day column ─────────────────────────────────── */
1358
1420
  .tw-col {
@@ -1372,7 +1434,7 @@ function onWindowKeydown(e) {
1372
1434
  }
1373
1435
  /* What has already happened steps back; a cancelled block keeps its own look. */
1374
1436
  .tw-ev--past:not(.tw-ev--cancelled) {
1375
- opacity: 0.6;
1437
+ opacity: 0.78;
1376
1438
  }
1377
1439
  .tw-col--weekend:not(.tw-col--today):not(.tw-col--past) {
1378
1440
  background: var(--dt-weekend-bg, rgba(0, 0, 0, 0.012));
@@ -1421,8 +1483,7 @@ function onWindowKeydown(e) {
1421
1483
  left: 0;
1422
1484
  right: 0;
1423
1485
  height: 0;
1424
- border-top: 1px dotted var(--dt-accent, #2563eb);
1425
- opacity: 0.7;
1486
+ border-top: 2px solid var(--dt-accent, #2563eb);
1426
1487
  z-index: 12;
1427
1488
  pointer-events: none;
1428
1489
  transform: translateY(-1px);
@@ -1430,7 +1491,7 @@ function onWindowKeydown(e) {
1430
1491
  .tw-now-dot {
1431
1492
  position: absolute;
1432
1493
  left: -4px;
1433
- top: -3px;
1494
+ top: -5px;
1434
1495
  width: 8px;
1435
1496
  height: 8px;
1436
1497
  border-radius: 50%;
@@ -1441,8 +1502,8 @@ function onWindowKeydown(e) {
1441
1502
  .tw-ev {
1442
1503
  position: absolute;
1443
1504
  z-index: 6;
1444
- border-radius: 5px;
1445
- background: color-mix(in srgb, var(--ev-color) 14%, var(--dt-surface, var(--dt-bg, #ffffff)));
1505
+ border-radius: 0;
1506
+ background: transparent;
1446
1507
  display: flex;
1447
1508
  align-items: stretch;
1448
1509
  overflow: hidden;
@@ -1455,7 +1516,7 @@ function onWindowKeydown(e) {
1455
1516
  -webkit-tap-highlight-color: transparent;
1456
1517
  }
1457
1518
  .tw-ev:hover {
1458
- background: color-mix(in srgb, var(--ev-color) 24%, var(--dt-surface, var(--dt-bg, #ffffff)));
1519
+ background: var(--dt-hover, rgba(0, 0, 0, 0.04));
1459
1520
  z-index: 8;
1460
1521
  }
1461
1522
  /* Short blocks keep duration-proportional height, but get a 44px
@@ -1471,12 +1532,11 @@ function onWindowKeydown(e) {
1471
1532
  height: 44px;
1472
1533
  }
1473
1534
  .tw-ev--selected {
1474
- box-shadow: 0 0 0 2px var(--ev-color),
1475
- 0 2px 12px color-mix(in srgb, var(--ev-color) 25%, transparent);
1535
+ box-shadow: inset 0 0 0 1px var(--ev-color);
1476
1536
  z-index: 9;
1477
1537
  }
1478
1538
  .tw-ev--current {
1479
- background: color-mix(in srgb, var(--ev-color) 22%, var(--dt-surface, var(--dt-bg, #ffffff)));
1539
+ background: var(--dt-accent-dim, rgba(37, 99, 235, 0.12));
1480
1540
  }
1481
1541
  .tw-ev--resizing {
1482
1542
  z-index: 50;
@@ -1491,40 +1551,39 @@ function onWindowKeydown(e) {
1491
1551
  }
1492
1552
  /* Status treatments: token-level dims + a non-opacity signal
1493
1553
  (strikethrough / border style) — consistent with the other views. */
1494
- .tw-ev--cancelled {
1495
- background: color-mix(in srgb, var(--ev-color) 5%, var(--dt-surface, var(--dt-bg, #ffffff)));
1496
- }
1554
+ /* Printed states: a cancelled class is struck through and stays on the
1555
+ grid; a tentative one is set in grey with a dashed bar. */
1497
1556
  .tw-ev--cancelled .tw-ev-title {
1498
1557
  text-decoration: line-through;
1499
1558
  color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
1500
1559
  }
1501
1560
  .tw-ev--cancelled .tw-ev-stripe { opacity: 0.45; /* decorative bar only */ }
1502
- .tw-ev--tentative {
1503
- background: color-mix(in srgb, var(--ev-color) 6%, var(--dt-surface, var(--dt-bg, #ffffff)));
1504
- border: 1px dashed color-mix(in srgb, var(--ev-color) 45%, transparent);
1505
- }
1506
- .tw-ev--full {
1507
- background: color-mix(in srgb, var(--ev-color) 6%, var(--dt-surface, var(--dt-bg, #ffffff)));
1508
- border: 1px solid color-mix(in srgb, var(--ev-color) 30%, transparent);
1561
+ .tw-ev--tentative .tw-ev-title,
1562
+ .tw-ev--full .tw-ev-title {
1563
+ color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
1509
1564
  }
1510
- .tw-ev--full .tw-ev-title { color: var(--dt-text-2, rgba(0, 0, 0, 0.54)); }
1511
- .tw-ev--limited {
1512
- background: color-mix(in srgb, var(--ev-color) 8%, var(--dt-surface, var(--dt-bg, #ffffff)));
1513
- border: 1px dashed color-mix(in srgb, var(--ev-color) 45%, transparent);
1565
+ .tw-ev--tentative .tw-ev-stripe,
1566
+ .tw-ev--limited .tw-ev-stripe {
1567
+ background: repeating-linear-gradient(
1568
+ 180deg,
1569
+ var(--ev-color) 0 4px,
1570
+ transparent 4px 7px
1571
+ );
1514
1572
  }
1573
+ .tw-ev--full .tw-ev-stripe { opacity: 0.45; }
1515
1574
  .tw-ev--readonly { cursor: default; }
1516
1575
 
1517
1576
  .tw-ev-stripe {
1518
1577
  width: 3px;
1519
1578
  background: var(--ev-color);
1520
1579
  flex-shrink: 0;
1521
- border-radius: 5px 0 0 5px;
1522
1580
  }
1523
1581
 
1524
1582
  .tw-ev-body {
1583
+ container: tw-ev / inline-size;
1525
1584
  flex: 1;
1526
1585
  min-width: 0;
1527
- padding: 3px 6px;
1586
+ padding: 3px 7px;
1528
1587
  display: flex;
1529
1588
  flex-direction: column;
1530
1589
  gap: 1px;
@@ -1539,16 +1598,24 @@ function onWindowKeydown(e) {
1539
1598
  padding-bottom: 1px;
1540
1599
  }
1541
1600
 
1601
+ /* Title first, time under it; both one size, rank by weight and ink. */
1542
1602
  .tw-ev-time {
1543
- font: 400 11px/1.1 var(--dt-mono, ui-monospace, monospace);
1544
- color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
1603
+ order: 1;
1604
+ font: 400 14px/1.2 var(--dt-sans, system-ui, sans-serif);
1605
+ font-variant-numeric: tabular-nums;
1606
+ color: var(--dt-text, rgba(0, 0, 0, 0.87));
1545
1607
  white-space: nowrap;
1546
1608
  flex-shrink: 0;
1547
1609
  }
1548
1610
  .tw-ev--compact .tw-ev-time { order: 0; }
1611
+ /* A narrow overlap column keeps the start time whole and drops the end. */
1612
+ @container tw-ev (max-width: 104px) {
1613
+ .tw-ev-end { display: none; }
1614
+ }
1549
1615
 
1550
1616
  .tw-ev-title {
1551
- font: 600 12px/1.2 var(--dt-sans, system-ui, sans-serif);
1617
+ order: 0;
1618
+ font: 500 15px/1.25 var(--dt-sans, system-ui, sans-serif);
1552
1619
  color: var(--dt-text, rgba(0, 0, 0, 0.87));
1553
1620
  white-space: nowrap;
1554
1621
  overflow: hidden;
@@ -1556,8 +1623,9 @@ function onWindowKeydown(e) {
1556
1623
  }
1557
1624
 
1558
1625
  .tw-ev-loc {
1559
- font: 400 10px/1.2 var(--dt-sans, system-ui, sans-serif);
1560
- color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
1626
+ order: 2;
1627
+ font: 400 12.5px/1.2 var(--dt-sans, system-ui, sans-serif);
1628
+ color: var(--dt-text, rgba(0, 0, 0, 0.87));
1561
1629
  white-space: nowrap;
1562
1630
  overflow: hidden;
1563
1631
  text-overflow: ellipsis;
@@ -1641,8 +1709,8 @@ function onWindowKeydown(e) {
1641
1709
  left: 1px;
1642
1710
  right: 3px;
1643
1711
  z-index: 40;
1644
- border-radius: 5px;
1645
- background: color-mix(in srgb, var(--ev-color) 22%, var(--dt-surface, var(--dt-bg, #ffffff)));
1712
+ border-radius: 0;
1713
+ background: color-mix(in srgb, var(--ev-color) 12%, var(--dt-surface, var(--dt-bg, #ffffff)));
1646
1714
  outline: 1px solid color-mix(in srgb, var(--ev-color) 45%, transparent);
1647
1715
  box-shadow: 0 6px 18px color-mix(in srgb, var(--ev-color) 24%, rgba(0, 0, 0, 0.22));
1648
1716
  display: flex;
@@ -1660,7 +1728,8 @@ function onWindowKeydown(e) {
1660
1728
  box-shadow: none;
1661
1729
  }
1662
1730
  .tw-ghost-time {
1663
- font: 600 11px/1.1 var(--dt-mono, ui-monospace, monospace);
1731
+ font: 700 12px/1.15 var(--dt-sans, system-ui, sans-serif);
1732
+ font-variant-numeric: tabular-nums;
1664
1733
  color: var(--ev-color, var(--dt-accent, #2563eb));
1665
1734
  white-space: nowrap;
1666
1735
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nomideusz/svelte-calendar",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A themeable Svelte 5 calendar: day, week, scrolling-week and month views, agenda lists, touch-first mobile layouts, drag-and-drop, timezones, a headless API and an embeddable web component.",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -50,16 +50,16 @@
50
50
  "svelte": "^5.29.0"
51
51
  },
52
52
  "devDependencies": {
53
- "@sveltejs/adapter-auto": "8.0.0-next.4",
54
- "@sveltejs/adapter-vercel": "7.0.0-next.9",
55
- "@sveltejs/kit": "3.0.0-next.27",
56
- "@sveltejs/package": "3.0.0-next.7",
53
+ "@sveltejs/adapter-auto": "^8.0.0",
54
+ "@sveltejs/adapter-vercel": "^7.0.0",
55
+ "@sveltejs/kit": "^3.0.0",
56
+ "@sveltejs/package": "^3.0.0",
57
57
  "@sveltejs/vite-plugin-svelte": "^7.3.0",
58
58
  "@types/node": "^22.20.0",
59
59
  "@vercel/analytics": "^1.6.1",
60
60
  "jsdom": "^29.1.1",
61
61
  "marked": "^17.0.6",
62
- "svelte": "^5.57.0",
62
+ "svelte": "^5.57.1",
63
63
  "svelte-check": "^4.7.1",
64
64
  "typescript": "^6.0.3",
65
65
  "vite": "^8.3.0",