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,68 @@
|
|
|
1
|
+
@use '../../sass/variables' as *;
|
|
2
|
+
@use '../../sass/global' as *;
|
|
3
|
+
|
|
4
|
+
#toast-container {
|
|
5
|
+
display:block;
|
|
6
|
+
position: fixed;
|
|
7
|
+
z-index: 10000;
|
|
8
|
+
|
|
9
|
+
@media #{$small-and-down} {
|
|
10
|
+
min-width: 100%;
|
|
11
|
+
bottom: 0%;
|
|
12
|
+
}
|
|
13
|
+
@media #{$medium-only} {
|
|
14
|
+
left: 5%;
|
|
15
|
+
bottom: 7%;
|
|
16
|
+
max-width: 90%;
|
|
17
|
+
}
|
|
18
|
+
@media #{$large-and-up} {
|
|
19
|
+
top: 10%;
|
|
20
|
+
right: 7%;
|
|
21
|
+
max-width: 86%;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.toast {
|
|
26
|
+
@extend .z-depth-3;
|
|
27
|
+
border-radius: 4px;
|
|
28
|
+
top: 35px;
|
|
29
|
+
width: auto;
|
|
30
|
+
margin-top: 10px;
|
|
31
|
+
position: relative;
|
|
32
|
+
max-width: 100%;
|
|
33
|
+
height: auto;
|
|
34
|
+
min-height: 48px;
|
|
35
|
+
|
|
36
|
+
//line-height: 1.5em;
|
|
37
|
+
//padding: 10px 25px;
|
|
38
|
+
padding-left: 16px;
|
|
39
|
+
padding-right: 12px;
|
|
40
|
+
|
|
41
|
+
font-size: 14px;
|
|
42
|
+
font-weight: 500;
|
|
43
|
+
line-height: 20px;
|
|
44
|
+
|
|
45
|
+
color: var(--md-sys-color-inverse-on-surface);
|
|
46
|
+
background-color: var(--md-sys-color-inverse-surface);
|
|
47
|
+
|
|
48
|
+
display: flex;
|
|
49
|
+
align-items: center;
|
|
50
|
+
justify-content: space-between;
|
|
51
|
+
cursor: default;
|
|
52
|
+
|
|
53
|
+
.toast-action {
|
|
54
|
+
color: var(--md-sys-color-inverse-primary);
|
|
55
|
+
font-weight: 500;
|
|
56
|
+
margin-right: -25px;
|
|
57
|
+
margin-left: 3rem;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
&.rounded{
|
|
61
|
+
border-radius: 24px;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@media #{$small-and-down} {
|
|
65
|
+
width: 100%;
|
|
66
|
+
border-radius: 0;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
describe('Toasts:', () => {
|
|
2
|
+
afterEach(() => {
|
|
3
|
+
// Toast state (containers, pending dismiss timers) is static/shared across
|
|
4
|
+
// instances, and specs run in a random order. Without a hard reset here,
|
|
5
|
+
// a toast/container left over from one spec (or still mid-dismiss) leaks
|
|
6
|
+
// into the next one, making failures depend on run order.
|
|
7
|
+
M.Toast._toasts.forEach((toast) => toast.el.remove());
|
|
8
|
+
M.Toast._toasts = [];
|
|
9
|
+
M.Toast._removeContainer();
|
|
10
|
+
document.querySelectorAll('#toast-container').forEach((el) => el.remove());
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
describe('Toast javascript functions', () => {
|
|
14
|
+
it('should display and remove a toast', (done) => {
|
|
15
|
+
const instance = new M.Toast({
|
|
16
|
+
text: 'Test toast',
|
|
17
|
+
inDuration: 20,
|
|
18
|
+
displayLength: 100,
|
|
19
|
+
outDuration: 20
|
|
20
|
+
});
|
|
21
|
+
const wrapperWasCreated = document.querySelectorAll('#toast-container').length === 1;
|
|
22
|
+
expect(wrapperWasCreated).toEqual(true, 'because toast was created');
|
|
23
|
+
const toast = instance.el;
|
|
24
|
+
setTimeout(() => {
|
|
25
|
+
// is visible?
|
|
26
|
+
//const toasts = document.querySelectorAll('.toast');
|
|
27
|
+
//const toast = toasts[0];
|
|
28
|
+
//expect(toasts.length).toBe(1, 'because one toast was created');
|
|
29
|
+
expect(toast.getAttribute('role')).toBe('alert');
|
|
30
|
+
expect(toast.getAttribute('aria-live')).toBe('assertive');
|
|
31
|
+
expect(toast.getAttribute('aria-atomic')).toBe('true');
|
|
32
|
+
expect(toast).toBeVisible();
|
|
33
|
+
expect(toast.innerText).toBe('Test toast');
|
|
34
|
+
setTimeout(() => {
|
|
35
|
+
//const toasts = document.querySelectorAll('.toast');
|
|
36
|
+
expect(toast).toBeVisible();
|
|
37
|
+
//expect(toasts.length).toBe(1, 'because toast duration still on going');
|
|
38
|
+
setTimeout(() => {
|
|
39
|
+
//const toasts = document.querySelectorAll('.toast');
|
|
40
|
+
//console.log();
|
|
41
|
+
expect(typeof toast.el).toBe('undefined', 'because toast should be removed by now');
|
|
42
|
+
done();
|
|
43
|
+
}, 150);
|
|
44
|
+
}, 30);
|
|
45
|
+
}, 10);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// it('Opens a toast with HTML content', function(done) {
|
|
49
|
+
// let toastContent = document.createElement("span");
|
|
50
|
+
// toastContent.innerText = 'I am toast content';
|
|
51
|
+
// M.toast({html: toastContent.outerHTML, displayLength: 400});
|
|
52
|
+
// let toastSpan = document.querySelector('.toast span');
|
|
53
|
+
// expect(toastSpan.innerText).toBe('I am toast content');
|
|
54
|
+
// expect(toastSpan.innerText).not.toBe('I am toast');
|
|
55
|
+
// setTimeout(function() {
|
|
56
|
+
// done();
|
|
57
|
+
// }, 490);
|
|
58
|
+
// });
|
|
59
|
+
|
|
60
|
+
it('Toasts should call the callback function when dismissed', (done) => {
|
|
61
|
+
let wasCalled = false;
|
|
62
|
+
const callback = () => (wasCalled = true);
|
|
63
|
+
new M.Toast({
|
|
64
|
+
text: 'I am a toast',
|
|
65
|
+
inDuration: 10,
|
|
66
|
+
displayLength: 50,
|
|
67
|
+
outDuration: 10,
|
|
68
|
+
completeCallback: callback
|
|
69
|
+
});
|
|
70
|
+
setTimeout(() => {
|
|
71
|
+
expect(wasCalled).toBe(true, 'because the callback set it to true');
|
|
72
|
+
done();
|
|
73
|
+
}, 100);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should apply classes to toast', (done) => {
|
|
77
|
+
new M.Toast({
|
|
78
|
+
text: 'Hi',
|
|
79
|
+
displayLength: 100,
|
|
80
|
+
inDuration: 10,
|
|
81
|
+
outDuration: 10,
|
|
82
|
+
classes: 'round flat'
|
|
83
|
+
});
|
|
84
|
+
setTimeout(() => {
|
|
85
|
+
const toastFlat = document.querySelectorAll('.toast.round.flat');
|
|
86
|
+
expect(toastFlat.length).toBe(1, 'because the class parameter was passed with two classes');
|
|
87
|
+
done();
|
|
88
|
+
}, 20);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe('Toast _container null guard', () => {
|
|
93
|
+
afterEach(() => {
|
|
94
|
+
// Reset shared static state so other specs are unaffected
|
|
95
|
+
M.Toast.dismissAll();
|
|
96
|
+
M.Toast._removeContainer();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should not throw when _removeContainer is called with a null container', () => {
|
|
100
|
+
M.Toast._container = null;
|
|
101
|
+
expect(() => M.Toast._removeContainer()).not.toThrow();
|
|
102
|
+
expect(M.Toast._container).toBeNull('because there was no container to remove');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should not throw when _removeContainer is called twice', () => {
|
|
106
|
+
// First call removes a freshly created container, second call hits the guard.
|
|
107
|
+
M.Toast._createContainer();
|
|
108
|
+
expect(M.Toast._container).not.toBeNull('because a container was just created');
|
|
109
|
+
|
|
110
|
+
expect(() => M.Toast._removeContainer()).not.toThrow();
|
|
111
|
+
expect(M.Toast._container).toBeNull('because the container was just removed');
|
|
112
|
+
|
|
113
|
+
expect(() => M.Toast._removeContainer()).not.toThrow('because the guard protects the second call');
|
|
114
|
+
expect(M.Toast._container).toBeNull();
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('should not throw building a toast while _container is null', () => {
|
|
118
|
+
// Create a first toast so the container exists and _toasts is non-empty,
|
|
119
|
+
// then null the container to force the inconsistent state the guard handles
|
|
120
|
+
// (a second toast skips _createContainer because _toasts.length !== 0).
|
|
121
|
+
const first = new M.Toast({ text: 'First', displayLength: 50, inDuration: 10, outDuration: 10 });
|
|
122
|
+
expect(first.el).toBeDefined();
|
|
123
|
+
M.Toast._container = null;
|
|
124
|
+
|
|
125
|
+
let instance;
|
|
126
|
+
expect(() => {
|
|
127
|
+
instance = new M.Toast({ text: 'No container', displayLength: 50, inDuration: 10, outDuration: 10 });
|
|
128
|
+
}).not.toThrow('because _createToast guards the null container');
|
|
129
|
+
expect(instance.el).toBeDefined('because the toast element is still created without a container');
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import { BaseOptions } from '../../src/component';
|
|
2
|
+
|
|
3
|
+
export interface ToastOptions extends BaseOptions {
|
|
4
|
+
/**
|
|
5
|
+
* The content of the Toast.
|
|
6
|
+
* @default ""
|
|
7
|
+
*/
|
|
8
|
+
text: string;
|
|
9
|
+
/**
|
|
10
|
+
* Element Id for the tooltip.
|
|
11
|
+
* @default ""
|
|
12
|
+
*/
|
|
13
|
+
toastId?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Length in ms the Toast stays before dismissal.
|
|
16
|
+
* @default 4000
|
|
17
|
+
*/
|
|
18
|
+
displayLength: number;
|
|
19
|
+
/**
|
|
20
|
+
* Transition in duration in milliseconds.
|
|
21
|
+
* @default 300
|
|
22
|
+
*/
|
|
23
|
+
inDuration: number;
|
|
24
|
+
/**
|
|
25
|
+
* Transition out duration in milliseconds.
|
|
26
|
+
* @default 375
|
|
27
|
+
*/
|
|
28
|
+
outDuration: number;
|
|
29
|
+
/**
|
|
30
|
+
* Classes to be added to the toast element.
|
|
31
|
+
* @default ""
|
|
32
|
+
*/
|
|
33
|
+
classes: string;
|
|
34
|
+
/**
|
|
35
|
+
* Callback function called when toast is dismissed.
|
|
36
|
+
* @default null
|
|
37
|
+
*/
|
|
38
|
+
completeCallback: () => void;
|
|
39
|
+
/**
|
|
40
|
+
* The percentage of the toast's width it takes fora drag
|
|
41
|
+
* to dismiss a Toast.
|
|
42
|
+
* @default 0.8
|
|
43
|
+
*/
|
|
44
|
+
activationPercent: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const _defaults: ToastOptions = {
|
|
48
|
+
text: '',
|
|
49
|
+
displayLength: 4000,
|
|
50
|
+
inDuration: 300,
|
|
51
|
+
outDuration: 375,
|
|
52
|
+
classes: '',
|
|
53
|
+
completeCallback: null,
|
|
54
|
+
activationPercent: 0.8
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export class Toast {
|
|
58
|
+
/** The toast element. */
|
|
59
|
+
el: HTMLElement;
|
|
60
|
+
/**
|
|
61
|
+
* The remaining amount of time in ms that the toast
|
|
62
|
+
* will stay before dismissal.
|
|
63
|
+
*/
|
|
64
|
+
timeRemaining: number;
|
|
65
|
+
/**
|
|
66
|
+
* Describes the current pan state of the Toast.
|
|
67
|
+
*/
|
|
68
|
+
panning: boolean;
|
|
69
|
+
options: ToastOptions;
|
|
70
|
+
message: string;
|
|
71
|
+
counterInterval: NodeJS.Timeout | number;
|
|
72
|
+
wasSwiped: boolean;
|
|
73
|
+
startingXPos: number;
|
|
74
|
+
xPos: number;
|
|
75
|
+
time: number;
|
|
76
|
+
deltaX: number;
|
|
77
|
+
velocityX: number;
|
|
78
|
+
|
|
79
|
+
static _toasts: Toast[];
|
|
80
|
+
private static _container: HTMLElement | null;
|
|
81
|
+
static _draggedToast: Toast;
|
|
82
|
+
|
|
83
|
+
constructor(options: Partial<ToastOptions>) {
|
|
84
|
+
this.options = {
|
|
85
|
+
...Toast.defaults,
|
|
86
|
+
...options
|
|
87
|
+
};
|
|
88
|
+
this.message = this.options.text;
|
|
89
|
+
this.panning = false;
|
|
90
|
+
this.timeRemaining = this.options.displayLength;
|
|
91
|
+
if (!Toast._container) {
|
|
92
|
+
Toast._createContainer();
|
|
93
|
+
}
|
|
94
|
+
// Create new toast
|
|
95
|
+
Toast._toasts.push(this);
|
|
96
|
+
const toastElement = this._createToast();
|
|
97
|
+
toastElement['M_Toast'] = this;
|
|
98
|
+
this.el = toastElement;
|
|
99
|
+
this._animateIn();
|
|
100
|
+
this._setTimer();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
static get defaults(): ToastOptions {
|
|
104
|
+
return _defaults;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
static getInstance(el: HTMLElement): Toast {
|
|
108
|
+
return el['M_Toast'];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
static _createContainer() {
|
|
112
|
+
const container = document.createElement('div');
|
|
113
|
+
container.setAttribute('id', 'toast-container');
|
|
114
|
+
// Add event handler
|
|
115
|
+
container.addEventListener('touchstart', Toast._onDragStart);
|
|
116
|
+
container.addEventListener('touchmove', Toast._onDragMove);
|
|
117
|
+
container.addEventListener('touchend', Toast._onDragEnd);
|
|
118
|
+
container.addEventListener('mousedown', Toast._onDragStart);
|
|
119
|
+
document.addEventListener('mousemove', Toast._onDragMove);
|
|
120
|
+
document.addEventListener('mouseup', Toast._onDragEnd);
|
|
121
|
+
document.body.appendChild(container);
|
|
122
|
+
Toast._container = container;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
static _removeContainer() {
|
|
126
|
+
document.removeEventListener('mousemove', Toast._onDragMove);
|
|
127
|
+
document.removeEventListener('mouseup', Toast._onDragEnd);
|
|
128
|
+
if (Toast._container) {
|
|
129
|
+
Toast._container.remove();
|
|
130
|
+
Toast._container = null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
static _onDragStart(e: TouchEvent | MouseEvent) {
|
|
135
|
+
if (e.target && (<HTMLElement>e.target).closest('.toast')) {
|
|
136
|
+
const toastElem = (<HTMLElement>e.target).closest('.toast');
|
|
137
|
+
const toast: Toast = toastElem['M_Toast'];
|
|
138
|
+
toast.panning = true;
|
|
139
|
+
Toast._draggedToast = toast;
|
|
140
|
+
toast.el.classList.add('panning');
|
|
141
|
+
toast.el.style.transition = '';
|
|
142
|
+
toast.startingXPos = Toast._xPos(e);
|
|
143
|
+
toast.time = Date.now();
|
|
144
|
+
toast.xPos = Toast._xPos(e);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
static _onDragMove(e: TouchEvent | MouseEvent) {
|
|
149
|
+
if (!!Toast._draggedToast) {
|
|
150
|
+
e.preventDefault();
|
|
151
|
+
const toast = Toast._draggedToast;
|
|
152
|
+
toast.deltaX = Math.abs(toast.xPos - Toast._xPos(e));
|
|
153
|
+
toast.xPos = Toast._xPos(e);
|
|
154
|
+
toast.velocityX = toast.deltaX / (Date.now() - toast.time);
|
|
155
|
+
toast.time = Date.now();
|
|
156
|
+
|
|
157
|
+
const totalDeltaX = toast.xPos - toast.startingXPos;
|
|
158
|
+
const activationDistance = toast.el.offsetWidth * toast.options.activationPercent;
|
|
159
|
+
toast.el.style.transform = `translateX(${totalDeltaX}px)`;
|
|
160
|
+
toast.el.style.opacity = (1 - Math.abs(totalDeltaX / activationDistance)).toString();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
static _onDragEnd() {
|
|
165
|
+
if (!!Toast._draggedToast) {
|
|
166
|
+
const toast = Toast._draggedToast;
|
|
167
|
+
toast.panning = false;
|
|
168
|
+
toast.el.classList.remove('panning');
|
|
169
|
+
|
|
170
|
+
const totalDeltaX = toast.xPos - toast.startingXPos;
|
|
171
|
+
const activationDistance = toast.el.offsetWidth * toast.options.activationPercent;
|
|
172
|
+
const shouldBeDismissed = Math.abs(totalDeltaX) > activationDistance || toast.velocityX > 1;
|
|
173
|
+
|
|
174
|
+
// Remove toast
|
|
175
|
+
if (shouldBeDismissed) {
|
|
176
|
+
toast.wasSwiped = true;
|
|
177
|
+
toast.dismiss();
|
|
178
|
+
// Animate toast back to original position
|
|
179
|
+
} else {
|
|
180
|
+
toast.el.style.transition = 'transform .2s, opacity .2s';
|
|
181
|
+
toast.el.style.transform = '';
|
|
182
|
+
toast.el.style.opacity = '';
|
|
183
|
+
}
|
|
184
|
+
Toast._draggedToast = null;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
static _xPos(e: TouchEvent | MouseEvent) {
|
|
189
|
+
if (e.type.startsWith('touch') && (e as TouchEvent).targetTouches.length >= 1) {
|
|
190
|
+
return (e as TouchEvent).targetTouches[0].clientX;
|
|
191
|
+
}
|
|
192
|
+
// mouse event
|
|
193
|
+
return (e as MouseEvent).clientX;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* dismiss all toasts.
|
|
198
|
+
*/
|
|
199
|
+
static dismissAll() {
|
|
200
|
+
for (const toastIndex in Toast._toasts) {
|
|
201
|
+
Toast._toasts[toastIndex].dismiss();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
_createToast() {
|
|
206
|
+
let toast: HTMLElement = this.options.toastId
|
|
207
|
+
? document.getElementById(this.options.toastId)
|
|
208
|
+
: document.createElement('div');
|
|
209
|
+
if (toast instanceof HTMLTemplateElement) {
|
|
210
|
+
const node = (toast as HTMLTemplateElement).content.cloneNode(true);
|
|
211
|
+
toast = (node as HTMLElement).firstElementChild as HTMLElement;
|
|
212
|
+
}
|
|
213
|
+
toast.classList.add('toast');
|
|
214
|
+
toast.setAttribute('role', 'alert');
|
|
215
|
+
toast.setAttribute('aria-live', 'assertive');
|
|
216
|
+
toast.setAttribute('aria-atomic', 'true');
|
|
217
|
+
// Add custom classes onto toast
|
|
218
|
+
if (this.options.classes.length > 0) {
|
|
219
|
+
toast.classList.add(...this.options.classes.split(' '));
|
|
220
|
+
}
|
|
221
|
+
if (this.message) toast.innerText = this.message;
|
|
222
|
+
if (Toast._container) {
|
|
223
|
+
Toast._container.appendChild(toast);
|
|
224
|
+
}
|
|
225
|
+
return toast;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
_animateIn() {
|
|
229
|
+
// Animate toast in
|
|
230
|
+
this.el.style.display = '';
|
|
231
|
+
this.el.style.opacity = '0';
|
|
232
|
+
// easeOutCubic
|
|
233
|
+
this.el.style.transition = `
|
|
234
|
+
top ${this.options.inDuration}ms ease,
|
|
235
|
+
opacity ${this.options.inDuration}ms ease
|
|
236
|
+
`;
|
|
237
|
+
setTimeout(() => {
|
|
238
|
+
this.el.style.top = '0';
|
|
239
|
+
this.el.style.opacity = '1';
|
|
240
|
+
}, 1);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Create setInterval which automatically removes toast when timeRemaining >= 0
|
|
245
|
+
* has been reached.
|
|
246
|
+
*/
|
|
247
|
+
_setTimer() {
|
|
248
|
+
if (this.timeRemaining !== Infinity) {
|
|
249
|
+
this.counterInterval = setInterval(() => {
|
|
250
|
+
// If toast is not being dragged, decrease its time remaining
|
|
251
|
+
if (!this.panning) {
|
|
252
|
+
this.timeRemaining -= 20;
|
|
253
|
+
}
|
|
254
|
+
// Animate toast out
|
|
255
|
+
if (this.timeRemaining <= 0) {
|
|
256
|
+
this.dismiss();
|
|
257
|
+
}
|
|
258
|
+
}, 20);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Dismiss toast with animation.
|
|
264
|
+
*/
|
|
265
|
+
dismiss() {
|
|
266
|
+
clearInterval(this.counterInterval);
|
|
267
|
+
const activationDistance = this.el.offsetWidth * this.options.activationPercent;
|
|
268
|
+
|
|
269
|
+
if (this.wasSwiped) {
|
|
270
|
+
this.el.style.transition = 'transform .05s, opacity .05s';
|
|
271
|
+
this.el.style.transform = `translateX(${activationDistance}px)`;
|
|
272
|
+
this.el.style.opacity = '0';
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// easeOutExpo
|
|
276
|
+
this.el.style.transition = `
|
|
277
|
+
margin ${this.options.outDuration}ms ease,
|
|
278
|
+
opacity ${this.options.outDuration}ms ease`;
|
|
279
|
+
|
|
280
|
+
setTimeout(() => {
|
|
281
|
+
this.el.style.opacity = '0';
|
|
282
|
+
this.el.style.marginTop = '-40px';
|
|
283
|
+
}, 1);
|
|
284
|
+
|
|
285
|
+
setTimeout(() => {
|
|
286
|
+
// Call the optional callback
|
|
287
|
+
if (typeof this.options.completeCallback === 'function') {
|
|
288
|
+
this.options.completeCallback();
|
|
289
|
+
}
|
|
290
|
+
// Remove toast from DOM
|
|
291
|
+
if (this.el.id != this.options.toastId) {
|
|
292
|
+
this.el.remove();
|
|
293
|
+
const toastIndex = Toast._toasts.indexOf(this);
|
|
294
|
+
// indexOf returns -1 if this toast is no longer tracked (e.g. the
|
|
295
|
+
// static state was already reset elsewhere); splice(-1, 1) would
|
|
296
|
+
// otherwise silently remove an unrelated, still-active toast.
|
|
297
|
+
if (toastIndex !== -1) {
|
|
298
|
+
Toast._toasts.splice(toastIndex, 1);
|
|
299
|
+
}
|
|
300
|
+
if (Toast._toasts.length === 0) {
|
|
301
|
+
Toast._removeContainer();
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}, this.options.outDuration);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
static {
|
|
308
|
+
Toast._toasts = [];
|
|
309
|
+
Toast._container = null;
|
|
310
|
+
Toast._draggedToast = null;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
.switch {
|
|
2
|
+
--track-height: 32px;
|
|
3
|
+
--track-width: 52px;
|
|
4
|
+
--border-width: 2px;
|
|
5
|
+
--size-off: 16px;
|
|
6
|
+
--size-on: 24px;
|
|
7
|
+
--icon-size: 16px;
|
|
8
|
+
--gap-on: calc(((var(--track-height) - var(--size-on)) / 2) - var(--border-width));
|
|
9
|
+
--gap-off: calc(((var(--track-height) - var(--size-off)) / 2) - var(--border-width));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.switch,
|
|
13
|
+
.switch * {
|
|
14
|
+
-webkit-tap-highlight-color: transparent;
|
|
15
|
+
user-select: none;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.switch label {
|
|
19
|
+
cursor: pointer;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.switch label input[type=checkbox] {
|
|
23
|
+
opacity: 0;
|
|
24
|
+
width: 0;
|
|
25
|
+
height: 0;
|
|
26
|
+
|
|
27
|
+
// CHECKED
|
|
28
|
+
// Track
|
|
29
|
+
&:checked + .lever{
|
|
30
|
+
background-color: var(--md-sys-color-primary);
|
|
31
|
+
border-color: var(--md-sys-color-primary);
|
|
32
|
+
}
|
|
33
|
+
// Dot
|
|
34
|
+
&:checked + .lever {
|
|
35
|
+
&:before, &:after {
|
|
36
|
+
top: var(--gap-on);
|
|
37
|
+
left: calc(var(--track-width) - var(--size-on) - var(--gap-on) - 2 * var(--border-width));
|
|
38
|
+
width: var(--size-on);
|
|
39
|
+
height: var(--size-on);
|
|
40
|
+
}
|
|
41
|
+
&:after {
|
|
42
|
+
background-color: var(--md-sys-color-surface);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.switch label .lever {
|
|
48
|
+
content: "";
|
|
49
|
+
display: inline-block;
|
|
50
|
+
position: relative;
|
|
51
|
+
width: var(--track-width);
|
|
52
|
+
height: var(--track-height);
|
|
53
|
+
border-style: solid;
|
|
54
|
+
border-width: 2px;
|
|
55
|
+
border-color: var(--md-sys-color-outline);
|
|
56
|
+
|
|
57
|
+
//@extend .surface-variant;
|
|
58
|
+
background-color: var(--md-sys-color-surface-variant);
|
|
59
|
+
|
|
60
|
+
border-radius: 15px;
|
|
61
|
+
margin-right: 10px;
|
|
62
|
+
transition: background 0.3s ease;
|
|
63
|
+
vertical-align: middle;
|
|
64
|
+
margin: 0 16px;
|
|
65
|
+
|
|
66
|
+
// DOT
|
|
67
|
+
&:before, &:after {
|
|
68
|
+
content: "";
|
|
69
|
+
position: absolute;
|
|
70
|
+
display: inline-block;
|
|
71
|
+
width: var(--size-off);
|
|
72
|
+
height: var(--size-off);
|
|
73
|
+
border-radius: 50%;
|
|
74
|
+
|
|
75
|
+
left: var(--gap-off);
|
|
76
|
+
top: var(--gap-off);
|
|
77
|
+
|
|
78
|
+
transition: left 0.3s ease, background .3s ease, box-shadow 0.1s ease, transform .1s ease;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// NOT CHECKED [DOT]
|
|
82
|
+
&:after {
|
|
83
|
+
background-color: var(--md-sys-color-outline);
|
|
84
|
+
height: var(--size-off);
|
|
85
|
+
width: var(--size-off);
|
|
86
|
+
//@extend .surface-variant;
|
|
87
|
+
//box-shadow: 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
input[type=checkbox]:not(:disabled) ~ .lever:active:before,
|
|
92
|
+
input[type=checkbox]:not(:disabled).tabbed:focus ~ .lever::before,
|
|
93
|
+
input[type=checkbox]:not(:disabled) ~ .lever:hover::before {
|
|
94
|
+
transform: scale(2.4);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
input[type=checkbox]:checked:not(:disabled) ~ .lever:hover::before {
|
|
98
|
+
background-color: color-mix(in srgb, transparent, var(--md-sys-color-primary) 6%);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Switch active style
|
|
102
|
+
input[type=checkbox]:checked:not(:disabled) ~ .lever:active::before,
|
|
103
|
+
input[type=checkbox]:checked:not(:disabled).tabbed:focus ~ .lever::before {
|
|
104
|
+
background-color: color-mix(in srgb, transparent, var(--md-sys-color-primary) 18%);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
input[type=checkbox]:not(:disabled) ~ .lever:hover::before {
|
|
108
|
+
background-color: rgba(0, 0, 0, 0.04);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
input[type=checkbox]:not(:disabled) ~ .lever:active:before,
|
|
112
|
+
input[type=checkbox]:not(:disabled).tabbed:focus ~ .lever::before {
|
|
113
|
+
background-color: rgba(0, 0, 0, 0.12);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Disabled Styles
|
|
117
|
+
.switch input[type=checkbox][disabled] + .lever {
|
|
118
|
+
cursor: default;
|
|
119
|
+
opacity: 0.5;
|
|
120
|
+
}
|
|
121
|
+
|