kmaterialize 2.0.0 → 2.3.3-1.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/LICENSE +21 -21
- package/README.md +55 -91
- package/components/appbar/_navbar.old.scss +223 -0
- package/components/appbar/appbar.css +235 -0
- package/components/appbar/appbar.mjs +54 -0
- package/components/appbar/appbar.test.mjs +9 -0
- package/components/atomic/atomic.mjs +19 -0
- package/components/atomic/component.mjs +67 -0
- package/components/badge/_badges.scss +75 -0
- package/components/badge/badge.mjs +11 -0
- package/components/breadcrumb/_breadcrumb.scss +27 -0
- package/components/button/_buttons.scss +352 -0
- package/components/button/button.mjs +11 -0
- package/components/button/buttons.stories.ts +150 -0
- package/components/button/buttons.ts +282 -0
- package/components/button/examples.iso.js +18 -0
- package/components/button/fabSpec.js +65 -0
- package/components/button/test-button.mjs +16 -0
- package/components/card/_cards.scss +229 -0
- package/components/card/card.mjs +10 -0
- package/components/card/cards.ts +185 -0
- package/components/card/cardsSpec.js +269 -0
- package/components/carousel/_carousel.scss +93 -0
- package/components/carousel/_slider.scss +119 -0
- package/components/carousel/carousel.ts +693 -0
- package/components/carousel/carouselSpec.js +61 -0
- package/components/carousel/slider.ts +431 -0
- package/components/carousel/sliderSpec.js +99 -0
- package/components/checkbox/_checkboxes.scss +281 -0
- package/components/checkbox/checkbox.mdx +24 -0
- package/components/checkbox/checkbox.stories.ts +120 -0
- package/components/chip/chip.mjs +37 -0
- package/components/chip/chip.test.mjs +10 -0
- package/components/chip/chips.css +126 -0
- package/components/chip/chips.mdx +33 -0
- package/components/chip/chips.ts +440 -0
- package/components/chip/chipsSpec.js +165 -0
- package/components/chip/readme.md +323 -0
- package/components/collapsible/_collapsible.scss +82 -0
- package/components/collapsible/collapsible.ts +230 -0
- package/components/collapsible/collapsibleSpec.js +240 -0
- package/components/datepicker/_datepicker.scss +268 -0
- package/components/datepicker/datepicker.ts +1450 -0
- package/components/datepicker/datepickerSpec.js +162 -0
- package/components/dialog/_materialbox.scss +42 -0
- package/components/dialog/_modal.scss +79 -0
- package/components/dialog/materialbox.ts +446 -0
- package/components/dialog/materialboxSpec.js +37 -0
- package/components/dialog/modal.ts +111 -0
- package/components/dialog/modalSpec.js +83 -0
- package/components/dialog/readme.md +5 -0
- package/components/divider/readme.md +15 -0
- package/components/dropdown/_dropdown.scss +83 -0
- package/components/dropdown/dropdown.ts +653 -0
- package/components/dropdown/dropdownSpec.js +108 -0
- package/components/list/_collection.scss +114 -0
- package/components/list/_list.scss +6 -0
- package/components/list/list.mjs +58 -0
- package/components/list/list.test.mjs +16 -0
- package/components/loading/loading.mjs +26 -0
- package/components/loading/loading.test.mjs +10 -0
- package/components/navigation-bar/_old +582 -0
- package/components/navigation-bar/navigation-bar.mdx +20 -0
- package/components/navigation-bar/navigation-bar.stories.ts +39 -0
- package/components/navigation-drawer/_sidenav.scss +247 -0
- package/components/navigation-drawer/sidenav.ts +546 -0
- package/components/navigation-drawer/sidenavSpec.js +124 -0
- package/components/pagination/_pagination.scss +47 -0
- package/components/progress/_preloader.scss +416 -0
- package/components/radio-button/_radio-buttons.scss +112 -0
- package/components/radio-button/radio-buttons.mdx +28 -0
- package/components/radio-button/radio-buttons.stories.ts +51 -0
- package/components/search/autocomplete.ts +620 -0
- package/components/search/autocompleteSpec.js +321 -0
- package/components/slider/_range.scss +157 -0
- package/components/slider/range.ts +216 -0
- package/components/snackbar/_toast.scss +68 -0
- package/components/snackbar/toastSpec.js +132 -0
- package/components/snackbar/toasts.ts +312 -0
- package/components/switch/_switches.scss +121 -0
- package/components/tabs/_tabs.scss +171 -0
- package/components/tabs/tabs.mjs +31 -0
- package/components/tabs/tabs.ts +358 -0
- package/components/tabs/tabsSpec.js +180 -0
- package/components/textfield/_file-input.scss +41 -0
- package/components/textfield/_input-fields.scss +368 -0
- package/components/textfield/_select.scss +104 -0
- package/components/textfield/formfields.css +311 -0
- package/components/textfield/forms.ts +182 -0
- package/components/textfield/formsSpec.js +142 -0
- package/components/textfield/select.ts +472 -0
- package/components/textfield/selectSpec.js +390 -0
- package/components/textfield/textfield.mjs +29 -0
- package/components/textfield/textfield.test.mjs +10 -0
- package/components/timepicker/_timepicker.scss +362 -0
- package/components/timepicker/timepicker.ts +905 -0
- package/components/tooltip/_tooltip.scss +40 -0
- package/components/tooltip/tooltip.ts +380 -0
- package/components/tooltip/tooltipSpec.js +145 -0
- package/dist/css/materialize.colors.min.css +6 -0
- package/dist/css/materialize.css +7578 -6326
- package/dist/css/materialize.min.css +6 -13
- package/dist/css/materialize.min.css.map +1 -0
- package/dist/js/materialize.cjs.js +8410 -0
- package/dist/js/materialize.d.ts +2625 -0
- package/dist/js/materialize.js +8415 -12374
- package/dist/js/materialize.min.js +6 -6
- package/dist/js/materialize.mjs +8382 -0
- package/package.json +82 -47
- package/sass/_colors.scss +417 -0
- package/sass/_global.scss +490 -0
- package/sass/_grid.scss +172 -0
- package/sass/_table_of_contents.scss +28 -0
- package/sass/_tapTarget.scss +102 -0
- package/sass/_typography.scss +58 -0
- package/sass/_variables.scss +56 -0
- package/sass/materialize.scss +51 -0
- package/sass/mixins.module.scss +168 -0
- package/extras/noUiSlider/nouislider.css +0 -406
- package/extras/noUiSlider/nouislider.js +0 -2147
- package/extras/noUiSlider/nouislider.min.js +0 -1
- package/js/anime.min.js +0 -34
- package/js/autocomplete.js +0 -448
- package/js/buttons.js +0 -354
- package/js/cards.js +0 -40
- package/js/carousel.js +0 -717
- package/js/cash.js +0 -960
- package/js/characterCounter.js +0 -136
- package/js/chips.js +0 -481
- package/js/collapsible.js +0 -275
- package/js/component.js +0 -44
- package/js/datepicker.js +0 -975
- package/js/dropdown.js +0 -635
- package/js/forms.js +0 -275
- package/js/global.js +0 -444
- package/js/materialbox.js +0 -453
- package/js/modal.js +0 -382
- package/js/parallax.js +0 -138
- package/js/pushpin.js +0 -148
- package/js/range.js +0 -263
- package/js/scrollspy.js +0 -295
- package/js/select.js +0 -450
- package/js/sidenav.js +0 -580
- package/js/slider.js +0 -359
- package/js/tabs.js +0 -402
- package/js/tapTarget.js +0 -314
- package/js/timepicker.js +0 -647
- package/js/toasts.js +0 -310
- package/js/tooltip.js +0 -303
- package/js/waves.js +0 -335
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
@use '../../sass/variables' as *;
|
|
2
|
+
@use '../../sass/mixins.module.scss' as *;
|
|
3
|
+
|
|
4
|
+
.card-panel {
|
|
5
|
+
transition: box-shadow .25s;
|
|
6
|
+
padding: 24px;
|
|
7
|
+
margin: $element-top-margin 0 $element-bottom-margin 0;
|
|
8
|
+
border-radius: 12px;
|
|
9
|
+
@extend .z-depth-1;
|
|
10
|
+
background-color: var(--md-sys-color-surface);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.card {
|
|
14
|
+
--background-color: color-mix(in srgb, var(--md-sys-color-surface), var(--md-sys-color-surface-tint) 17%);
|
|
15
|
+
|
|
16
|
+
position: relative;
|
|
17
|
+
//margin: $element-top-margin 0 $element-bottom-margin 0;
|
|
18
|
+
background-color: var(--background-color);
|
|
19
|
+
transition: box-shadow .25s;
|
|
20
|
+
border-radius: 12px;
|
|
21
|
+
@extend .z-depth-1;
|
|
22
|
+
|
|
23
|
+
.card-title {
|
|
24
|
+
font-size: 24px;
|
|
25
|
+
font-weight: 300;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Card Sizes
|
|
29
|
+
&.small, &.medium, &.large {
|
|
30
|
+
position: relative;
|
|
31
|
+
|
|
32
|
+
.card-image {
|
|
33
|
+
max-height: 60%;
|
|
34
|
+
overflow: hidden;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.card-image + .card-content {
|
|
38
|
+
max-height: 40%;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.card-content {
|
|
42
|
+
max-height: 100%;
|
|
43
|
+
overflow: hidden;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.card-action {
|
|
47
|
+
position: absolute;
|
|
48
|
+
bottom: 0;
|
|
49
|
+
left: 0;
|
|
50
|
+
right: 0;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&.small {
|
|
55
|
+
height: 300px;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
&.medium {
|
|
59
|
+
height: 400px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
&.large {
|
|
63
|
+
height: 500px;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Horizontal Cards
|
|
67
|
+
&.horizontal {
|
|
68
|
+
display: flex;
|
|
69
|
+
|
|
70
|
+
&.small, &.medium, &.large {
|
|
71
|
+
.card-image {
|
|
72
|
+
height: 100%;
|
|
73
|
+
max-height: none;
|
|
74
|
+
overflow: visible;
|
|
75
|
+
|
|
76
|
+
img {
|
|
77
|
+
height: 100%;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.card-image {
|
|
83
|
+
max-width: 50%;
|
|
84
|
+
|
|
85
|
+
img {
|
|
86
|
+
border-radius: 2px 0 0 2px;
|
|
87
|
+
max-width: 100%;
|
|
88
|
+
width: auto;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.card-stacked {
|
|
93
|
+
display: flex;
|
|
94
|
+
flex-direction: column;
|
|
95
|
+
flex: 1;
|
|
96
|
+
position: relative;
|
|
97
|
+
|
|
98
|
+
.card-content {
|
|
99
|
+
flex-grow: 1;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Sticky Action Section
|
|
105
|
+
&.sticky-action {
|
|
106
|
+
.card-action {
|
|
107
|
+
z-index: 2;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.card-reveal {
|
|
111
|
+
z-index: 1;
|
|
112
|
+
padding-bottom: 64px;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.card-image {
|
|
117
|
+
position: relative;
|
|
118
|
+
|
|
119
|
+
// Image background for content
|
|
120
|
+
img {
|
|
121
|
+
display: block;
|
|
122
|
+
border-radius: 2px 2px 0 0;
|
|
123
|
+
position: relative;
|
|
124
|
+
left: 0;
|
|
125
|
+
right: 0;
|
|
126
|
+
top: 0;
|
|
127
|
+
bottom: 0;
|
|
128
|
+
width: 100%;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.card-title {
|
|
132
|
+
color: var(--md-sys-color-surface);
|
|
133
|
+
position: absolute;
|
|
134
|
+
bottom: 0;
|
|
135
|
+
left: 0;
|
|
136
|
+
max-width: 100%;
|
|
137
|
+
padding: 24px;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.activator {
|
|
141
|
+
position: absolute;
|
|
142
|
+
left: 0;
|
|
143
|
+
right: 0;
|
|
144
|
+
top:0;
|
|
145
|
+
bottom: 0;
|
|
146
|
+
cursor: pointer;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
img.activator {
|
|
150
|
+
position: relative;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.card-content {
|
|
155
|
+
padding: 24px;
|
|
156
|
+
border-radius: 0 0 2px 2px;
|
|
157
|
+
|
|
158
|
+
p {
|
|
159
|
+
margin: 0;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.card-title {
|
|
163
|
+
display: block;
|
|
164
|
+
line-height: 32px;
|
|
165
|
+
margin-bottom: 8px;
|
|
166
|
+
|
|
167
|
+
i {
|
|
168
|
+
line-height: 32px;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
&.activator {
|
|
172
|
+
cursor: pointer;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.card-action {
|
|
178
|
+
padding: 0 1.6rem;
|
|
179
|
+
|
|
180
|
+
&:last-child {
|
|
181
|
+
border-radius: 0 0 2px 2px;
|
|
182
|
+
}
|
|
183
|
+
// Replaced card links with buttons (Accessibility, @see https://github.com/materializecss/materialize/issues/565)
|
|
184
|
+
a {
|
|
185
|
+
@include btn(
|
|
186
|
+
var(--btn-height),
|
|
187
|
+
var(--btn-border-radius),
|
|
188
|
+
var(--btn-padding),
|
|
189
|
+
var(--btn-padding),
|
|
190
|
+
var(--btn-font-size)
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
&:first-child {
|
|
194
|
+
margin-left: -1.6rem;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
&:last-child {
|
|
198
|
+
margin-right: -1.6rem;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.btn {
|
|
203
|
+
&.filled,
|
|
204
|
+
&.tonal,
|
|
205
|
+
&.elevated,
|
|
206
|
+
&.outlined {
|
|
207
|
+
margin: 0 .26rem 1.6rem 0;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.card-reveal {
|
|
213
|
+
padding: 24px;
|
|
214
|
+
position: absolute;
|
|
215
|
+
background-color: var(--md-sys-color-surface);
|
|
216
|
+
width: 100%;
|
|
217
|
+
overflow-y: auto;
|
|
218
|
+
left: 0;
|
|
219
|
+
top: 100%;
|
|
220
|
+
height: 100%;
|
|
221
|
+
z-index: 3;
|
|
222
|
+
display: none;
|
|
223
|
+
|
|
224
|
+
.card-title {
|
|
225
|
+
cursor: pointer;
|
|
226
|
+
display: block;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { Utils } from '../../src/utils';
|
|
2
|
+
import { Component, BaseOptions, InitElements, MElement, Openable } from '../../src/component';
|
|
3
|
+
|
|
4
|
+
interface CardsOptions extends BaseOptions {
|
|
5
|
+
onOpen: (el: Element) => void;
|
|
6
|
+
onClose: (el: Element) => void;
|
|
7
|
+
inDuration: number;
|
|
8
|
+
outDuration: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const _defaults: CardsOptions = {
|
|
12
|
+
onOpen: null,
|
|
13
|
+
onClose: null,
|
|
14
|
+
inDuration: 225,
|
|
15
|
+
outDuration: 300
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
class Cards extends Component<CardsOptions> implements Openable {
|
|
19
|
+
readonly #cardReveal: HTMLElement | null;
|
|
20
|
+
readonly #initialOverflow: string;
|
|
21
|
+
#activators: HTMLElement[] | null;
|
|
22
|
+
#cardRevealClose: HTMLElement | null;
|
|
23
|
+
isOpen: boolean = false;
|
|
24
|
+
|
|
25
|
+
constructor(el: HTMLElement, options: Partial<CardsOptions>) {
|
|
26
|
+
super(el, options, Cards);
|
|
27
|
+
this.el['M_Cards'] = this;
|
|
28
|
+
this.options = {
|
|
29
|
+
...Cards.defaults,
|
|
30
|
+
...options
|
|
31
|
+
};
|
|
32
|
+
this.#activators = [];
|
|
33
|
+
this.#cardReveal = this.el.querySelector('.card-reveal');
|
|
34
|
+
if (this.#cardReveal) {
|
|
35
|
+
this.#initialOverflow = getComputedStyle(this.el).overflow;
|
|
36
|
+
this.#activators = Array.from(this.el.querySelectorAll('.activator'));
|
|
37
|
+
this.#activators.forEach((el: HTMLElement) => {
|
|
38
|
+
if (el) el.tabIndex = 0;
|
|
39
|
+
});
|
|
40
|
+
this.#cardRevealClose = this.#cardReveal?.querySelector('.card-title');
|
|
41
|
+
if (this.#cardRevealClose) this.#cardRevealClose.tabIndex = -1;
|
|
42
|
+
this.#cardReveal.ariaExpanded = 'false';
|
|
43
|
+
this.#setupEventHandlers();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static get defaults(): CardsOptions {
|
|
48
|
+
return _defaults;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Initializes instance of Cards.
|
|
53
|
+
* @param el HTML element.
|
|
54
|
+
* @param options Component options.
|
|
55
|
+
*/
|
|
56
|
+
static init(el: HTMLElement, options?: Partial<CardsOptions>): Cards;
|
|
57
|
+
/**
|
|
58
|
+
* Initializes instances of Cards.
|
|
59
|
+
* @param els HTML elements.
|
|
60
|
+
* @param options Component options.
|
|
61
|
+
*/
|
|
62
|
+
static init(els: InitElements<MElement>, options?: Partial<CardsOptions>): Cards[];
|
|
63
|
+
/**
|
|
64
|
+
* Initializes instances of Cards.
|
|
65
|
+
* @param els HTML elements.
|
|
66
|
+
* @param options Component options.
|
|
67
|
+
*/
|
|
68
|
+
static init(
|
|
69
|
+
els: HTMLElement | InitElements<MElement>,
|
|
70
|
+
options?: Partial<CardsOptions>
|
|
71
|
+
): Cards | Cards[] {
|
|
72
|
+
return super.init(els, options, Cards);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static getInstance(el: HTMLElement): Cards {
|
|
76
|
+
return el['M_Cards'];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* {@inheritDoc}
|
|
81
|
+
*/
|
|
82
|
+
destroy() {
|
|
83
|
+
this.#removeEventHandlers();
|
|
84
|
+
this.#activators = [];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
#setupEventHandlers = () => {
|
|
88
|
+
this.#activators.forEach((el: HTMLElement) => {
|
|
89
|
+
el.addEventListener('click', this.#handleClickInteraction);
|
|
90
|
+
el.addEventListener('keypress', this.#handleKeypressEvent);
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
#removeEventHandlers = () => {
|
|
95
|
+
this.#activators.forEach((el: HTMLElement) => {
|
|
96
|
+
el.removeEventListener('click', this.#handleClickInteraction);
|
|
97
|
+
el.removeEventListener('keypress', this.#handleKeypressEvent);
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
#handleClickInteraction = () => {
|
|
102
|
+
this.#handleRevealEvent();
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
#handleKeypressEvent: (e: KeyboardEvent) => void = (e: KeyboardEvent) => {
|
|
106
|
+
if (Utils.keys.ENTER.includes(e.key)) {
|
|
107
|
+
this.#handleRevealEvent();
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
#handleRevealEvent = () => {
|
|
112
|
+
this.#activators.forEach((el: HTMLElement) => (el.tabIndex = -1)); // Reveal Card
|
|
113
|
+
this.open();
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
#setupRevealCloseEventHandlers = () => {
|
|
117
|
+
this.#cardRevealClose.addEventListener('click', this.close);
|
|
118
|
+
this.#cardRevealClose.addEventListener('keypress', this.#handleKeypressCloseEvent);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
#removeRevealCloseEventHandlers = () => {
|
|
122
|
+
this.#cardRevealClose.addEventListener('click', this.close);
|
|
123
|
+
this.#cardRevealClose.addEventListener('keypress', this.#handleKeypressCloseEvent);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
#handleKeypressCloseEvent: (e: KeyboardEvent) => void = (e: KeyboardEvent) => {
|
|
127
|
+
if (Utils.keys.ENTER.includes(e.key)) {
|
|
128
|
+
this.close();
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Show card reveal.
|
|
134
|
+
*/
|
|
135
|
+
open: () => void = () => {
|
|
136
|
+
if (this.isOpen) return;
|
|
137
|
+
this.isOpen = true;
|
|
138
|
+
this.el.style.overflow = 'hidden';
|
|
139
|
+
this.#cardReveal.style.display = 'block';
|
|
140
|
+
this.#cardReveal.ariaExpanded = 'true';
|
|
141
|
+
this.#cardRevealClose.tabIndex = 0;
|
|
142
|
+
setTimeout(() => {
|
|
143
|
+
this.#cardReveal.style.transition = `transform ${this.options.outDuration}ms ease`; //easeInOutQuad
|
|
144
|
+
this.#cardReveal.style.transform = 'translateY(-100%)';
|
|
145
|
+
}, 1);
|
|
146
|
+
if (typeof this.options.onOpen === 'function') {
|
|
147
|
+
this.options.onOpen.call(this);
|
|
148
|
+
}
|
|
149
|
+
this.#setupRevealCloseEventHandlers();
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Hide card reveal.
|
|
154
|
+
*/
|
|
155
|
+
close: () => void = () => {
|
|
156
|
+
if (!this.isOpen) return;
|
|
157
|
+
this.isOpen = false;
|
|
158
|
+
this.#cardReveal.style.transition = `transform ${this.options.inDuration}ms ease`; //easeInOutQuad
|
|
159
|
+
this.#cardReveal.style.transform = 'translateY(0)';
|
|
160
|
+
setTimeout(() => {
|
|
161
|
+
this.#cardReveal.style.display = 'none';
|
|
162
|
+
this.#cardReveal.ariaExpanded = 'false';
|
|
163
|
+
this.#activators.forEach((el: HTMLElement) => (el.tabIndex = 0));
|
|
164
|
+
this.#cardRevealClose.tabIndex = -1;
|
|
165
|
+
this.el.style.overflow = this.#initialOverflow;
|
|
166
|
+
}, this.options.inDuration);
|
|
167
|
+
if (typeof this.options.onClose === 'function') {
|
|
168
|
+
this.options.onClose.call(this);
|
|
169
|
+
}
|
|
170
|
+
this.#removeRevealCloseEventHandlers();
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
static Init() {
|
|
174
|
+
if (typeof document !== 'undefined')
|
|
175
|
+
// Handle initialization of static cards.
|
|
176
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
177
|
+
const cards = document.querySelectorAll('.card');
|
|
178
|
+
cards.forEach((el) => {
|
|
179
|
+
if (el && el['M_Card'] == undefined) this.init(el as HTMLElement);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export { Cards, CardsOptions };
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
describe('Cards', () => {
|
|
2
|
+
const fixture = `
|
|
3
|
+
<div class="row">
|
|
4
|
+
<div class="col s12 m6">
|
|
5
|
+
<div class="card reveal">
|
|
6
|
+
<div class="card-image waves-effect waves-block waves-light">
|
|
7
|
+
<img
|
|
8
|
+
class="activator"
|
|
9
|
+
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
|
|
10
|
+
>
|
|
11
|
+
</div>
|
|
12
|
+
<div class="card-content">
|
|
13
|
+
<span class="card-title activator grey-text text-darken-4">
|
|
14
|
+
Card Title
|
|
15
|
+
<i class="material-icons right">more_vert</i>
|
|
16
|
+
</span>
|
|
17
|
+
<p><a href="#">This is a link</a></p>
|
|
18
|
+
</div>
|
|
19
|
+
<div class="card-reveal">
|
|
20
|
+
<span class="card-title grey-text text-darken-4">
|
|
21
|
+
Card Title
|
|
22
|
+
<i class="material-icons right">close</i>
|
|
23
|
+
</span>
|
|
24
|
+
<p>
|
|
25
|
+
Here is some more information about this product that is only revealed once clicked on.
|
|
26
|
+
</p>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<div class="col s12 m6">
|
|
32
|
+
<div class="card image">
|
|
33
|
+
<div class="card-image">
|
|
34
|
+
<img
|
|
35
|
+
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
|
|
36
|
+
>
|
|
37
|
+
<span class="card-title">Card Title</span>
|
|
38
|
+
</div>
|
|
39
|
+
<div class="card-content">
|
|
40
|
+
<p>
|
|
41
|
+
I am a very simple card. I am good at containing small bits of information.
|
|
42
|
+
I am convenient because I require little markup to use effectively.
|
|
43
|
+
</p>
|
|
44
|
+
</div>
|
|
45
|
+
<div class="card-action">
|
|
46
|
+
<a href="#">This is a link</a>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<div class="row">
|
|
53
|
+
<div class="col s4">
|
|
54
|
+
<div class="card small">
|
|
55
|
+
<div class="card-image">
|
|
56
|
+
<img
|
|
57
|
+
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
|
|
58
|
+
>
|
|
59
|
+
<span class="card-title">Card Title</span>
|
|
60
|
+
</div>
|
|
61
|
+
<div class="card-content">
|
|
62
|
+
<p>
|
|
63
|
+
I am a very simple card. I am good at containing small bits of information.
|
|
64
|
+
I am convenient because I require little markup to use effectively.
|
|
65
|
+
</p>
|
|
66
|
+
</div>
|
|
67
|
+
<div class="card-action">
|
|
68
|
+
<a href="#">This is a link</a>
|
|
69
|
+
<a href="#">This is a link</a>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<div class="col s4">
|
|
75
|
+
<div class="card medium">
|
|
76
|
+
<div class="card-image">
|
|
77
|
+
<img
|
|
78
|
+
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
|
|
79
|
+
>
|
|
80
|
+
<span class="card-title">Card Title</span>
|
|
81
|
+
</div>
|
|
82
|
+
<div class="card-content">
|
|
83
|
+
<p>
|
|
84
|
+
I am a very simple card. I am good at containing small bits of information.
|
|
85
|
+
I am convenient because I require little markup to use effectively.
|
|
86
|
+
</p>
|
|
87
|
+
</div>
|
|
88
|
+
<div class="card-action">
|
|
89
|
+
<a href="#">This is a link</a>
|
|
90
|
+
<a href="#">This is a link</a>
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
<div class="col s4">
|
|
96
|
+
<div class="card large">
|
|
97
|
+
<div class="card-image">
|
|
98
|
+
<img
|
|
99
|
+
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
|
|
100
|
+
>
|
|
101
|
+
<span class="card-title">Card Title</span>
|
|
102
|
+
</div>
|
|
103
|
+
<div class="card-content">
|
|
104
|
+
<p>
|
|
105
|
+
I am a very simple card. I am good at containing small bits of information.
|
|
106
|
+
I am convenient because I require little markup to use effectively.
|
|
107
|
+
</p>
|
|
108
|
+
</div>
|
|
109
|
+
<div class="card-action">
|
|
110
|
+
<a href="#">This is a link</a>
|
|
111
|
+
<a href="#">This is a link</a>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
`;
|
|
117
|
+
|
|
118
|
+
const roundedRect = (el) => {
|
|
119
|
+
const rect = el.getBoundingClientRect();
|
|
120
|
+
return {
|
|
121
|
+
top: Math.round(rect.top),
|
|
122
|
+
left: Math.round(rect.left),
|
|
123
|
+
width: Math.round(rect.width),
|
|
124
|
+
height: Math.round(rect.height),
|
|
125
|
+
right: Math.round(rect.right),
|
|
126
|
+
bottom: Math.round(rect.bottom)
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
beforeEach(() => {
|
|
131
|
+
XloadHtml(fixture);
|
|
132
|
+
M.Cards.init(document.querySelectorAll('.card'));
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
afterEach(() => {
|
|
136
|
+
XunloadFixtures();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe('reveal cards', () => {
|
|
140
|
+
let revealCard;
|
|
141
|
+
let revealDiv;
|
|
142
|
+
|
|
143
|
+
beforeEach(() => {
|
|
144
|
+
revealCard = document.querySelector('.card.reveal');
|
|
145
|
+
revealDiv = revealCard.querySelector('.card-reveal');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should have a hidden card-reveal initially', () => {
|
|
149
|
+
expect(revealDiv).toBeHidden('reveal div should be hidden initially');
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('should show card-reveal after clicking an activator', (done) => {
|
|
153
|
+
const activator = revealCard.querySelector('.activator');
|
|
154
|
+
|
|
155
|
+
click(activator);
|
|
156
|
+
|
|
157
|
+
setTimeout(() => {
|
|
158
|
+
expect(revealDiv).toBeVisible('reveal did not appear after activator was clicked.');
|
|
159
|
+
done();
|
|
160
|
+
}, 500);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('should size and position card-reveal to cover the card when opened', (done) => {
|
|
164
|
+
const activator = revealCard.querySelector('.activator');
|
|
165
|
+
|
|
166
|
+
click(activator);
|
|
167
|
+
|
|
168
|
+
setTimeout(() => {
|
|
169
|
+
const revealRect = roundedRect(revealDiv);
|
|
170
|
+
const cardRect = roundedRect(revealCard);
|
|
171
|
+
|
|
172
|
+
expect(revealDiv).toBeVisible('reveal did not appear after activator was clicked.');
|
|
173
|
+
expect(revealRect.width).toEqual(cardRect.width, 'reveal width should match card width');
|
|
174
|
+
expect(revealRect.height).toEqual(
|
|
175
|
+
cardRect.height,
|
|
176
|
+
'reveal height should match card height'
|
|
177
|
+
);
|
|
178
|
+
expect(revealRect.top).toEqual(cardRect.top, 'reveal top should align with card top');
|
|
179
|
+
expect(revealRect.left).toEqual(cardRect.left, 'reveal left should align with card left');
|
|
180
|
+
|
|
181
|
+
done();
|
|
182
|
+
}, 500);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
describe('image cards', () => {
|
|
187
|
+
let imageCard;
|
|
188
|
+
let image;
|
|
189
|
+
|
|
190
|
+
beforeEach(() => {
|
|
191
|
+
imageCard = document.querySelector('.card.image');
|
|
192
|
+
image = imageCard.querySelector('.card-image > img');
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('should have an image that fills the full width of the card', () => {
|
|
196
|
+
const imageRect = roundedRect(image);
|
|
197
|
+
const cardRect = roundedRect(imageCard);
|
|
198
|
+
|
|
199
|
+
expect(imageRect.width).toEqual(cardRect.width, 'image does not fill width of card');
|
|
200
|
+
expect(imageRect.top).toEqual(cardRect.top, 'image top should align with card top');
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
describe('sized cards', () => {
|
|
205
|
+
const expectSizedCardLayout = ({
|
|
206
|
+
card,
|
|
207
|
+
expectedHeight,
|
|
208
|
+
maxImageHeight,
|
|
209
|
+
maxContentHeight,
|
|
210
|
+
sizeName
|
|
211
|
+
}) => {
|
|
212
|
+
const cardImage = card.querySelector('.card-image');
|
|
213
|
+
const cardContent = card.querySelector('.card-content');
|
|
214
|
+
const cardAction = card.querySelector('.card-action');
|
|
215
|
+
|
|
216
|
+
const cardRect = roundedRect(card);
|
|
217
|
+
const imageRect = roundedRect(cardImage);
|
|
218
|
+
const contentRect = roundedRect(cardContent);
|
|
219
|
+
const actionRect = roundedRect(cardAction);
|
|
220
|
+
|
|
221
|
+
expect(cardRect.height).toEqual(
|
|
222
|
+
expectedHeight,
|
|
223
|
+
`${sizeName} card should be ${expectedHeight}px high`
|
|
224
|
+
);
|
|
225
|
+
expect(imageRect.height).toBeLessThan(
|
|
226
|
+
maxImageHeight + 1,
|
|
227
|
+
`${sizeName} image should be <= ${maxImageHeight}px high`
|
|
228
|
+
);
|
|
229
|
+
expect(contentRect.height).toBeLessThan(
|
|
230
|
+
maxContentHeight + 1,
|
|
231
|
+
`${sizeName} content should be <= ${maxContentHeight}px high`
|
|
232
|
+
);
|
|
233
|
+
expect(actionRect.bottom).toEqual(
|
|
234
|
+
cardRect.bottom,
|
|
235
|
+
`${sizeName} action should be at bottom of card`
|
|
236
|
+
);
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
it('should have small card dimensions', () => {
|
|
240
|
+
expectSizedCardLayout({
|
|
241
|
+
card: document.querySelector('.card.small'),
|
|
242
|
+
expectedHeight: 300,
|
|
243
|
+
maxImageHeight: 180,
|
|
244
|
+
maxContentHeight: 120,
|
|
245
|
+
sizeName: 'small'
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('should have medium card dimensions', () => {
|
|
250
|
+
expectSizedCardLayout({
|
|
251
|
+
card: document.querySelector('.card.medium'),
|
|
252
|
+
expectedHeight: 400,
|
|
253
|
+
maxImageHeight: 240,
|
|
254
|
+
maxContentHeight: 160,
|
|
255
|
+
sizeName: 'medium'
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('should have large card dimensions', () => {
|
|
260
|
+
expectSizedCardLayout({
|
|
261
|
+
card: document.querySelector('.card.large'),
|
|
262
|
+
expectedHeight: 500,
|
|
263
|
+
maxImageHeight: 300,
|
|
264
|
+
maxContentHeight: 200,
|
|
265
|
+
sizeName: 'large'
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
});
|