From 06379591823372519c0befdcf6e4dda2c24123dd Mon Sep 17 00:00:00 2001 From: Rares Mardare Date: Tue, 22 Sep 2020 23:40:56 +0300 Subject: [PATCH 01/14] Package.json update --- package-lock.json | 47 +++++++++++++++++++++++++++++++---------------- package.json | 2 +- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/package-lock.json b/package-lock.json index ec3a05d..a3a072f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6289,28 +6289,28 @@ "dev": true }, "copy-webpack-plugin": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.0.3.tgz", - "integrity": "sha512-q5m6Vz4elsuyVEIUXr7wJdIdePWTubsqVbEMvf1WQnHGv0Q+9yPRu7MtYFPt+GBOXRav9lvIINifTQ1vSCs+eA==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.1.1.tgz", + "integrity": "sha512-4TlkHFYkrZ3WppLA5XkPmBLI5lnEpFsXvpeqxCf5PzkratZiVklNXsvoQkLhUU43q7ZL3AOXtaHAd9jLNJoU0w==", "dev": true, "requires": { - "cacache": "^15.0.4", + "cacache": "^15.0.5", "fast-glob": "^3.2.4", "find-cache-dir": "^3.3.1", "glob-parent": "^5.1.1", "globby": "^11.0.1", "loader-utils": "^2.0.0", "normalize-path": "^3.0.0", - "p-limit": "^3.0.1", - "schema-utils": "^2.7.0", - "serialize-javascript": "^4.0.0", + "p-limit": "^3.0.2", + "schema-utils": "^2.7.1", + "serialize-javascript": "^5.0.1", "webpack-sources": "^1.4.3" }, "dependencies": { "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "version": "6.12.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", + "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -6319,6 +6319,12 @@ "uri-js": "^4.2.2" } }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true + }, "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -6519,14 +6525,14 @@ } }, "schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", "dev": true, "requires": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" } }, "semver": { @@ -6535,6 +6541,15 @@ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", diff --git a/package.json b/package.json index 634dc5c..31dbb73 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "babel-plugin-transform-class-properties": "^6.24.1", "bootstrap": "^4.3.1", "clean-webpack-plugin": "^3.0.0", - "copy-webpack-plugin": "^6.0.3", + "copy-webpack-plugin": "^6.1.1", "css-loader": "^4.2.1", "css-select-base-adapter": "^0.1.1", "eslint": "^7.7.0", From b43b7b7337fed910244e621cff25eefca3d03c02 Mon Sep 17 00:00:00 2001 From: Rares Mardare Date: Tue, 22 Sep 2020 23:41:23 +0300 Subject: [PATCH 02/14] Updated tsconfig to provide type definitions for build --- tsconfig.json | 6 ++++-- webpack.prod.js | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 7e93a2f..8be2fde 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,7 @@ "src/*": ["src/*"] }, - "declaration": false, + "declaration": true, "noImplicitReturns": false, "alwaysStrict": true, "noImplicitThis": false, @@ -28,7 +28,9 @@ "preserveConstEnums": true, "experimentalDecorators": true, "forceConsistentCasingInFileNames": true, - "target": "es2015" + "target": "es2015", + + "outDir": "dist/js" }, "include": [ diff --git a/webpack.prod.js b/webpack.prod.js index dcafe3a..cae965b 100644 --- a/webpack.prod.js +++ b/webpack.prod.js @@ -24,7 +24,7 @@ module.exports = { new CopyPlugin({ patterns: [ { from: 'src/scss', to: 'scss' }, - { from: 'build/index.ts', to: 'index.js' } + { from: 'build/index.js', to: 'index.js' } ], }) ] From 70168573f662c44eceaf7218c4677463ba577914 Mon Sep 17 00:00:00 2001 From: Rares Mardare Date: Tue, 29 Sep 2020 23:48:33 +0300 Subject: [PATCH 03/14] Changed style to match BEM --- samples/styles/_customTypes.scss | 24 ++-- samples/styles/stylesheet.scss | 8 +- src/scss/_containers.scss | 164 ++++++++++++------------- src/scss/_types.scss | 180 +++++++++++++-------------- src/scss/notification.scss | 201 +++++++++++++++---------------- 5 files changed, 286 insertions(+), 291 deletions(-) diff --git a/samples/styles/_customTypes.scss b/samples/styles/_customTypes.scss index 3e3dfc5..2b08a99 100644 --- a/samples/styles/_customTypes.scss +++ b/samples/styles/_customTypes.scss @@ -1,4 +1,4 @@ -.notification-custom-icon { +.notification__custom-icon { flex-basis: 20%; position: relative; padding: 8px 8px 8px 12px; @@ -12,58 +12,58 @@ } } -.notification-custom-content { +.notification__custom { flex-basis: 80%; padding: 12px 12px 12px 8px; display: inline-block; } -.notification-custom-success { +.notification__custom--success { width: 100%; display: flex; background-color: #28a745; - .notification-custom-icon { + .notification__custom-icon { border-left: 8px solid darken(#28a745, 15%); } } -.notification-custom-default { +.notification__custom--default { width: 100%; display: flex; background-color: #007bff; - .notification-custom-icon { + .notification__custom-icon { border-left: 8px solid darken(#007bff, 15%); } } -.notification-custom-danger { +.notification__custom--danger { width: 100%; display: flex; background-color: #dc3545; - .notification-custom-icon { + .notification__custom-icon { border-left: 8px solid darken(#dc3545, 15%); } } -.notification-custom-info { +.notification__custom--info { width: 100%; display: flex; background-color: #17a2b8; - .notification-custom-icon { + .notification__custom-icon { border-left: 8px solid darken(#17a2b8, 15%); } } -.notification-custom-warning { +.notification__custom--warning { width: 100%; display: flex; background-color: #eab000; - .notification-custom-icon { + .notification__custom-icon { border-left: 8px solid darken(#eab000, 15%); } } diff --git a/samples/styles/stylesheet.scss b/samples/styles/stylesheet.scss index dbe0e1a..83eb9b8 100644 --- a/samples/styles/stylesheet.scss +++ b/samples/styles/stylesheet.scss @@ -13,10 +13,10 @@ body { html, body, -.notification-parent, -.notification-title, -.notification-message, -.notification-item { +.notification, +.notification__title, +.notification__message, +.notification__item { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol' !important; } diff --git a/src/scss/_containers.scss b/src/scss/_containers.scss index 396a6b5..eb44f75 100644 --- a/src/scss/_containers.scss +++ b/src/scss/_containers.scss @@ -1,82 +1,82 @@ -.notification-container-top-center, -.notification-container-top-left, -.notification-container-top-right, -.notification-container-bottom-center, -.notification-container-bottom-left, -.notification-container-bottom-right, -.notification-container-center { - width: 325px; - position: absolute; - pointer-events: all; -} - -.notification-container-center, -.notification-container-top-center, -.notification-container-bottom-center { - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; - left: calc(50% - 162.5px); -} - -.notification-container-center { - top: 20px; - height: 100%; - pointer-events: none; - - .center-inner { - width: 325px; - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; - pointer-events: all; - } -} - -.notification-container-top-center { - top: 20px; -} -.notification-container-bottom-center { - bottom: 20px; -} - -.notification-container-top-left { - left: 20px; - top: 20px; -} - -.notification-container-top-right { - right: 20px; - top: 20px; -} - -.notification-container-bottom-left { - left: 20px; - bottom: 20px; -} - -.notification-container-bottom-right { - bottom: 20px; - right: 20px; -} - -.notification-container-mobile-top, -.notification-container-mobile-bottom { - pointer-events: all; - position: absolute; -} - -.notification-container-mobile-top { - right: 20px; - left: 20px; - top: 20px; -} - -.notification-container-mobile-bottom { - right: 20px; - left: 20px; - bottom: 20px; - margin-bottom: -15px; -} +.notification-container--top-center, +.notification-container--top-left, +.notification-container--top-right, +.notification-container--bottom-center, +.notification-container--bottom-left, +.notification-container--bottom-right, +.notification-container--center { + width: 325px; + position: absolute; + pointer-events: all; +} + +.notification-container--center, +.notification-container--top-center, +.notification-container--bottom-center { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + left: calc(50% - 162.5px); +} + +.notification-container--center { + top: 20px; + height: 100%; + pointer-events: none; +} + +.flex-center { + width: 325px; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + pointer-events: all; +} + +.notification-container--top-center { + top: 20px; +} +.notification-container--bottom-center { + bottom: 20px; +} + +.notification-container--top-left { + left: 20px; + top: 20px; +} + +.notification-container--top-right { + right: 20px; + top: 20px; +} + +.notification-container--bottom-left { + left: 20px; + bottom: 20px; +} + +.notification-container--bottom-right { + bottom: 20px; + right: 20px; +} + +.notification-container--mobile-top, +.notification-container--mobile-bottom { + pointer-events: all; + position: absolute; +} + +.notification-container--mobile-top { + right: 20px; + left: 20px; + top: 20px; +} + +.notification-container--mobile-bottom { + right: 20px; + left: 20px; + bottom: 20px; + margin-bottom: -15px; +} diff --git a/src/scss/_types.scss b/src/scss/_types.scss index b93c19c..9a14947 100644 --- a/src/scss/_types.scss +++ b/src/scss/_types.scss @@ -1,91 +1,91 @@ -@import "_variables.scss"; - -.notification-default { - background-color: $default; - border-left: 8px solid $default_dark; - - .timer { - background-color: $default_timer; - } - .timer-filler { - background-color: $default_timer_filler; - } - .notification-close { - background-color: $default; - } -} - -.notification-success { - background-color: $success; - border-left: 8px solid $success_dark; - - .timer { - background-color: $success_timer; - } - .timer-filler { - background-color: $success_timer_filler; - } - .notification-close { - background-color: $success; - } -} - -.notification-danger { - background-color: $danger; - border-left: 8px solid $danger_dark; - - .timer { - background-color: $danger_timer; - } - .timer-filler { - background-color: $danger_timer_filler; - } - .notification-close { - background-color: $danger; - } -} - -.notification-info { - background-color: $info; - border-left: 8px solid $info_dark; - - .timer { - background-color: $info_timer; - } - .timer-filler { - background-color: $info_timer_filler; - } - .notification-close { - background-color: $info; - } -} - -.notification-warning { - background-color: $warning; - border-left: 8px solid $warning_dark; - - .timer { - background-color: $warning_timer; - } - .timer-filler { - background-color: $warning_timer_filler; - } - .notification-close { - background-color: $warning; - } -} - -.notification-awesome { - background-color: $awesome; - border-left: 8px solid $awesome_dark; - - .timer { - background-color: $awesome_timer; - } - .timer-filler { - background-color: $awesome_timer_filler; - } - .notification-close { - background-color: $awesome; - } +@import "_variables.scss"; + +.notification__item--default { + background-color: $default; + border-left: 8px solid $default_dark; + + .notification__timer { + background-color: $default_timer; + } + .notification__timer-filler { + background-color: $default_timer_filler; + } + .notification__close { + background-color: $default; + } +} + +.notification__item--success { + background-color: $success; + border-left: 8px solid $success_dark; + + .notification__timer { + background-color: $success_timer; + } + .notification__timer-filler { + background-color: $success_timer_filler; + } + .notification__close { + background-color: $success; + } +} + +.notification__item--danger { + background-color: $danger; + border-left: 8px solid $danger_dark; + + .notification__timer { + background-color: $danger_timer; + } + .notification__timer-filler { + background-color: $danger_timer_filler; + } + .notification__close { + background-color: $danger; + } +} + +.notification__item--info { + background-color: $info; + border-left: 8px solid $info_dark; + + .notification__timer { + background-color: $info_timer; + } + .notification__timer-filler { + background-color: $info_timer_filler; + } + .notification__close { + background-color: $info; + } +} + +.notification__item--warning { + background-color: $warning; + border-left: 8px solid $warning_dark; + + .notification__timer { + background-color: $warning_timer; + } + .notification__timer-filler { + background-color: $warning_timer_filler; + } + .notification__close { + background-color: $warning; + } +} + +.notification__item--awesome { + background-color: $awesome; + border-left: 8px solid $awesome_dark; + + .notification__timer { + background-color: $awesome_timer; + } + .notification__timer-filler { + background-color: $awesome_timer_filler; + } + .notification__close { + background-color: $awesome; + } } \ No newline at end of file diff --git a/src/scss/notification.scss b/src/scss/notification.scss index 0379958..19fbf33 100644 --- a/src/scss/notification.scss +++ b/src/scss/notification.scss @@ -1,104 +1,99 @@ -@import "./_containers.scss"; -@import "./_types.scss"; - -@keyframes timer { - 0% { width: 100%; } - 100% { width: 0%; } -} - -.react-notification-root { - position: fixed; - z-index: 9000; - pointer-events: none; - width: 100%; - height: 100%; -} - -.notification-item { - display: flex; - position: relative; - border-radius: 3px; - margin-bottom: 15px; - box-shadow: 1px 3px 4px rgba(0, 0, 0, 0.2); - cursor: pointer; - - .timer { - width: 100%; - height: 3px; - margin-top: 10px; - border-radius: 5px; - - .timer-filler { - height: 3px; - border-radius: 5px; - } - } - - .notification-title { - color: #fff; - font-weight: 700; - font-size: 14px; - margin-top: 5px; - margin-bottom: 5px; - } - - .notification-message { - color: #fff; - max-width: calc(100% - 15px); - font-size: 14px; - line-height: 150%; - word-wrap: break-word; - margin-bottom: 0; - margin-top: 0; - } - - .notification-content { - padding: 8px 15px; - display: inline-block; - width: 100%; - } - - .notification-close { - width: 18px; - height: 18px; - border-radius: 50%; - display: inline-block; - position: absolute; - right: 10px; - top: 10px; - - &::after { - content: '\D7'; - position: absolute; - transform: translate(-50%, -50%); - color: #fff; - font-size: 12px; - left: 50%; - top: 50%; - } - } -} - -.notification-container-mobile-top .notification-item, -.notification-container-mobile-bottom .notification-item, -.notification-container-mobile-top .notification-parent, -.notification-container-mobile-bottom .notification-parent { - max-width: 100%; - width: 100%; -} - -.notification-container-top-right .notification-parent, -.notification-container-bottom-right .notification-parent { - margin-left: auto; -} - -.notification-container-top-left .notification-parent, -.notification-container-bottom-left .notification-parent { - margin-right: auto; -} - -.notification-container-mobile-top .notification-parent, -.notification-container-mobile-bottom .notification-parent { - margin-left: auto; - margin-right: auto; +@import "./_containers.scss"; +@import "./_types.scss"; + +@keyframes timer { + 0% { width: 100%; } + 100% { width: 0%; } +} + +.notifications-component { + position: fixed; + z-index: 9000; + pointer-events: none; + width: 100%; + height: 100%; +} + +.notification__item { + display: flex; + position: relative; + border-radius: 3px; + margin-bottom: 15px; + box-shadow: 1px 3px 4px rgba(0, 0, 0, 0.2); + cursor: pointer; +} + +.notification__timer { + width: 100%; + height: 3px; + margin-top: 10px; + border-radius: 5px; +} +.notification__timer-filler { + height: 3px; + border-radius: 5px; +} +.notification__title { + color: #fff; + font-weight: 700; + font-size: 14px; + margin-top: 5px; + margin-bottom: 5px; +} +.notification__message { + color: #fff; + max-width: calc(100% - 15px); + font-size: 14px; + line-height: 150%; + word-wrap: break-word; + margin-bottom: 0; + margin-top: 0; +} +.notification__content { + padding: 8px 15px; + display: inline-block; + width: 100%; +} +.notification__close { + width: 18px; + height: 18px; + border-radius: 50%; + display: inline-block; + position: absolute; + right: 10px; + top: 10px; + + &::after { + content: '\D7'; + position: absolute; + transform: translate(-50%, -50%); + color: #fff; + font-size: 12px; + left: 50%; + top: 50%; + } +} + +.notification-container--mobile-top .notification__item, +.notification-container--mobile-bottom .notification__item, +.notification-container--mobile-top .notification, +.notification-container--mobile-bottom .notification { + max-width: 100%; + width: 100%; +} + +.notification-container--top-right .notification, +.notification-container--bottom-right .notification { + margin-left: auto; +} + +.notification-container--top-left .notification, +.notification-container--bottom-left .notification { + margin-right: auto; +} + +.notification-container--mobile-top .notification, +.notification-container--mobile-bottom .notification { + margin-left: auto; + margin-right: auto; } \ No newline at end of file From b00d429ba48ad6489c4c81b14cbfc52d8ce2d31f Mon Sep 17 00:00:00 2001 From: Rares Mardare Date: Tue, 29 Sep 2020 23:49:06 +0300 Subject: [PATCH 04/14] Changed class names to match BEM --- .../examples/CustomContentExample.tsx | 8 +++--- .../js/components/examples/TypeExample.tsx | 2 +- src/utils/constants.ts | 2 +- src/utils/helpers.ts | 28 +++++++++---------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/samples/js/components/examples/CustomContentExample.tsx b/samples/js/components/examples/CustomContentExample.tsx index 4339777..847ec06 100644 --- a/samples/js/components/examples/CustomContentExample.tsx +++ b/samples/js/components/examples/CustomContentExample.tsx @@ -84,12 +84,12 @@ function addCustomIcon(type: string, iconClassName: string): void { width: 275, container: getContainer(), content: ( -
-
+
+
-
-

{message}

+
+

{message}

) diff --git a/samples/js/components/examples/TypeExample.tsx b/samples/js/components/examples/TypeExample.tsx index 913ecc6..5ecb1b3 100644 --- a/samples/js/components/examples/TypeExample.tsx +++ b/samples/js/components/examples/TypeExample.tsx @@ -43,7 +43,7 @@ export default function TypeExample() { {' '} -
diff --git a/src/utils/constants.ts b/src/utils/constants.ts index cc03f2e..7606395 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -1,4 +1,4 @@ -export const NOTIFICATION_BASE_CLASS = 'notification-item'; +export const NOTIFICATION_BASE_CLASS = 'notification__item'; export enum NOTIFICATION_CONTAINER { BOTTOM_LEFT = 'bottom-left', diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index 8bcdd8e..4848706 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -48,15 +48,15 @@ export function shouldNotificationHaveSliding(notification: iNotification, count export function htmlClassesForExistingType(type: NOTIFICATION_TYPE) { switch (type) { case NT.DEFAULT: - return [NOTIFICATION_BASE_CLASS, 'notification-default']; + return [NOTIFICATION_BASE_CLASS, 'notification__item--default']; case NT.SUCCESS: - return [NOTIFICATION_BASE_CLASS, 'notification-success']; + return [NOTIFICATION_BASE_CLASS, 'notification__item--success']; case NT.DANGER: - return [NOTIFICATION_BASE_CLASS, 'notification-danger']; + return [NOTIFICATION_BASE_CLASS, 'notification__item--danger']; case NT.WARNING: - return [NOTIFICATION_BASE_CLASS, 'notification-warning']; + return [NOTIFICATION_BASE_CLASS, 'notification__item--warning']; case NT.INFO: - return [NOTIFICATION_BASE_CLASS, 'notification-info']; + return [NOTIFICATION_BASE_CLASS, 'notification__item--info']; default: return [NOTIFICATION_BASE_CLASS]; } @@ -78,8 +78,8 @@ export function getHtmlClassesForType(notification: iNotification) { } export function getNotificationsForMobileView(notifications: iNotification[]) { - const top = []; - const bottom = []; + const top: iNotification[] = []; + const bottom: iNotification[] = []; notifications.forEach((notification) => { const { container } = notification; @@ -96,13 +96,13 @@ export function getNotificationsForMobileView(notifications: iNotification[]) { } export function getNotificationsForEachContainer(notifications: iNotification[]) { - const topLeft = []; - const topRight = []; - const topCenter = []; - const bottomLeft = []; - const bottomRight = []; - const bottomCenter = []; - const center = []; + const topLeft: iNotification[] = []; + const topRight: iNotification[] = []; + const topCenter: iNotification[] = []; + const bottomLeft: iNotification[] = []; + const bottomRight: iNotification[] = []; + const bottomCenter: iNotification[] = []; + const center: iNotification[] = []; notifications.forEach((notification) => { const { container } = notification; From 877f4e069728247b1444a15dec2c9574f098d9a5 Mon Sep 17 00:00:00 2001 From: Rares Mardare Date: Tue, 29 Sep 2020 23:50:00 +0300 Subject: [PATCH 05/14] Replaced bindings with arrow functions, added new API call --- samples/js/components/App.tsx | 2 +- src/components/Container.tsx | 54 ++++++++++++------------ src/components/Notification.tsx | 73 +++++++++++++++++---------------- src/store/index.ts | 4 +- 4 files changed, 69 insertions(+), 64 deletions(-) diff --git a/samples/js/components/App.tsx b/samples/js/components/App.tsx index f00cbcd..0e25e23 100644 --- a/samples/js/components/App.tsx +++ b/samples/js/components/App.tsx @@ -10,7 +10,7 @@ export default function App() { { notifications: [], width: undefined }; - - this.add = this.add.bind(this); - this.remove = this.remove.bind(this); - this.toggleRemoval = this.toggleRemoval.bind(this); - this.handleResize = this.handleResize.bind(this); } static propTypes = propTypes; @@ -54,10 +49,11 @@ class Container extends React.Component { const { types } = this.props; store.register({ - addNotification: this.add, - removeNotification: this.remove, - types - }); + addNotification: this.add, + removeNotification: this.remove, + removeAllNotifications: this.removeAllNotifications, + types + }); this.setState({ width: window.innerWidth }); window.addEventListener('resize', this.handleResize); @@ -67,22 +63,22 @@ class Container extends React.Component { window.removeEventListener('resize', this.handleResize); } - handleResize() { + handleResize = () => { this.setState({ width: window.innerWidth }); } - add(notification: iNotification) { + add = (notification: iNotification) => { this.setState(({ notifications }) => ({ notifications: notification.insert === 'top' - ? [notification, ...notifications] - : [...notifications, notification] + ? [notification, ...notifications] + : [...notifications, notification] })); return notification.id; } - remove(id: string) { + remove = (id: string) => { this.setState(({ notifications }) => ({ notifications: notifications.map((notification) => { if (notification.id === id) { @@ -94,7 +90,11 @@ class Container extends React.Component { })); } - toggleRemoval(id: string, callback: () => void) { + removeAllNotifications = () => { + this.setState({ notifications: [] }) + } + + toggleRemoval = (id: string, callback: () => void) => { this.setState( ({ notifications }) => ({ notifications: notifications.filter(({ id: nId }) => nId !== id) @@ -124,9 +124,9 @@ class Container extends React.Component { const bottom = this.renderNotifications(mobileNotifications.bottom); return ( -
-
{top}
-
{bottom}
+
+
{top}
+
{bottom}
); } @@ -144,16 +144,16 @@ class Container extends React.Component { const center = this.renderNotifications(items.center); return ( -
-
{topLeft}
-
{topRight}
-
{bottomLeft}
-
{bottomRight}
-
{topCenter}
-
-
{center}
+
+
{topLeft}
+
{topRight}
+
{bottomLeft}
+
{bottomRight}
+
{topCenter}
+
+
{center}
-
{bottomCenter}
+
{bottomCenter}
); } diff --git a/src/components/Notification.tsx b/src/components/Notification.tsx index 93833b2..77fa70a 100644 --- a/src/components/Notification.tsx +++ b/src/components/Notification.tsx @@ -2,7 +2,12 @@ import PropTypes from 'prop-types'; import React from 'react'; import { iNotification } from 'src/types/Notification'; import { REMOVAL } from '../utils/constants'; -import { getHtmlClassesForType, getTransition, hasFullySwiped, shouldNotificationHaveSliding } from '../utils/helpers'; +import { + getHtmlClassesForType, + getTransition, + hasFullySwiped, + shouldNotificationHaveSliding +} from '../utils/helpers'; import Timer from '../utils/timer'; class iNotificationProps { @@ -35,12 +40,6 @@ class Notification extends React.Component toggleRemoval(id, () => onRemoval(id, removalFlag)); const parentStyle: iParentStyle = { height: `0px`, @@ -134,12 +133,12 @@ class Notification extends React.Component { this.setState({ - parentStyle: { - width, - ...parentStyle - }, - onTransitionEnd - }); + parentStyle: { + width, + ...parentStyle + }, + onTransitionEnd + }); } })); } @@ -154,16 +153,16 @@ class Notification extends React.Component { const { notification: { dismiss } } = this.props; if (dismiss.click || dismiss.showIcon) { this.removeNotification(REMOVAL.CLICK); } - } + }; - onTouchStart(event: React.TouchEvent) { + onTouchStart = (event: React.TouchEvent) => { const { pageX } = event.touches[0]; this.setState(({ parentStyle }) => ({ @@ -174,9 +173,9 @@ class Notification extends React.Component { const { pageX } = event.touches[0]; const { startX } = this.state; const { @@ -229,9 +228,9 @@ class Notification extends React.Component { const { notification: { touchRevert } } = this.props; @@ -243,23 +242,23 @@ class Notification extends React.Component { if (this.timer) { this.timer.pause(); } else { this.setState({ animationPlayState: 'paused' }); } - } + }; - onMouseLeave() { + onMouseLeave = () => { if (this.timer) { this.timer.resume(); } else { this.setState({ animationPlayState: 'running' }); } - } + }; renderTimer() { const { @@ -283,8 +282,12 @@ class Notification extends React.Component this.removeNotification(REMOVAL.TIMEOUT); return ( -
-
+
+
); } @@ -303,7 +306,7 @@ class Notification extends React.Component @@ -325,14 +328,14 @@ class Notification extends React.Component -
- {showIcon &&
} - {title &&
{title}
} -
{message}
+
+ {showIcon &&
} + {title &&
{title}
} +
{message}
{this.renderTimer()}
@@ -352,7 +355,7 @@ class Notification extends React.Component void; + public removeAllNotifications: () => void; private types: iNotificationCustomType[]; private add: (notification: iNotification) => string; @@ -37,9 +38,10 @@ class Store implements iStore { return this.add(parseNotification(notification, this.types)); } - public register({ addNotification, removeNotification, types }) { + public register({ addNotification, removeNotification, removeAllNotifications, types }) { this.add = addNotification; this.removeNotification = removeNotification; + this.removeAllNotifications = removeAllNotifications; this.types = types; } } From d16dc72a4fbdabfa6c5d6027ae065cc3cf355a57 Mon Sep 17 00:00:00 2001 From: Rares Mardare Date: Tue, 10 Nov 2020 22:16:18 +0200 Subject: [PATCH 06/14] A few more changes --- package.json | 3 - samples/js/components/App.tsx | 25 ++++- .../components/examples/ContainerExample.tsx | 7 ++ samples/js/helpers/notification.ts | 2 +- src/components/Container.tsx | 91 +++++++++---------- src/components/Notification.tsx | 41 +++++---- src/scss/_containers.scss | 14 ++- src/store/index.ts | 38 ++++++-- src/types/Notification.ts | 2 +- src/utils/constants.ts | 18 +++- src/utils/helpers.ts | 59 ++++++++---- src/utils/validators.ts | 54 +++-------- 12 files changed, 205 insertions(+), 149 deletions(-) diff --git a/package.json b/package.json index 31dbb73..daae504 100644 --- a/package.json +++ b/package.json @@ -92,8 +92,5 @@ }, "peerDependencies": { "react": "^16.0.0" - }, - "dependencies": { - "prop-types": "^15.6.2" } } diff --git a/samples/js/components/App.tsx b/samples/js/components/App.tsx index 0e25e23..3906717 100644 --- a/samples/js/components/App.tsx +++ b/samples/js/components/App.tsx @@ -1,10 +1,31 @@ -import React from 'react'; -import ReactNotification from 'src'; +import React, { useEffect, useState } from 'react'; +import ReactNotification, { store } from 'src'; +import { iNotification } from 'src/types/Notification'; +import { getMessage, getTitle, getType } from 'samples/js/helpers/randomize'; +import notification from 'samples/js/helpers/notification'; import Header from 'samples/js/components/Header'; import Content from 'samples/js/components/Content'; import GithubCorner from 'react-github-corner'; export default function App() { + useEffect(() => { + let intervalCount = 0 + setInterval(() => { + if (intervalCount++ >= 3) return + const object: iNotification = {}; + const type = getType(); + store.addNotification( + Object.assign(object, notification, { + title: getTitle(type), + message: 'Custom types can be used as well. Pretty cool, huh!? Custom types can be used as well. Pretty cool, huh!?', + width: [0, 400, 600, 200][Math.floor(Math.random() * 6) + 1], + container: 'bottom-right', + type: getType() + }) + ); + }, 500); + }, []); + return ( {' '} +
diff --git a/samples/js/helpers/notification.ts b/samples/js/helpers/notification.ts index 058970c..033570e 100644 --- a/samples/js/helpers/notification.ts +++ b/samples/js/helpers/notification.ts @@ -40,7 +40,7 @@ export default { }, dismiss: { - duration: 5000, + duration: 0, onScreen: false, pauseOnHover: true, waitForAnimation: false, diff --git a/src/components/Container.tsx b/src/components/Container.tsx index d86cf0a..cffd101 100644 --- a/src/components/Container.tsx +++ b/src/components/Container.tsx @@ -3,59 +3,48 @@ import React from 'react'; import ReactNotification from 'src/components/Notification'; import 'src/scss/notification.scss'; import store from 'src/store'; +import { DEFAULT_CONTAINER_VALUES as DCV } from 'src/utils/constants'; import { iNotification, iNotificationCustomType } from 'src/types/Notification'; -import { getNotificationsForEachContainer, getNotificationsForMobileView } from 'src/utils/helpers'; +import { getNotificationsForEachContainer, getNotificationsForMobileView, isNull } from 'src/utils/helpers'; interface iContainerProps { - isMobile: boolean; - breakpoint: number; - types: iNotificationCustomType[]; + isMobile?: boolean; + breakpoint?: number; + types?: iNotificationCustomType[]; + defaultNotificationWidth?: number; } interface iContainerState { isMobile: boolean; breakpoint: number; notifications: iNotification[]; - width: number; + windowWidth: number; } -const defaultProps = { - isMobile: true, - breakpoint: 768 -}; - -const propTypes = { - isMobile: PropTypes.bool, - breakpoint: PropTypes.number, - types: PropTypes.array -}; - class Container extends React.Component { constructor(props: iContainerProps) { super(props); this.state = { - isMobile: props.isMobile, - breakpoint: props.breakpoint, + isMobile: isNull(props.isMobile) ? DCV.isMobile : props.isMobile, + breakpoint: isNull(props.breakpoint) ? DCV.breakpoint : props.breakpoint, notifications: [], - width: undefined - }; + windowWidth: undefined + } } - static propTypes = propTypes; - static defaultProps = defaultProps; - componentDidMount() { - const { types } = this.props; + const { types, defaultNotificationWidth } = this.props; store.register({ addNotification: this.add, removeNotification: this.remove, removeAllNotifications: this.removeAllNotifications, - types + defaultNotificationWidth: defaultNotificationWidth || DCV.defaultNotificationWidth, + types, }); - this.setState({ width: window.innerWidth }); + this.setState({ windowWidth: window.innerWidth }); window.addEventListener('resize', this.handleResize); } @@ -64,8 +53,8 @@ class Container extends React.Component { } handleResize = () => { - this.setState({ width: window.innerWidth }); - } + this.setState({ windowWidth: window.innerWidth }); + }; add = (notification: iNotification) => { this.setState(({ notifications }) => ({ @@ -76,23 +65,23 @@ class Container extends React.Component { })); return notification.id; - } + }; remove = (id: string) => { this.setState(({ notifications }) => ({ notifications: notifications.map((notification) => { if (notification.id === id) { - notification.removed = true; + notification.hasBeenRemoved = true; } return notification; }) })); - } + }; removeAllNotifications = () => { - this.setState({ notifications: [] }) - } + this.setState({ notifications: [] }); + }; toggleRemoval = (id: string, callback: () => void) => { this.setState( @@ -101,17 +90,19 @@ class Container extends React.Component { }), callback ); - } + }; - renderNotifications(notifications: iNotification[]) { + renderNotifications(notifications: iNotification[], isMobile: boolean) { return notifications.map((notification) => ( )); } @@ -120,8 +111,8 @@ class Container extends React.Component { const { className, id } = props; const { notifications } = this.state; const mobileNotifications = getNotificationsForMobileView(notifications); - const top = this.renderNotifications(mobileNotifications.top); - const bottom = this.renderNotifications(mobileNotifications.bottom); + const top = this.renderNotifications(mobileNotifications.top, true); + const bottom = this.renderNotifications(mobileNotifications.bottom, true); return (
@@ -135,16 +126,20 @@ class Container extends React.Component { const { className, id } = props; const { notifications } = this.state; const items = getNotificationsForEachContainer(notifications); - const topLeft = this.renderNotifications(items.topLeft); - const topRight = this.renderNotifications(items.topRight); - const topCenter = this.renderNotifications(items.topCenter); - const bottomLeft = this.renderNotifications(items.bottomLeft); - const bottomRight = this.renderNotifications(items.bottomRight); - const bottomCenter = this.renderNotifications(items.bottomCenter); - const center = this.renderNotifications(items.center); + const topFull = this.renderNotifications(items.topFull, false); + const bottomFull = this.renderNotifications(items.bottomFull, false); + const topLeft = this.renderNotifications(items.topLeft, false); + const topRight = this.renderNotifications(items.topRight, false); + const topCenter = this.renderNotifications(items.topCenter, false); + const bottomLeft = this.renderNotifications(items.bottomLeft, false); + const bottomRight = this.renderNotifications(items.bottomRight, false); + const bottomCenter = this.renderNotifications(items.bottomCenter, false); + const center = this.renderNotifications(items.center, false); return (
+
{topFull}
+
{bottomFull}
{topLeft}
{topRight}
{bottomLeft}
@@ -160,9 +155,9 @@ class Container extends React.Component { render() { const { isMobile } = this.props; - const { width, breakpoint } = this.state; + const { windowWidth, breakpoint } = this.state; - if (isMobile && width <= breakpoint) { + if (isMobile && windowWidth <= breakpoint) { return this.renderMobileNotifications(this.props); } diff --git a/src/components/Notification.tsx b/src/components/Notification.tsx index 77fa70a..9871f9f 100644 --- a/src/components/Notification.tsx +++ b/src/components/Notification.tsx @@ -1,7 +1,6 @@ -import PropTypes from 'prop-types'; import React from 'react'; import { iNotification } from 'src/types/Notification'; -import { REMOVAL } from '../utils/constants'; +import { NOTIFICATION_CONTAINER as NC, REMOVAL } from '../utils/constants'; import { getHtmlClassesForType, getTransition, @@ -13,8 +12,10 @@ import Timer from '../utils/timer'; class iNotificationProps { id: string; notification: iNotification; - count: number; - removed: boolean; + defaultNotificationWidth: number; + notificationsCount: number; + isMobile: boolean; + hasBeenRemoved: boolean; toggleRemoval: (id: string, callback: () => void) => void; } @@ -41,29 +42,29 @@ class Notification extends React.Component; private timer: Timer; - static propTypes = { - toggleRemoval: PropTypes.func.isRequired, - count: PropTypes.number.isRequired, - removed: PropTypes.bool - }; - componentWillUnmount() { if (this.timer) { this.timer.clear(); @@ -71,17 +72,15 @@ class Notification extends React.Component { - if (!duration || onScreen) { - return; - } + if (!duration || onScreen) return; const callback = () => this.removeNotification(REMOVAL.TIMEOUT); this.timer = new Timer(callback, duration); }; @@ -107,8 +106,8 @@ class Notification extends React.Component toggleRemoval(id, () => onRemoval(id, removalFlag)); const parentStyle: iParentStyle = { height: `0px`, + overflow: 'hidden', transition: getTransition(notification.slidingExit, 'height') }; @@ -213,6 +213,7 @@ class Notification extends React.Component void; +interface iRegisterParams { + addNotification: (notification: iNotification) => string; + removeNotification: (id: string) => void; + removeAllNotifications: () => void; types: iNotificationCustomType[]; + defaultNotificationWidth: number; } class Store implements iStore { @@ -20,12 +22,15 @@ class Store implements iStore { this.add = null; } - public counter: number; public removeNotification: (id: string) => void; public removeAllNotifications: () => void; private types: iNotificationCustomType[]; private add: (notification: iNotification) => string; + private defaultNotificationWidth: number; + private counter: number; + + private incrementCounter = () => (this.counter += 1); public addNotification(notification: iNotification) { if (process.env.NODE_ENV === 'development') { @@ -34,14 +39,31 @@ class Store implements iStore { validators.forEach((validator) => validator(notification, this.types)); } - this.counter += 1; - return this.add(parseNotification(notification, this.types)); + this.incrementCounter(); + + const parsedNotification = parseNotification( + notification, + this.types, + this.defaultNotificationWidth + ); + return this.add(parsedNotification); } - public register({ addNotification, removeNotification, removeAllNotifications, types }) { + public getCounter = () => this.counter; + + public register(parameters: iRegisterParams) { + const { + addNotification, + removeNotification, + removeAllNotifications, + types, + defaultNotificationWidth + } = parameters; + this.add = addNotification; this.removeNotification = removeNotification; this.removeAllNotifications = removeAllNotifications; + this.defaultNotificationWidth = defaultNotificationWidth; this.types = types; } } diff --git a/src/types/Notification.ts b/src/types/Notification.ts index afeb598..287c3b0 100644 --- a/src/types/Notification.ts +++ b/src/types/Notification.ts @@ -18,7 +18,7 @@ export interface iNotification { touchSlidingExit?: iTouchTransition; userDefinedTypes?: iNotificationCustomType[]; width?: number; - removed?: boolean + hasBeenRemoved?: boolean } export type NotificationTitleMessage = string | React.ReactNode | React.FunctionComponent; diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 7606395..e70850c 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -1,3 +1,9 @@ +export const DEFAULT_CONTAINER_VALUES = { + isMobile: true, + breakpoint: 768, + defaultNotificationWidth: 325 +}; + export const NOTIFICATION_BASE_CLASS = 'notification__item'; export enum NOTIFICATION_CONTAINER { @@ -7,13 +13,15 @@ export enum NOTIFICATION_CONTAINER { TOP_LEFT = 'top-left', TOP_RIGHT = 'top-right', TOP_CENTER = 'top-center', - CENTER = 'center' -}; + CENTER = 'center', + TOP_FULL = 'top-full', + BOTTOM_FULL = 'bottom-full' +} export enum INSERTION { TOP = 'top', BOTTOM = 'bottom' -}; +} export enum NOTIFICATION_TYPE { SUCCESS = 'success', @@ -21,14 +29,14 @@ export enum NOTIFICATION_TYPE { INFO = 'info', DEFAULT = 'default', WARNING = 'warning' -}; +} export enum REMOVAL { TIMEOUT = 'timeout', CLICK = 'click', TOUCH = 'touch', MANUAL = 'manual' -}; +} export const ERROR = { ANIMATION_IN: 'Validation error. `animationIn` option must be an array', diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index 4848706..3abe2c7 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -1,5 +1,11 @@ import store from 'src/store'; -import { iDismiss, iNotification, iNotificationCustomType, iTouchTransition, iTransition } from 'src/types/Notification'; +import { + iDismiss, + iNotification, + iNotificationCustomType, + iTouchTransition, + iTransition +} from 'src/types/Notification'; import { INSERTION, NOTIFICATION_BASE_CLASS, @@ -8,10 +14,11 @@ import { NOTIFICATION_TYPE as NT } from 'src/utils/constants'; -const isNull = (object: any) => object === null || object === undefined; +export const isNull = (object: any) => object === null || object === undefined; export function isBottomContainer(container: string) { return ( + container === NOTIFICATION_CONTAINER.BOTTOM_FULL || container === NOTIFICATION_CONTAINER.BOTTOM_LEFT || container === NOTIFICATION_CONTAINER.BOTTOM_RIGHT || container === NOTIFICATION_CONTAINER.BOTTOM_CENTER @@ -20,6 +27,7 @@ export function isBottomContainer(container: string) { export function isTopContainer(container: string) { return ( + container === NOTIFICATION_CONTAINER.TOP_FULL || container === NOTIFICATION_CONTAINER.TOP_LEFT || container === NOTIFICATION_CONTAINER.TOP_RIGHT || container === NOTIFICATION_CONTAINER.TOP_CENTER @@ -40,8 +48,8 @@ export function shouldNotificationHaveSliding(notification: iNotification, count return ( count > 1 && ((notification.insert === INSERTION.TOP && isTopContainer(notification.container)) || - (notification.insert === INSERTION.BOTTOM && isBottomContainer(notification.container)) || - notification.container === NOTIFICATION_CONTAINER.CENTER) + (notification.insert === INSERTION.BOTTOM && isBottomContainer(notification.container)) || + notification.container === NOTIFICATION_CONTAINER.CENTER) ); } @@ -103,10 +111,16 @@ export function getNotificationsForEachContainer(notifications: iNotification[]) const bottomRight: iNotification[] = []; const bottomCenter: iNotification[] = []; const center: iNotification[] = []; + const topFull: iNotification[] = []; + const bottomFull: iNotification[] = []; notifications.forEach((notification) => { const { container } = notification; - if (container === NOTIFICATION_CONTAINER.TOP_LEFT) { + if (container === NOTIFICATION_CONTAINER.TOP_FULL) { + topFull.push(notification); + } else if (container === NOTIFICATION_CONTAINER.BOTTOM_FULL) { + bottomFull.push(notification); + } else if (container === NOTIFICATION_CONTAINER.TOP_LEFT) { topLeft.push(notification); } else if (container === NOTIFICATION_CONTAINER.TOP_RIGHT) { topRight.push(notification); @@ -124,6 +138,8 @@ export function getNotificationsForEachContainer(notifications: iNotification[]) }); return { + topFull, + bottomFull, topLeft, topRight, topCenter, @@ -138,8 +154,11 @@ export function getTransition({ duration, timingFunction, delay }: iTransition, return `${duration}ms ${property} ${timingFunction} ${delay}ms`; } -function defaultTransition(transition: iTransition, { duration, timingFunction, delay }: iTransition) { - const transitionOptions = transition || {} as iTransition; +function defaultTransition( + transition: iTransition, + { duration, timingFunction, delay }: iTransition +) { + const transitionOptions = transition || ({} as iTransition); if (isNull(transitionOptions.duration)) { transitionOptions.duration = duration; @@ -181,7 +200,10 @@ function defaultDismiss(dismiss: iDismiss): iDismiss { return option; } -function defaultUserDefinedTypes(notification: iNotification, definedTypes: iNotificationCustomType[]) { +function defaultUserDefinedTypes( + notification: iNotification, + definedTypes: iNotificationCustomType[] +) { const { content, type } = notification; if (content) { return undefined; @@ -201,7 +223,11 @@ function defaultUserDefinedTypes(notification: iNotification, definedTypes: iNot return definedTypes; } -export function parseNotification(options: iNotification, userDefinedTypes: any): iNotification { +export function parseNotification( + options: iNotification, + userDefinedTypes: iNotificationCustomType[], + defaultNotificationWidth: number +): iNotification { const notification = options; const { id, @@ -220,17 +246,14 @@ export function parseNotification(options: iNotification, userDefinedTypes: any) onRemoval } = notification; - notification.id = id || store.counter.toString(); - notification.type = content ? null : type.toLowerCase() as NOTIFICATION_TYPE; + notification.id = id || store.getCounter().toString(); + notification.type = content ? null : (type.toLowerCase() as NOTIFICATION_TYPE); if (userDefinedTypes && !content) { notification.userDefinedTypes = defaultUserDefinedTypes(notification, userDefinedTypes); } - if (!isNull(width)) { - notification.width = width; - } - + notification.width = isNull(width) ? defaultNotificationWidth : width; notification.container = container.toLowerCase() as NOTIFICATION_CONTAINER; notification.insert = (insert || 'top').toLowerCase() as INSERTION; notification.dismiss = defaultDismiss(dismiss); @@ -248,9 +271,9 @@ export function parseNotification(options: iNotification, userDefinedTypes: any) notification.slidingExit = defaultTransition(slidingExit, t(600, 'linear', 0)); notification.touchRevert = defaultTransition(touchRevert, t(600, 'linear', 0)); - const touchExit = touchSlidingExit || {} as iTouchTransition; - const swipe = touchExit.swipe || {} as iTransition; - const fade = touchExit.fade || {} as iTransition; + const touchExit = touchSlidingExit || ({} as iTouchTransition); + const swipe = touchExit.swipe || ({} as iTransition); + const fade = touchExit.fade || ({} as iTransition); notification.touchSlidingExit = touchExit; notification.touchSlidingExit.swipe = defaultTransition(swipe, t(600, 'linear', 0)); notification.touchSlidingExit.fade = defaultTransition(fade, t(300, 'linear', 0)); diff --git a/src/utils/validators.ts b/src/utils/validators.ts index c9fd187..81aafa1 100644 --- a/src/utils/validators.ts +++ b/src/utils/validators.ts @@ -10,7 +10,7 @@ const isFunction = (object: any) => !!(object && object.constructor && object.ca const isArray = (object: any) => !isNull(object) && object.constructor === Array; function isClassComponent(component: any) { - return typeof component === 'function' && component.prototype && !!component.prototype.isReactComponent; + return typeof component === 'function' && component.prototype && !!component.prototype.render; } function isFunctionComponent(component: any) { @@ -36,17 +36,11 @@ export function validateTransition(notification: iNotification, transition: stri export const validators = [ function title({ content, title }: iNotification) { - if (content) { - return; - } - if (isNull(title)) { - return; - } + if (content) return; + if (isNull(title)) return; const isReactEl = isReactElement(title); - if (isReactEl || typeof title === 'string') { - return; - } + if (isReactEl || typeof title === 'string') return; if (!isReactEl) { throw new Error(ERROR.TITLE_ELEMENT); } @@ -56,9 +50,7 @@ export const validators = [ }, function message({ content, message }: iNotification) { - if (content) { - return; - } + if (content) return; if (!message) { throw new Error(ERROR.MESSAGE_REQUIRED); @@ -77,9 +69,7 @@ export const validators = [ }, function type({ content, type }: iNotification, userDefinedTypes: iNotificationCustomType[]) { - if (content) { - return; - } + if (content) return; if (!type) { throw new Error(ERROR.TYPE_REQUIRED); } @@ -109,18 +99,14 @@ export const validators = [ }, function insert({ insert }: iNotification) { - if (isNull(insert)) { - return; - } + if (isNull(insert)) return; if (!isString(insert)) { throw new Error(ERROR.INSERT_STRING); } }, function width({ width }: iNotification) { - if (isNull(width)) { - return; - } + if (isNull(width)) return; if (!isNumber(width)) { throw new Error(ERROR.WIDTH_NUMBER); } @@ -130,9 +116,7 @@ export const validators = [ { type, content }: iNotification, userDefinedTypes: iNotificationCustomType[] ) { - if (content) { - return; - } + if (content) return; if ( type === NT.SUCCESS || @@ -151,9 +135,7 @@ export const validators = [ }, function content({ content }: iNotification) { - if (!content) { - return; - } + if (!content) return; const isClass = isClassComponent(content); const isFunction = isFunctionComponent(content); const isElem = React.isValidElement(content); @@ -163,36 +145,28 @@ export const validators = [ }, function animationIn({ animationIn }: iNotification) { - if (isNull(animationIn)) { - return; - } + if (isNull(animationIn)) return; if (!isArray(animationIn)) { throw new Error(ERROR.ANIMATION_IN); } }, function animationOut({ animationOut }: iNotification) { - if (isNull(animationOut)) { - return; - } + if (isNull(animationOut)) return; if (!isArray(animationOut)) { throw new Error(ERROR.ANIMATION_OUT); } }, function onRemoval({ onRemoval }: iNotification) { - if (!onRemoval) { - return; - } + if (!onRemoval) return; if (!isFunction(onRemoval)) { throw new Error(ERROR.REMOVAL_FUNC); } }, function dismiss({ dismiss }: iNotification) { - if (!dismiss) { - return; - } + if (!dismiss) return; const { duration, From 4b32d2b115b2d9ec9590d371c42044f36a89ff7e Mon Sep 17 00:00:00 2001 From: Rares Mardare Date: Tue, 10 Nov 2020 22:24:37 +0200 Subject: [PATCH 07/14] Smoother handle for all removal --- samples/js/components/Content.tsx | 4 ++ .../components/examples/ContainerExample.tsx | 42 ++++++++++--------- src/components/Container.tsx | 17 ++++++-- 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/samples/js/components/Content.tsx b/samples/js/components/Content.tsx index 3c92a5d..518cc25 100644 --- a/samples/js/components/Content.tsx +++ b/samples/js/components/Content.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { store } from 'src'; import ContainerExample from 'components/examples/ContainerExample'; import TypeExample from 'components/examples/TypeExample'; import InsertExample from 'components/examples/InsertExample'; @@ -10,6 +11,9 @@ function ExampleHeading() {

Examples

+
All notifications have been set to be automatically dismissed after{' '} diff --git a/samples/js/components/examples/ContainerExample.tsx b/samples/js/components/examples/ContainerExample.tsx index d6891b7..f18788e 100644 --- a/samples/js/components/examples/ContainerExample.tsx +++ b/samples/js/components/examples/ContainerExample.tsx @@ -25,52 +25,45 @@ export default function ContainerExample() { onClick={() => add('top-left')} > Top Left - - {' '} + {' '} - {' '} + {' '} - {' '} + {' '} - {' '} + {' '} - {' '} + {' '} - {' '} + {' '} - {' '} + {' '} +
@@ -88,10 +88,12 @@ function add(container: string): string { const type = getType(); const object: iNotification = {}; - return store.addNotification(Object.assign(object, notification, { - title: getTitle(type), - message: getMessage(type), - container, - type - })); + return store.addNotification( + Object.assign(object, notification, { + title: getTitle(type), + message: getMessage(type), + container, + type + }) + ); } diff --git a/src/components/Container.tsx b/src/components/Container.tsx index cffd101..c41e182 100644 --- a/src/components/Container.tsx +++ b/src/components/Container.tsx @@ -5,7 +5,11 @@ import 'src/scss/notification.scss'; import store from 'src/store'; import { DEFAULT_CONTAINER_VALUES as DCV } from 'src/utils/constants'; import { iNotification, iNotificationCustomType } from 'src/types/Notification'; -import { getNotificationsForEachContainer, getNotificationsForMobileView, isNull } from 'src/utils/helpers'; +import { + getNotificationsForEachContainer, + getNotificationsForMobileView, + isNull +} from 'src/utils/helpers'; interface iContainerProps { isMobile?: boolean; @@ -30,7 +34,7 @@ class Container extends React.Component { breakpoint: isNull(props.breakpoint) ? DCV.breakpoint : props.breakpoint, notifications: [], windowWidth: undefined - } + }; } componentDidMount() { @@ -41,7 +45,7 @@ class Container extends React.Component { removeNotification: this.remove, removeAllNotifications: this.removeAllNotifications, defaultNotificationWidth: defaultNotificationWidth || DCV.defaultNotificationWidth, - types, + types }); this.setState({ windowWidth: window.innerWidth }); @@ -80,7 +84,12 @@ class Container extends React.Component { }; removeAllNotifications = () => { - this.setState({ notifications: [] }); + this.setState({ + notifications: this.state.notifications.map((notification) => ({ + ...notification, + hasBeenRemoved: true + })) + }); }; toggleRemoval = (id: string, callback: () => void) => { From 29d4910d5163ed0cb9081ee77e49b915c64087e3 Mon Sep 17 00:00:00 2001 From: Rares Mardare Date: Tue, 10 Nov 2020 22:30:36 +0200 Subject: [PATCH 08/14] App cleanup --- samples/js/components/App.tsx | 25 ++----------------- .../components/examples/ContainerExample.tsx | 6 ++--- 2 files changed, 5 insertions(+), 26 deletions(-) diff --git a/samples/js/components/App.tsx b/samples/js/components/App.tsx index 3906717..0e25e23 100644 --- a/samples/js/components/App.tsx +++ b/samples/js/components/App.tsx @@ -1,31 +1,10 @@ -import React, { useEffect, useState } from 'react'; -import ReactNotification, { store } from 'src'; -import { iNotification } from 'src/types/Notification'; -import { getMessage, getTitle, getType } from 'samples/js/helpers/randomize'; -import notification from 'samples/js/helpers/notification'; +import React from 'react'; +import ReactNotification from 'src'; import Header from 'samples/js/components/Header'; import Content from 'samples/js/components/Content'; import GithubCorner from 'react-github-corner'; export default function App() { - useEffect(() => { - let intervalCount = 0 - setInterval(() => { - if (intervalCount++ >= 3) return - const object: iNotification = {}; - const type = getType(); - store.addNotification( - Object.assign(object, notification, { - title: getTitle(type), - message: 'Custom types can be used as well. Pretty cool, huh!? Custom types can be used as well. Pretty cool, huh!?', - width: [0, 400, 600, 200][Math.floor(Math.random() * 6) + 1], - container: 'bottom-right', - type: getType() - }) - ); - }, 500); - }, []); - return ( {' '} + {' '}