accomadesc 0.0.13 → 0.1.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 (69) hide show
  1. package/dist/AccoCard.svelte +1 -1
  2. package/dist/AccoCard.svelte.d.ts +3 -2
  3. package/dist/AccoDescription.svelte +1 -1
  4. package/dist/AccoDescription.svelte.d.ts +3 -2
  5. package/dist/AmenitiesCore.svelte +3 -3
  6. package/dist/AmenitiesCore.svelte.d.ts +3 -2
  7. package/dist/BookingRequest.svelte +272 -0
  8. package/dist/BookingRequest.svelte.d.ts +5 -0
  9. package/dist/Calendar.svelte +26 -13
  10. package/dist/Calendar.svelte.d.ts +3 -2
  11. package/dist/CalendarAvailable.svelte +12 -19
  12. package/dist/CalendarAvailable.svelte.d.ts +3 -2
  13. package/dist/CalendarGrid.svelte +22 -0
  14. package/dist/CalendarGrid.svelte.d.ts +5 -0
  15. package/dist/CalendarRows.svelte +22 -0
  16. package/dist/CalendarRows.svelte.d.ts +5 -0
  17. package/dist/ContactForm.svelte +180 -0
  18. package/dist/ContactForm.svelte.d.ts +5 -0
  19. package/dist/LeafletMap.svelte +1 -1
  20. package/dist/LeafletMap.svelte.d.ts +1 -1
  21. package/dist/Photo.svelte +1 -1
  22. package/dist/Photo.svelte.d.ts +3 -2
  23. package/dist/PhotoGallery.svelte +89 -35
  24. package/dist/PhotoGallery.svelte.d.ts +3 -2
  25. package/dist/Pricing.svelte +1 -1
  26. package/dist/Pricing.svelte.d.ts +3 -2
  27. package/dist/PricingShort.svelte +1 -1
  28. package/dist/PricingShort.svelte.d.ts +3 -2
  29. package/dist/Section.svelte +1 -1
  30. package/dist/Section.svelte.d.ts +3 -2
  31. package/dist/Text.svelte +1 -1
  32. package/dist/Text.svelte.d.ts +3 -2
  33. package/dist/Weather.svelte +2 -3
  34. package/dist/Weather.svelte.d.ts +3 -2
  35. package/dist/basic/Avatar.svelte.d.ts +3 -2
  36. package/dist/basic/Button.svelte +6 -3
  37. package/dist/basic/Button.svelte.d.ts +4 -3
  38. package/dist/basic/Icon.svelte.d.ts +3 -2
  39. package/dist/basic/Notes.svelte +83 -0
  40. package/dist/basic/Notes.svelte.d.ts +7 -0
  41. package/dist/basic/Spinner.svelte.d.ts +3 -2
  42. package/dist/basic/TextInput.svelte.d.ts +3 -2
  43. package/dist/helpers/debounce.d.ts +7 -0
  44. package/dist/helpers/debounce.js +49 -0
  45. package/dist/helpers/iCSEventExample.ics +14 -0
  46. package/dist/helpers/normalizeDate.d.ts +2 -0
  47. package/dist/helpers/normalizeDate.js +53 -0
  48. package/dist/helpers/readICS.d.ts +7 -0
  49. package/dist/helpers/readICS.js +94 -0
  50. package/dist/index.d.ts +2 -2
  51. package/dist/index.js +1 -1
  52. package/dist/names/gen.js +3 -3
  53. package/dist/occuplan/OccuPlanAvailableInfo.svelte +38 -0
  54. package/dist/occuplan/OccuPlanAvailableInfo.svelte.d.ts +12 -0
  55. package/dist/occuplan/OccuPlanGrid.svelte +356 -0
  56. package/dist/occuplan/OccuPlanGrid.svelte.d.ts +13 -0
  57. package/dist/occuplan/OccuPlanPicker.svelte +559 -0
  58. package/dist/occuplan/OccuPlanPicker.svelte.d.ts +16 -0
  59. package/dist/occuplan/OccuPlanRows.svelte +360 -0
  60. package/dist/occuplan/OccuPlanRows.svelte.d.ts +13 -0
  61. package/dist/occuplan/OccuPlanWrapper.svelte +113 -0
  62. package/dist/occuplan/OccuPlanWrapper.svelte.d.ts +5 -0
  63. package/dist/occuplan/state.svelte.d.ts +90 -0
  64. package/dist/occuplan/state.svelte.js +383 -0
  65. package/dist/svg/ExtLinkSVG.svelte.d.ts +3 -2
  66. package/dist/svg/LinkSVG.svelte.d.ts +3 -2
  67. package/dist/types.d.ts +75 -4
  68. package/dist/types.js +20 -0
  69. package/package.json +64 -61
