diff --git a/README.md b/README.md index 88281e7..998ad57 100644 --- a/README.md +++ b/README.md @@ -1,116 +1,134 @@ # 🦞 modali -A delightful modal dialog library for React, built from the ground up to support React Hooks. Modali provides a simple interface to build beautiful modals in minutes. + +A delightful modal dialog library for React, built from the ground up to support +React Hooks. Modali provides a simple interface to build beautiful modals in +minutes.

drawing

-A full tutorial on [Modal Components in React Using Custom Hooks](https://upmostly.com/tutorials/modal-components-react-custom-hooks/) can be found over at https://upmostly.com +A full tutorial on +[Modal Components in React Using Custom Hooks](https://upmostly.com/tutorials/modal-components-react-custom-hooks/) +can be found over at https://upmostly.com ## Live Demo https://upmostly.github.io/modali/ ## Installation + Install Modali in your project using npm: ``` npm install --save modali ``` -**⚠️ Modali uses React Hooks, therefore you are required to use React v16.8 or above when using Modali.** +**⚠️ Modali uses React Hooks, therefore you are required to use React v16.8 or +above when using Modali.** ## Usage -Import the `Modali` component and `useModali` Hook in your React components, like so: +Import the `Modali` component and `useModali` Hook in your React components, +like so: + ```javascript -import Modali, { useModali } from 'modali'; +import Modali, { useModali } from "modali"; ``` -After you've imported the Modali component and useModali Hook, you're ready to start using Modali inside your components! 🎉 +After you've imported the Modali component and useModali Hook, you're ready to +start using Modali inside your components! 🎉 ### Basic Modal ```jsx -import React from 'react'; -import Modali, { useModali } from 'modali'; +import React from "react"; +import Modali, { useModali } from "modali"; const App = () => { const [exampleModal, toggleExampleModal] = useModali(); return (
- - - Hi, I'm a Modali! - + + Hi, I'm a Modali!
); }; export default App; - ``` ### Title, Message, and Buttons -Modali provides everything you need to build beautiful modals in minutes. Use the title, message and buttons props to customize your modal as quick as a flash! ⚡️ +Modali provides everything you need to build beautiful modals in minutes. Use +the title, message and buttons props to customize your modal as quick as a +flash! ⚡️ ```jsx -import React from 'react'; -import Modali, { useModali } from 'modali'; +import React from "react"; +import Modali, { useModali } from "modali"; const App = () => { const [completeExample, toggleCompleteModal] = useModali({ animated: true, - title: 'Are you sure?', - message: 'Deleting this user will be permanent.', + title: "Are you sure?", + message: "Deleting this user will be permanent.", buttons: [ - toggleCompleteModal()} - />, - deleteUserWithId('123')} - />, + { + key: "cancel", + content: ( + toggleCompleteModal()} + /> + ), + }, + { + key: "delete", + content: ( + deleteUserWithId("123")} + /> + ), + }, ], }); return (
- +
); }; export default App; - ``` ### useModali Hook -Much like the useState Hook, the `useModali` Hook returns two values which can be named whatever you'd like: +Much like the useState Hook, the `useModali` Hook returns two values which can +be named whatever you'd like: - An object containing props which must be passed into the Modali component. - A function to toggle the Modali component. -This is demonstrated in the example above, from the following line: -
+This is demonstrated in the example above, from the following line:
`const [exampleModal, toggleExampleModal] = useModali();` -- `exampleModal` is the props object. Again, this must be passed into the Modali component. + +- `exampleModal` is the props object. Again, this must be passed into the Modali + component. - `toggleExampleModal` is the function to show/hide Modali. ### Component -The `` component provides a beautiful, WAI-ARIA accessible modal dialog out of the box. Import it, add it to your component tree, pass in the props object that you get from the useModali Hook and you're all set. +The `` component provides a beautiful, WAI-ARIA accessible modal +dialog out of the box. Import it, add it to your component tree, pass in the +props object that you get from the useModali Hook and you're all set. ```jsx ... @@ -129,62 +147,77 @@ return ( ### Component -The `` component provides a ready-to-go button component that includes three separate styles of button: default, cancel, and destructive. +The `` component provides a ready-to-go button component that +includes three separate styles of button: default, cancel, and destructive. ```jsx -... +// ... const [completeExample, toggleCompleteModal] = useModali({ buttons: [ - handleDoneClicked()} - />, - toggleCompleteModal()} - />, - deleteUserWithId('123')} - />, + { + key: "done", + content: ( + handleDoneClicked()} + /> + ), + }, + { + key: "cancel", + content: ( + toggleCompleteModal()} + /> + ), + }, + { + key: "delete", + content: ( + deleteUserWithId("123")} + /> + ), + }, ], }); -return ( - - Hi, I'm a Modali - -); - -... +return Hi, I'm a Modali; +// ... ``` + ### Props -| Prop | Description | -| --- | --- | -| `label` | String that is shown on the button | -| `isStyleDefault` | Pass in this prop as true to show the default button | -| `isStyleCancel` | Pass in this prop as true to show a cancel button | -| `isStyleDestructive` | Pass in this prop as true to show a delete button | -| `onClick` | Called when the button is clicked | + +| Prop | Description | +| -------------------- | ---------------------------------------------------- | +| `label` | String that is shown on the button | +| `isStyleDefault` | Pass in this prop as true to show the default button | +| `isStyleCancel` | Pass in this prop as true to show a cancel button | +| `isStyleDestructive` | Pass in this prop as true to show a delete button | +| `onClick` | Called when the button is clicked | ## More Examples ### Multiple Modals -This flexibility of being able to name the props object and toggle function allows us to use multiple Modalis in the same component: + +This flexibility of being able to name the props object and toggle function +allows us to use multiple Modalis in the same component: ```jsx -import React from 'react'; -import Modali, { useModali } from 'modali'; +import React from "react"; +import Modali, { useModali } from "modali"; const App = () => { const [firstModal, toggleFirstModal] = useModali(); const [secondModal, toggleSecondModal] = useModali(); - + return (
- - Hi, I'm the first Modali - - - And I'm the second Modali - + Hi, I'm the first Modali + And I'm the second Modali
); }; export default App; - ``` ## Modali Options -Modali provides an easy to use interface for accessing useful events, such as when the modal shows and hides. +Modali provides an easy to use interface for accessing useful events, such as +when the modal shows and hides. ### Events -| Event | Description | -| --- | --- | -| `onShow` | Called when the component finishes mounting to the DOM | -| `onHide` | Called when the component is removed from the DOM | -| `onEscapeKeyDown` | Called when the escape key is pressed while the component is mounted to the DOM | -| `onOverlayClick` | Called when the modal overlay back is clicked while the component is mounted to the DOM | +| Event | Description | +| ----------------- | --------------------------------------------------------------------------------------- | +| `onShow` | Called when the component finishes mounting to the DOM | +| `onHide` | Called when the component is removed from the DOM | +| `onEscapeKeyDown` | Called when the escape key is pressed while the component is mounted to the DOM | +| `onOverlayClick` | Called when the modal overlay back is clicked while the component is mounted to the DOM | Example ```javascript const [exampleModal, toggleExampleModal] = useModali({ - onShow: () => console.log('Modali is shown'), - onHide: () => console.log('Modali is hidden') + onShow: () => console.log("Modali is shown"), + onHide: () => console.log("Modali is hidden"), }); - ``` -Modali can be easily customized by passing in an object of key/value pairs to the useModali Hook's initializer: +Modali can be easily customized by passing in an object of key/value pairs to +the useModali Hook's initializer: ### Props -| Option | Default Value | Description | -| --- | --- | --- | -| `title` | string | The text displayed in the upper left corner | -| `message` | string | The text displayed in the body of the modal | -| `buttons` | array | Displays whatever is passed in in the footer | -| `closeButton` | true | Controls the visibility of the close button | -| `animated` | false | Fades in the modal when it mounts to the DOM | -| `centered` | false | Positions the modal in the center of the screen | -| `large` | false | Changes the size of the modal to be 800px wide | -| `overlayClose` | true | Disables clicking the modal overlay to hide it | -| `keyboardClose` | true | Disables the ESC key hiding the modal | +| Option | Default Value | Description | +| --------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------- | +| `title` | string | The text displayed in the upper left corner | +| `message` | string | The text displayed in the body of the modal | +| `buttons` | array | Displays whatever is passed in in the footer. Array elements must have the form `{ key: uniqueString, content: any }`. | +| `closeButton` | true | Controls the visibility of the close button | +| `animated` | false | Fades in the modal when it mounts to the DOM | +| `centered` | false | Positions the modal in the center of the screen | +| `large` | false | Changes the size of the modal to be 800px wide | +| `overlayClose` | true | Disables clicking the modal overlay to hide it | +| `keyboardClose` | true | Disables the ESC key hiding the modal | Example @@ -254,13 +283,12 @@ const [exampleModal, toggleExampleModal] = useModali({ large: true, closeButton: false, }); - ``` -Of course, props and events can be combined when passing the options to the useModali Hook: +Of course, props and events can be combined when passing the options to the +useModali Hook: ```javascript - function handleModalOnHide() { // do something when the modal hides } @@ -270,5 +298,4 @@ const [exampleModal, toggleExampleModal] = useModali({ large: true, closeButton: false, }); - ``` diff --git a/package-lock.json b/package-lock.json index d4eab4e..24a015d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -56,17 +56,19 @@ } }, "@babel/runtime": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.3.tgz", - "integrity": "sha512-9lsJwJLxDh/T3Q3SZszfWOTkk3pHbkmH+3KY+zwIDmsNlxsumuhS2TH3NIpktU4kNvfzy+k3eLT7aTJSPTo0OA==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.3.tgz", + "integrity": "sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA==", + "dev": true, "requires": { "regenerator-runtime": "^0.13.2" }, "dependencies": { "regenerator-runtime": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz", - "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==" + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", + "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", + "dev": true } } }, @@ -1845,19 +1847,22 @@ } }, "character-entities": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz", - "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==" + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.3.tgz", + "integrity": "sha512-yB4oYSAa9yLcGyTbB4ItFwHw43QHdH129IJ5R+WvxOkWlyFnR5FAaBNnUq4mcxsTVZGh28bHoeTHMKXH1wZf3w==", + "dev": true }, "character-entities-legacy": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz", - "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.3.tgz", + "integrity": "sha512-YAxUpPoPwxYFsslbdKkhrGnXAtXoHNgYjlBM3WMXkWGTl5RsY3QmOyhwAgL8Nxm9l5LBThXGawxKPn68y6/fww==", + "dev": true }, "character-reference-invalid": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz", - "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.3.tgz", + "integrity": "sha512-VOq6PRzQBam/8Jm6XBGk2fNEnHXAdGd6go0rtd4weAGECBamHDwwCQSOT12TACIYUZegUXnV6xBXqUssijtxIg==", + "dev": true }, "chardet": { "version": "0.7.0", @@ -1974,6 +1979,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.4.tgz", "integrity": "sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ==", + "dev": true, "optional": true, "requires": { "good-listener": "^1.2.2", @@ -2057,12 +2063,10 @@ "dev": true }, "comma-separated-tokens": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz", - "integrity": "sha512-Cg90/fcK93n0ecgYTAz1jaA3zvnQ0ExlmKY1rdbyHqAx6BHxwoJc+J7HDu0iuQ7ixEs1qaa+WyQ6oeuBpYP1iA==", - "requires": { - "trim": "0.0.1" - } + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.7.tgz", + "integrity": "sha512-Jrx3xsP4pPv4AwJUDWY9wOXGtwPXARej6Xd99h4TUGotmf8APuquKMpK+dnD3UgyxK7OEWaisjZz+3b5jtL6xQ==", + "dev": true }, "commander": { "version": "2.20.0", @@ -2486,6 +2490,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", + "dev": true, "optional": true }, "depd": { @@ -3392,9 +3397,10 @@ "dev": true }, "fault": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.2.tgz", - "integrity": "sha512-o2eo/X2syzzERAtN5LcGbiVQ0WwZSlN3qLtadwAz3X8Bu+XWD16dja/KMsjZLiQr+BLGPDnHGkc4yUJf1Xpkpw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.3.tgz", + "integrity": "sha512-sfFuP4X0hzrbGKjAUNXYvNqsZ5F6ohx/dZ9I0KQud/aiZNwg263r5L9yGB0clvXHCkzXh5W3t7RSHchggYIFmA==", + "dev": true, "requires": { "format": "^0.2.2" } @@ -3619,7 +3625,8 @@ "format": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", - "integrity": "sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=" + "integrity": "sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=", + "dev": true }, "forwarded": { "version": "0.1.2", @@ -4425,6 +4432,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", + "dev": true, "optional": true, "requires": { "delegate": "^3.1.2" @@ -4525,14 +4533,16 @@ } }, "hast-util-parse-selector": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.1.tgz", - "integrity": "sha512-Xyh0v+nHmQvrOqop2Jqd8gOdyQtE8sIP9IQf7mlVDqp924W4w/8Liuguk2L2qei9hARnQSG2m+wAOCxM7npJVw==" + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.2.tgz", + "integrity": "sha512-jIMtnzrLTjzqgVEQqPEmwEZV+ea4zHRFTP8Z2Utw0I5HuBOXHzUPPQWr6ouJdJqDKLbFU/OEiYwZ79LalZkmmw==", + "dev": true }, "hastscript": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-5.0.0.tgz", - "integrity": "sha512-xJtuJ8D42Xtq5yJrnDg/KAIxl2cXBXKoiIJwmWX9XMf8113qHTGl/Bf7jEsxmENJ4w6q4Tfl8s/Y6mEZo8x8qw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-5.1.0.tgz", + "integrity": "sha512-7mOQX5VfVs/gmrOGlN8/EDfp1GqV6P3gTNVt+KnX4gbYhpASTM8bklFdFQCbFRAadURXAmw0R1QQdBdqp7jswQ==", + "dev": true, "requires": { "comma-separated-tokens": "^1.0.0", "hast-util-parse-selector": "^2.2.0", @@ -4549,7 +4559,8 @@ "highlight.js": { "version": "9.13.1", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.13.1.tgz", - "integrity": "sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==" + "integrity": "sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==", + "dev": true }, "hmac-drbg": { "version": "1.0.1", @@ -5078,14 +5089,16 @@ } }, "is-alphabetical": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.2.tgz", - "integrity": "sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.3.tgz", + "integrity": "sha512-eEMa6MKpHFzw38eKm56iNNi6GJ7lf6aLLio7Kr23sJPAECscgRtZvOBYybejWDQ2bM949Y++61PY+udzj5QMLA==", + "dev": true }, "is-alphanumerical": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", - "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.3.tgz", + "integrity": "sha512-A1IGAPO5AW9vSh7omxIlOGwIqEvpW/TA+DksVOPM5ODuxKlZS09+TEM1E3275lJqO2oJ38vDpeAL3DCIiHE6eA==", + "dev": true, "requires": { "is-alphabetical": "^1.0.0", "is-decimal": "^1.0.0" @@ -5134,9 +5147,10 @@ "dev": true }, "is-decimal": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.2.tgz", - "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.3.tgz", + "integrity": "sha512-bvLSwoDg2q6Gf+E2LEPiklHZxxiSi3XAh4Mav65mKqTfCO1HM3uBs24TjEH8iJX3bbDdLXKJXBTmGzuTUuAEjQ==", + "dev": true }, "is-descriptor": { "version": "0.1.6", @@ -5214,9 +5228,10 @@ } }, "is-hexadecimal": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz", - "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.3.tgz", + "integrity": "sha512-zxQ9//Q3D/34poZf8fiy3m3XVpbQc7ren15iKqrTtLPwkPD/t3Scy9Imp63FujULGxuK0ZlCwoo5xNpktFgbOA==", + "dev": true }, "is-number": { "version": "3.0.0", @@ -5537,6 +5552,7 @@ "version": "1.11.0", "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.11.0.tgz", "integrity": "sha512-xrGGN6XLL7MbTMdPD6NfWPwY43SNkjf/d0mecSx/CW36fUZTjRHEq0/Cdug3TWKtRXLWi7iMl1eP0olYxj/a4A==", + "dev": true, "requires": { "fault": "^1.0.2", "highlight.js": "~9.13.0" @@ -5837,11 +5853,6 @@ "dev": true, "optional": true }, - "nanoid": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.0.3.tgz", - "integrity": "sha512-NbaoqdhIYmY6FXDRB4eYtDVC9Z9eCbn8TyaiC16LNKtpPv/aqa0tOPD8y6gNE4yUNnaZ7LLhYtXOev/6+cBtfw==" - }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -6326,9 +6337,10 @@ } }, "parse-entities": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.1.tgz", - "integrity": "sha512-NBWYLQm1KSoDKk7GAHyioLTvCZ5QjdH/ASBBQTD3iLiAWJXS5bg1jEWI8nIJ+vgVvsceBVBcDGRWSo0KVQBvvg==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", + "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", + "dev": true, "requires": { "character-entities": "^1.0.0", "character-entities-legacy": "^1.0.0", @@ -6668,9 +6680,10 @@ } }, "prismjs": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.16.0.tgz", - "integrity": "sha512-OA4MKxjFZHSvZcisLGe14THYsug/nF6O1f0pAJc0KN0wTyAcLqmsbE+lTGKSpyh+9pEW57+k6pg2AfYR+coyHA==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.17.1.tgz", + "integrity": "sha512-PrEDJAFdUGbOP6xK/UsfkC5ghJsPJviKgnQOoxaDbBjwc8op68Quupwt1DeAFoG8GImPhiKXAvvsH7wDSLsu1Q==", + "dev": true, "requires": { "clipboard": "^2.0.0" } @@ -6716,9 +6729,10 @@ } }, "property-information": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.0.1.tgz", - "integrity": "sha512-nAtBDVeSwFM3Ot/YxT7s4NqZmqXI7lLzf46BThvotEtYf2uk2yH0ACYuWQkJ7gxKs49PPtKVY0UlDGkyN9aJlw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.3.0.tgz", + "integrity": "sha512-IslotQn1hBCZDY7SaJ3zmCjVea219VTwmOk6Pu3z9haU9m4+T8GwaDubur+6NMHEU+Fjs/6/p66z6QULPkcL1w==", + "dev": true, "requires": { "xtend": "^4.0.1" } @@ -6924,6 +6938,7 @@ "version": "10.2.1", "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-10.2.1.tgz", "integrity": "sha512-oiCu5H0cv8FoBx1RfKWFJJEWARIyvl8FbOpzLtTextkN2D6mPAFjRooSyP0sU7/BqZnt7C6vF1CqrjdnEKREYw==", + "dev": true, "requires": { "@babel/runtime": "^7.3.1", "highlight.js": "~9.13.0", @@ -6980,13 +6995,14 @@ } }, "refractor": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/refractor/-/refractor-2.8.0.tgz", - "integrity": "sha512-w+jG49/1MX60GeE9u8lyx1KYMBRdAHjOIfgcDJ0wq2ogOnEmab0MgIj+AtPq6kelw0mr1l9U0i2rFvLlOCkxiw==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/refractor/-/refractor-2.10.0.tgz", + "integrity": "sha512-maW2ClIkm9IYruuFYGTqKzj+m31heq92wlheW4h7bOstP+gf8bocmMec+j7ljLcaB1CAID85LMB3moye31jH1g==", + "dev": true, "requires": { "hastscript": "^5.0.0", "parse-entities": "^1.1.2", - "prismjs": "~1.16.0" + "prismjs": "~1.17.0" } }, "regenerate": { @@ -7284,6 +7300,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=", + "dev": true, "optional": true }, "select-hose": { @@ -7427,14 +7444,6 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, - "shortid": { - "version": "2.2.14", - "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.14.tgz", - "integrity": "sha512-4UnZgr9gDdA1kaKj/38IiudfC3KHKhDc1zi/HSxd9FQDR0VLwH3/y79tZJLsVYPsJgIjeHjqIWaWVRJUj9qZOQ==", - "requires": { - "nanoid": "^2.0.0" - } - }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -7677,12 +7686,10 @@ "dev": true }, "space-separated-tokens": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz", - "integrity": "sha512-G3jprCEw+xFEs0ORweLmblJ3XLymGGr6hxZYTYZjIlvDti9vOBUjRQa1Rzjt012aRrocKstHwdNi+F7HguPsEA==", - "requires": { - "trim": "0.0.1" - } + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.4.tgz", + "integrity": "sha512-UyhMSmeIqZrQn2UdjYpxEkwY9JUrn8pP+7L4f91zRzOQuI8MF1FGLfYU9DKCYeLdo7LXMxwrX5zKFy7eeeVHuA==", + "dev": true }, "spdx-correct": { "version": "3.1.0", @@ -8187,6 +8194,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", + "dev": true, "optional": true }, "tmp": { @@ -8247,11 +8255,6 @@ "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", "dev": true }, - "trim": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" - }, "trim-repeated": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", @@ -9041,7 +9044,8 @@ "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true }, "y18n": { "version": "3.2.1", diff --git a/package.json b/package.json index aa34540..96dc084 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "html-webpack-plugin": "^3.2.0", "react": "^16.8.0", "react-dom": "^16.8.0", + "react-syntax-highlighter": "^10.2.1", "style-loader": "^0.23.1", "webpack": "^4.29.6", "webpack-cli": "^3.3.0", @@ -60,7 +61,6 @@ "dependencies": { "classnames": "^2.2.6", "prop-types": "^15.7.2", - "react-syntax-highlighter": "^10.2.1", "shortid": "^2.2.14" } } diff --git a/src/index.js b/src/index.js index 6dba248..ced0dd3 100644 --- a/src/index.js +++ b/src/index.js @@ -73,13 +73,14 @@ const Modal = ({ function renderFooter() { const { buttons } = options; + return (
{buttons.map(button => ( - {button} + {button.content} ))}
@@ -88,14 +89,14 @@ const Modal = ({ const modaliWrapperClass = classNames({ 'modali-wrapper': true, - 'modali-wrapper-centered': options && options.centered, + 'modali-wrapper-centered': options.centered, }); const modaliClass = classNames({ modali: true, - 'modali-size-large': options && options.large, - 'modali-size-regular': !options || (options && !options.large), - 'modali-animated modali-animation-fade-in': options && options.animated, + 'modali-size-large': options.large, + 'modali-size-regular': !options.large, + 'modali-animated modali-animation-fade-in': options.animated, }); return isModalVisible ? ReactDOM.createPortal( @@ -104,9 +105,9 @@ const Modal = ({
- {options !== undefined && options.closeButton === false ? null : ( + {options.closeButton === false ? null : (
- {options !== undefined && options.title !== undefined && ( + {options.title !== undefined && (
{options.title}
@@ -119,7 +120,7 @@ const Modal = ({
{renderBody()}
- {options && options.buttons && options.buttons.length > 0 && renderFooter()} + {options.buttons && options.buttons.length > 0 && renderFooter()}
@@ -127,12 +128,35 @@ const Modal = ({ ) : null; }; +Modal.propTypes = { + isModalVisible: PropTypes.bool.isRequired, + hide: PropTypes.func.isRequired, + options: PropTypes.shape({ + onShow: PropTypes.func, + onHide: PropTypes.func, + onEscapeKeyDown: PropTypes.func, + onOverlayClick: PropTypes.func, + title: PropTypes.string, + message: PropTypes.string, + buttons: PropTypes.arrayOf(PropTypes.exact({ + key: PropTypes.string, + content: PropTypes.any, + })), + closeButton: PropTypes.bool, + animated: PropTypes.bool, + centered: PropTypes.bool, + large: PropTypes.bool, + overlayClose: PropTypes.bool, + keyboardClose: PropTypes.bool, + }).isRequired, +}; + const Modali = () => {}; Modali.Button = Button; Modali.Modal = Modal; export default Modali; -export const useModali = (options) => { +export const useModali = (options = {}) => { const [hasToggledBefore, setHasToggledBefore] = useState(false); const [isModalVisible, setIsModalVisible] = useState(false); const [isShown, setIsShown] = useState(false); @@ -150,23 +174,23 @@ export const useModali = (options) => { } function handleKeyDown(event) { - if (event.keyCode !== 27 || (options && options.keyboardClose === false)) return; + if (event.keyCode !== 27 || (options.keyboardClose === false)) return; toggle(); - if (options && options.onEscapeKeyDown) { + if (options.onEscapeKeyDown) { options.onEscapeKeyDown(); } } useEffect(() => { if (isShown) { - if (options && options.onShow) { + if (options.onShow) { options.onShow(); } document.addEventListener('keydown', handleKeyDown); document.body.classList.add('modali-open'); } if (!isShown && hasToggledBefore) { - if (options && options.onHide) { + if (options.onHide) { options.onHide(); } document.body.classList.remove('modali-open');