@code-collective/booking-widget 1.0.12 → 1.0.13

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/package.json CHANGED
@@ -1,58 +1,58 @@
1
- {
2
- "name": "@code-collective/booking-widget",
3
- "version": "1.0.12",
4
- "type": "module",
5
- "main": "dist/booking-widget.umd.cjs",
6
- "module": "dist/booking-widget.js",
7
- "svelte": "src/lib/index.ts",
8
- "exports": {
9
- ".": {
10
- "svelte": "./src/lib/index.ts",
11
- "import": "./dist/booking-widget.js",
12
- "require": "./dist/booking-widget.umd.cjs"
13
- },
14
- "./style.css": "./dist/booking-widget.css",
15
- "./elements": "./dist/booking-widget.min.js"
16
- },
17
- "files": [
18
- "dist",
19
- "src/lib",
20
- "!src/lib/**/*.test.ts",
21
- "!src/lib/test",
22
- "CHANGELOG.md"
23
- ],
24
- "scripts": {
25
- "dev": "vite",
26
- "build": "vite build",
27
- "prepublishOnly": "npm run build && npm run build:elements",
28
- "build:elements": "vite build --mode elements",
29
- "postbuild:elements": "node -e \"const{readFileSync:r}=require('fs'),{createHash:h}=require('crypto');['dist/booking-widget.min.js','dist/booking-widget.min.css'].forEach(f=>{const d=h('sha384').update(r(f)).digest('base64');console.log(f+' -> sha384-'+d)})\"",
30
- "build:demo": "vite build --mode demo",
31
- "preview": "vite preview",
32
- "check": "svelte-check --tsconfig ./tsconfig.json",
33
- "test": "vitest run",
34
- "release": "node scripts/publish.cjs"
35
- },
36
- "devDependencies": {
37
- "@sveltejs/vite-plugin-svelte": "^7.3.0",
38
- "@testing-library/svelte": "^5.4.2",
39
- "@tsconfig/svelte": "^5.0.0",
40
- "jsdom": "^30.0.1",
41
- "svelte": "^5.0.0",
42
- "svelte-check": "^4.0.0",
43
- "typescript": "^5.5.0",
44
- "vite": "^8.2.2",
45
- "vitest": "^5.0.0"
46
- },
47
- "peerDependencies": {
48
- "svelte": "^5.0.0"
49
- },
50
- "peerDependenciesMeta": {
51
- "svelte": {
52
- "optional": true
53
- }
54
- },
55
- "dependencies": {
56
- "openapi-fetch": "^0.17.0"
57
- }
58
- }
1
+ {
2
+ "name": "@code-collective/booking-widget",
3
+ "version": "1.0.13",
4
+ "type": "module",
5
+ "main": "dist/booking-widget.umd.cjs",
6
+ "module": "dist/booking-widget.js",
7
+ "svelte": "src/lib/index.ts",
8
+ "exports": {
9
+ ".": {
10
+ "svelte": "./src/lib/index.ts",
11
+ "import": "./dist/booking-widget.js",
12
+ "require": "./dist/booking-widget.umd.cjs"
13
+ },
14
+ "./style.css": "./dist/booking-widget.css",
15
+ "./elements": "./dist/booking-widget.min.js"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "src/lib",
20
+ "!src/lib/**/*.test.ts",
21
+ "!src/lib/test",
22
+ "CHANGELOG.md"
23
+ ],
24
+ "scripts": {
25
+ "dev": "vite",
26
+ "build": "vite build",
27
+ "prepublishOnly": "npm run build && npm run build:elements",
28
+ "build:elements": "vite build --mode elements",
29
+ "postbuild:elements": "node -e \"const{readFileSync:r}=require('fs'),{createHash:h}=require('crypto');['dist/booking-widget.min.js','dist/booking-widget.min.css'].forEach(f=>{const d=h('sha384').update(r(f)).digest('base64');console.log(f+' -> sha384-'+d)})\"",
30
+ "build:demo": "vite build --mode demo",
31
+ "preview": "vite preview",
32
+ "check": "svelte-check --tsconfig ./tsconfig.json",
33
+ "test": "vitest run",
34
+ "release": "node scripts/publish.cjs"
35
+ },
36
+ "devDependencies": {
37
+ "@sveltejs/vite-plugin-svelte": "^7.3.0",
38
+ "@testing-library/svelte": "^5.4.2",
39
+ "@tsconfig/svelte": "^5.0.0",
40
+ "jsdom": "^30.0.1",
41
+ "svelte": "^5.0.0",
42
+ "svelte-check": "^4.0.0",
43
+ "typescript": "^5.5.0",
44
+ "vite": "^8.2.2",
45
+ "vitest": "^5.0.0"
46
+ },
47
+ "peerDependencies": {
48
+ "svelte": "^5.0.0"
49
+ },
50
+ "peerDependenciesMeta": {
51
+ "svelte": {
52
+ "optional": true
53
+ }
54
+ },
55
+ "dependencies": {
56
+ "openapi-fetch": "^0.17.0"
57
+ }
58
+ }
@@ -1,21 +1,21 @@
1
- <script lang="ts">
2
- // Puts a host in context for everything beneath it. The host itself is still built by the consumer -
3
- // createBookingHost() works anywhere, including a module shared across several Astro islands, and this
4
- // only decides which components can see it.
5
- import type { Snippet } from 'svelte';
6
- import type { BookingHost } from './host.svelte';
7
- import { setBookingHostContext } from './booking-context';
8
-
9
- interface Props {
10
- host: BookingHost;
11
- children: Snippet;
12
- }
13
- let { host, children }: Props = $props();
14
-
15
- // Read once, deliberately: context is set at initialisation and a provider serves one host for its
16
- // lifetime. Swapping hosts mid-flight would strand every component already reading the old one.
17
- // svelte-ignore state_referenced_locally
18
- setBookingHostContext(host);
19
- </script>
20
-
21
- {@render children()}
1
+ <script lang="ts">
2
+ // Puts a host in context for everything beneath it. The host itself is still built by the consumer -
3
+ // createBookingHost() works anywhere, including a module shared across several Astro islands, and this
4
+ // only decides which components can see it.
5
+ import type { Snippet } from 'svelte';
6
+ import type { BookingHost } from './host.svelte';
7
+ import { setBookingHostContext } from './booking-context';
8
+
9
+ interface Props {
10
+ host: BookingHost;
11
+ children: Snippet;
12
+ }
13
+ let { host, children }: Props = $props();
14
+
15
+ // Read once, deliberately: context is set at initialisation and a provider serves one host for its
16
+ // lifetime. Swapping hosts mid-flight would strand every component already reading the old one.
17
+ // svelte-ignore state_referenced_locally
18
+ setBookingHostContext(host);
19
+ </script>
20
+
21
+ {@render children()}
@@ -1,26 +1,26 @@
1
- <script lang="ts">
2
- import type { BookingApi } from './api';
3
- import type { CartOverviewState } from './config';
4
- import { CartManager } from './cart-manager';
5
- import { createCartOverview } from './cart-overview.svelte';
6
- import CartBarView from './CartBarView.svelte';
7
- import { getBookingHostContext, requireBookingService } from './booking-context';
8
-
9
- interface Props {
10
- api?: BookingApi;
11
- cartManager?: CartManager;
12
- // Lets a host render its own summary against the same state the bar is in, rather than inferring it from
13
- // an empty DOM - see cart-overview.svelte.ts.
14
- onStateChange?: (state: CartOverviewState) => void;
15
- }
16
- let { api, cartManager, onStateChange }: Props = $props();
17
-
18
- const bookingHost = getBookingHostContext();
19
- const overview = createCartOverview(
20
- () => requireBookingService(api ?? bookingHost?.api, 'CartBar', 'api'),
21
- () => requireBookingService(cartManager ?? bookingHost?.cartManager, 'CartBar', 'cartManager'),
22
- (s) => onStateChange?.(s),
23
- );
24
- </script>
25
-
26
- <CartBarView cart={overview.cart} state={overview.state} onRetry={overview.reload} />
1
+ <script lang="ts">
2
+ import type { BookingApi } from './api';
3
+ import type { CartOverviewState } from './config';
4
+ import { CartManager } from './cart-manager';
5
+ import { createCartOverview } from './cart-overview.svelte';
6
+ import CartBarView from './CartBarView.svelte';
7
+ import { getBookingHostContext, requireBookingService } from './booking-context';
8
+
9
+ interface Props {
10
+ api?: BookingApi;
11
+ cartManager?: CartManager;
12
+ // Lets a host render its own summary against the same state the bar is in, rather than inferring it from
13
+ // an empty DOM - see cart-overview.svelte.ts.
14
+ onStateChange?: (state: CartOverviewState) => void;
15
+ }
16
+ let { api, cartManager, onStateChange }: Props = $props();
17
+
18
+ const bookingHost = getBookingHostContext();
19
+ const overview = createCartOverview(
20
+ () => requireBookingService(api ?? bookingHost?.api, 'CartBar', 'api'),
21
+ () => requireBookingService(cartManager ?? bookingHost?.cartManager, 'CartBar', 'cartManager'),
22
+ (s) => onStateChange?.(s),
23
+ );
24
+ </script>
25
+
26
+ <CartBarView cart={overview.cart} state={overview.state} onRetry={overview.reload} />
@@ -1,78 +1,78 @@
1
- <script lang="ts">
2
- import type { CheckoutCartDetailDto } from './client-types';
3
- import type { CartOverviewState } from './config';
4
- import { formatCurrency } from './currency';
5
- import { postMessage } from './messages';
6
- import CountdownTimer from './CountdownTimer.svelte';
7
- import { cartDeadline } from './cart-expiry';
8
-
9
- interface Props {
10
- cart: CheckoutCartDetailDto | null;
11
- state?: CartOverviewState;
12
- onRetry?: () => void;
13
- }
14
- let { cart, state = 'ready', onRetry }: Props = $props();
15
-
16
- let itemCount = $derived(cart?.items.length ?? 0);
17
-
18
- let totalLabel = $derived(() => {
19
- if (!cart || cart.items.length === 0) return '';
20
- const currency = cart.items[0].currencyCode;
21
- const total = cart.items.reduce((sum, i) => sum + i.amount, 0);
22
- return formatCurrency(total, currency, 2, 2);
23
- });
24
-
25
- let expiresAt = $derived(() => cart ? cartDeadline(cart) : new Date());
26
- </script>
27
-
28
- {#if state === 'error'}
29
- <!-- An empty cart and a cart that could not be read used to render identically (as nothing), which left a
30
- shopper on a narrow layout with no route to checkout and no sign that anything had gone wrong. -->
31
- <div class="cart-bar bw-widget" role="alert">
32
- <div class="cart-info">
33
- <span class="item-count">Cart unavailable</span>
34
- <span class="error-detail">We could not load your cart just now.</span>
35
- </div>
36
- <button class="btn btn-primary" onclick={() => onRetry?.()}>Retry</button>
37
- </div>
38
- {:else if cart && cart.items.length > 0}
39
- <div class="cart-bar bw-widget">
40
- <div class="cart-info">
41
- <span class="item-count">{itemCount === 1 ? '1 item' : `${itemCount} items`} <CountdownTimer expiresAt={expiresAt()} /></span>
42
- <span class="total">{totalLabel()}</span>
43
- </div>
44
- <button class="btn btn-primary" onclick={() => postMessage({ type: 'modal:open' })}>
45
- Checkout
46
- </button>
47
- </div>
48
- {/if}
49
-
50
- <style>
51
- .cart-bar {
52
- display: flex;
53
- align-items: center;
54
- justify-content: space-between;
55
- padding: 12px 16px;
56
- background: white;
57
- border-top: 1px solid var(--bw-color-border);
58
- box-shadow: 0 -2px 8px rgba(0,0,0,0.06);
59
- width: 100%;
60
- }
61
- .cart-info {
62
- display: flex;
63
- flex-direction: column;
64
- gap: 2px;
65
- }
66
- .item-count {
67
- font-size: 12px;
68
- color: var(--bw-color-text-secondary);
69
- }
70
- .error-detail {
71
- font-size: 14px;
72
- font-weight: 600;
73
- }
74
- .total {
75
- font-size: 16px;
76
- font-weight: 700;
77
- }
78
- </style>
1
+ <script lang="ts">
2
+ import type { CheckoutCartDetailDto } from './client-types';
3
+ import type { CartOverviewState } from './config';
4
+ import { formatCurrency } from './currency';
5
+ import { postMessage } from './messages';
6
+ import CountdownTimer from './CountdownTimer.svelte';
7
+ import { cartDeadline } from './cart-expiry';
8
+
9
+ interface Props {
10
+ cart: CheckoutCartDetailDto | null;
11
+ state?: CartOverviewState;
12
+ onRetry?: () => void;
13
+ }
14
+ let { cart, state = 'ready', onRetry }: Props = $props();
15
+
16
+ let itemCount = $derived(cart?.items.length ?? 0);
17
+
18
+ let totalLabel = $derived(() => {
19
+ if (!cart || cart.items.length === 0) return '';
20
+ const currency = cart.items[0].currencyCode;
21
+ const total = cart.items.reduce((sum, i) => sum + i.amount, 0);
22
+ return formatCurrency(total, currency, 2, 2);
23
+ });
24
+
25
+ let expiresAt = $derived(() => cart ? cartDeadline(cart) : new Date());
26
+ </script>
27
+
28
+ {#if state === 'error'}
29
+ <!-- An empty cart and a cart that could not be read used to render identically (as nothing), which left a
30
+ shopper on a narrow layout with no route to checkout and no sign that anything had gone wrong. -->
31
+ <div class="cart-bar bw-widget" role="alert">
32
+ <div class="cart-info">
33
+ <span class="item-count">Cart unavailable</span>
34
+ <span class="error-detail">We could not load your cart just now.</span>
35
+ </div>
36
+ <button class="btn btn-primary" onclick={() => onRetry?.()}>Retry</button>
37
+ </div>
38
+ {:else if cart && cart.items.length > 0}
39
+ <div class="cart-bar bw-widget">
40
+ <div class="cart-info">
41
+ <span class="item-count">{itemCount === 1 ? '1 item' : `${itemCount} items`} <CountdownTimer expiresAt={expiresAt()} /></span>
42
+ <span class="total">{totalLabel()}</span>
43
+ </div>
44
+ <button class="btn btn-primary" onclick={() => postMessage({ type: 'modal:open' })}>
45
+ Checkout
46
+ </button>
47
+ </div>
48
+ {/if}
49
+
50
+ <style>
51
+ .cart-bar {
52
+ display: flex;
53
+ align-items: center;
54
+ justify-content: space-between;
55
+ padding: 12px 16px;
56
+ background: white;
57
+ border-top: 1px solid var(--bw-color-border);
58
+ box-shadow: 0 -2px 8px rgba(0,0,0,0.06);
59
+ width: 100%;
60
+ }
61
+ .cart-info {
62
+ display: flex;
63
+ flex-direction: column;
64
+ gap: 2px;
65
+ }
66
+ .item-count {
67
+ font-size: 12px;
68
+ color: var(--bw-color-text-secondary);
69
+ }
70
+ .error-detail {
71
+ font-size: 14px;
72
+ font-weight: 600;
73
+ }
74
+ .total {
75
+ font-size: 16px;
76
+ font-weight: 700;
77
+ }
78
+ </style>