tyrell-components 1.0.0-TC52 → 1.0.0-TC53

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 (105) hide show
  1. package/css/tyrell-theme.css +25 -2
  2. package/css/tyrell.css +4 -0
  3. package/dist/tyrell-colors-static.css +1 -316
  4. package/dist/tyrell-theme.css +1 -1443
  5. package/dist/tyrell.css +1 -1390
  6. package/dist/tyrell.js +1 -1
  7. package/lib/base/ty-component.js +196 -196
  8. package/lib/components/button.d.ts +1 -1
  9. package/lib/components/button.js +260 -259
  10. package/lib/components/calendar-month.d.ts +2 -2
  11. package/lib/components/calendar-month.js +426 -416
  12. package/lib/components/calendar-navigation.js +238 -238
  13. package/lib/components/calendar.js +605 -602
  14. package/lib/components/checkbox.d.ts +1 -1
  15. package/lib/components/checkbox.js +273 -272
  16. package/lib/components/copy.d.ts +1 -1
  17. package/lib/components/copy.js +279 -278
  18. package/lib/components/date-picker.d.ts +1 -1
  19. package/lib/components/date-picker.js +1103 -1108
  20. package/lib/components/file-upload.js +404 -404
  21. package/lib/components/icon.js +141 -141
  22. package/lib/components/input.d.ts +1 -1
  23. package/lib/components/input.js +593 -596
  24. package/lib/components/modal.js +319 -319
  25. package/lib/components/option.js +167 -167
  26. package/lib/components/popup.js +233 -233
  27. package/lib/components/radio.d.ts +2 -2
  28. package/lib/components/radio.js +407 -406
  29. package/lib/components/resize-observer.js +67 -67
  30. package/lib/components/scroll-container.js +294 -294
  31. package/lib/components/select.d.ts +1 -1
  32. package/lib/components/select.js +1524 -1532
  33. package/lib/components/selected-tags.js +184 -184
  34. package/lib/components/step.js +62 -62
  35. package/lib/components/switch.d.ts +1 -1
  36. package/lib/components/switch.js +214 -213
  37. package/lib/components/tab.js +62 -62
  38. package/lib/components/tabs.js +507 -507
  39. package/lib/components/tag.d.ts +1 -1
  40. package/lib/components/tag.js +236 -235
  41. package/lib/components/textarea.d.ts +1 -1
  42. package/lib/components/textarea.js +457 -456
  43. package/lib/components/tooltip.js +283 -283
  44. package/lib/components/wizard.js +384 -384
  45. package/lib/icons/heroicons/micro.js +392 -392
  46. package/lib/icons/heroicons/mini.js +382 -382
  47. package/lib/icons/heroicons/outline.js +337 -337
  48. package/lib/icons/heroicons/solid.js +407 -407
  49. package/lib/icons/lucide.js +22843 -22843
  50. package/lib/icons/material/filled.js +9653 -9653
  51. package/lib/icons/material/outlined.js +10271 -10271
  52. package/lib/icons/material/round.js +10495 -10495
  53. package/lib/icons/material/sharp.js +9905 -9905
  54. package/lib/icons/material/two-tone.js +12792 -12792
  55. package/lib/index.js +21 -21
  56. package/lib/styles/button.js +176 -288
  57. package/lib/styles/calendar-month.js +123 -183
  58. package/lib/styles/calendar-navigation.js +60 -79
  59. package/lib/styles/calendar.js +8 -9
  60. package/lib/styles/checkbox.js +45 -72
  61. package/lib/styles/copy.js +67 -91
  62. package/lib/styles/custom-scrollbar.js +80 -100
  63. package/lib/styles/date-picker.js +261 -331
  64. package/lib/styles/field-size.d.ts +6 -0
  65. package/lib/styles/field-size.js +91 -0
  66. package/lib/styles/file-upload.js +139 -169
  67. package/lib/styles/icon.js +92 -156
  68. package/lib/styles/input.js +125 -241
  69. package/lib/styles/modal.js +67 -102
  70. package/lib/styles/option.d.ts +1 -1
  71. package/lib/styles/option.js +47 -67
  72. package/lib/styles/popup.js +34 -65
  73. package/lib/styles/radio.js +69 -96
  74. package/lib/styles/resize-observer.js +2 -5
  75. package/lib/styles/scroll-container.js +100 -130
  76. package/lib/styles/select-base.js +525 -778
  77. package/lib/styles/select.js +140 -228
  78. package/lib/styles/step.js +22 -29
  79. package/lib/styles/switch.js +34 -55
  80. package/lib/styles/tab.js +22 -29
  81. package/lib/styles/tabs.js +171 -252
  82. package/lib/styles/tag.js +135 -188
  83. package/lib/styles/textarea.d.ts +1 -1
  84. package/lib/styles/textarea.js +205 -271
  85. package/lib/styles/tooltip.js +3 -3
  86. package/lib/styles/wizard.js +170 -226
  87. package/lib/types/common.d.ts +2 -0
  88. package/lib/types/common.js +6 -5
  89. package/lib/utils/calendar-utils.js +100 -100
  90. package/lib/utils/custom-scrollbar.js +272 -272
  91. package/lib/utils/flavor-sheet.js +14 -14
  92. package/lib/utils/icon-registry.js +127 -127
  93. package/lib/utils/loader-registry.js +3 -3
  94. package/lib/utils/locale.js +34 -34
  95. package/lib/utils/mobile.js +1 -1
  96. package/lib/utils/number-format.js +54 -54
  97. package/lib/utils/positioning.js +212 -212
  98. package/lib/utils/property-capture.js +36 -36
  99. package/lib/utils/property-manager.js +125 -125
  100. package/lib/utils/resize-observer.js +23 -23
  101. package/lib/utils/scroll-lock.js +57 -57
  102. package/lib/utils/styles.js +17 -17
  103. package/lib/version.d.ts +1 -1
  104. package/lib/version.js +1 -1
  105. package/package.json +4 -4
