makki-toast 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +5 -0
  2. package/index.js +287 -0
  3. package/package.json +14 -0
  4. package/style.css +168 -0
package/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # Makki Toast
2
+
3
+ Fancy makki toast
4
+
5
+ Create by Daniel Jimenez
package/index.js ADDED
@@ -0,0 +1,287 @@
1
+ "use strict";
2
+
3
+ import './style.css'
4
+
5
+ const DEFAULT_VALUES = {
6
+ autoClose: 5000,
7
+ darkMode: false,
8
+ status: 'success',
9
+ backgroundColor: null,
10
+ canClose: true,
11
+ icon: null,
12
+ message: 'Example message',
13
+ position: 'top-right',
14
+ showProgress: true,
15
+ }
16
+
17
+ export class Toast {
18
+ show(options) {
19
+ new ToastAlert(options);
20
+ }
21
+ }
22
+
23
+ class ToastAlert {
24
+ #toastElement
25
+ #removeBinded
26
+ #statusValue
27
+ #darkModeValue
28
+ #noHaveError
29
+ #iconElement
30
+ #visibleTimeSince
31
+ #autoClose
32
+ #progressInterval
33
+ #autoCloseInterval
34
+
35
+ constructor(options) {
36
+ this.#toastElement = document.createElement('div')
37
+ this.#noHaveError = true
38
+ this.#visibleTimeSince = new Date()
39
+ this.#toastElement.classList.add('makki-toast')
40
+ requestAnimationFrame(() => { this.#toastElement.classList.add('makki-show') })
41
+ this.#removeBinded = () => this.#remove()
42
+ Object.entries({ ...DEFAULT_VALUES, ...options }).forEach(([key, value]) => {
43
+ this[key] = value
44
+ })
45
+ }
46
+
47
+ set autoClose(value) {
48
+ this.#autoClose = value
49
+ if (value === false) return
50
+ if (this.#autoCloseInterval != null) clearTimeout(this.#autoCloseInterval)
51
+ this.#autoCloseInterval = setTimeout(() => { this.#remove() }, value)
52
+ }
53
+
54
+ set darkMode(value) {
55
+ this.#darkModeValue = value
56
+ if (value)
57
+ this.#toastElement.classList.add('makki-dark-toast')
58
+ else
59
+ this.#toastElement.classList.add('makki-light-toast')
60
+ }
61
+
62
+ set status(value) {
63
+ try {
64
+ this.#statusValue = value
65
+ validateStatus(value)
66
+ if (value === 'success')
67
+ this.#toastElement.classList.add('makki-success')
68
+ else if (value === 'warning')
69
+ this.#toastElement.classList.add('makki-warning')
70
+ else if (value === 'danger')
71
+ this.#toastElement.classList.add('makki-danger')
72
+ else if (value === 'none')
73
+ this.#toastElement.classList.add('makki-none')
74
+ } catch (error) {
75
+ console.error(error)
76
+ this.#noHaveError = false
77
+ }
78
+ }
79
+
80
+ set backgroundColor(value) {
81
+ let hexColor
82
+ try {
83
+ if(value == null || value == '' || this.#statusValue != 'none')
84
+ return
85
+ validateBackgroundColor(value)
86
+ let root = document.querySelector(':root')
87
+ root.style.setProperty('--makki-toast-bg-color-hover', value)
88
+
89
+ if (this.#darkModeValue)
90
+ hexColor = calcHexColor(value, true)
91
+ else
92
+ hexColor = calcHexColor(value, false)
93
+
94
+ root.style.setProperty('--makki-toast-bg-color', hexColor)
95
+ let textColor = getTextColor(hexColor)
96
+ this.#toastElement.style.color = textColor
97
+
98
+ const textColorHover = getTextColor(value)
99
+ console.log(textColorHover)
100
+ this.#toastElement.style.setProperty('--makki-toast-bg-color-text', textColorHover)
101
+
102
+ } catch (error) {
103
+ console.error(error)
104
+ this.#noHaveError = false
105
+ }
106
+ }
107
+
108
+ set canClose(value) {
109
+ this.#toastElement.classList.toggle('makki-can-close', value)
110
+ if (value)
111
+ this.#toastElement.addEventListener('click', this.#removeBinded)
112
+ else
113
+ this.#toastElement.removeEventListener('click', this.#removeBinded)
114
+ }
115
+
116
+ set icon(value) {
117
+ let iconToast = document.createElement('i')
118
+ iconToast.classList.add('makki-toast-icon')
119
+ if (this.#statusValue === 'success') {
120
+ iconToast.classList.add('bx')
121
+ iconToast.classList.add('bx-check')
122
+ this.#iconElement = iconToast
123
+ }
124
+ else if (this.#statusValue === 'warning') {
125
+ iconToast.classList.add('bx')
126
+ iconToast.classList.add('bx-error')
127
+ this.#iconElement = iconToast
128
+ }
129
+ else if (this.#statusValue === 'danger') {
130
+ iconToast.classList.add('bx')
131
+ iconToast.classList.add('bx-error-alt')
132
+ this.#iconElement = iconToast
133
+ }
134
+ else if (this.#statusValue === 'none') {
135
+ if(value) {
136
+ let arrayClases = value.split(' ')
137
+ for(let i = 0; i < arrayClases.length; i++){
138
+ iconToast.classList.add(arrayClases[i])
139
+ }
140
+ this.#iconElement = iconToast
141
+ }
142
+ }
143
+ }
144
+
145
+ set message(value) {
146
+ this.#toastElement.textContent = value
147
+ }
148
+
149
+ set position(value) {
150
+ validatePosition(value)
151
+ const selector = `.makki-toast-container[data-position='${value}']`
152
+ const toastContainer = document.querySelector(selector) || createContainer(value)
153
+ if (this.#noHaveError) {
154
+ if (this.#iconElement)
155
+ this.#toastElement.prepend(this.#iconElement)
156
+ toastContainer.append(this.#toastElement)
157
+ }
158
+ }
159
+
160
+ set showProgress(value) {
161
+ let bgColor
162
+ this.#toastElement.classList.toggle('makki-progress', value)
163
+ this.#toastElement.style.setProperty('--makki-progress', 1)
164
+
165
+ if (this.#statusValue === 'none')
166
+ bgColor = getComputedStyle(this.#toastElement).getPropertyValue('--makki-toast-bg-color-hover');
167
+ else if (this.#statusValue === 'success')
168
+ bgColor = '#38A95C'
169
+ else if (this.#statusValue === 'warning')
170
+ bgColor = '#ECC94B'
171
+ else if (this.#statusValue === 'danger')
172
+ bgColor = '#D74B4B'
173
+
174
+ this.#toastElement.style.setProperty('--makki-progress-bg', bgColor)
175
+ if (value) {
176
+ this.#progressInterval = setInterval(() => {
177
+ const timeVisible = new Date() - this.#visibleTimeSince
178
+ this.#toastElement.style.setProperty('--makki-progress', 1 - timeVisible / this.#autoClose)
179
+ }, 10)
180
+ }
181
+ }
182
+
183
+ #remove() {
184
+ clearTimeout(this.#autoCloseInterval)
185
+ clearInterval(this.#progressInterval)
186
+ const toastContainer = this.#toastElement.parentElement
187
+ this.#toastElement.classList.add('makki-close')
188
+ this.#toastElement.addEventListener('transitionend', () => {
189
+ this.#toastElement.remove()
190
+ if (toastContainer.hasChildNodes()) return
191
+ toastContainer.remove()
192
+ })
193
+ }
194
+ }
195
+
196
+ function createContainer(position) {
197
+ validatePosition(position)
198
+ const container = document.createElement('div')
199
+ container.classList.add('makki-toast-container')
200
+ container.dataset.position = position
201
+ document.body.append(container)
202
+ return container
203
+ }
204
+
205
+ function getHex(or, og, ob) {
206
+ let r = or.toString(16)
207
+ let g = og.toString(16)
208
+ let b = ob.toString(16)
209
+
210
+ if (r.length == 1)
211
+ r = "0" + r
212
+ if (g.length == 1)
213
+ g = "0" + g
214
+ if (b.length == 1)
215
+ b = "0" + b
216
+
217
+ return "#" + r + g + b
218
+ }
219
+
220
+ function getRBGColor(color) {
221
+ var color_hex = color.substring(1, 7)
222
+ var r = parseInt(color_hex.substring(0, 2), 16)
223
+ var g = parseInt(color_hex.substring(2, 4), 16)
224
+ var b = parseInt(color_hex.substring(4, 6), 16)
225
+ return { r, g, b }
226
+ }
227
+
228
+ function getTextColor(bgColor) {
229
+ let color = getRBGColor(bgColor)
230
+ let uiColors = [ color.r / 255, color.g / 255, color.b / 255 ]
231
+ let c = uiColors.map((col) => {
232
+ if (col <= 0.03928) {
233
+ return col / 12.92
234
+ }
235
+ return Math.pow((col + 0.055) / 1.055, 2.4)
236
+ })
237
+ let l = (0.2126 * c[0]) + (0.7152 * c[1]) + (0.0722 * c[2])
238
+ return (l > 0.279) ? '#050505' : '#EDF2F7'
239
+ }
240
+
241
+ function calcTintColor(or,og,ob) {
242
+ const r = or + Math.round((255 - or) * 0.25)
243
+ const g = og + Math.round((255 - og) * 0.25)
244
+ const b = ob + Math.round((255 - ob) * 0.25)
245
+ return { r, g, b }
246
+ }
247
+
248
+ function calcShadeColor(or,og,ob) {
249
+ const r = Math.round(or * 0.8)
250
+ const g = Math.round(og * 0.8)
251
+ const b = Math.round(ob * 0.8)
252
+ return { r, g, b }
253
+ }
254
+
255
+ function calcHexColor(bgColor, darkMode) {
256
+ let color = getRBGColor(bgColor)
257
+
258
+ if (darkMode)
259
+ Object.assign(color, calcShadeColor(color.r, color.g, color.b));
260
+ else
261
+ Object.assign(color, calcTintColor(color.r, color.g, color.b));
262
+
263
+ return getHex(color.r, color.g, color.b)
264
+ }
265
+
266
+ function validateBackgroundColor(value) {
267
+ if (value.length > 7 || value.charAt(0) != '#')
268
+ throw new Error('toast background color hex format is wrong')
269
+ if (!/^#[0-9A-F]{6}$/i.test(value))
270
+ throw new Error('toast background color hex code is wrong')
271
+ return
272
+ }
273
+
274
+ function validatePosition(position) {
275
+ const positions = ['top-right', 'top-left', 'top-center', 'bottom-right', 'bottom-left', 'bottom-center']
276
+ if (!positions.includes(position))
277
+ throw new Error('toast position is wrong')
278
+ return
279
+ }
280
+
281
+ function validateStatus(status) {
282
+ const styles = ['success', 'warning', 'danger', 'none']
283
+ if (!styles.includes(status.toLowerCase()))
284
+ throw new Error('toast status is wrong')
285
+ return
286
+ }
287
+
package/package.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "makki-toast",
3
+ "version": "1.0.0",
4
+ "description": "Fancy makki toast",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "keywords": [
10
+ "Toast"
11
+ ],
12
+ "author": "Daniel Jimenez",
13
+ "license": "ISC"
14
+ }
package/style.css ADDED
@@ -0,0 +1,168 @@
1
+ @import url(https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css);
2
+
3
+ :root {
4
+ --makki-toast-bg-color: #FFFFFF;
5
+ --makki-toast-bg-color-hover: #FFFFFF;
6
+ }
7
+
8
+ .makki-toast-container {
9
+ position: fixed;
10
+ margin: 10px;
11
+ width: 250px;
12
+ display: flex;
13
+ flex-direction: column;
14
+ gap: 0.5rem;
15
+ }
16
+
17
+ .makki-toast-container[data-position^="top-"] {
18
+ top: 0;
19
+ }
20
+
21
+ .makki-toast-container[data-position^="bottom-"] {
22
+ bottom: 0;
23
+ }
24
+
25
+ .makki-toast-container[data-position$="-right"] {
26
+ right: 0;
27
+ }
28
+
29
+ .makki-toast-container[data-position$="-left"] {
30
+ left: 0;
31
+ }
32
+
33
+ .makki-toast-container[data-position$="-center"] {
34
+ left: 50%;
35
+ transform: translate(-50%);
36
+ }
37
+
38
+ .makki-toast {
39
+ display: flex;
40
+ align-items: center;
41
+ box-sizing: border-box;
42
+ padding: 0.75rem 1.5rem 1rem 0.75rem;
43
+ background-color: white;
44
+ border-radius: .25em;
45
+ position: relative;
46
+ cursor: pointer;
47
+ opacity: 0;
48
+ font-size: 14px;
49
+ font-weight: 500;
50
+ transition: 200ms ease-in-out;
51
+ overflow: hidden;
52
+ }
53
+
54
+ .makki-toast-container[data-position$="-right"] .makki-toast {
55
+ transform: translateX(50px);
56
+ }
57
+
58
+ .makki-toast-container[data-position$="-left"] .makki-toast {
59
+ transform: translateX(-50px);
60
+ }
61
+
62
+ .makki-toast-container[data-position="top-center"] .makki-toast {
63
+ transform: translateY(-50px);
64
+ }
65
+
66
+ .makki-toast-container[data-position="bottom-center"] .makki-toast {
67
+ transform: translateY(50px);
68
+ }
69
+
70
+ .makki-toast-container .makki-toast.makki-show {
71
+ opacity: 0.9;
72
+ transform: translate(0, 0);
73
+ }
74
+
75
+ .makki-toast-container .makki-toast.makki-show.makki-close {
76
+ opacity: 0;
77
+ transform: translate(0, 0) scale(0.75);
78
+ transition: 250ms ease-in-out;
79
+ }
80
+
81
+ .makki-toast.makki-progress::before {
82
+ content: '';
83
+ position: absolute;
84
+ height: 5px;
85
+ width: calc(100% * var(--makki-progress));
86
+ background-color: var(--makki-progress-bg);
87
+ bottom: 0;
88
+ left: 0;
89
+ right: 0;
90
+ }
91
+
92
+ .makki-toast.makki-can-close::after {
93
+ content: "\00D7";
94
+ position: absolute;
95
+ top: 4px;
96
+ right: 8px;
97
+ }
98
+
99
+ .makki-toast-icon {
100
+ margin-right: 0.5rem;
101
+ font-size: 20px;
102
+ }
103
+
104
+ .makki-success.makki-light-toast {
105
+ background-color: #328E4F;
106
+ color: #EDF2F7;
107
+ }
108
+
109
+ .makki-success.makki-dark-toast {
110
+ background-color: #68CA87;
111
+ color: #2D3748;;
112
+ }
113
+
114
+ .makki-success.makki-light-toast:hover,
115
+ .makki-success.makki-dark-toast:hover {
116
+ background-color: #38A95C;
117
+ opacity: 1;
118
+ }
119
+
120
+ .makki-warning.makki-light-toast {
121
+ background-color: #d8b73d;
122
+ color: #2D3748;
123
+ }
124
+
125
+ .makki-warning.makki-dark-toast {
126
+ background-color: #fde692;
127
+ color: #2D3748;
128
+ }
129
+
130
+ .makki-warning.makki-dark-toast:hover,
131
+ .makki-warning.makki-light-toast:hover {
132
+ background-color: #ECC94B;
133
+ opacity: 1;
134
+ color: #2D3748;
135
+ }
136
+
137
+ .makki-danger.makki-light-toast {
138
+ background-color: #9C3030;
139
+ color: #EDF2F7;
140
+ }
141
+
142
+ .makki-danger.makki-dark-toast {
143
+ background-color: #e76f6f;
144
+ color: #EDF2F7;
145
+ }
146
+
147
+ .makki-danger.makki-light-toast:hover,
148
+ .makki-danger.makki-dark-toast:hover {
149
+ background-color: #D74B4B;
150
+ opacity: 1;
151
+ }
152
+
153
+ .makki-light-toast.makki-none,
154
+ .makki-dark-toast.makki-none {
155
+ background-color: var(--makki-toast-bg-color);
156
+ opacity: 0.9;
157
+ }
158
+
159
+ .makki-light-toast.makki-none:hover,
160
+ .makki-dark-toast.makki-none:hover {
161
+ background-color: var(--makki-toast-bg-color-hover);
162
+ color: var(--makki-toast-bg-color-text) !important;
163
+ opacity: 1;
164
+ }
165
+
166
+ .makki-background {
167
+ background-color: #1b1b1b;
168
+ }