accomadesc 0.4.7 → 0.4.9
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/dist/basic/Icon.svelte +3 -1
- package/package.json +2 -2
- package/dist/occusplan-link/OccuPlanAvailableInfo.svelte +0 -43
- package/dist/occusplan-link/OccuPlanGrid.svelte +0 -383
- package/dist/occusplan-link/OccuPlanPicker.svelte +0 -584
- package/dist/occusplan-link/OccuPlanRows.svelte +0 -376
- package/dist/occusplan-link/OccuPlanWrapper.svelte +0 -120
- package/dist/occusplan-link/defaultTranslations.js +0 -157
- package/dist/occusplan-link/state.svelte.d.ts +0 -94
- package/dist/occusplan-link/state.svelte.js +0 -413
package/dist/basic/Icon.svelte
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
height?: string;
|
|
14
14
|
filter?: string;
|
|
15
15
|
} = $props();
|
|
16
|
+
|
|
17
|
+
const icon = $derived(getIcon(iconName, color));
|
|
16
18
|
</script>
|
|
17
19
|
|
|
18
20
|
<div
|
|
@@ -23,5 +25,5 @@
|
|
|
23
25
|
{filter ? `filter: ${filter};` : ''}
|
|
24
26
|
"
|
|
25
27
|
>
|
|
26
|
-
{@html
|
|
28
|
+
{@html icon}
|
|
27
29
|
</div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "accomadesc",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.9",
|
|
4
4
|
"files": [
|
|
5
5
|
"dist",
|
|
6
6
|
"!dist/**/*.test.*",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"prettier": "^3.8.1",
|
|
42
42
|
"prettier-plugin-svelte": "^3.5.1",
|
|
43
43
|
"publint": "^0.3.18",
|
|
44
|
-
"svelte": "^5.53.
|
|
44
|
+
"svelte": "^5.53.12",
|
|
45
45
|
"svelte-check": "^4.4.5",
|
|
46
46
|
"typescript": "^5.9.3",
|
|
47
47
|
"vite": "^6.4.1",
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { DateTime } from 'luxon';
|
|
3
|
-
import { normalizeDate } from '../helpers/normalizeDate.js';
|
|
4
|
-
import { getContext, onMount, untrack, setContext, type Snippet } from 'svelte';
|
|
5
|
-
import { OccupationState, contextKey, type AvailableSpans } from '../occuplan/state.svelte.js';
|
|
6
|
-
import Spinner from '../basic/Spinner.svelte';
|
|
7
|
-
|
|
8
|
-
let {
|
|
9
|
-
url,
|
|
10
|
-
debug = false,
|
|
11
|
-
search = [3, 7, 14],
|
|
12
|
-
maxFutureDate = normalizeDate(DateTime.utc().plus({ years: 1 })),
|
|
13
|
-
children,
|
|
14
|
-
}: {
|
|
15
|
-
url: string;
|
|
16
|
-
debug?: boolean | undefined;
|
|
17
|
-
search?: number[];
|
|
18
|
-
maxFutureDate?: DateTime;
|
|
19
|
-
children: Snippet<[AvailableSpans]>;
|
|
20
|
-
} = $props();
|
|
21
|
-
|
|
22
|
-
const stateID = contextKey(untrack(() => url));
|
|
23
|
-
let ss: OccupationState = getContext(stateID);
|
|
24
|
-
if (!ss) {
|
|
25
|
-
ss = new OccupationState(() => {
|
|
26
|
-
return { iCalURL: url, debug };
|
|
27
|
-
});
|
|
28
|
-
setContext(stateID, ss);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
let occupationState: OccupationState = $derived(ss);
|
|
32
|
-
let av = $derived(occupationState ? occupationState.calcAvailability(search, maxFutureDate) : {});
|
|
33
|
-
|
|
34
|
-
onMount(() => {
|
|
35
|
-
occupationState.loadOccupations();
|
|
36
|
-
});
|
|
37
|
-
</script>
|
|
38
|
-
|
|
39
|
-
{#if !occupationState || occupationState.loading}
|
|
40
|
-
<Spinner />
|
|
41
|
-
{/if}
|
|
42
|
-
|
|
43
|
-
{@render children(av)}
|
|
@@ -1,383 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { DateTime, type MonthNumbers } from 'luxon';
|
|
3
|
-
import {
|
|
4
|
-
contextKey,
|
|
5
|
-
defaultMonthHeaderFormat,
|
|
6
|
-
defaultMonthLabels,
|
|
7
|
-
defaultWeekdayLabels,
|
|
8
|
-
OccupationState,
|
|
9
|
-
occupationTypeFormatting,
|
|
10
|
-
realFirstMonth,
|
|
11
|
-
type FirstMonth,
|
|
12
|
-
type OccupationType,
|
|
13
|
-
type OccuplanTranslations,
|
|
14
|
-
} from './state.svelte.js';
|
|
15
|
-
import Button from '../basic/Button.svelte';
|
|
16
|
-
import Spinner from '../basic/Spinner.svelte';
|
|
17
|
-
import { randomID } from '../names/gen.js';
|
|
18
|
-
import { getContext, onMount, setContext, untrack } from 'svelte';
|
|
19
|
-
|
|
20
|
-
let {
|
|
21
|
-
url,
|
|
22
|
-
debug = false,
|
|
23
|
-
header = '',
|
|
24
|
-
footer = '',
|
|
25
|
-
nextPage = '>',
|
|
26
|
-
prevPage = '<',
|
|
27
|
-
weekdayLabels = defaultWeekdayLabels,
|
|
28
|
-
monthLabels = defaultMonthLabels,
|
|
29
|
-
monthHeaderFormat = defaultMonthHeaderFormat,
|
|
30
|
-
numberOfMonth = 12,
|
|
31
|
-
maxWidth = '1200px',
|
|
32
|
-
firstMonth = DateTime.utc().month,
|
|
33
|
-
maxDate = DateTime.utc().plus({ years: 2 }),
|
|
34
|
-
minDate = DateTime.utc(),
|
|
35
|
-
typeLabels = {
|
|
36
|
-
one: 'BOOKING',
|
|
37
|
-
two: 'RESERVATION',
|
|
38
|
-
three: 'PERSONAL',
|
|
39
|
-
},
|
|
40
|
-
}: OccuplanTranslations & {
|
|
41
|
-
url: string;
|
|
42
|
-
debug?: boolean;
|
|
43
|
-
numberOfMonth?: number;
|
|
44
|
-
firstMonth?: FirstMonth;
|
|
45
|
-
minDate?: DateTime;
|
|
46
|
-
maxDate?: DateTime;
|
|
47
|
-
maxWidth?: string;
|
|
48
|
-
} = $props();
|
|
49
|
-
|
|
50
|
-
const id = randomID();
|
|
51
|
-
|
|
52
|
-
const stateID = contextKey(untrack(() => url));
|
|
53
|
-
let ss: OccupationState = getContext(stateID);
|
|
54
|
-
if (!ss) {
|
|
55
|
-
ss = new OccupationState(() => {
|
|
56
|
-
return { iCalURL: url, debug };
|
|
57
|
-
});
|
|
58
|
-
setContext(stateID, ss);
|
|
59
|
-
}
|
|
60
|
-
let occupationState: OccupationState = $derived(ss);
|
|
61
|
-
|
|
62
|
-
//let formatFun = $derived(Sqrl.compile(monthHeaderFormat, { useWith: true }));
|
|
63
|
-
const monthHeader = (monthNum: MonthNumbers, year: number): string => {
|
|
64
|
-
const monthLabel = monthLabels[monthNum];
|
|
65
|
-
|
|
66
|
-
let formatted = monthHeaderFormat.replace('{{month}}', monthLabel);
|
|
67
|
-
formatted = formatted.replace('{{year}}', `${year}`);
|
|
68
|
-
|
|
69
|
-
return formatted;
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
let page: number = $state(0);
|
|
73
|
-
let rfMonth: DateTime = $derived(
|
|
74
|
-
realFirstMonth(firstMonth, DateTime.utc().get('year'), numberOfMonth, page),
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
let currentMaxDate = $derived(rfMonth.plus({ month: numberOfMonth }));
|
|
78
|
-
|
|
79
|
-
let months: DateTime[] = $derived.by(() => {
|
|
80
|
-
const result = [];
|
|
81
|
-
|
|
82
|
-
let fMonth: DateTime = DateTime.utc(rfMonth.year, rfMonth.month, 1);
|
|
83
|
-
|
|
84
|
-
result.push(fMonth);
|
|
85
|
-
|
|
86
|
-
let nMonth = fMonth.plus({ months: 1 });
|
|
87
|
-
for (let c = 1; c < numberOfMonth; c++) {
|
|
88
|
-
result.push(nMonth);
|
|
89
|
-
nMonth = nMonth.plus({ months: 1 });
|
|
90
|
-
}
|
|
91
|
-
return result;
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
const nextClicked = () => {
|
|
95
|
-
page += 1;
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
const prevClicked = () => {
|
|
99
|
-
page -= 1;
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
let monthGridTemplateColumns = `[rowLegend] 1fr [d1] 1fr [d2] 1fr [d3] 1fr [d4] 1fr [d5] 1fr [d6] 1fr [d7] 1fr`;
|
|
103
|
-
|
|
104
|
-
let monthGridTemplateRows = (m: DateTime): string => {
|
|
105
|
-
let res = `[columnLegend] 1fr [w${m.weekNumber}] 1fr`;
|
|
106
|
-
let n = m.plus({ weeks: 1 });
|
|
107
|
-
for (let w = 1; w <= 5; w++) {
|
|
108
|
-
res += ` [w${n.weekNumber}] 1fr`;
|
|
109
|
-
n = n.plus({ weeks: 1 });
|
|
110
|
-
}
|
|
111
|
-
return res;
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
const weeks = (m: DateTime): DateTime[] => {
|
|
115
|
-
let n = m.plus({ weeks: 1 });
|
|
116
|
-
let res: DateTime[] = [m, n];
|
|
117
|
-
for (let i = 1; i <= 4; i++) {
|
|
118
|
-
n = n.plus({ weeks: 1 });
|
|
119
|
-
res.push(n);
|
|
120
|
-
}
|
|
121
|
-
return res;
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
const days = (m: DateTime): DateTime[] => {
|
|
125
|
-
//find first
|
|
126
|
-
let firstDay = m.startOf('week');
|
|
127
|
-
|
|
128
|
-
//find last
|
|
129
|
-
let lastDayOfMonth = m.endOf('month');
|
|
130
|
-
let lastDay = lastDayOfMonth.endOf('week');
|
|
131
|
-
|
|
132
|
-
let n = firstDay.plus({ days: 1 });
|
|
133
|
-
let res: DateTime[] = [firstDay];
|
|
134
|
-
|
|
135
|
-
while (n <= lastDay) {
|
|
136
|
-
res.push(n);
|
|
137
|
-
n = n.plus({ days: 1 });
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return res;
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
const hiddenWeekNum = (m: DateTime, w: DateTime): boolean => {
|
|
144
|
-
let lastDayOfMonth = m.endOf('month');
|
|
145
|
-
let firstDayOfWeek = w.startOf('week');
|
|
146
|
-
return lastDayOfMonth < firstDayOfWeek;
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
let foundOccupationTypes: OccupationType[] = $derived(
|
|
150
|
-
occupationState?.occupations.reduce((res, occupation) => {
|
|
151
|
-
if (!res.includes(occupation.type)) {
|
|
152
|
-
res.push(occupation.type);
|
|
153
|
-
}
|
|
154
|
-
return res;
|
|
155
|
-
}, [] as OccupationType[]),
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
onMount(() => {
|
|
159
|
-
occupationState.loadOccupations();
|
|
160
|
-
});
|
|
161
|
-
</script>
|
|
162
|
-
|
|
163
|
-
{#if !occupationState || occupationState.loading}
|
|
164
|
-
<Spinner />
|
|
165
|
-
{/if}
|
|
166
|
-
|
|
167
|
-
<section class="occuplan-wrapper" style="max-width: {maxWidth};">
|
|
168
|
-
<header class="occupation-plan-header">
|
|
169
|
-
<div class="header-controls">
|
|
170
|
-
{#if rfMonth >= minDate}
|
|
171
|
-
<Button text={`${prevPage}`} clicked={prevClicked} />
|
|
172
|
-
{/if}
|
|
173
|
-
</div>
|
|
174
|
-
<div class="header-label"><h3>{@html header}</h3></div>
|
|
175
|
-
<div class="header-controls">
|
|
176
|
-
{#if currentMaxDate <= maxDate}
|
|
177
|
-
<Button text={`${nextPage}`} clicked={nextClicked} />
|
|
178
|
-
{/if}
|
|
179
|
-
</div>
|
|
180
|
-
</header>
|
|
181
|
-
<main>
|
|
182
|
-
{#each months as m (`${m.year}-${m.month}`)}
|
|
183
|
-
<div class="month">
|
|
184
|
-
<header class="month-header">{monthHeader(m.month as MonthNumbers, m.year)}</header>
|
|
185
|
-
<div
|
|
186
|
-
id={`${m.year}-${m.month}-${id}`}
|
|
187
|
-
style="
|
|
188
|
-
grid-template-columns: {monthGridTemplateColumns};
|
|
189
|
-
grid-template-rows: {monthGridTemplateRows(m)};
|
|
190
|
-
"
|
|
191
|
-
class="days"
|
|
192
|
-
>
|
|
193
|
-
<div class="weekday-header" style="grid-area: columnLegend / d1 / columnLegend / d1;">
|
|
194
|
-
{weekdayLabels[1]}
|
|
195
|
-
</div>
|
|
196
|
-
<div class="weekday-header" style="grid-area: columnLegend / d2 / columnLegend / d2;">
|
|
197
|
-
{weekdayLabels[2]}
|
|
198
|
-
</div>
|
|
199
|
-
<div class="weekday-header" style="grid-area: columnLegend / d3 / columnLegend / d3;">
|
|
200
|
-
{weekdayLabels[3]}
|
|
201
|
-
</div>
|
|
202
|
-
<div class="weekday-header" style="grid-area: columnLegend / d4 / columnLegend / d4;">
|
|
203
|
-
{weekdayLabels[4]}
|
|
204
|
-
</div>
|
|
205
|
-
<div class="weekday-header" style="grid-area: columnLegend / d5 / columnLegend / d5;">
|
|
206
|
-
{weekdayLabels[5]}
|
|
207
|
-
</div>
|
|
208
|
-
<div class="weekday-header" style="grid-area: columnLegend / d6 / columnLegend / d6;">
|
|
209
|
-
{weekdayLabels[6]}
|
|
210
|
-
</div>
|
|
211
|
-
<div class="weekday-header" style="grid-area: columnLegend / d7 / columnLegend / d7;">
|
|
212
|
-
{weekdayLabels[7]}
|
|
213
|
-
</div>
|
|
214
|
-
|
|
215
|
-
{#each days(m) as d (`${d.year}-${d.month}-${d.day}`)}
|
|
216
|
-
<div
|
|
217
|
-
id={`${m.year}-${m.month}-${m.day}-${id}`}
|
|
218
|
-
class:weekend={[6, 7].includes(d.weekday)}
|
|
219
|
-
class:other-month={m.month !== d.month}
|
|
220
|
-
class="day"
|
|
221
|
-
style="
|
|
222
|
-
grid-area: w{d.weekNumber} / d{d.weekday} / w{d.weekNumber} / d{d.weekday};
|
|
223
|
-
{occupationState?.occupationStyle(
|
|
224
|
-
{ day: d.day, month: d.month as MonthNumbers, year: d.year },
|
|
225
|
-
false,
|
|
226
|
-
maxDate,
|
|
227
|
-
)}
|
|
228
|
-
"
|
|
229
|
-
>
|
|
230
|
-
{d.day}
|
|
231
|
-
</div>
|
|
232
|
-
{/each}
|
|
233
|
-
|
|
234
|
-
{#each weeks(m) as w (`${w.year}-${w.month}-${w.weekNumber}`)}
|
|
235
|
-
<div
|
|
236
|
-
id={`${w.year}-${w.month}-${w.weekNumber}-${id}`}
|
|
237
|
-
class:hidden={hiddenWeekNum(m, w)}
|
|
238
|
-
class="week-number"
|
|
239
|
-
style="grid-area: w{w.weekNumber} / rowLegend / w{w.weekNumber} / rowLegend;"
|
|
240
|
-
>
|
|
241
|
-
{w.weekNumber}
|
|
242
|
-
</div>
|
|
243
|
-
{/each}
|
|
244
|
-
</div>
|
|
245
|
-
</div>
|
|
246
|
-
{/each}
|
|
247
|
-
</main>
|
|
248
|
-
<footer>
|
|
249
|
-
<div class="legend">
|
|
250
|
-
{#each foundOccupationTypes as t}
|
|
251
|
-
{@const format = occupationTypeFormatting(t)}
|
|
252
|
-
<span>{typeLabels[t]}</span>
|
|
253
|
-
<div
|
|
254
|
-
id="occupation-type-{t}-legend"
|
|
255
|
-
class="legend-entry-marker"
|
|
256
|
-
style="background-color: {format.bgColor};"
|
|
257
|
-
>
|
|
258
|
-
|
|
259
|
-
</div>
|
|
260
|
-
{/each}
|
|
261
|
-
</div>
|
|
262
|
-
<div class="footer-content">
|
|
263
|
-
{@html footer}
|
|
264
|
-
</div>
|
|
265
|
-
</footer>
|
|
266
|
-
</section>
|
|
267
|
-
|
|
268
|
-
<style>
|
|
269
|
-
.footer-content {
|
|
270
|
-
display: flex;
|
|
271
|
-
flex-direction: column;
|
|
272
|
-
justify-content: flex-end;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
.legend-entry-marker {
|
|
276
|
-
outline: var(--occuplan-grid-border);
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
.month-header {
|
|
280
|
-
text-align: center;
|
|
281
|
-
color: var(--occuplan-main-font-color);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
.hidden {
|
|
285
|
-
display: none;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
.occupation-plan-header {
|
|
289
|
-
display: flex;
|
|
290
|
-
flex-direction: row;
|
|
291
|
-
width: 100%;
|
|
292
|
-
justify-content: space-between;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
.header-label {
|
|
296
|
-
text-transform: capitalize;
|
|
297
|
-
font-weight: bold;
|
|
298
|
-
font-variant: small-caps;
|
|
299
|
-
|
|
300
|
-
h3 {
|
|
301
|
-
color: var(--occuplan-main-font-color);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
.week-number {
|
|
306
|
-
text-align: left;
|
|
307
|
-
font-style: italic;
|
|
308
|
-
font-weight: lighter;
|
|
309
|
-
background-color: var(--occuplan-weeknum-bg-color);
|
|
310
|
-
color: var(--occuplan-weeknum-font-color);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
.weekday-header {
|
|
314
|
-
text-align: center;
|
|
315
|
-
background-color: var(--occuplan-days-header-bg-color);
|
|
316
|
-
color: var(--occuplan-days-header-font-color);
|
|
317
|
-
grid-area: columnLegend / d1 / columnLegend / d1;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
.day {
|
|
321
|
-
text-align: center;
|
|
322
|
-
color: var(--occuplan-main-font-color);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
.weekend {
|
|
326
|
-
font-weight: bold;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
.occuplan-wrapper {
|
|
330
|
-
height: 100%;
|
|
331
|
-
width: calc(100% - 0.5rem);
|
|
332
|
-
padding: 0.5rem;
|
|
333
|
-
margin: 0;
|
|
334
|
-
display: flex;
|
|
335
|
-
flex-direction: column;
|
|
336
|
-
flex-wrap: nowrap;
|
|
337
|
-
align-items: center;
|
|
338
|
-
|
|
339
|
-
border: var(--occuplan-main-border);
|
|
340
|
-
color: var(--occuplan-main-font-color);
|
|
341
|
-
background-color: var(--occuplan-main-bg-color);
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
main {
|
|
345
|
-
display: grid;
|
|
346
|
-
grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
|
|
347
|
-
gap: 1rem;
|
|
348
|
-
width: 100%;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
.month {
|
|
352
|
-
display: flex;
|
|
353
|
-
flex-direction: column;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
.days {
|
|
357
|
-
display: grid;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
footer {
|
|
361
|
-
display: flex;
|
|
362
|
-
flex-direction: row;
|
|
363
|
-
align-items: stretch;
|
|
364
|
-
justify-content: space-between;
|
|
365
|
-
width: 100%;
|
|
366
|
-
margin-top: 1rem;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
.legend {
|
|
370
|
-
display: grid;
|
|
371
|
-
grid-template-columns: [label] 1fr [marker] 1rem;
|
|
372
|
-
column-gap: 1rem;
|
|
373
|
-
text-transform: capitalize;
|
|
374
|
-
font-variant: small-caps;
|
|
375
|
-
|
|
376
|
-
span {
|
|
377
|
-
color: var(--occuplan-main-font-color);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
.header-controls {
|
|
381
|
-
width: 2rem;
|
|
382
|
-
}
|
|
383
|
-
</style>
|