@@ -3,440 +3,440 @@ import { wizardStyles } from '../styles/wizard.js';
3
3
  const eventHandlers = new WeakMap();
4
4
  const resizeObservers = new WeakMap();
5
5
  function getWizardAttributes(el) {
6
- return {
7
- width: el.getAttribute('width') || '100%',
8
- height: el.getAttribute('height') || '700px',
9
- active: el.getAttribute('active'),
10
- completed: el.getAttribute('completed') || '',
11
- orientation: (el.getAttribute('orientation') || 'horizontal'),
12
- };
6
+ return {
7
+ width: el.getAttribute('width') || '100%',
8
+ height: el.getAttribute('height') || '700px',
9
+ active: el.getAttribute('active'),
10
+ completed: el.getAttribute('completed') || '',
11
+ orientation: (el.getAttribute('orientation') || 'horizontal'),
12
+ };
13
13
  }
14
14
  function getChildSteps(el) {
15
- return Array.from(el.querySelectorAll('ty-step'));
15
+ return Array.from(el.querySelectorAll('ty-step'));
16
16
  }
17
17
  function getStepId(step) {
18
- return step.getAttribute('id');
18
+ return step.getAttribute('id');
19
19
  }
20
20
  function getCompletedStepIds(el) {
21
- const completedAttr = el.getAttribute('completed') || '';
22
- if (!completedAttr.trim())
23
- return new Set();
24
- return new Set(completedAttr.split(',').map(id => id.trim()).filter(Boolean));
21
+ const completedAttr = el.getAttribute('completed') || '';
22
+ if (!completedAttr.trim())
23
+ return new Set();
24
+ return new Set(completedAttr.split(',').map(id => id.trim()).filter(Boolean));
25
25
  }
26
26
  function hasCustomIndicator(wizardEl, stepId) {
27
- return wizardEl.querySelector(`[slot='indicator-${stepId}']`) !== null;
27
+ return wizardEl.querySelector(`[slot='indicator-${stepId}']`) !== null;
28
28
  }
29
29
  function isStepDisabled(step) {
30
- return step.hasAttribute('disabled');
30
+ return step.hasAttribute('disabled');
31
31
  }
32
32
  function findStepIndex(steps, stepId) {
33
- const index = steps.findIndex(step => getStepId(step) === stepId);
34
- return index >= 0 ? index : undefined;
33
+ const index = steps.findIndex(step => getStepId(step) === stepId);
34
+ return index >= 0 ? index : undefined;
35
35
  }
36
36
  function getActiveStepId(el, steps) {
37
- const activeAttr = el.getAttribute('active');
38
- if (activeAttr && findStepIndex(steps, activeAttr) !== undefined) {
39
- return activeAttr;
40
- }
41
- if (steps.length > 0) {
42
- return getStepId(steps[0]);
43
- }
44
- return null;
37
+ const activeAttr = el.getAttribute('active');
38
+ if (activeAttr && findStepIndex(steps, activeAttr) !== undefined) {
39
+ return activeAttr;
40
+ }
41
+ if (steps.length > 0) {
42
+ return getStepId(steps[0]);
43
+ }
44
+ return null;
45
45
  }
46
46
  function setActiveStep(el, stepId) {
47
- el.setAttribute('active', stepId);
47
+ el.setAttribute('active', stepId);
48
48
  }
49
49
  function calculateProgressPercent(steps, activeId, completedIds) {
50
- if (steps.length <= 1 || !activeId)
51
- return 0;
52
- const activeIndex = steps.findIndex(s => getStepId(s) === activeId);
53
- return (activeIndex / (steps.length - 1)) * 100;
50
+ if (steps.length <= 1 || !activeId)
51
+ return 0;
52
+ const activeIndex = steps.findIndex(s => getStepId(s) === activeId);
53
+ return (activeIndex / (steps.length - 1)) * 100;
54
54
  }
55
55
  function dispatchStepChangeEvent(el, activeId, activeIndex, previousId, previousIndex) {
56
- const direction = previousIndex === null ? 'none'
57
- : activeIndex > previousIndex ? 'forward'
58
- : activeIndex < previousIndex ? 'backward'
59
- : 'none';
60
- const event = new CustomEvent('ty-wizard-step-change', {
61
- detail: {
62
- activeId,
63
- activeIndex,
64
- previousId,
65
- previousIndex,
66
- direction,
67
- },
68
- bubbles: true,
69
- cancelable: false,
70
- });
71
- el.dispatchEvent(event);
56
+ const direction = previousIndex === null ? 'none'
57
+ : activeIndex > previousIndex ? 'forward'
58
+ : activeIndex < previousIndex ? 'backward'
59
+ : 'none';
60
+ const event = new CustomEvent('ty-wizard-step-change', {
61
+ detail: {
62
+ activeId,
63
+ activeIndex,
64
+ previousId,
65
+ previousIndex,
66
+ direction,
67
+ },
68
+ bubbles: true,
69
+ cancelable: false,
70
+ });
71
+ el.dispatchEvent(event);
72
72
  }
