tyrell-components 1.0.0-RC13 → 1.0.0-RC15
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.
- package/README.md +10 -2
- package/css/tyrell-theme.css +192 -180
- package/css/tyrell.css +23 -0
- package/dist/tyrell-colors-static.css +1 -316
- package/dist/tyrell-theme.css +1 -1454
- package/dist/tyrell.css +1 -1371
- package/dist/tyrell.js +1 -1
- package/lib/base/ty-component.d.ts +20 -10
- package/lib/base/ty-component.js +196 -319
- package/lib/components/button.d.ts +3 -17
- package/lib/components/button.js +261 -295
- package/lib/components/calendar-month.d.ts +4 -50
- package/lib/components/calendar-month.js +443 -582
- package/lib/components/calendar-navigation.d.ts +3 -48
- package/lib/components/calendar-navigation.js +239 -362
- package/lib/components/calendar.d.ts +8 -83
- package/lib/components/calendar.js +616 -829
- package/lib/components/checkbox.d.ts +5 -72
- package/lib/components/checkbox.js +273 -416
- package/lib/components/copy.d.ts +4 -57
- package/lib/components/copy.js +280 -397
- package/lib/components/date-picker.d.ts +21 -163
- package/lib/components/date-picker.js +1143 -1674
- package/lib/components/file-upload.d.ts +9 -15
- package/lib/components/file-upload.js +404 -426
- package/lib/components/icon.d.ts +3 -24
- package/lib/components/icon.js +141 -230
- package/lib/components/input.d.ts +8 -108
- package/lib/components/input.js +593 -784
- package/lib/components/modal.d.ts +17 -26
- package/lib/components/modal.js +340 -484
- package/lib/components/option.d.ts +2 -9
- package/lib/components/option.js +168 -216
- package/lib/components/popup.d.ts +2 -17
- package/lib/components/popup.js +249 -380
- package/lib/components/radio.d.ts +5 -25
- package/lib/components/radio.js +407 -461
- package/lib/components/resize-observer.d.ts +3 -30
- package/lib/components/resize-observer.js +69 -103
- package/lib/components/scroll-container.d.ts +2 -12
- package/lib/components/scroll-container.js +293 -338
- package/lib/components/select.d.ts +87 -159
- package/lib/components/select.js +1609 -2090
- package/lib/components/selected-tags.d.ts +5 -48
- package/lib/components/selected-tags.js +188 -276
- package/lib/components/step.d.ts +1 -6
- package/lib/components/step.js +62 -68
- package/lib/components/switch.d.ts +1 -12
- package/lib/components/switch.js +214 -247
- package/lib/components/tab.d.ts +1 -6
- package/lib/components/tab.js +62 -69
- package/lib/components/tabs.d.ts +6 -63
- package/lib/components/tabs.js +545 -777
- package/lib/components/tag.d.ts +3 -37
- package/lib/components/tag.js +236 -335
- package/lib/components/textarea.d.ts +7 -87
- package/lib/components/textarea.js +457 -627
- package/lib/components/tooltip.d.ts +3 -11
- package/lib/components/tooltip.js +307 -443
- package/lib/components/wizard.d.ts +6 -54
- package/lib/components/wizard.js +405 -618
- package/lib/icons/fontawesome/brands.d.ts +0 -1
- package/lib/icons/fontawesome/brands.js +0 -8
- package/lib/icons/fontawesome/regular.d.ts +0 -1
- package/lib/icons/fontawesome/regular.js +0 -8
- package/lib/icons/fontawesome/solid.d.ts +0 -1
- package/lib/icons/fontawesome/solid.js +0 -8
- package/lib/icons/heroicons/micro.d.ts +0 -1
- package/lib/icons/heroicons/micro.js +392 -400
- package/lib/icons/heroicons/mini.d.ts +0 -1
- package/lib/icons/heroicons/mini.js +382 -390
- package/lib/icons/heroicons/outline.d.ts +0 -1
- package/lib/icons/heroicons/outline.js +337 -345
- package/lib/icons/heroicons/solid.d.ts +0 -1
- package/lib/icons/heroicons/solid.js +407 -415
- package/lib/icons/lucide.d.ts +0 -1
- package/lib/icons/lucide.js +24479 -26351
- package/lib/icons/material/filled.d.ts +0 -1
- package/lib/icons/material/filled.js +9653 -9663
- package/lib/icons/material/outlined.d.ts +0 -1
- package/lib/icons/material/outlined.js +10271 -10281
- package/lib/icons/material/round.d.ts +0 -1
- package/lib/icons/material/round.js +10495 -10505
- package/lib/icons/material/sharp.d.ts +0 -1
- package/lib/icons/material/sharp.js +9905 -9915
- package/lib/icons/material/two-tone.d.ts +0 -1
- package/lib/icons/material/two-tone.js +12792 -12802
- package/lib/index.d.ts +0 -1
- package/lib/index.js +21 -41
- package/lib/styles/button.d.ts +2 -20
- package/lib/styles/button.js +202 -404
- package/lib/styles/calendar-month.d.ts +1 -5
- package/lib/styles/calendar-month.js +127 -244
- package/lib/styles/calendar-navigation.d.ts +2 -6
- package/lib/styles/calendar-navigation.js +64 -104
- package/lib/styles/calendar.d.ts +1 -2
- package/lib/styles/calendar.js +9 -22
- package/lib/styles/checkbox.d.ts +0 -1
- package/lib/styles/checkbox.js +45 -94
- package/lib/styles/copy.d.ts +0 -1
- package/lib/styles/copy.js +67 -106
- package/lib/styles/custom-scrollbar.d.ts +1 -2
- package/lib/styles/custom-scrollbar.js +80 -115
- package/lib/styles/date-picker.d.ts +1 -5
- package/lib/styles/date-picker.js +261 -335
- package/lib/styles/field-size.d.ts +6 -0
- package/lib/styles/field-size.js +91 -0
- package/lib/styles/file-upload.d.ts +1 -2
- package/lib/styles/file-upload.js +143 -188
- package/lib/styles/icon.d.ts +2 -6
- package/lib/styles/icon.js +92 -170
- package/lib/styles/input.d.ts +1 -6
- package/lib/styles/input.js +125 -290
- package/lib/styles/modal.d.ts +1 -2
- package/lib/styles/modal.js +71 -108
- package/lib/styles/option.d.ts +2 -6
- package/lib/styles/option.js +49 -64
- package/lib/styles/popup.d.ts +1 -2
- package/lib/styles/popup.js +42 -77
- package/lib/styles/radio.d.ts +0 -1
- package/lib/styles/radio.js +69 -110
- package/lib/styles/resize-observer.d.ts +1 -2
- package/lib/styles/resize-observer.js +2 -12
- package/lib/styles/scroll-container.d.ts +1 -2
- package/lib/styles/scroll-container.js +100 -149
- package/lib/styles/select-base.d.ts +0 -1
- package/lib/styles/select-base.js +597 -785
- package/lib/styles/select.d.ts +1 -2
- package/lib/styles/select.js +140 -236
- package/lib/styles/step.d.ts +1 -2
- package/lib/styles/step.js +22 -33
- package/lib/styles/switch.d.ts +0 -1
- package/lib/styles/switch.js +34 -73
- package/lib/styles/tab.d.ts +1 -2
- package/lib/styles/tab.js +22 -34
- package/lib/styles/tabs.d.ts +3 -11
- package/lib/styles/tabs.js +190 -222
- package/lib/styles/tag.d.ts +1 -5
- package/lib/styles/tag.js +136 -218
- package/lib/styles/textarea.d.ts +1 -2
- package/lib/styles/textarea.js +210 -319
- package/lib/styles/tooltip.d.ts +0 -1
- package/lib/styles/tooltip.js +3 -13
- package/lib/styles/wizard.d.ts +5 -21
- package/lib/styles/wizard.js +170 -306
- package/lib/types/common.d.ts +2 -2
- package/lib/types/common.js +6 -17
- package/lib/utils/calendar-utils.d.ts +4 -21
- package/lib/utils/calendar-utils.js +100 -273
- package/lib/utils/custom-scrollbar.d.ts +6 -20
- package/lib/utils/custom-scrollbar.js +273 -317
- package/lib/utils/flavor-sheet.d.ts +0 -1
- package/lib/utils/flavor-sheet.js +14 -37
- package/lib/utils/icon-registry.d.ts +0 -2
- package/lib/utils/icon-registry.js +137 -243
- package/lib/utils/icons.d.ts +0 -1
- package/lib/utils/icons.js +0 -9
- package/lib/utils/loader-registry.d.ts +0 -1
- package/lib/utils/loader-registry.js +3 -35
- package/lib/utils/locale.d.ts +2 -23
- package/lib/utils/locale.js +34 -120
- package/lib/utils/mobile.d.ts +0 -1
- package/lib/utils/mobile.js +1 -18
- package/lib/utils/number-format.d.ts +6 -3
- package/lib/utils/number-format.js +54 -110
- package/lib/utils/positioning.d.ts +50 -7
- package/lib/utils/positioning.js +224 -234
- package/lib/utils/property-capture.d.ts +5 -27
- package/lib/utils/property-capture.js +36 -144
- package/lib/utils/property-manager.d.ts +0 -1
- package/lib/utils/property-manager.js +126 -196
- package/lib/utils/resize-observer.d.ts +0 -1
- package/lib/utils/resize-observer.js +23 -59
- package/lib/utils/scroll-lock.d.ts +4 -11
- package/lib/utils/scroll-lock.js +65 -172
- package/lib/utils/styles.d.ts +0 -1
- package/lib/utils/styles.js +17 -41
- package/lib/version.d.ts +1 -2
- package/lib/version.js +1 -11
- package/package.json +4 -4
- package/lib/base/ty-component.d.ts.map +0 -1
- package/lib/base/ty-component.js.map +0 -1
- package/lib/components/button.d.ts.map +0 -1
- package/lib/components/button.js.map +0 -1
- package/lib/components/calendar-month.d.ts.map +0 -1
- package/lib/components/calendar-month.js.map +0 -1
- package/lib/components/calendar-navigation.d.ts.map +0 -1
- package/lib/components/calendar-navigation.js.map +0 -1
- package/lib/components/calendar.d.ts.map +0 -1
- package/lib/components/calendar.js.map +0 -1
- package/lib/components/checkbox.d.ts.map +0 -1
- package/lib/components/checkbox.js.map +0 -1
- package/lib/components/copy.d.ts.map +0 -1
- package/lib/components/copy.js.map +0 -1
- package/lib/components/date-picker.d.ts.map +0 -1
- package/lib/components/date-picker.js.map +0 -1
- package/lib/components/file-upload.d.ts.map +0 -1
- package/lib/components/file-upload.js.map +0 -1
- package/lib/components/icon.d.ts.map +0 -1
- package/lib/components/icon.js.map +0 -1
- package/lib/components/input.d.ts.map +0 -1
- package/lib/components/input.js.map +0 -1
- package/lib/components/modal.d.ts.map +0 -1
- package/lib/components/modal.js.map +0 -1
- package/lib/components/option.d.ts.map +0 -1
- package/lib/components/option.js.map +0 -1
- package/lib/components/popup.d.ts.map +0 -1
- package/lib/components/popup.js.map +0 -1
- package/lib/components/radio.d.ts.map +0 -1
- package/lib/components/radio.js.map +0 -1
- package/lib/components/resize-observer.d.ts.map +0 -1
- package/lib/components/resize-observer.js.map +0 -1
- package/lib/components/scroll-container.d.ts.map +0 -1
- package/lib/components/scroll-container.js.map +0 -1
- package/lib/components/select.d.ts.map +0 -1
- package/lib/components/select.js.map +0 -1
- package/lib/components/selected-tags.d.ts.map +0 -1
- package/lib/components/selected-tags.js.map +0 -1
- package/lib/components/step.d.ts.map +0 -1
- package/lib/components/step.js.map +0 -1
- package/lib/components/switch.d.ts.map +0 -1
- package/lib/components/switch.js.map +0 -1
- package/lib/components/tab.d.ts.map +0 -1
- package/lib/components/tab.js.map +0 -1
- package/lib/components/tabs.d.ts.map +0 -1
- package/lib/components/tabs.js.map +0 -1
- package/lib/components/tag.d.ts.map +0 -1
- package/lib/components/tag.js.map +0 -1
- package/lib/components/textarea.d.ts.map +0 -1
- package/lib/components/textarea.js.map +0 -1
- package/lib/components/tooltip.d.ts.map +0 -1
- package/lib/components/tooltip.js.map +0 -1
- package/lib/components/wizard.d.ts.map +0 -1
- package/lib/components/wizard.js.map +0 -1
- package/lib/icons/fontawesome/brands.d.ts.map +0 -1
- package/lib/icons/fontawesome/brands.js.map +0 -1
- package/lib/icons/fontawesome/regular.d.ts.map +0 -1
- package/lib/icons/fontawesome/regular.js.map +0 -1
- package/lib/icons/fontawesome/solid.d.ts.map +0 -1
- package/lib/icons/fontawesome/solid.js.map +0 -1
- package/lib/icons/heroicons/micro.d.ts.map +0 -1
- package/lib/icons/heroicons/micro.js.map +0 -1
- package/lib/icons/heroicons/mini.d.ts.map +0 -1
- package/lib/icons/heroicons/mini.js.map +0 -1
- package/lib/icons/heroicons/outline.d.ts.map +0 -1
- package/lib/icons/heroicons/outline.js.map +0 -1
- package/lib/icons/heroicons/solid.d.ts.map +0 -1
- package/lib/icons/heroicons/solid.js.map +0 -1
- package/lib/icons/lucide.d.ts.map +0 -1
- package/lib/icons/lucide.js.map +0 -1
- package/lib/icons/material/filled.d.ts.map +0 -1
- package/lib/icons/material/filled.js.map +0 -1
- package/lib/icons/material/outlined.d.ts.map +0 -1
- package/lib/icons/material/outlined.js.map +0 -1
- package/lib/icons/material/round.d.ts.map +0 -1
- package/lib/icons/material/round.js.map +0 -1
- package/lib/icons/material/sharp.d.ts.map +0 -1
- package/lib/icons/material/sharp.js.map +0 -1
- package/lib/icons/material/two-tone.d.ts.map +0 -1
- package/lib/icons/material/two-tone.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/styles/button.d.ts.map +0 -1
- package/lib/styles/button.js.map +0 -1
- package/lib/styles/calendar-month.d.ts.map +0 -1
- package/lib/styles/calendar-month.js.map +0 -1
- package/lib/styles/calendar-navigation.d.ts.map +0 -1
- package/lib/styles/calendar-navigation.js.map +0 -1
- package/lib/styles/calendar.d.ts.map +0 -1
- package/lib/styles/calendar.js.map +0 -1
- package/lib/styles/checkbox.d.ts.map +0 -1
- package/lib/styles/checkbox.js.map +0 -1
- package/lib/styles/copy.d.ts.map +0 -1
- package/lib/styles/copy.js.map +0 -1
- package/lib/styles/custom-scrollbar.d.ts.map +0 -1
- package/lib/styles/custom-scrollbar.js.map +0 -1
- package/lib/styles/date-picker.d.ts.map +0 -1
- package/lib/styles/date-picker.js.map +0 -1
- package/lib/styles/file-upload.d.ts.map +0 -1
- package/lib/styles/file-upload.js.map +0 -1
- package/lib/styles/icon.d.ts.map +0 -1
- package/lib/styles/icon.js.map +0 -1
- package/lib/styles/input.d.ts.map +0 -1
- package/lib/styles/input.js.map +0 -1
- package/lib/styles/modal.d.ts.map +0 -1
- package/lib/styles/modal.js.map +0 -1
- package/lib/styles/multiselect.d.ts +0 -8
- package/lib/styles/multiselect.d.ts.map +0 -1
- package/lib/styles/multiselect.js +0 -849
- package/lib/styles/multiselect.js.map +0 -1
- package/lib/styles/option.d.ts.map +0 -1
- package/lib/styles/option.js.map +0 -1
- package/lib/styles/popup.d.ts.map +0 -1
- package/lib/styles/popup.js.map +0 -1
- package/lib/styles/radio.d.ts.map +0 -1
- package/lib/styles/radio.js.map +0 -1
- package/lib/styles/resize-observer.d.ts.map +0 -1
- package/lib/styles/resize-observer.js.map +0 -1
- package/lib/styles/scroll-container.d.ts.map +0 -1
- package/lib/styles/scroll-container.js.map +0 -1
- package/lib/styles/select-base.d.ts.map +0 -1
- package/lib/styles/select-base.js.map +0 -1
- package/lib/styles/select.d.ts.map +0 -1
- package/lib/styles/select.js.map +0 -1
- package/lib/styles/step.d.ts.map +0 -1
- package/lib/styles/step.js.map +0 -1
- package/lib/styles/switch.d.ts.map +0 -1
- package/lib/styles/switch.js.map +0 -1
- package/lib/styles/tab.d.ts.map +0 -1
- package/lib/styles/tab.js.map +0 -1
- package/lib/styles/tabs.d.ts.map +0 -1
- package/lib/styles/tabs.js.map +0 -1
- package/lib/styles/tag.d.ts.map +0 -1
- package/lib/styles/tag.js.map +0 -1
- package/lib/styles/textarea.d.ts.map +0 -1
- package/lib/styles/textarea.js.map +0 -1
- package/lib/styles/tooltip.d.ts.map +0 -1
- package/lib/styles/tooltip.js.map +0 -1
- package/lib/styles/wizard.d.ts.map +0 -1
- package/lib/styles/wizard.js.map +0 -1
- package/lib/types/common.d.ts.map +0 -1
- package/lib/types/common.js.map +0 -1
- package/lib/utils/calendar-utils.d.ts.map +0 -1
- package/lib/utils/calendar-utils.js.map +0 -1
- package/lib/utils/custom-scrollbar.d.ts.map +0 -1
- package/lib/utils/custom-scrollbar.js.map +0 -1
- package/lib/utils/flavor-sheet.d.ts.map +0 -1
- package/lib/utils/flavor-sheet.js.map +0 -1
- package/lib/utils/icon-registry.d.ts.map +0 -1
- package/lib/utils/icon-registry.js.map +0 -1
- package/lib/utils/icons.d.ts.map +0 -1
- package/lib/utils/icons.js.map +0 -1
- package/lib/utils/loader-registry.d.ts.map +0 -1
- package/lib/utils/loader-registry.js.map +0 -1
- package/lib/utils/locale.d.ts.map +0 -1
- package/lib/utils/locale.js.map +0 -1
- package/lib/utils/mobile.d.ts.map +0 -1
- package/lib/utils/mobile.js.map +0 -1
- package/lib/utils/number-format.d.ts.map +0 -1
- package/lib/utils/number-format.js.map +0 -1
- package/lib/utils/parse-boolean.d.ts +0 -39
- package/lib/utils/parse-boolean.d.ts.map +0 -1
- package/lib/utils/parse-boolean.js +0 -58
- package/lib/utils/parse-boolean.js.map +0 -1
- package/lib/utils/positioning.d.ts.map +0 -1
- package/lib/utils/positioning.js.map +0 -1
- package/lib/utils/property-capture.d.ts.map +0 -1
- package/lib/utils/property-capture.js.map +0 -1
- package/lib/utils/property-manager.d.ts.map +0 -1
- package/lib/utils/property-manager.js.map +0 -1
- package/lib/utils/resize-observer.d.ts.map +0 -1
- package/lib/utils/resize-observer.js.map +0 -1
- package/lib/utils/scroll-lock.d.ts.map +0 -1
- package/lib/utils/scroll-lock.js.map +0 -1
- package/lib/utils/styles.d.ts.map +0 -1
- package/lib/utils/styles.js.map +0 -1
- package/lib/version.d.ts.map +0 -1
- package/lib/version.js.map +0 -1
package/lib/components/wizard.js
CHANGED
|
@@ -1,655 +1,442 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Wizard Component
|
|
3
|
-
*
|
|
4
|
-
* A carousel-based wizard/stepper component with smooth animations, progress tracking, and completion state.
|
|
5
|
-
* Features horizontal sliding transitions between steps, animated progress line, and step completion tracking.
|
|
6
|
-
* Behaves like tabs - a "dumb" component that only renders and fires events. All navigation and validation
|
|
7
|
-
* is controlled by the user.
|
|
8
|
-
*
|
|
9
|
-
* Features:
|
|
10
|
-
* - Carousel animation with smooth sliding transitions between steps
|
|
11
|
-
* - Fixed dimensions prevent layout shift between steps
|
|
12
|
-
* - Animated progress line showing completion status
|
|
13
|
-
* - Step indicators with completed/active/pending states
|
|
14
|
-
* - Rich indicator support via slots (icons, custom content)
|
|
15
|
-
* - Independent panel scrolling with scroll position reset
|
|
16
|
-
* - ResizeObserver for responsive percentage widths
|
|
17
|
-
* - Smart rendering - only updates DOM when necessary
|
|
18
|
-
* - Accessibility with ARIA roles and attributes
|
|
19
|
-
* - Fires events on step clicks - user controls navigation
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* <!-- Basic wizard with text labels -->
|
|
23
|
-
* <ty-wizard width="900px" height="600px" active="welcome">
|
|
24
|
-
* <ty-step id="welcome" label="Welcome">
|
|
25
|
-
* <div class="p-6">
|
|
26
|
-
* <h1>Welcome!</h1>
|
|
27
|
-
* <button onclick="goToStep('account')">Next</button>
|
|
28
|
-
* </div>
|
|
29
|
-
* </ty-step>
|
|
30
|
-
* <ty-step id="account" label="Account Setup">
|
|
31
|
-
* <div class="p-6">
|
|
32
|
-
* <h2>Account Setup</h2>
|
|
33
|
-
* <button onclick="goToStep('welcome')">Previous</button>
|
|
34
|
-
* <button onclick="goToStep('complete')">Next</button>
|
|
35
|
-
* </div>
|
|
36
|
-
* </ty-step>
|
|
37
|
-
* </ty-wizard>
|
|
38
|
-
*
|
|
39
|
-
* @example
|
|
40
|
-
* <!-- Wizard with custom indicators -->
|
|
41
|
-
* <ty-wizard width="100%" height="700px" active="welcome" completed="welcome,account">
|
|
42
|
-
* <!-- Custom indicator icons -->
|
|
43
|
-
* <div slot="indicator-welcome">
|
|
44
|
-
* <ty-icon name="hand" size="sm"></ty-icon>
|
|
45
|
-
* </div>
|
|
46
|
-
* <div slot="indicator-account">
|
|
47
|
-
* <span class="text-lg font-bold">1</span>
|
|
48
|
-
* </div>
|
|
49
|
-
*
|
|
50
|
-
* <ty-step id="welcome" label="Welcome">...</ty-step>
|
|
51
|
-
* <ty-step id="account" label="Account">...</ty-step>
|
|
52
|
-
* <ty-step id="profile" label="Profile">...</ty-step>
|
|
53
|
-
* </ty-wizard>
|
|
54
|
-
*/
|
|
55
1
|
import { ensureStyles } from '../utils/styles.js';
|
|
56
2
|
import { wizardStyles } from '../styles/wizard.js';
|
|
57
|
-
// ============================================================================
|
|
58
|
-
// WeakMaps for State Management
|
|
59
|
-
// ============================================================================
|
|
60
3
|
const eventHandlers = new WeakMap();
|
|
61
4
|
const resizeObservers = new WeakMap();
|
|
62
|
-
// ============================================================================
|
|
63
|
-
// Helper Functions - Attribute Parsing
|
|
64
|
-
// ============================================================================
|
|
65
|
-
/**
|
|
66
|
-
* Extract wizard configuration from element attributes
|
|
67
|
-
*/
|
|
68
5
|
function getWizardAttributes(el) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Get all ty-step child elements
|
|
79
|
-
*/
|
|
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
|
+
}
|
|
80
14
|
function getChildSteps(el) {
|
|
81
|
-
|
|
15
|
+
return Array.from(el.querySelectorAll('ty-step'));
|
|
82
16
|
}
|
|
83
|
-
/**
|
|
84
|
-
* Get ID from a ty-step element
|
|
85
|
-
*/
|
|
86
17
|
function getStepId(step) {
|
|
87
|
-
|
|
18
|
+
return step.getAttribute('id');
|
|
88
19
|
}
|
|
89
|
-
/**
|
|
90
|
-
* Get completed step IDs as a Set
|
|
91
|
-
*/
|
|
92
20
|
function getCompletedStepIds(el) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Check if wizard has a direct child indicator slot for this step-id.
|
|
100
|
-
* Looks in ty-wizard's light DOM for slot='indicator-{step-id}' elements.
|
|
101
|
-
*/
|
|
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
|
+
}
|
|
102
26
|
function hasCustomIndicator(wizardEl, stepId) {
|
|
103
|
-
|
|
27
|
+
return wizardEl.querySelector(`[slot='indicator-${stepId}']`) !== null;
|
|
104
28
|
}
|
|
105
|
-
/**
|
|
106
|
-
* Check if step is disabled
|
|
107
|
-
*/
|
|
108
29
|
function isStepDisabled(step) {
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
// ============================================================================
|
|
112
|
-
// Helper Functions - Active Step Management
|
|
113
|
-
// ============================================================================
|
|
114
|
-
/**
|
|
115
|
-
* Find index of step with given ID
|
|
116
|
-
*/
|
|
30
|
+
return step.hasAttribute('disabled');
|
|
31
|
+
}
|
|
117
32
|
function findStepIndex(steps, stepId) {
|
|
118
|
-
|
|
119
|
-
|
|
33
|
+
const index = steps.findIndex(step => getStepId(step) === stepId);
|
|
34
|
+
return index >= 0 ? index : undefined;
|
|
120
35
|
}
|
|
121
|
-
/**
|
|
122
|
-
* Get the active step ID, defaulting to first step if not specified
|
|
123
|
-
*/
|
|
124
36
|
function getActiveStepId(el, steps) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Set the active step by ID
|
|
137
|
-
*/
|
|
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
|
+
}
|
|
138
46
|
function setActiveStep(el, stepId) {
|
|
139
|
-
|
|
47
|
+
el.setAttribute('active', stepId);
|
|
140
48
|
}
|
|
141
|
-
/**
|
|
142
|
-
* Calculate progress percentage for the progress line overlay
|
|
143
|
-
*/
|
|
144
49
|
function calculateProgressPercent(steps, activeId, completedIds) {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Dispatch ty-wizard-step-change event
|
|
153
|
-
*/
|
|
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
|
+
}
|
|
154
55
|
function dispatchStepChangeEvent(el, activeId, activeIndex, previousId, previousIndex) {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
// ============================================================================
|
|
173
|
-
// Event Handlers - Step Indicator Click
|
|
174
|
-
// ============================================================================
|
|
175
|
-
/**
|
|
176
|
-
* Handle step indicator click - only dispatch event (like tabs)
|
|
177
|
-
*/
|
|
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
|
+
}
|
|
178
73
|
function handleStepClick(el, stepId, event) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Cleanup existing event listeners
|
|
207
|
-
*/
|
|
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
|
+
}
|
|
208
99
|
function cleanupEventListeners(el) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Setup event listeners for step indicator clicks
|
|
226
|
-
*/
|
|
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
|
+
}
|
|
227
114
|
function setupEventListeners(el, shadowRoot, steps) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
});
|
|
246
|
-
// Store handlers for cleanup
|
|
247
|
-
eventHandlers.set(el, handlers);
|
|
248
|
-
}
|
|
249
|
-
// ============================================================================
|
|
250
|
-
// Transform & Positioning Updates
|
|
251
|
-
// ============================================================================
|
|
252
|
-
/**
|
|
253
|
-
* Update the transform on panels-wrapper based on active index and measured width
|
|
254
|
-
*/
|
|
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
|
+
}
|
|
255
132
|
function updateTransform(el, activeIndex) {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
panelsWrapper.style.transform = `translateX(-${offsetPx}px)`;
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Update progress line overlay width
|
|
270
|
-
*/
|
|
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
|
+
}
|
|
271
143
|
function updateProgressLine(el) {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* Update ARIA attributes on step indicators without re-rendering
|
|
286
|
-
*/
|
|
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
|
+
}
|
|
287
156
|
function updateStepIndicators(el, shadowRoot, activeId) {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
/**
|
|
316
|
-
* Update pointer-events, opacity, and data-active on step panels without re-rendering
|
|
317
|
-
*/
|
|
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
|
+
}
|
|
318
182
|
function updatePanelInteraction(el, activeId) {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
}
|
|
337
|
-
/**
|
|
338
|
-
* Update only the active step state without re-rendering DOM.
|
|
339
|
-
* This is called when only the active or completed attribute changes.
|
|
340
|
-
*/
|
|
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
|
+
}
|
|
341
200
|
function updateActiveStepState(el, stepId) {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
// Reset scroll position of new active panel
|
|
363
|
-
const newPanel = steps[newIndex];
|
|
364
|
-
if (newPanel?.resetScroll) {
|
|
365
|
-
newPanel.resetScroll();
|
|
366
|
-
}
|
|
367
|
-
// Dispatch change event
|
|
368
|
-
dispatchStepChangeEvent(el, stepId, newIndex, currentActive, currentIndex ?? null);
|
|
369
|
-
}
|
|
370
|
-
// ============================================================================
|
|
371
|
-
// ResizeObserver for Responsive Width
|
|
372
|
-
// ============================================================================
|
|
373
|
-
/**
|
|
374
|
-
* Setup ResizeObserver for percentage widths
|
|
375
|
-
*/
|
|
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
|
+
}
|
|
376
221
|
function setupResizeObserver(el) {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
observer.observe(el);
|
|
399
|
-
resizeObservers.set(el, observer);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
/**
|
|
403
|
-
* Cleanup ResizeObserver
|
|
404
|
-
*/
|
|
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
|
+
}
|
|
405
243
|
function cleanupResizeObserver(el) {
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
}
|
|
412
|
-
// ============================================================================
|
|
413
|
-
// Rendering Functions
|
|
414
|
-
// ============================================================================
|
|
415
|
-
/**
|
|
416
|
-
* Get step status - use user's explicit status attribute or fall back to automatic detection
|
|
417
|
-
*/
|
|
244
|
+
const observer = resizeObservers.get(el);
|
|
245
|
+
if (observer) {
|
|
246
|
+
observer.disconnect();
|
|
247
|
+
resizeObservers.delete(el);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
418
250
|
function getStepStatus(step, stepId, activeId, completedIds) {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
return isCompleted ? 'completed' : isActive ? 'active' : 'pending';
|
|
428
|
-
}
|
|
429
|
-
/**
|
|
430
|
-
* Generate HTML for step indicators with progress line
|
|
431
|
-
*/
|
|
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
|
+
}
|
|
432
259
|
function renderStepIndicators(wizardEl, steps, activeId, completedIds) {
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
<div class="step-indicators-wrapper" part="indicators-wrapper">
|
|
492
|
-
<div class="step-indicators" style="--ty-wizard-step-count: ${stepCount}">
|
|
493
|
-
<div class="progress-line" part="progress-line" role="progressbar" aria-label="Wizard progress" aria-valuenow="${Math.round(progressPercent)}" aria-valuemin="0" aria-valuemax="100">
|
|
494
|
-
<div class="progress-overlay" style="width: ${progressPercent}%"></div>
|
|
495
|
-
</div>
|
|
496
|
-
<div class="step-tablist" role="tablist" style="display: contents;">
|
|
497
|
-
${indicators}
|
|
498
|
-
</div>
|
|
499
|
-
</div>
|
|
500
|
-
</div>
|
|
501
|
-
`;
|
|
502
|
-
}
|
|
503
|
-
/**
|
|
504
|
-
* Render the wizard container with step indicators and panel viewport.
|
|
505
|
-
* Smart rendering: checks if structure exists and only updates when needed.
|
|
506
|
-
*/
|
|
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
|
+
}
|
|
507
318
|
function render(el) {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
const indicators = shadowRoot.querySelector('.step-indicators-wrapper');
|
|
582
|
-
if (indicators) {
|
|
583
|
-
const indicatorsHeight = indicators.offsetHeight;
|
|
584
|
-
el.style.setProperty('--ty-wizard-indicators-height', `${indicatorsHeight}px`);
|
|
585
|
-
}
|
|
586
|
-
// Update transform with measured width
|
|
587
|
-
updateTransform(el, activeIndex);
|
|
588
|
-
// Update progress line
|
|
589
|
-
updateProgressLine(el);
|
|
590
|
-
});
|
|
591
|
-
// Setup event listeners
|
|
592
|
-
setupEventListeners(el, shadowRoot, steps);
|
|
593
|
-
// Update ARIA and data-active attributes on initial render
|
|
594
|
-
updateStepIndicators(el, shadowRoot, activeId || '');
|
|
595
|
-
// Setup ResizeObserver for responsive width
|
|
596
|
-
setupResizeObserver(el);
|
|
597
|
-
// Update step panel states
|
|
598
|
-
if (activeId) {
|
|
599
|
-
updatePanelInteraction(el, activeId);
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
/**
|
|
604
|
-
* Cleanup when wizard component is disconnected
|
|
605
|
-
*/
|
|
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
|
+
}
|
|
606
392
|
function cleanup(el) {
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
}
|
|
610
|
-
// ============================================================================
|
|
611
|
-
// Component Definition
|
|
612
|
-
// ============================================================================
|
|
613
|
-
/**
|
|
614
|
-
* TyWizard Web Component
|
|
615
|
-
*/
|
|
393
|
+
cleanupEventListeners(el);
|
|
394
|
+
cleanupResizeObserver(el);
|
|
395
|
+
}
|
|
616
396
|
export class TyWizard extends HTMLElement {
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
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
|
+
}
|
|
652
440
|
if (!customElements.get('ty-wizard')) {
|
|
653
|
-
|
|
441
|
+
customElements.define('ty-wizard', TyWizard);
|
|
654
442
|
}
|
|
655
|
-
//# sourceMappingURL=wizard.js.map
|