kmaterialize 2.3.3-1.0.22 → 2.3.3-1.0.24

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 (49) hide show
  1. package/components/air-datepicker/air-datepicker.js +152 -0
  2. package/components/alert/alert.js +54 -0
  3. package/components/button/buttons.js +220 -0
  4. package/components/card/cards.js +149 -0
  5. package/components/carousel/carousel.js +574 -0
  6. package/components/carousel/slider.js +340 -0
  7. package/components/chip/chips.js +341 -0
  8. package/components/collapsible/collapsible.js +156 -0
  9. package/components/color-input/color-input.js +166 -0
  10. package/components/color-input/color-input.ts +2 -1
  11. package/components/datepicker/datepicker.js +1035 -0
  12. package/components/dialog/materialbox.js +377 -0
  13. package/components/dialog/modal.js +72 -0
  14. package/components/dropdown/dropdown.js +505 -0
  15. package/components/file-input/file-input.js +169 -0
  16. package/components/kanban/_kanban.scss +8 -3
  17. package/components/kanban/kanban.js +168 -0
  18. package/components/kanban/kanban.ts +63 -3
  19. package/components/loading/_loading.scss +68 -0
  20. package/components/loading/loading.ts +104 -0
  21. package/components/loading/loadingSpec.js +102 -0
  22. package/components/navigation-drawer/sidenav.js +454 -0
  23. package/components/number-input/number-input.js +68 -0
  24. package/components/password-input/password-input.js +49 -0
  25. package/components/popup/_popup.scss +106 -0
  26. package/components/popup/popup.ts +113 -0
  27. package/components/popup/popupSpec.js +140 -0
  28. package/components/search/autocomplete.js +470 -0
  29. package/components/slider/range.js +169 -0
  30. package/components/snackbar/toasts.js +244 -0
  31. package/components/tabs/tabs.js +289 -0
  32. package/components/textfield/_input-fields.scss +7 -2
  33. package/components/textfield/forms.js +172 -0
  34. package/components/textfield/select.js +385 -0
  35. package/components/timepicker/timepicker.js +698 -0
  36. package/components/tom-select/tom-select-field.js +130 -0
  37. package/components/toolbar/toolbar.js +134 -0
  38. package/components/tooltip/tooltip.js +270 -0
  39. package/dist/css/materialize.colors.min.css +1 -1
  40. package/dist/css/materialize.css +271 -6
  41. package/dist/css/materialize.min.css +2 -2
  42. package/dist/css/materialize.min.css.map +1 -1
  43. package/dist/js/materialize.cjs.js +249 -38
  44. package/dist/js/materialize.d.ts +58 -3
  45. package/dist/js/materialize.js +249 -38
  46. package/dist/js/materialize.min.js +2 -2
  47. package/dist/js/materialize.mjs +248 -39
  48. package/package.json +6 -1
  49. package/sass/materialize.scss +2 -0