73
73
  function handleStepClick(el, stepId, event) {
74
- event.preventDefault();
75
- event.stopPropagation();
76
- const steps = getChildSteps(el);
77
- const targetIndex = steps.findIndex(s => getStepId(s) === stepId);
78
- if (targetIndex < 0)
79
- return;
80
- const currentActive = getActiveStepId(el, steps);
81
- const currentIndex = currentActive ? findStepIndex(steps, currentActive) ?? null : null;
82
- const direction = currentIndex === null ? 'none'
83
- : targetIndex > currentIndex ? 'forward'
84
- : targetIndex < currentIndex ? 'backward'
85
- : 'none';
86
- const event2 = new CustomEvent('ty-wizard-step-change', {
87
- detail: {
88
- activeId: stepId,
89
- activeIndex: targetIndex,
90
- previousId: currentActive,
91
- previousIndex: currentIndex,
92
- direction,
93
- },
94
- bubbles: true,
95
- cancelable: false,
96
- });
97
- el.dispatchEvent(event2);
74
+ event.preventDefault();
75
+ event.stopPropagation();
76
+ const steps = getChildSteps(el);
77
+ const targetIndex = steps.findIndex(s => getStepId(s) === stepId);
78
+ if (targetIndex < 0)
79
+ return;
80
+ const currentActive = getActiveStepId(el, steps);
81
+ const currentIndex = currentActive ? findStepIndex(steps, currentActive) ?? null : null;
82
+ const direction = currentIndex === null ? 'none'
83
+ : targetIndex > currentIndex ? 'forward'
84
+ : targetIndex < currentIndex ? 'backward'
85
+ : 'none';
86
+ const event2 = new CustomEvent('ty-wizard-step-change', {
87
+ detail: {
88
+ activeId: stepId,
89
+ activeIndex: targetIndex,
90
+ previousId: currentActive,
91
+ previousIndex: currentIndex,
92
+ direction,
93
+ },
94
+ bubbles: true,
95
+ cancelable: false,
96
+ });
97
+ el.dispatchEvent(event2);
98
98
  }
99
99
  function cleanupEventListeners(el) {
100
- const handlers = eventHandlers.get(el);
101
- if (!handlers)
102
- return;
103
- const shadowRoot = el.shadowRoot;
104
- if (!shadowRoot)
105
- return;
106
- handlers.stepClickHandlers.forEach((handler, stepId) => {
107
- const button = shadowRoot.querySelector(`[data-step-id='${stepId}']`);
108
- if (button) {
109
- button.removeEventListener('pointerdown', handler);
110
- }
111
- });
112
- handlers.stepClickHandlers.clear();
100
+ const handlers = eventHandlers.get(el);
101
+ if (!handlers)
102
+ return;
103
+ const shadowRoot = el.shadowRoot;
104
+ if (!shadowRoot)
105
+ return;
106
+ handlers.stepClickHandlers.forEach((handler, stepId) => {
107
+ const button = shadowRoot.querySelector(`[data-step-id='${stepId}']`);
108
+ if (button) {
109
+ button.removeEventListener('pointerdown', handler);
110
+ }
111
+ });
112
+ handlers.stepClickHandlers.clear();
113
113
  }
114
114
  function setupEventListeners(el, shadowRoot, steps) {
115
- cleanupEventListeners(el);
116
- const handlers = {
117
- stepClickHandlers: new Map(),
118
- };
119
- steps.forEach((step) => {
120
- const stepId = getStepId(step);
121
- if (!stepId)
122
- return;
123
- const button = shadowRoot.querySelector(`[data-step-id='${stepId}']`);
124
- if (button) {
125
- const handler = (e) => handleStepClick(el, stepId, e);
126
- button.addEventListener('pointerdown', handler);
127
- handlers.stepClickHandlers.set(stepId, handler);
128
- }
129
- });
130
- eventHandlers.set(el, handlers);
115
+ cleanupEventListeners(el);
116
+ const handlers = {
117
+ stepClickHandlers: new Map(),
118
+ };
119
+ steps.forEach((step) => {
120
+ const stepId = getStepId(step);
121
+ if (!stepId)
122
+ return;
123
+ const button = shadowRoot.querySelector(`[data-step-id='${stepId}']`);
124
+ if (button) {
125
+ const handler = (e) => handleStepClick(el, stepId, e);
126
+ button.addEventListener('pointerdown', handler);
127
+ handlers.stepClickHandlers.set(stepId, handler);
128
+ }
129
+ });
130
+ eventHandlers.set(el, handlers);
131
131
  }
