@nomideusz/svelte-calendar 0.3.1 → 0.5.1

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 (75) hide show
  1. package/README.md +193 -406
  2. package/dist/adapters/recurring.d.ts +45 -8
  3. package/dist/adapters/recurring.js +227 -49
  4. package/dist/adapters/rest.js +6 -1
  5. package/dist/calendar/Calendar.svelte +137 -29
  6. package/dist/calendar/Calendar.svelte.d.ts +10 -8
  7. package/dist/calendar/index.d.ts +0 -1
  8. package/dist/calendar/index.js +0 -1
  9. package/dist/core/index.d.ts +5 -4
  10. package/dist/core/index.js +2 -3
  11. package/dist/core/locale.d.ts +74 -0
  12. package/dist/core/locale.js +96 -4
  13. package/dist/core/time.d.ts +30 -0
  14. package/dist/core/time.js +42 -0
  15. package/dist/core/types.d.ts +1 -72
  16. package/dist/core/types.js +1 -8
  17. package/dist/engine/event-store.svelte.js +2 -2
  18. package/dist/engine/index.d.ts +1 -1
  19. package/dist/engine/view-state.svelte.d.ts +12 -6
  20. package/dist/engine/view-state.svelte.js +8 -4
  21. package/dist/index.d.ts +6 -7
  22. package/dist/index.js +4 -4
  23. package/dist/primitives/EmptySlot.svelte +6 -16
  24. package/dist/primitives/EventBlock.svelte +6 -19
  25. package/dist/primitives/NowIndicator.svelte +7 -4
  26. package/dist/primitives/TimeGutter.svelte +1 -1
  27. package/dist/theme/index.d.ts +1 -1
  28. package/dist/theme/index.js +1 -1
  29. package/dist/theme/presets.d.ts +11 -19
  30. package/dist/theme/presets.js +25 -111
  31. package/dist/views/agenda/Agenda.svelte +17 -1514
  32. package/dist/views/agenda/Agenda.svelte.d.ts +0 -13
  33. package/dist/views/agenda/AgendaDay.svelte +976 -0
  34. package/dist/views/agenda/AgendaDay.svelte.d.ts +14 -0
  35. package/dist/views/agenda/AgendaWeek.svelte +775 -0
  36. package/dist/views/agenda/AgendaWeek.svelte.d.ts +15 -0
  37. package/dist/views/agenda/index.d.ts +2 -0
  38. package/dist/views/agenda/index.js +2 -0
  39. package/dist/views/index.d.ts +2 -6
  40. package/dist/views/index.js +2 -6
  41. package/dist/views/planner/Planner.svelte +17 -0
  42. package/dist/views/planner/Planner.svelte.d.ts +7 -0
  43. package/dist/views/planner/PlannerDay.svelte +957 -0
  44. package/dist/views/{day/DayGrid.svelte.d.ts → planner/PlannerDay.svelte.d.ts} +8 -16
  45. package/dist/views/planner/PlannerWeek.svelte +826 -0
  46. package/dist/views/{week/WeekGrid.svelte.d.ts → planner/PlannerWeek.svelte.d.ts} +5 -9
  47. package/dist/views/planner/index.d.ts +1 -0
  48. package/dist/views/planner/index.js +1 -0
  49. package/dist/widget/CalendarWidget.svelte +54 -35
  50. package/dist/widget/CalendarWidget.svelte.d.ts +1 -1
  51. package/dist/widget/widget.d.ts +1 -7
  52. package/dist/widget/widget.js +44 -3
  53. package/package.json +5 -2
  54. package/widget/svelte-calendar.css +1 -0
  55. package/widget/widget.js +6 -144
  56. package/dist/calendar/Toolbar.svelte +0 -241
  57. package/dist/calendar/Toolbar.svelte.d.ts +0 -19
  58. package/dist/views/day/DayGrid.svelte +0 -1101
  59. package/dist/views/day/DayTimeline.svelte +0 -532
  60. package/dist/views/day/DayTimeline.svelte.d.ts +0 -4
  61. package/dist/views/day/index.d.ts +0 -2
  62. package/dist/views/day/index.js +0 -2
  63. package/dist/views/schedule/WeekSchedule.svelte +0 -133
  64. package/dist/views/schedule/WeekSchedule.svelte.d.ts +0 -38
  65. package/dist/views/schedule/index.d.ts +0 -1
  66. package/dist/views/schedule/index.js +0 -2
  67. package/dist/views/settings/Settings.svelte +0 -307
  68. package/dist/views/settings/Settings.svelte.d.ts +0 -23
  69. package/dist/views/settings/index.d.ts +0 -2
  70. package/dist/views/settings/index.js +0 -1
  71. package/dist/views/week/WeekGrid.svelte +0 -631
  72. package/dist/views/week/WeekHeatmap.svelte +0 -460
  73. package/dist/views/week/WeekHeatmap.svelte.d.ts +0 -8
  74. package/dist/views/week/index.d.ts +0 -2
  75. package/dist/views/week/index.js +0 -2
