@lit-material/calendar 0.0.0-stage → 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 bohdaq
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,162 @@
1
- # Temporary Holding Version
1
+ # @lit-material/calendar
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A calendar and scheduler web component styled after Material Design 3, built with [Lit](https://lit.dev/): a month
4
+ grid, week and day time grids, and an agenda list, with drag-and-drop, resizing and keyboard moves. Part of
5
+ [lit-material](https://github.com/bohdaq/lit-material).
6
+
7
+ ## Install
8
+
9
+ ```sh
10
+ npm install @lit-material/calendar @lit-material/tokens
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```html
16
+ <link rel="stylesheet" href="node_modules/@lit-material/tokens/css/index.css" />
17
+ <script type="module">
18
+ import "@lit-material/calendar";
19
+ </script>
20
+
21
+ <lit-material-calendar
22
+ view="week"
23
+ date="2026-06-15"
24
+ events='[
25
+ { "id": 1, "title": "Standup", "start": "2026-06-15T09:00", "end": "2026-06-15T09:15" },
26
+ { "id": 2, "title": "Offsite", "start": "2026-06-16", "end": "2026-06-18", "color": "#7d5260" }
27
+ ]'
28
+ ></lit-material-calendar>
29
+
30
+ <script type="module">
31
+ const calendar = document.querySelector("lit-material-calendar");
32
+
33
+ // Events are controlled: apply the change (or call preventDefault() to refuse it).
34
+ calendar.addEventListener("event-change", (e) => {
35
+ const { event, start, end } = e.detail;
36
+ calendar.events = calendar.events.map((x) => (x === event ? { ...x, start, end } : x));
37
+ });
38
+
39
+ // An empty slot or day was clicked, or a time range dragged out.
40
+ calendar.addEventListener("slot-click", (e) => {
41
+ const { start, end, allDay } = e.detail;
42
+ calendar.events = [...calendar.events, { id: crypto.randomUUID(), title: "New event", start, end, allDay }];
43
+ });
44
+
45
+ calendar.addEventListener("event-click", (e) => openEditor(e.detail.event));
46
+
47
+ // The period on screen changed: load its events.
48
+ calendar.addEventListener("navigate", (e) => load(e.detail.start, e.detail.end));
49
+ </script>
50
+ ```
51
+
52
+ ## Events and time zones
53
+
54
+ Each event is `{ id, title, start, end?, allDay?, color?, editable?, ...data }`. `id`s should be unique; extra
55
+ fields are kept, and `event-click`/`event-change` hand back the object you passed in.
56
+
57
+ - `start`/`end` are `Date`s or ISO strings. `"2026-06-15"` is a day, `"2026-06-15T09:30"` a local time, and a string
58
+ with `Z` or an offset an instant.
59
+ - `end` is exclusive. Without it (or when it isn't after `start`), a timed event lasts an hour and an all-day one a
60
+ day. An all-day event from the 16th to the 17th inclusive is `start: "2026-06-16", end: "2026-06-18"`.
61
+ - `allDay` defaults to `true` when `start` is a date-only string. All-day events go in the all-day row of the week
62
+ and day views; timed events that cross midnight are split at each day.
63
+ - **Time zone**: everything is shown in the local time zone of the browser (or the server, when rendering there),
64
+ and `slot-click`/`event-change` give local `Date`s. Convert to and from another zone in your app; a `time-zone`
65
+ property isn't supported (see Scope).
66
+
67
+ ## Views
68
+
69
+ - **Month** (`view="month"`): an ARIA grid of the weeks around the month. All-day and multi-day events are bars
70
+ across the days they cover; timed events show their start time. After `day-max-events` rows a day shows
71
+ "+N more", which opens that day.
72
+ - **Week and day** (`view="week"`, `view="day"`): a scrolling time grid with a row per `slot-minutes`, an all-day row,
73
+ and a red line at the current time. Overlapping events share the width of the day in columns. The grid opens
74
+ scrolled to `scroll-to-hour`.
75
+ - **Agenda** (`view="agenda"`): the events of `agenda-days` days from `date`, grouped by day.
76
+
77
+ The toolbar has Today, previous and next, the period's title (formatted in the element's language with `Intl`)
78
+ and a view switch (`lit-material-segmented-button-group`). Without `first-day-of-week`, weeks start on the
79
+ language's first day (from `Intl.Locale` week info, else Sunday), as in `@lit-material/date-picker`.
80
+
81
+ ## Keyboard
82
+
83
+ The month view is an ARIA `grid` of days. The week and day views are one `grid` too: a header row of days, then an
84
+ "All day" row and a row per time slot, each with a time `rowheader`. Each cell is named by its date (and time) and
85
+ how many events it has; each event is a button named by its title and its date and time
86
+ ("Standup, Monday, June 15, 9:00 – 9:15 AM").
87
+
88
+ | Key | In the grid |
89
+ | --- | --- |
90
+ | Arrow keys | Move between days; in the week and day views Up/Down move between time slots and the all-day row. Left/Right swap in right-to-left layouts. |
91
+ | Shift+Up/Down | Week and day views: extend a time range from the focused slot. |
92
+ | Enter, Space | `slot-click` for the focused day, all-day cell, slot or selected range. |
93
+ | Home, End | First or last day of the week (Ctrl+Home/End: first or last slot of the day). |
94
+ | PageUp, PageDown | Previous or next month, week or day (Shift: a year, in the month view). |
95
+ | T | Today. |
96
+ | Tab | From the focused cell to its events (and "+N more"), then out of the grid. |
97
+
98
+ | Key | On an event |
99
+ | --- | --- |
100
+ | Enter, Space | `event-click`. |
101
+ | Alt+Left/Right | Move it a day earlier or later (mirrored in right-to-left layouts). |
102
+ | Alt+Up/Down | Move it a slot (week and day views) or a week (month view, all-day row). |
103
+ | Alt+Shift+arrows | Change its end by the same steps. |
104
+ | Escape | Back to the cell. |
105
+
106
+ After an `event-change` the app applies, focus follows the event and its new time is announced. In the agenda, Up/Down,
107
+ Home/End move between events, PageUp/PageDown change the period and T goes to today.
108
+
109
+ With a mouse or pen, drag across empty slots to fire `slot-click` for the range, drag an event to move it, and drag
110
+ its bottom edge to resize it (week and day views; in the month view and the all-day row, drag to another day).
111
+
112
+ ## API
113
+
114
+ | Property | Attribute | Type | Default |
115
+ | --- | --- | --- | --- |
116
+ | `view` | `view` (reflected) | `"month" \| "week" \| "day" \| "agenda"` | `"month"` |
117
+ | `date` | `date` | `string` (ISO `YYYY-MM-DD`, the focused day) | today |
118
+ | `events` | `events` (JSON) | `CalendarEvent[]` | `[]` |
119
+ | `firstDayOfWeek` | `first-day-of-week` | `number` (0 = Sunday) | the language's first day, else `0` |
120
+ | `slotMinutes` | `slot-minutes` | `number` | `30` |
121
+ | `scrollToHour` | `scroll-to-hour` | `number` | `8` |
122
+ | `dayMaxEvents` | `day-max-events` | `number` | `3` |
123
+ | `agendaDays` | `agenda-days` | `number` | `7` |
124
+ | `readonly` | `readonly` (reflected) | `boolean` (no drag, resize or keyboard moves) | `false` |
125
+ | `visibleRange` | — | `{ start: Date, end: Date }` (read only, `end` exclusive) | |
126
+
127
+ Methods: `next()`, `previous()`, `goToToday()`. `date` and `view` change as the user navigates.
128
+
129
+ | Event | `detail` |
130
+ | --- | --- |
131
+ | `event-click` | `{ event }` |
132
+ | `slot-click` | `{ start, end, allDay }` (`end` exclusive) |
133
+ | `event-change` | `{ event, start, end, allDay }`. Cancelable; the calendar doesn't move the event itself. |
134
+ | `navigate` | `{ view, date, start, end }`, when the toolbar, keyboard or "+N more" changes the view or period |
135
+
136
+ Parts `toolbar`, `title`, `views`, `grid`, `agenda`, `event`. Custom properties
137
+ `--lit-material-calendar-slot-height` (24px) and `--lit-material-calendar-height` (640px, the time grid's maximum
138
+ height); an event's `color` is its accent. Strings are in `@lit-material/translations` (`calendar.*`).
139
+
140
+ `normalizeEvents`, `layoutDay` (overlap columns for one day) and `layoutSpans` (lanes for bars across days) are
141
+ exported from `@lit-material/calendar/calendar-utils.js` and work without a DOM.
142
+
143
+ Positions are set with `cssProps` from `@lit-material/core` (the CSSOM, not style attributes), so the calendar works
144
+ under a `style-src 'self'` Content-Security-Policy. It renders on the server from attributes, including `events`.
145
+ Set `date` when the markup is rendered ahead of time (a prerendered page): without it the server's "today" picks the
146
+ period. The current-time line is drawn only in the browser, after hydration.
147
+
148
+ ## Scope
149
+
150
+ Left out of this version:
151
+
152
+ - Time zones other than the local one (`time-zone`): convert in the app.
153
+ - Recurring events (expand them in the app for the visible range, from `navigate`), and an event editor or popover.
154
+ - Dragging a timed event into the all-day row or back, dragging events between the agenda's days, and resizing in
155
+ the month view with a pointer (Alt+Shift+arrows work there). Drag to create a range is for mouse and pen; on touch,
156
+ tap a slot.
157
+ - A multi-day event in the month view is reachable with Tab from the cell where its bar starts in each week.
158
+ - Resource (per-person or per-room) columns, week numbers, and hiding weekends.
159
+
160
+ ## License
161
+
162
+ MIT