132
132
  function updateTransform(el, activeIndex) {
133
- const shadowRoot = el.shadowRoot;
134
- if (!shadowRoot)
135
- return;
136
- const panelsWrapper = shadowRoot.querySelector('.panels-wrapper');
137
- if (!panelsWrapper)
138
- return;
139
- const containerWidth = el.offsetWidth;
140
- const offsetPx = activeIndex * containerWidth;
141
- panelsWrapper.style.transform = `translateX(-${offsetPx}px)`;
133
+ const shadowRoot = el.shadowRoot;
134
+ if (!shadowRoot)
135
+ return;
136
+ const panelsWrapper = shadowRoot.querySelector('.panels-wrapper');
137
+ if (!panelsWrapper)
138
+ return;
139
+ const containerWidth = el.offsetWidth;
140
+ const offsetPx = activeIndex * containerWidth;
141
+ panelsWrapper.style.transform = `translateX(-${offsetPx}px)`;
142
142
  }
143
143
  function updateProgressLine(el) {
144
- const shadowRoot = el.shadowRoot;
145
- if (!shadowRoot)
146
- return;
147
- const progressOverlay = shadowRoot.querySelector('.progress-overlay');
148
- if (!progressOverlay)
149
- return;
150
- const steps = getChildSteps(el);
151
- const activeId = getActiveStepId(el, steps);
152
- const completedIds = getCompletedStepIds(el);
153
- const progressPercent = calculateProgressPercent(steps, activeId, completedIds);
154
- progressOverlay.style.width = `${progressPercent}%`;
144
+ const shadowRoot = el.shadowRoot;
145
+ if (!shadowRoot)
146
+ return;
147
+ const progressOverlay = shadowRoot.querySelector('.progress-overlay');
148
+ if (!progressOverlay)
149
+ return;
150
+ const steps = getChildSteps(el);
151
+ const activeId = getActiveStepId(el, steps);
152
+ const completedIds = getCompletedStepIds(el);
153
+ const progressPercent = calculateProgressPercent(steps, activeId, completedIds);
154
+ progressOverlay.style.width = `${progressPercent}%`;
155
155
  }
156
156
  function updateStepIndicators(el, shadowRoot, activeId) {
157
- const steps = getChildSteps(el);
158
- const completedIds = getCompletedStepIds(el);
159
- const activeIndex = activeId ? steps.findIndex(s => getStepId(s) === activeId) : 0;
160
- steps.forEach((step, index) => {
161
- const stepId = getStepId(step);
162
- if (!stepId)
163
- return;
164
- const button = shadowRoot.querySelector(`[data-step-id='${stepId}']`);
165
- const circle = shadowRoot.querySelector(`[data-step-id='${stepId}'] .step-circle`);
166
- const isActive = stepId === activeId;
167
- if (button) {
168
- button.setAttribute('aria-selected', String(isActive));
169
- button.setAttribute('tabindex', isActive ? '0' : '-1');
170
- button.setAttribute('data-active', String(isActive));
171
- }
172
- if (circle) {
173
- const state = getStepStatus(step, stepId, activeId, completedIds);
174
- circle.setAttribute('data-state', state);
175
- }
176
- const slottedIndicator = el.querySelector(`[slot='indicator-${stepId}']`);
177
- if (slottedIndicator) {
178
- slottedIndicator.setAttribute('data-active', String(isActive));
179
- }
180
- });
157
+ const steps = getChildSteps(el);
158
+ const completedIds = getCompletedStepIds(el);
159
+ const activeIndex = activeId ? steps.findIndex(s => getStepId(s) === activeId) : 0;
160
+ steps.forEach((step, index) => {
161
+ const stepId = getStepId(step);
162
+ if (!stepId)
163
+ return;
164
+ const button = shadowRoot.querySelector(`[data-step-id='${stepId}']`);
165
+ const circle = shadowRoot.querySelector(`[data-step-id='${stepId}'] .step-circle`);
166
+ const isActive = stepId === activeId;
167
+ if (button) {
168
+ button.setAttribute('aria-selected', String(isActive));
169
+ button.setAttribute('tabindex', isActive ? '0' : '-1');
170
+ button.setAttribute('data-active', String(isActive));
171
+ }
172
+ if (circle) {
173
+ const state = getStepStatus(step, stepId, activeId, completedIds);
174
+ circle.setAttribute('data-state', state);
175
+ }
176
+ const slottedIndicator = el.querySelector(`[slot='indicator-${stepId}']`);
177
+ if (slottedIndicator) {
178
+ slottedIndicator.setAttribute('data-active', String(isActive));
179
+ }
180
+ });
181
181
  }
182
182
  function updatePanelInteraction(el, activeId) {
183
- const steps = getChildSteps(el);
184
- steps.forEach((step) => {
185
- const stepId = getStepId(step);
186
- if (!stepId)
187
- return;
188
- const isActive = stepId === activeId;
189
- step.setAttribute('data-active', String(isActive));
190
- if (isActive) {
191
- step.style.pointerEvents = 'auto';
192
- step.style.opacity = '1';
193
- }
194
- else {
195
- step.style.pointerEvents = 'none';
196
- step.style.opacity = '0';
197
- }
198
- });
183
+ const steps = getChildSteps(el);
184
+ steps.forEach((step) => {
185
+ const stepId = getStepId(step);
186
+ if (!stepId)
187
+ return;
188
+ const isActive = stepId === activeId;
189
+ step.setAttribute('data-active', String(isActive));
190
+ if (isActive) {
191
+ step.style.pointerEvents = 'auto';
192
+ step.style.opacity = '1';
193
+ }
194
+ else {
195
+ step.style.pointerEvents = 'none';
196
+ step.style.opacity = '0';
197
+ }
198
+ });
199
199
  }
