├── .babelrc ├── .editorconfig ├── .eslintrc ├── .github └── workflows │ └── npmpublish.yml ├── .gitignore ├── .npmignore ├── .prettierignore ├── .prettierrc ├── .storybook └── main.js ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── examples └── src │ ├── index.html │ └── index.js ├── jest.config.json ├── package-lock.json ├── package.json ├── src ├── components │ └── ConfirmModal.js └── index.js ├── stories └── 0-Confirm.stories.js ├── test ├── components │ └── dialog.test.js └── confirm.test.js └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env", 4 | "@babel/preset-react" 5 | ], 6 | "plugins": [ 7 | "@babel/transform-async-to-generator", 8 | "@babel/transform-regenerator" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true 4 | }, 5 | "extends": [ 6 | "plugin:react/recommended" 7 | ], 8 | "parserOptions": { 9 | "ecmaVersion": 9, 10 | "sourceType": "module" 11 | }, 12 | "plugins": [ 13 | "react" 14 | ], 15 | "rules": { 16 | "indent": [ 17 | "error", 18 | 2 19 | ], 20 | "linebreak-style": [ 21 | "error", 22 | "unix" 23 | ], 24 | "quotes": [ 25 | "error", 26 | "single" 27 | ], 28 | "semi": [ 29 | "error", 30 | "always" 31 | ] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /.github/workflows/npmpublish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages 3 | 4 | name: Node.js Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | - uses: actions/setup-node@v2 16 | with: 17 | node-version: 14 18 | - run: npm install 19 | - run: npm run build 20 | - run: npm test 21 | 22 | publish-npm: 23 | needs: build 24 | runs-on: ubuntu-latest 25 | steps: 26 | - uses: actions/checkout@v2 27 | - uses: actions/setup-node@v2 28 | with: 29 | node-version: 14 30 | registry-url: https://registry.npmjs.org/ 31 | - run: npm install 32 | - run: npm run build 33 | - run: npm publish 34 | env: 35 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 36 | 37 | publish-gpr: 38 | needs: build 39 | runs-on: ubuntu-latest 40 | permissions: 41 | contents: read 42 | packages: write 43 | steps: 44 | - uses: actions/checkout@v2 45 | - uses: actions/setup-node@v2 46 | with: 47 | node-version: 14 48 | registry-url: https://npm.pkg.github.com/ 49 | scope: '@algm' 50 | - run: npm install 51 | - run: npm run build 52 | - run: npm publish 53 | env: 54 | NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.lock 3 | dist 4 | .coverage 5 | .nyc_output 6 | .vscode 7 | out* 8 | storybook-static 9 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | examples 3 | .babelrc 4 | .gitignore 5 | webpack.config.js 6 | .git 7 | .storybook 8 | stories 9 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | webpack.config.js 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "singleQuote": true, 4 | "trailingComma": "es5" 5 | } 6 | -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | core: { 3 | builder: 'webpack5', 4 | }, 5 | stories: [ 6 | '../stories/*.stories.mdx', 7 | '../stories/*.stories.@(js|jsx|ts|tsx)', 8 | ], 9 | addons: ['@storybook/addon-links', '@storybook/addon-essentials'], 10 | }; 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - '10' 5 | - '8' 6 | - '6' 7 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 1.2.0 2 | 3 | ## New features 4 | 5 | - Allow customization of the button component of the modal by using the buttonsComponent prop. 6 | - Allow customization of the modal size by passing the size option. 7 | 8 | ## Bugfixes 9 | 10 | - Fixed reactstrap peer dependency warning. 11 | - Update reactstrap version to 8.1.1 12 | - Fix git submodule errror. See #6. 13 | 14 | ## Other improvements 15 | 16 | - The dialog component is now a function. 17 | - The testing framework has been changed from mocha to jest+enzyme. 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Antonio Gázquez 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Reactstrap confirm 2 | 3 | [![Build Status](https://travis-ci.org/algm/reactstrap-confirm.svg?branch=master)](https://travis-ci.org/algm/reactstrap-confirm) 4 | [![Codacy Badge](https://app.codacy.com/project/badge/Grade/f8a7f7a13a2b4d71ba3d49c2631162a9)](https://www.codacy.com/gh/algm/reactstrap-confirm/dashboard?utm_source=github.com&utm_medium=referral&utm_content=algm/reactstrap-confirm&utm_campaign=Badge_Grade) 5 | [![npm version](https://badge.fury.io/js/reactstrap-confirm.svg)](https://badge.fury.io/js/reactstrap-confirm) 6 | 7 | An easy to use promise based confirm dialog for reactstrap. 8 | 9 | The objective of this package is to offer a simple and easy way for developers to show confirm dialogs within their apps without having to worry about states or having to repeat the same components in many places. 10 | 11 | Demo: https://algm.github.io/reactstrap-confirm 12 | 13 | ## Installation 14 | 15 | Simply use npm 16 | 17 | ```bash 18 | npm i --save reactstrap-confirm 19 | ``` 20 | 21 | You can use yarn as well 22 | 23 | ```bash 24 | yarn add reactstrap-confirm 25 | ``` 26 | 27 | ## Dependencies 28 | 29 | You must manually install react, react-dom and reactstrap in your project in order for this module to work correctly. 30 | 31 | ## Usage 32 | 33 | Simply, import the module and call it as a function anywhere in your code. 34 | 35 | ```javascript 36 | import confirm from "reactstrap-confirm"; 37 | 38 | // ...code 39 | 40 | let result = await confirm(); //will display a confirmation dialog with default settings 41 | 42 | console.log(result); //if the user confirmed, the result value will be true, false otherwhise 43 | ``` 44 | 45 | You can also pass options to the confirm function: 46 | 47 | ```javascript 48 | confirm({ 49 | title: ( 50 | <> 51 | Content can have JSX! 52 | 53 | ), 54 | message: "This is a custom message", 55 | confirmText: "Custom confirm message", 56 | confirmColor: "primary", 57 | cancelColor: "link text-danger" 58 | }); 59 | ``` 60 | 61 | The above example will render a customized dialog. 62 | 63 | ### Available options 64 | 65 | | Option | Effect | Default value | 66 | | ---------------- | ------------------------------------------------------------------------------------------------------------- | ------------- | 67 | | message | Sets the message body of the confirmation dialog | Are you sure? | 68 | | title | Sets the title of the dialog window | Warning! | 69 | | confirmText | Sets the text of the confirm button | Ok | 70 | | cancelText | Sets the text of the cancel button | Cancel | 71 | | confirmColor | Sets the color class of the confirm button (see reactstrap docs) | primary | 72 | | cancelColor | Sets the color class of the cancel button (see reactstrap docs) | _empty_ | 73 | | size | Sets the size property for the modal component (see reactstrap docs) | _empty_ | 74 | | buttonsComponent | Can receive a component for rendering the buttons. The component will receive the onClose function as a prop. | _empty_ | 75 | -------------------------------------------------------------------------------- /examples/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | Reactstrap confirm 12 | 13 | 14 | 15 |
16 |
17 |
18 |
loading...
19 |
20 |
21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /examples/src/index.js: -------------------------------------------------------------------------------- 1 | import 'core-js/stable'; 2 | import 'regenerator-runtime'; 3 | import React from 'react'; 4 | import { render } from 'react-dom'; 5 | import { Button, Container } from 'reactstrap'; 6 | import confirm from '../../src/index'; 7 | 8 | const Example = () => { 9 | const handleBasic = async () => { 10 | let result = await confirm(); 11 | 12 | alert(`Confirm result: ${result}`); 13 | }; 14 | 15 | const handleCustom = async () => { 16 | let result = await confirm({ 17 | title: ( 18 | <> 19 | Content can have JSX! 20 | 21 | ), 22 | message: 'This is a custom message', 23 | confirmText: 'Custom confirm message', 24 | confirmColor: 'primary', 25 | cancelColor: 'link text-danger', 26 | }); 27 | 28 | alert(`Confirm result: ${result}`); 29 | }; 30 | 31 | const handleAlert = async () => { 32 | let result = await confirm({ 33 | title: null, 34 | message: 'I can use this component to display alerts!', 35 | confirmText: 'Understood!', 36 | confirmColor: 'primary', 37 | cancelText: null, 38 | }); 39 | 40 | alert(`Confirm result: ${result}`); 41 | }; 42 | 43 | const handleCustomButtons = async () => { 44 | const CustomComponent = ({ onClose }) => ( 45 |
46 |

I added a custom component for buttons!!

47 | 54 |
55 | ); 56 | 57 | let result = await confirm({ 58 | buttonsComponent: CustomComponent, 59 | }); 60 | 61 | alert(`Confirm result: ${result}`); 62 | }; 63 | 64 | const handleCustomBodyComponent = async () => { 65 | const CustomComponent = () => ( 66 |
67 | this is custom component as a body 68 |
69 | ); 70 | 71 | let result = await confirm({ 72 | bodyComponent: CustomComponent, 73 | title: ( 74 | <> 75 | Content can have JSX! 76 | 77 | ), 78 | message: 'This is a custom message', 79 | confirmText: 'Custom confirm message', 80 | confirmColor: 'primary', 81 | cancelColor: 'link text-danger', 82 | }); 83 | 84 | alert(`Confirm Body component rendered: ${result}`); 85 | }; 86 | 87 | return ( 88 | 89 | 92 | 93 | 96 | 97 | 100 | 101 | 104 | 105 | 108 | 109 | ); 110 | }; 111 | 112 | render(, document.getElementById('app')); 113 | -------------------------------------------------------------------------------- /jest.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "verbose": true 3 | } 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reactstrap-confirm", 3 | "version": "1.3.2", 4 | "description": "Promise based confirm for reactstrap", 5 | "main": "dist/index.js", 6 | "repository": "git@github.com:algm/reactstrap-confirm.git", 7 | "author": "Antonio Gázquez ", 8 | "license": "MIT", 9 | "devDependencies": { 10 | "@babel/cli": "^7.14.5", 11 | "@babel/core": "^7.14.6", 12 | "@babel/eslint-parser": "^7.14.7", 13 | "@babel/node": "^7.14.7", 14 | "@babel/plugin-transform-async-to-generator": "^7.14.5", 15 | "@babel/plugin-transform-regenerator": "^7.14.5", 16 | "@babel/preset-env": "^7.14.7", 17 | "@babel/preset-react": "^7.14.5", 18 | "@babel/register": "^7.14.5", 19 | "@babel/runtime": "^7.14.6", 20 | "@storybook/addon-actions": "^6.3.4", 21 | "@storybook/addon-essentials": "^6.3.4", 22 | "@storybook/addon-info": "^5.3.21", 23 | "@storybook/addon-links": "^6.3.4", 24 | "@storybook/addons": "^6.3.4", 25 | "@storybook/builder-webpack5": "^6.3.4", 26 | "@storybook/manager-webpack5": "^6.3.4", 27 | "@storybook/react": "^6.3.4", 28 | "@storybook/storybook-deployer": "^2.8.10", 29 | "@testing-library/jest-dom": "^5.14.1", 30 | "@testing-library/react": "^12.0.0", 31 | "babel-eslint": "^10.1.0", 32 | "babel-jest": "^27.0.6", 33 | "babel-loader": "^8.2.2", 34 | "bootstrap": "^5.0.2", 35 | "core-js": "^3.15.2", 36 | "css-loader": "^5.2.6", 37 | "eslint": "^7.30.0", 38 | "eslint-plugin-react": "^7.24.0", 39 | "gh-pages": "^3.2.3", 40 | "html-loader": "^2.1.2", 41 | "html-webpack-plugin": "^5.3.2", 42 | "jest": "^27.0.6", 43 | "jsdom": "^16.6.0", 44 | "node-notifier": "^10.0.0", 45 | "react": "^17.0.2", 46 | "react-dom": "^17.0.2", 47 | "reactstrap": "^8.9.0", 48 | "regenerator-runtime": "^0.13.7", 49 | "sinon": "^11.1.1", 50 | "style-loader": "^3.0.0", 51 | "webpack": "^5.44.0", 52 | "webpack-cli": "^4.7.2", 53 | "webpack-dev": "^1.1.1", 54 | "webpack-dev-server": "^3.11.2" 55 | }, 56 | "scripts": { 57 | "test": "node_modules/.bin/jest ", 58 | "tdd": "node_modules/.bin/jest --watch --notify ", 59 | "start": "npx webpack serve --mode=development", 60 | "build": "babel src -d dist --copy-files", 61 | "prepublishOnly": "npm run build", 62 | "buildExample": "npm run build-storybook", 63 | "deploy": "storybook-to-ghpages", 64 | "storybook": "start-storybook -p 6006", 65 | "build-storybook": "build-storybook" 66 | }, 67 | "peerDependencies": { 68 | "react": "^17.0", 69 | "react-dom": "^17.0", 70 | "reactstrap": "^8.9" 71 | }, 72 | "dependencies": { 73 | "lodash.defaults": "^4.2.0" 74 | }, 75 | "storybook-deployer": { 76 | "gitUsername": "algm", 77 | "gitEmail": "algm85@gmail.com", 78 | "commitMessage": "Deploy Storybook [skip ci]" 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/components/ConfirmModal.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from 'reactstrap'; 4 | 5 | const ConfirmModal = ({ 6 | onClose, 7 | message, 8 | title, 9 | confirmText, 10 | cancelText, 11 | confirmColor, 12 | cancelColor, 13 | className, 14 | buttonsComponent, 15 | size, 16 | bodyComponent, 17 | modalProps, 18 | }) => { 19 | let buttonsContent = ( 20 | 21 | {cancelText && ( 22 | 25 | )}{' '} 26 | 29 | 30 | ); 31 | 32 | if (buttonsComponent) { 33 | const CustomComponent = buttonsComponent; 34 | buttonsContent = ; 35 | } 36 | 37 | let BodyComponent = bodyComponent; 38 | 39 | return ( 40 | onClose(false)} 44 | className={`reactstrap-confirm ${className}`} 45 | {...modalProps} 46 | > 47 | {title && ( 48 | onClose(false)}>{title || null} 49 | )} 50 | {bodyComponent ? : message} 51 | {buttonsContent} 52 | 53 | ); 54 | }; 55 | 56 | ConfirmModal.defaultProps = { 57 | message: 'Are you sure?', 58 | title: 'Warning!', 59 | confirmText: 'Ok', 60 | cancelText: 'Cancel', 61 | confirmColor: 'primary', 62 | cancelColor: '', 63 | className: '', 64 | buttonsComponent: null, 65 | size: null, 66 | bodyComponent: null, 67 | modalProps: {}, 68 | }; 69 | 70 | ConfirmModal.propTypes = { 71 | onClose: PropTypes.func.isRequired, 72 | message: PropTypes.node, 73 | title: PropTypes.node, 74 | confirmText: PropTypes.node, 75 | cancelText: PropTypes.node, 76 | confirmColor: PropTypes.string, 77 | cancelColor: PropTypes.string, 78 | className: PropTypes.string, 79 | size: PropTypes.string, 80 | buttonsComponent: PropTypes.func, 81 | bodyComponent: PropTypes.func, 82 | modalProps: PropTypes.object, 83 | }; 84 | 85 | export default ConfirmModal; 86 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, unmountComponentAtNode } from 'react-dom'; 3 | import ConfirmModal from './components/ConfirmModal'; 4 | 5 | const confirm = (props) => { 6 | return new Promise((resolve) => { 7 | let el = document.createElement('div'); 8 | 9 | const handleResolve = (result) => { 10 | unmountComponentAtNode(el); 11 | el = null; 12 | resolve(result); 13 | }; 14 | 15 | render(, el); 16 | }); 17 | }; 18 | 19 | export default confirm; 20 | -------------------------------------------------------------------------------- /stories/0-Confirm.stories.js: -------------------------------------------------------------------------------- 1 | import 'bootstrap/dist/css/bootstrap.min.css'; 2 | import React, { useState } from 'react'; 3 | import confirm from '../src/index'; 4 | import PropTypes from 'prop-types'; 5 | import { 6 | Button, 7 | Container, 8 | Card, 9 | CardImg, 10 | CardBody, 11 | CardText, 12 | } from 'reactstrap'; 13 | 14 | export default { 15 | title: 'Confirm dialog', 16 | }; 17 | 18 | export const basic = () => { 19 | const [confirmed, setConfirmed] = useState(false); 20 | 21 | const basicDialog = async () => { 22 | const result = await confirm(); 23 | 24 | setConfirmed(result); 25 | }; 26 | 27 | return ( 28 | 29 |

