tyrell-components 1.0.0-TC51 → 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 (108) 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.d.ts +1 -0
  39. package/lib/components/tabs.js +507 -479
  40. package/lib/components/tag.d.ts +1 -1
  41. package/lib/components/tag.js +236 -235
  42. package/lib/components/textarea.d.ts +1 -1
  43. package/lib/components/textarea.js +457 -456
  44. package/lib/components/tooltip.js +283 -283
  45. package/lib/components/wizard.js +384 -384
  46. package/lib/icons/heroicons/micro.js +392 -392
  47. package/lib/icons/heroicons/mini.js +382 -382
  48. package/lib/icons/heroicons/outline.js +337 -337
  49. package/lib/icons/heroicons/solid.js +407 -407
  50. package/lib/icons/lucide.js +22843 -22843
  51. package/lib/icons/material/filled.js +9653 -9653
  52. package/lib/icons/material/outlined.js +10271 -10271
  53. package/lib/icons/material/round.js +10495 -10495
  54. package/lib/icons/material/sharp.js +9905 -9905
  55. package/lib/icons/material/two-tone.js +12792 -12792
  56. package/lib/index.js +21 -21
  57. package/lib/styles/button.js +176 -288
  58. package/lib/styles/calendar-month.js +123 -183
  59. package/lib/styles/calendar-navigation.js +60 -79
  60. package/lib/styles/calendar.js +8 -9
  61. package/lib/styles/checkbox.js +45 -72
  62. package/lib/styles/copy.js +67 -91
  63. package/lib/styles/custom-scrollbar.js +80 -100
  64. package/lib/styles/date-picker.js +261 -331
  65. package/lib/styles/field-size.d.ts +6 -0
  66. package/lib/styles/field-size.js +91 -0
  67. package/lib/styles/file-upload.js +139 -169
  68. package/lib/styles/icon.js +92 -156
  69. package/lib/styles/input.js +125 -241
  70. package/lib/styles/modal.js +67 -102
  71. package/lib/styles/option.d.ts +1 -1
  72. package/lib/styles/option.js +47 -67
  73. package/lib/styles/popup.js +34 -65
  74. package/lib/styles/radio.js +69 -96
  75. package/lib/styles/resize-observer.js +2 -5
  76. package/lib/styles/scroll-container.js +100 -130
  77. package/lib/styles/select-base.js +525 -778
  78. package/lib/styles/select.js +140 -228
  79. package/lib/styles/step.js +22 -29
  80. package/lib/styles/switch.js +34 -55
  81. package/lib/styles/tab.d.ts +1 -1
  82. package/lib/styles/tab.js +22 -29
  83. package/lib/styles/tabs.d.ts +1 -1
  84. package/lib/styles/tabs.js +175 -237
  85. package/lib/styles/tag.js +135 -188
  86. package/lib/styles/textarea.d.ts +1 -1
  87. package/lib/styles/textarea.js +205 -271
  88. package/lib/styles/tooltip.js +3 -3
  89. package/lib/styles/wizard.js +170 -226
  90. package/lib/types/common.d.ts +2 -0
  91. package/lib/types/common.js +6 -5
  92. package/lib/utils/calendar-utils.js +100 -100
  93. package/lib/utils/custom-scrollbar.js +272 -272
  94. package/lib/utils/flavor-sheet.js +14 -14
  95. package/lib/utils/icon-registry.js +127 -127
  96. package/lib/utils/loader-registry.js +3 -3
  97. package/lib/utils/locale.js +34 -34
  98. package/lib/utils/mobile.js +1 -1
  99. package/lib/utils/number-format.js +54 -54
  100. package/lib/utils/positioning.js +212 -212
  101. package/lib/utils/property-capture.js +36 -36
  102. package/lib/utils/property-manager.js +125 -125
  103. package/lib/utils/resize-observer.js +23 -23
  104. package/lib/utils/scroll-lock.js +57 -57
  105. package/lib/utils/styles.js +17 -17
  106. package/lib/version.d.ts +1 -1
  107. package/lib/version.js +1 -1
  108. 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
  }