200
200
  function updateActiveStepState(el, stepId) {
201
- const steps = getChildSteps(el);
202
- const shadowRoot = el.shadowRoot;
203
- if (!shadowRoot)
204
- return;
205
- const currentActive = getActiveStepId(el, steps);
206
- const currentIndex = currentActive ? findStepIndex(steps, currentActive) : undefined;
207
- const newIndex = findStepIndex(steps, stepId);
208
- if (currentActive === stepId || newIndex === undefined)
209
- return;
210
- el.style.setProperty('--ty-wizard-active-index', String(newIndex));
211
- updateTransform(el, newIndex);
212
- updateStepIndicators(el, shadowRoot, stepId);
213
- updateProgressLine(el);
214
- updatePanelInteraction(el, stepId);
215
- const newPanel = steps[newIndex];
216
- if (newPanel?.resetScroll) {
217
- newPanel.resetScroll();
218
- }
219
- dispatchStepChangeEvent(el, stepId, newIndex, currentActive, currentIndex ?? null);
201
+ const steps = getChildSteps(el);
202
+ const shadowRoot = el.shadowRoot;
203
+ if (!shadowRoot)
204
+ return;
205
+ const currentActive = getActiveStepId(el, steps);
206
+ const currentIndex = currentActive ? findStepIndex(steps, currentActive) : undefined;
207
+ const newIndex = findStepIndex(steps, stepId);
208
+ if (currentActive === stepId || newIndex === undefined)
209
+ return;
210
+ el.style.setProperty('--ty-wizard-active-index', String(newIndex));
211
+ updateTransform(el, newIndex);
212
+ updateStepIndicators(el, shadowRoot, stepId);
213
+ updateProgressLine(el);
214
+ updatePanelInteraction(el, stepId);
215
+ const newPanel = steps[newIndex];
216
+ if (newPanel?.resetScroll) {
217
+ newPanel.resetScroll();
218
+ }
219
+ dispatchStepChangeEvent(el, stepId, newIndex, currentActive, currentIndex ?? null);
220
220
  }
221
221
  function setupResizeObserver(el) {
222
- const oldObserver = resizeObservers.get(el);
223
- if (oldObserver) {
224
- oldObserver.disconnect();
225
- }
226
- const { width } = getWizardAttributes(el);
227
- if (width.includes('%')) {
228
- const observer = new ResizeObserver((entries) => {
229
- const entry = entries[0];
230
- const measuredWidth = entry.contentRect.width;
231
- const steps = getChildSteps(el);
232
- const activeId = getActiveStepId(el, steps);
233
- const activeIndex = activeId ? findStepIndex(steps, activeId) : 0;
234
- el.style.setProperty('--ty-wizard-width', `${measuredWidth}px`);
235
- if (activeIndex !== undefined) {
236
- updateTransform(el, activeIndex);
237
- }
238
- });
239
- observer.observe(el);
240
- resizeObservers.set(el, observer);
241
- }
222
+ const oldObserver = resizeObservers.get(el);
223
+ if (oldObserver) {
224
+ oldObserver.disconnect();
225
+ }
226
+ const { width } = getWizardAttributes(el);
227
+ if (width.includes('%')) {
228
+ const observer = new ResizeObserver((entries) => {
229
+ const entry = entries[0];
230
+ const measuredWidth = entry.contentRect.width;
231
+ const steps = getChildSteps(el);
232
+ const activeId = getActiveStepId(el, steps);
233
+ const activeIndex = activeId ? findStepIndex(steps, activeId) : 0;
234
+ el.style.setProperty('--ty-wizard-width', `${measuredWidth}px`);
235
+ if (activeIndex !== undefined) {
236
+ updateTransform(el, activeIndex);
237
+ }
238
+ });
239
+ observer.observe(el);
240
+ resizeObservers.set(el, observer);
241
+ }
242
242
  }
243
243
  function cleanupResizeObserver(el) {
244
- const observer = resizeObservers.get(el);
245
- if (observer) {
246
- observer.disconnect();
247
- resizeObservers.delete(el);
248
- }
244
+ const observer = resizeObservers.get(el);
245
+ if (observer) {
246
+ observer.disconnect();
247
+ resizeObservers.delete(el);
248
+ }
249
249
  }
250
250
  function getStepStatus(step, stepId, activeId, completedIds) {
251
- const explicitStatus = step.getAttribute('status');
252
- if (explicitStatus && ['completed', 'active', 'pending', 'error'].includes(explicitStatus)) {
253
- return explicitStatus;
254
- }
255
- const isActive = stepId === activeId;
256
- const isCompleted = completedIds.has(stepId);
257
- return isCompleted ? 'completed' : isActive ? 'active' : 'pending';
251
+ const explicitStatus = step.getAttribute('status');
252
+ if (explicitStatus && ['completed', 'active', 'pending', 'error'].includes(explicitStatus)) {
253
+ return explicitStatus;
254
+ }
255
+ const isActive = stepId === activeId;
256
+ const isCompleted = completedIds.has(stepId);
257
+ return isCompleted ? 'completed' : isActive ? 'active' : 'pending';
258
258
  }