@@ -0,0 +1,83 @@
1
+ <script lang="ts">
2
+ import { randomID } from '../names/gen.ts';
3
+
4
+ let {
5
+ disabled,
6
+ changed,
7
+ }: {
8
+ disabled: boolean;
9
+ changed: (value: string) => void;
10
+ } = $props();
11
+
12
+ let divElement: HTMLDivElement;
13
+ let id = randomID();
14
+
15
+ const contentChanged = (e: Event) => {
16
+ const target = e.currentTarget as HTMLDivElement;
17
+ changed(target.getHTML());
18
+ };
19
+
20
+ $effect(() => {
21
+ if (disabled) {
22
+ divElement.innerText = '';
23
+ }
24
+ });
25
+ </script>
26
+
27
+ <div
28
+ bind:this={divElement}
29
+ class:disabled
30
+ id="input-{id}"
31
+ contenteditable={disabled ? null : 'plaintext-only'}
32
+ class="question-input"
33
+ oninput={contentChanged}
34
+ ></div>
35
+
36
+ <style>
37
+ .question-input {
38
+ position: relative;
39
+
40
+ min-width: 400px;
41
+ width: 100%;
42
+ max-width: 800px;
43
+ min-height: 5rem;
44
+ height: 100%;
45
+
46
+ border: var(--main-border);
47
+ border-radius: 1rem;
48
+
49
+ background-color: var(--longinput-bg-color);
50
+
51
+ padding-left: 1.3rem;
52
+ padding-right: 1.3rem;
53
+ padding-top: 0.5rem;
54
+
55
+ line-height: 24px;
56
+
57
+ background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' height='24' width='24'><line x1='0' y1='4' x2='16' y2='4' stroke='rgba(15,15,15,0.5)' stroke-width='0.1' /></svg>");
58
+ background-repeat: repeat;
59
+ }
60
+
61
+ .question-input.disabled {
62
+ border-color: var(--disabled-border-color);
63
+ font: var(--font-disabled-color);
64
+ background-color: var(--longinput-disabled-bg-color);
65
+ }
66
+
67
+ .question-input::after {
68
+ content: '';
69
+ position: absolute;
70
+ border: var(--dashed-border);
71
+ right: 1rem;
72
+ top: 0;
73
+ bottom: 0;
74
+ }
75
+ .question-input::before {
76
+ content: '';
77
+ position: absolute;
78
+ border: var(--dashed-border);
79
+ left: 1rem;
80
+ top: 0;
81
+ bottom: 0;
82
+ }
83
+ </style>
@@ -0,0 +1,7 @@
1
+ type $$ComponentProps = {
2
+ disabled: boolean;
3
+ changed: (value: string) => void;
4
+ };
5
+ declare const Notes: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type Notes = ReturnType<typeof Notes>;
7
+ export default Notes;
@@ -1,8 +1,9 @@
1
- declare const Spinner: import("svelte").Component<{
1
+ type $$ComponentProps = {
2
2
  color?: string;
3
3
  inline?: boolean;
4
4
  height?: string;
5
5
  width?: string;
6
- }, {}, "">;
6
+ };
7
+ declare const Spinner: import("svelte").Component<$$ComponentProps, {}, "">;
7
8
  type Spinner = ReturnType<typeof Spinner>;
8
9
  export default Spinner;