@@ -1,38 +0,0 @@
1
- import type { TimelineEvent } from '../../core/types.js';
2
- import type { RecurringEvent } from '../../adapters/recurring.js';
3
- interface Props {
4
- /** Concrete events (mutually exclusive with `schedule`) */
5
- events?: TimelineEvent[];
6
- /** Recurring weekly schedule (mutually exclusive with `events`) */
7
- schedule?: RecurringEvent[];
8
- /** CSS theme string */
9
- theme?: string;
10
- /** BCP 47 locale */
11
- locale?: string;
12
- /** Total height */
13
- height?: number;
14
- /** Start week on Monday */
15
- mondayStart?: boolean;
16
- /** Read-only mode (default: true for schedule display) */
17
- readOnly?: boolean;
18
- /** Visible hour range [startHour, endHour) */
19
- visibleHours?: [number, number];
20
- /** Show toolbar */
21
- showToolbar?: boolean;
22
- /** Show agenda view toggle */
23
- showAgenda?: boolean;
24
- /** Map of category/title to color */
25
- colorMap?: Record<string, string>;
26
- /** Auto-assign colors */
27
- autoColor?: boolean;
28
- /** Event click handler */
29
- oneventclick?: (event: TimelineEvent) => void;
30
- /** Event create handler (only works when readOnly is false) */
31
- oneventcreate?: (range: {
32
- start: Date;
33
- end: Date;
34
- }) => void;
35
- }
36
- declare const WeekSchedule: import("svelte").Component<Props, {}, "">;
37
- type WeekSchedule = ReturnType<typeof WeekSchedule>;
38
- export default WeekSchedule;
@@ -1 +0,0 @@
1
- export { default as WeekSchedule } from './WeekSchedule.svelte';
@@ -1,2 +0,0 @@
1
- // ─── Schedule views barrel export ───────────────────────
2
- export { default as WeekSchedule } from './WeekSchedule.svelte';
@@ -1,307 +0,0 @@
1
- <script lang="ts">
2
- import { slide } from 'svelte/transition';
3
- import type { PresetName } from '../../theme/presets.js';
4
- import { presets } from '../../theme/presets.js';
5
-
6
- /* ─── Field definition types ─────────────────────── */
7
- type RangeField = {
8
- key: string;
9
- label: string;
10
- type: 'range';
11
- min: number;
12
- max: number;
13
- step: number;
14
- };
15
-
16
- type ToggleField = {
17
- key: string;
18
- label: string;
19
- type: 'toggle';
20
- };
21
-
22
- export type SettingsField = RangeField | ToggleField;
23
-
24
- /* ─── Props ───────────────────────────────────────── */
25
- interface Props {
26
- fields: SettingsField[];
27
- values: Record<string, number | boolean>;
28
- theme: PresetName;
29
- }
30
-
31
- let { fields, values = $bindable(), theme = $bindable() }: Props = $props();
32
-
33
- const themeKeys: PresetName[] = ['midnight', 'parchment', 'indigo', 'neutral', 'bare'];
34
- const themeLabels: Record<PresetName, string> = {
35
- midnight: 'Midnight',
36
- parchment: 'Parchment',
37
- indigo: 'Indigo',
38
- neutral: 'Neutral',
39
- bare: 'Bare',
40
- };
41
- const themeAccents: Record<PresetName, string> = {
42
- midnight: '#ef4444',
43
- parchment: '#b85c2f',
44
- indigo: '#6366f1',
45
- neutral: '#94a0b4',
46
- bare: '#94a0b4',
47
- };
48
-
49
- let open = $state(true);
50
-
51
- function setVal(key: string, v: number | boolean) {
52
- values = { ...values, [key]: v };
53
- }
54
-
55
- function fmt(v: number | boolean): string {
56
- if (typeof v === 'boolean') return v ? 'true' : 'false';
57
- if (Number.isInteger(v)) return String(v);
58
- return v.toFixed(2);
59
- }
60
- </script>
61
-
62
- <div class="stg">
63
- <button class="stg-toggle" onclick={() => (open = !open)}>
64
- <svg class="stg-icon" class:stg-icon--open={open} viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round">
65
- <path d="M6 4l4 4-4 4" />
66
- </svg>
67
- <span>Settings</span>
68
- </button>
69
-
70
- {#if open}
71
- <div class="stg-body" transition:slide={{ duration: 180 }}>
72
- <!-- Theme picker -->
73
- <div class="stg-row">
74
- <span class="stg-label">Theme</span>
75
- <div class="stg-themes">
76
- {#each themeKeys as k (k)}
77
- <button
78
- class="stg-chip"
79
- class:stg-chip--active={theme === k}
80
- style="--chip-c: {themeAccents[k]}"
81
- onclick={() => (theme = k)}
82
- >
83
- <span class="stg-chip-dot"></span>
84
- {themeLabels[k]}
85
- </button>
86
- {/each}
87
- </div>
88
- </div>
89
-
90
- <!-- Dynamic fields -->
91
- {#each fields as f (f.key)}
92
- <div class="stg-row">
93
- <span class="stg-label">{f.label}</span>
94
- {#if f.type === 'range'}
95
- <div class="stg-slider-wrap">
96
- <input
97
- class="stg-slider"
98
- type="range"
99
- min={f.min}
100
- max={f.max}
101
- step={f.step}
102
- value={values[f.key]}
103
- oninput={(e) => setVal(f.key, Number((e.target as HTMLInputElement).value))}
104
- />
105
- <span class="stg-val">{fmt(values[f.key])}</span>
106
- </div>
107
- {:else if f.type === 'toggle'}
108
- <button
109
- class="stg-sw"
110
- class:stg-sw--on={values[f.key] === true}
111
- onclick={() => setVal(f.key, !values[f.key])}
112
- aria-pressed={values[f.key] === true}
113
- aria-label={f.label}
114
- >
115
- <span class="stg-sw-knob"></span>
116
- </button>
117
- {/if}
118
- </div>
119
- {/each}
120
- </div>
121
- {/if}
122
- </div>
123
-
124
- <style>
125
- .stg {
126
- border: 1px solid rgba(148, 160, 180, 0.06);
127
- border-radius: 10px;
128
- background: rgba(148, 160, 180, 0.02);
129
- overflow: hidden;
130
- margin-bottom: 20px;
131
- }
132
-
133
- /* ─── Toggle header ──────────────────────────────── */
134
- .stg-toggle {
135
- display: flex;
136
- align-items: center;
137
- gap: 6px;
138
- width: 100%;
139
- padding: 10px 14px;
140
- background: none;
141
- border: none;
142
- cursor: pointer;
143
- font: 500 10px / 1 'Outfit', system-ui, sans-serif;
144
- letter-spacing: 0.08em;
145
- text-transform: uppercase;
146
- color: rgba(148, 160, 180, 0.4);
147
- transition: color 120ms;
148
- }
149
- .stg-toggle:hover {
150
- color: rgba(220, 225, 235, 0.7);
151
- }
152
-
153
- .stg-icon {
154
- width: 12px;
155
- height: 12px;
156
- transition: transform 160ms ease;
157
- flex-shrink: 0;
158
- }
159
- .stg-icon--open {
160
- transform: rotate(90deg);
161
- }
162
-
163
- /* ─── Body ────────────────────────────────────────── */
164
- .stg-body {
165
- padding: 2px 14px 14px;
166
- display: flex;
167
- flex-direction: column;
168
- gap: 10px;
169
- }
170
-
171
- /* ─── Row ─────────────────────────────────────────── */
172
- .stg-row {
173
- display: flex;
174
- align-items: center;
175
- gap: 12px;
176
- min-height: 28px;
177
- }
178
- .stg-label {
179
- flex-shrink: 0;
180
- width: 100px;
181
- font: 400 10px / 1 'SF Mono', 'Cascadia Code', 'Fira Code', Consolas, monospace;
182
- color: rgba(148, 160, 180, 0.35);
183
- white-space: nowrap;
184
- }
185
-
186
- /* ─── Theme chips ────────────────────────────────── */
187
- .stg-themes {
188
- display: flex;
189
- gap: 6px;
190
- flex-wrap: wrap;
191
- }
192
- .stg-chip {
193
- display: inline-flex;
194
- align-items: center;
195
- gap: 5px;
196
- padding: 4px 10px;
197
- border-radius: 100px;
198
- border: 1px solid rgba(148, 160, 180, 0.08);
199
- background: rgba(148, 160, 180, 0.03);
200
- cursor: pointer;
201
- font: 400 10px / 1 'Outfit', system-ui, sans-serif;
202
- color: rgba(148, 160, 180, 0.4);
203
- transition: border-color 140ms, background 140ms, color 140ms;
204
- }
205
- .stg-chip:hover {
206
- border-color: rgba(148, 160, 180, 0.15);
207
- color: rgba(220, 225, 235, 0.6);
208
- }
209
- .stg-chip--active {
210
- border-color: var(--chip-c);
211
- background: color-mix(in srgb, var(--chip-c) 8%, transparent);
212
- color: var(--chip-c);
213
- }
214
- .stg-chip-dot {
215
- width: 7px;
216
- height: 7px;
217
- border-radius: 50%;
218
- background: var(--chip-c);
219
- opacity: 0.6;
220
- }
221
- .stg-chip--active .stg-chip-dot {
222
- opacity: 1;
223
- box-shadow: 0 0 6px var(--chip-c);
224
- }
225
-
226
- /* ─── Range slider ───────────────────────────────── */
227
- .stg-slider-wrap {
228
- flex: 1;
229
- display: flex;
230
- align-items: center;
231
- gap: 10px;
232
- }
233
- .stg-slider {
234
- flex: 1;
235
- -webkit-appearance: none;
236
- appearance: none;
237
- height: 3px;
238
- border-radius: 2px;
239
- background: rgba(148, 160, 180, 0.1);
240
- outline: none;
241
- cursor: pointer;
242
- }
243
- .stg-slider::-webkit-slider-thumb {
244
- -webkit-appearance: none;
245
- width: 14px;
246
- height: 14px;
247
- border-radius: 50%;
248
- background: rgba(220, 225, 235, 0.5);
249
- border: 2px solid rgba(220, 225, 235, 0.15);
250
- cursor: grab;
251
- transition: background 100ms, transform 100ms;
252
- }
253
- .stg-slider::-webkit-slider-thumb:hover {
254
- background: rgba(220, 225, 235, 0.7);
255
- transform: scale(1.15);
256
- }
257
- .stg-slider::-webkit-slider-thumb:active {
258
- cursor: grabbing;
259
- }
260
- .stg-slider::-moz-range-thumb {
261
- width: 14px;
262
- height: 14px;
263
- border-radius: 50%;
264
- background: rgba(220, 225, 235, 0.5);
265
- border: 2px solid rgba(220, 225, 235, 0.15);
266
- cursor: grab;
267
- }
268
- .stg-val {
269
- flex-shrink: 0;
270
- min-width: 38px;
271
- text-align: right;
272
- font: 500 10px / 1 'SF Mono', 'Cascadia Code', monospace;
273
- color: rgba(220, 225, 235, 0.45);
274
- font-variant-numeric: tabular-nums;
275
- }
276
-
277
- /* ─── Toggle switch ──────────────────────────────── */
278
- .stg-sw {
279
- position: relative;
280
- width: 34px;
281
- height: 18px;
282
- border-radius: 9px;
283
- border: 1px solid rgba(148, 160, 180, 0.12);
284
- background: rgba(148, 160, 180, 0.08);
285
- cursor: pointer;
286
- padding: 0;
287
- transition: background 160ms, border-color 160ms;
288
- }
289
- .stg-sw--on {
290
- background: rgba(99, 102, 241, 0.25);
291
- border-color: rgba(99, 102, 241, 0.35);
292
- }
293
- .stg-sw-knob {
294
- position: absolute;
295
- top: 2px;
296
- left: 2px;
297
- width: 12px;
298
- height: 12px;
299
- border-radius: 50%;
300
- background: rgba(148, 160, 180, 0.4);
301
- transition: transform 160ms ease, background 160ms;
302
- }
303
- .stg-sw--on .stg-sw-knob {
304
- transform: translateX(16px);
305
- background: rgba(99, 102, 241, 0.9);
306
- }
307
- </style>
@@ -1,23 +0,0 @@
1
- import type { PresetName } from '../../theme/presets.js';
2
- type RangeField = {
3
- key: string;
4
- label: string;
5
- type: 'range';
6
- min: number;
7
- max: number;
8
- step: number;
9
- };
10
- type ToggleField = {
11
- key: string;
12
- label: string;
13
- type: 'toggle';
14
- };
15
- export type SettingsField = RangeField | ToggleField;
16
- interface Props {
17
- fields: SettingsField[];
18
- values: Record<string, number | boolean>;
19
- theme: PresetName;
20
- }
21
- declare const Settings: import("svelte").Component<Props, {}, "values" | "theme">;
22
- type Settings = ReturnType<typeof Settings>;
23
- export default Settings;
@@ -1,2 +0,0 @@
1
- export { default as Settings } from './Settings.svelte';
2
- export type { SettingsField } from './Settings.svelte';
@@ -1 +0,0 @@
1
- export { default as Settings } from './Settings.svelte';