259
259
  function renderStepIndicators(wizardEl, steps, activeId, completedIds) {
260
- const activeIndex = activeId ? steps.findIndex(s => getStepId(s) === activeId) : 0;
261
- const indicators = steps.map((step, index) => {
262
- const stepId = getStepId(step);
263
- if (!stepId)
264
- return '';
265
- const label = step.getAttribute('label') || `Step ${index + 1}`;
266
- const description = step.getAttribute('description') || '';
267
- const disabled = isStepDisabled(step);
268
- const isActive = stepId === activeId;
269
- const hasCustom = hasCustomIndicator(wizardEl, stepId);
270
- const state = getStepStatus(step, stepId, activeId, completedIds);
271
- let circleContent = '';
272
- if (hasCustom) {
273
- circleContent = `<slot name="indicator-${stepId}"></slot>`;
274
- }
275
- else if (state === 'completed') {
276
- circleContent = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>`;
277
- }
278
- else if (state === 'error') {
279
- circleContent = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>`;
280
- }
281
- else {
282
- circleContent = `<span style="font-size: 12px; font-weight: 700;">${index + 1}</span>`;
283
- }
284
- return `<button
285
- class="step-indicator"
286
- role="tab"
287
- data-step-id="${stepId}"
288
- id="step-${stepId}"
289
- aria-selected="${isActive}"
290
- tabindex="${isActive ? '0' : '-1'}"
291
- data-active="${isActive}"
292
- ${disabled ? 'disabled aria-disabled="true"' : ''}
293
- >
294
- <div class="step-circle" data-state="${state}" part="step-circle">
295
- ${circleContent}
296
- </div>
297
- <div class="step-text">
298
- <span class="step-label">${label}</span>
299
- ${description ? `<span class="step-description">${description}</span>` : ''}
300
- </div>
301
- </button>`;
302
- }).join('');
303
- const progressPercent = calculateProgressPercent(steps, activeId, completedIds);
304
- const stepCount = steps.length;
305
- return `
306
- <div class="step-indicators-wrapper" part="indicators-wrapper">
307
- <div class="step-indicators" style="--ty-wizard-step-count: ${stepCount}">
308
- <div class="progress-line" part="progress-line" role="progressbar" aria-label="Wizard progress" aria-valuenow="${Math.round(progressPercent)}" aria-valuemin="0" aria-valuemax="100">
309
- <div class="progress-overlay" style="width: ${progressPercent}%"></div>
310
- </div>
311
- <div class="step-tablist" role="tablist" style="display: contents;">
312
- ${indicators}
313
- </div>
314
- </div>
315
- </div>
316
- `;
260
+ const activeIndex = activeId ? steps.findIndex(s => getStepId(s) === activeId) : 0;
261
+ const indicators = steps.map((step, index) => {
262
+ const stepId = getStepId(step);
263
+ if (!stepId)
264
+ return '';
265
+ const label = step.getAttribute('label') || `Step ${index + 1}`;
266
+ const description = step.getAttribute('description') || '';
267
+ const disabled = isStepDisabled(step);
268
+ const isActive = stepId === activeId;
269
+ const hasCustom = hasCustomIndicator(wizardEl, stepId);
270
+ const state = getStepStatus(step, stepId, activeId, completedIds);
271
+ let circleContent = '';
272
+ if (hasCustom) {
273
+ circleContent = `<slot name="indicator-${stepId}"></slot>`;
274
+ }
275
+ else if (state === 'completed') {
276
+ circleContent = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>`;
277
+ }
278
+ else if (state === 'error') {
279
+ circleContent = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>`;
280
+ }
281
+ else {
282
+ circleContent = `<span style="font-size: 12px; font-weight: 700;">${index + 1}</span>`;
283
+ }
284
+ return `<button
285
+ class="step-indicator"
286
+ role="tab"
287
+ data-step-id="${stepId}"
288
+ id="step-${stepId}"
289
+ aria-selected="${isActive}"
290
+ tabindex="${isActive ? '0' : '-1'}"
291
+ data-active="${isActive}"
292
+ ${disabled ? 'disabled aria-disabled="true"' : ''}
293
+ >
294
+ <div class="step-circle" data-state="${state}" part="step-circle">
295
+ ${circleContent}
296
+ </div>
297
+ <div class="step-text">
298
+ <span class="step-label">${label}</span>
299
+ ${description ? `<span class="step-description">${description}</span>` : ''}
300
+ </div>
301
+ </button>`;
302
+ }).join('');
303
+ const progressPercent = calculateProgressPercent(steps, activeId, completedIds);
304
+ const stepCount = steps.length;
305
+ return `
306
+ <div class="step-indicators-wrapper" part="indicators-wrapper">
307
+ <div class="step-indicators" style="--ty-wizard-step-count: ${stepCount}">
308
+ <div class="progress-line" part="progress-line" role="progressbar" aria-label="Wizard progress" aria-valuenow="${Math.round(progressPercent)}" aria-valuemin="0" aria-valuemax="100">
309
+ <div class="progress-overlay" style="width: ${progressPercent}%"></div>
310
+ </div>
311
+ <div class="step-tablist" role="tablist" style="display: contents;">
312
+ ${indicators}
313
+ </div>
314
+ </div>
315
+ </div>
316
+ `;
317
317
  }
