accomadesc 0.3.34 → 0.3.36

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.
@@ -1,6 +1,5 @@
1
1
  <script lang="ts">
2
2
  import type { BookingRequestContent, I18nFacade } from './types.js';
3
- import { getContext } from 'svelte';
4
3
  import Button from './basic/Button.svelte';
5
4
  import Notes from './basic/Notes.svelte';
6
5
  import Spinner from './basic/Spinner.svelte';
@@ -55,9 +54,9 @@
55
54
  let sending = $state(false);
56
55
  let disabled = $derived(preview || errored || successfullySent);
57
56
 
58
- let occupationState: OccupationState = getOccupationState(calUrl);
57
+ let occupationState: OccupationState = $derived(getOccupationState(calUrl));
59
58
  let invalid = $derived(
60
- occupationState && arrival && leave ? occupationState.validRequest(arrival, leave) : false,
59
+ occupationState && arrival && leave ? !occupationState.validRequest(arrival, leave) : false,
61
60
  );
62
61
  const messageChanged = (value: string) => {
63
62
  message = value;
@@ -127,6 +126,9 @@
127
126
 
128
127
  arrival = undefined;
129
128
  leave = undefined;
129
+ email = '';
130
+ name = '';
131
+ message = '';
130
132
  inputDatesEngaged = false;
131
133
  sending = false;
132
134
 
@@ -72,6 +72,9 @@
72
72
  errored = true;
73
73
  }
74
74
  sending = false;
75
+ email = '';
76
+ name = '';
77
+ question = '';
75
78
 
