@jpahd/kalendus 0.1.0 → 0.1.7

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 CHANGED
@@ -1,6 +1,33 @@
1
1
  # kalendus
2
2
 
3
- A sophisticated, responsive calendar web component built with Lit 3.x and TypeScript. Designed for Library Management Systems and other applications requiring advanced calendar functionality with support for overlapping events, multiple view modes, per-instance localization, and extensive customization.
3
+ A sophisticated, responsive calendar web component built with Lit 3.x and TypeScript. Multiple view modes, overlapping event handling, per-instance localization, and 80+ CSS design tokens.
4
+
5
+ ![demo](assets/demo.gif)
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ pnpm add @jpahd/kalendus
11
+ ```
12
+
13
+ ## Quick Usage
14
+
15
+ ```html
16
+ <lms-calendar
17
+ .heading="My Calendar"
18
+ .activeDate=${{ day: 15, month: 3, year: 2024 }}
19
+ .entries=${myEvents}
20
+ .color="#1976d2"
21
+ ></lms-calendar>
22
+ ```
23
+
24
+ Each instance auto-detects its locale from `<html lang="...">`. Override per-instance:
25
+
26
+ ```html
27
+ <lms-calendar locale="ja" .firstDayOfWeek="${0}"></lms-calendar>
28
+ <lms-calendar locale="es"></lms-calendar>
29
+ <lms-calendar locale="zh-Hans"></lms-calendar>
30
+ ```
4
31
 
5
32
  ## Features
6
33
 
@@ -34,54 +61,18 @@ A sophisticated, responsive calendar web component built with Lit 3.x and TypeSc
34
61
  - **Localized Date Formatting**: Weekday names, month names, and date formats use the instance's locale
35
62
  - **Configurable Week Start**: `firstDayOfWeek` property supports Monday (ISO), Sunday (US/JP), Saturday (AR), or any day
36
63
 
37
- ## Installation
38
-
39
- ```bash
40
- pnpm add @jpahd/kalendus
41
- ```
42
-
43
- ## Usage
44
-
45
- See `docs/integration-guide.md` for end-to-end recipes covering vanilla HTML, React, Lit, theming tokens, and analytics hooks. A few quick snippets are included below.
46
-
47
- ## Documentation Map
48
-
49
- | Audience | Document | Highlights |
50
- | ---------------------- | ------------------------------------------------------------ | -------------------------------------------------- |
51
- | Integrators | [Integration Guide](docs/integration-guide.md) | Framework recipes, theming tokens, analytics hooks |
52
- | Application Developers | [Library Usage](docs/library-usage.md) | API surface, data contracts, DOM events |
53
- | Component Contributors | [Developer Guide](docs/developer-guide.md) | Internal architecture, debugging tips |
54
- | Rendering Internals | [Rendering Calculations](docs/rendering-calculations.md) | Grid math, condensed weeks, density modes |
55
- | Design Systems | [Design Token Refactoring](docs/design-token-refactoring.md) | Token audit and proposed hierarchy |
56
- | Backend/API | [API Server Guide](docs/api-server.md) | REST + SSE backend, database + adapters |
57
-
58
- ### Basic Usage
59
-
60
- ```html
61
- <lms-calendar
62
- .heading="My Calendar"
63
- .activeDate=${{ day: 15, month: 3, year: 2024 }}
64
- .entries=${myEvents}
65
- .color="#1976d2"
66
- ></lms-calendar>
67
- ```
68
-
69
- ### Per-Instance Locale
70
-
71
- By default, every calendar auto-detects its locale from the page's `<html lang="...">` attribute. You can override individual instances with the `locale` property:
72
-
73
- ```html
74
- <!-- Auto-detects from <html lang="de"> — no config needed -->
75
- <lms-calendar .entries="${events}"></lms-calendar>
76
-
77
- <!-- Explicitly override to Japanese with Sunday-first weeks -->
78
- <lms-calendar .entries="${events}" locale="ja" .firstDayOfWeek="${0}"></lms-calendar>
64
+ ## Properties
79
65
 