318
318
  function render(el) {
319
- const shadowRoot = el.shadowRoot;
320
- if (!shadowRoot)
321
- return;
322
- const { width, height } = getWizardAttributes(el);
323
- const steps = getChildSteps(el);
324
- const activeId = getActiveStepId(el, steps);
325
- const activeIndex = activeId ? (findStepIndex(steps, activeId) ?? 0) : 0;
326
- const completedIds = getCompletedStepIds(el);
327
- steps.forEach((step) => {
328
- const stepId = getStepId(step);
329
- if (!stepId)
330
- return;
331
- step.setAttribute('role', 'tabpanel');
332
- step.setAttribute('aria-labelledby', `step-${stepId}`);
333
- step.setAttribute('tabindex', '0');
334
- });
335
- const existingContainer = shadowRoot.querySelector('.wizard-container');
336
- const existingIndicators = shadowRoot.querySelector('.step-indicators-wrapper');
337
- const existingViewport = shadowRoot.querySelector('.panels-viewport');
338
- ensureStyles(shadowRoot, { css: wizardStyles, id: 'ty-wizard' });
339
- el.style.setProperty('--ty-wizard-width', width.includes('%') ? '100%' : width);
340
- el.style.setProperty('--ty-wizard-height', height);
341
- el.style.setProperty('--ty-wizard-active-index', String(activeIndex));
342
- el.style.setProperty('--ty-wizard-step-count', String(steps.length));
343
- if (existingContainer && existingIndicators && existingViewport) {
344
- existingIndicators.remove();
345
- const newIndicatorsHtml = renderStepIndicators(el, steps, activeId, completedIds);
346
- const tempDiv = document.createElement('div');
347
- tempDiv.innerHTML = newIndicatorsHtml;
348
- existingContainer.insertBefore(tempDiv.firstElementChild, existingViewport);
349
- setupEventListeners(el, shadowRoot, steps);
350
- updateStepIndicators(el, shadowRoot, activeId || '');
351
- requestAnimationFrame(() => {
352
- const indicators = shadowRoot.querySelector('.step-indicators-wrapper');
353
- if (indicators) {
354
- const indicatorsHeight = indicators.offsetHeight;
355
- el.style.setProperty('--ty-wizard-indicators-height', `${indicatorsHeight}px`);
356
- }
357
- updateTransform(el, activeIndex);
358
- updateProgressLine(el);
359
- });
360
- if (activeId) {
361
- updatePanelInteraction(el, activeId);
362
- }
363
- }
364
- else {
365
- shadowRoot.innerHTML = `
366
- <div class="wizard-container">
367
- ${renderStepIndicators(el, steps, activeId, completedIds)}
368
- <div class="panels-viewport" part="panels-container">
369
- <div class="panels-wrapper">
370
- <slot></slot>
371
- </div>
372
- </div>
373
- </div>
374
- `;
375
- requestAnimationFrame(() => {
376
- const indicators = shadowRoot.querySelector('.step-indicators-wrapper');
377
- if (indicators) {
378
- const indicatorsHeight = indicators.offsetHeight;
379
- el.style.setProperty('--ty-wizard-indicators-height', `${indicatorsHeight}px`);
380
- }
381
- updateTransform(el, activeIndex);
382
- updateProgressLine(el);
383
- });
384
- setupEventListeners(el, shadowRoot, steps);
385
- updateStepIndicators(el, shadowRoot, activeId || '');
386
- setupResizeObserver(el);
387
- if (activeId) {
388
- updatePanelInteraction(el, activeId);
389
- }
390
- }
319
+ const shadowRoot = el.shadowRoot;
320
+ if (!shadowRoot)
321
+ return;
322
+ const { width, height } = getWizardAttributes(el);
323
+ const steps = getChildSteps(el);
324
+ const activeId = getActiveStepId(el, steps);
325
+ const activeIndex = activeId ? (findStepIndex(steps, activeId) ?? 0) : 0;
326
+ const completedIds = getCompletedStepIds(el);
327
+ steps.forEach((step) => {
328
+ const stepId = getStepId(step);
329
+ if (!stepId)
330
+ return;
331
+ step.setAttribute('role', 'tabpanel');
332
+ step.setAttribute('aria-labelledby', `step-${stepId}`);
333
+ step.setAttribute('tabindex', '0');
334
+ });
335
+ const existingContainer = shadowRoot.querySelector('.wizard-container');
336
+ const existingIndicators = shadowRoot.querySelector('.step-indicators-wrapper');
337
+ const existingViewport = shadowRoot.querySelector('.panels-viewport');
338
+ ensureStyles(shadowRoot, { css: wizardStyles, id: 'ty-wizard' });
339
+ el.style.setProperty('--ty-wizard-width', width.includes('%') ? '100%' : width);
340
+ el.style.setProperty('--ty-wizard-height', height);
341
+ el.style.setProperty('--ty-wizard-active-index', String(activeIndex));
342
+ el.style.setProperty('--ty-wizard-step-count', String(steps.length));
343
+ if (existingContainer && existingIndicators && existingViewport) {
344
+ existingIndicators.remove();
345
+ const newIndicatorsHtml = renderStepIndicators(el, steps, activeId, completedIds);
346
+ const tempDiv = document.createElement('div');
347
+ tempDiv.innerHTML = newIndicatorsHtml;
348
+ existingContainer.insertBefore(tempDiv.firstElementChild, existingViewport);
349
+ setupEventListeners(el, shadowRoot, steps);
350
+ updateStepIndicators(el, shadowRoot, activeId || '');
351
+ requestAnimationFrame(() => {
352
+ const indicators = shadowRoot.querySelector('.step-indicators-wrapper');
353
+ if (indicators) {
354
+ const indicatorsHeight = indicators.offsetHeight;
355
+ el.style.setProperty('--ty-wizard-indicators-height', `${indicatorsHeight}px`);
356
+ }
357
+ updateTransform(el, activeIndex);
358
+ updateProgressLine(el);
359
+ });
360
+ if (activeId) {
361
+ updatePanelInteraction(el, activeId);
362
+ }
363
+ }
364
+ else {
365
+ shadowRoot.innerHTML = `
366
+ <div class="wizard-container">
367
+ ${renderStepIndicators(el, steps, activeId, completedIds)}
368
+ <div class="panels-viewport" part="panels-container">
369
+ <div class="panels-wrapper">
370
+ <slot></slot>
371
+ </div>
372
+ </div>
373
+ </div>
374
+ `;
375
+ requestAnimationFrame(() => {
376
+ const indicators = shadowRoot.querySelector('.step-indicators-wrapper');
377
+ if (indicators) {
378
+ const indicatorsHeight = indicators.offsetHeight;
379
+ el.style.setProperty('--ty-wizard-indicators-height', `${indicatorsHeight}px`);
380
+ }
381
+ updateTransform(el, activeIndex);
382
+ updateProgressLine(el);
383
+ });
384
+ setupEventListeners(el, shadowRoot, steps);
385
+ updateStepIndicators(el, shadowRoot, activeId || '');
386
+ setupResizeObserver(el);
387
+ if (activeId) {
388
+ updatePanelInteraction(el, activeId);
389
+ }
390
+ }
391
391
  }
