accomadesc 0.3.41 → 0.4.0

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 (39) hide show
  1. package/README.md +130 -34
  2. package/dist/AccoCard.svelte +1 -1
  3. package/dist/CalendarAvailable.svelte +1 -1
  4. package/dist/MainNav.svelte +1 -2
  5. package/dist/PageComponent.svelte +1 -2
  6. package/dist/PhotoGallery.svelte +5 -1
  7. package/dist/Pricing.svelte +81 -168
  8. package/dist/SiteState.svelte.d.ts +1 -1
  9. package/dist/SiteState.svelte.js +21 -13
  10. package/dist/basic/TextInput.svelte +69 -116
  11. package/dist/basic/TextInput.svelte.d.ts +2 -0
  12. package/dist/basic/icons/actions.d.ts +13 -0
  13. package/dist/basic/icons/actions.js +44 -0
  14. package/dist/basic/icons/navigation.d.ts +6 -0
  15. package/dist/basic/icons/navigation.js +16 -0
  16. package/dist/basic/icons/ui.d.ts +13 -0
  17. package/dist/basic/icons/ui.js +44 -0
  18. package/dist/basic/icons.d.ts +4 -0
  19. package/dist/basic/icons.js +51 -413
  20. package/dist/helpers/debounce.js +8 -2
  21. package/dist/helpers/format.js +2 -1
  22. package/dist/helpers/normalizeDate.d.ts +1 -1
  23. package/dist/helpers/normalizeDate.js +25 -16
  24. package/dist/helpers/readICS.js +21 -4
  25. package/dist/index.d.ts +1 -1
  26. package/dist/names/README.md +1 -1
  27. package/dist/names/gen.js +10 -1
  28. package/dist/occuplan/state.svelte.js +7 -3
  29. package/dist/occusplan-link/OccuPlanAvailableInfo.svelte +38 -0
  30. package/dist/occusplan-link/OccuPlanGrid.svelte +375 -0
  31. package/dist/occusplan-link/OccuPlanPicker.svelte +575 -0
  32. package/dist/occusplan-link/OccuPlanRows.svelte +368 -0
  33. package/dist/occusplan-link/OccuPlanWrapper.svelte +108 -0
  34. package/dist/occusplan-link/defaultTranslations.js +157 -0
  35. package/dist/occusplan-link/state.svelte.d.ts +92 -0
  36. package/dist/occusplan-link/state.svelte.js +424 -0
  37. package/dist/svg/LogoSVG.svelte +0 -1
  38. package/dist/types.d.ts +2 -1
  39. package/package.json +12 -6
