@marianmeres/stuic 3.115.0 → 3.117.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 (101) hide show
  1. package/API.md +297 -304
  2. package/dist/actions/dim-behind/index.css +4 -1
  3. package/dist/actions/focus-trap.fixture.svelte +16 -0
  4. package/dist/actions/focus-trap.fixture.svelte.d.ts +7 -0
  5. package/dist/actions/focus-trap.js +3 -1
  6. package/dist/components/Accordion/README.md +17 -17
  7. package/dist/components/Accordion/index.css +4 -2
  8. package/dist/components/AssetsPreview/README.md +7 -7
  9. package/dist/components/AssetsPreview/_internal/assets-preview-types.d.ts +1 -2
  10. package/dist/components/AssetsPreview/_internal/assets-preview-utils.d.ts +1 -1
  11. package/dist/components/AssetsPreview/_internal/assets-preview-utils.js +9 -3
  12. package/dist/components/Avatar/Avatar.svelte +1 -3
  13. package/dist/components/Avatar/README.md +33 -27
  14. package/dist/components/Book/Book.svelte +6 -1
  15. package/dist/components/Book/README.md +22 -20
  16. package/dist/components/Book/index.css +4 -2
  17. package/dist/components/Button/README.md +17 -17
  18. package/dist/components/Card/Card.svelte +25 -8
  19. package/dist/components/Card/README.md +52 -56
  20. package/dist/components/Card/index.css +2 -1
  21. package/dist/components/Carousel/Carousel.svelte +1 -3
  22. package/dist/components/Carousel/README.md +28 -28
  23. package/dist/components/Cart/Cart.svelte +2 -1
  24. package/dist/components/Cart/README.md +25 -25
  25. package/dist/components/Checkout/CheckoutGuestOrLoginForm.svelte +8 -3
  26. package/dist/components/Checkout/CheckoutShippingStep.svelte +1 -2
  27. package/dist/components/Checkout/README.md +143 -130
  28. package/dist/components/CommandMenu/CommandMenu.fixture.svelte +24 -0
  29. package/dist/components/CommandMenu/CommandMenu.fixture.svelte.d.ts +7 -0
  30. package/dist/components/CommandMenu/CommandMenu.svelte +10 -13
  31. package/dist/components/CommandMenu/_internal/command-menu-utils.d.ts +22 -0
  32. package/dist/components/CommandMenu/_internal/command-menu-utils.js +37 -0
  33. package/dist/components/CronInput/CronInput.svelte +64 -60
  34. package/dist/components/CronInput/README.md +46 -46
  35. package/dist/components/DataTable/DataTable.svelte +5 -1
  36. package/dist/components/DataTable/README.md +78 -63
  37. package/dist/components/DropdownMenu/DropdownMenu.svelte +14 -29
  38. package/dist/components/DropdownMenu/README.md +33 -27
  39. package/dist/components/DropdownMenu/_internal/dropdown-menu-search.d.ts +21 -0
  40. package/dist/components/DropdownMenu/_internal/dropdown-menu-search.js +47 -0
  41. package/dist/components/EmailVerifyForm/EmailVerifyForm.svelte +2 -9
  42. package/dist/components/EmailVerifyForm/README.md +30 -30
  43. package/dist/components/Header/Header.svelte +161 -165
  44. package/dist/components/Header/README.md +7 -7
  45. package/dist/components/IconSwap/README.md +20 -15
  46. package/dist/components/IconSwap/index.css +2 -1
  47. package/dist/components/ImageCycler/ImageCycler.svelte +19 -5
  48. package/dist/components/ImageCycler/ImageCycler.svelte.d.ts +14 -10
  49. package/dist/components/ImageCycler/README.md +15 -15
  50. package/dist/components/ImageCycler/index.css +26 -20
  51. package/dist/components/Input/FieldFile.svelte +1 -3
  52. package/dist/components/Input/FieldInput.svelte +1 -3
  53. package/dist/components/Input/FieldKeyValues.svelte +2 -6
  54. package/dist/components/Input/FieldObject.svelte +2 -1
  55. package/dist/components/Input/README.md +11 -11
  56. package/dist/components/Input/node_modules/.vite/vitest/d2a04d71301a8915217dd5faf81d12cffd6cd958/_svelte_metadata.json +1 -0
  57. package/dist/components/Input/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/_svelte_metadata.json +1 -0
  58. package/dist/components/KbdShortcut/index.css +2 -1
  59. package/dist/components/LoginForm/LoginForm.svelte +1 -7
  60. package/dist/components/LoginForm/README.md +46 -46
  61. package/dist/components/ModalDialog/ModalDialog.fixture.svelte +19 -0
  62. package/dist/components/ModalDialog/ModalDialog.fixture.svelte.d.ts +4 -0
  63. package/dist/components/ModalDialog/index.css +2 -1
  64. package/dist/components/Notifications/index.css +24 -6
  65. package/dist/components/OtpInput/OtpInput.svelte +0 -0
  66. package/dist/components/OtpInput/README.md +15 -19
  67. package/dist/components/OtpInput/index.css +1 -4
  68. package/dist/components/OtpInput/index.d.ts +1 -1
  69. package/dist/components/OtpInput/index.js +1 -1
  70. package/dist/components/Pill/README.md +41 -40
  71. package/dist/components/Pill/index.css +3 -6
  72. package/dist/components/PricingTable/README.md +86 -86
  73. package/dist/components/PricingTable/index.css +20 -35
  74. package/dist/components/RegisterForm/README.md +60 -60
  75. package/dist/components/RegisterForm/RegisterForm.svelte +1 -7
  76. package/dist/components/Separator/README.md +7 -7
  77. package/dist/components/SlidingPanels/SlidingPanels.fixture.svelte +20 -0
  78. package/dist/components/SlidingPanels/SlidingPanels.fixture.svelte.d.ts +6 -0
  79. package/dist/components/TabbedMenu/index.css +6 -3
  80. package/dist/components/Tree/README.md +67 -67
  81. package/dist/components/UserAvatarMenu/UserAvatarMenu.svelte +1 -5
  82. package/dist/components/WithSidePanel/index.css +4 -4
  83. package/dist/index.css +12 -8
  84. package/dist/utils/design-tokens.d.ts +1 -1
  85. package/dist/utils/design-tokens.js +1 -1
  86. package/docs/architecture.md +7 -7
  87. package/docs/component-testing/00-overview-and-roadmap.md +19 -19
  88. package/docs/component-testing/01-framework-setup.md +6 -6
  89. package/docs/component-testing/02-test-conventions.md +6 -5
  90. package/docs/component-testing/03-component-coverage-roadmap.md +27 -27
  91. package/docs/component-testing/04-hard-cases-and-e2e.md +8 -8
  92. package/docs/component-testing/05-ci.md +3 -3
  93. package/docs/component-testing/PROGRESS.md +118 -26
  94. package/docs/component-testing/README.md +8 -8
  95. package/docs/conventions.md +25 -25
  96. package/docs/domains/components.md +386 -385
  97. package/docs/domains/theming.md +24 -24
  98. package/docs/domains/utils.md +22 -25
  99. package/docs/testing.md +2 -2
  100. package/docs/upgrading.md +32 -28
  101. package/package.json +2 -1