392
392
  function cleanup(el) {
393
- cleanupEventListeners(el);
394
- cleanupResizeObserver(el);
393
+ cleanupEventListeners(el);
394
+ cleanupResizeObserver(el);
395
395
  }
396
396
  export class TyWizard extends HTMLElement {
397
- static get observedAttributes() {
398
- return ['width', 'height', 'active', 'completed', 'orientation'];
399
- }
400
- constructor() {
401
- super();
402
- this._childObserver = null;
403
- this._childRenderQueued = false;
404
- this.attachShadow({ mode: 'open' });
405
- }
406
- connectedCallback() {
407
- render(this);
408
- this._childObserver = new MutationObserver(() => {
409
- if (this._childRenderQueued)
410
- return;
411
- this._childRenderQueued = true;
412
- queueMicrotask(() => {
413
- this._childRenderQueued = false;
414
- if (this.isConnected)
415
- render(this);
416
- });
417
- });
418
- this._childObserver.observe(this, { childList: true });
419
- }
420
- disconnectedCallback() {
421
- this._childObserver?.disconnect();
422
- this._childObserver = null;
423
- cleanup(this);
424
- }
425
- attributeChangedCallback(name, oldValue, newValue) {
426
- if (name === 'active') {
427
- if (newValue) {
428
- updateActiveStepState(this, newValue);
429
- }
430
- render(this);
431
- }
432
- else if (name === 'completed') {
433
- render(this);
434
- }
435
- else {
436
- render(this);
437
- }
438
- }
397
+ static get observedAttributes() {
398
+ return ['width', 'height', 'active', 'completed', 'orientation'];
399
+ }
400
+ constructor() {
401
+ super();
402
+ this._childObserver = null;
403
+ this._childRenderQueued = false;
404
+ this.attachShadow({ mode: 'open' });
405
+ }
406
+ connectedCallback() {
407
+ render(this);
408
+ this._childObserver = new MutationObserver(() => {
409
+ if (this._childRenderQueued)
410
+ return;
411
+ this._childRenderQueued = true;
412
+ queueMicrotask(() => {
413
+ this._childRenderQueued = false;
414
+ if (this.isConnected)
415
+ render(this);
416
+ });
417
+ });
418
+ this._childObserver.observe(this, { childList: true });
419
+ }
420
+ disconnectedCallback() {
421
+ this._childObserver?.disconnect();
422
+ this._childObserver = null;
423
+ cleanup(this);
424
+ }
425
+ attributeChangedCallback(name, oldValue, newValue) {
426
+ if (name === 'active') {
427
+ if (newValue) {
428
+ updateActiveStepState(this, newValue);
429
+ }
430
+ render(this);
431
+ }
432
+ else if (name === 'completed') {
433
+ render(this);
434
+ }
435
+ else {
436
+ render(this);
437
+ }
438
+ }
439
439
  }
440
440
  if (!customElements.get('ty-wizard')) {
441
- customElements.define('ty-wizard', TyWizard);
441
+ customElements.define('ty-wizard', TyWizard);
442
442
  }