@nomideusz/svelte-calendar 0.5.2 → 0.6.3

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.
Files changed (49) hide show
  1. package/README.md +408 -178
  2. package/dist/adapters/memory.d.ts +7 -9
  3. package/dist/adapters/memory.js +8 -23
  4. package/dist/adapters/recurring.d.ts +8 -6
  5. package/dist/adapters/recurring.js +28 -30
  6. package/dist/calendar/Calendar.svelte +776 -356
  7. package/dist/calendar/Calendar.svelte.d.ts +57 -6
  8. package/dist/core/index.d.ts +2 -2
  9. package/dist/core/index.js +1 -1
  10. package/dist/core/locale.js +2 -2
  11. package/dist/core/palette.d.ts +5 -0
  12. package/dist/core/palette.js +8 -0
  13. package/dist/core/types.d.ts +14 -0
  14. package/dist/engine/event-store.svelte.d.ts +0 -17
  15. package/dist/engine/event-store.svelte.js +30 -17
  16. package/dist/engine/index.d.ts +1 -1
  17. package/dist/engine/view-state.svelte.d.ts +10 -5
  18. package/dist/engine/view-state.svelte.js +32 -16
  19. package/dist/index.d.ts +7 -7
  20. package/dist/index.js +3 -4
  21. package/dist/primitives/DayHeader.svelte +103 -103
  22. package/dist/primitives/EmptySlot.svelte +105 -105
  23. package/dist/primitives/EventBlock.svelte +312 -312
  24. package/dist/primitives/NowIndicator.svelte +178 -178
  25. package/dist/primitives/TimeGutter.svelte +104 -104
  26. package/dist/theme/auto.d.ts +53 -0
  27. package/dist/theme/auto.js +534 -0
  28. package/dist/theme/index.d.ts +3 -1
  29. package/dist/theme/index.js +3 -1
  30. package/dist/theme/presets.d.ts +20 -6
  31. package/dist/theme/presets.js +55 -42
  32. package/dist/views/agenda/AgendaDay.svelte +1073 -976
  33. package/dist/views/agenda/AgendaWeek.svelte +934 -775
  34. package/dist/views/agenda/index.d.ts +0 -2
  35. package/dist/views/agenda/index.js +0 -2
  36. package/dist/views/index.d.ts +3 -2
  37. package/dist/views/index.js +3 -2
  38. package/dist/views/mobile/Mobile.svelte +17 -0
  39. package/dist/views/mobile/Mobile.svelte.d.ts +7 -0
  40. package/dist/views/mobile/MobileDay.svelte +702 -0
  41. package/dist/views/mobile/MobileDay.svelte.d.ts +20 -0
  42. package/dist/views/mobile/MobileWeek.svelte +461 -0
  43. package/dist/views/mobile/MobileWeek.svelte.d.ts +20 -0
  44. package/dist/views/mobile/index.d.ts +1 -0
  45. package/dist/views/mobile/index.js +1 -0
  46. package/dist/views/planner/PlannerDay.svelte +1129 -957
  47. package/dist/views/planner/PlannerWeek.svelte +949 -840
  48. package/dist/widget/CalendarWidget.svelte +142 -157
  49. package/package.json +2 -1
@@ -2,24 +2,22 @@
2
2
  * In-memory adapter — the default for demos and testing.
3
3
  *
4
4
  * Events are stored in a plain array. No persistence across page loads.
5
- * Perfect for prototyping and unit tests.
5
+ * Events without a `color` are auto-assigned one from a palette,
6
+ * grouped by `category` or `title` so related events share a color.
6
7
  *
7
8
  * Usage:
8
9
  * import { createMemoryAdapter } from './';
9
10
  * const adapter = createMemoryAdapter(initialEvents);
10
- * const store = createEventStore(adapter);
11
+ * const adapter = createMemoryAdapter(initialEvents, { palette: myColors });
11
12
  */
12
13
  import type { TimelineEvent } from '../core/types.js';
13
14
  import type { CalendarAdapter } from './types.js';
14
15
  export interface MemoryAdapterOptions {
15
- /** Map of category/title to color */
16
- colorMap?: Record<string, string>;
17
16
  /**
18
- * Auto-assign colors to events by category or title.
19
- * true → use the default vivid palette
20
- * string → hex accent color (e.g. '#6366f1') to generate a
21
- * theme-harmonious palette via golden-angle hue rotation
17
+ * Custom color palette for auto-coloring events.
18
+ * Defaults to VIVID_PALETTE. Pass `generatePalette(accent)` to
19
+ * make event colors adapt to your theme.
22
20
  */
23
- autoColor?: boolean | string;
21
+ palette?: string[];
24
22
  }
25
23
  export declare function createMemoryAdapter(initial?: TimelineEvent[], options?: MemoryAdapterOptions): CalendarAdapter;
@@ -1,38 +1,23 @@
1
- import { generatePalette, VIVID_PALETTE } from '../core/palette.js';
1
+ import { VIVID_PALETTE } from '../core/palette.js';
2
2
  let counter = 0;