@@ -1,4 +1,4 @@
1
- declare const TextInput: import("svelte").Component<{
1
+ type $$ComponentProps = {
2
2
  placeholder?: string;
3
3
  phonePattern?: string;
4
4
  name?: string;
@@ -28,6 +28,7 @@ declare const TextInput: import("svelte").Component<{
28
28
  focussed?: (name: string, value: string | number) => void;
29
29
  validityChanged?: (valid: boolean, name: string, value: string | number) => void;
30
30
  valueChanged?: (valid: boolean, name: string, value: string | number) => void;
31
- }, {}, "valid" | "value">;
31
+ };
32
+ declare const TextInput: import("svelte").Component<$$ComponentProps, {}, "valid" | "value">;
32
33
  type TextInput = ReturnType<typeof TextInput>;
33
34
  export default TextInput;
@@ -0,0 +1,7 @@
1
+ export type DebounceFunction = () => Promise<boolean>;
2
+ export interface DebounceConfig {
3
+ initialDelay: number;
4
+ debounceDelay: number;
5
+ }
6
+ export declare const DefaultDebounceConfig: DebounceConfig;
7
+ export declare const debounce: (id: string, func: DebounceFunction, config?: DebounceConfig) => Promise<boolean>;
@@ -0,0 +1,49 @@
1
+ import { DateTime as luxon } from 'luxon';
2
+ export const DefaultDebounceConfig = {
3
+ initialDelay: 0,
4
+ debounceDelay: 10000,
5
+ };
6
+ let updateTimestamps = {};
7
+ let nextUpdates = {};
8
+ let scheduled = {};
9
+ export const debounce = async (id, func, config = DefaultDebounceConfig) => {
10
+ //console.log(`DEBOUNCE: ${id}`)
11
+ nextUpdates[id] = func;
12
+ return doDebounce(id, true, config);
13
+ };
14
+ const doDebounce = async (id, firstRun, config) => {
15
+ const now = luxon.utc();
16
+ const priorExecTime = updateTimestamps[id];
17
+ //no prior timestamp, execute and store timestamp
18
+ if (!priorExecTime) {
19
+ if (firstRun && config.initialDelay > 0) {
20
+ setTimeout(() => {
21
+ return doDebounce(id, false, config);
22
+ }, config.initialDelay + 10);
23
+ }
24
+ else {
25
+ const result = await nextUpdates[id]();
26
+ updateTimestamps[id] = now;
27
+ //console.log('INITIAL')
28
+ return result;
29
+ }
30
+ }
31
+ //last execution was more than debounceDelay ms ago
32
+ else if (priorExecTime < now.minus({ milliseconds: config.debounceDelay })) {
33
+ const result = await nextUpdates[id]();
34
+ updateTimestamps[id] = now;
35
+ //console.log('DUE')
36
+ return result;
37
+ }
38
+ //else retry after timeout
39
+ else if (firstRun && !scheduled[id]) {
40
+ //console.log('SCHEDULE')
41
+ scheduled[id] = true;
42
+ setTimeout(() => {
43
+ //console.log('RETRY')
44
+ scheduled[id] = false;
45
+ return doDebounce(id, false, config);
46
+ }, config.debounceDelay + 10);
47
+ }
48
+ return false;
49
+ };
@@ -0,0 +1,14 @@
1
+ BEGIN:VEVENT
2
+ DTSTART;VALUE=DATE:20230207
3
+ DTEND;VALUE=DATE:20230223
4
+ DTSTAMP:20230118T163615Z
5
+ UID:6cfjhjfvp50tldvkbrbgp9m6r0@google.com
6
+ CREATED:20230118T163028Z
7
+ DESCRIPTION:
8
+ LAST-MODIFIED:20230118T163028Z
9
+ LOCATION:
10
+ SEQUENCE:0
11
+ STATUS:CONFIRMED
12
+ SUMMARY:Mertens
13
+ TRANSP:TRANSPARENT
14
+ END:VEVENT
@@ -0,0 +1,2 @@
1
+ import type { DateTime } from 'luxon';
2
+ export declare const normalizeDate: (date?: any) => DateTime;
@@ -0,0 +1,53 @@
1
+ import { DateTime as luxon } from 'luxon';
2
+ export const normalizeDate = (date) => {
3
+ //initialize default return values, for the case the input is not
4
+ //"normalizable"
5
+ const nowUTC = luxon.utc().set({ hour: 12, minute: 0, second: 0, millisecond: 0 });
6
+ //no parameter or falsy
7
+ if (!date) {
8
+ return nowUTC;
9
+ }
10
+ //parameter is an instance of date;
11
+ if (date instanceof Date) {
12
+ // but invalid
13
+ if (Number.isNaN(Number(date))) {
14
+ return nowUTC;
15
+ }
16
+ return luxon.utc(date.getFullYear(), date.getMonth() + 1, date.getDate(), 12);
17
+ }
18
+ //otherwise try different parsing methods
19
+ let pDate;
20
+ //check if it's already a numeric value, assuming millis from start of time
21
+ if (Number.isInteger(date)) {
22
+ pDate = luxon.fromMillis(date);
23
+ if (pDate.isValid) {
24
+ return luxon.utc(pDate.year, pDate.month, pDate.day, 12);
25
+ }
26
+ }
27
+ //check if it has a valueOf function and if that function yields an integer
28
+ if (typeof date.valueOf === 'function' && Number.isInteger(date.valueOf())) {
29
+ pDate = luxon.fromMillis(date.valueOf());
30
+ if (pDate.isValid) {
31
+ return luxon.utc(pDate.year, pDate.month, pDate.day, 12);
32
+ }
33
+ }
34
+ //parse it, as if it is an ISO string
35
+ pDate = luxon.fromISO(date, { setZone: true });
36
+ if (pDate.isValid) {
37
+ return luxon.utc(pDate.year, pDate.month, pDate.day, 12);
38
+ }
39
+ //parse it, as if it is in HTTP format
40
+ //@ts-ignore
41
+ pDate = luxon.fromHTTP(date, { setZone: true });
42
+ if (pDate.isValid) {
43
+ return luxon.utc(pDate.year, pDate.month, pDate.day, 12);
44
+ }
45
+ //parse it, as if it is in SQL format
46
+ //@ts-ignore
47
+ pDate = luxon.fromSQL(date, { setZone: true });
48
+ if (pDate.isValid) {
49
+ return luxon.utc(pDate.year, pDate.month, pDate.day, 12);
50
+ }
51
+ //if nothing helps, return today at noon GMT
52
+ return nowUTC;
53
+ };
@@ -0,0 +1,7 @@
1
+ import type { OccupationCallback } from '../occuplan/state.svelte.js';
2
+ export interface GetEventsResult {
3
+ message: string;
4
+ code: number;
5
+ error: boolean;
6
+ }
7
+ export declare const getEvents: (url: string, eventCallback: OccupationCallback) => Promise<GetEventsResult>;
@@ -0,0 +1,94 @@
1
+ import { DateTime as lx } from 'luxon';
2
+ const extractOccupationType = (line) => {
3
+ try {
4
+ const oTypes = line.split('CATEGORIES:')[1];
5
+ const [first] = oTypes.split(',');
6
+ return first.trim();
7
+ }
8
+ catch (e) {
9
+ console.log('Error occured extracting occupation type from line', line);
10
+ }
11
+ return 'one';
12
+ };
13
+ const readIcsFromResponse = async (resp, eventCallback) => {
14
+ const text = await resp.text();
15
+ //console.log(text)
16
+ let insideEvent = false;
17
+ let arrival = '';
18
+ let leave = '';
19
+ let oType = 'one';
20
+ text.split(/\r?\n/).forEach((line) => {
21
+ switch (true) {
22
+ case /^BEGIN:VEVENT$/.test(line):
23
+ insideEvent = true;
24
+ break;
25
+ case /^DTSTART;VALUE=.*/.test(line) && insideEvent:
26
+ arrival = line;
27
+ break;
28
+ case /^DTEND;VALUE=.*/.test(line) && insideEvent:
29
+ leave = line;
30
+ break;
31
+ case /^CATEGORIES:.*$/.test(line) && insideEvent:
32
+ oType = extractOccupationType(line);
33
+ break;
34
+ case /^END:VEVENT$/.test(line) && insideEvent:
35
+ insideEvent = false;
36
+ eventCallback({
37
+ type: oType,
38
+ arrival: getDate(arrival),
39
+ leave: getDate(leave),
40
+ });
41
+ break;
42
+ }
43
+ });
44
+ };
45
+ export const getEvents = async (url, eventCallback) => {
46
+ let result = {
47
+ message: 'undefined',
48
+ code: 100,
49
+ error: false,
50
+ };
51
+ let resp;
52
+ try {
53
+ resp = await fetch(url, {
54
+ headers: {
55
+ Accept: 'text/calendar',
56
+ },
57
+ //mode: "no-cors"
58
+ });
59
+ result = {
60
+ message: resp.statusText,
61
+ code: resp.status,
62
+ error: resp.status > 299 ? true : false,
63
+ };
64
+ if (resp.status > 299)
65
+ return result;
66
+ await readIcsFromResponse(resp, eventCallback);
67
+ }
68
+ catch (e) {
69
+ console.log('Error occured while fetching events from proxy via calUrl:', e);
70
+ return {
71
+ message: `Fetch threw error: ${e}`,
72
+ code: 500,
73
+ error: true,
74
+ };
75
+ }
76
+ return result;
77
+ };
78
+ const getDate = (icsLine) => {
79
+ //e.g. DTEND;VALUE=DATE:20260818
80
+ const [typePart, valuePart] = icsLine.split('=');
81
+ const dateString = valuePart.split(':')[1];
82
+ let rawDateTime = lx.fromISO(dateString);
83
+ //end date has to be moved back when whole day ending
84
+ if (/^DTEND;VALUE$/.test(typePart)) {
85
+ if (rawDateTime.hour == 0 &&
86
+ rawDateTime.minute == 0 &&
87
+ rawDateTime.second == 0 &&
88
+ rawDateTime.millisecond == 0) {
89
+ rawDateTime = rawDateTime.plus({ hour: 12 });
90
+ }
91
+ }
92
+ //normalize to noon
93
+ return rawDateTime.set({ hour: 12, minute: 0, second: 0, millisecond: 0 });
94
+ };
package/dist/index.d.ts CHANGED
@@ -17,6 +17,6 @@ import PricingShort from './PricingShort.svelte';
17
17
  import Section from './Section.svelte';
18
18
  import Text from './Text.svelte';
19
19
  import Weather from './Weather.svelte';
20
- export type { GridPhoto, LeafletMap as LeafletMapI, LeafletMapContent, Calendar as CalendarI, CalendarContent, CalendarAvailable as CalendarAvailableI, CalendarAvailableContent, Text as TextI, TextContent, Weather as WeatherI, WeatherContent, Photo as PhotoI, PhotoContent, PhotoGallery as PhotoGalleryI, PhotoGalleryContent, Pricing as PricingI, PricingContent, PricingShort as PricingShortI, PricingShortContent, PricingEntry, PricingRange, StaticRangeDate, StaticPricingRange, AmenitiesCore as AmenitiesCoreI, AmenitiesCoreContent, AccoCard as AccoCardI, AccoCardContent, CardContent, AccoDescription as AccoDescriptionI, AccoDescriptionContent, Section as SectionI, I18nFacade, Acco as AccoI, } from './types.ts';
21
- export { PRICING_COLUMNS } from './types.ts';
20
+ export type { GridPhoto, LeafletMap as LeafletMapI, LeafletMapContent, Calendar as CalendarI, CalendarContent, CalendarAvailable as CalendarAvailableI, CalendarAvailableContent, Text as TextI, TextContent, Weather as WeatherI, WeatherContent, Photo as PhotoI, PhotoContent, PhotoGallery as PhotoGalleryI, PhotoGalleryContent, Pricing as PricingI, PricingContent, PricingShort as PricingShortI, PricingShortContent, PricingEntry, PricingRange, StaticRangeDate, StaticPricingRange, AmenitiesCore as AmenitiesCoreI, AmenitiesCoreContent, AccoCard as AccoCardI, AccoCardContent, CardContent, AccoDescription as AccoDescriptionI, AccoDescriptionContent, Section as SectionI, I18nFacade, Acco as AccoI, } from './types.js';
21
+ export { PRICING_COLUMNS } from './types.js';
22
22
  export { randomID, randomName, Avatar, Button, Icon, Spinner, TextInput, AccoCard, AccoDescription, AmenitiesCore, Calendar, CalendarAvailable, LeafletMap, Photo, PhotoGallery, Pricing, PricingShort, Section, Text, Weather, };
package/dist/index.js CHANGED
@@ -18,5 +18,5 @@ import PricingShort from './PricingShort.svelte';
18
18
  import Section from './Section.svelte';
19
19
  import Text from './Text.svelte';
20
20
  import Weather from './Weather.svelte';
21
- export { PRICING_COLUMNS } from './types.ts';
21
+ export { PRICING_COLUMNS } from './types.js';
22
22
  export { randomID, randomName, Avatar, Button, Icon, Spinner, TextInput, AccoCard, AccoDescription, AmenitiesCore, Calendar, CalendarAvailable, LeafletMap, Photo, PhotoGallery, Pricing, PricingShort, Section, Text, Weather, };
package/dist/names/gen.js CHANGED
@@ -1,5 +1,5 @@
1
- import adjectives from './adjectives.json';
2
- import plants from './plants.json';
1
+ import adjectives from './adjectives.json' with { type: 'json' };
2
+ import plants from './plants.json' with { type: 'json' };
3
3
  const rndAdjective = () => {
4
4
  let i = Math.floor(Math.random() * adjectives.length);
5
5
  return adjectives[i];
@@ -12,7 +12,7 @@ const rndSpecies = () => {
12
12
  };
13
13
  const capWord = (w) => {
14
14
  const [firstLetter, ...rest] = w;
15
- return `${firstLetter.toLocaleUpperCase()}${rest.join("")}`.trim();
15
+ return `${firstLetter.toLocaleUpperCase()}${rest.join('')}`.trim();
16
16
  };
17
17
  const rndName = () => {
18
18
  const adj = rndAdjective();
@@ -0,0 +1,38 @@
1
+ <script lang="ts">
2
+ import { DateTime } from 'luxon';
3
+ import { normalizeDate } from '../helpers/normalizeDate.js';
4
+ import type { AvailableSpans } from './state.svelte.js';
5
+ import { getContext, setContext, type Snippet } from 'svelte';
6
+ import { OCCUPATION_STATE, OccupationState } from './state.svelte.js';
7
+ import Spinner from '../basic/Spinner.svelte';
8
+ import { browser } from '$app/environment';
9
+
10
+ let {
11
+ url,
12
+ search = [3, 7, 14],
13
+ maxFutureDate = normalizeDate(DateTime.utc().plus({ years: 1 })),
14
+ children,
15
+ }: {
16
+ url: string;
17
+ search?: number[];
18
+ maxFutureDate?: DateTime;
19
+ children: Snippet<[AvailableSpans]>;
20
+ } = $props();
21
+
22
+ const oStateID = `i-${url}-${OCCUPATION_STATE}`;
23
+ let occupationState: OccupationState = $state(getContext(oStateID));
24
+
25
+ $effect(() => {
26
+ if (!occupationState && browser) {
27
+ occupationState = new OccupationState(url);
28
+ setContext(oStateID, occupationState);
29
+ }
30
+ });
31
+ let av = $derived(occupationState ? occupationState.calcAvailability(search, maxFutureDate) : {});
32
+ </script>
33
+
34
+ {#if !occupationState || occupationState.loading}
35
+ <Spinner />
36
+ {/if}
37
+
38
+ {@render children(av)}
@@ -0,0 +1,12 @@
1
+ import { DateTime } from 'luxon';
2
+ import type { AvailableSpans } from './state.svelte.js';
3
+ import { type Snippet } from 'svelte';
4
+ type $$ComponentProps = {
5
+ url: string;
6
+ search?: number[];
7
+ maxFutureDate?: DateTime;
8
+ children: Snippet<[AvailableSpans]>;
9
+ };
10
+ declare const OccuPlanAvailableInfo: import("svelte").Component<$$ComponentProps, {}, "">;
11
+ type OccuPlanAvailableInfo = ReturnType<typeof OccuPlanAvailableInfo>;
12
+ export default OccuPlanAvailableInfo;