material-inspired-component-library 3.0.2 → 4.0.0
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 +16 -14
- package/components/README.md +1 -1
- package/components/accordion/README.md +8 -3
- package/components/alert/README.md +76 -0
- package/components/alert/index.scss +121 -0
- package/components/appbar/README.md +9 -4
- package/components/appbar/index.scss +1 -1
- package/components/badge/README.md +8 -3
- package/components/badge/index.scss +1 -0
- package/components/bottomsheet/README.md +8 -3
- package/components/button/README.md +8 -3
- package/components/button/index.scss +7 -0
- package/components/card/README.md +10 -4
- package/components/card/index.scss +1 -1
- package/components/checkbox/README.md +56 -13
- package/components/checkbox/index.scss +148 -183
- package/components/checkbox/index.ts +148 -0
- package/components/dialog/README.md +8 -3
- package/components/dialog/index.scss +1 -0
- package/components/divider/README.md +8 -3
- package/components/iconbutton/README.md +8 -3
- package/components/iconbutton/index.scss +3 -1
- package/components/list/README.md +8 -3
- package/components/list/index.scss +2 -0
- package/components/list/index.ts +2 -3
- package/components/menu/README.md +7 -2
- package/components/menu/index.ts +2 -2
- package/components/navigationrail/README.md +8 -3
- package/components/navigationrail/index.scss +1 -0
- package/components/radio/README.md +8 -3
- package/components/radio/index.scss +8 -24
- package/components/select/README.md +3 -3
- package/components/sidesheet/README.md +8 -3
- package/components/slider/README.md +8 -3
- package/components/slider/index.scss +1 -0
- package/components/slider/index.ts +9 -10
- package/components/stepper/README.md +190 -0
- package/components/stepper/index.scss +93 -14
- package/components/stepper/index.ts +169 -88
- package/components/switch/README.md +8 -3
- package/components/switch/index.scss +2 -0
- package/components/textfield/README.md +8 -3
- package/components/textfield/index.ts +8 -41
- package/dist/alert.css +1 -0
- package/dist/alert.js +1 -0
- package/dist/badge.css +1 -1
- package/dist/button.css +1 -1
- package/dist/card.css +1 -1
- package/dist/checkbox.css +1 -1
- package/dist/components/checkbox/index.d.ts +5 -0
- package/dist/components/textfield/index.d.ts +0 -1
- package/dist/dialog.css +1 -1
- package/dist/foundations/form/index.d.ts +5 -0
- package/dist/iconbutton.css +1 -1
- package/dist/list.css +1 -1
- package/dist/micl.css +1 -1
- package/dist/micl.js +1 -1
- package/dist/navigationrail.css +1 -1
- package/dist/radio.css +1 -1
- package/dist/slider.css +1 -1
- package/dist/stepper.css +1 -1
- package/dist/switch.css +1 -1
- package/docs/accordion.html +1 -1
- package/docs/alert.html +176 -0
- package/docs/bottomsheet.html +2 -2
- package/docs/button.html +2 -2
- package/docs/card.html +7 -7
- package/docs/checkbox.html +33 -9
- package/docs/dialog.html +2 -2
- package/docs/divider.html +8 -8
- package/docs/iconbutton.html +2 -2
- package/docs/index.html +43 -32
- package/docs/list.html +2 -2
- package/docs/menu.html +2 -2
- package/docs/micl.css +1 -1
- package/docs/micl.js +1 -1
- package/docs/radio.html +2 -2
- package/docs/select.html +2 -2
- package/docs/sidesheet.html +2 -2
- package/docs/slider.html +2 -2
- package/docs/stepper.html +318 -0
- package/docs/switch.html +8 -4
- package/docs/textfield.html +2 -2
- package/foundations/form/index.ts +174 -0
- package/{layout → foundations/layout}/README.md +5 -0
- package/{layout → foundations/layout}/index.scss +1 -1
- package/micl.ts +3 -3
- package/package.json +3 -1
- package/styles.scss +2 -1
- package/webpack.config.js +1 -1
|
@@ -19,11 +19,15 @@
|
|
|
19
19
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
20
|
// SOFTWARE.
|
|
21
21
|
|
|
22
|
-
@use '../../layout';
|
|
22
|
+
@use '../../foundations/layout';
|
|
23
23
|
@use '../../styles/motion';
|
|
24
24
|
|
|
25
25
|
:root {
|
|
26
|
-
--md-sys-stepper-
|
|
26
|
+
--md-sys-stepper-counter-style: decimal;
|
|
27
|
+
--md-sys-stepper-dot-size: 12px;
|
|
28
|
+
}
|
|
29
|
+
body {
|
|
30
|
+
--md-sys-stepper-dot-done-color: var(--md-sys-color-tertiary-container, blue);
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
.micl-stepper {
|
|
@@ -35,8 +39,38 @@
|
|
|
35
39
|
display: flex;
|
|
36
40
|
flex-direction: column;
|
|
37
41
|
row-gap: var(--md-sys-layout-padding-xl, 24px);
|
|
42
|
+
margin: 0;
|
|
38
43
|
background-color: inherit;
|
|
39
44
|
|
|
45
|
+
.micl-stepper__header {
|
|
46
|
+
--md-sys-stepper-dot-size: 24px;
|
|
47
|
+
|
|
48
|
+
display: flex;
|
|
49
|
+
justify-content: space-between;
|
|
50
|
+
align-items: flex-start;
|
|
51
|
+
margin-inline: -10px;
|
|
52
|
+
background-color: inherit;
|
|
53
|
+
background-image: linear-gradient(90deg, var(--md-sys-divider-color), var(--md-sys-divider-color));
|
|
54
|
+
background-position: center;
|
|
55
|
+
background-repeat: no-repeat;
|
|
56
|
+
background-size: 100% 1px;
|
|
57
|
+
counter-reset: dotnumber;
|
|
58
|
+
|
|
59
|
+
button {
|
|
60
|
+
background-color: inherit;
|
|
61
|
+
pointer-events: none;
|
|
62
|
+
|
|
63
|
+
&.micl-stepper__progress--done {
|
|
64
|
+
pointer-events: inherit;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
.micl-stepper__progress-dot::before {
|
|
68
|
+
content: counter(dotnumber, var(--md-sys-stepper-counter-style));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
&.micl-stepper--nonlinear .micl-stepper__header button {
|
|
72
|
+
pointer-events: inherit;
|
|
73
|
+
}
|
|
40
74
|
.micl-stepper__steps {
|
|
41
75
|
display: grid;
|
|
42
76
|
grid-template-areas: "stepper-steps";
|
|
@@ -48,7 +82,9 @@
|
|
|
48
82
|
display: flex;
|
|
49
83
|
visibility: hidden;
|
|
50
84
|
flex-direction: column;
|
|
51
|
-
|
|
85
|
+
margin: 0;
|
|
86
|
+
padding: 0;
|
|
87
|
+
border: none;
|
|
52
88
|
opacity: 0%;
|
|
53
89
|
background-color: inherit;
|
|
54
90
|
transform: translateX(100%);
|
|
@@ -56,30 +92,73 @@
|
|
|
56
92
|
opacity var(--md-sys-stepper-motion-duration) linear,
|
|
57
93
|
transform var(--md-sys-stepper-motion-duration) var(--md-sys-stepper-motion-spatial);
|
|
58
94
|
|
|
59
|
-
&:has(~ .micl-stepper__step
|
|
95
|
+
&:has(~ .micl-stepper__step[aria-current=step]) {
|
|
60
96
|
transform: translateX(-100%);
|
|
61
97
|
}
|
|
62
|
-
&.micl-stepper__step--
|
|
98
|
+
&.micl-stepper__step--toselected {
|
|
63
99
|
visibility: visible;
|
|
64
100
|
}
|
|
65
|
-
|
|
101
|
+
&[aria-current=step] {
|
|
66
102
|
visibility: visible;
|
|
67
103
|
opacity: 100%;
|
|
68
104
|
transform: translateX(0%);
|
|
69
105
|
}
|
|
70
|
-
&.micl-stepper__step--
|
|
106
|
+
&.micl-stepper__step--fromselected {
|
|
71
107
|
visibility: visible;
|
|
72
108
|
}
|
|
73
|
-
|
|
74
|
-
.micl-stepper__content {
|
|
75
|
-
box-sizing: border-box;
|
|
76
|
-
padding-inline: var(--md-sys-stepper-padding-inline);
|
|
77
|
-
background-color: inherit;
|
|
78
|
-
}
|
|
79
109
|
}
|
|
80
110
|
}
|
|
81
111
|
.micl-stepper__actions {
|
|
82
112
|
display: flex;
|
|
83
|
-
|
|
113
|
+
flex-direction: row;
|
|
114
|
+
justify-content: center;
|
|
115
|
+
inline-size: 100%;
|
|
116
|
+
align-items: center;
|
|
117
|
+
|
|
118
|
+
&>:first-child,
|
|
119
|
+
&>:last-child {
|
|
120
|
+
display: flex;
|
|
121
|
+
flex: 1 1 0;
|
|
122
|
+
column-gap: var(--md-sys-layout-padding-xs, 8px)
|
|
123
|
+
}
|
|
124
|
+
&>:last-child {
|
|
125
|
+
justify-content: flex-end;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
.micl-stepper__progress-dots {
|
|
129
|
+
display: flex;
|
|
130
|
+
align-items: center;
|
|
131
|
+
column-gap: 4px;
|
|
132
|
+
}
|
|
133
|
+
.micl-stepper__progress-dot {
|
|
134
|
+
block-size: var(--md-sys-stepper-dot-size);
|
|
135
|
+
inline-size: var(--md-sys-stepper-dot-size);
|
|
136
|
+
min-inline-size: var(--md-sys-stepper-dot-size);
|
|
137
|
+
line-height: var(--md-sys-stepper-dot-size);
|
|
138
|
+
border-radius: calc(var(--md-sys-stepper-dot-size) / 2);
|
|
139
|
+
text-align: center;
|
|
140
|
+
background-color: var(--md-sys-color-on-surface);
|
|
141
|
+
color: var(--md-sys-color-surface);
|
|
142
|
+
opacity: 38%;
|
|
143
|
+
counter-increment: dotnumber 1;
|
|
144
|
+
}
|
|
145
|
+
.micl-stepper__progress--done.micl-stepper__progress-dot,
|
|
146
|
+
.micl-stepper__progress--done .micl-stepper__progress-dot {
|
|
147
|
+
background-color: var(--md-sys-stepper-dot-done-color);
|
|
148
|
+
color: var(--md-sys-color-on-tertiary-container);
|
|
149
|
+
opacity: 100%;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
[dir=rtl] {
|
|
154
|
+
.micl-stepper .micl-stepper__steps .micl-stepper__step {
|
|
155
|
+
transform: translateX(-100%);
|
|
156
|
+
|
|
157
|
+
&:has(~ .micl-stepper__step[aria-current=step]) {
|
|
158
|
+
transform: translateX(100%);
|
|
159
|
+
}
|
|
160
|
+
&[aria-current=step] {
|
|
161
|
+
transform: translateX(0%);
|
|
162
|
+
}
|
|
84
163
|
}
|
|
85
164
|
}
|
|
@@ -19,145 +19,226 @@
|
|
|
19
19
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
20
|
// SOFTWARE.
|
|
21
21
|
|
|
22
|
+
import form from '../../foundations/form';
|
|
23
|
+
|
|
22
24
|
export const stepperSelector = '.micl-stepper';
|
|
23
25
|
|
|
26
|
+
const ACTIONS_SELECTOR = '.micl-stepper__action-back,.micl-stepper__action-next';
|
|
27
|
+
const BUTTON_SELECTOR = '.micl-stepper__header button[role=tab][aria-controls]';
|
|
28
|
+
const STEP_CLASS = 'micl-stepper__step';
|
|
29
|
+
const STEP_SELECTOR = '.' + STEP_CLASS;
|
|
30
|
+
|
|
24
31
|
export default (() =>
|
|
25
32
|
{
|
|
26
|
-
const
|
|
33
|
+
const getSelectedStep = (stepper: HTMLElement): HTMLElement | null =>
|
|
27
34
|
{
|
|
28
|
-
let step = stepper.querySelector(
|
|
35
|
+
let step = stepper.querySelector(`${STEP_SELECTOR}[aria-current=step]`);
|
|
29
36
|
if (step) {
|
|
30
|
-
return step;
|
|
37
|
+
return step as HTMLElement;
|
|
31
38
|
}
|
|
32
|
-
|
|
39
|
+
return setSelectedStep(stepper, stepper.querySelector(STEP_SELECTOR));
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const getStepNumber = (stepper: HTMLElement, step: HTMLElement): number =>
|
|
43
|
+
{
|
|
44
|
+
const allSteps = Array.from(stepper.querySelectorAll(STEP_SELECTOR));
|
|
45
|
+
const index = allSteps.indexOf(step);
|
|
46
|
+
|
|
47
|
+
return index + 1;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const setSelectedStep = (stepper: HTMLElement, step: HTMLElement | null): HTMLElement | null =>
|
|
51
|
+
{
|
|
33
52
|
if (!step) {
|
|
34
53
|
return null;
|
|
35
54
|
}
|
|
36
|
-
|
|
55
|
+
let index = 0;
|
|
56
|
+
stepper.querySelectorAll(STEP_SELECTOR).forEach((e, i) =>
|
|
57
|
+
{
|
|
58
|
+
e.setAttribute('aria-current', e === step ? 'step' : 'false');
|
|
59
|
+
if (e === step) {
|
|
60
|
+
index = i;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
const button = stepper.querySelectorAll(BUTTON_SELECTOR).item(index);
|
|
64
|
+
stepper.querySelectorAll(BUTTON_SELECTOR).forEach((e, i) =>
|
|
65
|
+
{
|
|
66
|
+
e.setAttribute('aria-selected', e === button ? 'true' : 'false');
|
|
67
|
+
});
|
|
68
|
+
refresh(stepper, step);
|
|
69
|
+
|
|
37
70
|
return step;
|
|
38
71
|
};
|
|
39
72
|
|
|
40
|
-
const
|
|
73
|
+
const endTransitionSelected = (event: Event): void =>
|
|
41
74
|
{
|
|
42
|
-
|
|
75
|
+
const target = event.currentTarget as Element;
|
|
76
|
+
if ((event as TransitionEvent).propertyName !== 'transform' || !target) {
|
|
43
77
|
return;
|
|
44
78
|
}
|
|
45
|
-
|
|
46
|
-
'micl-stepper__step--
|
|
47
|
-
'micl-stepper__step--
|
|
79
|
+
target.classList.remove(
|
|
80
|
+
'micl-stepper__step--fromselected',
|
|
81
|
+
'micl-stepper__step--toselected'
|
|
48
82
|
);
|
|
49
|
-
|
|
83
|
+
target.removeEventListener('transitionend', endTransitionSelected);
|
|
50
84
|
};
|
|
51
85
|
|
|
52
|
-
const
|
|
86
|
+
const goToSibling = (stepper: HTMLElement, selectedStep: HTMLElement, sibling: HTMLElement): void =>
|
|
87
|
+
{
|
|
88
|
+
selectedStep.addEventListener('transitionend', endTransitionSelected);
|
|
89
|
+
selectedStep.classList.add('micl-stepper__step--fromselected');
|
|
90
|
+
selectedStep.offsetHeight;
|
|
91
|
+
|
|
92
|
+
sibling.addEventListener('transitionend', endTransitionSelected);
|
|
93
|
+
sibling.classList.add('micl-stepper__step--toselected');
|
|
94
|
+
sibling.offsetHeight;
|
|
95
|
+
|
|
96
|
+
setSelectedStep(stepper, sibling);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const isBackAction = (action: HTMLElement): boolean =>
|
|
100
|
+
action.classList.contains('micl-stepper__action-back');
|
|
101
|
+
|
|
102
|
+
const showHideActions = (stepper: HTMLElement, step: HTMLElement): void =>
|
|
53
103
|
{
|
|
54
|
-
|
|
104
|
+
Array.from(stepper.querySelectorAll<HTMLElement>(ACTIONS_SELECTOR)).forEach(action =>
|
|
55
105
|
{
|
|
56
|
-
action
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
106
|
+
const siblingKey = isBackAction(action) ? 'previousElementSibling' : 'nextElementSibling';
|
|
107
|
+
const hasSibling = (step[siblingKey] as Element)?.classList.contains(STEP_CLASS);
|
|
108
|
+
|
|
109
|
+
action.classList.toggle('micl-hidden', !hasSibling);
|
|
60
110
|
});
|
|
61
111
|
};
|
|
62
112
|
|
|
63
113
|
const showHideElements = (stepper: HTMLElement, step: HTMLElement): void =>
|
|
64
114
|
{
|
|
115
|
+
const selectedStep = getStepNumber(stepper, step);
|
|
116
|
+
|
|
65
117
|
stepper.querySelectorAll<HTMLElement>('[data-step]').forEach(element =>
|
|
66
118
|
{
|
|
67
|
-
|
|
119
|
+
const shouldHide = element.dataset.step != `${selectedStep}`;
|
|
120
|
+
element.classList.toggle('micl-hidden', shouldHide);
|
|
68
121
|
});
|
|
69
122
|
};
|
|
70
123
|
|
|
71
|
-
const
|
|
124
|
+
const updateProgress = (stepper: HTMLElement, step: HTMLElement): void =>
|
|
72
125
|
{
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
).forEach(
|
|
78
|
-
|
|
79
|
-
if (!input.checkValidity()) {
|
|
80
|
-
currentStep = null;
|
|
81
|
-
}
|
|
82
|
-
});
|
|
126
|
+
const index = getStepNumber(stepper, step);
|
|
127
|
+
const totalSteps = stepper.querySelectorAll(STEP_SELECTOR).length;
|
|
128
|
+
const linear = !stepper.classList.contains('micl-stepper--nonlinear');
|
|
129
|
+
const setText = (selector: string, content: string): void => {
|
|
130
|
+
stepper.querySelectorAll(selector).forEach(e => { e.textContent = content; });
|
|
131
|
+
};
|
|
83
132
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (nrChecked === 0) {
|
|
98
|
-
console.log("NOT ENGOUGH CHECKS");
|
|
133
|
+
setText('.micl-stepper__progress-current', `${index}`);
|
|
134
|
+
setText('.micl-stepper__progress-total', `${totalSteps}`);
|
|
135
|
+
|
|
136
|
+
stepper.querySelectorAll('.micl-stepper__progress-dots').forEach(dots =>
|
|
137
|
+
{
|
|
138
|
+
const fragment = document.createDocumentFragment();
|
|
139
|
+
|
|
140
|
+
dots.innerHTML = '';
|
|
141
|
+
for (let i = 1; i <= totalSteps; i++) {
|
|
142
|
+
let dot = document.createElement('span');
|
|
143
|
+
dot.classList.add('micl-stepper__progress-dot');
|
|
144
|
+
if ((linear && (i <= index)) || (!linear && (i === index))) {
|
|
145
|
+
dot.classList.add('micl-stepper__progress--done');
|
|
99
146
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
147
|
+
fragment.appendChild(dot);
|
|
148
|
+
}
|
|
149
|
+
dots.appendChild(fragment);
|
|
150
|
+
});
|
|
151
|
+
stepper.querySelectorAll(BUTTON_SELECTOR).forEach((button, i) =>
|
|
152
|
+
{
|
|
153
|
+
button.classList.toggle(
|
|
154
|
+
'micl-stepper__progress--done',
|
|
155
|
+
linear ? i + 1 <= index : i + 1 === index
|
|
156
|
+
);
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const refresh = (stepper: HTMLElement, step: HTMLElement): void =>
|
|
161
|
+
{
|
|
162
|
+
showHideActions(stepper, step);
|
|
163
|
+
showHideElements(stepper, step);
|
|
164
|
+
updateProgress(stepper, step);
|
|
103
165
|
};
|
|
104
166
|
|
|
105
167
|
return {
|
|
106
168
|
initialize: (stepper: HTMLElement): void =>
|
|
107
169
|
{
|
|
108
|
-
if (
|
|
109
|
-
!stepper.matches(stepperSelector)
|
|
110
|
-
|| stepper.dataset.miclinitialized
|
|
111
|
-
) {
|
|
170
|
+
if (!stepper.matches(stepperSelector) || stepper.dataset.miclinitialized) {
|
|
112
171
|
return;
|
|
113
172
|
}
|
|
114
173
|
stepper.dataset.miclinitialized = '1';
|
|
115
174
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
step.dataset.miclstep = `${index + 1}`;
|
|
119
|
-
});
|
|
175
|
+
const step = getSelectedStep(stepper);
|
|
176
|
+
const header = stepper.querySelector('.micl-stepper__header');
|
|
120
177
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
actions = stepper.querySelectorAll<HTMLButtonElement>(
|
|
124
|
-
'button.micl-stepper--goback,button.micl-stepper--gonext'
|
|
125
|
-
);
|
|
126
|
-
showHideActions([...actions], step);
|
|
127
|
-
step && showHideElements(stepper, step);
|
|
178
|
+
if (step) {
|
|
179
|
+
refresh(stepper, step);
|
|
128
180
|
|
|
129
|
-
|
|
181
|
+
header?.querySelectorAll<HTMLButtonElement>(
|
|
182
|
+
'button[role=tab][aria-controls]'
|
|
183
|
+
).forEach(button =>
|
|
184
|
+
{
|
|
185
|
+
button.addEventListener('click', () =>
|
|
186
|
+
{
|
|
187
|
+
if (
|
|
188
|
+
('ariaControlsElements' in Element.prototype)
|
|
189
|
+
&& button.ariaControlsElements
|
|
190
|
+
) {
|
|
191
|
+
setSelectedStep(stepper, button.ariaControlsElements[0] as HTMLElement);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
const id = button.getAttribute('aria-controls');
|
|
195
|
+
if (id) {
|
|
196
|
+
setSelectedStep(stepper, document.getElementById(id));
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
Array.from(stepper.querySelectorAll<HTMLElement>(ACTIONS_SELECTOR)).forEach(action =>
|
|
130
204
|
{
|
|
131
|
-
action.addEventListener('click', ()
|
|
205
|
+
action.addEventListener('click', function(event: Event)
|
|
132
206
|
{
|
|
133
|
-
const
|
|
134
|
-
|
|
207
|
+
const back = isBackAction(this);
|
|
208
|
+
const selectedStep = getSelectedStep(stepper);
|
|
209
|
+
|
|
210
|
+
if (
|
|
211
|
+
!selectedStep
|
|
212
|
+
|| (!back
|
|
213
|
+
&& selectedStep instanceof HTMLFieldSetElement
|
|
214
|
+
&& !form.validateFieldSet(selectedStep, true))
|
|
215
|
+
) {
|
|
216
|
+
if (!back) {
|
|
217
|
+
event.stopImmediatePropagation();
|
|
218
|
+
}
|
|
135
219
|
return;
|
|
136
220
|
}
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (sibling?.classList.contains('micl-stepper__step')) {
|
|
144
|
-
currentStep.addEventListener('transitionend', endTransitionCurrent);
|
|
145
|
-
currentStep.classList.add('micl-stepper__step--fromcurrent');
|
|
146
|
-
currentStep.offsetHeight;
|
|
147
|
-
|
|
148
|
-
sibling.addEventListener('transitionend', endTransitionCurrent);
|
|
149
|
-
sibling.classList.add('micl-stepper__step--tocurrent');
|
|
150
|
-
sibling.offsetHeight;
|
|
151
|
-
|
|
152
|
-
sibling.classList.add('micl-stepper__step--current');
|
|
153
|
-
currentStep.classList.remove('micl-stepper__step--current');
|
|
154
|
-
currentStep.offsetHeight;
|
|
155
|
-
|
|
156
|
-
showHideActions([...actions], sibling);
|
|
157
|
-
showHideElements(stepper, sibling);
|
|
221
|
+
const sibling = selectedStep[
|
|
222
|
+
back ? 'previousElementSibling' : 'nextElementSibling'
|
|
223
|
+
] as HTMLElement;
|
|
224
|
+
|
|
225
|
+
if (sibling?.classList.contains(STEP_CLASS)) {
|
|
226
|
+
goToSibling(stepper, selectedStep, sibling);
|
|
158
227
|
}
|
|
159
|
-
});
|
|
228
|
+
}, true);
|
|
160
229
|
});
|
|
230
|
+
|
|
231
|
+
if (stepper instanceof HTMLFormElement) {
|
|
232
|
+
stepper.addEventListener('submit', (event: SubmitEvent) =>
|
|
233
|
+
{
|
|
234
|
+
if (!event.submitter?.classList.contains('micl-form--dosubmit')) {
|
|
235
|
+
event.preventDefault();
|
|
236
|
+
}
|
|
237
|
+
if (!form.validateForm(stepper, true)) {
|
|
238
|
+
event.stopImmediatePropagation();
|
|
239
|
+
}
|
|
240
|
+
}, true);
|
|
241
|
+
}
|
|
161
242
|
}
|
|
162
243
|
};
|
|
163
244
|
})();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# Switch
|
|
2
|
-
This component implements the
|
|
2
|
+
This component implements the [Material Design 3 Expressive Switch](https://m3.material.io/components/switch/overview) design. Switches toggle the state of a single setting on or off.
|
|
3
3
|
|
|
4
4
|
## Basic Usage
|
|
5
5
|
|
|
@@ -18,11 +18,16 @@ Import the switch styles into your project:
|
|
|
18
18
|
@use "material-inspired-component-library/dist/switch";
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
+
Or import all MICL styles:
|
|
22
|
+
```CSS
|
|
23
|
+
@use "material-inspired-component-library/styles";
|
|
24
|
+
```
|
|
25
|
+
|
|
21
26
|
### JavaScript
|
|
22
27
|
No custom JavaScript is required for the core functionality of this component.
|
|
23
28
|
|
|
24
|
-
### Demo
|
|
25
|
-
A live example of the [Switch component](https://henkpb.github.io/micl/switch.html) is available
|
|
29
|
+
### Live Demo
|
|
30
|
+
A live example of the [Switch component](https://henkpb.github.io/micl/switch.html) is available to interact with.
|
|
26
31
|
|
|
27
32
|
## Variants
|
|
28
33
|
By default, the component displays an icon on the switch handle in both the selected and unselected state. To remove the icon in the unselected state, assign an empty string to the following CSS variable:
|
|
@@ -48,6 +48,7 @@ input[type=checkbox].micl-switch {
|
|
|
48
48
|
margin: 0;
|
|
49
49
|
border-radius: calc(var(--md-sys-switch-target-height) / 2);
|
|
50
50
|
outline: none;
|
|
51
|
+
-webkit-tap-highlight-color: transparent;
|
|
51
52
|
|
|
52
53
|
&::before {
|
|
53
54
|
content: "";
|
|
@@ -172,6 +173,7 @@ input[type=checkbox].micl-switch {
|
|
|
172
173
|
|
|
173
174
|
input[type=checkbox].micl-switch:not(:disabled) + label,
|
|
174
175
|
label:has(+ input[type=checkbox].micl-switch:not(:disabled)) {
|
|
176
|
+
-webkit-tap-highlight-color: transparent;
|
|
175
177
|
cursor: pointer;
|
|
176
178
|
}
|
|
177
179
|
input[type=checkbox].micl-switch + label,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# Text field
|
|
2
|
-
This component implements the
|
|
2
|
+
This component implements the [Material Design 3 Expressive Text field](https://m3.material.io/components/text-fields/overview) design.
|
|
3
3
|
|
|
4
4
|
## Basic Usage
|
|
5
5
|
|
|
@@ -20,6 +20,11 @@ Import the text field styles into your project:
|
|
|
20
20
|
@use "material-inspired-component-library/dist/textfield";
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
Or import all MICL styles:
|
|
24
|
+
```CSS
|
|
25
|
+
@use "material-inspired-component-library/styles";
|
|
26
|
+
```
|
|
27
|
+
|
|
23
28
|
### JavaScript
|
|
24
29
|
This component requires JavaScript for interactive features like the **character counter**:
|
|
25
30
|
|
|
@@ -29,8 +34,8 @@ import micl from "material-inspired-component-library/dist/micl";
|
|
|
29
34
|
|
|
30
35
|
This will initialize any Text field component, including those that will be added to the DOM later on.
|
|
31
36
|
|
|
32
|
-
### Demo
|
|
33
|
-
A live example of the [Text field component](https://henkpb.github.io/micl/textfield.html) is available
|
|
37
|
+
### Live Demo
|
|
38
|
+
A live example of the [Text field component](https://henkpb.github.io/micl/textfield.html) is available to interact with.
|
|
34
39
|
|
|
35
40
|
## Variants
|
|
36
41
|
The following example shows a text field with every available feature. You can include any combination of these elements. The order of elements inside the `<div>` does not change the layout.
|
|
@@ -25,14 +25,9 @@ export const selectSelector = '.micl-textfield-filled > select,.micl-textfield-o
|
|
|
25
25
|
|
|
26
26
|
export default (() =>
|
|
27
27
|
{
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
{
|
|
32
|
-
return eventTarget instanceof HTMLInputElement ||
|
|
33
|
-
eventTarget instanceof HTMLSelectElement ||
|
|
34
|
-
eventTarget instanceof HTMLTextAreaElement;
|
|
35
|
-
};
|
|
28
|
+
const isTextFieldElement = (target: EventTarget | null): target is
|
|
29
|
+
HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement =>
|
|
30
|
+
(target as Element).matches(`${textfieldSelector},${selectSelector},${textareaSelector}`);
|
|
36
31
|
|
|
37
32
|
const setCounter = (input: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement): void =>
|
|
38
33
|
{
|
|
@@ -49,26 +44,6 @@ export default (() =>
|
|
|
49
44
|
}
|
|
50
45
|
};
|
|
51
46
|
|
|
52
|
-
const handleInvalid = (
|
|
53
|
-
input: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement,
|
|
54
|
-
isValid?: boolean
|
|
55
|
-
): void => {
|
|
56
|
-
if (input.required) {
|
|
57
|
-
input.parentElement?.classList.toggle('micl-textfield--error', !isValid);
|
|
58
|
-
|
|
59
|
-
const supporting = input.parentElement?.querySelector(
|
|
60
|
-
'.micl-textfield__supporting-text'
|
|
61
|
-
) as HTMLElement;
|
|
62
|
-
|
|
63
|
-
if (supporting) {
|
|
64
|
-
if (!isValid && !('micltext' in supporting.dataset)) {
|
|
65
|
-
supporting.dataset.micltext = supporting.textContent;
|
|
66
|
-
}
|
|
67
|
-
supporting.textContent = input.validationMessage || supporting.dataset.micltext || '';
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
|
|
72
47
|
return {
|
|
73
48
|
initialize: (input: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement): void =>
|
|
74
49
|
{
|
|
@@ -84,14 +59,13 @@ export default (() =>
|
|
|
84
59
|
if (input instanceof HTMLSelectElement) {
|
|
85
60
|
input.addEventListener('mousedown', () =>
|
|
86
61
|
{
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
roomBelow = window.innerHeight - rect.bottom;
|
|
62
|
+
const rect = input.getBoundingClientRect();
|
|
63
|
+
const spaceAbove = rect.top;
|
|
64
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
91
65
|
|
|
92
66
|
!input.matches(':open') && input.style.setProperty(
|
|
93
67
|
'--md-sys-select-picker-origin',
|
|
94
|
-
|
|
68
|
+
spaceAbove > spaceBelow ? 'left bottom' : 'left top'
|
|
95
69
|
);
|
|
96
70
|
});
|
|
97
71
|
}
|
|
@@ -102,8 +76,7 @@ export default (() =>
|
|
|
102
76
|
input: (event: Event): void =>
|
|
103
77
|
{
|
|
104
78
|
if (
|
|
105
|
-
!
|
|
106
|
-
|| !event.target.matches(`${textfieldSelector},${selectSelector},${textareaSelector}`)
|
|
79
|
+
!isTextFieldElement(event.target)
|
|
107
80
|
|| !event.target.dataset.miclinitialized
|
|
108
81
|
|| event.target.disabled
|
|
109
82
|
) {
|
|
@@ -117,13 +90,7 @@ export default (() =>
|
|
|
117
90
|
delete event.target.dataset.miclvalue;
|
|
118
91
|
}
|
|
119
92
|
|
|
120
|
-
handleInvalid(event.target, true);
|
|
121
93
|
setCounter(event.target);
|
|
122
|
-
},
|
|
123
|
-
|
|
124
|
-
invalid: (event: Event): void =>
|
|
125
|
-
{
|
|
126
|
-
isRequiredType(event.target) && handleInvalid(event.target);
|
|
127
94
|
}
|
|
128
95
|
};
|
|
129
96
|
})();
|