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,150 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/html-vite';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Components/Buttons'
|
|
5
|
+
} satisfies Meta;
|
|
6
|
+
|
|
7
|
+
const BTN_SIZES = {
|
|
8
|
+
Small: ['btn-small'],
|
|
9
|
+
'Small disabled': ['btn-small', 'disabled'],
|
|
10
|
+
Normal: [],
|
|
11
|
+
'Normal disabled': ['disabled'],
|
|
12
|
+
Large: ['btn-large'],
|
|
13
|
+
'Large disabled': ['btn-large', 'disabled']
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const BTN_STYLES = {
|
|
17
|
+
Default: [], // uncomment this to see the default button when no filled/tonal/outlined/text is set
|
|
18
|
+
Filled: ['filled'],
|
|
19
|
+
Tonal: ['tonal'],
|
|
20
|
+
Outlined: ['outlined'],
|
|
21
|
+
Text: ['text']
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const Basic: StoryObj = {
|
|
25
|
+
render(args) {
|
|
26
|
+
const table = document.createElement('table');
|
|
27
|
+
const headerRow = table.insertRow();
|
|
28
|
+
headerRow.insertCell();
|
|
29
|
+
for (const size in BTN_SIZES) {
|
|
30
|
+
const cell = headerRow.insertCell();
|
|
31
|
+
cell.innerText = size;
|
|
32
|
+
}
|
|
33
|
+
for (const btnStype in BTN_STYLES) {
|
|
34
|
+
const row = table.insertRow();
|
|
35
|
+
const cell = row.insertCell();
|
|
36
|
+
cell.innerText = btnStype;
|
|
37
|
+
for (const size in BTN_SIZES) {
|
|
38
|
+
const cell = row.insertCell();
|
|
39
|
+
const classes = [...BTN_STYLES[btnStype], ...BTN_SIZES[size], ...(args.classes ?? [])];
|
|
40
|
+
const disabled = classes.includes('disabled') ? 'disabled="disabled"' : '';
|
|
41
|
+
let iconHtml = '';
|
|
42
|
+
if (args.icon) {
|
|
43
|
+
iconHtml = `<i class="material-icons">${args.icon}</i>`;
|
|
44
|
+
} else if (args.iconLeft) {
|
|
45
|
+
classes.push('icon-left');
|
|
46
|
+
iconHtml = `<i class="material-icons">${args.iconLeft}</i>`;
|
|
47
|
+
} else if (args.iconRight) {
|
|
48
|
+
classes.push('icon-right');
|
|
49
|
+
iconHtml = `<i class="material-icons">${args.iconRight}</i>`;
|
|
50
|
+
}
|
|
51
|
+
// TODO - why is anchor tag used in docs rather than button tag?
|
|
52
|
+
cell.innerHTML = `
|
|
53
|
+
<button ${disabled} class="${classes.join(' ')}">
|
|
54
|
+
${args.label}${iconHtml}
|
|
55
|
+
</button>
|
|
56
|
+
`;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return table;
|
|
60
|
+
},
|
|
61
|
+
args: {
|
|
62
|
+
label: 'Button',
|
|
63
|
+
classes: ['btn']
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const Elevated: StoryObj = {
|
|
68
|
+
...Basic,
|
|
69
|
+
args: {
|
|
70
|
+
label: 'Button',
|
|
71
|
+
classes: ['btn', 'elevated']
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const FloatingWithText: StoryObj = {
|
|
76
|
+
...Basic,
|
|
77
|
+
args: {
|
|
78
|
+
label: 'B',
|
|
79
|
+
classes: ['btn-floating']
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const FloatingWithIcon: StoryObj = {
|
|
84
|
+
...Basic,
|
|
85
|
+
args: {
|
|
86
|
+
label: '',
|
|
87
|
+
icon: 'edit',
|
|
88
|
+
classes: ['btn-floating']
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const IconLeft: StoryObj = {
|
|
93
|
+
...Basic,
|
|
94
|
+
args: {
|
|
95
|
+
label: 'Button',
|
|
96
|
+
iconLeft: 'cloud',
|
|
97
|
+
classes: ['btn']
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export const IconRight: StoryObj = {
|
|
102
|
+
...Basic,
|
|
103
|
+
args: {
|
|
104
|
+
label: 'Submit',
|
|
105
|
+
iconRight: 'send',
|
|
106
|
+
classes: ['btn']
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export const FloatingActionButton: StoryObj = {
|
|
111
|
+
render() {
|
|
112
|
+
return `
|
|
113
|
+
<div class="fixed-action-btn">
|
|
114
|
+
<a class="btn-floating btn-large red">
|
|
115
|
+
<i class="large material-icons">mode_edit</i>
|
|
116
|
+
</a>
|
|
117
|
+
<ul>
|
|
118
|
+
<li><a class="btn-floating red"><i class="material-icons">insert_chart</i></a></li>
|
|
119
|
+
<li><a class="btn-floating yellow darken-1"><i class="material-icons">format_quote</i></a></li>
|
|
120
|
+
<li><a class="btn-floating green"><i class="material-icons">publish</i></a></li>
|
|
121
|
+
<li><a class="btn-floating blue"><i class="material-icons">attach_file</i></a></li>
|
|
122
|
+
</ul>
|
|
123
|
+
</div>
|
|
124
|
+
|
|
125
|
+
<div class="fixed-action-btn horizontal">
|
|
126
|
+
<a class="btn-floating btn-large red">
|
|
127
|
+
<i class="large material-icons">mode_edit</i>
|
|
128
|
+
</a>
|
|
129
|
+
<ul>
|
|
130
|
+
<li><a class="btn-floating red"><i class="material-icons">insert_chart</i></a></li>
|
|
131
|
+
<li><a class="btn-floating yellow darken-1"><i class="material-icons">format_quote</i></a></li>
|
|
132
|
+
<li><a class="btn-floating green"><i class="material-icons">publish</i></a></li>
|
|
133
|
+
<li><a class="btn-floating blue"><i class="material-icons">attach_file</i></a></li>
|
|
134
|
+
</ul>
|
|
135
|
+
</div>
|
|
136
|
+
|
|
137
|
+
<div class="fixed-action-btn click-to-toggle">
|
|
138
|
+
<a class="btn-floating btn-large red">
|
|
139
|
+
<i class="large material-icons">mode_edit</i>
|
|
140
|
+
</a>
|
|
141
|
+
<ul>
|
|
142
|
+
<li><a class="btn-floating red"><i class="material-icons">insert_chart</i></a></li>
|
|
143
|
+
<li><a class="btn-floating yellow darken-1"><i class="material-icons">format_quote</i></a></li>
|
|
144
|
+
<li><a class="btn-floating green"><i class="material-icons">publish</i></a></li>
|
|
145
|
+
<li><a class="btn-floating blue"><i class="material-icons">attach_file</i></a></li>
|
|
146
|
+
</ul>
|
|
147
|
+
</div>
|
|
148
|
+
`;
|
|
149
|
+
}
|
|
150
|
+
};
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { Component, BaseOptions, InitElements, MElement, Openable } from '../../src/component';
|
|
2
|
+
import { Utils } from '../../src/utils';
|
|
3
|
+
|
|
4
|
+
interface FloatingActionButtonOptions extends BaseOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Direction FAB menu opens.
|
|
7
|
+
* @default "top"
|
|
8
|
+
*/
|
|
9
|
+
direction: 'top' | 'right' | 'bottom' | 'left';
|
|
10
|
+
/**
|
|
11
|
+
* true: FAB menu appears on hover, false: FAB menu appears on click.
|
|
12
|
+
* @default true
|
|
13
|
+
*/
|
|
14
|
+
hoverEnabled: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Enable transit the FAB into a toolbar on click.
|
|
17
|
+
* @default false
|
|
18
|
+
*/
|
|
19
|
+
toolbarEnabled: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const _defaults: FloatingActionButtonOptions = {
|
|
23
|
+
direction: 'top',
|
|
24
|
+
hoverEnabled: true,
|
|
25
|
+
toolbarEnabled: false
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
class FloatingActionButton extends Component<FloatingActionButtonOptions> implements Openable {
|
|
29
|
+
#anchor: HTMLAnchorElement;
|
|
30
|
+
#menu: HTMLElement | null;
|
|
31
|
+
#floatingBtns: HTMLElement[];
|
|
32
|
+
#floatingBtnsReverse: HTMLElement[];
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Describes open/close state of FAB.
|
|
36
|
+
*/
|
|
37
|
+
isOpen: boolean;
|
|
38
|
+
offsetY: number;
|
|
39
|
+
offsetX: number;
|
|
40
|
+
btnBottom: number;
|
|
41
|
+
btnLeft: number;
|
|
42
|
+
btnWidth: number;
|
|
43
|
+
|
|
44
|
+
constructor(el: HTMLElement, options: Partial<FloatingActionButtonOptions>) {
|
|
45
|
+
super(el, options, FloatingActionButton);
|
|
46
|
+
this.el['M_FloatingActionButton'] = this;
|
|
47
|
+
|
|
48
|
+
this.options = {
|
|
49
|
+
...FloatingActionButton.defaults,
|
|
50
|
+
...options
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
this.isOpen = false;
|
|
54
|
+
this.#anchor = this.el.querySelector('a');
|
|
55
|
+
this.#menu = this.el.querySelector('ul');
|
|
56
|
+
this.#floatingBtns = Array.from(this.el.querySelectorAll('ul .btn-floating'));
|
|
57
|
+
this.#floatingBtnsReverse = this.#floatingBtns.reverse();
|
|
58
|
+
this.offsetY = 0;
|
|
59
|
+
this.offsetX = 0;
|
|
60
|
+
|
|
61
|
+
this.el.classList.add(`direction-${this.options.direction}`);
|
|
62
|
+
this.#anchor.tabIndex = 0;
|
|
63
|
+
this.#menu.ariaExpanded = 'false';
|
|
64
|
+
if (this.options.direction === 'top') this.offsetY = 40;
|
|
65
|
+
else if (this.options.direction === 'right') this.offsetX = -40;
|
|
66
|
+
else if (this.options.direction === 'bottom') this.offsetY = -40;
|
|
67
|
+
else this.offsetX = 40;
|
|
68
|
+
this.#setupEventHandlers();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static get defaults() {
|
|
72
|
+
return _defaults;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Initializes instance of FloatingActionButton.
|
|
77
|
+
* @param el HTML element.
|
|
78
|
+
* @param options Component options.
|
|
79
|
+
*/
|
|
80
|
+
static init(
|
|
81
|
+
el: HTMLElement,
|
|
82
|
+
options?: Partial<FloatingActionButtonOptions>
|
|
83
|
+
): FloatingActionButton;
|
|
84
|
+
/**
|
|
85
|
+
* Initializes instances of FloatingActionButton.
|
|
86
|
+
* @param els HTML elements.
|
|
87
|
+
* @param options Component options.
|
|
88
|
+
*/
|
|
89
|
+
static init(
|
|
90
|
+
els: InitElements<MElement>,
|
|
91
|
+
options?: Partial<FloatingActionButtonOptions>
|
|
92
|
+
): FloatingActionButton[];
|
|
93
|
+
/**
|
|
94
|
+
* Initializes instances of FloatingActionButton.
|
|
95
|
+
* @param els HTML elements.
|
|
96
|
+
* @param options Component options.
|
|
97
|
+
*/
|
|
98
|
+
static init(
|
|
99
|
+
els: HTMLElement | InitElements<MElement>,
|
|
100
|
+
options: Partial<FloatingActionButtonOptions> = {}
|
|
101
|
+
): FloatingActionButton | FloatingActionButton[] {
|
|
102
|
+
return super.init(els, options, FloatingActionButton);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
static getInstance(el: HTMLElement): FloatingActionButton {
|
|
106
|
+
return el['M_FloatingActionButton'];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
destroy() {
|
|
110
|
+
this.#removeEventHandlers();
|
|
111
|
+
this.el['M_FloatingActionButton'] = undefined;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
#setupEventHandlers() {
|
|
115
|
+
if (this.options.hoverEnabled && !this.options.toolbarEnabled) {
|
|
116
|
+
this.el.addEventListener('mouseenter', this.open);
|
|
117
|
+
this.el.addEventListener('mouseleave', this.close);
|
|
118
|
+
} else {
|
|
119
|
+
this.el.addEventListener('click', this.#handleFABClick);
|
|
120
|
+
}
|
|
121
|
+
this.el.addEventListener('keypress', this.#handleFABKeyPress);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
#removeEventHandlers() {
|
|
125
|
+
if (this.options.hoverEnabled && !this.options.toolbarEnabled) {
|
|
126
|
+
this.el.removeEventListener('mouseenter', this.open);
|
|
127
|
+
this.el.removeEventListener('mouseleave', this.close);
|
|
128
|
+
} else {
|
|
129
|
+
this.el.removeEventListener('click', this.#handleFABClick);
|
|
130
|
+
}
|
|
131
|
+
this.el.removeEventListener('keypress', this.#handleFABKeyPress);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
#handleFABClick = () => {
|
|
135
|
+
this.#handleFABToggle();
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
#handleFABKeyPress = (e) => {
|
|
139
|
+
if (Utils.keys.ENTER.includes(e.key)) {
|
|
140
|
+
this.#handleFABToggle();
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
#handleFABToggle = () => {
|
|
145
|
+
if (this.isOpen) {
|
|
146
|
+
this.close();
|
|
147
|
+
} else {
|
|
148
|
+
this.open();
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
#handleDocumentClick = (e: MouseEvent) => {
|
|
153
|
+
const elem = e.target;
|
|
154
|
+
if (elem !== this.#menu) this.close();
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Open FAB.
|
|
159
|
+
*/
|
|
160
|
+
open = (): void => {
|
|
161
|
+
if (this.isOpen) return;
|
|
162
|
+
if (this.options.toolbarEnabled) this.#animateInToolbar();
|
|
163
|
+
else this.#animateInFAB();
|
|
164
|
+
this.isOpen = true;
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Close FAB.
|
|
169
|
+
*/
|
|
170
|
+
close = (): void => {
|
|
171
|
+
if (!this.isOpen) return;
|
|
172
|
+
if (this.options.toolbarEnabled) {
|
|
173
|
+
window.removeEventListener('scroll', this.close, true);
|
|
174
|
+
document.body.removeEventListener('click', this.#handleDocumentClick, true);
|
|
175
|
+
} else {
|
|
176
|
+
this.#animateOutFAB();
|
|
177
|
+
}
|
|
178
|
+
this.isOpen = false;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
#animateInFAB() {
|
|
182
|
+
this.el.classList.add('active');
|
|
183
|
+
this.#menu.ariaExpanded = 'true';
|
|
184
|
+
const delayIncrement = 40;
|
|
185
|
+
const duration = 275;
|
|
186
|
+
|
|
187
|
+
this.#floatingBtnsReverse.forEach((el, index) => {
|
|
188
|
+
const delay = delayIncrement * index;
|
|
189
|
+
el.style.transition = 'none';
|
|
190
|
+
el.style.opacity = '0';
|
|
191
|
+
el.style.transform = `translate(${this.offsetX}px, ${this.offsetY}px) scale(0.4)`;
|
|
192
|
+
setTimeout(() => {
|
|
193
|
+
// from:
|
|
194
|
+
el.style.opacity = '0.4';
|
|
195
|
+
// easeInOutQuad
|
|
196
|
+
setTimeout(() => {
|
|
197
|
+
// to:
|
|
198
|
+
el.style.transition = `opacity ${duration}ms ease, transform ${duration}ms ease`;
|
|
199
|
+
el.style.opacity = '1';
|
|
200
|
+
el.style.transform = 'translate(0, 0) scale(1)';
|
|
201
|
+
el.tabIndex = 0;
|
|
202
|
+
}, 1);
|
|
203
|
+
}, delay);
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
#animateOutFAB() {
|
|
208
|
+
const duration = 175;
|
|
209
|
+
setTimeout(() => {
|
|
210
|
+
this.el.classList.remove('active');
|
|
211
|
+
this.#menu.ariaExpanded = 'false';
|
|
212
|
+
}, duration);
|
|
213
|
+
this.#floatingBtnsReverse.forEach((el) => {
|
|
214
|
+
el.style.transition = `opacity ${duration}ms ease, transform ${duration}ms ease`;
|
|
215
|
+
// to
|
|
216
|
+
el.style.opacity = '0';
|
|
217
|
+
el.style.transform = `translate(${this.offsetX}px, ${this.offsetY}px) scale(0.4)`;
|
|
218
|
+
el.tabIndex = -1;
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
#animateInToolbar() {
|
|
223
|
+
const windowWidth = window.innerWidth;
|
|
224
|
+
const windowHeight = window.innerHeight;
|
|
225
|
+
const btnRect = this.el.getBoundingClientRect();
|
|
226
|
+
|
|
227
|
+
const backdrop = document.createElement('div'),
|
|
228
|
+
scaleFactor = windowWidth / backdrop[0].clientWidth,
|
|
229
|
+
fabColor = getComputedStyle(this.#anchor).backgroundColor; // css('background-color');
|
|
230
|
+
backdrop.classList.add('fab-backdrop'); // $('<div class="fab-backdrop"></div>');
|
|
231
|
+
backdrop.style.backgroundColor = fabColor;
|
|
232
|
+
this.#anchor.append(backdrop);
|
|
233
|
+
|
|
234
|
+
this.offsetX = btnRect.left - windowWidth / 2 + btnRect.width / 2;
|
|
235
|
+
this.offsetY = windowHeight - btnRect.bottom;
|
|
236
|
+
this.btnBottom = btnRect.bottom;
|
|
237
|
+
this.btnLeft = btnRect.left;
|
|
238
|
+
this.btnWidth = btnRect.width;
|
|
239
|
+
|
|
240
|
+
// Set initial state
|
|
241
|
+
this.el.classList.add('active');
|
|
242
|
+
this.el.style.textAlign = 'center';
|
|
243
|
+
this.el.style.width = '100%';
|
|
244
|
+
this.el.style.bottom = '0';
|
|
245
|
+
this.el.style.left = '0';
|
|
246
|
+
this.el.style.transform = 'translateX(' + this.offsetX + 'px)';
|
|
247
|
+
this.el.style.transition = 'none';
|
|
248
|
+
this.#menu.ariaExpanded = 'true';
|
|
249
|
+
|
|
250
|
+
this.#anchor.style.transform = `translateY(${this.offsetY}px`;
|
|
251
|
+
this.#anchor.style.transition = 'none';
|
|
252
|
+
|
|
253
|
+
setTimeout(() => {
|
|
254
|
+
this.el.style.transform = '';
|
|
255
|
+
this.el.style.transition =
|
|
256
|
+
'transform .2s cubic-bezier(0.550, 0.085, 0.680, 0.530), background-color 0s linear .2s';
|
|
257
|
+
|
|
258
|
+
this.#anchor.style.overflow = 'visible';
|
|
259
|
+
this.#anchor.style.transform = '';
|
|
260
|
+
this.#anchor.style.transition = 'transform .2s';
|
|
261
|
+
|
|
262
|
+
setTimeout(() => {
|
|
263
|
+
this.el.style.overflow = 'hidden';
|
|
264
|
+
this.el.style.backgroundColor = fabColor;
|
|
265
|
+
|
|
266
|
+
backdrop.style.transform = 'scale(' + scaleFactor + ')';
|
|
267
|
+
backdrop.style.transition = 'transform .2s cubic-bezier(0.550, 0.055, 0.675, 0.190)';
|
|
268
|
+
|
|
269
|
+
this.#menu.querySelectorAll('li > a').forEach((a: HTMLAnchorElement) => {
|
|
270
|
+
a.style.opacity = '1';
|
|
271
|
+
a.tabIndex = 0;
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
// Scroll to close.
|
|
275
|
+
window.addEventListener('scroll', this.close, true);
|
|
276
|
+
document.body.addEventListener('click', this.#handleDocumentClick, true);
|
|
277
|
+
}, 100);
|
|
278
|
+
}, 0);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export { FloatingActionButton, FloatingActionButtonOptions };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Number, Text } from '../atomic/atomic.mjs';
|
|
2
|
+
import { Card } from '../card/card.mjs';
|
|
3
|
+
import { Button } from './button.mjs';
|
|
4
|
+
|
|
5
|
+
// Example App (isomorphic javascript)
|
|
6
|
+
|
|
7
|
+
function createCounterApp() {
|
|
8
|
+
return new Card({
|
|
9
|
+
children: [
|
|
10
|
+
new Text('Counter Example').setTagName('div'),
|
|
11
|
+
new Number(9),
|
|
12
|
+
new Button('➕'),
|
|
13
|
+
new Button('➖')
|
|
14
|
+
]
|
|
15
|
+
}).addClassname('p-3');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { createCounterApp };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
describe('Fab Plugin:', () => {
|
|
2
|
+
const fixture = `<div class="fixed-action-btn">
|
|
3
|
+
<a class="btn-floating btn-large red">
|
|
4
|
+
<i class="large material-icons">mode_edit</i>
|
|
5
|
+
</a>
|
|
6
|
+
<ul>
|
|
7
|
+
<li><a class="btn-floating red"><i class="material-icons">insert_chart</i></a></li>
|
|
8
|
+
<li><a class="btn-floating yellow darken-1"><i class="material-icons">format_quote</i></a></li>
|
|
9
|
+
<li><a class="btn-floating green"><i class="material-icons">publish</i></a></li>
|
|
10
|
+
<li><a class="btn-floating blue"><i class="material-icons">attach_file</i></a></li>
|
|
11
|
+
</ul>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<div class="fixed-action-btn horizontal">
|
|
15
|
+
<a class="btn-floating btn-large red">
|
|
16
|
+
<i class="large material-icons">mode_edit</i>
|
|
17
|
+
</a>
|
|
18
|
+
<ul>
|
|
19
|
+
<li><a class="btn-floating red"><i class="material-icons">insert_chart</i></a></li>
|
|
20
|
+
<li><a class="btn-floating yellow darken-1"><i class="material-icons">format_quote</i></a></li>
|
|
21
|
+
<li><a class="btn-floating green"><i class="material-icons">publish</i></a></li>
|
|
22
|
+
<li><a class="btn-floating blue"><i class="material-icons">attach_file</i></a></li>
|
|
23
|
+
</ul>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div class="fixed-action-btn click-to-toggle">
|
|
27
|
+
<a class="btn-floating btn-large red">
|
|
28
|
+
<i class="large material-icons">mode_edit</i>
|
|
29
|
+
</a>
|
|
30
|
+
<ul>
|
|
31
|
+
<li><a class="btn-floating red"><i class="material-icons">insert_chart</i></a></li>
|
|
32
|
+
<li><a class="btn-floating yellow darken-1"><i class="material-icons">format_quote</i></a></li>
|
|
33
|
+
<li><a class="btn-floating green"><i class="material-icons">publish</i></a></li>
|
|
34
|
+
<li><a class="btn-floating blue"><i class="material-icons">attach_file</i></a></li>
|
|
35
|
+
</ul>
|
|
36
|
+
</div>
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
beforeEach(() => XloadHtml(fixture));
|
|
40
|
+
afterEach(() => XunloadFixtures());
|
|
41
|
+
|
|
42
|
+
describe('Floating Action Button', () => {
|
|
43
|
+
it('should open correctly', (done) => {
|
|
44
|
+
const normalFAB = document.querySelector('.fixed-action-btn');
|
|
45
|
+
M.FloatingActionButton.init(normalFAB);
|
|
46
|
+
const ul = normalFAB.querySelector('ul');
|
|
47
|
+
const ulStyle = getComputedStyle(ul);
|
|
48
|
+
expect(ulStyle.getPropertyValue('visibility')).toEqual(
|
|
49
|
+
'hidden',
|
|
50
|
+
'FAB menu div should be hidden initially'
|
|
51
|
+
);
|
|
52
|
+
setTimeout(() => {
|
|
53
|
+
mouseenter(normalFAB);
|
|
54
|
+
setTimeout(() => {
|
|
55
|
+
const ulStyle = getComputedStyle(ul);
|
|
56
|
+
expect(ulStyle.getPropertyValue('visibility')).toEqual(
|
|
57
|
+
'visible',
|
|
58
|
+
'FAB menu did not appear after mouseenter.'
|
|
59
|
+
);
|
|
60
|
+
done();
|
|
61
|
+
}, 400);
|
|
62
|
+
}, 100);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Number, Text } from '../atomic/atomic.mjs';
|
|
2
|
+
import { Button, Card } from './button.mjs';
|
|
3
|
+
|
|
4
|
+
// Example App (isomorphic javascript)
|
|
5
|
+
const app = new Card({
|
|
6
|
+
children: [
|
|
7
|
+
new Text('Example App').setTagName('div'), //
|
|
8
|
+
new Number(9),
|
|
9
|
+
new Button('➕'),
|
|
10
|
+
new Button('➖')
|
|
11
|
+
]
|
|
12
|
+
}).addClassname('p-3');
|
|
13
|
+
|
|
14
|
+
// Html
|
|
15
|
+
const html = app.toHTML();
|
|
16
|
+
console.log(html);
|