80
- <!-- Multiple locales on the same page - each fully independent -->
81
- <lms-calendar locale="es"></lms-calendar>
82
- <lms-calendar locale="fr"></lms-calendar>
83
- <lms-calendar locale="zh-Hans"></lms-calendar>
84
- ```
66
+ | Property | Type | Default | Description |
67
+ | ----------------- | ------------------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------- |
68
+ | `heading` | `string` | `undefined` | Calendar title displayed in header |
69
+ | `activeDate` | `CalendarDate` | Current date | Initially displayed date |
70
+ | `entries` | `CalendarEntry[]` | `[]` | Array of calendar events |
71
+ | `color` | `string` | `'#000000'` | Primary theme color |
72
+ | `locale` | `string` | `document.documentElement.lang \|\| 'en'` | Locale for UI strings and date formatting (auto-detected from page, overridable per-instance) |
73
+ | `firstDayOfWeek` | `0-6` | `1` | First day of the week (0=Sun, 1=Mon, ..., 6=Sat) |
74
+ | `yearDrillTarget` | `'day' \| 'month'` | `'month'` | Determines whether a year-view click opens day or month view |
75
+ | `yearDensityMode` | `'dot' \| 'heatmap' \| 'count'` | `'dot'` | Chooses how per-day entry density is visualized in year view |
85
76
 
86
77
  ### Event Structure
87
78
 
@@ -102,45 +93,8 @@ interface CalendarEntry {
102
93
  }
103
94
  ```
104
95
 
105
- ### Example Events
106
-
107
- ```typescript
108
- const events = [
109
- {
110
- heading: 'Team Meeting',
111
- content: 'Weekly team sync',
112
- color: '#1976d2',
113
- isContinuation: false,
114
- date: {
115
- start: { day: 15, month: 3, year: 2024 },
116
- end: { day: 15, month: 3, year: 2024 },
117
- },
118
- time: {
119
- start: { hour: 9, minute: 0 },
120
- end: { hour: 10, minute: 30 },
121
- },
122
- },
123
- {
124
- heading: 'Project Sprint',
125
- content: 'Development sprint',
126
- color: '#2e7d32',
127
- isContinuation: false,
128
- date: {
129
- start: { day: 20, month: 3, year: 2024 },
130
- end: { day: 22, month: 3, year: 2024 },
131
- },
132
- time: {
133
- start: { hour: 8, minute: 0 },
134
- end: { hour: 17, minute: 0 },
135
- },
136
- },
137
- ];
138
- ```
139
-
140
96
  ### Year View Controls
141
97
 
142
- The year overview makes it easy to hop between distant dates. Two properties tune how it behaves:
143
-
144
98
  ```html
145
99
  <lms-calendar
146
100
  year-drill-target="day"
@@ -152,19 +106,6 @@ The year overview makes it easy to hop between distant dates. Two properties tun
152
106
  - `year-drill-target` (`day` \| `month`): picking a day can either open the specific day or simply focus its month.
153
107
  - `year-density-mode` (`dot` \| `heatmap` \| `count`): swap between subtle dots, tonal heatmaps, or explicit counts for per-day density.
154
108
 
155
- ## Properties
156
-
157
- | Property | Type | Default | Description |
158
- | ----------------- | ------------------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------- |
159
- | `heading` | `string` | `undefined` | Calendar title displayed in header |
160
- | `activeDate` | `CalendarDate` | Current date | Initially displayed date |
161
- | `entries` | `CalendarEntry[]` | `[]` | Array of calendar events |
162
- | `color` | `string` | `'#000000'` | Primary theme color |
163
- | `locale` | `string` | `document.documentElement.lang \|\| 'en'` | Locale for UI strings and date formatting (auto-detected from page, overridable per-instance) |
164
- | `firstDayOfWeek` | `0-6` | `1` | First day of the week (0=Sun, 1=Mon, ..., 6=Sat) |
165
- | `yearDrillTarget` | `'day' \| 'month'` | `'month'` | Determines whether a year-view click opens day or month view |
166
- | `yearDensityMode` | `'dot' \| 'heatmap' \| 'count'` | `'dot'` | Chooses how per-day entry density is visualized in year view |
167
-
168
109
  ### Supported Locales
169
110
 
170
111
  | Code | Language | Default Week Start |
@@ -193,141 +134,31 @@ The year overview makes it easy to hop between distant dates. Two properties tun
193
134
 
194
135
  ## Styling & Theming
195
136
 
196
- The calendar uses CSS custom properties for comprehensive theming:
197
-
198
- ### Primary Colors
137
+ Override CSS custom properties to match your design system:
199
138
 
200
139
  ```css
201
140
  lms-calendar {
202
141
  --primary-color: #1976d2;
203
142
  --background-color: #ffffff;
204
- --separator-light: rgba(0, 0, 0, 0.1);
205
- --separator-dark: rgba(0, 0, 0, 0.7);
206
- }
207
- ```
208
-
209
- ### Entry Styling
210
-
211
- ```css
212
- lms-calendar {
213
143
  --entry-border-radius: 6px;
214
- --entry-font-size: 0.75rem;
215
- --entry-padding: 0.15em 0.25em;
216
- --entry-min-height: 1.2em;
217
- }
218
- ```
219
-
220
- ### Layout & Spacing
221
-
222
- ```css
223
- lms-calendar {
224
144
  --header-height: 4em;
225
- --day-padding: 0.5em;
226
- --day-gap: 1px;
227
- --time-column-width: 4em;
228
145
  }