@@ -10,11 +10,7 @@ A flexible card component for displaying content in a contained, visually distin
10
10
  </script>
11
11
 
12
12
  <!-- Basic -->
13
- <Card
14
- image="/photo.jpg"
15
- title="Card Title"
16
- description="A brief description."
17
- />
13
+ <Card image="/photo.jpg" title="Card Title" description="A brief description." />
18
14
 
19
15
  <!-- With eyebrow and footer actions -->
20
16
  <Card
@@ -55,63 +51,63 @@ A flexible card component for displaying content in a contained, visually distin
55
51
 
56
52
  ## Props
57
53
 
58
- | Prop | Type | Default | Description |
59
- |------|------|---------|-------------|
60
- | `image` | `string` | - | Image URL for the top (vertical) or side (horizontal) area |
61
- | `imageAlt` | `string` | `""` | Alt text for the image |
62
- | `eyebrow` | `THC` | - | Small label above the title (category, date, tag) |
63
- | `title` | `THC` | - | Card title |
64
- | `description` | `THC` | - | Short description below the title |
65
- | `variant` | `"vertical" \| "horizontal"` | `"vertical"` | Layout variant |
66
- | `horizontalThreshold` | `number` | `480` | Width (px) below which horizontal auto-switches to vertical. Set 0 to disable. |
67
- | `href` | `string` | - | Renders card as `<a>` |
68
- | `onclick` | `(e: MouseEvent) => void` | - | Renders card as `<button>` |
69
- | `disabled` | `boolean` | `false` | Disabled state (reduced opacity, no interaction) |
70
- | `unstyled` | `boolean` | `false` | Skip all default styling |
71
- | `class` | `string` | - | Additional CSS classes for the card shell |
72
- | `classImage` | `string` | - | Additional CSS classes for the image container |
73
- | `classContent` | `string` | - | Additional CSS classes for the content area |
74
- | `classFooter` | `string` | - | Additional CSS classes for the footer |
75
- | `el` | `HTMLElement` | - | Bindable element reference |
54
+ | Prop | Type | Default | Description |
55
+ | --------------------- | ---------------------------- | ------------ | ------------------------------------------------------------------------------ |
56
+ | `image` | `string` | - | Image URL for the top (vertical) or side (horizontal) area |
57
+ | `imageAlt` | `string` | `""` | Alt text for the image |
58
+ | `eyebrow` | `THC` | - | Small label above the title (category, date, tag) |
59
+ | `title` | `THC` | - | Card title |
60
+ | `description` | `THC` | - | Short description below the title |
61
+ | `variant` | `"vertical" \| "horizontal"` | `"vertical"` | Layout variant |
62
+ | `horizontalThreshold` | `number` | `480` | Width (px) below which horizontal auto-switches to vertical. Set 0 to disable. |
63
+ | `href` | `string` | - | Renders card as `<a>` |
64
+ | `onclick` | `(e: MouseEvent) => void` | - | Renders card as `<button>` |
65
+ | `disabled` | `boolean` | `false` | Disabled state (reduced opacity, no interaction) |
66
+ | `unstyled` | `boolean` | `false` | Skip all default styling |
67
+ | `class` | `string` | - | Additional CSS classes for the card shell |
68
+ | `classImage` | `string` | - | Additional CSS classes for the image container |
69
+ | `classContent` | `string` | - | Additional CSS classes for the content area |
70
+ | `classFooter` | `string` | - | Additional CSS classes for the footer |
71
+ | `el` | `HTMLElement` | - | Bindable element reference |
76
72
 