@@ -0,0 +1,152 @@
1
+ import { Component } from '../../src/component';
2
+ import { loadPeer } from '../../src/peer-loader';
3
+ const _defaults = {};
4
+ let activeAirDatepickerField;
5
+ // @implement /Users/kzarshenas/Sites/CrazyProject/CrazyPHP/src/Front/Library/Utility/Form/Date.ts
6
+ // Enhances `<input type="text" data-type="date" data-date-picker="air-datepicker">`
7
+ // with the air-datepicker calendar/range picker - deliberately separate from
8
+ // kmaterialize's own native `components/datepicker/` (a different, already
9
+ // existing class-based component); this one is opted into per-input via the
10
+ // `data-date-picker` attribute so it never collides with `.datepicker`
11
+ // elements. The `multiple` attribute switches the picker into range mode,
12
+ // `data-date-format`/`data-date-lang` (only "fr-FR" ported so far) mirror
13
+ // CrazyPHP's own dataset convention.
14
+ //
15
+ // air-datepicker is an optional peerDependency, loaded on demand via
16
+ // peer-loader. Its own base stylesheet (air-datepicker/air-datepicker.css)
17
+ // must be imported separately by the consumer - see the docs page.
18
+ export class AirDatepickerField extends Component {
19
+ picker;
20
+ ready;
21
+ _triggers;
22
+ _handleOutsideClick = (e) => {
23
+ const calendarEl = document.querySelector('.air-datepicker');
24
+ const clickedTrigger = this._triggers.some(trigger => trigger.contains(e.target));
25
+ if (calendarEl instanceof HTMLElement &&
26
+ !calendarEl.contains(e.target) &&
27
+ !this.el.contains(e.target) &&
28
+ !clickedTrigger) {
29
+ this.picker?.hide();
30
+ }
31
+ };
32
+ constructor(el, options) {
33
+ super(el, options, AirDatepickerField);
34
+ this.el.M_AirDatepickerField = this;
35
+ this.options = {
36
+ ...AirDatepickerField.defaults,
37
+ ...options
38
+ };
39
+ const labels = Array.from(document.querySelectorAll('label')).filter(label => label.htmlFor === this.el.id);
40
+ const icons = Array.from(this.el.parentElement?.querySelectorAll('.prefix, .suffix') ?? []);
41
+ this._triggers = [...labels, ...icons];
42
+ this._triggers.forEach(trigger => trigger.addEventListener('click', this._handleTriggerClick));
43
+ this.ready = this._setup();
44
+ }
45
+ static get defaults() {
46
+ return _defaults;
47
+ }
48
+ static init(els, options = {}) {
49
+ return super.init(els, options, AirDatepickerField);
50
+ }
51
+ static getInstance(el) {
52
+ return el.M_AirDatepickerField;
53
+ }
54
+ destroy() {
55
+ document.removeEventListener('click', this._handleOutsideClick);
56
+ this._triggers.forEach(trigger => trigger.removeEventListener('click', this._handleTriggerClick));
57
+ this.picker?.destroy();
58
+ if (activeAirDatepickerField === this)
59
+ activeAirDatepickerField = undefined;
60
+ this.el.M_AirDatepickerField = undefined;
61
+ }
62
+ _handleTriggerClick = (event) => {
63
+ event.preventDefault();
64
+ event.stopPropagation();
65
+ void this.ready.then(() => this.picker?.show());
66
+ };
67
+ async _setup() {
68
+ const AirDatepicker = await loadPeer({
69
+ specifier: 'air-datepicker',
70
+ globalName: 'AirDatepicker',
71
+ feature: 'Date input (air-datepicker) enhancement',
72
+ cdnHint: '<link rel="stylesheet" href="path/to/air-datepicker.css">\n' +
73
+ ' <script src="path/to/air-datepicker.js"></script>\n' +
74
+ ' (self-hosted - copy from node_modules/air-datepicker/, or a CDN of your choice)'
75
+ }, () => import('air-datepicker'));
76
+ const dataset = this.el.dataset;
77
+ const builtInLocale = dataset.dateLang === 'fr-FR'
78
+ ? (await import('air-datepicker/locale/fr')).default
79
+ : (await import('air-datepicker/locale/en')).default;
80
+ const pickerOptions = {
81
+ dateFormat: dataset.dateFormat || 'yyyy-MM-dd',
82
+ autoClose: dataset.dateAutoClose !== 'false',
83
+ locale: (this.options.locale ?? builtInLocale),
84
+ onShow: isAnimationComplete => {
85
+ if (isAnimationComplete)
86
+ return;
87
+ if (activeAirDatepickerField && activeAirDatepickerField !== this) {
88
+ activeAirDatepickerField.picker?.hide();
89
+ }
90
+ activeAirDatepickerField = this;
91
+ },
92
+ onHide: isAnimationComplete => {
93
+ if (isAnimationComplete && activeAirDatepickerField === this) {
94
+ activeAirDatepickerField = undefined;
95
+ }
96
+ }
97
+ };
98
+ let multiple = false;
99
+ if (this.el.multiple || dataset.dateRange === 'true') {
100
+ pickerOptions.range = true;
101
+ pickerOptions.multipleDatesSeparator = ' - ';
102
+ multiple = true;
103
+ }
104
+ const initialValue = this.el.getAttribute('value')?.trim();
105
+ if (initialValue) {
106
+ pickerOptions.selectedDates = multiple
107
+ ? initialValue.split(' - ').map(value => value.trim())
108
+ : [initialValue];
109
+ }
110
+ if (dataset.dateTimepicker === 'true') {
111
+ pickerOptions.timepicker = true;
112
+ if (dataset.dateTimeFormat)
113
+ pickerOptions.timeFormat = dataset.dateTimeFormat;
114
+ }
115
+ const supportedViews = ['days', 'months', 'years'];
116
+ if (supportedViews.includes(dataset.dateView ?? '')) {
117
+ pickerOptions.view = dataset.dateView;
118
+ }
119
+ if (supportedViews.includes(dataset.dateMinView ?? '')) {
120
+ pickerOptions.minView = dataset.dateMinView;
121
+ }
122
+ if (dataset.dateMobile === 'true')
123
+ pickerOptions.isMobile = true;
124
+ if (dataset.datePosition) {
125
+ pickerOptions.position = dataset.datePosition;
126
+ }
127
+ if (dataset.dateButtons) {
128
+ const supportedButtons = ['today', 'clear'];
129
+ pickerOptions.buttons = dataset.dateButtons
130
+ .split(',')
131
+ .map(button => button.trim())
132
+ .filter(button => supportedButtons.includes(button));
133
+ }
134
+ if (this.el.hasAttribute('min') && this.el.getAttribute('min')) {
135
+ pickerOptions.minDate = new Date(this.el.getAttribute('min'));
136
+ }
137
+ if (this.el.hasAttribute('max') && this.el.getAttribute('max')) {
138
+ pickerOptions.maxDate = new Date(this.el.getAttribute('max'));
139
+ }
140
+ if (!this.el.required && !pickerOptions.buttons) {
141
+ pickerOptions.buttons = ['clear'];
142
+ }
143
+ pickerOptions.onSelect = ({ date }) => {
144
+ if (multiple && Array.isArray(date) && date.length === 1)
145
+ return;
146
+ this.el.dispatchEvent(new Event('input', { bubbles: true }));
147
+ this.el.dispatchEvent(new Event('change', { bubbles: true }));
148
+ };
149
+ this.picker = new AirDatepicker(this.el, pickerOptions);
150
+ document.addEventListener('click', this._handleOutsideClick);
151
+ }
152
+ }
@@ -0,0 +1,54 @@
1
+ import { Component } from '../../src/component';
2
+ const _defaults = {
3
+ dismissible: true
4
+ };
5
+ /** A persistent, contextual feedback banner. */
6
+ export class Alert extends Component {
7
+ _closeButton = null;
8
+ _onClose = () => this.dismiss();
9
+ constructor(el, options) {
10
+ super(el, options, Alert);
11
+ this.options = { ...Alert.defaults, ...options };
12
+ this.el['M_Alert'] = this;
13
+ this._bindCloseButton();
14
+ }
15
+ static get defaults() {
16
+ return _defaults;
17
+ }
18
+ static init(els, options = {}) {
19
+ return super.init(els, options, Alert);
20
+ }
21
+ static getInstance(el) {
22
+ return el['M_Alert'];
23
+ }
24
+ _bindCloseButton() {
25
+ this._closeButton = this.el.querySelector('.alert-close');
26
+ if (this.options.dismissible && this._closeButton) {
27
+ this._closeButton.addEventListener('click', this._onClose);
28
+ }
29
+ }
30
+ /** Hide and remove the alert from the document. */
31
+ dismiss() {
32
+ if (!this.el.isConnected)
33
+ return;
34
+ this.el.classList.add('alert-dismissing');
35
+ const remove = () => {
36
+ this.el.removeEventListener('transitionend', remove);
37
+ this.el.hidden = true;
38
+ this.options.onDismiss?.(this);
39
+ };
40
+ if (getComputedStyle(this.el).transitionDuration === '0s')
41
+ remove();
42
+ else
43
+ this.el.addEventListener('transitionend', remove, { once: true });
44
+ }
45
+ /** Show an alert that was previously dismissed. */
46
+ open() {
47
+ this.el.hidden = false;
48
+ this.el.classList.remove('alert-dismissing');
49
+ }
50
+ destroy() {
51
+ this._closeButton?.removeEventListener('click', this._onClose);
52
+ delete this.el['M_Alert'];
53
+ }
54
+ }
@@ -0,0 +1,220 @@
1
+ import { Component } from '../../src/component';
2
+ import { Utils } from '../../src/utils';
3
+ const _defaults = {
4
+ direction: 'top',
5
+ hoverEnabled: true,
6
+ toolbarEnabled: false
7
+ };
8
+ class FloatingActionButton extends Component {
9
+ #anchor;
10
+ #menu;
11
+ #floatingBtns;
12
+ #floatingBtnsReverse;
13
+ /**
14
+ * Describes open/close state of FAB.
15
+ */
16
+ isOpen;
17
+ offsetY;
18
+ offsetX;
19
+ btnBottom;
20
+ btnLeft;
21
+ btnWidth;
22
+ constructor(el, options) {
23
+ super(el, options, FloatingActionButton);
24
+ this.el['M_FloatingActionButton'] = this;
25
+ this.options = {
26
+ ...FloatingActionButton.defaults,
27
+ ...options
28
+ };
29
+ this.isOpen = false;
30
+ this.#anchor = this.el.querySelector('a');
31
+ this.#menu = this.el.querySelector('ul');
32
+ this.#floatingBtns = Array.from(this.el.querySelectorAll('ul .btn-floating'));
33
+ this.#floatingBtnsReverse = this.#floatingBtns.reverse();
34
+ this.offsetY = 0;
35
+ this.offsetX = 0;
36
+ this.el.classList.add(`direction-${this.options.direction}`);
37
+ this.#anchor.tabIndex = 0;
38
+ this.#menu.ariaExpanded = 'false';
39
+ if (this.options.direction === 'top')
40
+ this.offsetY = 40;
41
+ else if (this.options.direction === 'right')
42
+ this.offsetX = -40;
43
+ else if (this.options.direction === 'bottom')
44
+ this.offsetY = -40;
45
+ else
46
+ this.offsetX = 40;
47
+ this.#setupEventHandlers();
48
+ }
49
+ static get defaults() {
50
+ return _defaults;
51
+ }
52
+ /**
53
+ * Initializes instances of FloatingActionButton.
54
+ * @param els HTML elements.
55
+ * @param options Component options.
56
+ */
57
+ static init(els, options = {}) {
58
+ return super.init(els, options, FloatingActionButton);
59
+ }
60
+ static getInstance(el) {
61
+ return el['M_FloatingActionButton'];
62
+ }
63
+ destroy() {
64
+ this.#removeEventHandlers();
65
+ this.el['M_FloatingActionButton'] = undefined;
66
+ }
67
+ #setupEventHandlers() {
68
+ if (this.options.hoverEnabled && !this.options.toolbarEnabled) {
69
+ this.el.addEventListener('mouseenter', this.open);
70
+ this.el.addEventListener('mouseleave', this.close);
71
+ }
72
+ else {
73
+ this.el.addEventListener('click', this.#handleFABClick);
74
+ }
75
+ this.el.addEventListener('keypress', this.#handleFABKeyPress);
76
+ }
77
+ #removeEventHandlers() {
78
+ if (this.options.hoverEnabled && !this.options.toolbarEnabled) {
79
+ this.el.removeEventListener('mouseenter', this.open);
80
+ this.el.removeEventListener('mouseleave', this.close);
81
+ }
82
+ else {
83
+ this.el.removeEventListener('click', this.#handleFABClick);
84
+ }
85
+ this.el.removeEventListener('keypress', this.#handleFABKeyPress);
86
+ }
87
+ #handleFABClick = () => {
88
+ this.#handleFABToggle();
89
+ };
90
+ #handleFABKeyPress = (e) => {
91
+ if (Utils.keys.ENTER.includes(e.key)) {
92
+ this.#handleFABToggle();
93
+ }
94
+ };
95
+ #handleFABToggle = () => {
96
+ if (this.isOpen) {
97
+ this.close();
98
+ }
99
+ else {
100
+ this.open();
101
+ }
102
+ };
103
+ #handleDocumentClick = (e) => {
104
+ const elem = e.target;
105
+ if (elem !== this.#menu)
106
+ this.close();
107
+ };
108
+ /**
109
+ * Open FAB.
110
+ */
111
+ open = () => {
112
+ if (this.isOpen)
113
+ return;
114
+ if (this.options.toolbarEnabled)
115
+ this.#animateInToolbar();
116
+ else
117
+ this.#animateInFAB();
118
+ this.isOpen = true;
119
+ };
120
+ /**
121
+ * Close FAB.
122
+ */
123
+ close = () => {
124
+ if (!this.isOpen)
125
+ return;
126
+ if (this.options.toolbarEnabled) {
127
+ window.removeEventListener('scroll', this.close, true);
128
+ document.body.removeEventListener('click', this.#handleDocumentClick, true);
129
+ }
130
+ else {
131
+ this.#animateOutFAB();
132
+ }
133
+ this.isOpen = false;
134
+ };
135
+ #animateInFAB() {
136
+ this.el.classList.add('active');
137
+ this.#menu.ariaExpanded = 'true';
138
+ const delayIncrement = 40;
139
+ const duration = 275;
140
+ this.#floatingBtnsReverse.forEach((el, index) => {
141
+ const delay = delayIncrement * index;
142
+ el.style.transition = 'none';
143
+ el.style.opacity = '0';
144
+ el.style.transform = `translate(${this.offsetX}px, ${this.offsetY}px) scale(0.4)`;
145
+ setTimeout(() => {
146
+ // from:
147
+ el.style.opacity = '0.4';
148
+ // easeInOutQuad
149
+ setTimeout(() => {
150
+ // to:
151
+ el.style.transition = `opacity ${duration}ms ease, transform ${duration}ms ease`;
152
+ el.style.opacity = '1';
153
+ el.style.transform = 'translate(0, 0) scale(1)';
154
+ el.tabIndex = 0;
155
+ }, 1);
156
+ }, delay);
157
+ });
158
+ }
159
+ #animateOutFAB() {
160
+ const duration = 175;
161
+ setTimeout(() => {
162
+ this.el.classList.remove('active');
163
+ this.#menu.ariaExpanded = 'false';
164
+ }, duration);
165
+ this.#floatingBtnsReverse.forEach((el) => {
166
+ el.style.transition = `opacity ${duration}ms ease, transform ${duration}ms ease`;
167
+ // to
168
+ el.style.opacity = '0';
169
+ el.style.transform = `translate(${this.offsetX}px, ${this.offsetY}px) scale(0.4)`;
170
+ el.tabIndex = -1;
171
+ });
172
+ }
173
+ #animateInToolbar() {
174
+ const windowWidth = window.innerWidth;
175
+ const windowHeight = window.innerHeight;
176
+ const btnRect = this.el.getBoundingClientRect();
177
+ const backdrop = document.createElement('div'), scaleFactor = windowWidth / backdrop[0].clientWidth, fabColor = getComputedStyle(this.#anchor).backgroundColor; // css('background-color');
178
+ backdrop.classList.add('fab-backdrop'); // $('<div class="fab-backdrop"></div>');
179
+ backdrop.style.backgroundColor = fabColor;
180
+ this.#anchor.append(backdrop);
181
+ this.offsetX = btnRect.left - windowWidth / 2 + btnRect.width / 2;
182
+ this.offsetY = windowHeight - btnRect.bottom;
183
+ this.btnBottom = btnRect.bottom;
184
+ this.btnLeft = btnRect.left;
185
+ this.btnWidth = btnRect.width;
186
+ // Set initial state
187
+ this.el.classList.add('active');
188
+ this.el.style.textAlign = 'center';
189
+ this.el.style.width = '100%';
190
+ this.el.style.bottom = '0';
191
+ this.el.style.left = '0';
192
+ this.el.style.transform = 'translateX(' + this.offsetX + 'px)';
193
+ this.el.style.transition = 'none';
194
+ this.#menu.ariaExpanded = 'true';
195
+ this.#anchor.style.transform = `translateY(${this.offsetY}px`;
196
+ this.#anchor.style.transition = 'none';
197
+ setTimeout(() => {
198
+ this.el.style.transform = '';
199
+ this.el.style.transition =
200
+ 'transform .2s cubic-bezier(0.550, 0.085, 0.680, 0.530), background-color 0s linear .2s';
201
+ this.#anchor.style.overflow = 'visible';
202
+ this.#anchor.style.transform = '';
203
+ this.#anchor.style.transition = 'transform .2s';
204
+ setTimeout(() => {
205
+ this.el.style.overflow = 'hidden';
206
+ this.el.style.backgroundColor = fabColor;
207
+ backdrop.style.transform = 'scale(' + scaleFactor + ')';
208
+ backdrop.style.transition = 'transform .2s cubic-bezier(0.550, 0.055, 0.675, 0.190)';
209
+ this.#menu.querySelectorAll('li > a').forEach((a) => {
210
+ a.style.opacity = '1';
211
+ a.tabIndex = 0;
212
+ });
213
+ // Scroll to close.
214
+ window.addEventListener('scroll', this.close, true);
215
+ document.body.addEventListener('click', this.#handleDocumentClick, true);
216
+ }, 100);
217
+ }, 0);
218
+ }
219
+ }
220
+ export { FloatingActionButton };
@@ -0,0 +1,149 @@
1
+ import { Utils } from '../../src/utils';
2
+ import { Component } from '../../src/component';
3
+ const _defaults = {
4
+ onOpen: null,
5
+ onClose: null,
6
+ inDuration: 225,
7
+ outDuration: 300
8
+ };
9
+ class Cards extends Component {
10
+ #cardReveal;
11
+ #initialOverflow;
12
+ #activators;
13
+ #cardRevealClose;
14
+ isOpen = false;
15
+ constructor(el, options) {
16
+ super(el, options, Cards);
17
+ this.el['M_Cards'] = this;
18
+ this.options = {
19
+ ...Cards.defaults,
20
+ ...options
21
+ };
22
+ this.#activators = [];
23
+ this.#cardReveal = this.el.querySelector('.card-reveal');
24
+ if (this.#cardReveal) {
25
+ this.#initialOverflow = getComputedStyle(this.el).overflow;
26
+ this.#activators = Array.from(this.el.querySelectorAll('.activator'));
27
+ this.#activators.forEach((el) => {
28
+ if (el)
29
+ el.tabIndex = 0;
30
+ });
31
+ this.#cardRevealClose = this.#cardReveal?.querySelector('.card-title');
32
+ if (this.#cardRevealClose)
33
+ this.#cardRevealClose.tabIndex = -1;
34
+ this.#cardReveal.ariaExpanded = 'false';
35
+ this.#setupEventHandlers();
36
+ }
37
+ }
38
+ static get defaults() {
39
+ return _defaults;
40
+ }
41
+ /**
42
+ * Initializes instances of Cards.
43
+ * @param els HTML elements.
44
+ * @param options Component options.
45
+ */
46
+ static init(els, options) {
47
+ return super.init(els, options, Cards);
48
+ }
49
+ static getInstance(el) {
50
+ return el['M_Cards'];
51
+ }
52
+ /**
53
+ * {@inheritDoc}
54
+ */
55
+ destroy() {
56
+ this.#removeEventHandlers();
57
+ this.#activators = [];
58
+ }
59
+ #setupEventHandlers = () => {
60
+ this.#activators.forEach((el) => {
61
+ el.addEventListener('click', this.#handleClickInteraction);
62
+ el.addEventListener('keypress', this.#handleKeypressEvent);
63
+ });
64
+ };
65
+ #removeEventHandlers = () => {
66
+ this.#activators.forEach((el) => {
67
+ el.removeEventListener('click', this.#handleClickInteraction);
68
+ el.removeEventListener('keypress', this.#handleKeypressEvent);
69
+ });
70
+ };
71
+ #handleClickInteraction = () => {
72
+ this.#handleRevealEvent();
73
+ };
74
+ #handleKeypressEvent = (e) => {
75
+ if (Utils.keys.ENTER.includes(e.key)) {
76
+ this.#handleRevealEvent();
77
+ }
78
+ };
79
+ #handleRevealEvent = () => {
80
+ this.#activators.forEach((el) => (el.tabIndex = -1)); // Reveal Card
81
+ this.open();
82
+ };
83
+ #setupRevealCloseEventHandlers = () => {
84
+ this.#cardRevealClose.addEventListener('click', this.close);
85
+ this.#cardRevealClose.addEventListener('keypress', this.#handleKeypressCloseEvent);
86
+ };
87
+ #removeRevealCloseEventHandlers = () => {
88
+ this.#cardRevealClose.addEventListener('click', this.close);
89
+ this.#cardRevealClose.addEventListener('keypress', this.#handleKeypressCloseEvent);
90
+ };
91
+ #handleKeypressCloseEvent = (e) => {
92
+ if (Utils.keys.ENTER.includes(e.key)) {
93
+ this.close();
94
+ }
95
+ };
96
+ /**
97
+ * Show card reveal.
98
+ */
99
+ open = () => {
100
+ if (this.isOpen)
101
+ return;
102
+ this.isOpen = true;
103
+ this.el.style.overflow = 'hidden';
104
+ this.#cardReveal.style.display = 'block';
105
+ this.#cardReveal.ariaExpanded = 'true';
106
+ this.#cardRevealClose.tabIndex = 0;
107
+ setTimeout(() => {
108
+ this.#cardReveal.style.transition = `transform ${this.options.outDuration}ms ease`; //easeInOutQuad
109
+ this.#cardReveal.style.transform = 'translateY(-100%)';
110
+ }, 1);
111
+ if (typeof this.options.onOpen === 'function') {
112
+ this.options.onOpen.call(this);
113
+ }
114
+ this.#setupRevealCloseEventHandlers();
115
+ };
116
+ /**
117
+ * Hide card reveal.
118
+ */
119
+ close = () => {
120
+ if (!this.isOpen)
121
+ return;
122
+ this.isOpen = false;
123
+ this.#cardReveal.style.transition = `transform ${this.options.inDuration}ms ease`; //easeInOutQuad
124
+ this.#cardReveal.style.transform = 'translateY(0)';
125
+ setTimeout(() => {
126
+ this.#cardReveal.style.display = 'none';
127
+ this.#cardReveal.ariaExpanded = 'false';
128
+ this.#activators.forEach((el) => (el.tabIndex = 0));
129
+ this.#cardRevealClose.tabIndex = -1;
130
+ this.el.style.overflow = this.#initialOverflow;
131
+ }, this.options.inDuration);
132
+ if (typeof this.options.onClose === 'function') {
133
+ this.options.onClose.call(this);
134
+ }
135
+ this.#removeRevealCloseEventHandlers();
136
+ };
137
+ static Init() {
138
+ if (typeof document !== 'undefined')
139
+ // Handle initialization of static cards.
140
+ document.addEventListener('DOMContentLoaded', () => {
141
+ const cards = document.querySelectorAll('.card');
142
+ cards.forEach((el) => {
143
+ if (el && el['M_Card'] == undefined)
144
+ this.init(el);
145
+ });
146
+ });
147
+ }
148
+ }
149
+ export { Cards };