@nomideusz/svelte-calendar 0.6.3 → 0.6.5

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 (47) hide show
  1. package/README.md +192 -10
  2. package/dist/adapters/composite.d.ts +15 -0
  3. package/dist/adapters/composite.js +65 -0
  4. package/dist/adapters/index.d.ts +5 -1
  5. package/dist/adapters/index.js +2 -0
  6. package/dist/adapters/mapped.d.ts +170 -0
  7. package/dist/adapters/mapped.js +343 -0
  8. package/dist/adapters/recurring.d.ts +4 -0
  9. package/dist/adapters/recurring.js +5 -10
  10. package/dist/adapters/types.d.ts +11 -2
  11. package/dist/assets/favicon.svg +9 -1
  12. package/dist/calendar/Calendar.svelte +161 -90
  13. package/dist/calendar/Calendar.svelte.d.ts +12 -0
  14. package/dist/core/index.d.ts +3 -1
  15. package/dist/core/index.js +2 -0
  16. package/dist/core/measure.d.ts +104 -0
  17. package/dist/core/measure.js +195 -0
  18. package/dist/core/time.js +2 -2
  19. package/dist/core/types.d.ts +32 -0
  20. package/dist/engine/event-store.svelte.js +22 -7
  21. package/dist/headless/create-agenda.svelte.d.ts +67 -0
  22. package/dist/headless/create-agenda.svelte.js +139 -0
  23. package/dist/headless/create-calendar.svelte.d.ts +2 -0
  24. package/dist/headless/create-calendar.svelte.js +380 -0
  25. package/dist/headless/index.d.ts +4 -0
  26. package/dist/headless/index.js +2 -0
  27. package/dist/headless/types.d.ts +219 -0
  28. package/dist/headless/types.js +1 -0
  29. package/dist/index.d.ts +6 -4
  30. package/dist/index.js +4 -2
  31. package/dist/primitives/DayHeader.svelte +6 -6
  32. package/dist/primitives/EmptySlot.svelte +3 -3
  33. package/dist/primitives/EventBlock.svelte +99 -14
  34. package/dist/primitives/NowIndicator.svelte +5 -5
  35. package/dist/views/agenda/AgendaDay.svelte +215 -116
  36. package/dist/views/agenda/AgendaWeek.svelte +166 -113
  37. package/dist/views/mobile/MobileDay.svelte +45 -21
  38. package/dist/views/mobile/MobileWeek.svelte +85 -35
  39. package/dist/views/planner/PlannerDay.svelte +116 -60
  40. package/dist/views/planner/PlannerWeek.svelte +228 -166
  41. package/dist/views/shared/context.svelte.d.ts +47 -0
  42. package/dist/views/shared/context.svelte.js +47 -0
  43. package/dist/views/shared/format.d.ts +19 -0
  44. package/dist/views/shared/format.js +46 -0
  45. package/dist/views/shared/index.d.ts +4 -0
  46. package/dist/views/shared/index.js +2 -0
  47. package/package.json +9 -2
@@ -61,7 +61,7 @@
61
61
  }
62
62
 
63
63
  .dh-name {
64
- font: 500 10px / 1 var(--dt-sans, 'Outfit', system-ui, sans-serif);
64
+ font: 500 10px / 1 var(--dt-sans, system-ui, sans-serif);
65
65
  letter-spacing: 0.04em;
66
66
  text-transform: uppercase;
67
67
  color: var(--dt-text-2, rgba(148, 163, 184, 0.55));
@@ -74,7 +74,7 @@
74
74
  }
75
75
 
76
76
  .dh-num {
77
- font: 600 14px / 1 var(--dt-sans, 'Outfit', system-ui, sans-serif);
77
+ font: 600 14px / 1 var(--dt-sans, system-ui, sans-serif);
78
78
  color: var(--dt-text, rgba(226, 232, 240, 0.85));
79
79
  width: 28px;
80
80
  height: 28px;
@@ -84,20 +84,20 @@
84
84
  border-radius: 50%;
85
85
  }