229
146
  ```
230
147
 
231
- ### Week Column Controls
148
+ See [docs/theming.md](docs/theming.md) for the full token reference (primary colors, entry styling, layout & spacing, week column controls, year view tokens).
232
149
 
233
- ```css
234
- lms-calendar {
235
- --week-day-count: 7; /* full-width columns */
236
- --week-mobile-day-count: 3; /* columns when condensed */
237
- --week-mobile-breakpoint: 768px;
238
- }
239
- ```
240
-
241
- `computeWeekDisplayContext` reads these tokens at runtime to decide how many day columns to render. Below the breakpoint the component centers a smaller window (e.g., three days) around the active date and exposes peek navigation so users can slide through the full week without sacrificing readability on narrow screens.
242
-
243
- ### Year View Tokens
244
-
245
- ```css
246
- lms-calendar {
247
- --year-grid-columns: 3;
248
- --year-grid-columns-tablet: 2;
249
- --year-grid-columns-mobile: 1;
250
- --year-month-label-font-size: 0.875em;
251
- --year-day-font-size: 0.7em;
252
- --year-cell-size: 1.8em;
253
- --year-dot-color: var(--indicator-color, var(--primary-color));
254
- --year-heatmap-1: rgba(30, 144, 255, 0.15);
255
- --year-heatmap-2: rgba(30, 144, 255, 0.35);
256
- --year-heatmap-3: rgba(30, 144, 255, 0.55);
257
- --year-heatmap-4: rgba(30, 144, 255, 0.75);
258
- }
259
- ```
260
-
261
- Adjust these tokens to align the overview grid with your design system (e.g., forcing a single-column mobile layout or brand-specific heatmap shades).
262
-
263
- ### Week View Tokens
264
-
265
- ```css
266
- lms-calendar {
267
- --week-day-count: 7; /* columns at full width (1-7) */
268
- --week-mobile-day-count: 3; /* columns below breakpoint (1-7) */
269
- --week-mobile-breakpoint: 768px; /* width threshold */
270
- }
271
- ```
272
-
273
- On narrow viewports the week view automatically condenses to show fewer day columns centered on the active date, with subtle peek indicators at the edges. Values are clamped to the 1-7 range.
274
-
275
- ## Architecture
276
-
277
- ### Component Structure
278
-
279
- ```
280
- src/
281
- ├── lms-calendar.ts # Main calendar component & global types
282
- ├── components/
283
- │ ├── Header.ts # Navigation and view controls
284
- │ ├── Month.ts # Monthly calendar grid
285
- │ ├── Week.ts # Weekly time-based view
286
- │ ├── Day.ts # Daily detailed view
287
- │ ├── Year.ts # Year overview with drill targets and density modes
288
- │ ├── Entry.ts # Individual event component
289
- │ ├── Context.ts # Weekday header row (month view)
290
- │ └── Menu.ts # Event detail popover with ICS export
291
- ├── lib/
292
- │ ├── messages.ts # Per-instance i18n via direct template lookup
293
- │ ├── localization.ts # Locale-parameterized date/time formatting
294
- │ ├── ViewStateController.ts # Per-instance view mode & date state
295
- │ ├── LayoutCalculator.ts # Overlap detection & box layout
296
- │ ├── SlotManager.ts # Slot naming & CSS position generation
297
- │ ├── allDayLayout.ts # All-day event row allocation
298
- │ ├── weekStartHelper.ts # Week start offset & locale mapping
299
- │ ├── DirectionalCalendarDateCalculator.ts
300
- │ ├── getOverlappingEntitiesIndices.ts
301
- │ ├── getSortedGradingsByIndex.ts
302
- │ ├── partitionOverlappingIntervals.ts
303
- │ └── getColorTextWithContrast.ts
304
- └── generated/
305
- ├── locale-codes.ts # Source & target locale definitions
306
- └── locales/ # Generated translation templates (hash ID → string)
307
- ├── ar.ts, bn.ts, de.ts, de-DE.ts, es.ts, fr.ts, hi.ts
308
- ├── id.ts, it.ts, ja.ts, ko.ts, nl.ts, pl.ts, pt.ts
309
- ├── ru.ts, th.ts, tr.ts, uk.ts, vi.ts
310
- └── zh-Hans.ts
311
- ```
312
-
313
- ### Key Technologies
314
-
315
- - **Lit 3.x**: Modern web components with reactive properties and decorators
316
- - **TypeScript**: Type-safe development with strict mode
317
- - **Luxon**: Robust date/time manipulation and locale-aware formatting
318
- - **Remeda**: Functional programming utilities for data transformations
319
- - **ts-pattern**: Pattern matching for cleaner conditional logic
320
- - **ts-ics**: ICS calendar file generation for event export
321
- - **@lit/localize** (build-time only): Template extraction and generation via `lit-localize` CLI
322
-
323
- ### Design Patterns
150
+ ## Documentation Map
324
151
 
325
- - **Per-instance state** via `ViewStateController` (Lit `ReactiveController`)
326
- - **Per-instance localization** via direct template hash lookups (bypasses `@lit/localize` singleton)
327
- - **Event bubbling** for component communication (`switchdate`, `switchview`, `expand`, `open-menu`)
328
- - **CSS custom properties** for theming (80+ tokens)
329
- - **Slot-based composition** for entry placement in view grids
330
- - **Container queries** for responsive header layout
152
+ | Audience | Document | Highlights |
153
+ | ---------------------- | ------------------------------------------------------------ | ----------------------------------------------------- |
154
+ | Integrators | [Integration Guide](docs/integration-guide.md) | Framework recipes, theming tokens, analytics hooks |
155
+ | Application Developers | [Library Usage](docs/library-usage.md) | API surface, data contracts, DOM events |
156
+ | Component Contributors | [Developer Guide](docs/developer-guide.md) | Internal architecture, debugging tips, adding locales |
157
+ | Rendering Internals | [Rendering Calculations](docs/rendering-calculations.md) | Grid math, condensed weeks, density modes |
158
+ | Design Systems | [Theming Reference](docs/theming.md) | Full CSS custom property reference (80+ tokens) |
159
+ | Architecture | [Architecture Overview](docs/architecture.md) | Component tree, technologies, design patterns |
160
+ | Design Tokens | [Design Token Refactoring](docs/design-token-refactoring.md) | Token audit and proposed hierarchy |
161
+ | Backend/API | [API Server Guide](docs/api-server.md) | REST + SSE backend, database + adapters |
331
162
 
332
163
  ## Testing
333
164
 
@@ -338,7 +169,10 @@ pnpm test
338
169
  # Run tests in watch mode
339
170
  pnpm test:watch
340
171
 
341
- # Run Storybook tests
172
+ # Run component tests (Web Test Runner + Playwright)
173
+ pnpm test:components
174
+
175
+ # Run Storybook interaction tests (Vitest)
342
176
  pnpm test-storybook
343
177
  ```
