@nomideusz/svelte-calendar 1.2.0 → 1.3.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.
- package/README.md +3 -3
- package/dist/calendar/Calendar.svelte +202 -296
- package/dist/theme/presets.d.ts +2 -2
- package/dist/theme/presets.js +2 -2
- package/dist/views/agenda/AgendaDay.svelte +162 -278
- package/dist/views/agenda/AgendaWeek.svelte +113 -191
- package/dist/views/mobile/MobileDay.svelte +51 -32
- package/dist/views/mobile/MobileWeek.svelte +17 -10
- package/dist/views/month/MonthGrid.svelte +50 -19
- package/dist/views/planner/PlannerScroll.svelte +33 -27
- package/dist/views/planner/PlannerWeek.svelte +52 -25
- package/dist/views/shared/format.d.ts +3 -0
- package/dist/views/shared/format.js +10 -1
- package/package.json +1 -1
- package/widget/widget.js +671 -653
|
@@ -21,7 +21,8 @@ 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 { fmtHParts, fmtTime, fmtDuration, weekdayShort, weekdayLong } from "../../core/locale.js";
|
|
24
|
+
import { fmtHParts, fmtTime, fmtDuration, fmtWeekRange, weekdayShort, weekdayLong } from "../../core/locale.js";
|
|
25
|
+
import { dateLong } from "../shared/format.js";
|
|
25
26
|
let { mode = "week", mondayStart = true, locale, height = 520, events = [], style = "", focusDate, oneventclick, oneventcreate, onexternaldrop, selectedEventId = null, readOnly = false, visibleHours } = $props();
|
|
26
27
|
// ── Context ────────────────────────────────────────
|
|
27
28
|
const ctx = useCalendarContext();
|
|
@@ -899,7 +900,9 @@ function onWindowKeydown(e) {
|
|
|
899
900
|
style:--tw-col-min="{MIN_COL_W}px"
|
|
900
901
|
style:height={autoHeight ? undefined : (height ? `${height}px` : '100%')}
|
|
901
902
|
role="region"
|
|
902
|
-
aria-label={L.weekAhead}
|
|
903
|
+
aria-label="{singleDay ? L.dayPlanner : L.weekAhead}{dayCols.length
|
|
904
|
+
? `, ${singleDay ? dateLong(dayCols[0].ms, locale) : fmtWeekRange(dayCols[0].ms, locale, dayCols[dayCols.length - 1].ms)}`
|
|
905
|
+
: ''}"
|
|
903
906
|
>
|
|
904
907
|
<div class="tw-scroll" bind:this={scrollEl}>
|
|
905
908
|
<div class="tw-inner" style:min-width="{innerMinWidth}px">
|
|
@@ -1017,7 +1020,7 @@ function onWindowKeydown(e) {
|
|
|
1017
1020
|
class:tw-col--disabled={day.isDisabled}
|
|
1018
1021
|
data-day={day.ms}
|
|
1019
1022
|
role={colsCreate ? 'group' : undefined}
|
|
1020
|
-
aria-label={colsCreate ? `${
|
|
1023
|
+
aria-label={colsCreate ? `${dateLong(day.ms, locale)}, ${L.createEvent}` : undefined}
|
|
1021
1024
|
aria-keyshortcuts={colsCreate ? 'Enter' : undefined}
|
|
1022
1025
|
tabindex={colsCreate ? (day.ms === tabbableColMs ? 0 : -1) : undefined}
|
|
1023
1026
|
onfocusin={() => (focusedColMs = day.ms)}
|
|
@@ -1064,6 +1067,7 @@ function onWindowKeydown(e) {
|
|
|
1064
1067
|
class:tw-ev--past={p.ev.end.getTime() < clock.tick}
|
|
1065
1068
|
class:tw-ev--short={p.height < 44}
|
|
1066
1069
|
class:tw-ev--compact={p.height < 34}
|
|
1070
|
+
class:tw-ev--on-now={weekHasToday && nowY !== null && p.top < nowY && p.top + p.height > nowY}
|
|
1067
1071
|
style:top="{p.top}px"
|
|
1068
1072
|
style:height="{p.height}px"
|
|
1069
1073
|
style:left="calc({(p.col / p.totalCols) * 100}% + 1px)"
|
|
@@ -1138,9 +1142,8 @@ function onWindowKeydown(e) {
|
|
|
1138
1142
|
|
|
1139
1143
|
<!-- Now line (today's column only) -->
|
|
1140
1144
|
{#if day.isToday && nowY !== null}
|
|
1141
|
-
<div class="tw-now" style:top="{nowY}px" aria-label={L.currentTime}>
|
|
1142
|
-
|
|
1143
|
-
</div>
|
|
1145
|
+
<div class="tw-now" style:top="{nowY}px" aria-label={L.currentTime}></div>
|
|
1146
|
+
<span class="tw-now-dot" style:top="{nowY}px" aria-hidden="true"></span>
|
|
1144
1147
|
{/if}
|
|
1145
1148
|
</div>
|
|
1146
1149
|
{/each}
|
|
@@ -1283,8 +1286,9 @@ function onWindowKeydown(e) {
|
|
|
1283
1286
|
padding: 6px 8px 6px 0;
|
|
1284
1287
|
}
|
|
1285
1288
|
.tw-ad-gutter-lb {
|
|
1286
|
-
font: 500
|
|
1287
|
-
|
|
1289
|
+
font: 500 12px/1.2 var(--dt-sans, system-ui, sans-serif);
|
|
1290
|
+
letter-spacing: 0.08em;
|
|
1291
|
+
color: var(--dt-text-2, rgba(0, 0, 0, 0.66));
|
|
1288
1292
|
text-align: right;
|
|
1289
1293
|
}
|
|
1290
1294
|
|
|
@@ -1350,7 +1354,7 @@ function onWindowKeydown(e) {
|
|
|
1350
1354
|
min-width: 0;
|
|
1351
1355
|
}
|
|
1352
1356
|
.tw-ad-span {
|
|
1353
|
-
font: 400
|
|
1357
|
+
font: 400 12.5px/1 var(--dt-sans, system-ui, sans-serif);
|
|
1354
1358
|
font-variant-numeric: tabular-nums;
|
|
1355
1359
|
color: inherit;
|
|
1356
1360
|
opacity: 0.75;
|
|
@@ -1383,7 +1387,7 @@ function onWindowKeydown(e) {
|
|
|
1383
1387
|
border-radius: 3px;
|
|
1384
1388
|
text-align: left;
|
|
1385
1389
|
align-self: flex-start;
|
|
1386
|
-
font:
|
|
1390
|
+
font: 400 12.5px/1 var(--dt-sans, system-ui, sans-serif);
|
|
1387
1391
|
color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
|
|
1388
1392
|
padding: 2px 6px;
|
|
1389
1393
|
cursor: pointer;
|
|
@@ -1519,17 +1523,20 @@ function onWindowKeydown(e) {
|
|
|
1519
1523
|
/* The gutter's right border already bounds the first column */
|
|
1520
1524
|
.tw-lines + .tw-col { border-left: none; }
|
|
1521
1525
|
|
|
1522
|
-
|
|
1526
|
+
/* --tw-col-wash: the column's ground, repeated under an event that the
|
|
1527
|
+
now line crosses (that event is opaque, so the line runs beneath it). */
|
|
1528
|
+
.tw-col { background: var(--tw-col-wash, transparent); }
|
|
1529
|
+
.tw-col--today { --tw-col-wash: var(--dt-today-bg, rgba(37, 99, 235, 0.04)); }
|
|
1523
1530
|
/* Dim past days with a wash, never a subtree opacity (event contrast) */
|
|
1524
1531
|
.tw-col--past {
|
|
1525
|
-
|
|
1532
|
+
--tw-col-wash: color-mix(in srgb, var(--dt-text, rgba(0, 0, 0, 0.87)) 4%, transparent);
|
|
1526
1533
|
}
|
|
1527
1534
|
/* What has already happened steps back; a cancelled block keeps its own look. */
|
|
1528
1535
|
.tw-ev--past:not(.tw-ev--cancelled) {
|
|
1529
1536
|
opacity: 0.78;
|
|
1530
1537
|
}
|
|
1531
1538
|
.tw-col--weekend:not(.tw-col--today):not(.tw-col--past) {
|
|
1532
|
-
|
|
1539
|
+
--tw-col-wash: var(--dt-weekend-bg, rgba(0, 0, 0, 0.012));
|
|
1533
1540
|
}
|
|
1534
1541
|
.tw-col--disabled {
|
|
1535
1542
|
background: repeating-linear-gradient(
|
|
@@ -1561,7 +1568,7 @@ function onWindowKeydown(e) {
|
|
|
1561
1568
|
overflow: hidden;
|
|
1562
1569
|
}
|
|
1563
1570
|
.tw-blocked-lb {
|
|
1564
|
-
font: 500
|
|
1571
|
+
font: 500 11px/1 var(--dt-sans, system-ui, sans-serif);
|
|
1565
1572
|
color: var(--dt-text-2, rgba(0, 0, 0, 0.54));
|
|
1566
1573
|
text-transform: uppercase;
|
|
1567
1574
|
letter-spacing: 0.04em;
|
|
@@ -1570,24 +1577,28 @@ function onWindowKeydown(e) {
|
|
|
1570
1577
|
}
|
|
1571
1578
|
|
|
1572
1579
|
/* ─── Now line ───────────────────────────────────── */
|
|
1580
|
+
/* Under the events (z 6): the one it crosses is opaque (.tw-ev--on-now),
|
|
1581
|
+
so the line never strikes through a title. The dot stays on top. */
|
|
1573
1582
|
.tw-now {
|
|
1574
1583
|
position: absolute;
|
|
1575
1584
|
left: 0;
|
|
1576
1585
|
right: 0;
|
|
1577
1586
|
height: 0;
|
|
1578
1587
|
border-top: 2px solid var(--dt-accent, #2563eb);
|
|
1579
|
-
z-index:
|
|
1588
|
+
z-index: 5;
|
|
1580
1589
|
pointer-events: none;
|
|
1581
1590
|
transform: translateY(-1px);
|
|
1582
1591
|
}
|
|
1583
1592
|
.tw-now-dot {
|
|
1584
1593
|
position: absolute;
|
|
1585
1594
|
left: -4px;
|
|
1586
|
-
top: -5px;
|
|
1587
1595
|
width: 8px;
|
|
1588
1596
|
height: 8px;
|
|
1597
|
+
margin-top: -4px;
|
|
1589
1598
|
border-radius: 50%;
|
|
1590
1599
|
background: var(--dt-accent, #2563eb);
|
|
1600
|
+
z-index: 12;
|
|
1601
|
+
pointer-events: none;
|
|
1591
1602
|
}
|
|
1592
1603
|
|
|
1593
1604
|
/* ─── Events ─────────────────────────────────────── */
|
|
@@ -1630,6 +1641,17 @@ function onWindowKeydown(e) {
|
|
|
1630
1641
|
.tw-ev--current {
|
|
1631
1642
|
background: var(--dt-accent-dim, rgba(37, 99, 235, 0.12));
|
|
1632
1643
|
}
|
|
1644
|
+
/* An event the now line crosses lays its column's ground (and its own
|
|
1645
|
+
wash) over the paper, so the line passes beneath its text. */
|
|
1646
|
+
.tw-ev.tw-ev--on-now {
|
|
1647
|
+
background:
|
|
1648
|
+
linear-gradient(var(--tw-ev-wash, transparent), var(--tw-ev-wash, transparent)),
|
|
1649
|
+
linear-gradient(var(--tw-col-wash, transparent), var(--tw-col-wash, transparent)),
|
|
1650
|
+
var(--dt-paper, none),
|
|
1651
|
+
var(--dt-bg, #ffffff);
|
|
1652
|
+
}
|
|
1653
|
+
.tw-ev--on-now.tw-ev--current { --tw-ev-wash: var(--dt-accent-dim, rgba(37, 99, 235, 0.12)); }
|
|
1654
|
+
.tw-ev--on-now:hover { --tw-ev-wash: var(--dt-hover, rgba(0, 0, 0, 0.04)); }
|
|
1633
1655
|
.tw-ev--resizing {
|
|
1634
1656
|
z-index: 50;
|
|
1635
1657
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
|
|
@@ -1681,14 +1703,20 @@ function onWindowKeydown(e) {
|
|
|
1681
1703
|
gap: 1px;
|
|
1682
1704
|
overflow: hidden;
|
|
1683
1705
|
}
|
|
1684
|
-
/* Compact (< ~35min at default zoom):
|
|
1706
|
+
/* Compact (< ~35min at default zoom): one line, "Title 9:00". The title
|
|
1707
|
+
wins the room: the time wraps onto a second line, which the block
|
|
1708
|
+
clips, before the title is cut; a title too long alone ellipsizes. */
|
|
1685
1709
|
.tw-ev--compact .tw-ev-body {
|
|
1686
1710
|
flex-direction: row;
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1711
|
+
flex-wrap: wrap;
|
|
1712
|
+
align-content: flex-start;
|
|
1713
|
+
align-items: baseline;
|
|
1714
|
+
gap: 24px 5px;
|
|
1715
|
+
padding-top: 2px;
|
|
1716
|
+
padding-bottom: 0;
|
|
1717
|
+
}
|
|
1718
|
+
.tw-ev--compact .tw-ev-title { flex: 0 1 auto; min-width: 0; }
|
|
1719
|
+
.tw-ev--compact .tw-ev-end { display: none; }
|
|
1692
1720
|
|
|
1693
1721
|
/* Title first, time under it; both one size, rank by weight and ink. */
|
|
1694
1722
|
.tw-ev-time {
|
|
@@ -1699,7 +1727,6 @@ function onWindowKeydown(e) {
|
|
|
1699
1727
|
white-space: nowrap;
|
|
1700
1728
|
flex-shrink: 0;
|
|
1701
1729
|
}
|
|
1702
|
-
.tw-ev--compact .tw-ev-time { order: 0; }
|
|
1703
1730
|
/* A narrow overlap column keeps the start time whole and drops the end. */
|
|
1704
1731
|
@container tw-ev (max-width: 104px) {
|
|
1705
1732
|
.tw-ev-end { display: none; }
|
|
@@ -1820,13 +1847,13 @@ function onWindowKeydown(e) {
|
|
|
1820
1847
|
box-shadow: none;
|
|
1821
1848
|
}
|
|
1822
1849
|
.tw-ghost-time {
|
|
1823
|
-
font:
|
|
1850
|
+
font: 500 12.5px/1.15 var(--dt-sans, system-ui, sans-serif);
|
|
1824
1851
|
font-variant-numeric: tabular-nums;
|
|
1825
1852
|
color: var(--ev-color, var(--dt-accent, #2563eb));
|
|
1826
1853
|
white-space: nowrap;
|
|
1827
1854
|
}
|
|
1828
1855
|
.tw-ghost-title {
|
|
1829
|
-
font:
|
|
1856
|
+
font: 500 12.5px/1.2 var(--dt-sans, system-ui, sans-serif);
|
|
1830
1857
|
color: var(--dt-text, rgba(0, 0, 0, 0.87));
|
|
1831
1858
|
white-space: nowrap;
|
|
1832
1859
|
overflow: hidden;
|
|
@@ -18,3 +18,6 @@ export interface TimeSlot {
|
|
|
18
18
|
events: TimelineEvent[];
|
|
19
19
|
}
|
|
20
20
|
export declare function groupIntoSlots(evts: TimelineEvent[]): TimeSlot[];
|
|
21
|
+
/** A day in full, in the locale's own order: "Monday, October 19" (en-US),
|
|
22
|
+
* "poniedziałek, 19 października" (pl-PL). For screen-reader names. */
|
|
23
|
+
export declare function dateLong(ms: number, locale?: string): string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fmtTime as _fmtTime, fmtDuration, getLabels } from '../../core/locale.js';
|
|
1
|
+
import { fmtTime as _fmtTime, fmtDuration, getLabels, getDefaultLocale } from '../../core/locale.js';
|
|
2
2
|
export function fmtTime(d, locale) {
|
|
3
3
|
return _fmtTime(d, locale);
|
|
4
4
|
}
|
|
@@ -47,3 +47,12 @@ export function groupIntoSlots(evts) {
|
|
|
47
47
|
}
|
|
48
48
|
return slots;
|
|
49
49
|
}
|
|
50
|
+
/** A day in full, in the locale's own order: "Monday, October 19" (en-US),
|
|
51
|
+
* "poniedziałek, 19 października" (pl-PL). For screen-reader names. */
|
|
52
|
+
export function dateLong(ms, locale) {
|
|
53
|
+
return new Date(ms).toLocaleDateString(locale ?? getDefaultLocale(), {
|
|
54
|
+
weekday: 'long',
|
|
55
|
+
month: 'long',
|
|
56
|
+
day: 'numeric',
|
|
57
|
+
});
|
|
58
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nomideusz/svelte-calendar",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.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": [
|