@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.
- package/README.md +193 -406
- package/dist/adapters/recurring.d.ts +45 -8
- package/dist/adapters/recurring.js +227 -49
- package/dist/adapters/rest.js +6 -1
- package/dist/calendar/Calendar.svelte +137 -29
- package/dist/calendar/Calendar.svelte.d.ts +10 -8
- package/dist/calendar/index.d.ts +0 -1
- package/dist/calendar/index.js +0 -1
- package/dist/core/index.d.ts +5 -4
- package/dist/core/index.js +2 -3
- package/dist/core/locale.d.ts +74 -0
- package/dist/core/locale.js +96 -4
- package/dist/core/time.d.ts +30 -0
- package/dist/core/time.js +42 -0
- package/dist/core/types.d.ts +1 -72
- package/dist/core/types.js +1 -8
- package/dist/engine/event-store.svelte.js +2 -2
- package/dist/engine/index.d.ts +1 -1
- package/dist/engine/view-state.svelte.d.ts +12 -6
- package/dist/engine/view-state.svelte.js +8 -4
- package/dist/index.d.ts +6 -7
- package/dist/index.js +4 -4
- package/dist/primitives/EmptySlot.svelte +6 -16
- package/dist/primitives/EventBlock.svelte +6 -19
- package/dist/primitives/NowIndicator.svelte +7 -4
- package/dist/primitives/TimeGutter.svelte +1 -1
- package/dist/theme/index.d.ts +1 -1
- package/dist/theme/index.js +1 -1
- package/dist/theme/presets.d.ts +11 -19
- package/dist/theme/presets.js +25 -111
- package/dist/views/agenda/Agenda.svelte +17 -1514
- package/dist/views/agenda/Agenda.svelte.d.ts +0 -13
- package/dist/views/agenda/AgendaDay.svelte +976 -0
- package/dist/views/agenda/AgendaDay.svelte.d.ts +14 -0
- package/dist/views/agenda/AgendaWeek.svelte +775 -0
- package/dist/views/agenda/AgendaWeek.svelte.d.ts +15 -0
- package/dist/views/agenda/index.d.ts +2 -0
- package/dist/views/agenda/index.js +2 -0
- package/dist/views/index.d.ts +2 -6
- package/dist/views/index.js +2 -6
- package/dist/views/planner/Planner.svelte +17 -0
- package/dist/views/planner/Planner.svelte.d.ts +7 -0
- package/dist/views/planner/PlannerDay.svelte +957 -0
- package/dist/views/{day/DayGrid.svelte.d.ts → planner/PlannerDay.svelte.d.ts} +8 -16
- package/dist/views/planner/PlannerWeek.svelte +826 -0
- package/dist/views/{week/WeekGrid.svelte.d.ts → planner/PlannerWeek.svelte.d.ts} +5 -9
- package/dist/views/planner/index.d.ts +1 -0
- package/dist/views/planner/index.js +1 -0
- package/dist/widget/CalendarWidget.svelte +54 -35
- package/dist/widget/CalendarWidget.svelte.d.ts +1 -1
- package/dist/widget/widget.d.ts +1 -7
- package/dist/widget/widget.js +44 -3
- package/package.json +5 -2
- package/widget/svelte-calendar.css +1 -0
- package/widget/widget.js +6 -144
- package/dist/calendar/Toolbar.svelte +0 -241
- package/dist/calendar/Toolbar.svelte.d.ts +0 -19
- package/dist/views/day/DayGrid.svelte +0 -1101
- package/dist/views/day/DayTimeline.svelte +0 -532
- package/dist/views/day/DayTimeline.svelte.d.ts +0 -4
- package/dist/views/day/index.d.ts +0 -2
- package/dist/views/day/index.js +0 -2
- package/dist/views/schedule/WeekSchedule.svelte +0 -133
- package/dist/views/schedule/WeekSchedule.svelte.d.ts +0 -38
- package/dist/views/schedule/index.d.ts +0 -1
- package/dist/views/schedule/index.js +0 -2
- package/dist/views/settings/Settings.svelte +0 -307
- package/dist/views/settings/Settings.svelte.d.ts +0 -23
- package/dist/views/settings/index.d.ts +0 -2
- package/dist/views/settings/index.js +0 -1
- package/dist/views/week/WeekGrid.svelte +0 -631
- package/dist/views/week/WeekHeatmap.svelte +0 -460
- package/dist/views/week/WeekHeatmap.svelte.d.ts +0 -8
- package/dist/views/week/index.d.ts +0 -2
- 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,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 +0,0 @@
|
|
|
1
|
-
export { default as Settings } from './Settings.svelte';
|