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,323 @@
|
|
|
1
|
+
# Chips
|
|
2
|
+
|
|
3
|
+
Chips can be used to represent small blocks of information. They are most commonly used either for contacts or for tags.
|
|
4
|
+
|
|
5
|
+
<!-- component -->
|
|
6
|
+
<div class="chip">
|
|
7
|
+
<img src="images/yuna.jpg" alt="Contact Person"> Jane Doe
|
|
8
|
+
</div>
|
|
9
|
+
<div class="chip">
|
|
10
|
+
Tag
|
|
11
|
+
<i class="close material-icons">close</i>
|
|
12
|
+
</div>
|
|
13
|
+
<div class="chip">
|
|
14
|
+
<i class="material-icons">check</i>
|
|
15
|
+
Filter
|
|
16
|
+
<i class="close material-icons">close</i>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="chip outlined">Information</div>
|
|
19
|
+
<div class="chip outlined">
|
|
20
|
+
<i class="material-icons">check</i>
|
|
21
|
+
Filter
|
|
22
|
+
<i class="close material-icons">close</i>
|
|
23
|
+
</div>
|
|
24
|
+
<!-- /component -->
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<div class="chip">
|
|
28
|
+
<img src="images/yuna.jpg" alt="Contact Person"> Jane Doe
|
|
29
|
+
</div>
|
|
30
|
+
<div class="chip">
|
|
31
|
+
Tag
|
|
32
|
+
<i class="close material-icons">close</i>
|
|
33
|
+
</div>
|
|
34
|
+
<div class="chip">
|
|
35
|
+
<i class="material-icons">check</i>
|
|
36
|
+
Filter
|
|
37
|
+
<i class="close material-icons">close</i>
|
|
38
|
+
</div>
|
|
39
|
+
<div class="chip outlined">Information</div>
|
|
40
|
+
<div class="chip outlined">
|
|
41
|
+
<i class="material-icons">check</i>
|
|
42
|
+
Filter
|
|
43
|
+
<i class="close material-icons">close</i>
|
|
44
|
+
</div>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Contacts
|
|
48
|
+
|
|
49
|
+
To create a contact chip just add an img inside.
|
|
50
|
+
|
|
51
|
+
<!-- component -->
|
|
52
|
+
<div class="chip">
|
|
53
|
+
<img src="images/yuna.jpg" alt="Contact Person"> Jane Doe
|
|
54
|
+
</div>
|
|
55
|
+
<!-- /component -->
|
|
56
|
+
|
|
57
|
+
```html
|
|
58
|
+
<div class="chip">
|
|
59
|
+
<img src="images/yuna.jpg" alt="Contact Person">
|
|
60
|
+
Jane Doe
|
|
61
|
+
</div>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Tags
|
|
65
|
+
|
|
66
|
+
To create a tag chip just add a close icon inside with the class `close`.
|
|
67
|
+
|
|
68
|
+
<!-- component -->
|
|
69
|
+
<div class="chip">
|
|
70
|
+
Tag
|
|
71
|
+
<i class="close material-icons">close</i>
|
|
72
|
+
</div>
|
|
73
|
+
<!-- /component -->
|
|
74
|
+
|
|
75
|
+
```html
|
|
76
|
+
<div class="chip">
|
|
77
|
+
Tag
|
|
78
|
+
<i class="close material-icons">close</i>
|
|
79
|
+
</div>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Javascript Plugin
|
|
83
|
+
|
|
84
|
+
To add tags, just enter your tag text and press enter. You can delete them by clicking on the close icon or by
|
|
85
|
+
using your delete button.
|
|
86
|
+
|
|
87
|
+
<!-- Update Info -->
|
|
88
|
+
<p class="red-text"><strong>ATTENTION:</strong> Data-Format has changed from version 1.X.X to 2.0.0! Please update option 'data'.</p>
|
|
89
|
+
|
|
90
|
+
Normal:
|
|
91
|
+
|
|
92
|
+
<!-- component -->
|
|
93
|
+
<div class="chips"></div>
|
|
94
|
+
<!-- /component -->
|
|
95
|
+
|
|
96
|
+
Set initial tags:
|
|
97
|
+
|
|
98
|
+
<!-- component -->
|
|
99
|
+
<div class="chips chips-initial"></div>
|
|
100
|
+
<!-- /component -->
|
|
101
|
+
|
|
102
|
+
Use placeholders and override hint texts:
|
|
103
|
+
|
|
104
|
+
<!-- component -->
|
|
105
|
+
<div class="chips chips-placeholder"></div>
|
|
106
|
+
<!-- /component -->
|
|
107
|
+
|
|
108
|
+
Use autocomplete with chips:
|
|
109
|
+
|
|
110
|
+
<!-- component -->
|
|
111
|
+
<div class="chips chips-autocomplete"></div>
|
|
112
|
+
<!-- /component -->
|
|
113
|
+
|
|
114
|
+
```html
|
|
115
|
+
<!-- Default with no input (automatically generated) -->
|
|
116
|
+
<div class="chips"></div>
|
|
117
|
+
<div class="chips chips-initial"></div>
|
|
118
|
+
<div class="chips chips-placeholder"></div>
|
|
119
|
+
<div class="chips chips-autocomplete"></div>
|
|
120
|
+
<!-- Customizable input -->
|
|
121
|
+
<div class="chips">
|
|
122
|
+
<input class="custom-class">
|
|
123
|
+
</div>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Initialization
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
130
|
+
const elems = document.querySelectorAll('.chips');
|
|
131
|
+
const instances = M.Chips.init(elems, {
|
|
132
|
+
// specify options here
|
|
133
|
+
autocompleteOptions: {
|
|
134
|
+
data: [
|
|
135
|
+
{id: 12, text: "Apple"},
|
|
136
|
+
{id: 13, text: "Microsoft"},
|
|
137
|
+
{id: 42, text: "Google", image: 'http://placehold.it/250x250'}
|
|
138
|
+
]
|
|
139
|
+
},
|
|
140
|
+
placeholder: 'Enter a tag',
|
|
141
|
+
secondaryPlaceholder: '+Tag',
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Chip data object:
|
|
147
|
+
|
|
148
|
+
```javascript
|
|
149
|
+
const chip = {
|
|
150
|
+
id: '4711', // unique identifier (can be a string too)
|
|
151
|
+
text: 'Title' // optional Text
|
|
152
|
+
image: '', // optional Image-Url
|
|
153
|
+
};
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Options
|
|
157
|
+
|
|
158
|
+
Note: This could be generated from the JSDocs
|
|
159
|
+
|
|
160
|
+
<table class="table highlight">
|
|
161
|
+
<thead>
|
|
162
|
+
<tr>
|
|
163
|
+
<th>Name</th>
|
|
164
|
+
<th>Type</th>
|
|
165
|
+
<th>Default</th>
|
|
166
|
+
<th>Description</th>
|
|
167
|
+
</tr>
|
|
168
|
+
</thead>
|
|
169
|
+
<tbody>
|
|
170
|
+
<tr>
|
|
171
|
+
<td>data</td>
|
|
172
|
+
<td>Array</td>
|
|
173
|
+
<td>[]</td>
|
|
174
|
+
<td>Set the chip data (look at the Chip data object)</td>
|
|
175
|
+
</tr>
|
|
176
|
+
<tr>
|
|
177
|
+
<td>placeholder</td>
|
|
178
|
+
<td>String</td>
|
|
179
|
+
<td>''</td>
|
|
180
|
+
<td>Set first placeholder when there are no tags.</td>
|
|
181
|
+
</tr>
|
|
182
|
+
<tr>
|
|
183
|
+
<td>secondaryPlaceholder</td>
|
|
184
|
+
<td>String</td>
|
|
185
|
+
<td>''</td>
|
|
186
|
+
<td>Set second placeholder when adding additional tags.</td>
|
|
187
|
+
</tr>
|
|
188
|
+
<tr>
|
|
189
|
+
<td>closeIconClass</td>
|
|
190
|
+
<td>String</td>
|
|
191
|
+
<td>'material-icons'</td>
|
|
192
|
+
<td>Specifies class to be used in "close" button (useful when working with Material Symbols icon set).</td>
|
|
193
|
+
</tr>
|
|
194
|
+
<tr>
|
|
195
|
+
<td>allowUserInput</td>
|
|
196
|
+
<td>Boolean</td>
|
|
197
|
+
<td>false</td>
|
|
198
|
+
<td>Specifies option to render user input field</td>
|
|
199
|
+
</tr>
|
|
200
|
+
<tr>
|
|
201
|
+
<td>autocompleteOptions</td>
|
|
202
|
+
<td>Object</td>
|
|
203
|
+
<td>{}</td>
|
|
204
|
+
<td>Set autocomplete options.</td>
|
|
205
|
+
</tr>
|
|
206
|
+
<tr>
|
|
207
|
+
<td>autocompleteOnly</td>
|
|
208
|
+
<td>Boolean</td>
|
|
209
|
+
<td>false</td>
|
|
210
|
+
<td>Toggles abililty to add custom value not in autocomplete list.</td>
|
|
211
|
+
</tr>
|
|
212
|
+
<tr>
|
|
213
|
+
<td>limit</td>
|
|
214
|
+
<td>Integer</td>
|
|
215
|
+
<td>Infinity</td>
|
|
216
|
+
<td>Set chips limit.</td>
|
|
217
|
+
</tr>
|
|
218
|
+
<tr>
|
|
219
|
+
<td>onChipAdd</td>
|
|
220
|
+
<td>Function</td>
|
|
221
|
+
<td>null</td>
|
|
222
|
+
<td>Callback for chip add.</td>
|
|
223
|
+
</tr>
|
|
224
|
+
<tr>
|
|
225
|
+
<td>onChipSelect</td>
|
|
226
|
+
<td>Function</td>
|
|
227
|
+
<td>null</td>
|
|
228
|
+
<td>Callback for chip select.</td>
|
|
229
|
+
</tr>
|
|
230
|
+
<tr>
|
|
231
|
+
<td>onChipDelete</td>
|
|
232
|
+
<td>Function</td>
|
|
233
|
+
<td>null</td>
|
|
234
|
+
<td>Callback for chip delete.</td>
|
|
235
|
+
</tr>
|
|
236
|
+
<tr>
|
|
237
|
+
</tbody>
|
|
238
|
+
</table>
|
|
239
|
+
|
|
240
|
+
## Methods
|
|
241
|
+
|
|
242
|
+
Use these methods to interact with chips. All the methods are called on the plugin instance. You can get the plugin instance like this:
|
|
243
|
+
|
|
244
|
+
```javascript
|
|
245
|
+
const instance = M.Chips.getInstance(elem);
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
### .addChip();
|
|
250
|
+
Add chip to input.
|
|
251
|
+
|
|
252
|
+
#### Arguments
|
|
253
|
+
<b>Chip:</b> Chip data object.
|
|
254
|
+
|
|
255
|
+
```javascript
|
|
256
|
+
instance.addChip({
|
|
257
|
+
id: 1337,
|
|
258
|
+
text: 'John Doe', // optional
|
|
259
|
+
image: '', // optional
|
|
260
|
+
});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
### .deleteChip();
|
|
265
|
+
Delete nth chip.
|
|
266
|
+
|
|
267
|
+
#### Arguments
|
|
268
|
+
<b>Integer:</b> Index of chip.
|
|
269
|
+
|
|
270
|
+
```javascript
|
|
271
|
+
instance.deleteChip(3); // Delete 3rd chip.
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### .selectChip();
|
|
275
|
+
Select nth chip.
|
|
276
|
+
|
|
277
|
+
#### Arguments
|
|
278
|
+
<b>Integer:</b> Index of chip.
|
|
279
|
+
|
|
280
|
+
```javascript
|
|
281
|
+
instance.selectChip(2); // Select 2nd chip
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Properties
|
|
285
|
+
|
|
286
|
+
Note: This could be generated from JSDocs.
|
|
287
|
+
|
|
288
|
+
<table class="striped">
|
|
289
|
+
<thead>
|
|
290
|
+
<tr>
|
|
291
|
+
<th>Name</th>
|
|
292
|
+
<th>Type</th>
|
|
293
|
+
<th>Description</th>
|
|
294
|
+
</tr>
|
|
295
|
+
</thead>
|
|
296
|
+
<tbody>
|
|
297
|
+
<tr>
|
|
298
|
+
<td>el</td>
|
|
299
|
+
<td>Element</td>
|
|
300
|
+
<td>The DOM element the plugin was initialized with.</td>
|
|
301
|
+
</tr>
|
|
302
|
+
<tr>
|
|
303
|
+
<td>options</td>
|
|
304
|
+
<td>Object</td>
|
|
305
|
+
<td>The options the instance was initialized with.</td>
|
|
306
|
+
</tr>
|
|
307
|
+
<tr>
|
|
308
|
+
<td>chipsData</td>
|
|
309
|
+
<td>Array</td>
|
|
310
|
+
<td>Array of the current chips data.</td>
|
|
311
|
+
</tr>
|
|
312
|
+
<tr>
|
|
313
|
+
<td>hasAutocomplete</td>
|
|
314
|
+
<td>Boolean</td>
|
|
315
|
+
<td>If the chips has autocomplete enabled.</td>
|
|
316
|
+
</tr>
|
|
317
|
+
<tr>
|
|
318
|
+
<td>autocomplete</td>
|
|
319
|
+
<td>Object</td>
|
|
320
|
+
<td><a href="autocomplete.html">Autocomplete</a> instance, if any.</td>
|
|
321
|
+
</tr>
|
|
322
|
+
</tbody>
|
|
323
|
+
</table>
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
@use '../../sass/variables' as *;
|
|
2
|
+
@use '../../sass/global' as *;
|
|
3
|
+
|
|
4
|
+
.collapsible {
|
|
5
|
+
padding-left: 0;
|
|
6
|
+
list-style-type: none;
|
|
7
|
+
border-top: 1px solid var(--md-sys-color-outline-variant);
|
|
8
|
+
border-right: 1px solid var(--md-sys-color-outline-variant);
|
|
9
|
+
border-left: 1px solid var(--md-sys-color-outline-variant);
|
|
10
|
+
margin: $element-top-margin 0 $element-bottom-margin 0;
|
|
11
|
+
@extend .z-depth-1;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.collapsible-header {
|
|
15
|
+
display: flex;
|
|
16
|
+
cursor: pointer;
|
|
17
|
+
-webkit-tap-highlight-color: transparent;
|
|
18
|
+
line-height: 1.5;
|
|
19
|
+
padding: 1rem;
|
|
20
|
+
border-bottom: 1px solid var(--md-sys-color-outline-variant);
|
|
21
|
+
|
|
22
|
+
&:focus {
|
|
23
|
+
outline: 0
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
i {
|
|
27
|
+
width: 2rem;
|
|
28
|
+
font-size: 1.6rem;
|
|
29
|
+
display: inline-block;
|
|
30
|
+
text-align: center;
|
|
31
|
+
margin-right: 1rem;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.collapsible-header::after {
|
|
36
|
+
content: '\e5cf';
|
|
37
|
+
margin-left: .5rem;
|
|
38
|
+
font-family: 'Material Symbols Outlined', 'Material Symbols Rounded', 'Material Symbols Sharp', 'Material Icons';
|
|
39
|
+
font-size: 25px;
|
|
40
|
+
line-height: .9;
|
|
41
|
+
-webkit-font-smoothing: antialiased;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.active .collapsible-header::after {
|
|
45
|
+
content: '\e5ce';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.keyboard-focused .collapsible-header:focus {
|
|
49
|
+
background-color: rgba(0, 0, 0, 0.12);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.collapsible-header-content {
|
|
53
|
+
flex-grow: 1;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.collapsible-body {
|
|
57
|
+
max-height: 0;
|
|
58
|
+
border-bottom: 1px solid var(--md-sys-color-outline-variant);
|
|
59
|
+
box-sizing: border-box;
|
|
60
|
+
padding: 0 2rem;
|
|
61
|
+
overflow: hidden;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Popout Collapsible
|
|
65
|
+
|
|
66
|
+
.collapsible.popout {
|
|
67
|
+
border: none;
|
|
68
|
+
box-shadow: none;
|
|
69
|
+
|
|
70
|
+
> li {
|
|
71
|
+
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
|
|
72
|
+
// transform: scaleX(.92);
|
|
73
|
+
margin: 0 24px;
|
|
74
|
+
transition: margin .35s cubic-bezier(0.250, 0.460, 0.450, 0.940);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
> li.active {
|
|
78
|
+
box-shadow: 0 5px 11px 0 rgba(0, 0, 0, 0.18), 0 4px 15px 0 rgba(0, 0, 0, 0.15);
|
|
79
|
+
margin: 16px 0;
|
|
80
|
+
// transform: scaleX(1);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { Utils } from '../../src/utils';
|
|
2
|
+
import { Component, BaseOptions, InitElements, MElement } from '../../src/component';
|
|
3
|
+
|
|
4
|
+
export interface CollapsibleOptions extends BaseOptions {
|
|
5
|
+
/**
|
|
6
|
+
* If accordion versus collapsible.
|
|
7
|
+
* @default true
|
|
8
|
+
*/
|
|
9
|
+
accordion: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Transition in duration in milliseconds.
|
|
12
|
+
* @default 300
|
|
13
|
+
*/
|
|
14
|
+
inDuration: number;
|
|
15
|
+
/**
|
|
16
|
+
* Transition out duration in milliseconds.
|
|
17
|
+
* @default 300
|
|
18
|
+
*/
|
|
19
|
+
outDuration: number;
|
|
20
|
+
/**
|
|
21
|
+
* Callback function called before collapsible is opened.
|
|
22
|
+
* @default null
|
|
23
|
+
*/
|
|
24
|
+
onOpenStart: (el: Element) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Callback function called after collapsible is opened.
|
|
27
|
+
* @default null
|
|
28
|
+
*/
|
|
29
|
+
onOpenEnd: (el: Element) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Callback function called before collapsible is closed.
|
|
32
|
+
* @default null
|
|
33
|
+
*/
|
|
34
|
+
onCloseStart: (el: Element) => void;
|
|
35
|
+
/**
|
|
36
|
+
* Callback function called after collapsible is closed.
|
|
37
|
+
* @default null
|
|
38
|
+
*/
|
|
39
|
+
onCloseEnd: (el: Element) => void;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const _defaults: CollapsibleOptions = {
|
|
43
|
+
accordion: true,
|
|
44
|
+
onOpenStart: null,
|
|
45
|
+
onOpenEnd: null,
|
|
46
|
+
onCloseStart: null,
|
|
47
|
+
onCloseEnd: null,
|
|
48
|
+
inDuration: 300,
|
|
49
|
+
outDuration: 300
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export class Collapsible extends Component<CollapsibleOptions> {
|
|
53
|
+
private _headers: HTMLElement[];
|
|
54
|
+
|
|
55
|
+
constructor(el: HTMLElement, options: Partial<CollapsibleOptions>) {
|
|
56
|
+
super(el, options, Collapsible);
|
|
57
|
+
this.el['M_Collapsible'] = this;
|
|
58
|
+
|
|
59
|
+
this.options = {
|
|
60
|
+
...Collapsible.defaults,
|
|
61
|
+
...options
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Setup tab indices
|
|
65
|
+
this._headers = Array.from(this.el.querySelectorAll('li > .collapsible-header'));
|
|
66
|
+
this._headers.forEach((el) => (el.tabIndex = 0));
|
|
67
|
+
this._setupEventHandlers();
|
|
68
|
+
|
|
69
|
+
// Open active
|
|
70
|
+
const activeBodies: HTMLElement[] = Array.from(
|
|
71
|
+
this.el.querySelectorAll('li.active > .collapsible-body')
|
|
72
|
+
);
|
|
73
|
+
if (this.options.accordion) {
|
|
74
|
+
if (activeBodies.length > 0) {
|
|
75
|
+
// Accordion => open first active only
|
|
76
|
+
this._setExpanded(activeBodies[0]);
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
// Expandables => all active
|
|
80
|
+
activeBodies.forEach((el) => this._setExpanded(el));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
static get defaults(): CollapsibleOptions {
|
|
85
|
+
return _defaults;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Initializes instance of Collapsible.
|
|
90
|
+
* @param el HTML element.
|
|
91
|
+
* @param options Component options.
|
|
92
|
+
*/
|
|
93
|
+
static init(el: HTMLElement, options?: Partial<CollapsibleOptions>): Collapsible;
|
|
94
|
+
/**
|
|
95
|
+
* Initializes instances of Collapsible.
|
|
96
|
+
* @param els HTML elements.
|
|
97
|
+
* @param options Component options.
|
|
98
|
+
*/
|
|
99
|
+
static init(els: InitElements<MElement>, options?: Partial<CollapsibleOptions>): Collapsible[];
|
|
100
|
+
/**
|
|
101
|
+
* Initializes instances of Collapsible.
|
|
102
|
+
* @param els HTML elements.
|
|
103
|
+
* @param options Component options.
|
|
104
|
+
*/
|
|
105
|
+
static init(
|
|
106
|
+
els: HTMLElement | InitElements<MElement>,
|
|
107
|
+
options: Partial<CollapsibleOptions> = {}
|
|
108
|
+
): Collapsible | Collapsible[] {
|
|
109
|
+
return super.init(els, options, Collapsible);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
static getInstance(el: HTMLElement): Collapsible {
|
|
113
|
+
return el['M_Collapsible'];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
destroy() {
|
|
117
|
+
this._removeEventHandlers();
|
|
118
|
+
this.el['M_Collapsible'] = undefined;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
_setupEventHandlers() {
|
|
122
|
+
this.el.addEventListener('click', this._handleCollapsibleClick);
|
|
123
|
+
this._headers.forEach((header) =>
|
|
124
|
+
header.addEventListener('keydown', this._handleCollapsibleKeydown)
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
_removeEventHandlers() {
|
|
129
|
+
this.el.removeEventListener('click', this._handleCollapsibleClick);
|
|
130
|
+
this._headers.forEach((header) =>
|
|
131
|
+
header.removeEventListener('keydown', this._handleCollapsibleKeydown)
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
_handleCollapsibleClick = (e: MouseEvent | KeyboardEvent) => {
|
|
136
|
+
const header = (e.target as HTMLElement).closest('.collapsible-header');
|
|
137
|
+
if (e.target && header) {
|
|
138
|
+
const collapsible = header.closest('.collapsible');
|
|
139
|
+
if (collapsible !== this.el) return;
|
|
140
|
+
|
|
141
|
+
const li = header.closest('li');
|
|
142
|
+
const isActive = li.classList.contains('active');
|
|
143
|
+
const index = [...li.parentNode.children].indexOf(li);
|
|
144
|
+
|
|
145
|
+
if (isActive) this.close(index);
|
|
146
|
+
else this.open(index);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
_handleCollapsibleKeydown = (e: KeyboardEvent) => {
|
|
151
|
+
if (Utils.keys.ENTER.includes(e.key)) {
|
|
152
|
+
this._handleCollapsibleClick(e);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
private _setExpanded(li: HTMLElement): void {
|
|
157
|
+
li.style.maxHeight = li.scrollHeight + 'px';
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
_animateIn(index: number) {
|
|
161
|
+
const li = <HTMLLIElement>this.el.children[index];
|
|
162
|
+
if (!li) return;
|
|
163
|
+
const body: HTMLElement = li.querySelector('.collapsible-body');
|
|
164
|
+
const duration = this.options.inDuration; // easeInOutCubic
|
|
165
|
+
body.style.transition = `max-height ${duration}ms ease-out`;
|
|
166
|
+
this._setExpanded(body);
|
|
167
|
+
setTimeout(() => {
|
|
168
|
+
if (typeof this.options.onOpenEnd === 'function') {
|
|
169
|
+
this.options.onOpenEnd.call(this, li);
|
|
170
|
+
}
|
|
171
|
+
}, duration);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
_animateOut(index: number) {
|
|
175
|
+
const li = this.el.children[index];
|
|
176
|
+
if (!li) return;
|
|
177
|
+
const body: HTMLElement = li.querySelector('.collapsible-body');
|
|
178
|
+
const duration = this.options.outDuration; // easeInOutCubic
|
|
179
|
+
body.style.transition = `max-height ${duration}ms ease-out`;
|
|
180
|
+
body.style.maxHeight = '0';
|
|
181
|
+
setTimeout(() => {
|
|
182
|
+
if (typeof this.options.onCloseEnd === 'function') {
|
|
183
|
+
this.options.onCloseEnd.call(this, li);
|
|
184
|
+
}
|
|
185
|
+
}, duration);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Open collapsible section.
|
|
190
|
+
* @param n Nth section to open.
|
|
191
|
+
*/
|
|
192
|
+
open = (index: number) => {
|
|
193
|
+
const listItems = Array.from(this.el.children).filter((c) => c.tagName === 'LI');
|
|
194
|
+
const li = listItems[index];
|
|
195
|
+
if (li && !li.classList.contains('active')) {
|
|
196
|
+
// onOpenStart callback
|
|
197
|
+
if (typeof this.options.onOpenStart === 'function') {
|
|
198
|
+
this.options.onOpenStart.call(this, li);
|
|
199
|
+
}
|
|
200
|
+
// Handle accordion behavior
|
|
201
|
+
if (this.options.accordion) {
|
|
202
|
+
const activeLis = listItems.filter((li) => li.classList.contains('active'));
|
|
203
|
+
activeLis.forEach((activeLi) => {
|
|
204
|
+
const index = listItems.indexOf(activeLi);
|
|
205
|
+
this.close(index);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
// Animate in
|
|
209
|
+
li.classList.add('active');
|
|
210
|
+
this._animateIn(index);
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Close collapsible section.
|
|
216
|
+
* @param n Nth section to close.
|
|
217
|
+
*/
|
|
218
|
+
close = (index: number) => {
|
|
219
|
+
const li = Array.from(this.el.children).filter((c) => c.tagName === 'LI')[index];
|
|
220
|
+
if (li && li.classList.contains('active')) {
|
|
221
|
+
// onCloseStart callback
|
|
222
|
+
if (typeof this.options.onCloseStart === 'function') {
|
|
223
|
+
this.options.onCloseStart.call(this, li);
|
|
224
|
+
}
|
|
225
|
+
// Animate out
|
|
226
|
+
li.classList.remove('active');
|
|
227
|
+
this._animateOut(index);
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
}
|