react-js-banner 0.7.1 → 0.8.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/package.json CHANGED
@@ -1,49 +1,49 @@
1
- {
2
- "name": "react-js-banner",
3
- "version": "0.7.1",
4
- "description": "React JS Banner component customizable with auto hide option",
5
- "main": "build/index.js",
6
- "peerDependencies": {},
7
- "dependencies": {
8
- "source-map-explorer": "^2.5.3"
9
- },
10
- "scripts": {
11
- "start": "webpack --watch",
12
- "build": "webpack"
13
- },
14
- "author": {
15
- "name": "Jose Antonio Ciccio",
16
- "email": "jciccio@gmail.com"
17
- },
18
- "devDependencies": {
19
- "@babel/core": "^7.13.14",
20
- "@babel/plugin-proposal-class-properties": "^7.13.0",
21
- "@babel/preset-env": "^7.13.12",
22
- "@babel/preset-react": "^7.13.13",
23
- "babel-loader": "^8.2.2",
24
- "css-loader": "^5.2.0",
25
- "eslint": "^6.8.0",
26
- "html-loader": "^2.1.2",
27
- "html-webpack-plugin": "^5.3.1",
28
- "prop-types": "^15.8.1",
29
- "react": "^18.2.0",
30
- "react-dom": "^18.2.0",
31
- "style-loader": "^3.3.4",
32
- "webpack": "^5.91.0",
33
- "webpack-cli": "^5.1.4"
34
- },
35
- "repository": {
36
- "type": "git",
37
- "url": "https://github.com/jciccio/react-js-banner.git"
38
- },
39
- "keywords": [
40
- "react js banner",
41
- "js banner",
42
- "banner",
43
- "message notification",
44
- "notification",
45
- "toaster"
46
- ],
47
- "license": "MIT",
48
- "homepage": "https://github.com/jciccio/react-js-banner/blob/master/README.md"
49
- }
1
+ {
2
+ "name": "react-js-banner",
3
+ "version": "0.8.0",
4
+ "description": "React JS Banner component customizable with auto hide option",
5
+ "main": "build/index.js",
6
+ "peerDependencies": {
7
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
8
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
9
+ },
10
+ "dependencies": {},
11
+ "scripts": {
12
+ "start": "webpack --watch",
13
+ "build": "webpack"
14
+ },
15
+ "author": {
16
+ "name": "Jose Antonio Ciccio",
17
+ "email": "jciccio@gmail.com"
18
+ },
19
+ "devDependencies": {
20
+ "@babel/core": "^7.24.0",
21
+ "@babel/preset-env": "^7.24.0",
22
+ "@babel/preset-react": "^7.24.0",
23
+ "babel-loader": "^9.1.3",
24
+ "css-loader": "^7.0.0",
25
+ "eslint": "^8.57.0",
26
+ "html-loader": "^5.0.0",
27
+ "html-webpack-plugin": "^5.6.0",
28
+ "prop-types": "^15.8.1",
29
+ "react": "^18.3.0",
30
+ "react-dom": "^18.3.0",
31
+ "style-loader": "^4.0.0",
32
+ "webpack": "^5.91.0",
33
+ "webpack-cli": "^5.1.0"
34
+ },
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://github.com/jciccio/react-js-banner.git"
38
+ },
39
+ "keywords": [
40
+ "react js banner",
41
+ "js banner",
42
+ "banner",
43
+ "message notification",
44
+ "notification",
45
+ "toaster"
46
+ ],
47
+ "license": "MIT",
48
+ "homepage": "https://github.com/jciccio/react-js-banner/blob/master/README.md"
49
+ }
package/src/banner.css CHANGED
@@ -1,61 +1,78 @@
1
- @keyframes opacityOn {
2
- 0% {
3
- opacity: 0;
4
- }
5
- 25% {
6
- opacity: 0;
7
- }
8
- 50% {
9
- opacity: 1;
10
- }
11
- 85% {
12
- opacity: 1;
13
- }
14
- 100% {
15
- opacity: 0;
16
- }
17
- }
18
-
19
- @keyframes noFadeOut {
20
- 0% {
21
- opacity: 0;
22
- }
23
- 50% {
24
- opacity: 1;
25
- }
26
- 100% {
27
- opacity: 1;
28
- }
29
- }
30
-
31
- .banner{
32
- background-color: orange;
33
- text-align: center;
34
- padding: 10px 10px;
35
- font-size: 16px;
36
- font-weight: bold;
37
- display: flex;
38
- margin-bottom: 10px;
39
- text-align: center;
40
- align-items: center;
41
- justify-content: center;
42
- animation: opacityOn 5s normal forwards;
43
- }
44
-
45
- .banner-transition-appear {
46
- opacity: 0.01;
47
- }
48
-
49
- .banner-transition-appear.banner-transition-appear-active {
50
- opacity: 1;
51
- transition: opacity 2s ease;
52
- }
53
-
54
- .banner-transition-leave {
55
- opacity: 1;
56
- }
57
-
58
- .banner-transition-leave.banner-transition-leave-active {
59
- opacity: 0.01;
60
- transition: opacity 2s ease;
61
- }
1
+ .banner {
2
+ display: flex;
3
+ justify-content: center;
4
+ align-items: center;
5
+ width: 100%;
6
+ min-height: 50px;
7
+ font-family: Arial, sans-serif;
8
+ color: #fff;
9
+ transition: opacity 1s, top 0.5s, bottom 0.5s;
10
+ z-index: 1000;
11
+ box-sizing: border-box;
12
+ padding: 10px 20px;
13
+ position: relative;
14
+ }
15
+
16
+ .banner-content {
17
+ display: flex;
18
+ align-items: center;
19
+ flex: 1;
20
+ justify-content: center;
21
+ }
22
+
23
+ .banner-close-btn {
24
+ background: transparent;
25
+ border: none;
26
+ color: inherit;
27
+ font-size: 20px;
28
+ cursor: pointer;
29
+ padding: 0 10px;
30
+ margin-left: auto;
31
+ opacity: 0.8;
32
+ }
33
+
34
+ .banner-close-btn:hover {
35
+ opacity: 1;
36
+ }
37
+
38
+ /* Positions */
39
+ .banner-top {
40
+ position: fixed;
41
+ top: 0;
42
+ left: 0;
43
+ }
44
+
45
+ .banner-bottom {
46
+ position: fixed;
47
+ bottom: 0;
48
+ left: 0;
49
+ }
50
+
51
+ /* Variants */
52
+ .banner-success {
53
+ background-color: #28a745;
54
+ }
55
+
56
+ .banner-error {
57
+ background-color: #dc3545;
58
+ }
59
+
60
+ .banner-warning {
61
+ background-color: #ffc107;
62
+ color: #333;
63
+ }
64
+
65
+ .banner-info {
66
+ background-color: #17a2b8;
67
+ }
68
+
69
+ /* Animations */
70
+ @keyframes opacityOn {
71
+ 0% { opacity: 0; }
72
+ 100% { opacity: 1; }
73
+ }
74
+
75
+ @keyframes noFadeOut {
76
+ 0% { opacity: 1; }
77
+ 100% { opacity: 1; }
78
+ }
package/src/index.js CHANGED
@@ -1,133 +1,118 @@
1
- import React, { Component } from "react";
2
- import {useState} from 'react';
3
- import PropTypes from 'prop-types';
4
- import "./banner.css";
5
-
6
- /**
7
- * Banner component
8
- * @author [Jose Antonio Ciccio](https://github.com/jciccio)
9
- */
10
- class Banner extends Component {
11
- constructor(props) {
12
- super(props);
13
- this.state = {
14
- showBanner: undefined
15
- };
16
-
17
- }
18
-
19
- componentDidMount() {
20
- this.hideBanner();
21
- }
22
-
23
- static getDerivedStateFromProps(nextProps, prevState) {
24
- if (nextProps.visibleTime !== undefined && nextProps.visibleTime > 0){
25
- let newState = {
26
- bannerMessage: nextProps.bannerMessage,
27
- showBanner: true
28
- };
29
-
30
- return newState;
31
- }
32
- return null;
33
- }
34
-
35
- render() {
36
- let appearTime = this.props.transitionAppearTime ? this.props.transitionAppearTime: 1000;
37
- let transitionTime = this.props.transitionTime ? this.props.transitionTime: 1000;
38
- return (
39
- this.renderBanner()
40
- );
41
- }
42
-
43
- renderImage(){
44
- if (this.props.image && this.props.imageClass){
45
- return(
46
- <img
47
- src={this.props.image}
48
- className={this.props.imageClass}
49
- />
50
- )
51
- }
52
- else if(this.props.image){
53
- return (
54
- <img
55
- src={this.props.image}
56
- />
57
- )
58
- }
59
- else{
60
- return null;
61
- }
62
- }
63
-
64
- async hideBanner() {
65
- if(this.props.visibleTime !== undefined && this.props.visibleTime > 0)
66
- {
67
- this.timeout(this.props.visibleTime);
68
- }
69
- }
70
-
71
- renderBanner() {
72
-
73
- const showBanner = this.state.showBanner !== undefined ? this.state.showBanner : true;
74
-
75
- const visibleTimeAnim = (this.props.visibleTime > 0) ? `opacityOn ${this.props.visibleTime/1000}s` : `noFadeOut 3s`;
76
- const animation = {"animation": `${visibleTimeAnim} normal forwards`}
77
- if(showBanner){
78
- if (this.props.title && (this.state.show === undefined || this.state.showBanner) ) {
79
-
80
- return (
81
- <div key="banner" className="banner" style={{...this.props.css, ...animation}}>
82
- {this.renderImage()}
83
- {this.renderTitle()}
84
- </div>
85
- );
86
- }
87
- else if (this.props.children){
88
- return(
89
- <div key="banner" className="banner" style={{...this.props.css, ...animation}}>
90
- {this.props.children}
91
- </div>
92
- )
93
- }
94
- else {
95
- return null;
96
- }
97
- }
98
- return null;
99
- }
100
-
101
- renderTitle(){
102
- return <div key={`BannerId-${this.props.id}`}>{this.props.title}</div>
103
- }
104
-
105
- timeout(ms) {
106
- setTimeout(() => {
107
- if(this.props.onHideCallback != null){
108
- this.props.onHideCallback(this.props.id);
109
- }
110
- }, ms);
111
- }
112
-
113
- }
114
-
115
- Banner.propTypes = {
116
- title: PropTypes.node,
117
- css: PropTypes.object,
118
- visibleTime: PropTypes.number,
119
- image: PropTypes.string,
120
- imageClass: PropTypes.string,
121
- id: PropTypes.string.isRequired,
122
- transitionAppearTime: PropTypes.number,
123
- transitionTime: PropTypes.number,
124
- showBanner: PropTypes.bool,
125
- children: PropTypes.node,
126
- onHideCallback: PropTypes.func
127
- };
128
-
129
- Banner.defaultProps = {
130
- onHideCallback: null,
131
- }
132
-
133
- export default Banner;
1
+ import React, { useState, useEffect } from "react";
2
+ import PropTypes from 'prop-types';
3
+ import "./banner.css";
4
+
5
+ /**
6
+ * Banner component
7
+ * @author [Jose Antonio Ciccio](https://github.com/jciccio)
8
+ */
9
+ const Banner = ({
10
+ title,
11
+ css = {},
12
+ visibleTime = 0,
13
+ image,
14
+ imageClass,
15
+ id,
16
+ children,
17
+ onHideCallback,
18
+ variant,
19
+ position,
20
+ dismissible
21
+ }) => {
22
+ const [showBanner, setShowBanner] = useState(false);
23
+ const [isClosing, setIsClosing] = useState(false);
24
+
25
+ useEffect(() => {
26
+ // Show banner on mount
27
+ setShowBanner(true);
28
+
29
+ if (visibleTime > 0) {
30
+ const timer = setTimeout(() => {
31
+ handleClose();
32
+ }, visibleTime);
33
+ return () => clearTimeout(timer);
34
+ }
35
+ }, [visibleTime, title, children]); // Re-run if content or timing changes
36
+
37
+ const handleClose = () => {
38
+ setIsClosing(true);
39
+ setTimeout(() => {
40
+ setShowBanner(false);
41
+ setIsClosing(false);
42
+ if (onHideCallback) {
43
+ onHideCallback(id);
44
+ }
45
+ }, 500); // Wait for animation if we add one, or simply unmount
46
+ };
47
+
48
+ if (!showBanner) return null;
49
+
50
+ const getVariantClass = () => {
51
+ switch (variant) {
52
+ case 'success': return 'banner-success';
53
+ case 'error': return 'banner-error';
54
+ case 'warning': return 'banner-warning';
55
+ case 'info': return 'banner-info';
56
+ default: return '';
57
+ }
58
+ };
59
+
60
+ const getPositionClass = () => {
61
+ switch (position) {
62
+ case 'top': return 'banner-top';
63
+ case 'bottom': return 'banner-bottom';
64
+ default: return '';
65
+ }
66
+ };
67
+
68
+ // Construct styles and classes
69
+ const bannerClasses = `banner ${getVariantClass()} ${getPositionClass()}`;
70
+ const animationStyle = visibleTime > 0
71
+ ? { animation: `opacityOn ${visibleTime / 1000}s normal forwards` }
72
+ : { animation: `noFadeOut 3s normal forwards` };
73
+
74
+ return (
75
+ <div
76
+ key="banner"
77
+ className={bannerClasses}
78
+ style={{ ...css, ...animationStyle }}
79
+ >
80
+ <div className="banner-content">
81
+ {image && (
82
+ <img
83
+ src={image}
84
+ className={imageClass}
85
+ alt="banner icon"
86
+ style={{ marginRight: 10 }}
87
+ />
88
+ )}
89
+ {title && <div key={`BannerId-${id}`}>{title}</div>}
90
+ {children}
91
+ </div>
92
+
93
+ {dismissible && (
94
+ <button className="banner-close-btn" onClick={handleClose}>
95
+ &times;
96
+ </button>
97
+ )}
98
+ </div>
99
+ );
100
+ };
101
+
102
+ Banner.propTypes = {
103
+ title: PropTypes.node,
104
+ css: PropTypes.object,
105
+ visibleTime: PropTypes.number,
106
+ image: PropTypes.string,
107
+ imageClass: PropTypes.string,
108
+ id: PropTypes.string, // Made optional as it's not strictly needed for internal logic anymore unless for callback
109
+ transitionAppearTime: PropTypes.number,
110
+ transitionTime: PropTypes.number,
111
+ children: PropTypes.node,
112
+ onHideCallback: PropTypes.func,
113
+ variant: PropTypes.oneOf(['success', 'error', 'warning', 'info']),
114
+ position: PropTypes.oneOf(['top', 'bottom']),
115
+ dismissible: PropTypes.bool
116
+ };
117
+
118
+ export default Banner;
package/webpack.config.js CHANGED
@@ -1,27 +1,23 @@
1
- var path = require("path");
2
-
3
- module.exports = {
4
- mode: "production",
5
- entry: "./src/index.js",
6
- output: {
7
- path: path.resolve("build"),
8
- filename: "index.js",
9
- libraryTarget: "commonjs2"
10
- },
11
- module: {
12
- rules: [
13
- { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" },
14
- {
15
- test: /\.css$/,
16
- loader: "style-loader"
17
- },
18
- {
19
- test: /\.css$/,
20
- loader: "css-loader"
21
- }
22
- ]
23
- },
24
- externals: {
25
- react: "react"
26
- }
1
+ var path = require("path");
2
+
3
+ module.exports = {
4
+ mode: "production",
5
+ entry: "./src/index.js",
6
+ output: {
7
+ path: path.resolve("build"),
8
+ filename: "index.js",
9
+ libraryTarget: "commonjs2"
10
+ },
11
+ module: {
12
+ rules: [
13
+ { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" },
14
+ {
15
+ test: /\.css$/,
16
+ use: ["style-loader", "css-loader"]
17
+ }
18
+ ]
19
+ },
20
+ externals: {
21
+ react: "react"
22
+ }
27
23
  };