344
178
 
@@ -346,7 +180,7 @@ pnpm test-storybook
346
180
 
347
181
  - **Unit tests** (`test/unit/lib/`): Pure function tests with Mocha + Chai
348
182
  - **Component tests** (`test/unit/components/`): Lit component tests with @open-wc/testing
349
- - **Visual tests**: Storybook stories for all views, locales, and edge cases
183
+ - **Interaction tests**: Storybook stories with `play` functions, run via `@storybook/addon-vitest`
350
184
 
351
185
  ## Storybook
352
186
 
@@ -376,6 +210,7 @@ pnpm build # Build with Vite
376
210
  pnpm test # Run tests
377
211
  pnpm lint # Run lit-analyzer + oxlint
378
212
  pnpm format # Format with oxfmt
213
+ pnpm demo:gif # Record demo GIF (requires ffmpeg)
379
214
  ```
380
215
 
381
216
  See `docs/developer-guide.md` for internal architecture notes, troubleshooting checklists, and tips on extending condensed week layouts or localization.
@@ -393,14 +228,6 @@ pnpm --filter @jpahd/kalendus-server dev
393
228
 
394
229
  Configuration, endpoint overview, and adapter usage live in `docs/api-server.md`.
395
230
 
396
- ### Adding a New Locale
397
-
398
- 1. Add the locale code to `lit-localize.json` target locales
399
- 2. Run `pnpm exec lit-localize extract` to generate the template file
400
- 3. Translate strings in `src/generated/locales/<locale>.ts`
401
- 4. Add the import and entry in `src/lib/messages.ts` (`allTemplates` map)
402
- 5. Optionally add a `LUXON_LOCALE_MAP` entry in `localization.ts` if the locale code differs from Intl/Luxon conventions
403
-
404
231
  ## License
405
232
 
406
233
  MIT License - see LICENSE file for details.