@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.
Files changed (49) hide show
  1. package/dist/components/Book/Book.svelte +14 -10
  2. package/dist/components/Cart/Cart.svelte +44 -29
  3. package/dist/components/Cart/Cart.svelte.d.ts +2 -2
  4. package/dist/components/Cart/index.css +26 -2
  5. package/dist/components/Checkout/CheckoutAddressForm.svelte +23 -1
  6. package/dist/components/Checkout/CheckoutCartReview.svelte +24 -11
  7. package/dist/components/Checkout/CheckoutCartReview.svelte.d.ts +3 -0
  8. package/dist/components/Checkout/CheckoutCompleteStep.svelte +2 -3
  9. package/dist/components/Checkout/CheckoutConfirmStep.svelte +23 -20
  10. package/dist/components/Checkout/CheckoutConfirmStep.svelte.d.ts +3 -0
  11. package/dist/components/Checkout/CheckoutGuestForm.svelte +26 -1
  12. package/dist/components/Checkout/CheckoutGuestOrLoginForm.svelte +139 -0
  13. package/dist/components/Checkout/CheckoutGuestOrLoginForm.svelte.d.ts +38 -0
  14. package/dist/components/Checkout/CheckoutLoginForm.svelte +59 -17
  15. package/dist/components/Checkout/CheckoutLoginForm.svelte.d.ts +13 -1
  16. package/dist/components/Checkout/CheckoutOrderConfirmation.svelte +86 -91
  17. package/dist/components/Checkout/CheckoutOrderConfirmation.svelte.d.ts +3 -0
  18. package/dist/components/Checkout/CheckoutOrderReview.svelte +88 -52
  19. package/dist/components/Checkout/CheckoutOrderReview.svelte.d.ts +4 -1
  20. package/dist/components/Checkout/CheckoutReviewStep.svelte +16 -57
  21. package/dist/components/Checkout/CheckoutReviewStep.svelte.d.ts +2 -0
  22. package/dist/components/Checkout/CheckoutSectionHeader.svelte +43 -0
  23. package/dist/components/Checkout/CheckoutSectionHeader.svelte.d.ts +14 -0
  24. package/dist/components/Checkout/CheckoutShippingStep.svelte +38 -43
  25. package/dist/components/Checkout/CheckoutShippingStep.svelte.d.ts +3 -0
  26. package/dist/components/Checkout/_address-form.css +30 -0
  27. package/dist/components/Checkout/_cart-review.css +30 -0
  28. package/dist/components/Checkout/_complete-step.css +32 -0
  29. package/dist/components/Checkout/_confirm-step.css +82 -0
  30. package/dist/components/Checkout/_delivery-options.css +114 -0
  31. package/dist/components/Checkout/_guest-form.css +60 -0
  32. package/dist/components/Checkout/_guest-or-login-form.css +62 -0
  33. package/dist/components/Checkout/_internal/checkout-i18n-defaults.js +4 -0
  34. package/dist/components/Checkout/_login-form.css +63 -0
  35. package/dist/components/Checkout/_order-confirmation.css +111 -0
  36. package/dist/components/Checkout/_order-review.css +72 -0
  37. package/dist/components/Checkout/_order-summary.css +54 -0
  38. package/dist/components/Checkout/_progress.css +72 -0
  39. package/dist/components/Checkout/_review-step.css +37 -0
  40. package/dist/components/Checkout/_shared.css +152 -0
  41. package/dist/components/Checkout/_shipping-step.css +60 -0
  42. package/dist/components/Checkout/index.css +20 -1058
  43. package/dist/components/Checkout/index.d.ts +1 -0
  44. package/dist/components/Checkout/index.js +1 -0
  45. package/dist/components/DismissibleMessage/DismissibleMessage.svelte +1 -0
  46. package/dist/components/ModalDialog/ModalDialog.svelte +21 -21
  47. package/dist/icons/index.d.ts +13 -3
  48. package/dist/icons/index.js +14 -3
  49. 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
- <!-- svelte-ignore a11y_no_static_element_interactions -->
722
- {#each sheet.frontPage.areas as area (area.id)}
721
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
722
+ {#each sheet.frontPage.areas as area (area.id)}
723
723
  <rect
724
- x={area.x} y={area.y}
725
- width={area.w} height={area.h}
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
- <!-- svelte-ignore a11y_no_static_element_interactions -->
770
- {#each sheet.backPage.areas as area (area.id)}
771
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
772
+ {#each sheet.backPage.areas as area (area.id)}
771
773
  <rect
772
- x={area.x} y={area.y}
773
- width={area.w} height={area.h}
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 isReadonly = $derived(readonlyProp || isCompact);
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 itemRow}
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
+ &times;{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 summary}
434
- {@render summary({ items, total, itemCount, formatPrice })}
435
- {:else}
436
- <div
437
- class={!unstyled ? "stuic-cart-summary" : undefined}
438
- data-variant={!unstyled ? variant : undefined}
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
- {formatPrice(total)}
451
- </span>
452
- </div>
453
- {/if}
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
- <!-- Footer -->
456
- {#if footer}
457
- <div class={!unstyled ? "stuic-cart-footer" : undefined}>
458
- {@render footer({ items, total, itemCount })}
459
- </div>
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-top: 1.5rem;
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 bind:this={el} class={_class} {...rest}>
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
- <div class={unstyled ? undefined : "stuic-checkout-cart-review-header"}>
99
+ <CheckoutSectionHeader>
93
100
  {#if typeof titleProp === "function"}
94
101
  {@render titleProp()}
95
102
  {:else}
96
- <h3 class={unstyled ? undefined : "stuic-checkout-cart-review-title"}>
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
- </h3>
109
+ </H>
99
110
  {/if}
100
111
 
101
- {#if editAction}
102
- {@render editAction({ onEditCart })}
103
- {:else if onEditCart}
104
- <Button variant="outline" size="sm" onclick={onEditCart}>
105
- {t("checkout.cart.edit")}
106
- </Button>
107
- {/if}
108
- </div>
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
- <div class={unstyled ? undefined : "stuic-checkout-alert"} role="alert">
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
- {#if error}
150
- <div class={unstyled ? undefined : "stuic-checkout-alert"} role="alert">
151
- {error}
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
- <h3
192
- class={unstyled ? undefined : "stuic-checkout-confirm-step-section-heading"}
193
- >
194
- {t("checkout.step.summary_title")}
195
- </h3>
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 bind:this={el} class={_class} onsubmit={handleSubmit} novalidate {...rest}>
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")}