77
73
  ## Snippets
78
74
 
79
- | Snippet | Parameters | Description |
80
- |---------|------------|-------------|
81
- | `children` | - | Overrides the entire card body |
82
- | `renderImage` | `{ image, imageAlt }` | Overrides the image area |
83
- | `renderBadge` | - | Badge/overlay positioned over the image |
84
- | `renderContent` | `{ eyebrow?, title?, description? }` | Overrides the content area |
85
- | `renderFooter` | - | Footer area (action buttons, metadata) |
75
+ | Snippet | Parameters | Description |
76
+ | --------------- | ------------------------------------ | --------------------------------------- |
77
+ | `children` | - | Overrides the entire card body |
78
+ | `renderImage` | `{ image, imageAlt }` | Overrides the image area |
79
+ | `renderBadge` | - | Badge/overlay positioned over the image |
80
+ | `renderContent` | `{ eyebrow?, title?, description? }` | Overrides the content area |
81
+ | `renderFooter` | - | Footer area (action buttons, metadata) |
86
82
 
87
83
  ## CSS Variables
88
84
 
89
- | Variable | Default | Description |
90
- |----------|---------|-------------|
91
- | `--stuic-card-bg` | `var(--stuic-color-card, var(--stuic-color-background))` | Background color |
92
- | `--stuic-card-bg-hover` | `var(--stuic-color-card-hover, var(--stuic-color-muted))` | Hover background (interactive only) |
93
- | `--stuic-card-border-width` | `1px` | Border width |
94
- | `--stuic-card-border` | `var(--stuic-color-border)` | Border color |
95
- | `--stuic-card-border-hover` | `var(--stuic-color-border-hover)` | Hover border color |
96
- | `--stuic-card-radius` | `var(--radius-lg)` | Border radius |
97
- | `--stuic-card-shadow` | `var(--shadow-sm)` | Box shadow |
98
- | `--stuic-card-shadow-hover` | `var(--shadow-md)` | Hover box shadow |
99
- | `--stuic-card-transition` | `150ms` | Transition duration |
100
- | `--stuic-card-padding` | `1rem` | Content and footer padding |
101
- | `--stuic-card-content-gap` | `0.5rem` | Gap between content elements |
102
- | `--stuic-card-image-aspect-ratio` | `16 / 9` | Image aspect ratio (vertical only) |
103
- | `--stuic-card-image-object-fit` | `cover` | Image object-fit |
104
- | `--stuic-card-image-width-horizontal` | `40%` | Image width in horizontal variant |
105
- | `--stuic-card-eyebrow-font-size` | `var(--text-xs)` | Eyebrow font size |
106
- | `--stuic-card-eyebrow-text` | `var(--stuic-color-muted-foreground)` | Eyebrow text color |
107
- | `--stuic-card-title-font-size` | `var(--text-lg)` | Title font size |
108
- | `--stuic-card-title-font-weight` | `var(--font-weight-semibold)` | Title font weight |
109
- | `--stuic-card-title-text` | `var(--stuic-color-foreground)` | Title text color |
110
- | `--stuic-card-description-font-size` | `var(--text-sm)` | Description font size |
111
- | `--stuic-card-description-text` | `var(--stuic-color-muted-foreground)` | Description text color |
112
- | `--stuic-card-ring-width` | `3px` | Focus ring width |
113
- | `--stuic-card-ring-color` | `var(--stuic-color-ring)` | Focus ring color |
114
- | `--stuic-card-opacity-disabled` | `0.5` | Disabled opacity |
85
+ | Variable | Default | Description |
86
+ | ------------------------------------- | --------------------------------------------------------- | ----------------------------------- |
87
+ | `--stuic-card-bg` | `var(--stuic-color-card, var(--stuic-color-background))` | Background color |
88
+ | `--stuic-card-bg-hover` | `var(--stuic-color-card-hover, var(--stuic-color-muted))` | Hover background (interactive only) |
89
+ | `--stuic-card-border-width` | `1px` | Border width |
90
+ | `--stuic-card-border` | `var(--stuic-color-border)` | Border color |
91
+ | `--stuic-card-border-hover` | `var(--stuic-color-border-hover)` | Hover border color |
92
+ | `--stuic-card-radius` | `var(--radius-lg)` | Border radius |
93
+ | `--stuic-card-shadow` | `var(--shadow-sm)` | Box shadow |
94
+ | `--stuic-card-shadow-hover` | `var(--shadow-md)` | Hover box shadow |
95
+ | `--stuic-card-transition` | `150ms` | Transition duration |
96
+ | `--stuic-card-padding` | `1rem` | Content and footer padding |
97
+ | `--stuic-card-content-gap` | `0.5rem` | Gap between content elements |
98
+ | `--stuic-card-image-aspect-ratio` | `16 / 9` | Image aspect ratio (vertical only) |
99
+ | `--stuic-card-image-object-fit` | `cover` | Image object-fit |
100
+ | `--stuic-card-image-width-horizontal` | `40%` | Image width in horizontal variant |
101
+ | `--stuic-card-eyebrow-font-size` | `var(--text-xs)` | Eyebrow font size |
102
+ | `--stuic-card-eyebrow-text` | `var(--stuic-color-muted-foreground)` | Eyebrow text color |
103
+ | `--stuic-card-title-font-size` | `var(--text-lg)` | Title font size |
104
+ | `--stuic-card-title-font-weight` | `var(--font-weight-semibold)` | Title font weight |
105
+ | `--stuic-card-title-text` | `var(--stuic-color-foreground)` | Title text color |
106
+ | `--stuic-card-description-font-size` | `var(--text-sm)` | Description font size |
107
+ | `--stuic-card-description-text` | `var(--stuic-color-muted-foreground)` | Description text color |
108
+ | `--stuic-card-ring-width` | `3px` | Focus ring width |
109
+ | `--stuic-card-ring-color` | `var(--stuic-color-ring)` | Focus ring color |
110
+ | `--stuic-card-opacity-disabled` | `0.5` | Disabled opacity |
115
111
 
