@nuvia-ui/components 4.0.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 (230) hide show
  1. package/package.json +27 -0
  2. package/src/ds-accordion/ds-accordion-item.js +288 -0
  3. package/src/ds-accordion/ds-accordion-item.stories.js +82 -0
  4. package/src/ds-accordion/ds-accordion.a11y.test.js +92 -0
  5. package/src/ds-accordion/ds-accordion.js +68 -0
  6. package/src/ds-accordion/ds-accordion.stories.js +118 -0
  7. package/src/ds-accordion/ds-accordion.test.js +146 -0
  8. package/src/ds-accordion/index.js +2 -0
  9. package/src/ds-action-bar/ds-action-bar.js +116 -0
  10. package/src/ds-action-bar/ds-action-bar.stories.js +86 -0
  11. package/src/ds-action-bar/ds-action-bar.test.js +64 -0
  12. package/src/ds-action-bar/index.js +1 -0
  13. package/src/ds-alert/ds-alert.a11y.test.js +151 -0
  14. package/src/ds-alert/ds-alert.js +223 -0
  15. package/src/ds-alert/ds-alert.mdx +142 -0
  16. package/src/ds-alert/ds-alert.stories.js +166 -0
  17. package/src/ds-alert/ds-alert.test.js +256 -0
  18. package/src/ds-alert/index.js +1 -0
  19. package/src/ds-avatar/ds-avatar.a11y.test.js +45 -0
  20. package/src/ds-avatar/ds-avatar.js +216 -0
  21. package/src/ds-avatar/ds-avatar.stories.js +120 -0
  22. package/src/ds-avatar/ds-avatar.test.js +83 -0
  23. package/src/ds-avatar/index.js +1 -0
  24. package/src/ds-avatar-extended/ds-avatar-extended.a11y.test.js +29 -0
  25. package/src/ds-avatar-extended/ds-avatar-extended.js +108 -0
  26. package/src/ds-avatar-extended/ds-avatar-extended.stories.js +93 -0
  27. package/src/ds-avatar-extended/ds-avatar-extended.test.js +66 -0
  28. package/src/ds-avatar-extended/index.js +1 -0
  29. package/src/ds-banner/ds-banner.a11y.test.js +51 -0
  30. package/src/ds-banner/ds-banner.js +233 -0
  31. package/src/ds-banner/ds-banner.stories.js +185 -0
  32. package/src/ds-banner/ds-banner.test.js +116 -0
  33. package/src/ds-banner/index.js +1 -0
  34. package/src/ds-breadcrumb-item/ds-breadcrumb-item.js +135 -0
  35. package/src/ds-breadcrumb-item/ds-breadcrumb-item.stories.js +49 -0
  36. package/src/ds-breadcrumb-item/ds-breadcrumb-item.test.js +55 -0
  37. package/src/ds-breadcrumbs/ds-breadcrumbs.js +194 -0
  38. package/src/ds-breadcrumbs/ds-breadcrumbs.stories.js +54 -0
  39. package/src/ds-breadcrumbs/ds-breadcrumbs.test.js +33 -0
  40. package/src/ds-button/ds-button.a11y.test.js +49 -0
  41. package/src/ds-button/ds-button.js +205 -0
  42. package/src/ds-button/ds-button.mdx +141 -0
  43. package/src/ds-button/ds-button.stories.js +152 -0
  44. package/src/ds-button/ds-button.test.js +62 -0
  45. package/src/ds-button/index.js +1 -0
  46. package/src/ds-button-group/ds-button-group.js +82 -0
  47. package/src/ds-button-group/ds-button-group.mdx +39 -0
  48. package/src/ds-button-group/ds-button-group.stories.js +47 -0
  49. package/src/ds-button-group/ds-button-group.test.js +47 -0
  50. package/src/ds-button-group/index.js +1 -0
  51. package/src/ds-checkbox/ds-checkbox.a11y.test.js +79 -0
  52. package/src/ds-checkbox/ds-checkbox.js +271 -0
  53. package/src/ds-checkbox/ds-checkbox.stories.js +77 -0
  54. package/src/ds-checkbox/ds-checkbox.test.js +191 -0
  55. package/src/ds-checkbox/index.js +1 -0
  56. package/src/ds-checkbox-group/ds-checkbox-group.a11y.test.js +146 -0
  57. package/src/ds-checkbox-group/ds-checkbox-group.js +235 -0
  58. package/src/ds-checkbox-group/ds-checkbox-group.stories.js +210 -0
  59. package/src/ds-checkbox-group/ds-checkbox-group.test.js +150 -0
  60. package/src/ds-checkbox-group/index.js +1 -0
  61. package/src/ds-dialog/ds-dialog.js +466 -0
  62. package/src/ds-dialog/ds-dialog.stories.js +274 -0
  63. package/src/ds-dialog/ds-dialog.test.js +441 -0
  64. package/src/ds-dialog/index.js +1 -0
  65. package/src/ds-dropdown/ds-dropdown.a11y.test.js +80 -0
  66. package/src/ds-dropdown/ds-dropdown.js +891 -0
  67. package/src/ds-dropdown/ds-dropdown.stories.js +259 -0
  68. package/src/ds-dropdown/ds-dropdown.test.js +268 -0
  69. package/src/ds-dropdown/index.js +1 -0
  70. package/src/ds-dropdown-group/ds-dropdown-group.js +55 -0
  71. package/src/ds-dropdown-panel/ds-dropdown-panel.js +34 -0
  72. package/src/ds-file-uploaded/ds-file-uploaded.a11y.test.js +40 -0
  73. package/src/ds-file-uploaded/ds-file-uploaded.js +135 -0
  74. package/src/ds-file-uploaded/ds-file-uploaded.mdx +33 -0
  75. package/src/ds-file-uploaded/ds-file-uploaded.stories.js +81 -0
  76. package/src/ds-file-uploaded/ds-file-uploaded.test.js +85 -0
  77. package/src/ds-file-uploader/ds-file-uploader.a11y.test.js +61 -0
  78. package/src/ds-file-uploader/ds-file-uploader.js +442 -0
  79. package/src/ds-file-uploader/ds-file-uploader.mdx +44 -0
  80. package/src/ds-file-uploader/ds-file-uploader.stories.js +76 -0
  81. package/src/ds-file-uploader/ds-file-uploader.test.js +142 -0
  82. package/src/ds-header/ds-header.a11y.test.js +38 -0
  83. package/src/ds-header/ds-header.js +149 -0
  84. package/src/ds-header/ds-header.stories.js +63 -0
  85. package/src/ds-header/ds-header.test.js +52 -0
  86. package/src/ds-header/index.js +1 -0
  87. package/src/ds-header-nav/ds-header-nav.a11y.test.js +69 -0
  88. package/src/ds-header-nav/ds-header-nav.js +114 -0
  89. package/src/ds-header-nav/ds-header-nav.stories.js +17 -0
  90. package/src/ds-header-nav/ds-header-nav.test.js +93 -0
  91. package/src/ds-header-nav-item/ds-header-nav-item.a11y.test.js +71 -0
  92. package/src/ds-header-nav-item/ds-header-nav-item.js +124 -0
  93. package/src/ds-header-nav-item/ds-header-nav-item.stories.js +43 -0
  94. package/src/ds-header-nav-item/ds-header-nav-item.test.js +61 -0
  95. package/src/ds-icon/ds-icon.a11y.test.js +49 -0
  96. package/src/ds-icon/ds-icon.js +75 -0
  97. package/src/ds-icon/ds-icon.mdx +36 -0
  98. package/src/ds-icon/ds-icon.stories.js +88 -0
  99. package/src/ds-icon/ds-icon.test.js +97 -0
  100. package/src/ds-icon/index.js +1 -0
  101. package/src/ds-icon-button/ds-icon-button.a11y.test.js +55 -0
  102. package/src/ds-icon-button/ds-icon-button.js +224 -0
  103. package/src/ds-icon-button/ds-icon-button.mdx +131 -0
  104. package/src/ds-icon-button/ds-icon-button.stories.js +128 -0
  105. package/src/ds-icon-button/ds-icon-button.test.js +90 -0
  106. package/src/ds-icon-button/index.js +1 -0
  107. package/src/ds-input/ds-input.a11y.test.js +145 -0
  108. package/src/ds-input/ds-input.js +645 -0
  109. package/src/ds-input/ds-input.mdx +251 -0
  110. package/src/ds-input/ds-input.stories.js +298 -0
  111. package/src/ds-input/ds-input.test.js +792 -0
  112. package/src/ds-input/index.js +1 -0
  113. package/src/ds-link/ds-link.js +111 -0
  114. package/src/ds-link/ds-link.stories.js +56 -0
  115. package/src/ds-link/ds-link.test.js +74 -0
  116. package/src/ds-list-item/ds-list-item.a11y.test.js +39 -0
  117. package/src/ds-list-item/ds-list-item.js +292 -0
  118. package/src/ds-list-item/ds-list-item.stories.js +101 -0
  119. package/src/ds-list-item/ds-list-item.test.js +63 -0
  120. package/src/ds-menu/ds-menu.js +30 -0
  121. package/src/ds-menu/ds-menu.stories.js +120 -0
  122. package/src/ds-menu/ds-menu.test.js +123 -0
  123. package/src/ds-menu-group/ds-menu-group.js +101 -0
  124. package/src/ds-menu-group/ds-menu-group.stories.js +99 -0
  125. package/src/ds-nav-item/ds-nav-item.a11y.test.js +91 -0
  126. package/src/ds-nav-item/ds-nav-item.js +307 -0
  127. package/src/ds-nav-item/ds-nav-item.stories.js +99 -0
  128. package/src/ds-nav-item/ds-nav-item.test.js +169 -0
  129. package/src/ds-nav-item/index.js +1 -0
  130. package/src/ds-nav-vertical/ds-nav-vertical.a11y.test.js +69 -0
  131. package/src/ds-nav-vertical/ds-nav-vertical.js +173 -0
  132. package/src/ds-nav-vertical/ds-nav-vertical.stories.js +124 -0
  133. package/src/ds-nav-vertical/ds-nav-vertical.test.js +176 -0
  134. package/src/ds-nav-vertical/index.js +1 -0
  135. package/src/ds-pagination/ds-pagination.a11y.test.js +50 -0
  136. package/src/ds-pagination/ds-pagination.js +232 -0
  137. package/src/ds-pagination/ds-pagination.stories.js +63 -0
  138. package/src/ds-pagination/ds-pagination.test.js +141 -0
  139. package/src/ds-pagination/index.js +1 -0
  140. package/src/ds-progress-bar/ds-progress-bar.a11y.test.js +25 -0
  141. package/src/ds-progress-bar/ds-progress-bar.js +81 -0
  142. package/src/ds-progress-bar/ds-progress-bar.stories.js +69 -0
  143. package/src/ds-progress-bar/ds-progress-bar.test.js +60 -0
  144. package/src/ds-radio/ds-radio.a11y.test.js +69 -0
  145. package/src/ds-radio/ds-radio.js +240 -0
  146. package/src/ds-radio/ds-radio.stories.js +102 -0
  147. package/src/ds-radio/ds-radio.test.js +114 -0
  148. package/src/ds-radio/index.js +1 -0
  149. package/src/ds-radio-group/ds-radio-group.a11y.test.js +164 -0
  150. package/src/ds-radio-group/ds-radio-group.js +257 -0
  151. package/src/ds-radio-group/ds-radio-group.stories.js +247 -0
  152. package/src/ds-radio-group/ds-radio-group.test.js +194 -0
  153. package/src/ds-radio-group/index.js +1 -0
  154. package/src/ds-rich-list/ds-rich-list.js +246 -0
  155. package/src/ds-rich-list/ds-rich-list.stories.js +368 -0
  156. package/src/ds-rich-list/ds-rich-list.test.js +293 -0
  157. package/src/ds-rich-list-item/ds-rich-list-item.js +579 -0
  158. package/src/ds-rich-list-item/ds-rich-list-item.stories.js +197 -0
  159. package/src/ds-rich-list-item/ds-rich-list-item.test.js +434 -0
  160. package/src/ds-slider/ds-slider.js +399 -0
  161. package/src/ds-slider/ds-slider.stories.js +107 -0
  162. package/src/ds-slider/ds-slider.test.js +308 -0
  163. package/src/ds-spinner/ds-spinner.js +173 -0
  164. package/src/ds-spinner/ds-spinner.stories.js +52 -0
  165. package/src/ds-spinner/ds-spinner.test.js +50 -0
  166. package/src/ds-status-border/ds-status-border.js +88 -0
  167. package/src/ds-status-border/ds-status-border.stories.js +242 -0
  168. package/src/ds-status-border/ds-status-border.test.js +168 -0
  169. package/src/ds-stepper/ds-stepper.a11y.test.js +198 -0
  170. package/src/ds-stepper/ds-stepper.js +207 -0
  171. package/src/ds-stepper/ds-stepper.stories.js +530 -0
  172. package/src/ds-stepper/ds-stepper.test.js +311 -0
  173. package/src/ds-stepper-item/ds-stepper-item.js +485 -0
  174. package/src/ds-stepper-item/ds-stepper-item.stories.js +288 -0
  175. package/src/ds-switch/ds-switch.js +348 -0
  176. package/src/ds-switch/ds-switch.stories.js +145 -0
  177. package/src/ds-switch/ds-switch.test.js +226 -0
  178. package/src/ds-switch/index.js +1 -0
  179. package/src/ds-tab-item/ds-tab-item.js +341 -0
  180. package/src/ds-tab-item/ds-tab-item.stories.js +69 -0
  181. package/src/ds-tabs/ds-tab-panel.js +48 -0
  182. package/src/ds-tabs/ds-tabs.a11y.test.js +56 -0
  183. package/src/ds-tabs/ds-tabs.js +180 -0
  184. package/src/ds-tabs/ds-tabs.stories.js +152 -0
  185. package/src/ds-tabs/ds-tabs.test.js +306 -0
  186. package/src/ds-tabs/index.js +3 -0
  187. package/src/ds-tag-action/ds-tag-action.a11y.test.js +32 -0
  188. package/src/ds-tag-action/ds-tag-action.js +185 -0
  189. package/src/ds-tag-action/ds-tag-action.stories.js +55 -0
  190. package/src/ds-tag-action/ds-tag-action.test.js +44 -0
  191. package/src/ds-tag-removable/ds-tag-removable.a11y.test.js +24 -0
  192. package/src/ds-tag-removable/ds-tag-removable.js +146 -0
  193. package/src/ds-tag-removable/ds-tag-removable.stories.js +52 -0
  194. package/src/ds-tag-removable/ds-tag-removable.test.js +46 -0
  195. package/src/ds-tag-status/ds-tag-status.a11y.test.js +93 -0
  196. package/src/ds-tag-status/ds-tag-status.js +164 -0
  197. package/src/ds-tag-status/ds-tag-status.stories.js +200 -0
  198. package/src/ds-tag-status/ds-tag-status.test.js +140 -0
  199. package/src/ds-tag-status/index.js +1 -0
  200. package/src/ds-textarea/ds-textarea-clearable.test.js +89 -0
  201. package/src/ds-textarea/ds-textarea.a11y.test.js +66 -0
  202. package/src/ds-textarea/ds-textarea.js +505 -0
  203. package/src/ds-textarea/ds-textarea.stories.js +335 -0
  204. package/src/ds-textarea/ds-textarea.test.js +218 -0
  205. package/src/ds-textarea/index.js +1 -0
  206. package/src/ds-thumbnail/ds-thumbnail.js +207 -0
  207. package/src/ds-thumbnail/ds-thumbnail.stories.js +217 -0
  208. package/src/ds-thumbnail/ds-thumbnail.test.js +220 -0
  209. package/src/ds-toast/ds-toast-provider.js +110 -0
  210. package/src/ds-toast/ds-toast.a11y.test.js +34 -0
  211. package/src/ds-toast/ds-toast.js +243 -0
  212. package/src/ds-toast/ds-toast.stories.js +143 -0
  213. package/src/ds-toast/ds-toast.test.js +93 -0
  214. package/src/ds-toast/index.js +2 -0
  215. package/src/ds-tooltip/ds-tooltip.a11y.test.js +110 -0
  216. package/src/ds-tooltip/ds-tooltip.js +217 -0
  217. package/src/ds-tooltip/ds-tooltip.mdx +75 -0
  218. package/src/ds-tooltip/ds-tooltip.stories.js +72 -0
  219. package/src/ds-tooltip/ds-tooltip.test.js +191 -0
  220. package/src/ds-tooltip/index.js +1 -0
  221. package/src/ds-tooltip/positioner.js +117 -0
  222. package/src/index.js +50 -0
  223. package/src/mixins/field-label.mixin.js +113 -0
  224. package/src/mixins/field-message.mixin.js +66 -0
  225. package/src/token-provider/index.js +1 -0
  226. package/src/token-provider/token-provider.a11y.test.js +44 -0
  227. package/src/token-provider/token-provider.js +85 -0
  228. package/src/token-provider/token-provider.stories.js +105 -0
  229. package/src/token-provider/token-provider.test.js +134 -0
  230. package/src/utils/number-input.utils.js +42 -0
