@schukai/monster 4.43.5 → 4.43.7
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/CHANGELOG.md +20 -0
- package/package.json +1 -1
- package/source/components/form/password.mjs +140 -140
- package/source/components/navigation/site-navigation.mjs +36 -27
- package/source/components/navigation/style/site-navigation.pcss +0 -16
- package/source/components/navigation/style/wizard-navigation.pcss +82 -60
- package/source/components/navigation/stylesheet/site-navigation.mjs +1 -1
- package/source/components/navigation/stylesheet/wizard-navigation.mjs +7 -14
- package/source/components/navigation/wizard-navigation.mjs +407 -179
- package/source/types/version.mjs +1 -1
- package/test/cases/monster.mjs +1 -1
- package/test/web/test.html +2 -2
- package/test/web/tests.js +25 -18
|
@@ -1,216 +1,444 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved.
|
|
3
|
-
* Node module: @schukai/monster
|
|
4
|
-
*
|
|
5
|
-
* This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3).
|
|
6
|
-
* The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.en.html
|
|
7
|
-
*
|
|
8
|
-
* For those who do not wish to adhere to the AGPLv3, a commercial license is available.
|
|
9
|
-
* Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms.
|
|
10
|
-
* For more information about purchasing a commercial license, please contact schukai GmbH.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
1
|
import { instanceSymbol } from "../../constants.mjs";
|
|
14
|
-
import {
|
|
2
|
+
import { ATTRIBUTE_ROLE } from "../../dom/constants.mjs";
|
|
15
3
|
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
import { CustomElement, getSlottedElements } from "../../dom/customelement.mjs";
|
|
21
|
-
import {
|
|
22
|
-
assembleMethodSymbol,
|
|
23
|
-
registerCustomElement,
|
|
4
|
+
assembleMethodSymbol,
|
|
5
|
+
CustomElement,
|
|
6
|
+
getSlottedElements,
|
|
7
|
+
registerCustomElement,
|
|
24
8
|
} from "../../dom/customelement.mjs";
|
|
25
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
findTargetElementFromEvent,
|
|
11
|
+
fireCustomEvent,
|
|
12
|
+
} from "../../dom/events.mjs";
|
|
26
13
|
import { isFunction } from "../../types/is.mjs";
|
|
27
14
|
import { WizardNavigationStyleSheet } from "./stylesheet/wizard-navigation.mjs";
|
|
28
|
-
import { fireCustomEvent } from "../../dom/events.mjs";
|
|
29
|
-
import { buildTree } from "../../data/buildtree.mjs";
|
|
30
|
-
import { NodeRecursiveIterator } from "../../types/noderecursiveiterator.mjs";
|
|
31
|
-
import { validateInstance } from "../../types/validate.mjs";
|
|
32
|
-
import { Node } from "../../types/node.mjs";
|
|
33
|
-
import { Formatter } from "../../text/formatter.mjs";
|
|
34
|
-
|
|
35
|
-
export { WizardNavigation };
|
|
36
15
|
|
|
37
|
-
/**
|
|
38
|
-
* @private
|
|
39
|
-
* @type {symbol}
|
|
40
|
-
*/
|
|
41
16
|
const wizardNavigationElementSymbol = Symbol("wizardNavigationElement");
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* @private
|
|
45
|
-
* @type {symbol}
|
|
46
|
-
*/
|
|
47
17
|
const wizardNavigationListElementSymbol = Symbol("wizardNavigationListElement");
|
|
18
|
+
const currentStepIndexSymbol = Symbol("currentStepIndex");
|
|
19
|
+
const stepsSymbol = Symbol("steps");
|
|
20
|
+
const isTransitioningSymbol = Symbol("isTransitioning");
|
|
21
|
+
const currentSubStepIndexSymbol = Symbol("currentSubStepIndex");
|
|
48
22
|
|
|
49
23
|
/**
|
|
50
|
-
* A WizardNavigation
|
|
51
|
-
*
|
|
52
|
-
* @fragments /fragments/components/navigation/wizard-navigation/
|
|
24
|
+
* A WizardNavigation component to display progress and allow navigation through a series of steps,
|
|
25
|
+
* including support for nested sub-steps.
|
|
53
26
|
*
|
|
27
|
+
* @fragments /fragments/components/navigation/wizard-navigation
|
|
54
28
|
* @example /examples/components/navigation/wizard-navigation-simple
|
|
55
|
-
*
|
|
56
|
-
* Work in Progress, currently only the basic functionality is implemented.
|
|
57
|
-
*
|
|
58
29
|
* @since 4.26.0
|
|
59
30
|
* @copyright schukai GmbH
|
|
60
|
-
* @summary A
|
|
31
|
+
* @summary A vertical step-by-step navigation component for wizards.
|
|
32
|
+
* @fires monster-wizard-step-changed - Fired when the main active step changes.
|
|
33
|
+
* @fires monster-wizard-substep-changed - Fired when the active sub-step changes.
|
|
34
|
+
* @fires monster-wizard-completed - Fired when the entire wizard is marked as complete via completeAll().
|
|
61
35
|
*/
|
|
62
36
|
class WizardNavigation extends CustomElement {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return Symbol.for(
|
|
69
|
-
"@schukai/monster/components/navigation/wizard-navigation@@instance",
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
*
|
|
75
|
-
* @return {Components.Navigation.WizardNavigation
|
|
76
|
-
*/
|
|
77
|
-
[assembleMethodSymbol]() {
|
|
78
|
-
super[assembleMethodSymbol]();
|
|
79
|
-
initControlReferences.call(this);
|
|
80
|
-
initEventHandler.call(this);
|
|
81
|
-
queueMicrotask(() => {
|
|
82
|
-
importContent.call(this);
|
|
83
|
-
});
|
|
84
|
-
return this;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* To set the options via the HTML Tag, the attribute `data-monster-options` must be used.
|
|
89
|
-
* @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
|
|
90
|
-
*
|
|
91
|
-
* The individual configuration values can be found in the table.
|
|
92
|
-
*
|
|
93
|
-
* @property {Object} templates Template definitions
|
|
94
|
-
* @property {string} templates.main Main template
|
|
95
|
-
* @property {Object} labels Label definitions
|
|
96
|
-
* @property {Object} actions Callbacks
|
|
97
|
-
* @property {string} actions.click="throw Error" Callback when clicked
|
|
98
|
-
* @property {Object} features Features
|
|
99
|
-
* @property {Object} classes CSS classes
|
|
100
|
-
* @property {boolean} disabled=false Disabled state
|
|
101
|
-
*/
|
|
102
|
-
get defaults() {
|
|
103
|
-
return Object.assign({}, super.defaults, {
|
|
104
|
-
templates: {
|
|
105
|
-
main: getTemplate(),
|
|
106
|
-
},
|
|
107
|
-
labels: {},
|
|
108
|
-
classes: {},
|
|
109
|
-
disabled: false,
|
|
110
|
-
features: {},
|
|
111
|
-
actions: {
|
|
112
|
-
click: () => {
|
|
113
|
-
throw new Error("the click action is not defined");
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* @return {string}
|
|
121
|
-
*/
|
|
122
|
-
static getTag() {
|
|
123
|
-
return "monster-wizard-navigation";
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* @return {CSSStyleSheet[]}
|
|
128
|
-
*/
|
|
129
|
-
static getCSSStyleSheet() {
|
|
130
|
-
return [WizardNavigationStyleSheet];
|
|
131
|
-
}
|
|
132
|
-
}
|
|
37
|
+
static get [instanceSymbol]() {
|
|
38
|
+
return Symbol.for(
|
|
39
|
+
"@schukai/monster/components/navigation/wizard-navigation@@instance",
|
|
40
|
+
);
|
|
41
|
+
}
|
|
133
42
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
43
|
+
[assembleMethodSymbol]() {
|
|
44
|
+
super[assembleMethodSymbol]();
|
|
45
|
+
this[isTransitioningSymbol] = false;
|
|
46
|
+
this[currentStepIndexSymbol] = -1;
|
|
47
|
+
this[currentSubStepIndexSymbol] = -1;
|
|
48
|
+
|
|
49
|
+
initControlReferences.call(this);
|
|
50
|
+
initEventHandler.call(this);
|
|
51
|
+
|
|
52
|
+
queueMicrotask(() => {
|
|
53
|
+
importContent.call(this);
|
|
54
|
+
this.activate(0, 0, { force: true });
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* To set the options via the HTML Tag, the attribute `data-monster-options` must be used.
|
|
62
|
+
* @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
|
|
63
|
+
*
|
|
64
|
+
* The individual configuration values can be found in the table.
|
|
65
|
+
*
|
|
66
|
+
* @property {Object} templates Template definitions
|
|
67
|
+
* @property {string} templates.main Main template
|
|
68
|
+
* @property {Object} actions Action callbacks
|
|
69
|
+
* @property {function(number, number):(boolean|Promise<boolean>)} actions.beforeStepChange - Callback fired before a main step change. Must return `true` or a Promise that resolves to `true` to allow the transition. Parameters are `fromIndex` and `toIndex`.
|
|
70
|
+
* @property {function} actions.click - General click handler callback.
|
|
71
|
+
*/
|
|
72
|
+
get defaults() {
|
|
73
|
+
return Object.assign({}, super.defaults, {
|
|
74
|
+
templates: {
|
|
75
|
+
main: getTemplate(),
|
|
76
|
+
},
|
|
77
|
+
actions: {
|
|
78
|
+
beforeStepChange: (fromIndex, toIndex) => true,
|
|
79
|
+
click: () => {},
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Navigates to the specified main step if the transition logic allows it.
|
|
86
|
+
* @param {number} index The index of the target step.
|
|
87
|
+
* @param {object} [options={}] Additional options.
|
|
88
|
+
* @param {boolean} [options.force=false] If true, the `beforeStepChange` callback is skipped.
|
|
89
|
+
* @returns {Promise<void>}
|
|
90
|
+
* @fires monster-wizard-step-changed
|
|
91
|
+
*/
|
|
92
|
+
async goToStep(index, options = {}) {
|
|
93
|
+
if (typeof index !== "number") {
|
|
94
|
+
console.error("WizardNavigation.goToStep: index must be a number.");
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const { force = false } = options;
|
|
99
|
+
const stepsData = this[stepsSymbol];
|
|
100
|
+
const oldIndex = this[currentStepIndexSymbol];
|
|
101
|
+
|
|
102
|
+
if (
|
|
103
|
+
!stepsData ||
|
|
104
|
+
index < 0 ||
|
|
105
|
+
index >= stepsData.length ||
|
|
106
|
+
index === oldIndex ||
|
|
107
|
+
this[isTransitioningSymbol]
|
|
108
|
+
) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
this[isTransitioningSymbol] = true;
|
|
113
|
+
|
|
114
|
+
if (!force) {
|
|
115
|
+
const callback = this.getOption("actions.beforeStepChange");
|
|
116
|
+
if (isFunction(callback)) {
|
|
117
|
+
const isAllowed = await Promise.resolve(
|
|
118
|
+
callback.call(this, oldIndex, index),
|
|
119
|
+
);
|
|
120
|
+
if (!isAllowed) {
|
|
121
|
+
this[isTransitioningSymbol] = false;
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
stepsData.forEach((stepData, i) => {
|
|
128
|
+
stepData.element.classList.remove("step-active");
|
|
129
|
+
stepData.element.setAttribute("aria-selected", "false");
|
|
130
|
+
|
|
131
|
+
if (stepData.subStepList) {
|
|
132
|
+
stepData.subStepList.style.maxHeight =
|
|
133
|
+
i === index ? stepData.subStepList.scrollHeight + "px" : "0px";
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (i < index) {
|
|
137
|
+
stepData.element.classList.add("step-completed");
|
|
138
|
+
stepData.subSteps.forEach((sub) =>
|
|
139
|
+
sub.classList.add("sub-item-completed"),
|
|
140
|
+
);
|
|
141
|
+
} else {
|
|
142
|
+
stepData.element.classList.remove("step-completed");
|
|
143
|
+
stepData.subSteps.forEach((sub) =>
|
|
144
|
+
sub.classList.remove("sub-item-completed"),
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
if (oldIndex !== -1 && stepsData[oldIndex]) {
|
|
150
|
+
stepsData[oldIndex].subSteps.forEach((sub) =>
|
|
151
|
+
sub.classList.remove("sub-item-active"),
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
this[currentSubStepIndexSymbol] = -1;
|
|
156
|
+
this[currentStepIndexSymbol] = index;
|
|
157
|
+
|
|
158
|
+
const currentStepData = stepsData[index];
|
|
159
|
+
currentStepData.element.classList.remove("step-completed");
|
|
160
|
+
currentStepData.element.classList.add("step-active");
|
|
161
|
+
currentStepData.element.setAttribute("aria-selected", "true");
|
|
162
|
+
|
|
163
|
+
fireCustomEvent(this, "monster-wizard-step-changed", {
|
|
164
|
+
newIndex: index,
|
|
165
|
+
oldIndex: oldIndex,
|
|
166
|
+
element: currentStepData.element,
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
this[isTransitioningSymbol] = false;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Activates a specific main step and sub-step.
|
|
174
|
+
* @param {number} mainIndex The index of the main step.
|
|
175
|
+
* @param {number} subIndex The index of the sub-step.
|
|
176
|
+
* @param {object} [options={}] Additional options.
|
|
177
|
+
* @param {boolean} [options.force=false] If true, the `beforeStepChange` callback is skipped.
|
|
178
|
+
* @returns {Promise<void>}
|
|
179
|
+
* @fires monster-wizard-substep-changed
|
|
180
|
+
*/
|
|
181
|
+
async activate(mainIndex, subIndex, options = {}) {
|
|
182
|
+
if (typeof mainIndex !== "number" || typeof subIndex !== "number") {
|
|
183
|
+
console.error(
|
|
184
|
+
"WizardNavigation.activate: mainIndex and subIndex must be numbers.",
|
|
185
|
+
);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
await this.goToStep(mainIndex, options);
|
|
190
|
+
|
|
191
|
+
const stepsData = this[stepsSymbol];
|
|
192
|
+
if (!stepsData || !stepsData[mainIndex]) return;
|
|
142
193
|
|
|
143
|
-
|
|
194
|
+
const targetStep = stepsData[mainIndex];
|
|
195
|
+
if (
|
|
196
|
+
!targetStep.subSteps ||
|
|
197
|
+
subIndex < 0 ||
|
|
198
|
+
subIndex >= targetStep.subSteps.length
|
|
199
|
+
) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
144
202
|
|
|
145
|
-
|
|
146
|
-
|
|
203
|
+
stepsData.forEach((step) => {
|
|
204
|
+
step.subSteps.forEach((subStep) =>
|
|
205
|
+
subStep.classList.remove("sub-item-active"),
|
|
206
|
+
);
|
|
207
|
+
});
|
|
147
208
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
209
|
+
for (let i = 0; i < subIndex; i++) {
|
|
210
|
+
if (targetStep.subSteps[i]) {
|
|
211
|
+
targetStep.subSteps[i].classList.add("sub-item-completed");
|
|
212
|
+
}
|
|
213
|
+
}
|
|
151
214
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
215
|
+
const targetSubStep = targetStep.subSteps[subIndex];
|
|
216
|
+
targetSubStep.classList.remove("sub-item-completed");
|
|
217
|
+
targetSubStep.classList.add("sub-item-active");
|
|
218
|
+
this[currentSubStepIndexSymbol] = subIndex;
|
|
155
219
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
220
|
+
fireCustomEvent(this, "monster-wizard-substep-changed", {
|
|
221
|
+
mainIndex,
|
|
222
|
+
subIndex,
|
|
223
|
+
element: targetSubStep,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
161
226
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
227
|
+
/**
|
|
228
|
+
* Navigates to the next step or sub-step in sequence.
|
|
229
|
+
* @returns {Promise<void>}
|
|
230
|
+
*/
|
|
231
|
+
async next() {
|
|
232
|
+
const mainIndex = this[currentStepIndexSymbol];
|
|
233
|
+
const subIndex = this[currentSubStepIndexSymbol];
|
|
234
|
+
const stepsData = this[stepsSymbol];
|
|
165
235
|
|
|
166
|
-
|
|
167
|
-
});
|
|
236
|
+
if (mainIndex === -1 || !stepsData || !stepsData[mainIndex]) return;
|
|
168
237
|
|
|
169
|
-
|
|
238
|
+
const currentStepData = stepsData[mainIndex];
|
|
239
|
+
const hasSubSteps = currentStepData.subSteps.length > 0;
|
|
240
|
+
|
|
241
|
+
if (hasSubSteps && subIndex < currentStepData.subSteps.length - 1) {
|
|
242
|
+
await this.activate(mainIndex, subIndex + 1);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const nextMainIndex = mainIndex + 1;
|
|
247
|
+
if (nextMainIndex < stepsData.length) {
|
|
248
|
+
if (stepsData[nextMainIndex].subSteps.length > 0) {
|
|
249
|
+
await this.activate(nextMainIndex, 0);
|
|
250
|
+
} else {
|
|
251
|
+
await this.goToStep(nextMainIndex);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Navigates to the previous step or sub-step in sequence.
|
|
258
|
+
* @returns {Promise<void>}
|
|
259
|
+
*/
|
|
260
|
+
async previous() {
|
|
261
|
+
const mainIndex = this[currentStepIndexSymbol];
|
|
262
|
+
const subIndex = this[currentSubStepIndexSymbol];
|
|
263
|
+
const stepsData = this[stepsSymbol];
|
|
264
|
+
|
|
265
|
+
if (subIndex > 0) {
|
|
266
|
+
await this.activate(mainIndex, subIndex - 1);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const prevMainIndex = mainIndex - 1;
|
|
271
|
+
if (prevMainIndex >= 0) {
|
|
272
|
+
const prevStepData = stepsData[prevMainIndex];
|
|
273
|
+
if (prevStepData.subSteps.length > 0) {
|
|
274
|
+
await this.activate(prevMainIndex, prevStepData.subSteps.length - 1);
|
|
275
|
+
} else {
|
|
276
|
+
await this.goToStep(prevMainIndex);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Marks the current step as completed and automatically navigates to the next step.
|
|
283
|
+
* @returns {Promise<void>}
|
|
284
|
+
*/
|
|
285
|
+
async completeAndNext() {
|
|
286
|
+
const currentIndex = this[currentStepIndexSymbol];
|
|
287
|
+
const stepsData = this[stepsSymbol];
|
|
288
|
+
|
|
289
|
+
if (currentIndex === -1 || !stepsData || !stepsData[currentIndex]) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const currentStepData = stepsData[currentIndex];
|
|
294
|
+
currentStepData.element.classList.add("step-completed");
|
|
295
|
+
currentStepData.element.classList.remove("step-active");
|
|
296
|
+
|
|
297
|
+
currentStepData.subSteps.forEach((sub) => {
|
|
298
|
+
sub.classList.add("sub-item-completed");
|
|
299
|
+
sub.classList.remove("sub-item-active");
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
await this.next();
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Marks the entire wizard workflow as completed.
|
|
307
|
+
* @fires monster-wizard-completed
|
|
308
|
+
*/
|
|
309
|
+
completeAll() {
|
|
310
|
+
const stepsData = this[stepsSymbol];
|
|
311
|
+
if (!stepsData) return;
|
|
312
|
+
|
|
313
|
+
stepsData.forEach((stepData) => {
|
|
314
|
+
stepData.element.classList.add("step-completed");
|
|
315
|
+
stepData.element.classList.remove("step-active");
|
|
316
|
+
stepData.element.setAttribute("aria-selected", "false");
|
|
317
|
+
|
|
318
|
+
stepData.subSteps.forEach((sub) => {
|
|
319
|
+
sub.classList.add("sub-item-completed");
|
|
320
|
+
sub.classList.remove("sub-item-active");
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
if (stepData.subStepList) {
|
|
324
|
+
stepData.subStepList.style.maxHeight = "0px";
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
this[currentStepIndexSymbol] = -1;
|
|
329
|
+
this[currentSubStepIndexSymbol] = -1;
|
|
330
|
+
|
|
331
|
+
fireCustomEvent(this, "monster-wizard-completed", {
|
|
332
|
+
detail: { message: "All steps completed." },
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Gets the index of the currently active main step.
|
|
338
|
+
* @returns {number} The index of the current step, or -1 if none is active.
|
|
339
|
+
*/
|
|
340
|
+
getCurrentStepIndex() {
|
|
341
|
+
return this[currentStepIndexSymbol];
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Gets the index of the currently active sub-step within the main step.
|
|
346
|
+
* @returns {number} The index of the current sub-step, or -1 if none is active.
|
|
347
|
+
*/
|
|
348
|
+
getCurrentSubStepIndex() {
|
|
349
|
+
return this[currentSubStepIndexSymbol];
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
static getTag() {
|
|
353
|
+
return "monster-wizard-navigation";
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
static getCSSStyleSheet() {
|
|
357
|
+
return [WizardNavigationStyleSheet];
|
|
358
|
+
}
|
|
170
359
|
}
|
|
171
360
|
|
|
172
|
-
/**
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
361
|
+
/** @private */
|
|
362
|
+
function initEventHandler() {
|
|
363
|
+
const self = this;
|
|
364
|
+
this[wizardNavigationElementSymbol].addEventListener(
|
|
365
|
+
"click",
|
|
366
|
+
function (event) {
|
|
367
|
+
const targetStepElement = findTargetElementFromEvent(event, "li.step");
|
|
368
|
+
if (!targetStepElement) return;
|
|
369
|
+
|
|
370
|
+
const targetIndex = self[stepsSymbol].findIndex(
|
|
371
|
+
(stepData) => stepData.element === targetStepElement,
|
|
372
|
+
);
|
|
180
373
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
374
|
+
if (targetIndex !== -1) {
|
|
375
|
+
self.goToStep(targetIndex);
|
|
376
|
+
}
|
|
377
|
+
},
|
|
378
|
+
);
|
|
184
379
|
}
|
|
185
380
|
|
|
186
|
-
/**
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
381
|
+
/** @private */
|
|
382
|
+
function initControlReferences() {
|
|
383
|
+
this[wizardNavigationElementSymbol] = this.shadowRoot.querySelector(
|
|
384
|
+
`[${ATTRIBUTE_ROLE}="control"]`,
|
|
385
|
+
);
|
|
386
|
+
this[wizardNavigationListElementSymbol] = this.shadowRoot.querySelector(
|
|
387
|
+
`[${ATTRIBUTE_ROLE}="list"]`,
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/** @private */
|
|
194
392
|
function importContent() {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
393
|
+
const elements = getSlottedElements.call(this, "ol.wizard-steps");
|
|
394
|
+
elements.forEach((element) => {
|
|
395
|
+
const clonedContent = element.cloneNode(true);
|
|
396
|
+
this[wizardNavigationListElementSymbol].innerHTML = "";
|
|
397
|
+
this[wizardNavigationListElementSymbol].appendChild(clonedContent);
|
|
398
|
+
|
|
399
|
+
const stepElements =
|
|
400
|
+
this[wizardNavigationListElementSymbol].querySelectorAll("li.step");
|
|
401
|
+
|
|
402
|
+
this[stepsSymbol] = Array.from(stepElements).map((stepEl) => {
|
|
403
|
+
const subStepList = stepEl.querySelector("ul");
|
|
404
|
+
const subSteps = subStepList
|
|
405
|
+
? Array.from(subStepList.querySelectorAll("li"))
|
|
406
|
+
: [];
|
|
407
|
+
|
|
408
|
+
if (subStepList) {
|
|
409
|
+
subStepList.style.maxHeight = "0px";
|
|
410
|
+
subStepList.style.overflow = "hidden";
|
|
411
|
+
subStepList.style.transition = "max-height 0.4s ease-in-out";
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
return {
|
|
415
|
+
element: stepEl,
|
|
416
|
+
subStepList: subStepList,
|
|
417
|
+
subSteps: subSteps,
|
|
418
|
+
};
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
this[currentStepIndexSymbol] = -1;
|
|
422
|
+
this[currentSubStepIndexSymbol] = -1;
|
|
423
|
+
|
|
424
|
+
this[wizardNavigationListElementSymbol]
|
|
425
|
+
.querySelector("ol")
|
|
426
|
+
?.setAttribute("role", "tablist");
|
|
427
|
+
|
|
428
|
+
this[stepsSymbol].forEach((stepData) => {
|
|
429
|
+
stepData.element.setAttribute("role", "tab");
|
|
430
|
+
stepData.element.setAttribute("aria-selected", "false");
|
|
431
|
+
});
|
|
432
|
+
});
|
|
201
433
|
}
|
|
202
434
|
|
|
203
|
-
/**
|
|
204
|
-
* @private
|
|
205
|
-
* @return {string}
|
|
206
|
-
*/
|
|
435
|
+
/** @private */
|
|
207
436
|
function getTemplate() {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
<
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
</div>`;
|
|
437
|
+
return `
|
|
438
|
+
<div data-monster-role="control" part="control">
|
|
439
|
+
<slot style="display: none;"></slot>
|
|
440
|
+
<div data-monster-role="list"></div>
|
|
441
|
+
</div>`;
|
|
214
442
|
}
|
|
215
443
|
|
|
216
444
|
registerCustomElement(WizardNavigation);
|
package/source/types/version.mjs
CHANGED
package/test/cases/monster.mjs
CHANGED
package/test/web/test.html
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="headline" style="display: flex;align-items: center;justify-content: center;flex-direction: column;">
|
|
12
|
-
<h1 style='margin-bottom: 0.1em;'>Monster 4.43.
|
|
13
|
-
<div id="lastupdate" style='font-size:0.7em'>last update
|
|
12
|
+
<h1 style='margin-bottom: 0.1em;'>Monster 4.43.6</h1>
|
|
13
|
+
<div id="lastupdate" style='font-size:0.7em'>last update Sa 11. Okt 18:38:25 CEST 2025</div>
|
|
14
14
|
</div>
|
|
15
15
|
<div id="mocha-errors"
|
|
16
16
|
style="color: red;font-weight: bold;display: flex;align-items: center;justify-content: center;flex-direction: column;margin:20px;"></div>
|