116
112
  ## Notes
117
113
 
@@ -50,7 +50,8 @@
50
50
  height: 100%;
51
51
  overflow: hidden;
52
52
  background: var(--stuic-card-bg);
53
- border: var(--stuic-card-border-width, var(--stuic-border-width)) solid var(--stuic-card-border);
53
+ border: var(--stuic-card-border-width, var(--stuic-border-width)) solid
54
+ var(--stuic-card-border);
54
55
  border-radius: var(--stuic-card-radius, var(--stuic-radius-container));
55
56
  box-shadow: var(--stuic-card-shadow, var(--stuic-shadow));
56
57
  transition:
@@ -403,9 +403,7 @@
403
403
  </div>
404
404
 
405
405
  {#if arrows && coll.size > 1}
406
- <div
407
- class="absolute inset-0 flex items-center justify-between pointer-events-none"
408
- >
406
+ <div class="absolute inset-0 flex items-center justify-between pointer-events-none">
409
407
  <Button
410
408
  class={twMerge(
411
409
  "stuic-carousel-arrow pointer-events-auto p-0! ml-4",
@@ -5,34 +5,34 @@ keyboard navigation, snap scrolling, and flexible content rendering via THC.
5
5
 
6
6
  ## Props
7
7
 
8
- | Prop | Type | Default | Description |
9
- | ----------------- | ------------------------------------------------------------------- | ---------- | -------------------------------------- |
10
- | `items` | `CarouselItem[]` | required | Array of carousel items |
11
- | `itemsPerView` | `number` | `1` | Number of items visible per view |
12
- | `peekPercent` | `number` | `0` | Percentage of next item to show (0-50) |
13
- | `gap` | `number \| string` | - | Gap between items |
14
- | `minItemWidth` | `number` | `150` | Minimum item width in px (auto-fit floor) |
15
- | `trackActive` | `boolean` | `false` | Enable active item tracking |
16
- | `syncActiveOnScroll` | `boolean` | `false` | Update active item based on scroll position (requires `trackActive`) |
17
- | `activeIndex` | `number` | `0` | Active item index (bindable) |
18
- | `value` | `string \| number` | - | Active item id (bindable) |
19
- | `snap` | `boolean` | `true` | Enable scroll snap |
20
- | `snapAlign` | `"start" \| "center" \| "end"` | `"start"` | Snap alignment |
21
- | `keyboard` | `boolean` | `true` | Enable keyboard navigation |
22
- | `wheelScroll` | `boolean` | `true` | Enable horizontal scrolling via mouse wheel |
23
- | `loop` | `boolean` | `false` | Loop navigation (arrows / keyboard only — wheel never loops) |
24
- | `scrollBehavior` | `ScrollBehavior` | `"smooth"` | Scroll behavior (overridden to `"instant"` when `prefers-reduced-motion: reduce`) |
25
- | `scrollbar` | `boolean` | `true` | Show the scrollbar on hover (set `false` when using nav buttons) |
26
- | `arrows` | `boolean` | `false` | Show prev/next arrow buttons overlaid on left/right edges |
27
- | `classArrow` | `string` | - | Custom class for arrow buttons |
28
- | `class` | `string` | - | Custom class for container |
29
- | `classTrack` | `string` | - | Custom class for scroll track |
30
- | `classItem` | `string` | - | Custom class for items |
31
- | `classItemActive` | `string` | - | Custom class for active item |
32
- | `unstyled` | `boolean` | `false` | Skip default styling |
33
- | `el` | `HTMLDivElement` | - | Element reference (bindable) |
34
- | `onActiveChange` | `(item: CarouselItem, index: number) => void` | - | Callback when active changes |
35
- | `renderItem` | `Snippet<[{ item: CarouselItem; index: number; active: boolean }]>` | - | Custom item render snippet |
8
+ | Prop | Type | Default | Description |
9
+ | -------------------- | ------------------------------------------------------------------- | ---------- | --------------------------------------------------------------------------------- |
10
+ | `items` | `CarouselItem[]` | required | Array of carousel items |
11
+ | `itemsPerView` | `number` | `1` | Number of items visible per view |
12
+ | `peekPercent` | `number` | `0` | Percentage of next item to show (0-50) |
13
+ | `gap` | `number \| string` | - | Gap between items |
14
+ | `minItemWidth` | `number` | `150` | Minimum item width in px (auto-fit floor) |
15
+ | `trackActive` | `boolean` | `false` | Enable active item tracking |
16
+ | `syncActiveOnScroll` | `boolean` | `false` | Update active item based on scroll position (requires `trackActive`) |
17
+ | `activeIndex` | `number` | `0` | Active item index (bindable) |
18
+ | `value` | `string \| number` | - | Active item id (bindable) |
19
+ | `snap` | `boolean` | `true` | Enable scroll snap |
20
+ | `snapAlign` | `"start" \| "center" \| "end"` | `"start"` | Snap alignment |
21
+ | `keyboard` | `boolean` | `true` | Enable keyboard navigation |
22
+ | `wheelScroll` | `boolean` | `true` | Enable horizontal scrolling via mouse wheel |
23
+ | `loop` | `boolean` | `false` | Loop navigation (arrows / keyboard only — wheel never loops) |
24
+ | `scrollBehavior` | `ScrollBehavior` | `"smooth"` | Scroll behavior (overridden to `"instant"` when `prefers-reduced-motion: reduce`) |
25
+ | `scrollbar` | `boolean` | `true` | Show the scrollbar on hover (set `false` when using nav buttons) |
26
+ | `arrows` | `boolean` | `false` | Show prev/next arrow buttons overlaid on left/right edges |
27
+ | `classArrow` | `string` | - | Custom class for arrow buttons |
28
+ | `class` | `string` | - | Custom class for container |
29
+ | `classTrack` | `string` | - | Custom class for scroll track |
30
+ | `classItem` | `string` | - | Custom class for items |
31
+ | `classItemActive` | `string` | - | Custom class for active item |
32
+ | `unstyled` | `boolean` | `false` | Skip default styling |
33
+ | `el` | `HTMLDivElement` | - | Element reference (bindable) |
34
+ | `onActiveChange` | `(item: CarouselItem, index: number) => void` | - | Callback when active changes |
35
+ | `renderItem` | `Snippet<[{ item: CarouselItem; index: number; active: boolean }]>` | - | Custom item render snippet |
36
36
 
37
37
  ## CarouselItem Interface
38
38
 
@@ -427,7 +427,8 @@
427
427
  type="button"
428
428
  class={!unstyled ? "stuic-cart-remove" : undefined}
429
429
  disabled={isUpdating}
430
- aria-label={t("remove_item_aria", { name: item.name }) || t("remove_item")}
430
+ aria-label={t("remove_item_aria", { name: item.name }) ||
431
+ t("remove_item")}
431
432
  onclick={() => onRemove?.(item.id)}
432
433
  >
433
434
  {t("remove_item")}
@@ -118,20 +118,20 @@ Minimal, dense read-only list for order confirmation screens or invoices. Each l
118
118
 
119
119
  ## Props
120
120
 
121
- | Prop | Type | Default | Description |
122
- | ------------------ | ----------------------------------- | ----------------------------- | ------------------------------------------------------------------- |
123
- | `items` | `CartComponentItem[]` | required | Cart items to display |
124
- | `variant` | `"default" \| "compact" \| "summary"` | `"default"` | Layout variant. `compact` = smaller/scrollable (implicit readonly); `summary` = receipt-style list with name ×qty + line total, no thumbnails/controls/footer (implicit readonly) |
125
- | `formatPrice` | `(value: number) => string` | `(v) => (v / 100).toFixed(2)` | Format numeric price for display |
126
- | `onQuantityChange` | `(id: string, qty: number) => void` | — | Called when quantity changes |
127
- | `onRemove` | `(id: string) => void` | — | Called when remove is clicked |
128
- | `readonly` | `boolean` | `false` | Hide interactive controls |
129
- | `loading` | `boolean` | `false` | Show loading skeleton |
130
- | `updatingItems` | `Set<string>` | `new Set()` | Item IDs currently being updated |
131
- | `t` | `TranslateFn` | built-in | Translation function |
132
- | `unstyled` | `boolean` | `false` | Skip all default styling |
133
- | `class` | `string` | — | Additional CSS classes |
134
- | `el` | `HTMLDivElement` | — | Bindable element reference |
121
+ | Prop | Type | Default | Description |
122
+ | ------------------ | ------------------------------------- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
123
+ | `items` | `CartComponentItem[]` | required | Cart items to display |
124
+ | `variant` | `"default" \| "compact" \| "summary"` | `"default"` | Layout variant. `compact` = smaller/scrollable (implicit readonly); `summary` = receipt-style list with name ×qty + line total, no thumbnails/controls/footer (implicit readonly) |
125
+ | `formatPrice` | `(value: number) => string` | `(v) => (v / 100).toFixed(2)` | Format numeric price for display |
126
+ | `onQuantityChange` | `(id: string, qty: number) => void` | — | Called when quantity changes |
127
+ | `onRemove` | `(id: string) => void` | — | Called when remove is clicked |
128
+ | `readonly` | `boolean` | `false` | Hide interactive controls |
129
+ | `loading` | `boolean` | `false` | Show loading skeleton |
130
+ | `updatingItems` | `Set<string>` | `new Set()` | Item IDs currently being updated |
131
+ | `t` | `TranslateFn` | built-in | Translation function |
132
+ | `unstyled` | `boolean` | `false` | Skip all default styling |
133
+ | `class` | `string` | — | Additional CSS classes |
134
+ | `el` | `HTMLDivElement` | — | Bindable element reference |
135
135
 
136
136
  ### CartComponentItem
137
137
 
@@ -184,15 +184,15 @@ Minimal, dense read-only list for order confirmation screens or invoices. Each l
184
184
 
185
185
  ## Translation Keys
186
186
 
187
- | Key | Default | Description |
188
- | ------------------- | -------------------- | ------------------------- |
189
- | `empty_cart` | "Your cart is empty" | Empty state text |
190
- | `unit_price_each` | "{price} each" | Unit price label |
191
- | `quantity_label` | "Qty: {quantity}" | Readonly quantity display |
192
- | `remove_item` | "Remove" | Remove button text |
187
+ | Key | Default | Description |
188
+ | ------------------- | -------------------- | ----------------------------------------------------------- |
189
+ | `empty_cart` | "Your cart is empty" | Empty state text |
190
+ | `unit_price_each` | "{price} each" | Unit price label |
191
+ | `quantity_label` | "Qty: {quantity}" | Readonly quantity display |
192
+ | `remove_item` | "Remove" | Remove button text |
193
193
  | `remove_item_aria` | "Remove {name}" | Accessible label on the remove button (announces item name) |
194
- | `total_label` | "Total" | Summary label |
195
- | `item_count_1` | "1 item" | Singular item count |
196
- | `item_count_n` | "{count} items" | Plural item count |
197
- | `decrease_quantity` | "Decrease quantity" | Aria label for − button |
198
- | `increase_quantity` | "Increase quantity" | Aria label for + button |
194
+ | `total_label` | "Total" | Summary label |
195
+ | `item_count_1` | "1 item" | Singular item count |
196
+ | `item_count_n` | "{count} items" | Plural item count |
197
+ | `decrease_quantity` | "Decrease quantity" | Aria label for − button |
198
+ | `increase_quantity` | "Increase quantity" | Aria label for + button |
@@ -156,7 +156,8 @@
156
156
  "register_form.email_invalid": "checkout.register.email_invalid",
157
157
  "register_form.password_required": "checkout.register.password_required",
158
158
  "register_form.password_too_short": "checkout.register.password_too_short",
159
- "register_form.password_confirm_required": "checkout.register.password_confirm_required",
159
+ "register_form.password_confirm_required":
160
+ "checkout.register.password_confirm_required",
160
161
  "register_form.password_mismatch": "checkout.register.password_mismatch",
161
162
  "register_form.field_required": "checkout.register.field_required",
162
163
  "register_form.social_divider": "checkout.register.social_divider",
@@ -177,7 +178,8 @@
177
178
  "login_or_register_form.mode_register": "checkout.login_or_register.mode_register",
178
179
  "login_or_register_form.mode_verify": "checkout.login_or_register.mode_verify",
179
180
  "login_or_register_form.social_divider": "checkout.login_or_register.social_divider",
180
- "login_or_register_form.modal_title_login": "checkout.login_or_register.modal_title_login",
181
+ "login_or_register_form.modal_title_login":
182
+ "checkout.login_or_register.modal_title_login",
181
183
  "login_or_register_form.modal_title_register":
182
184
  "checkout.login_or_register.modal_title_register",
183
185
  "login_or_register_form.modal_title_verify":
@@ -242,7 +244,10 @@
242
244
  let _loroVerifyEmail = $state("");
243
245
 
244
246
  $effect(() => {
245
- if (loginOrRegisterModal?.mode !== undefined && loginOrRegisterModal.mode !== _loroMode) {
247
+ if (
248
+ loginOrRegisterModal?.mode !== undefined &&
249
+ loginOrRegisterModal.mode !== _loroMode
250
+ ) {
246
251
  _loroMode = loginOrRegisterModal.mode;
247
252
  }
248
253
  });
@@ -222,8 +222,7 @@
222
222
  opts?: Parameters<typeof scrollToFirstInvalidField>[1]
223
223
  ): boolean {
224
224
  if (shippingFormRef?.scrollToFirstError(opts)) return true;
225
- if (!billingSameAsShipping && billingFormRef?.scrollToFirstError(opts))
226
- return true;
225
+ if (!billingSameAsShipping && billingFormRef?.scrollToFirstError(opts)) return true;
227
226
  return false;
228
227
  }
229
228