@marianmeres/stuic 3.17.0 → 3.18.1
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/components/Book/Book.svelte +14 -10
- package/dist/components/Cart/Cart.svelte +44 -29
- package/dist/components/Cart/Cart.svelte.d.ts +2 -2
- package/dist/components/Cart/index.css +26 -2
- package/dist/components/Checkout/CheckoutAddressForm.svelte +23 -1
- package/dist/components/Checkout/CheckoutCartReview.svelte +24 -11
- package/dist/components/Checkout/CheckoutCartReview.svelte.d.ts +3 -0
- package/dist/components/Checkout/CheckoutCompleteStep.svelte +2 -3
- package/dist/components/Checkout/CheckoutConfirmStep.svelte +23 -20
- package/dist/components/Checkout/CheckoutConfirmStep.svelte.d.ts +3 -0
- package/dist/components/Checkout/CheckoutGuestForm.svelte +26 -1
- package/dist/components/Checkout/CheckoutGuestOrLoginForm.svelte +139 -0
- package/dist/components/Checkout/CheckoutGuestOrLoginForm.svelte.d.ts +38 -0
- package/dist/components/Checkout/CheckoutLoginForm.svelte +59 -17
- package/dist/components/Checkout/CheckoutLoginForm.svelte.d.ts +13 -1
- package/dist/components/Checkout/CheckoutOrderConfirmation.svelte +86 -91
- package/dist/components/Checkout/CheckoutOrderConfirmation.svelte.d.ts +3 -0
- package/dist/components/Checkout/CheckoutOrderReview.svelte +88 -52
- package/dist/components/Checkout/CheckoutOrderReview.svelte.d.ts +4 -1
- package/dist/components/Checkout/CheckoutReviewStep.svelte +16 -57
- package/dist/components/Checkout/CheckoutReviewStep.svelte.d.ts +2 -0
- package/dist/components/Checkout/CheckoutSectionHeader.svelte +43 -0
- package/dist/components/Checkout/CheckoutSectionHeader.svelte.d.ts +14 -0
- package/dist/components/Checkout/CheckoutShippingStep.svelte +38 -43
- package/dist/components/Checkout/CheckoutShippingStep.svelte.d.ts +3 -0
- package/dist/components/Checkout/_address-form.css +30 -0
- package/dist/components/Checkout/_cart-review.css +30 -0
- package/dist/components/Checkout/_complete-step.css +32 -0
- package/dist/components/Checkout/_confirm-step.css +82 -0
- package/dist/components/Checkout/_delivery-options.css +114 -0
- package/dist/components/Checkout/_guest-form.css +60 -0
- package/dist/components/Checkout/_guest-or-login-form.css +62 -0
- package/dist/components/Checkout/_internal/checkout-i18n-defaults.js +4 -0
- package/dist/components/Checkout/_login-form.css +63 -0
- package/dist/components/Checkout/_order-confirmation.css +111 -0
- package/dist/components/Checkout/_order-review.css +72 -0
- package/dist/components/Checkout/_order-summary.css +54 -0
- package/dist/components/Checkout/_progress.css +72 -0
- package/dist/components/Checkout/_review-step.css +37 -0
- package/dist/components/Checkout/_shared.css +152 -0
- package/dist/components/Checkout/_shipping-step.css +60 -0
- package/dist/components/Checkout/index.css +20 -1058
- package/dist/components/Checkout/index.d.ts +1 -0
- package/dist/components/Checkout/index.js +1 -0
- package/dist/components/DismissibleMessage/DismissibleMessage.svelte +1 -0
- package/dist/components/ModalDialog/ModalDialog.svelte +21 -21
- package/dist/icons/index.d.ts +13 -3
- package/dist/icons/index.js +14 -3
- package/package.json +4 -4
|
@@ -711,18 +711,20 @@
|
|
|
711
711
|
draggable="false"
|
|
712
712
|
/>
|
|
713
713
|
{/if}
|
|
714
|
-
{#if onAreaClick && sheet.frontPage.areas?.length && sheet.frontPage.width && sheet.frontPage.height}
|
|
714
|
+
{#if onAreaClick && Math.abs(sheet.id - activeSpread) <= 1 && sheet.frontPage.areas?.length && sheet.frontPage.width && sheet.frontPage.height}
|
|
715
715
|
<svg
|
|
716
716
|
viewBox="0 0 {sheet.frontPage.width} {sheet.frontPage.height}"
|
|
717
717
|
preserveAspectRatio="xMidYMid meet"
|
|
718
718
|
class={!unstyled ? "stuic-book-areas" : undefined}
|
|
719
719
|
>
|
|
720
720
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
721
|
-
|
|
722
|
-
|
|
721
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
722
|
+
{#each sheet.frontPage.areas as area (area.id)}
|
|
723
723
|
<rect
|
|
724
|
-
x={area.x}
|
|
725
|
-
|
|
724
|
+
x={area.x}
|
|
725
|
+
y={area.y}
|
|
726
|
+
width={area.w}
|
|
727
|
+
height={area.h}
|
|
726
728
|
class={!unstyled ? "stuic-book-area" : undefined}
|
|
727
729
|
onclick={(e: MouseEvent) => {
|
|
728
730
|
if (_wasDragged) return;
|
|
@@ -759,18 +761,20 @@
|
|
|
759
761
|
draggable="false"
|
|
760
762
|
/>
|
|
761
763
|
{/if}
|
|
762
|
-
{#if onAreaClick && sheet.backPage.areas?.length && sheet.backPage.width && sheet.backPage.height}
|
|
764
|
+
{#if onAreaClick && Math.abs(sheet.id - activeSpread) <= 1 && sheet.backPage.areas?.length && sheet.backPage.width && sheet.backPage.height}
|
|
763
765
|
<svg
|
|
764
766
|
viewBox="0 0 {sheet.backPage.width} {sheet.backPage.height}"
|
|
765
767
|
preserveAspectRatio="xMidYMid meet"
|
|
766
768
|
class={!unstyled ? "stuic-book-areas" : undefined}
|
|
767
769
|
>
|
|
768
770
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
769
|
-
|
|
770
|
-
|
|
771
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
772
|
+
{#each sheet.backPage.areas as area (area.id)}
|
|
771
773
|
<rect
|
|
772
|
-
x={area.x}
|
|
773
|
-
|
|
774
|
+
x={area.x}
|
|
775
|
+
y={area.y}
|
|
776
|
+
width={area.w}
|
|
777
|
+
height={area.h}
|
|
774
778
|
class={!unstyled ? "stuic-book-area" : undefined}
|
|
775
779
|
onclick={(e: MouseEvent) => {
|
|
776
780
|
if (_wasDragged) return;
|
|
@@ -62,13 +62,13 @@
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
/** Layout variant */
|
|
65
|
-
export type CartVariant = "default" | "compact";
|
|
65
|
+
export type CartVariant = "default" | "compact" | "summary";
|
|
66
66
|
|
|
67
67
|
export interface Props extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
|
|
68
68
|
/** Cart items to display */
|
|
69
69
|
items: CartComponentItem[];
|
|
70
70
|
|
|
71
|
-
/** Layout variant. "compact" = smaller thumbnails, tighter spacing, scrollable, implicitly readonly */
|
|
71
|
+
/** Layout variant. "compact" = smaller thumbnails, tighter spacing, scrollable, implicitly readonly. "summary" = minimal receipt-style list (name ×qty, line total), no thumbnails/controls/footer, implicitly readonly */
|
|
72
72
|
variant?: CartVariant;
|
|
73
73
|
|
|
74
74
|
/** Format a numeric price for display. Default: (v) => (v / 100).toFixed(2) */
|
|
@@ -168,7 +168,8 @@
|
|
|
168
168
|
const bp = Breakpoint.instance;
|
|
169
169
|
let isDesktop = $derived(bp.md);
|
|
170
170
|
let isCompact = $derived(variant === "compact");
|
|
171
|
-
let
|
|
171
|
+
let isSummary = $derived(variant === "summary");
|
|
172
|
+
let isReadonly = $derived(readonlyProp || isCompact || isSummary);
|
|
172
173
|
|
|
173
174
|
// --- Derived ---
|
|
174
175
|
let total = $derived(items.reduce((sum, i) => sum + i.lineTotal, 0));
|
|
@@ -263,7 +264,19 @@
|
|
|
263
264
|
>
|
|
264
265
|
{#each items as item (item.id)}
|
|
265
266
|
{@const isUpdating = updatingItems.has(item.id)}
|
|
266
|
-
{#if
|
|
267
|
+
{#if isSummary}
|
|
268
|
+
<div class={!unstyled ? "stuic-cart-item" : undefined} data-variant="summary">
|
|
269
|
+
<span>
|
|
270
|
+
<span class={!unstyled ? "stuic-cart-item-name" : undefined}>
|
|
271
|
+
{item.name}
|
|
272
|
+
</span>
|
|
273
|
+
<span class={!unstyled ? "stuic-cart-item-qty" : undefined}>
|
|
274
|
+
×{item.quantity}
|
|
275
|
+
</span>
|
|
276
|
+
</span>
|
|
277
|
+
<span>{formatPrice(item.lineTotal)}</span>
|
|
278
|
+
</div>
|
|
279
|
+
{:else if itemRow}
|
|
267
280
|
{@render itemRow({
|
|
268
281
|
item,
|
|
269
282
|
isUpdating,
|
|
@@ -429,34 +442,36 @@
|
|
|
429
442
|
{/each}
|
|
430
443
|
</div>
|
|
431
444
|
|
|
432
|
-
<!-- Summary -->
|
|
433
|
-
{#if
|
|
434
|
-
{
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
>
|
|
440
|
-
<span class={!unstyled ? "stuic-cart-summary-label" : undefined}>
|
|
441
|
-
{t("total_label")}
|
|
442
|
-
({itemCount === 1
|
|
443
|
-
? t("item_count_1")
|
|
444
|
-
: t("item_count_n", { count: itemCount })})
|
|
445
|
-
</span>
|
|
446
|
-
<span
|
|
447
|
-
class={!unstyled ? "stuic-cart-summary-total" : undefined}
|
|
445
|
+
<!-- Summary (hidden in summary variant) -->
|
|
446
|
+
{#if !isSummary}
|
|
447
|
+
{#if summary}
|
|
448
|
+
{@render summary({ items, total, itemCount, formatPrice })}
|
|
449
|
+
{:else}
|
|
450
|
+
<div
|
|
451
|
+
class={!unstyled ? "stuic-cart-summary" : undefined}
|
|
448
452
|
data-variant={!unstyled ? variant : undefined}
|
|
449
453
|
>
|
|
450
|
-
{
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
+
<span class={!unstyled ? "stuic-cart-summary-label" : undefined}>
|
|
455
|
+
{t("total_label")}
|
|
456
|
+
({itemCount === 1
|
|
457
|
+
? t("item_count_1")
|
|
458
|
+
: t("item_count_n", { count: itemCount })})
|
|
459
|
+
</span>
|
|
460
|
+
<span
|
|
461
|
+
class={!unstyled ? "stuic-cart-summary-total" : undefined}
|
|
462
|
+
data-variant={!unstyled ? variant : undefined}
|
|
463
|
+
>
|
|
464
|
+
{formatPrice(total)}
|
|
465
|
+
</span>
|
|
466
|
+
</div>
|
|
467
|
+
{/if}
|
|
454
468
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
469
|
+
<!-- Footer -->
|
|
470
|
+
{#if footer}
|
|
471
|
+
<div class={!unstyled ? "stuic-cart-footer" : undefined}>
|
|
472
|
+
{@render footer({ items, total, itemCount })}
|
|
473
|
+
</div>
|
|
474
|
+
{/if}
|
|
460
475
|
{/if}
|
|
461
476
|
{/if}
|
|
462
477
|
</div>
|
|
@@ -31,11 +31,11 @@ export interface CartComponentItem {
|
|
|
31
31
|
maxQuantity?: number;
|
|
32
32
|
}
|
|
33
33
|
/** Layout variant */
|
|
34
|
-
export type CartVariant = "default" | "compact";
|
|
34
|
+
export type CartVariant = "default" | "compact" | "summary";
|
|
35
35
|
export interface Props extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
|
|
36
36
|
/** Cart items to display */
|
|
37
37
|
items: CartComponentItem[];
|
|
38
|
-
/** Layout variant. "compact" = smaller thumbnails, tighter spacing, scrollable, implicitly readonly */
|
|
38
|
+
/** Layout variant. "compact" = smaller thumbnails, tighter spacing, scrollable, implicitly readonly. "summary" = minimal receipt-style list (name ×qty, line total), no thumbnails/controls/footer, implicitly readonly */
|
|
39
39
|
variant?: CartVariant;
|
|
40
40
|
/** Format a numeric price for display. Default: (v) => (v / 100).toFixed(2) */
|
|
41
41
|
formatPrice?: (value: number) => string;
|
|
@@ -103,6 +103,10 @@
|
|
|
103
103
|
gap: 0;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
.stuic-cart-items[data-variant="summary"] {
|
|
107
|
+
gap: var(--stuic-cart-summary-item-gap, 0.25rem);
|
|
108
|
+
}
|
|
109
|
+
|
|
106
110
|
/* ============================================================================
|
|
107
111
|
ITEM CARD
|
|
108
112
|
============================================================================ */
|
|
@@ -130,6 +134,26 @@
|
|
|
130
134
|
border-top: 0;
|
|
131
135
|
}
|
|
132
136
|
|
|
137
|
+
.stuic-cart-item[data-variant="summary"] {
|
|
138
|
+
justify-content: space-between;
|
|
139
|
+
align-items: baseline;
|
|
140
|
+
font-size: 0.875rem;
|
|
141
|
+
gap: 0.5rem;
|
|
142
|
+
padding: 0;
|
|
143
|
+
border: 0;
|
|
144
|
+
background: transparent;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.stuic-cart-item[data-variant="summary"] .stuic-cart-item-name {
|
|
148
|
+
display: inline;
|
|
149
|
+
font-weight: 500;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.stuic-cart-item[data-variant="summary"] .stuic-cart-item-qty {
|
|
153
|
+
color: var(--stuic-color-muted-foreground);
|
|
154
|
+
margin-left: 0.5rem;
|
|
155
|
+
}
|
|
156
|
+
|
|
133
157
|
.stuic-cart-item[data-updating] {
|
|
134
158
|
opacity: 0.5;
|
|
135
159
|
pointer-events: none;
|
|
@@ -365,8 +389,8 @@
|
|
|
365
389
|
justify-content: space-between;
|
|
366
390
|
align-items: center;
|
|
367
391
|
margin-top: 1.5rem;
|
|
368
|
-
padding
|
|
369
|
-
border-top: 1px solid var(--stuic-cart-summary-border-color);
|
|
392
|
+
padding: 0 1rem;
|
|
393
|
+
/* border-top: 1px solid var(--stuic-cart-summary-border-color); */
|
|
370
394
|
}
|
|
371
395
|
|
|
372
396
|
.stuic-cart-summary[data-variant="compact"] {
|
|
@@ -98,14 +98,29 @@
|
|
|
98
98
|
return requiredFields.includes(field);
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
let containerWidth = $state(0);
|
|
102
|
+
let isSmall = $derived(containerWidth > 0 && containerWidth < 480);
|
|
103
|
+
|
|
101
104
|
let _class = $derived(
|
|
102
105
|
unstyled ? classProp : twMerge("stuic-checkout-address", classProp)
|
|
103
106
|
);
|
|
104
107
|
</script>
|
|
105
108
|
|
|
106
|
-
<fieldset
|
|
109
|
+
<fieldset
|
|
110
|
+
bind:this={el}
|
|
111
|
+
bind:offsetWidth={containerWidth}
|
|
112
|
+
class={_class}
|
|
113
|
+
data-small={!unstyled && isSmall ? "" : undefined}
|
|
114
|
+
{...rest}
|
|
115
|
+
>
|
|
107
116
|
<!-- Name (full width, block label) -->
|
|
117
|
+
<!--
|
|
118
|
+
svelte-ignore binding_property_non_reactive:
|
|
119
|
+
address is a $bindable prop — deep reactivity depends on the consumer
|
|
120
|
+
passing a $state() object. The bindings work correctly regardless.
|
|
121
|
+
-->
|
|
108
122
|
{#if fields?.name !== false}
|
|
123
|
+
<!-- svelte-ignore binding_property_non_reactive -->
|
|
109
124
|
<FieldInput
|
|
110
125
|
bind:value={address.name}
|
|
111
126
|
label={t("checkout.address.name_label")}
|
|
@@ -124,6 +139,7 @@
|
|
|
124
139
|
|
|
125
140
|
<!-- Street (full width, block label) -->
|
|
126
141
|
{#if fields?.street !== false}
|
|
142
|
+
<!-- svelte-ignore binding_property_non_reactive -->
|
|
127
143
|
<FieldInput
|
|
128
144
|
bind:value={address.street}
|
|
129
145
|
label={t("checkout.address.street_label")}
|
|
@@ -144,9 +160,11 @@
|
|
|
144
160
|
{#if fields?.city !== false || fields?.postal_code !== false}
|
|
145
161
|
<div class={unstyled ? undefined : "stuic-checkout-address-row"}>
|
|
146
162
|
{#if fields?.city !== false}
|
|
163
|
+
<!-- svelte-ignore binding_property_non_reactive -->
|
|
147
164
|
<FieldInput
|
|
148
165
|
bind:value={address.city}
|
|
149
166
|
label={t("checkout.address.city_label")}
|
|
167
|
+
labelLeftBreakpoint={0}
|
|
150
168
|
placeholder={t("checkout.address.city_placeholder")}
|
|
151
169
|
required={isRequired("city")}
|
|
152
170
|
name="{label}-city"
|
|
@@ -159,9 +177,11 @@
|
|
|
159
177
|
/>
|
|
160
178
|
{/if}
|
|
161
179
|
{#if fields?.postal_code !== false}
|
|
180
|
+
<!-- svelte-ignore binding_property_non_reactive -->
|
|
162
181
|
<FieldInput
|
|
163
182
|
bind:value={address.postal_code}
|
|
164
183
|
label={t("checkout.address.postal_code_label")}
|
|
184
|
+
labelLeftBreakpoint={0}
|
|
165
185
|
placeholder={t("checkout.address.postal_code_placeholder")}
|
|
166
186
|
required={isRequired("postal_code")}
|
|
167
187
|
name="{label}-postal_code"
|
|
@@ -189,6 +209,7 @@
|
|
|
189
209
|
id: `${label}-country`,
|
|
190
210
|
})}
|
|
191
211
|
{:else}
|
|
212
|
+
<!-- svelte-ignore binding_property_non_reactive -->
|
|
192
213
|
<FieldInput
|
|
193
214
|
bind:value={address.country}
|
|
194
215
|
label={t("checkout.address.country_label")}
|
|
@@ -208,6 +229,7 @@
|
|
|
208
229
|
|
|
209
230
|
<!-- Phone (full width, block label) -->
|
|
210
231
|
{#if fields?.phone !== false}
|
|
232
|
+
<!-- svelte-ignore binding_property_non_reactive -->
|
|
211
233
|
<FieldInput
|
|
212
234
|
bind:value={address.phone}
|
|
213
235
|
label={t("checkout.address.phone_label")}
|
|
@@ -51,6 +51,9 @@
|
|
|
51
51
|
unstyled?: boolean;
|
|
52
52
|
class?: string;
|
|
53
53
|
el?: HTMLDivElement;
|
|
54
|
+
|
|
55
|
+
hLevel?: HLevel;
|
|
56
|
+
hRenderLevel?: HLevel;
|
|
54
57
|
}
|
|
55
58
|
</script>
|
|
56
59
|
|
|
@@ -60,6 +63,8 @@
|
|
|
60
63
|
import { defaultFormatPrice } from "./_internal/checkout-utils.js";
|
|
61
64
|
import Cart from "../Cart/Cart.svelte";
|
|
62
65
|
import Button from "../Button/Button.svelte";
|
|
66
|
+
import { H, type HLevel } from "../H/index.js";
|
|
67
|
+
import CheckoutSectionHeader from "./CheckoutSectionHeader.svelte";
|
|
63
68
|
|
|
64
69
|
let {
|
|
65
70
|
items,
|
|
@@ -73,6 +78,8 @@
|
|
|
73
78
|
unstyled = false,
|
|
74
79
|
class: classProp,
|
|
75
80
|
el = $bindable(),
|
|
81
|
+
hLevel = 3,
|
|
82
|
+
hRenderLevel = 3,
|
|
76
83
|
...rest
|
|
77
84
|
}: Props = $props();
|
|
78
85
|
|
|
@@ -89,23 +96,29 @@
|
|
|
89
96
|
|
|
90
97
|
<div bind:this={el} class={_class} {...rest}>
|
|
91
98
|
<!-- Header bar -->
|
|
92
|
-
<
|
|
99
|
+
<CheckoutSectionHeader>
|
|
93
100
|
{#if typeof titleProp === "function"}
|
|
94
101
|
{@render titleProp()}
|
|
95
102
|
{:else}
|
|
96
|
-
<
|
|
103
|
+
<H
|
|
104
|
+
level={hLevel}
|
|
105
|
+
renderLevel={hRenderLevel}
|
|
106
|
+
class={unstyled ? undefined : "stuic-checkout-cart-review-title"}
|
|
107
|
+
>
|
|
97
108
|
{typeof titleProp === "string" ? titleProp : t("checkout.cart.title")}
|
|
98
|
-
</
|
|
109
|
+
</H>
|
|
99
110
|
{/if}
|
|
100
111
|
|
|
101
|
-
{#
|
|
102
|
-
{
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
112
|
+
{#snippet right()}
|
|
113
|
+
{#if editAction}
|
|
114
|
+
{@render editAction({ onEditCart })}
|
|
115
|
+
{:else if onEditCart}
|
|
116
|
+
<Button variant="soft" size="sm" onclick={onEditCart}>
|
|
117
|
+
{t("checkout.cart.edit")}
|
|
118
|
+
</Button>
|
|
119
|
+
{/if}
|
|
120
|
+
{/snippet}
|
|
121
|
+
</CheckoutSectionHeader>
|
|
109
122
|
|
|
110
123
|
<!-- Cart (readonly) -->
|
|
111
124
|
<Cart {items} readonly formatPrice={fp} {thumbnail} t={tProp} {unstyled}>
|
|
@@ -41,7 +41,10 @@ export interface Props extends Omit<HTMLAttributes<HTMLDivElement>, "children" |
|
|
|
41
41
|
unstyled?: boolean;
|
|
42
42
|
class?: string;
|
|
43
43
|
el?: HTMLDivElement;
|
|
44
|
+
hLevel?: HLevel;
|
|
45
|
+
hRenderLevel?: HLevel;
|
|
44
46
|
}
|
|
47
|
+
import { type HLevel } from "../H/index.js";
|
|
45
48
|
declare const CheckoutCartReview: import("svelte").Component<Props, {}, "el">;
|
|
46
49
|
type CheckoutCartReview = ReturnType<typeof CheckoutCartReview>;
|
|
47
50
|
export default CheckoutCartReview;
|
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
<script lang="ts">
|
|
65
65
|
import { twMerge } from "../../utils/tw-merge.js";
|
|
66
66
|
import Button from "../Button/Button.svelte";
|
|
67
|
+
import DismissibleMessage from "../DismissibleMessage/DismissibleMessage.svelte";
|
|
67
68
|
import Skeleton from "../Skeleton/Skeleton.svelte";
|
|
68
69
|
import CheckoutOrderConfirmation from "./CheckoutOrderConfirmation.svelte";
|
|
69
70
|
import CheckoutProgress from "./CheckoutProgress.svelte";
|
|
@@ -118,9 +119,7 @@
|
|
|
118
119
|
</div>
|
|
119
120
|
{:else if error}
|
|
120
121
|
<div class={unstyled ? undefined : "stuic-checkout-complete-step-error"}>
|
|
121
|
-
<
|
|
122
|
-
{error}
|
|
123
|
-
</div>
|
|
122
|
+
<DismissibleMessage message={error} intent="destructive" onDismiss={false} />
|
|
124
123
|
<div class={unstyled ? undefined : "stuic-checkout-complete-step-error-actions"}>
|
|
125
124
|
{#if onReturnToCheckout}
|
|
126
125
|
<Button variant="outline" onclick={onReturnToCheckout}>
|
|
@@ -74,17 +74,23 @@
|
|
|
74
74
|
unstyled?: boolean;
|
|
75
75
|
class?: string;
|
|
76
76
|
el?: HTMLDivElement;
|
|
77
|
+
|
|
78
|
+
hLevel?: HLevel;
|
|
79
|
+
hRenderLevel?: HLevel;
|
|
77
80
|
}
|
|
78
81
|
</script>
|
|
79
82
|
|
|
80
83
|
<script lang="ts">
|
|
81
84
|
import { twMerge } from "../../utils/tw-merge.js";
|
|
82
85
|
import Button from "../Button/Button.svelte";
|
|
86
|
+
import DismissibleMessage from "../DismissibleMessage/DismissibleMessage.svelte";
|
|
83
87
|
import Skeleton from "../Skeleton/Skeleton.svelte";
|
|
84
88
|
import CheckoutOrderReview from "./CheckoutOrderReview.svelte";
|
|
85
89
|
import CheckoutOrderSummary from "./CheckoutOrderSummary.svelte";
|
|
86
90
|
import CheckoutProgress from "./CheckoutProgress.svelte";
|
|
87
91
|
import { t_default } from "./_internal/checkout-i18n-defaults.js";
|
|
92
|
+
import H, { type HLevel } from "../H/H.svelte";
|
|
93
|
+
import CheckoutSectionHeader from "./CheckoutSectionHeader.svelte";
|
|
88
94
|
|
|
89
95
|
let {
|
|
90
96
|
order,
|
|
@@ -111,6 +117,9 @@
|
|
|
111
117
|
unstyled = false,
|
|
112
118
|
class: classProp,
|
|
113
119
|
el = $bindable(),
|
|
120
|
+
|
|
121
|
+
hLevel = 3,
|
|
122
|
+
hRenderLevel = 3,
|
|
114
123
|
...rest
|
|
115
124
|
}: Props = $props();
|
|
116
125
|
|
|
@@ -146,9 +155,14 @@
|
|
|
146
155
|
</div>
|
|
147
156
|
</div>
|
|
148
157
|
{:else}
|
|
149
|
-
{
|
|
150
|
-
|
|
151
|
-
|
|
158
|
+
<DismissibleMessage message={error} intent="destructive" onDismiss={false} />
|
|
159
|
+
|
|
160
|
+
<!-- Back link -->
|
|
161
|
+
{#if onBack}
|
|
162
|
+
<div class={unstyled ? undefined : "stuic-checkout-step-back"}>
|
|
163
|
+
<Button type="button" variant="link" size="sm" onclick={onBack}>
|
|
164
|
+
{t("checkout.step.back_to_shipping")}
|
|
165
|
+
</Button>
|
|
152
166
|
</div>
|
|
153
167
|
{/if}
|
|
154
168
|
|
|
@@ -158,17 +172,6 @@
|
|
|
158
172
|
{#if leftColumn}
|
|
159
173
|
{@render leftColumn()}
|
|
160
174
|
{:else}
|
|
161
|
-
<!-- Back link -->
|
|
162
|
-
{#if onBack}
|
|
163
|
-
<button
|
|
164
|
-
type="button"
|
|
165
|
-
class={unstyled ? undefined : "stuic-checkout-confirm-step-back"}
|
|
166
|
-
onclick={onBack}
|
|
167
|
-
>
|
|
168
|
-
{t("checkout.step.back_to_shipping")}
|
|
169
|
-
</button>
|
|
170
|
-
{/if}
|
|
171
|
-
|
|
172
175
|
<CheckoutOrderReview
|
|
173
176
|
{order}
|
|
174
177
|
{formatPrice}
|
|
@@ -188,11 +191,11 @@
|
|
|
188
191
|
{@render rightColumn()}
|
|
189
192
|
{:else}
|
|
190
193
|
<div class={unstyled ? undefined : "stuic-checkout-confirm-step-sidebar"}>
|
|
191
|
-
<
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
</
|
|
194
|
+
<CheckoutSectionHeader noMinHeight>
|
|
195
|
+
<H level={hLevel} renderLevel={hRenderLevel}>
|
|
196
|
+
{t("checkout.step.summary_title")}
|
|
197
|
+
</H>
|
|
198
|
+
</CheckoutSectionHeader>
|
|
196
199
|
<CheckoutOrderSummary
|
|
197
200
|
totals={order.totals}
|
|
198
201
|
hasShipping={!!order.delivery_option_id}
|
|
@@ -219,7 +222,7 @@
|
|
|
219
222
|
<!-- Place Order CTA -->
|
|
220
223
|
<Button
|
|
221
224
|
intent="primary"
|
|
222
|
-
class="w-full"
|
|
225
|
+
class="w-full mt-4"
|
|
223
226
|
disabled={!isValid || isSubmitting}
|
|
224
227
|
onclick={onPlaceOrder}
|
|
225
228
|
aria-busy={isSubmitting}
|
|
@@ -40,7 +40,10 @@ export interface Props extends Omit<HTMLAttributes<HTMLDivElement>, "children">
|
|
|
40
40
|
unstyled?: boolean;
|
|
41
41
|
class?: string;
|
|
42
42
|
el?: HTMLDivElement;
|
|
43
|
+
hLevel?: HLevel;
|
|
44
|
+
hRenderLevel?: HLevel;
|
|
43
45
|
}
|
|
46
|
+
import { type HLevel } from "../H/H.svelte";
|
|
44
47
|
declare const CheckoutConfirmStep: import("svelte").Component<Props, {}, "el">;
|
|
45
48
|
type CheckoutConfirmStep = ReturnType<typeof CheckoutConfirmStep>;
|
|
46
49
|
export default CheckoutConfirmStep;
|
|
@@ -122,13 +122,30 @@
|
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
let containerWidth = $state(0);
|
|
126
|
+
let isSmall = $derived(containerWidth > 0 && containerWidth < 480);
|
|
127
|
+
|
|
125
128
|
let _class = $derived(
|
|
126
129
|
unstyled ? classProp : twMerge("stuic-checkout-guest-form", classProp)
|
|
127
130
|
);
|
|
128
131
|
</script>
|
|
129
132
|
|
|
130
|
-
<form
|
|
133
|
+
<form
|
|
134
|
+
bind:this={el}
|
|
135
|
+
bind:offsetWidth={containerWidth}
|
|
136
|
+
class={_class}
|
|
137
|
+
data-small={!unstyled && isSmall ? "" : undefined}
|
|
138
|
+
onsubmit={handleSubmit}
|
|
139
|
+
novalidate
|
|
140
|
+
{...rest}
|
|
141
|
+
>
|
|
142
|
+
<!--
|
|
143
|
+
svelte-ignore binding_property_non_reactive:
|
|
144
|
+
formData is a $bindable prop — deep reactivity depends on the consumer
|
|
145
|
+
passing a $state() object. The bindings work correctly regardless.
|
|
146
|
+
-->
|
|
131
147
|
<!-- Email (always shown, always required) -->
|
|
148
|
+
<!-- svelte-ignore binding_property_non_reactive -->
|
|
132
149
|
<FieldInput
|
|
133
150
|
bind:value={formData.email}
|
|
134
151
|
label={t("checkout.guest.email_label")}
|
|
@@ -148,17 +165,21 @@
|
|
|
148
165
|
{#if fields?.first_name !== false || fields?.last_name !== false}
|
|
149
166
|
<div class={unstyled ? undefined : "stuic-checkout-guest-row"}>
|
|
150
167
|
{#if fields?.first_name !== false}
|
|
168
|
+
<!-- svelte-ignore binding_property_non_reactive -->
|
|
151
169
|
<FieldInput
|
|
152
170
|
bind:value={formData.first_name}
|
|
153
171
|
label={t("checkout.guest.first_name_label")}
|
|
172
|
+
labelLeftBreakpoint={0}
|
|
154
173
|
placeholder={t("checkout.guest.first_name_placeholder")}
|
|
155
174
|
name="checkout-guest-first-name"
|
|
156
175
|
/>
|
|
157
176
|
{/if}
|
|
158
177
|
{#if fields?.last_name !== false}
|
|
178
|
+
<!-- svelte-ignore binding_property_non_reactive -->
|
|
159
179
|
<FieldInput
|
|
160
180
|
bind:value={formData.last_name}
|
|
161
181
|
label={t("checkout.guest.last_name_label")}
|
|
182
|
+
labelLeftBreakpoint={0}
|
|
162
183
|
placeholder={t("checkout.guest.last_name_placeholder")}
|
|
163
184
|
name="checkout-guest-last-name"
|
|
164
185
|
/>
|
|
@@ -168,6 +189,7 @@
|
|
|
168
189
|
|
|
169
190
|
<!-- Phone -->
|
|
170
191
|
{#if fields?.phone !== false}
|
|
192
|
+
<!-- svelte-ignore binding_property_non_reactive -->
|
|
171
193
|
<FieldInput
|
|
172
194
|
bind:value={formData.phone}
|
|
173
195
|
label={t("checkout.guest.phone_label")}
|
|
@@ -186,6 +208,7 @@
|
|
|
186
208
|
</summary>
|
|
187
209
|
<div class={unstyled ? undefined : "stuic-checkout-guest-b2b-content"}>
|
|
188
210
|
{#if fields?.company_name !== false}
|
|
211
|
+
<!-- svelte-ignore binding_property_non_reactive -->
|
|
189
212
|
<FieldInput
|
|
190
213
|
bind:value={formData.company_name}
|
|
191
214
|
label={t("checkout.guest.company_name_label")}
|
|
@@ -196,6 +219,7 @@
|
|
|
196
219
|
{#if fields?.tax_id !== false || fields?.vat_number !== false}
|
|
197
220
|
<div class={unstyled ? undefined : "stuic-checkout-guest-row"}>
|
|
198
221
|
{#if fields?.tax_id !== false}
|
|
222
|
+
<!-- svelte-ignore binding_property_non_reactive -->
|
|
199
223
|
<FieldInput
|
|
200
224
|
bind:value={formData.tax_id}
|
|
201
225
|
label={t("checkout.guest.tax_id_label")}
|
|
@@ -203,6 +227,7 @@
|
|
|
203
227
|
/>
|
|
204
228
|
{/if}
|
|
205
229
|
{#if fields?.vat_number !== false}
|
|
230
|
+
<!-- svelte-ignore binding_property_non_reactive -->
|
|
206
231
|
<FieldInput
|
|
207
232
|
bind:value={formData.vat_number}
|
|
208
233
|
label={t("checkout.guest.vat_number_label")}
|