@@ -0,0 +1,368 @@
1
+ <script lang="ts">
2
+ import { DateTime, type DayNumbers, type MonthNumbers } from 'luxon';
3
+ import {
4
+ defaultMonthLabels,
5
+ defaultWeekendLabel,
6
+ OccupationState,
7
+ getOccupationState,
8
+ occupationTypeFormatting,
9
+ type OccupationType,
10
+ type OccuplanTranslations,
11
+ type DayHelper,
12
+ type FirstMonth,
13
+ realFirstMonth,
14
+ } from '../occuplan/state.svelte.js';
15
+ import Button from '../basic/Button.svelte';
16
+ import { browser } from '$app/environment';
17
+ import Spinner from '../basic/Spinner.svelte';
18
+ import { randomID } from '../names/gen.js';
19
+ import { onMount } from 'svelte';
20
+
21
+ let {
22
+ url,
23
+ debug = false,
24
+ header = '',
25
+ footer = '',
26
+ weekendLabel = defaultWeekendLabel,
27
+ monthLabels = defaultMonthLabels,
28
+ numberOfMonth = 12,
29
+ firstMonth = 1,
30
+ maxWidth = '1200px',
31
+ maxDate = DateTime.utc().plus({ years: 2 }),
32
+ minDate = DateTime.utc(),
33
+ typeLabels = {
34
+ one: 'BOOKING',
35
+ two: 'RESERVATION',
36
+ three: 'PERSONAL',
37
+ },
38
+ }: OccuplanTranslations & {
39
+ url: string;
40
+ debug?: boolean;
41
+ numberOfMonth?: number;
42
+ firstMonth?: FirstMonth;
43
+ minDate?: DateTime;
44
+ maxDate?: DateTime;
45
+ maxWidth?: string;
46
+ } = $props();
47
+
48
+ const id = randomID();
49
+
50
+ let occupationState: OccupationState = $derived(getOccupationState(url, debug));
51
+
52
+ let page: number = $state(0);
53
+ let rfMonth: number | DateTime = $derived(
54
+ realFirstMonth(firstMonth, DateTime.utc().get('year'), numberOfMonth, page),
55
+ );
56
+
57
+ let currentMaxDate = $derived(rfMonth.plus({ month: numberOfMonth }));
58
+
59
+ let months: DateTime[] = $derived.by(() => {
60
+ const result = [];
61
+ if (rfMonth.month == 1) {
62
+ //result.push(rfMonth);
63
+ }
64
+
65
+ let fMonth: DateTime = DateTime.utc(rfMonth.year, rfMonth.month, 1);
66
+ result.push(fMonth);
67
+
68
+ let nMonth = fMonth.plus({ months: 1 });
69
+ for (let c = 1; c < numberOfMonth; c++) {
70
+ result.push(nMonth);
71
+ nMonth = nMonth.plus({ months: 1 });
72
+ }
73
+ return result;
74
+ });
75
+
76
+ const nextClicked = () => {
77
+ page += 1;
78
+ };
79
+
80
+ const prevClicked = () => {
81
+ page -= 1;
82
+ };
83
+
84
+ const monthDays = [...Array(31).keys()].map((i) => i + 1);
85
+ let days: DayHelper[] = $derived.by(() => {
86
+ const ldays: DayHelper[] = [];
87
+ if (!browser) return ldays;
88
+ if (!occupationState || occupationState.loading) return ldays;
89
+
90
+ for (const m of months) {
91
+ for (let d: DayNumbers = 1; d <= 31; d++) {
92
+ const day: DayHelper = {
93
+ day: d,
94
+ month: m.month as MonthNumbers,
95
+ year: m.year,
96
+ };
97
+ ldays.push(day);
98
+ }
99
+ }
100
+ return ldays;
101
+ });
102
+
103
+ let monthGridTemplateColumns = $derived(
104
+ monthDays.reduce((s, d) => {
105
+ s += ` [d${d}] 1fr`;
106
+ return s;
107
+ }, '[rowLegend] 1.5fr'),
108
+ );
109
+
110
+ let monthGridTemplateRows = $derived(
111
+ months.reduce((s, m) => {
112
+ if (m.month == 1 && s != '[columnLegend] 1fr [firstYearRow] 1fr') {
113
+ s += ` [y${m.year}Row] 1fr`;
114
+ }
115
+
116
+ s += ` [m${m.month}y${m.year}] 1fr`;
117
+ return s;
118
+ }, '[columnLegend] 1fr [firstYearRow] 1fr'),
119
+ );
120
+
121
+ let foundOccupationTypes: OccupationType[] = $derived(
122
+ occupationState
123
+ ? occupationState.occupations.reduce((res, occupation) => {
124
+ if (!res.includes(occupation.type)) {
125
+ res.push(occupation.type);
126
+ }
127
+ return res;
128
+ }, [] as OccupationType[])
129
+ : [],
130
+ );
131
+
132
+ onMount(() => {
133
+ occupationState.loadOccupations();
134
+ });
135
+ </script>
136
+
137
+ {#if !occupationState || occupationState.loading}
138
+ <Spinner />
139
+ {/if}
140
+
141
+ <section class="occuplan-wrapper" style="max-width: {maxWidth};">
142
+ <header class="occupation-plan-header">
143
+ <div class="header-controls">
144
+ {#if rfMonth >= minDate}
145
+ <Button text="<" clicked={prevClicked} />
146
+ {/if}
147
+ </div>
148
+ <div class="header-label"><h3>{@html header}</h3></div>
149
+ <div class="header-controls">
150
+ {#if currentMaxDate <= maxDate}
151
+ <Button text=">" clicked={nextClicked} />
152
+ {/if}
153
+ </div>
154
+ </header>
155
+ <main
156
+ style="
157
+ grid-template-columns: {monthGridTemplateColumns};
158
+ grid-template-rows: {monthGridTemplateRows};
159
+ "
160
+ >
161
+ <div
162
+ class="corner"
163
+ style="
164
+ grid-area: columnLegend / rowLegend / columnLegend / rowLegend;
165
+ background-color: var(--occuplan-main-bg-color);"
166
+ >
167
+ &nbsp;
168
+ </div>
169
+
170
+ {#each monthDays as d}
171
+ <div class="monthday-header" style="grid-area: columnLegend / d{d} / columnLegend / d{d};">
172
+ <span>{d}</span>
173
+ </div>
174
+ {/each}
175
+
176
+ <div class="year-label" style="grid-area: firstYearRow / d1 / firstYearRow / d31;">
177
+ <span>{rfMonth.year}</span>
178
+ </div>
179
+ {#each months as m, i (`${m.year}-${m.month}`)}
180
+ {#if m.month == 1 && i != 0}
181
+ <div class="year-label" style="grid-area: y{m.year}Row / d1 / y{m.year}Row / d31;">
182
+ <span>{m.year}</span>
183
+ </div>
184
+ {/if}
185
+ <div
186
+ id={`${m.year}-${m.month}-${id}`}
187
+ class="month-label"
188
+ style="grid-area: m{m.month}y{m.year} / rowLegend / m{m.month}y{m.year} / rowLegend;"
189
+ >
190
+ <span>{monthLabels[m.month as MonthNumbers]}</span>
191
+ </div>
192
+ {/each}
193
+
194
+ {#if occupationState}
195
+ {#each days as d (`${d.year}-${d.month}-${d.day}`)}
196
+ <div
197
+ id={`${d.year}-${d.month}-${d.day}-${id}`}
198
+ class="day"
199
+ style="
200
+ outline: var(--occuplan-grid-border);
201
+ grid-area: m{d.month}y{d.year} / d{d.day} / m{d.month}y{d.year} / d{d.day};
202
+ {occupationState.occupationStyle(d, true, maxDate)}
203
+ "
204
+ >
205
+ &nbsp;
206
+ </div>
207
+ {/each}
208
+ {/if}
209
+ </main>
210
+ <footer>
211
+ <div class="legend">
212
+ <span>{weekendLabel}</span>
213
+ <div
214
+ id="weekend-legend"
215
+ class="legend-entry-marker"
216
+ style="
217
+ outline: var(--occuplan-grid-border);
218
+ background: radial-gradient(var(--occuplan-weekend-bg-color), var(--occuplan-main-bg-color), var(--occuplan-main-bg-color));
219
+ "
220
+ >
221
+ &nbsp;
222
+ </div>
223
+ {#each foundOccupationTypes as t}
224
+ {@const format = occupationTypeFormatting(t)}
225
+ <span>{typeLabels[t]}</span>
226
+ <div
227
+ id="occupation-type-{t}-legend"
228
+ class="legend-entry-marker"
229
+ style="background-color: {format.bgColor}; outline: var(--occuplan-grid-border);"
230
+ >
231
+ &nbsp;
232
+ </div>
233
+ {/each}
234
+ </div>
235
+ <div class="footer-content">
236
+ {@html footer}
237
+ </div>
238
+ </footer>
239
+ </section>
240
+
241
+ <style>
242
+ .footer-content {
243
+ display: flex;
244
+ flex-direction: column;
245
+ justify-content: flex-end;
246
+ }
247
+
248
+ .legend {
249
+ display: grid;
250
+ grid-template-columns: [label] 1fr [marker] 1rem;
251
+ column-gap: 1rem;
252
+ text-transform: capitalize;
253
+ font-variant: small-caps;
254
+
255
+ span {
256
+ color: var(--occuplan-main-font-color);
257
+ }
258
+ }
259
+
260
+ .legend-entry-marker {
261
+ width: 1rem;
262
+ height: 1rem;
263
+ }
264
+
265
+ main {
266
+ display: grid;
267
+ width: 100%;
268
+ overflow-x: auto;
269
+ }
270
+
271
+ .month-label {
272
+ aspect-ratio: 3 / 2;
273
+ display: flex;
274
+ align-items: center;
275
+ border-bottom: var(--occuplan-grid-border);
276
+ border-top: var(--occuplan-grid-border);
277
+ color: var(--occuplan-months-font-color);
278
+ background-color: var(--occuplan-months-bg-color);
279
+ container-type: size;
280
+ container-name: month-label;
281
+ padding-left: 0.3rem;
282
+ height: 100%;
283
+
284
+ span {
285
+ font-size: clamp(0.9rem, 55cqh, 2rem);
286
+ color: var(--occuplan-months-font-color);
287
+ }
288
+ }
289
+
290
+ .monthday-header {
291
+ text-align: center;
292
+ aspect-ratio: 1;
293
+ display: inline-grid;
294
+ align-content: center;
295
+ outline: var(--occuplan-grid-border);
296
+ background-color: var(--occuplan-days-header-bg-color);
297
+ color: var(--occuplan-days-header-font-color);
298
+ container-type: size;
299
+ container-name: month-header;
300
+
301
+ span {
302
+ color: var(--occuplan-days-header-font-color);
303
+ font-size: clamp(0.9rem, 55cqh, 2rem);
304
+ }
305
+ }
306
+
307
+ .occupation-plan-header {
308
+ display: flex;
309
+ flex-direction: row;
310
+ width: 100%;
311
+ justify-content: space-between;
312
+ margin-bottom: 0.5rem;
313
+ }
314
+
315
+ .header-label {
316
+ text-transform: capitalize;
317
+ font-variant: small-caps;
318
+ font-weight: bold;
319
+
320
+ h3 {
321
+ padding-top: 0;
322
+ padding-bottom: 0.2rem;
323
+ color: var(--occuplan-main-font-color);
324
+ }
325
+ }
326
+
327
+ .header-controls {
328
+ width: 2rem;
329
+ }
330
+
331
+ .occuplan-wrapper {
332
+ height: 100%;
333
+ width: calc(100% - 0.5rem);
334
+ padding: 0.5rem;
335
+ margin: 0;
336
+ display: flex;
337
+ flex-direction: column;
338
+ flex-wrap: nowrap;
339
+ align-items: center;
340
+
341
+ border: var(--occuplan-main-border);
342
+ color: var(--occuplan-main-font-color);
343
+ background-color: var(--occuplan-main-bg-color);
344
+ }
345
+
346
+ footer {
347
+ display: flex;
348
+ flex-direction: row;
349
+ align-items: stretch;
350
+ justify-content: space-between;
351
+ width: 100%;
352
+ margin-top: 1rem;
353
+ }
354
+
355
+ .year-label {
356
+ display: flex;
357
+ justify-content: center;
358
+ align-items: center;
359
+ container-type: size;
360
+ container-name: year-label;
361
+ text-decoration: underline;
362
+ height: 100%;
363
+ span {
364
+ color: var(--occuplan-main-font-color);
365
+ font-size: clamp(1rem, 55cqh, 2rem);
366
+ }
367
+ }
368
+ </style>
@@ -0,0 +1,108 @@
1
+ <script lang="ts">
2
+ import OccuPlanGrid from '../occuplan/OccuPlanGrid.svelte';
3
+ import OccuPlanRows from '../occuplan/OccuPlanRows.svelte';
4
+ import {
5
+ type OccuplanTranslations,
6
+ type OccuplanMiscProps,
7
+ defaultWeekendLabel,
8
+ defaultMonthLabels,
9
+ defaultWeekdayLabels,
10
+ defaultMonthHeaderFormat,
11
+ } from '../occuplan/state.svelte.js';
12
+ import { DateTime } from 'luxon';
13
+
14
+ let {
15
+ url,
16
+ header = '',
17
+ footer = '',
18
+ debug = false,
19
+ weekendLabel = defaultWeekendLabel,
20
+ monthLabels = defaultMonthLabels,
21
+ weekdayLabels = defaultWeekdayLabels,
22
+ monthHeaderFormat = defaultMonthHeaderFormat,
23
+ gridNumberOfMonths = 8,
24
+ gridFirstMonth = '-1',
25
+ gridMaxWidth = '1200px',
26
+ rowsNumberOfMonths = 12,
27
+ rowsFirstMonth = 1,
28
+ rowsMaxWidth = '1200px',
29
+ toggleGridOffset = 640,
30
+ toggleRowsOffset = 640,
31
+ maxDate = DateTime.utc().plus({ years: 2 }),
32
+ minDate = DateTime.utc(),
33
+ nextPage = '>',
34
+ prevPage = '<',
35
+ typeLabels = {
36
+ one: 'BOOKING',
37
+ two: 'RESERVATION',
38
+ three: 'PERSONAL',
39
+ },
40
+ }: OccuplanTranslations & OccuplanMiscProps = $props();
41
+
42
+ /*
43
+ use different component based on different media size.
44
+ */
45
+ let w: number = $state(0);
46
+ let showGrid: boolean = $state(false);
47
+ let showRows: boolean = $state(true);
48
+
49
+ $effect(() => {
50
+ if (w < toggleGridOffset && showRows) {
51
+ showGrid = true;
52
+ showRows = false;
53
+ }
54
+ });
55
+ $effect(() => {
56
+ if (w > toggleRowsOffset && showGrid) {
57
+ showRows = true;
58
+ showGrid = false;
59
+ }
60
+ });
61
+ </script>
62
+
63
+ <div class="calendar-wrapper" bind:clientWidth={w}>
64
+ {#if showRows}
65
+ <OccuPlanRows
66
+ {debug}
67
+ {url}
68
+ {header}
69
+ {footer}
70
+ {weekendLabel}
71
+ {monthLabels}
72
+ {maxDate}
73
+ {minDate}
74
+ maxWidth={rowsMaxWidth}
75
+ numberOfMonth={rowsNumberOfMonths}
76
+ firstMonth={rowsFirstMonth}
77
+ {typeLabels}
78
+ />
79
+ {:else if showGrid}
80
+ <OccuPlanGrid
81
+ {debug}
82
+ {url}
83
+ {header}
84
+ {footer}
85
+ {nextPage}
86
+ {prevPage}
87
+ {weekdayLabels}
88
+ {monthLabels}
89
+ {maxDate}
90
+ {minDate}
91
+ maxWidth={gridMaxWidth}
92
+ {monthHeaderFormat}
93
+ numberOfMonth={gridNumberOfMonths}
94
+ firstMonth={gridFirstMonth}
95
+ {typeLabels}
96
+ />
97
+ {/if}
98
+ </div>
99
+
100
+ <style>
101
+ .calendar-wrapper {
102
+ display: flex;
103
+ justify-content: center;
104
+ min-width: 210px;
105
+ max-width: 110rem;
106
+ width: 100%;
107
+ }
108
+ </style>
@@ -0,0 +1,157 @@
1
+ export const DefaultCalTranslations = {
2
+ es: {
3
+ weekdayLabels: {
4
+ 1: 'Lu',
5
+ 2: 'Ma',
6
+ 3: 'Mi',
7
+ 4: 'Ju',
8
+ 5: 'Vi',
9
+ 6: 'Sa',
10
+ 7: 'Do',
11
+ },
12
+ monthLabels: {
13
+ 1: 'Ene',
14
+ 2: 'Feb',
15
+ 3: 'Mar',
16
+ 4: 'Abr',
17
+ 5: 'May',
18
+ 6: 'Jun',
19
+ 7: 'Jul',
20
+ 8: 'Ago',
21
+ 9: 'Sep',
22
+ 10: 'Oct',
23
+ 11: 'Nov',
24
+ 12: 'Dic',
25
+ },
26
+ weekendLabel: 'Fin de Semana',
27
+ typeLabels: {
28
+ one: 'Ocupado',
29
+ two: 'Ocupade',
30
+ three: '',
31
+ },
32
+ },
33
+ fr: {
34
+ weekdayLabels: {
35
+ 1: 'Lu',
36
+ 2: 'Ma',
37
+ 3: 'Me',
38
+ 4: 'Je',
39
+ 5: 'Ve',
40
+ 6: 'Sa',
41
+ 7: 'Di',
42
+ },
43
+ monthLabels: {
44
+ 1: 'Jan',
45
+ 2: 'Fév',
46
+ 3: 'Mar',
47
+ 4: 'Avr',
48
+ 5: 'Mai',
49
+ 6: 'Juin',
50
+ 7: 'Juil',
51
+ 8: 'Août',
52
+ 9: 'Sept',
53
+ 10: 'Oct',
54
+ 11: 'Nov',
55
+ 12: 'Déc',
56
+ },
57
+ weekendLabel: 'Week-end',
58
+ typeLabels: {
59
+ one: 'Occupé',
60
+ two: 'Occupé',
61
+ three: '',
62
+ },
63
+ },
64
+ pl: {
65
+ weekdayLabels: {
66
+ 1: 'Pon',
67
+ 2: 'Wt',
68
+ 3: 'Śr',
69
+ 4: 'Czw',
70
+ 5: 'Pt',
71
+ 6: 'Sob',
72
+ 7: 'Ndz',
73
+ },
74
+ monthLabels: {
75
+ 1: 'Sty',
76
+ 2: 'Lut',
77
+ 3: 'Mar',
78
+ 4: 'Kwi',
79
+ 5: 'Maj',
80
+ 6: 'Cze',
81
+ 7: 'Lip',
82
+ 8: 'Sie',
83
+ 9: 'Wrz',
84
+ 10: 'Paź',
85
+ 11: 'Lis',
86
+ 12: 'Gru',
87
+ },
88
+ weekendLabel: 'Weekend',
89
+ typeLabels: {
90
+ one: 'Zajęty',
91
+ two: 'Zajęty',
92
+ three: '',
93
+ },
94
+ },
95
+ en: {
96
+ weekdayLabels: {
97
+ 1: 'Mo',
98
+ 2: 'Tu',
99
+ 3: 'We',
100
+ 4: 'Th',
101
+ 5: 'Fr',
102
+ 6: 'Sa',
103
+ 7: 'Su',
104
+ },
105
+ monthLabels: {
106
+ 1: 'Jan',
107
+ 2: 'Feb',
108
+ 3: 'Mar',
109
+ 4: 'Apr',
110
+ 5: 'May',
111
+ 6: 'Jun',
112
+ 7: 'Jul',
113
+ 8: 'Aug',
114
+ 9: 'Sep',
115
+ 10: 'Oct',
116
+ 11: 'Nov',
117
+ 12: 'Dec',
118
+ },
119
+ weekendLabel: 'Weekend',
120
+ typeLabels: {
121
+ one: 'Occupied',
122
+ two: 'Blocked',
123
+ three: 'Requested',
124
+ },
125
+ },
126
+ de: {
127
+ weekdayLabels: {
128
+ 1: 'Mo',
129
+ 2: 'Di',
130
+ 3: 'Mi',
131
+ 4: 'Do',
132
+ 5: 'Fr',
133
+ 6: 'Sa',
134
+ 7: 'So',
135
+ },
136
+ monthLabels: {
137
+ 1: 'Jan',
138
+ 2: 'Feb',
139
+ 3: 'Mär',
140
+ 4: 'Apr',
141
+ 5: 'Mai',
142
+ 6: 'Jun',
143
+ 7: 'Jul',
144
+ 8: 'Aug',
145
+ 9: 'Sep',
146
+ 10: 'Okt',
147
+ 11: 'Nov',
148
+ 12: 'Dez',
149
+ },
150
+ weekendLabel: 'Wochenende',
151
+ typeLabels: {
152
+ one: 'Belegt',
153
+ two: 'Geblockt',
154
+ three: 'Anfrage',
155
+ },
156
+ },
157
+ };