@@ -0,0 +1,311 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
+ import './ds-stepper.js';
3
+ import '../ds-stepper-item/ds-stepper-item.js';
4
+
5
+ const wait = (ms = 50) => new Promise(resolve => setTimeout(resolve, ms));
6
+
7
+ describe('ds-stepper', () => {
8
+ let container;
9
+
10
+ beforeEach(() => {
11
+ container = document.createElement('div');
12
+ document.body.appendChild(container);
13
+ });
14
+
15
+ afterEach(() => {
16
+ container.remove();
17
+ });
18
+
19
+ it('renders with default slots', async () => {
20
+ container.innerHTML = `
21
+ <ds-stepper>
22
+ <ds-stepper-item>Step 1</ds-stepper-item>
23
+ <ds-stepper-item>Step 2</ds-stepper-item>
24
+ <ds-stepper-item>Step 3</ds-stepper-item>
25
+ </ds-stepper>
26
+ `;
27
+ const el = container.querySelector('ds-stepper');
28
+ await wait();
29
+
30
+ expect(el).toBeTruthy();
31
+ const items = el.querySelectorAll('ds-stepper-item');
32
+ expect(items.length).toBe(3);
33
+ });
34
+
35
+ it('defaults to horizontal direction', async () => {
36
+ container.innerHTML = `
37
+ <ds-stepper>
38
+ <ds-stepper-item>Step 1</ds-stepper-item>
39
+ </ds-stepper>
40
+ `;
41
+ const el = container.querySelector('ds-stepper');
42
+ await wait();
43
+
44
+ expect(el.direction).toBe('horizontal');
45
+ });
46
+
47
+ it('supports vertical direction', async () => {
48
+ container.innerHTML = `
49
+ <ds-stepper direction="vertical">
50
+ <ds-stepper-item>Step 1</ds-stepper-item>
51
+ <ds-stepper-item>Step 2</ds-stepper-item>
52
+ </ds-stepper>
53
+ `;
54
+ const el = container.querySelector('ds-stepper');
55
+ await wait();
56
+
57
+ expect(el.direction).toBe('vertical');
58
+ expect(el.getAttribute('direction')).toBe('vertical');
59
+ });
60
+
61
+ it('assigns position (first, middle, last) to children', async () => {
62
+ container.innerHTML = `
63
+ <ds-stepper>
64
+ <ds-stepper-item>Step 1</ds-stepper-item>
65
+ <ds-stepper-item>Step 2</ds-stepper-item>
66
+ <ds-stepper-item>Step 3</ds-stepper-item>
67
+ </ds-stepper>
68
+ `;
69
+ await wait();
70
+
71
+ const items = container.querySelectorAll('ds-stepper-item');
72
+ expect(items[0]._position).toBe('first');
73
+ expect(items[1]._position).toBe('middle');
74
+ expect(items[2]._position).toBe('last');
75
+ });
76
+
77
+ it('assigns step numbers and total to children', async () => {
78
+ container.innerHTML = `
79
+ <ds-stepper>
80
+ <ds-stepper-item>Step 1</ds-stepper-item>
81
+ <ds-stepper-item>Step 2</ds-stepper-item>
82
+ <ds-stepper-item>Step 3</ds-stepper-item>
83
+ </ds-stepper>
84
+ `;
85
+ await wait();
86
+
87
+ const items = container.querySelectorAll('ds-stepper-item');
88
+ expect(items[0]._step).toBe(1);
89
+ expect(items[1]._step).toBe(2);
90
+ expect(items[2]._step).toBe(3);
91
+ expect(items[0]._totalSteps).toBe(3);
92
+ expect(items[2]._totalSteps).toBe(3);
93
+ });
94
+
95
+ it('derives completed/current states from active-step prop (controlled)', async () => {
96
+ container.innerHTML = `
97
+ <ds-stepper active-step="1">
98
+ <ds-stepper-item>Step 1</ds-stepper-item>
99
+ <ds-stepper-item>Step 2</ds-stepper-item>
100
+ <ds-stepper-item>Step 3</ds-stepper-item>
101
+ </ds-stepper>
102
+ `;
103
+ await wait();
104
+
105
+ const items = container.querySelectorAll('ds-stepper-item');
106
+ expect(items[0].completed).toBe(true);
107
+ expect(items[0].current).toBe(false);
108
+ expect(items[1].completed).toBe(false);
109
+ expect(items[1].current).toBe(true);
110
+ expect(items[2].completed).toBe(false);
111
+ expect(items[2].current).toBe(false);
112
+ });
113
+
114
+ it('defaults to step 0 active in uncontrolled mode', async () => {
115
+ container.innerHTML = `
116
+ <ds-stepper>
117
+ <ds-stepper-item>Step 1</ds-stepper-item>
118
+ <ds-stepper-item>Step 2</ds-stepper-item>
119
+ </ds-stepper>
120
+ `;
121
+ await wait();
122
+
123
+ const items = container.querySelectorAll('ds-stepper-item');
124
+ expect(items[0].current).toBe(true);
125
+ expect(items[1].current).toBe(false);
126
+ });
127
+
128
+ it('supports default-active-step for initial uncontrolled state', async () => {
129
+ container.innerHTML = `
130
+ <ds-stepper default-active-step="2">
131
+ <ds-stepper-item>Step 1</ds-stepper-item>
132
+ <ds-stepper-item>Step 2</ds-stepper-item>
133
+ <ds-stepper-item>Step 3</ds-stepper-item>
134
+ </ds-stepper>
135
+ `;
136
+ await wait();
137
+
138
+ const items = container.querySelectorAll('ds-stepper-item');
139
+ expect(items[0].completed).toBe(true);
140
+ expect(items[1].completed).toBe(true);
141
+ expect(items[2].current).toBe(true);
142
+ });
143
+
144
+ it('emits ds-change when a step is clicked', async () => {
145
+ container.innerHTML = `
146
+ <ds-stepper>
147
+ <ds-stepper-item>Step 1</ds-stepper-item>
148
+ <ds-stepper-item>Step 2</ds-stepper-item>
149
+ <ds-stepper-item>Step 3</ds-stepper-item>
150
+ </ds-stepper>
151
+ `;
152
+ await wait();
153
+
154
+ const el = container.querySelector('ds-stepper');
155
+ const items = container.querySelectorAll('ds-stepper-item');
156
+
157
+ let eventDetail = null;
158
+ el.addEventListener('ds-change', (e) => {
159
+ eventDetail = e.detail;
160
+ });
161
+
162
+ // Click second step indicator
163
+ const indicator = items[1].shadowRoot.querySelector('.indicator');
164
+ indicator.click();
165
+ await wait();
166
+
167
+ expect(eventDetail).not.toBeNull();
168
+ expect(eventDetail.currentStep).toBe(1); // 0-based
169
+ expect(eventDetail.previousStep).toBe(0);
170
+ });
171
+
172
+ it('updates internal state on click in uncontrolled mode', async () => {
173
+ container.innerHTML = `
174
+ <ds-stepper>
175
+ <ds-stepper-item>Step 1</ds-stepper-item>
176
+ <ds-stepper-item>Step 2</ds-stepper-item>
177
+ <ds-stepper-item>Step 3</ds-stepper-item>
178
+ </ds-stepper>
179
+ `;
180
+ await wait();
181
+
182
+ const el = container.querySelector('ds-stepper');
183
+ const items = container.querySelectorAll('ds-stepper-item');
184
+
185
+ // Click second step
186
+ const indicator = items[1].shadowRoot.querySelector('.indicator');
187
+ indicator.click();
188
+ await wait();
189
+
190
+ expect(el._internalActiveStep).toBe(1);
191
+ expect(items[0].completed).toBe(true);
192
+ expect(items[1].current).toBe(true);
193
+ });
194
+
195
+ it('does NOT update internal state on click in controlled mode', async () => {
196
+ container.innerHTML = `
197
+ <ds-stepper active-step="0">
198
+ <ds-stepper-item>Step 1</ds-stepper-item>
199
+ <ds-stepper-item>Step 2</ds-stepper-item>
200
+ <ds-stepper-item>Step 3</ds-stepper-item>
201
+ </ds-stepper>
202
+ `;
203
+ await wait();
204
+
205
+ const el = container.querySelector('ds-stepper');
206
+ const items = container.querySelectorAll('ds-stepper-item');
207
+
208
+ // Click second step - should NOT change internal state
209
+ const indicator = items[1].shadowRoot.querySelector('.indicator');
210
+ indicator.click();
211
+ await wait();
212
+
213
+ // State should remain at 0 since parent hasn't updated the prop
214
+ expect(items[0].current).toBe(true);
215
+ expect(items[1].current).toBe(false);
216
+ });
217
+
218
+ it('propagates linear mode to children', async () => {
219
+ container.innerHTML = `
220
+ <ds-stepper linear active-step="0">
221
+ <ds-stepper-item>Step 1</ds-stepper-item>
222
+ <ds-stepper-item>Step 2</ds-stepper-item>
223
+ <ds-stepper-item>Step 3</ds-stepper-item>
224
+ </ds-stepper>
225
+ `;
226
+ await wait();
227
+
228
+ const items = container.querySelectorAll('ds-stepper-item');
229
+ expect(items[0]._linear).toBe(true);
230
+ expect(items[1]._linear).toBe(true);
231
+ expect(items[2]._linear).toBe(true);
232
+ });
233
+
234
+ it('propagates _prevCompleted and _prevError to children', async () => {
235
+ container.innerHTML = `
236
+ <ds-stepper active-step="2">
237
+ <ds-stepper-item>Step 1</ds-stepper-item>
238
+ <ds-stepper-item error>Step 2</ds-stepper-item>
239
+ <ds-stepper-item>Step 3</ds-stepper-item>
240
+ </ds-stepper>
241
+ `;
242
+ await wait();
243
+
244
+ const items = container.querySelectorAll('ds-stepper-item');
245
+ // Item 2's prevCompleted should reference item 1 (completed since activeStep=2)
246
+ expect(items[1]._prevCompleted).toBe(true);
247
+ // Item 3's prevError should be true (item 2 has error)
248
+ expect(items[2]._prevError).toBe(true);
249
+ });
250
+
251
+ it('ignores click on same step', async () => {
252
+ container.innerHTML = `
253
+ <ds-stepper>
254
+ <ds-stepper-item>Step 1</ds-stepper-item>
255
+ <ds-stepper-item>Step 2</ds-stepper-item>
256
+ </ds-stepper>
257
+ `;
258
+ await wait();
259
+
260
+ const el = container.querySelector('ds-stepper');
261
+ const changeSpy = vi.fn();
262
+ el.addEventListener('ds-change', changeSpy);
263
+
264
+ // Click the already-active first step
265
+ const items = container.querySelectorAll('ds-stepper-item');
266
+ const indicator = items[0].shadowRoot.querySelector('.indicator');
267
+ indicator.click();
268
+ await wait();
269
+
270
+ expect(changeSpy).not.toHaveBeenCalled();
271
+ });
272
+
273
+ it('does NOT auto-complete steps when auto-complete="false"', async () => {
274
+ container.innerHTML = `
275
+ <ds-stepper active-step="2">
276
+ <ds-stepper-item>Step 1</ds-stepper-item>
277
+ <ds-stepper-item>Step 2</ds-stepper-item>
278
+ <ds-stepper-item>Step 3</ds-stepper-item>
279
+ </ds-stepper>
280
+ `;
281
+ const el = container.querySelector('ds-stepper');
282
+ el.autoComplete = false; // Set property directly
283
+ await wait();
284
+
285
+ const items = container.querySelectorAll('ds-stepper-item');
286
+ // With auto-complete=false, steps 0 and 1 should NOT be auto-completed
287
+ expect(items[0].completed).toBe(false);
288
+ expect(items[1].completed).toBe(false);
289
+ expect(items[2].current).toBe(true);
290
+ });
291
+
292
+ it('respects manual completed attribute when auto-complete="false"', async () => {
293
+ container.innerHTML = `
294
+ <ds-stepper active-step="2">
295
+ <ds-stepper-item completed>Step 1</ds-stepper-item>
296
+ <ds-stepper-item>Step 2</ds-stepper-item>
297
+ <ds-stepper-item>Step 3</ds-stepper-item>
298
+ </ds-stepper>
299
+ `;
300
+ const el = container.querySelector('ds-stepper');
301
+ el.autoComplete = false; // Set property directly
302
+ await wait();
303
+
304
+ const items = container.querySelectorAll('ds-stepper-item');
305
+ // Item 0 should be completed (manual attribute)
306
+ expect(items[0].completed).toBe(true);
307
+ // Item 1 should NOT be completed (no auto-complete, no manual attribute)
308
+ expect(items[1].completed).toBe(false);
309
+ expect(items[2].current).toBe(true);
310
+ });
311
+ });