86
86
  .dh-num-today {
87
- background: var(--dt-accent, #ef4444);
87
+ background: var(--dt-accent, #2563eb);
88
88
  color: var(--dt-btn-text, #fff);
89
89
  }
90
90
 
91
91
  .dh-date {
92
- font: 400 10px / 1 var(--dt-sans, 'Outfit', system-ui, sans-serif);
92
+ font: 400 10px / 1 var(--dt-sans, system-ui, sans-serif);
93
93
  color: var(--dt-text-2, rgba(148, 163, 184, 0.55));
94
94
  }
95
95
 
96
96
  .dh-rel {
97
- font: 500 12px / 1.3 var(--dt-sans, 'Outfit', system-ui, sans-serif);
97
+ font: 500 12px / 1.3 var(--dt-sans, system-ui, sans-serif);
98
98
  color: var(--dt-text, rgba(226, 232, 240, 0.85));
99
99
  }
100
100
  .dh-today .dh-rel {
101
- color: var(--dt-accent, #ef4444);
101
+ color: var(--dt-accent, #2563eb);
102
102
  }
103
103
  </style>
@@ -68,7 +68,7 @@
68
68
  background: var(--dt-accent-dim, rgba(239, 68, 68, 0.05));
69
69
  }
70
70
  .es:focus-visible {
71
- outline: 2px solid var(--dt-accent, #ef4444);
71
+ outline: 2px solid var(--dt-accent, #2563eb);
72
72
  outline-offset: 2px;
73
73
  border-color: var(--dt-accent-dim, rgba(239, 68, 68, 0.18));
74
74
  }
@@ -88,8 +88,8 @@
88
88
  }
89
89
 
90
90
  .es-plus {
91
- font: 500 14px / 1 var(--dt-sans, 'Outfit', system-ui, sans-serif);
92
- color: var(--dt-accent, #ef4444);
91
+ font: 500 14px / 1 var(--dt-sans, system-ui, sans-serif);
92
+ color: var(--dt-accent, #2563eb);
93
93
  }
94
94
  .es-range {
95
95
  font: 400 10px / 1 var(--dt-mono, 'SF Mono', monospace);
@@ -47,14 +47,20 @@
47
47
  children,
48
48
  }: Props = $props();
49
49
 
50
- const accentColor = $derived(event.color || 'var(--dt-accent, #ef4444)');
50
+ const accentColor = $derived(event.color || 'var(--dt-accent, #2563eb)');
51
+ const isCancelled = $derived(event.status === 'cancelled');
52
+ const isTentative = $derived(event.status === 'tentative');
53
+ const isFull = $derived(event.status === 'full');
54
+ const isLimited = $derived(event.status === 'limited');
51
55
 
52
56
  const ariaLabel = $derived.by(() => {
53
57
  const t = event.title;
54
58
  const time = `${fmtTime(event.start)} to ${fmtTime(event.end)}`;
55
59
  const dur = fmtDuration(event.start, event.end);
56
- const status = active ? `, ${L.happeningNow}` : past ? `, ${L.past}` : '';
57
- return `${t}, ${time}, ${dur}${status}`;
60
+ const loc = event.location ? `, ${event.location}` : '';
61
+ const statusStr = isCancelled ? ', cancelled' : isTentative ? ', tentative' : isFull ? ', full' : isLimited ? ', limited' : '';
62
+ const activeStr = active ? `, ${L.happeningNow}` : past ? `, ${L.past}` : '';
63
+ return `${t}${loc}, ${time}, ${dur}${statusStr}${activeStr}`;
58
64
  });
59
65
 
60
66
  function handleKeydown(e: KeyboardEvent) {
@@ -79,6 +85,9 @@
79
85
  {#if event.subtitle}
80
86
  <span class="eb-subtitle">{event.subtitle}</span>
81
87
  {/if}
88
+ {#if event.location}
89
+ <span class="eb-location">📍 {event.location}</span>
90
+ {/if}
82
91
  {#if showTime}
83
92
  <span class="eb-time">{fmtTime(event.start)} – {fmtTime(event.end)}</span>
84
93
  {/if}
@@ -92,6 +101,10 @@
92
101
  {/each}
93
102
  </div>
94
103
  {/if}
104
+ {#if isCancelled}<span class="eb-status-badge eb-cancelled-badge">Cancelled</span>{/if}
105
+ {#if isTentative}<span class="eb-status-badge eb-tentative-badge">Tentative</span>{/if}
106
+ {#if isFull}<span class="eb-status-badge eb-full-badge">Full</span>{/if}
107
+ {#if isLimited}<span class="eb-status-badge eb-limited-badge">Limited</span>{/if}
95
108
  {#if active}<span class="eb-live-badge">{L.now}</span>{/if}
96
109
  </div>
97
110
  {:else}
@@ -102,6 +115,9 @@
102
115
  {#if event.subtitle}
103
116
  <span class="eb-subtitle">{event.subtitle}</span>
104
117
  {/if}
118
+ {#if event.location}
119
+ <span class="eb-location">📍 {event.location}</span>
120
+ {/if}
105
121
  {#if showDuration}
106
122
  <span class="eb-dur">{fmtDuration(event.start, event.end)}</span>
107
123
  {/if}
@@ -112,6 +128,9 @@
112
128
  {/each}
113
129
  </span>
114
130
  {/if}
131
+ {#if isCancelled}<span class="eb-status-badge eb-cancelled-badge">Cancelled</span>{/if}
132
+ {#if isFull}<span class="eb-status-badge eb-full-badge">Full</span>{/if}
133
+ {#if isLimited}<span class="eb-status-badge eb-limited-badge">Limited</span>{/if}
115
134
  {#if active}<span class="eb-live-badge">{L.now}</span>{/if}
116
135
  {/if}
117
136
  {/snippet}
@@ -121,6 +140,10 @@
121
140
  class="eb eb-{variant}"
122
141
  class:eb-active={active}
123
142
  class:eb-past={past}
143
+ class:eb-cancelled={isCancelled}
144
+ class:eb-tentative={isTentative}
145
+ class:eb-full={isFull}
146
+ class:eb-limited={isLimited}
124
147
  class:eb-editable={editable}
125
148
  style="--eb-color: {accentColor}"
126
149
  role="button"
@@ -137,6 +160,10 @@
137
160
  class="eb eb-{variant}"
138
161
  class:eb-active={active}
139
162
  class:eb-past={past}
163
+ class:eb-cancelled={isCancelled}
164
+ class:eb-tentative={isTentative}
165
+ class:eb-full={isFull}
166
+ class:eb-limited={isLimited}
140
167
  class:eb-editable={editable}
141
168
  style="--eb-color: {accentColor}"
142
169
  role="article"
@@ -149,7 +176,7 @@
149
176
 
150
177
  <style>
151
178
  .eb {
152
- --_color: var(--eb-color, var(--dt-accent, #ef4444));
179
+ --_color: var(--eb-color, var(--dt-accent, #2563eb));
153
180
  cursor: default;
154
181
  transition: opacity 120ms, transform 80ms;
155
182
  }
@@ -160,20 +187,45 @@
160
187
  transform: translateY(-1px);
161
188
  }
162
189
  .eb:focus-visible {
163
- outline: 2px solid var(--dt-accent, #ef4444);
190
+ outline: 2px solid var(--dt-accent, #2563eb);
164
191
  outline-offset: 2px;
165
192
  border-radius: 4px;
166
193
  }
167
194
  .eb-past {
168
195
  opacity: 0.5;
169
196
  }
197
+ .eb-cancelled {
198
+ opacity: 0.45;
199
+ }
200
+ .eb-cancelled .eb-title {
201
+ text-decoration: line-through;
202
+ }
203
+ .eb-tentative {
204
+ opacity: 0.7;
205
+ }
206
+ .eb-tentative .eb-stripe {
207
+ background: repeating-linear-gradient(
208
+ 45deg,
209
+ var(--_color),
210
+ var(--_color) 2px,
211
+ transparent 2px,
212
+ transparent 4px
213
+ );
214
+ }
215
+ .eb-full {
216
+ opacity: 0.55;
217
+ }
218
+ .eb-limited .eb-stripe {
219
+ border-left: 2px dashed var(--_color);
220
+ background: none;
221
+ }
170
222
 
171
223
  /* ── Chip ── */
172
224
  .eb-chip {
173
225
  display: inline-flex;
174
226
  align-items: center;
175
227
  gap: 5px;
176
- font: 400 11px / 1 var(--dt-sans, 'Outfit', system-ui, sans-serif);
228
+ font: 400 11px / 1 var(--dt-sans, system-ui, sans-serif);
177
229
  color: var(--dt-text, rgba(226, 232, 240, 0.85));
178
230
  white-space: nowrap;
179
231
  overflow: hidden;
@@ -200,7 +252,7 @@
200
252
  .eb-card {
201
253
  display: flex;
202
254
  border-radius: 8px;
203
- background: var(--dt-surface, #10141c);
255
+ background: var(--dt-surface, var(--dt-bg, #ffffff));
204
256
  border: 1px solid var(--dt-border, rgba(148, 163, 184, 0.07));
205
257
  overflow: hidden;
206
258
  }
@@ -217,7 +269,7 @@
217
269
  min-width: 0;
218
270
  }
219
271
  .eb-card .eb-title {
220
- font: 500 12px / 1.3 var(--dt-sans, 'Outfit', system-ui, sans-serif);
272
+ font: 500 12px / 1.3 var(--dt-sans, system-ui, sans-serif);
221
273
  color: var(--dt-text, rgba(226, 232, 240, 0.85));
222
274
  overflow: hidden;
223
275
  text-overflow: ellipsis;
@@ -228,7 +280,7 @@
228
280
  color: var(--dt-text-2, rgba(148, 163, 184, 0.55));
229
281
  }
230
282
  .eb-card .eb-dur {
231
- font: 300 10px / 1 var(--dt-sans, 'Outfit', system-ui, sans-serif);
283
+ font: 300 10px / 1 var(--dt-sans, system-ui, sans-serif);
232
284
  color: var(--dt-text-3, rgba(100, 116, 139, 0.55));
233
285
  }
234
286
 
@@ -255,7 +307,7 @@
255
307
  width: 90px;
256
308
  }
257
309
  .eb-row .eb-title {
258
- font: 400 12px / 1.3 var(--dt-sans, 'Outfit', system-ui, sans-serif);
310
+ font: 400 12px / 1.3 var(--dt-sans, system-ui, sans-serif);
259
311
  color: var(--dt-text, rgba(226, 232, 240, 0.85));
260
312
  flex: 1;
261
313
  overflow: hidden;
@@ -263,14 +315,14 @@
263
315
  white-space: nowrap;
264
316
  }
265
317
  .eb-row .eb-dur {
266
- font: 300 10px / 1 var(--dt-sans, 'Outfit', system-ui, sans-serif);
318
+ font: 300 10px / 1 var(--dt-sans, system-ui, sans-serif);
267
319
  color: var(--dt-text-3, rgba(100, 116, 139, 0.55));
268
320
  flex-shrink: 0;
269
321
  }
270
322
 
271
323
  /* ── Shared ── */
272
324
  .eb-subtitle {
273
- font: 400 10px / 1.2 var(--dt-sans, 'Outfit', system-ui, sans-serif);
325
+ font: 400 10px / 1.2 var(--dt-sans, system-ui, sans-serif);
274
326
  color: var(--dt-text-2, rgba(148, 163, 184, 0.65));
275
327
  overflow: hidden;
276
328
  text-overflow: ellipsis;
@@ -283,7 +335,7 @@
283
335
  }
284
336
  .eb-tag {
285
337
  display: inline-block;
286
- font: 500 8px / 1 var(--dt-sans, 'Outfit', system-ui, sans-serif);
338
+ font: 500 8px / 1 var(--dt-sans, system-ui, sans-serif);
287
339
  letter-spacing: 0.04em;
288
340
  text-transform: uppercase;
289
341
  padding: 2px 5px;
@@ -291,10 +343,43 @@
291
343
  background: color-mix(in srgb, var(--_color) 18%, transparent);
292
344
  color: var(--_color);
293
345
  }
346
+ .eb-location {
347
+ font: 400 9px / 1.2 var(--dt-sans, system-ui, sans-serif);
348
+ color: var(--dt-text-3, rgba(100, 116, 139, 0.55));
349
+ overflow: hidden;
350
+ text-overflow: ellipsis;
351
+ white-space: nowrap;
352
+ }
353
+ .eb-status-badge {
354
+ display: inline-flex;
355
+ align-items: center;
356
+ font: 700 8px / 1 var(--dt-sans, system-ui, sans-serif);
357
+ letter-spacing: 0.06em;
358
+ text-transform: uppercase;
359
+ padding: 2px 6px;
360
+ border-radius: 3px;
361
+ width: fit-content;
362
+ }
363
+ .eb-cancelled-badge {
364
+ color: var(--dt-text-2, rgba(148, 163, 184, 0.65));
365
+ background: color-mix(in srgb, var(--dt-text-2, rgba(148, 163, 184, 0.3)) 15%, transparent);
366
+ }
367
+ .eb-tentative-badge {
368
+ color: var(--_color);
369
+ background: color-mix(in srgb, var(--_color) 12%, transparent);
370
+ }
371
+ .eb-full-badge {
372
+ color: #2563eb;
373
+ background: color-mix(in srgb, #2563eb 15%, transparent);
374
+ }
375
+ .eb-limited-badge {
376
+ color: var(--_color);
377
+ background: color-mix(in srgb, var(--_color) 12%, transparent);
378
+ }
294
379
  .eb-live-badge {
295
380
  display: inline-flex;
296
381
  align-items: center;
297
- font: 700 8px / 1 var(--dt-sans, 'Outfit', system-ui, sans-serif);
382
+ font: 700 8px / 1 var(--dt-sans, system-ui, sans-serif);
298
383
  letter-spacing: 0.08em;
299
384
  text-transform: uppercase;
300
385
  color: var(--dt-btn-text, #fff);
@@ -104,7 +104,7 @@
104
104
  height: 0;
105
105
  }
106
106
  .ni-line-bar {
107
- background: var(--ni-color, var(--dt-accent, #ef4444));
107
+ background: var(--ni-color, var(--dt-accent, #2563eb));
108
108
  }
109
109
  .ni-line.vertical .ni-line-bar {
110
110
  width: 2px;
@@ -122,7 +122,7 @@
122
122
  width: 10px;
123
123
  height: 10px;
124
124
  border-radius: 50%;
125
- background: var(--ni-color, var(--dt-accent, #ef4444));
125
+ background: var(--ni-color, var(--dt-accent, #2563eb));
126
126
  box-shadow: 0 0 6px var(--ni-color, var(--dt-glow, rgba(239, 68, 68, 0.35)));
127
127
  }
128
128
  .ni-dot.vertical .ni-dot-circle {
@@ -138,7 +138,7 @@
138
138
  white-space: nowrap;
139
139
  font: 600 10px / 1 var(--dt-mono, 'SF Mono', 'Fira Code', monospace);
140
140
  color: var(--dt-btn-text, #fff);
141
- background: var(--ni-color, var(--dt-accent, #ef4444));
141
+ background: var(--ni-color, var(--dt-accent, #2563eb));
142
142
  padding: 3px 6px;
143
143
  border-radius: 4px;
144
144
  }
@@ -161,11 +161,11 @@
161
161
  .ni-badge {
162
162
  display: inline-flex;
163
163
  align-items: center;
164
- font: 700 9px / 1 var(--dt-sans, 'Outfit', system-ui, sans-serif);
164
+ font: 700 9px / 1 var(--dt-sans, system-ui, sans-serif);
165
165
  letter-spacing: 0.08em;
166
166
  text-transform: uppercase;
167
167
  color: var(--dt-btn-text, #fff);
168
- background: var(--ni-color, var(--dt-accent, #ef4444));
168
+ background: var(--ni-color, var(--dt-accent, #2563eb));
169
169
  padding: 2px 7px;
170
170
  border-radius: 3px;
171
171
  animation: ni-pulse 2s ease-in-out infinite;