76
79
  setTimeout(() => {
77
80
  errored = false;
@@ -19,14 +19,13 @@
19
19
  close: () => void;
20
20
  } & I18nFacade = $props();
21
21
 
22
- let allTranslations = $state(supportedLangs);
23
22
  const pathForLang = (lang: string) => {
24
23
  const pathElements = currentPath.split('/');
25
24
  //initial slash results in empty string real first element
26
25
  if (pathElements.length == 1) return `/${lang}`;
27
26
 
28
27
  const firstElement = pathElements[1];
29
- if (allTranslations?.includes(firstElement)) {
28
+ if (supportedLangs?.includes(firstElement)) {
30
29
  return ['', lang, ...pathElements.slice(2)].join('/');
31
30
  } else {
32
31
  return ['', lang, ...pathElements.slice(1)].join('/');
@@ -46,11 +45,11 @@
46
45
  </li>
47
46
  {/each}
48
47
  </ul>
49
- {#if allTranslations && allTranslations.length > 1}
48
+ {#if supportedLangs && supportedLangs.length > 1}
50
49
  <fieldset>
51
50
  <legend>{translateFunc ? translateFunc('lang') : ''}</legend>
52
51
 
53
- {#each allTranslations as langKey}
52
+ {#each supportedLangs as langKey}
54
53
  <a
55
54
  data-sveltekit-keepfocus
56
55
  data-sveltekit-noscroll
@@ -17,7 +17,7 @@
17
17
  import Button from './basic/Button.svelte';
18
18
  import { fallbackCSS } from './style.js';
19
19
  import { GLOBAL_STATE, GlobalState } from './state.svelte';
20
- import { setContext } from 'svelte';
20
+ import { setContext, untrack } from 'svelte';
21
21
 
22
22
  let {
23
23
  hero,
@@ -44,12 +44,11 @@
44
44
  calendarTranslation,
45
45
  }: PageProps & I18nFacade = $props();
46
46
 
47
- setContext(GLOBAL_STATE, new GlobalState(disableLinks));
48
-
49
- let pageTitle = hero && hero.title ? hero.title : header ? header : title;
47
+ // initialize global state, use the initial value of disableLinks
48
+ setContext(GLOBAL_STATE, new GlobalState(untrack(() => disableLinks)));
50
49
 
50
+ let pageTitle = $derived(hero && hero.title ? hero.title : header ? header : title);
51
51
  let langSelectorOpen = $state(false);
52
- let allTranslations = $state(supportedLangs);
53
52
 
54
53
  let currentPath = $derived(page.url.pathname);
55
54
  const pathForLang = (lang: string) => {
@@ -58,7 +57,7 @@
58
57
  if (pathElements.length == 1) return `/${lang}`;
59
58
 
60
59
  const firstElement = pathElements[1];
61
- if (allTranslations?.includes(firstElement)) {
60
+ if (supportedLangs?.includes(firstElement)) {
62
61
  return ['', lang, ...pathElements.slice(2)].join('/');
63
62
  } else {
64
63
  return ['', lang, ...pathElements.slice(1)].join('/');
@@ -192,11 +191,11 @@
192
191
  {/if}
193
192
  {/if}
194
193
 
195
- {#if langSelectorOpen && allTranslations && allTranslations.length > 1}
194
+ {#if langSelectorOpen && supportedLangs && supportedLangs.length > 1}
196
195
  <fieldset class="lang-selector" transition:fade>
197
196
  <legend>{translateFunc ? translateFunc('lang') : ''}</legend>
198
197
 
199
- {#each allTranslations as langKey}
198
+ {#each supportedLangs as langKey}
200
199
  <a
201
200
  class={{
202
201
  'lang-link': true,
@@ -4,7 +4,7 @@
4
4
 
5
5
  let { nav, ref, translateFunc, currentLang }: { nav: Nav; ref?: string } & I18nFacade = $props();
6
6
 
7
- const contentRef = ref ?? 'footer_html';
7
+ const contentRef = $derived(ref ?? 'footer_html');
8
8
  </script>
9
9
 
10
10
  <footer>
@@ -24,9 +24,9 @@
24
24
  currentLang,
25
25
  }: PricingContent & I18nFacade = $props();
26
26
 
27
- if (!ranges || (ranges.length == 0 && entries)) {
28
- ranges = entries;
29
- }
27
+ $effect(() => {
28
+ if (!ranges || (ranges.length == 0 && entries)) ranges = entries;
29
+ });
30
30
 
31
31
  const colHeaderStyle: Record<PricingColumn, string> = {
32
32
  timeRange: 'width: 20%;',
@@ -14,7 +14,10 @@
14
14
  formatFunc,
15
15
  }: PricingShortContent & I18nFacade = $props();
16
16
 
17
- if (!ranges && entries) ranges = entries;
17
+ $effect(() => {
18
+ //unclear if this is even needed and working as expected
19
+ if (!ranges && entries) ranges = entries;
20
+ });
18
21
 
19
22
  let filteredEntries = $derived.by(() => {
20
23
  let now = DateTime.now();
@@ -53,7 +53,7 @@
53
53
 
54
54
  let translatedHeader = $derived(header && translateFunc ? translateFunc(header) : '');
55
55
 
56
- let gridTemplateColumns = $state(`repeat(${columnCount}, 1fr)`);
56
+ let gridTemplateColumns = $state(`repeat(2, 1fr)`);
57
57
 
58
58
  let originalPadding = $state(padding);
59
59
 
@@ -0,0 +1,31 @@
1
+ import { type I18nFacade, type OccuplanTranslations } from 'accomadesc';
2
+ import type { CookieSelection, Translation as CookieTranslation } from 'gdpr-cooco-banner';
3
+ import { DateTime } from 'luxon';
4
+ import type { SiteConfig } from './types.ts';
5
+ interface FullTranslation {
6
+ calendar: OccuplanTranslations;
7
+ cookies: CookieTranslation;
8
+ site: Record<string, string>;
9
+ }
10
+ export declare class SiteState implements I18nFacade {
11
+ fullTranslations: Record<string, FullTranslation>;
12
+ calendarTranslations: Record<string, OccuplanTranslations>;
13
+ cookieTranslations: Record<string, CookieTranslation>;
14
+ siteTranslations: Record<string, Record<string, string>>;
15
+ supportedLangs: string[];
16
+ isMenuOpen: boolean;
17
+ cookieSelection: CookieSelection;
18
+ currentLang: string;
19
+ translations: Record<string, Record<string, string>>;
20
+ calendarTranslation: OccuplanTranslations;
21
+ cookieTranslation: CookieTranslation;
22
+ formats: Record<string, Record<string, any>>;
23
+ selectedTheme: 'light' | 'dark';
24
+ selectedThemeInitialized: boolean;
25
+ constructor(siteConfig: SiteConfig, lang: string | undefined);
26
+ updateCurrentLang: (lang: string) => string;
27
+ translateFunc: (ref: string) => string;
28
+ formatFunc: (ref: string, props: Record<string, any>) => string;
29
+ formatDateFunc: (d: DateTime | string) => string;
30
+ }
31
+ export {};
@@ -0,0 +1,69 @@
1
+ import { format } from 'accomadesc';
2
+ import { DateTime } from 'luxon';
3
+ export class SiteState {
4
+ fullTranslations = {};
5
+ calendarTranslations = {};
6
+ cookieTranslations = {};
7
+ siteTranslations = {};
8
+ supportedLangs = $state(['en']);
9
+ isMenuOpen = $state(false);
10
+ cookieSelection = $state({
11
+ analytics: false,
12
+ marketing: false,
13
+ preferences: false,
14
+ necessary: true,
15
+ });
16
+ currentLang = $state('en');
17
+ translations = $state(this.siteTranslations);
18
+ calendarTranslation = $derived(this.calendarTranslations[this.currentLang]);
19
+ cookieTranslation = $state(this.cookieTranslations[this.currentLang]);
20
+ formats = $state({});
21
+ selectedTheme = $state('light');
22
+ selectedThemeInitialized = $state(false);
23
+ constructor(siteConfig, lang) {
24
+ if (!lang || !siteConfig.lang.supportedLangs.includes(lang)) {
25
+ this.currentLang = siteConfig.lang.defaultLang;
26
+ }
27
+ else {
28
+ this.currentLang = lang;
29
+ }
30
+ this.fullTranslations = siteConfig.lang.translations;
31
+ for (const lang in this.fullTranslations) {
32
+ this.calendarTranslations[lang] = this.fullTranslations[lang].calendar;
33
+ this.siteTranslations[lang] = this.fullTranslations[lang].site;
34
+ this.cookieTranslations[lang] = this.fullTranslations[lang].cookies;
35
+ }
36
+ this.supportedLangs = siteConfig.lang.supportedLangs;
37
+ this.formats = siteConfig.lang.formats;
38
+ }
39
+ updateCurrentLang = (lang) => (this.currentLang = lang);
40
+ translateFunc = (ref) => {
41
+ if (!ref)
42
+ return 'UNDEF';
43
+ const current = this.translations[this.currentLang];
44
+ if (!current[ref])
45
+ return '';
46
+ return this.translations[this.currentLang][ref];
47
+ };
48
+ formatFunc = (ref, props) => {
49
+ const fString = this.formats[this.currentLang][ref];
50
+ if (!fString) {
51
+ console.log('missing formatFunc', ref);
52
+ return '';
53
+ }
54
+ let formatted = format(fString, props);
55
+ return formatted;
56
+ };
57
+ formatDateFunc = (d) => {
58
+ let f = 'yyyy-MM-dd';
59
+ if (this.formats[this.currentLang]?.dateFormat) {
60
+ f = this.formats[this.currentLang].dateFormat;
61
+ }
62
+ let date;
63
+ if (typeof d === 'string')
64
+ date = DateTime.fromISO(d);
65
+ else
66
+ date = d;
67
+ return date.toFormat(f);
68
+ };
69
+ }
@@ -141,7 +141,7 @@
141
141
  let innerShadowWidth = $derived(activated ? size / 16 : size / 8);
142
142
  let outerShadowWidth = $derived(activated ? size / 8 : size / 4);
143
143
 
144
- const borderRadius = $state(size / 1.8);
144
+ const borderRadius = $derived(size / 1.8);
145
145
 
146
146
  let buttonWidth = $derived.by(() => {
147
147
  if (iconName && !text) {
@@ -79,16 +79,26 @@ const getDate = (icsLine) => {
79
79
  //e.g. DTEND;VALUE=DATE:20260818
80
80
  const [typePart, valuePart] = icsLine.split('=');
81
81
  const dateString = valuePart.split(':')[1];
82
- let rawDateTime = lx.fromISO(dateString);
82
+ //console.log(dateString);
83
+ const year = parseInt(dateString.slice(0, 4));
84
+ const month = parseInt(dateString.slice(4, 6));
85
+ const day = parseInt(dateString.slice(6, 8));
86
+ let rawDateTime = lx.utc().set({
87
+ year: year, month: month, day: day,
88
+ hour: 12, minute: 0, second: 0, millisecond: 0
89
+ });
90
+ return rawDateTime;
83
91
  //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 });
92
+ //if (/^DTEND;VALUE$/.test(typePart)) {
93
+ // if (
94
+ // rawDateTime.hour == 0 &&
95
+ // rawDateTime.minute == 0 &&
96
+ // rawDateTime.second == 0 &&
97
+ // rawDateTime.millisecond == 0
98
+ // ) {
99
+ // rawDateTime = rawDateTime.plus({ hour: 12 });
100
+ // }
101
+ //}
102
+ ////normalize to noon
103
+ //return rawDateTime.set({ hour: 12, minute: 0, second: 0, millisecond: 0 });
94
104
  };
@@ -23,8 +23,7 @@
23
23
  children: Snippet<[AvailableSpans]>;
24
24
  } = $props();
25
25
 
26
- let occupationState: OccupationState = getOccupationState(url, debug);
27
-
26
+ let occupationState: OccupationState = $derived(getOccupationState(url, debug));
28
27
  let av = $derived(occupationState ? occupationState.calcAvailability(search, maxFutureDate) : {});
29
28
 
30
29
  onMount(() => {
@@ -49,7 +49,7 @@
49
49
 
50
50
  const id = randomID();
51
51
 
52
- let occupationState: OccupationState = getOccupationState(url, debug);
52
+ let occupationState: OccupationState = $derived(getOccupationState(url, debug));
53
53
 
54
54
  //let formatFun = $derived(Sqrl.compile(monthHeaderFormat, { useWith: true }));
55
55
  const monthHeader = (monthNum: MonthNumbers, year: number): string => {
@@ -56,7 +56,7 @@
56
56
  dateSelected?: (arrival: DateTime, leave: DateTime) => void;
57
57
  } = $props();
58
58
 
59
- let occupationState: OccupationState = getOccupationState(url, debug);
59
+ let occupationState: OccupationState = $derived(getOccupationState(url, debug));
60
60
 
61
61
  const monthHeader = (monthNum: MonthNumbers, year: number): string => {
62
62
  const monthLabel = monthLabels[monthNum];
@@ -103,8 +103,17 @@
103
103
  page -= 1;
104
104
  };
105
105
 
106
- let requestStart: DateTime | undefined = $state(arrival);
107
- let requestEnd: DateTime | undefined = $state(leave);
106
+ let requestStart: DateTime | undefined = $state();
107
+ let requestEnd: DateTime | undefined = $state();
108
+
109
+ $effect(() => {
110
+ requestStart = arrival;
111
+ });
112
+
113
+ $effect(() => {
114
+ requestEnd = leave;
115
+ });
116
+
108
117
  let earliestStart: DateTime | undefined = $derived(
109
118
  occupationState ? occupationState.earliestRequestStart(requestEnd) : undefined,
110
119
  );
@@ -47,7 +47,7 @@
47
47
 
48
48
  const id = randomID();
49
49
 
50
- let occupationState: OccupationState = getOccupationState(url, debug);
50
+ let occupationState: OccupationState = $derived(getOccupationState(url, debug));
51
51
 
52
52
  let page: number = $state(0);
53
53
  let rfMonth: number | DateTime = $derived(
@@ -324,7 +324,8 @@ export class OccupationState {
324
324
  };
325
325
  validRequest = (from, to) => {
326
326
  //TODO take min nights into account
327
- return !this.occupations.find((o) => o.arrival < to && o.leave > from);
327
+ const found = this.occupations.find((o) => o.arrival < to && o.leave > from);
328
+ return !found;
328
329
  };
329
330
  occupationStyle = (d, highlightWeekend = false, maxDate) => {
330
331
  const valid = validDay(d);
@@ -410,7 +411,7 @@ export class OccupationState {
410
411
  export const getOccupationState = (url, debug = false) => {
411
412
  if (debug)
412
413
  console.log('Get OState /w url', url);
413
- const stateID = `i-${url}-${OCCUPATION_STATE}`;
414
+ const stateID = Symbol(`i-${url}-${OCCUPATION_STATE}`);
414
415
  let _instance = getContext(stateID);
415
416
  if (_instance)
416
417
  return _instance;
@@ -1,4 +1,4 @@
1
- export declare const GLOBAL_STATE = "GLOBAL_STATE";
1
+ export declare const GLOBAL_STATE: unique symbol;
2
2
  export declare class GlobalState {
3
3
  disableLinks: boolean;
4
4
  constructor(disableLinks: boolean);
@@ -1,4 +1,4 @@
1
- export const GLOBAL_STATE = 'GLOBAL_STATE';
1
+ export const GLOBAL_STATE = Symbol('GLOBAL_STATE');
2
2
  export class GlobalState {
3
3
  disableLinks = $state(false);
4
4
  constructor(disableLinks) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "accomadesc",
3
- "version": "0.3.34",
3
+ "version": "0.3.36",
4
4
  "files": [
5
5
  "dist",
6
6
  "!dist/**/*.test.*",
@@ -26,16 +26,16 @@
26
26
  "devDependencies": {
27
27
  "@sveltejs/adapter-auto": "^3.3.1",
28
28
  "@sveltejs/adapter-static": "^3.0.10",
29
- "@sveltejs/kit": "^2.49.0",
30
- "@sveltejs/package": "^2.5.6",
29
+ "@sveltejs/kit": "^2.49.2",
30
+ "@sveltejs/package": "^2.5.7",
31
31
  "@sveltejs/vite-plugin-svelte": "^5.1.1",
32
32
  "@types/luxon": "^3.7.1",
33
33
  "gdpr-cooco-banner": "^0.0.11",
34
- "prettier": "^3.6.2",
35
- "prettier-plugin-svelte": "^3.4.0",
36
- "publint": "^0.3.15",
37
- "svelte": "^5.43.14",
38
- "svelte-check": "^4.3.4",
34
+ "prettier": "^3.7.4",
35
+ "prettier-plugin-svelte": "^3.4.1",
36
+ "publint": "^0.3.16",
37
+ "svelte": "^5.46.1",
38
+ "svelte-check": "^4.3.5",
39
39
  "typescript": "^5.9.3",
40
40
  "vite": "^6.4.1"
41
41
  },