3
3
  function uid() {
4
4
  return `mem-${Date.now()}-${++counter}`;
5
5
  }
6
- /** Default palette for auto-coloring */
7
- const AUTO_COLORS = VIVID_PALETTE;
8
- export function createMemoryAdapter(initial = [], options = {}) {
9
- const { colorMap, autoColor } = options;
6
+ export function createMemoryAdapter(initial = [], options) {
10
7
  const events = [...initial];
11
- // Resolve palette: vivid default or theme-aware
12
- const palette = autoColor
13
- ? typeof autoColor === 'string'
14
- ? generatePalette(autoColor)
15
- : AUTO_COLORS
16
- : AUTO_COLORS;
17
- // Build auto-color assignments
8
+ const palette = options?.palette ?? VIVID_PALETTE;
9
+ // Auto-color: assign from vivid palette by category/title
18
10
  const colorAssignments = new Map();
19
11
  let colorIndex = 0;
20
12
  function resolveColor(ev) {
21
13
  if (ev.color)
22
14
  return ev.color;
23
- if (!colorMap && !autoColor)
24
- return undefined;
25
15
  const key = ev.category ?? ev.title;
26
- if (colorMap?.[key])
27
- return colorMap[key];
28
- if (autoColor) {
29
- if (!colorAssignments.has(key)) {
30
- colorAssignments.set(key, palette[colorIndex % palette.length]);
31
- colorIndex++;
32
- }
33
- return colorAssignments.get(key);
16
+ if (!colorAssignments.has(key)) {
17
+ colorAssignments.set(key, palette[colorIndex % palette.length]);
18
+ colorIndex++;
34
19
  }
35
- return undefined;
20
+ return colorAssignments.get(key);
36
21
  }
37
22
  function withColor(ev) {
38
23
  const color = resolveColor(ev);
@@ -63,19 +63,21 @@ export interface RecurringEvent {
63
63
  export interface RecurringAdapterOptions {
64
64
  /** Start weeks on Monday (default: true) */
65
65
  mondayStart?: boolean;
66
- /** Map of category/title to color */
67
- colorMap?: Record<string, string>;
68
66
  /**
69
- * Auto-assign colors to events by category or title.
70
- * true → use the default vivid palette
71
- * string → hex accent color to generate a harmonious palette
67
+ * Custom color palette for auto-coloring events.
68
+ * Pass `generatePalette('#yourAccent')` to get theme-harmonious colors,
69
+ * or provide your own array of hex strings.
70
+ * Defaults to the built-in vivid palette.
72
71
  */
73
- autoColor?: boolean | string;
72
+ palette?: string[];
74
73
  }
75
74
  /**
76
75
  * Create a CalendarAdapter that projects recurring events onto concrete
77
76
  * dates for whatever range the calendar requests.
78
77
  *
78
+ * Events without a `color` are auto-assigned one from a vivid palette,
79
+ * grouped by `category` or `title` so related events share a color.
80
+ *
79
81
  * Read-only by default — create/update/delete throw.
80
82
  */
81
83
  export declare function createRecurringAdapter(schedule: RecurringEvent[], options?: RecurringAdapterOptions): CalendarAdapter;
@@ -1,5 +1,5 @@
1
1
  import { startOfWeek, DAY_MS } from '../core/time.js';
2
- import { generatePalette, VIVID_PALETTE } from '../core/palette.js';
2
+ import { VIVID_PALETTE } from '../core/palette.js';
3
3
  // ── Helpers ─────────────────────────────────────────────
4
4
  /** Parse "HH:MM" into [hours, minutes] */
5
5
  function parseTime(time) {
@@ -46,14 +46,21 @@ function clampDayOfMonth(year, month, day) {
46
46
  const lastDay = new Date(year, month + 1, 0).getDate();
47
47
  return new Date(year, month, Math.min(day, lastDay));
48
48
  }
49
+ /** Format a Date as a compact "YYYYMMDD" key for stable instance IDs. */
50
+ function dateKey(d) {
51
+ const y = d.getFullYear();
52
+ const m = String(d.getMonth() + 1).padStart(2, '0');
53
+ const day = String(d.getDate()).padStart(2, '0');
54
+ return `${y}${m}${day}`;
55
+ }
49
56
  /** Create a concrete TimelineEvent from a recurring def + occurrence date */
50
- function createConcreteEvent(rec, date, instanceKey) {
57
+ function createConcreteEvent(rec, date) {
51
58
  const [sh, sm] = parseTime(rec.startTime);
52
59
  const [eh, em] = parseTime(rec.endTime);
53
60
  const start = new Date(date.getFullYear(), date.getMonth(), date.getDate(), sh, sm);
54
61
  const end = new Date(date.getFullYear(), date.getMonth(), date.getDate(), eh, em);
55
62
  return {
56
- id: `${rec.id}--${instanceKey}`,
63
+ id: `${rec.id}--${dateKey(date)}`,
57
64
  title: rec.title,
58
65
  start,
59
66
  end,
@@ -129,16 +136,14 @@ function projectDaily(rec, range, startDate, effectiveUntil, out) {
129
136
  if (cursor < rangeStart)
130
137
  cursor.setDate(cursor.getDate() + interval);
131
138
  }
132
- let idx = 0;
133
139
  while (cursor < range.end) {
134
140
  if (effectiveUntil && cursor > effectiveUntil)
135
141
  break;
136
- const ev = createConcreteEvent(rec, cursor, `d${idx}`);
142
+ const ev = createConcreteEvent(rec, cursor);
137
143
  if (ev.start < range.end && ev.end > range.start) {
138
144
  out.push(ev);
139
145
  }
140
146
  cursor.setDate(cursor.getDate() + interval);
141
- idx++;
142
147
  }
143
148
  }
144
149
  function projectWeekly(rec, range, startDate, effectiveUntil, mondayStart, out) {
@@ -165,7 +170,6 @@ function projectWeekly(rec, range, startDate, effectiveUntil, mondayStart, out)
165
170
  weekMs += interval * 7 * DAY_MS;
166
171
  }
167
172
  }
168
- let weekIndex = Math.round((weekMs - anchorWeekMs) / (7 * DAY_MS));
169
173
  while (weekMs < rangeEndMs) {
170
174
  for (const day of days) {
171
175
  const dayMs = weekMs + isoWeekdayToOffset(day) * DAY_MS;
@@ -176,13 +180,12 @@ function projectWeekly(rec, range, startDate, effectiveUntil, mondayStart, out)
176
180
  if (effectiveUntil && dayMs > effectiveUntil.getTime())
177
181
  return;
178
182
  const dayDate = new Date(dayMs);
179
- const ev = createConcreteEvent(rec, dayDate, `w${weekIndex}--d${day}`);
183
+ const ev = createConcreteEvent(rec, dayDate);
180
184
  if (ev.start < range.end && ev.end > range.start) {
181
185
  out.push(ev);
182
186
  }
183
187
  }
184
188
  weekMs += interval * 7 * DAY_MS;
185
- weekIndex += interval;
186
189
  }
187
190
  }
188
191
  function projectMonthly(rec, range, startDate, effectiveUntil, out) {
@@ -206,7 +209,7 @@ function projectMonthly(rec, range, startDate, effectiveUntil, out) {
206
209
  if (effectiveUntil && date > effectiveUntil)
207
210
  break;
208
211
  if (date >= range.start && (!startDate || date >= startDate)) {
209
- const ev = createConcreteEvent(rec, date, `m${y}-${String(m + 1).padStart(2, '0')}`);
212
+ const ev = createConcreteEvent(rec, date);
210
213
  if (ev.start < range.end && ev.end > range.start) {
211
214
  out.push(ev);
212
215
  }
@@ -216,34 +219,29 @@ function projectMonthly(rec, range, startDate, effectiveUntil, out) {
216
219
  }
217
220
  // ── Adapter factory ─────────────────────────────────────
218
221
  /** Default palette for auto-coloring */
219
- const AUTO_COLORS = VIVID_PALETTE;
222
+ const PALETTE = VIVID_PALETTE;
220
223
  /**
221
224
  * Create a CalendarAdapter that projects recurring events onto concrete
222
225
  * dates for whatever range the calendar requests.
223
226
  *
227
+ * Events without a `color` are auto-assigned one from a vivid palette,
228
+ * grouped by `category` or `title` so related events share a color.
229
+ *
224
230
  * Read-only by default — create/update/delete throw.
225
231
  */
226
232
  export function createRecurringAdapter(schedule, options = {}) {
227
- const { mondayStart = true, colorMap, autoColor } = options;
228
- // Resolve palette
229
- const palette = autoColor
230
- ? typeof autoColor === 'string'
231
- ? generatePalette(autoColor)
232
- : AUTO_COLORS
233
- : AUTO_COLORS;
234
- // Build auto-color assignments
233
+ const { mondayStart = true, palette } = options;
234
+ const colors = palette?.length ? palette : PALETTE;
235
+ // Auto-color: assign from palette by category/title
235
236
  const colorAssignments = new Map();
236
- if (autoColor || colorMap) {
237
- let colorIndex = 0;
238
- for (const rec of schedule) {
239
- const key = rec.category ?? rec.title;
240
- if (colorMap?.[key]) {
241
- colorAssignments.set(key, colorMap[key]);
242
- }
243
- else if (autoColor && !colorAssignments.has(key)) {
244
- colorAssignments.set(key, palette[colorIndex % palette.length]);
245
- colorIndex++;
246
- }
237
+ let colorIndex = 0;
238
+ for (const rec of schedule) {
239
+ if (rec.color)
240
+ continue;
241
+ const key = rec.category ?? rec.title;
242
+ if (!colorAssignments.has(key)) {
243
+ colorAssignments.set(key, colors[colorIndex % colors.length]);
244
+ colorIndex++;
247
245
  }
248
246
  }
249
247
  function resolveColor(rec) {