By default, the confirm function will render a basic dialog.

30 | 31 |

32 | Confirmed: {confirmed ? 'true' : 'false'} 33 |

34 |
35 | ); 36 | }; 37 | 38 | export const customized = () => { 39 | const [confirmed, setConfirmed] = useState(false); 40 | 41 | const customizedDialog = async () => { 42 | const result = await confirm({ 43 | title: 'I am a custom title 😍', 44 | message: ( 45 | 46 | 52 | 53 | 54 | You can customize the message using anything you want! 55 | 56 | 57 | 58 | ), 59 | confirmColor: 'danger', 60 | cancelText: "I am not sure, don't do anything", 61 | confirmText: 'Yes, I am sure, proceed!', 62 | size: 'sm', 63 | }); 64 | 65 | setConfirmed(result); 66 | }; 67 | 68 | return ( 69 | 70 |

71 | You have a lot of customization options, see{' '} 72 | 77 | Readme 78 | {' '} 79 | for options. 80 |

81 | 82 |

83 | Confirmed: {confirmed ? 'true' : 'false'} 84 |

85 |
86 | ); 87 | }; 88 | 89 | export const Alert = () => { 90 | const alertDialog = async () => { 91 | await confirm({ 92 | title: 'Warning!', 93 | message: 'You can use the confirm function as a way to display alerts!', 94 | cancelText: null, 95 | confirmText: 'Understood!', 96 | }); 97 | }; 98 | 99 | return ( 100 | 101 |

102 | This module can also be used for displaying alerts if you pass the 103 | cancelText as null (that will hide the cancel action). 104 |

105 | 106 |
107 | ); 108 | }; 109 | 110 | export const customButtonsComponent = () => { 111 | const [confirmed, setConfirmed] = useState(false); 112 | 113 | const customButtonsDialog = async () => { 114 | const CustomComponent = ({ onClose }) => ( 115 |
116 |

I added a custom component for buttons!!

117 | 124 |
125 | ); 126 | 127 | CustomComponent.propTypes = { 128 | onClose: PropTypes.func, 129 | }; 130 | 131 | const result = await confirm({ 132 | buttonsComponent: CustomComponent, 133 | }); 134 | 135 | setConfirmed(result); 136 | }; 137 | 138 | return ( 139 | 140 |

141 | You can pass a custom buttons component to customize the behavior even 142 | further! 143 |

144 | 145 |

146 | Confirmed: {confirmed ? 'true' : 'false'} 147 |

148 |
149 | ); 150 | }; 151 | 152 | /*import { Button } from '@storybook/react/demo'; 153 | 154 | export default { 155 | title: 'Button', 156 | }; 157 | 158 | export const text = () => ; 159 | 160 | export const emoji = () => ( 161 | 166 | ); 167 | */ 168 | -------------------------------------------------------------------------------- /test/components/dialog.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @jest-environment jsdom 3 | */ 4 | 5 | /* global describe, it, expect */ 6 | import React from 'react'; 7 | import { render, screen } from '@testing-library/react'; 8 | import Dialog from '../../src/components/ConfirmModal'; 9 | import { Button } from 'reactstrap'; 10 | 11 | describe('confirm dialog component', () => { 12 | it('renders with defaults', () => { 13 | render( {}}>); 14 | 15 | expect(screen.findByRole('dialog')).toBeDefined(); 16 | }); 17 | 18 | describe('content customization', () => { 19 | it('can customize title', () => { 20 | render( {}}>); 21 | const found = screen.findByText('custom title'); 22 | 23 | expect(found).toBeDefined(); 24 | }); 25 | 26 | it('can customize message', () => { 27 | render( {}}>); 28 | const found = screen.findByText('custom text'); 29 | expect(found).toBeDefined(); 30 | }); 31 | 32 | it('can customize size', () => { 33 | render( {}}>); 34 | const dialog = screen.getByRole('dialog'); 35 | 36 | const classes = dialog.getElementsByClassName('modal-lg'); 37 | 38 | expect(classes.length).toEqual(1); 39 | }); 40 | }); 41 | 42 | describe('button customization', () => { 43 | it('can customize colors', () => { 44 | render( 45 | {}} 49 | > 50 | ); 51 | const dialog = screen.getByRole('dialog'); 52 | 53 | expect(dialog.getElementsByClassName('btn-confirmColor').length).toEqual( 54 | 1 55 | ); 56 | expect(dialog.getElementsByClassName('btn-cancelColor').length).toEqual( 57 | 1 58 | ); 59 | }); 60 | 61 | it('can customize text', () => { 62 | render( 63 | {}} 69 | > 70 | ); 71 | 72 | expect(screen.getByText('confirmText')).toBeDefined(); 73 | expect(screen.getByText('cancelText')).toBeDefined(); 74 | }); 75 | 76 | it('can customize buttons component', () => { 77 | const CustomButtons = ({ onClose }) => ( 78 |
79 | 82 |
83 | ); 84 | 85 | render( 86 | {}}> 87 | ); 88 | 89 | const dialog = screen.getByRole('dialog'); 90 | 91 | expect(dialog.getElementsByClassName('custom-buttons').length).toEqual(1); 92 | }); 93 | }); 94 | }); 95 | -------------------------------------------------------------------------------- /test/confirm.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @jest-environment jsdom 3 | */ 4 | 5 | /* global describe, it, expect, jest */ 6 | import confirm from '../src/index'; 7 | import { screen } from '@testing-library/dom'; 8 | import { fireEvent } from '@testing-library/react'; 9 | 10 | describe('confirm function', () => { 11 | it('renders the modal on calling', () => { 12 | confirm(); 13 | 14 | const found = screen.findByText('Are you sure?'); 15 | 16 | expect(found).toBeDefined(); 17 | 18 | const button = screen.getByText('Ok'); 19 | 20 | fireEvent.click(button); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /*** webpack.config.js ***/ 2 | const path = require('path'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const htmlWebpackPlugin = new HtmlWebpackPlugin({ 5 | template: path.join(__dirname, 'examples/src/index.html'), 6 | filename: './index.html', 7 | }); 8 | module.exports = { 9 | entry: path.join(__dirname, 'examples/src/index.js'), 10 | mode: process.env.NODE_ENV || 'production', 11 | output: { 12 | path: path.join(__dirname, 'examples/dist'), 13 | filename: 'bundle.js', 14 | }, 15 | module: { 16 | rules: [ 17 | { 18 | test: /\.(js|jsx)$/, 19 | use: 'babel-loader', 20 | exclude: /node_modules/, 21 | }, 22 | ], 23 | }, 24 | plugins: [htmlWebpackPlugin], 25 | resolve: { 26 | extensions: ['.js', '.jsx'], 27 | }, 28 | devServer: { 29 | port: 3001, 30 | }, 31 | }; 32 | --------------------------------------------------------------------------------