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.
Files changed (150) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +55 -91
  3. package/components/appbar/_navbar.old.scss +223 -0
  4. package/components/appbar/appbar.css +235 -0
  5. package/components/appbar/appbar.mjs +54 -0
  6. package/components/appbar/appbar.test.mjs +9 -0
  7. package/components/atomic/atomic.mjs +19 -0
  8. package/components/atomic/component.mjs +67 -0
  9. package/components/badge/_badges.scss +75 -0
  10. package/components/badge/badge.mjs +11 -0
  11. package/components/breadcrumb/_breadcrumb.scss +27 -0
  12. package/components/button/_buttons.scss +352 -0
  13. package/components/button/button.mjs +11 -0
  14. package/components/button/buttons.stories.ts +150 -0
  15. package/components/button/buttons.ts +282 -0
  16. package/components/button/examples.iso.js +18 -0
  17. package/components/button/fabSpec.js +65 -0
  18. package/components/button/test-button.mjs +16 -0
  19. package/components/card/_cards.scss +229 -0
  20. package/components/card/card.mjs +10 -0
  21. package/components/card/cards.ts +185 -0
  22. package/components/card/cardsSpec.js +269 -0
  23. package/components/carousel/_carousel.scss +93 -0
  24. package/components/carousel/_slider.scss +119 -0
  25. package/components/carousel/carousel.ts +693 -0
  26. package/components/carousel/carouselSpec.js +61 -0
  27. package/components/carousel/slider.ts +431 -0
  28. package/components/carousel/sliderSpec.js +99 -0
  29. package/components/checkbox/_checkboxes.scss +281 -0
  30. package/components/checkbox/checkbox.mdx +24 -0
  31. package/components/checkbox/checkbox.stories.ts +120 -0
  32. package/components/chip/chip.mjs +37 -0
  33. package/components/chip/chip.test.mjs +10 -0
  34. package/components/chip/chips.css +126 -0
  35. package/components/chip/chips.mdx +33 -0
  36. package/components/chip/chips.ts +440 -0
  37. package/components/chip/chipsSpec.js +165 -0
  38. package/components/chip/readme.md +323 -0
  39. package/components/collapsible/_collapsible.scss +82 -0
  40. package/components/collapsible/collapsible.ts +230 -0
  41. package/components/collapsible/collapsibleSpec.js +240 -0
  42. package/components/datepicker/_datepicker.scss +268 -0
  43. package/components/datepicker/datepicker.ts +1450 -0
  44. package/components/datepicker/datepickerSpec.js +162 -0
  45. package/components/dialog/_materialbox.scss +42 -0
  46. package/components/dialog/_modal.scss +79 -0
  47. package/components/dialog/materialbox.ts +446 -0
  48. package/components/dialog/materialboxSpec.js +37 -0
  49. package/components/dialog/modal.ts +111 -0
  50. package/components/dialog/modalSpec.js +83 -0
  51. package/components/dialog/readme.md +5 -0
  52. package/components/divider/readme.md +15 -0
  53. package/components/dropdown/_dropdown.scss +83 -0
  54. package/components/dropdown/dropdown.ts +653 -0
  55. package/components/dropdown/dropdownSpec.js +108 -0
  56. package/components/list/_collection.scss +114 -0
  57. package/components/list/_list.scss +6 -0
  58. package/components/list/list.mjs +58 -0
  59. package/components/list/list.test.mjs +16 -0
  60. package/components/loading/loading.mjs +26 -0
  61. package/components/loading/loading.test.mjs +10 -0
  62. package/components/navigation-bar/_old +582 -0
  63. package/components/navigation-bar/navigation-bar.mdx +20 -0
  64. package/components/navigation-bar/navigation-bar.stories.ts +39 -0
  65. package/components/navigation-drawer/_sidenav.scss +247 -0
  66. package/components/navigation-drawer/sidenav.ts +546 -0
  67. package/components/navigation-drawer/sidenavSpec.js +124 -0
  68. package/components/pagination/_pagination.scss +47 -0
  69. package/components/progress/_preloader.scss +416 -0
  70. package/components/radio-button/_radio-buttons.scss +112 -0
  71. package/components/radio-button/radio-buttons.mdx +28 -0
  72. package/components/radio-button/radio-buttons.stories.ts +51 -0
  73. package/components/search/autocomplete.ts +620 -0
  74. package/components/search/autocompleteSpec.js +321 -0
  75. package/components/slider/_range.scss +157 -0
  76. package/components/slider/range.ts +216 -0
  77. package/components/snackbar/_toast.scss +68 -0
  78. package/components/snackbar/toastSpec.js +132 -0
  79. package/components/snackbar/toasts.ts +312 -0
  80. package/components/switch/_switches.scss +121 -0
  81. package/components/tabs/_tabs.scss +171 -0
  82. package/components/tabs/tabs.mjs +31 -0
  83. package/components/tabs/tabs.ts +358 -0
  84. package/components/tabs/tabsSpec.js +180 -0
  85. package/components/textfield/_file-input.scss +41 -0
  86. package/components/textfield/_input-fields.scss +368 -0
  87. package/components/textfield/_select.scss +104 -0
  88. package/components/textfield/formfields.css +311 -0
  89. package/components/textfield/forms.ts +182 -0
  90. package/components/textfield/formsSpec.js +142 -0
  91. package/components/textfield/select.ts +472 -0
  92. package/components/textfield/selectSpec.js +390 -0
  93. package/components/textfield/textfield.mjs +29 -0
  94. package/components/textfield/textfield.test.mjs +10 -0
  95. package/components/timepicker/_timepicker.scss +362 -0
  96. package/components/timepicker/timepicker.ts +905 -0
  97. package/components/tooltip/_tooltip.scss +40 -0
  98. package/components/tooltip/tooltip.ts +380 -0
  99. package/components/tooltip/tooltipSpec.js +145 -0
  100. package/dist/css/materialize.colors.min.css +6 -0
  101. package/dist/css/materialize.css +7578 -6326
  102. package/dist/css/materialize.min.css +6 -13
  103. package/dist/css/materialize.min.css.map +1 -0
  104. package/dist/js/materialize.cjs.js +8410 -0
  105. package/dist/js/materialize.d.ts +2625 -0
  106. package/dist/js/materialize.js +8415 -12374
  107. package/dist/js/materialize.min.js +6 -6
  108. package/dist/js/materialize.mjs +8382 -0
  109. package/package.json +82 -47
  110. package/sass/_colors.scss +417 -0
  111. package/sass/_global.scss +490 -0
  112. package/sass/_grid.scss +172 -0
  113. package/sass/_table_of_contents.scss +28 -0
  114. package/sass/_tapTarget.scss +102 -0
  115. package/sass/_typography.scss +58 -0
  116. package/sass/_variables.scss +56 -0
  117. package/sass/materialize.scss +51 -0
  118. package/sass/mixins.module.scss +168 -0
  119. package/extras/noUiSlider/nouislider.css +0 -406
  120. package/extras/noUiSlider/nouislider.js +0 -2147
  121. package/extras/noUiSlider/nouislider.min.js +0 -1
  122. package/js/anime.min.js +0 -34
  123. package/js/autocomplete.js +0 -448
  124. package/js/buttons.js +0 -354
  125. package/js/cards.js +0 -40
  126. package/js/carousel.js +0 -717
  127. package/js/cash.js +0 -960
  128. package/js/characterCounter.js +0 -136
  129. package/js/chips.js +0 -481
  130. package/js/collapsible.js +0 -275
  131. package/js/component.js +0 -44
  132. package/js/datepicker.js +0 -975
  133. package/js/dropdown.js +0 -635
  134. package/js/forms.js +0 -275
  135. package/js/global.js +0 -444
  136. package/js/materialbox.js +0 -453
  137. package/js/modal.js +0 -382
  138. package/js/parallax.js +0 -138
  139. package/js/pushpin.js +0 -148
  140. package/js/range.js +0 -263
  141. package/js/scrollspy.js +0 -295
  142. package/js/select.js +0 -450
  143. package/js/sidenav.js +0 -580
  144. package/js/slider.js +0 -359
  145. package/js/tabs.js +0 -402
  146. package/js/tapTarget.js +0 -314
  147. package/js/timepicker.js +0 -647
  148. package/js/toasts.js +0 -310
  149. package/js/tooltip.js +0 -303
  150. 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,10 @@
1
+ import { Component } from '../atomic/component.mjs';
2
+
3
+ class Card extends Component {
4
+ constructor(options) {
5
+ super(options);
6
+ this.addClassname('card');
7
+ }
8
+ }
9
+
10
+ export { Card };
@@ -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
+ });