{"_id":"@alexigrigorov/ocpr13-wealthhealth-modal","name":"@alexigrigorov/ocpr13-wealthhealth-modal","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@alexigrigorov/ocpr13-wealthhealth-modal","version":"1.0.0","description":"A reusable React Modal component for the WealthHealth project.","main":"dist/ocpr13-wealthhealth-modal.es.js","module":"dist/ocpr13-wealthhealth-modal.es.js","scripts":{"build":"vite build","prepare":"npm run build"},"repository":{"type":"git","url":"git+https://github.com/alexiGrigorov/OCPR13-WealthHealth-Modal.git"},"author":{"name":"Alexi GRIGOROV"},"license":"ISC","bugs":{"url":"https://github.com/alexiGrigorov/OCPR13-WealthHealth-Modal/issues"},"homepage":"https://github.com/alexiGrigorov/OCPR13-WealthHealth-Modal#readme","peerDependencies":{"react":"^19.1.0","react-dom":"^19.1.0"},"devDependencies":{"@vitejs/plugin-react":"^4.4.1","vite":"^6.3.5"},"_id":"@alexigrigorov/ocpr13-wealthhealth-modal@1.0.0","gitHead":"4f423cb67f63d284306a5e0489dfcc0ac37b3162","_nodeVersion":"22.14.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-beSGdaT/6v8ai5YSLGb07GP1ajUlgry0RdiOinuFiM5kldvN7uMywxgD7/fbSmxRuBgpBXEzue7tMdKkWkBKsA==","shasum":"6637d81f067f79426f2fbba59271527d05826d4a","tarball":"https://registry.npmjs.org/@alexigrigorov/ocpr13-wealthhealth-modal/-/ocpr13-wealthhealth-modal-1.0.0.tgz","fileCount":4,"unpackedSize":29169,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDTsaj8fYqNfGQ8fXdMgoNwWscku4uyBELsGEQs2CQRbQIgbzR3XSXBxOC/DOzC6DHaDlsouYMHfJ7kFqfmmybx+xI="}]},"_npmUser":{"name":"alexigrigorov","email":"alexigrigorov@gmail.com"},"directories":{},"maintainers":[{"name":"alexigrigorov","email":"alexigrigorov@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ocpr13-wealthhealth-modal_1.0.0_1747217197707_0.49634293238043514"},"_hasShrinkwrap":false}},"time":{"created":"2025-05-14T10:06:37.610Z","1.0.0":"2025-05-14T10:06:37.894Z","modified":"2025-05-14T10:06:38.171Z"},"maintainers":[{"name":"alexigrigorov","email":"alexigrigorov@gmail.com"}],"description":"A reusable React Modal component for the WealthHealth project.","homepage":"https://github.com/alexiGrigorov/OCPR13-WealthHealth-Modal#readme","repository":{"type":"git","url":"git+https://github.com/alexiGrigorov/OCPR13-WealthHealth-Modal.git"},"author":{"name":"Alexi GRIGOROV"},"bugs":{"url":"https://github.com/alexiGrigorov/OCPR13-WealthHealth-Modal/issues"},"license":"ISC","readme":"# ocpr13-wealthhealth-modal\n\nA reusable, unstyled React Modal component built on the native `<dialog>` element.  \nProvides a flexible compound-component API and focus management without imposing any CSS opinion.\n\n---\n\n## Installation\n\n```bash\n# From npm registry\nnpm install @alexigrigorov/ocpr13-wealthhealth-modal\n```\n\n**Peer Dependencies**\n\n- **react** `^19.1.0`\n- **react-dom** `^19.1.0`\n\n---\n\n## Quick Start\n\n1. **Add a portal container** to your HTML (e.g. `public/index.html`):\n\n   ```html\n   <body>\n     <div id=\"root\"></div>\n     <div id=\"modal\"></div>\n     <!-- Required portal target -->\n   </body>\n   ```\n\n2. **Use the Modal** in your React component:\n\n   ```jsx\n   import React, { useState } from \"react\";\n   import { Modal } from \"ocpr13-wealthhealth-modal\";\n\n   function App() {\n     const [isOpen, setIsOpen] = useState(false);\n\n     return (\n       <>\n         <button onClick={() => setIsOpen(true)}>Open Modal</button>\n\n         <Modal\n           isOpen={isOpen}\n           onClose={() => setIsOpen(false)}\n           showCloseButton={true}\n           disableBackdropClick={false}\n           /* Any other <dialog> props: className, style, id, aria-* */\n         >\n           <Modal.Header>\n             <h2>Modal Title</h2>\n           </Modal.Header>\n\n           <Modal.Body>\n             <p>Your content goes here.</p>\n           </Modal.Body>\n\n           <Modal.Footer>\n             <button onClick={() => setIsOpen(false)}>Close</button>\n           </Modal.Footer>\n         </Modal>\n       </>\n     );\n   }\n   ```\n\n---\n\n## API Reference\n\n### `<Modal />` props\n\n| Prop                   | Type         | Default | Description                                                                         |\n| ---------------------- | ------------ | ------- | ----------------------------------------------------------------------------------- |\n| `isOpen` _(required)_  | `boolean`    | —       | Control open state (`true` = open, `false` = closed).                               |\n| `onClose` _(required)_ | `() => void` | —       | Called when the modal requests to close (ESC key, backdrop click, or close button). |\n| `showCloseButton`      | `boolean`    | `true`  | Render a default `<Modal.CloseButton />` if you don’t provide one yourself.         |\n| `disableBackdropClick` | `boolean`    | `false` | When `true`, clicking the backdrop does **not** trigger `onClose`.                  |\n| _Other props_          | _various_    | —       | Forwarded to the underlying `<dialog>`: `className`, `style`, `id`, `aria-*`, etc.  |\n\n#### Compound Slots\n\nNest these components inside `<Modal>`:\n\n- **`<Modal.Header>`**  \n  Renders a `<header>` container.  \n  _Accepts_: `className`, `style`, and standard HTML props.\n\n- **`<Modal.Body>`**  \n  Renders a `<div>` for main content.  \n  _Accepts_: `className`, `style`, and standard HTML props.\n\n- **`<Modal.Footer>`**  \n  Renders a `<footer>` for action buttons.  \n  _Accepts_: `className`, `style`, and standard HTML props.\n\n- **`<Modal.CloseButton>`**  \n  A `<button>` wired to `onClose`. Default content is “×”, but you can override children.  \n  _Accepts_: `onClick`, `aria-label`, `className`, etc.\n\n- **`<Modal.Overlay>`**  \n  Renders a `<div>` for custom backdrops (unstyled).  \n  _Accepts_: `className`, `style`, and standard HTML props.\n\n> **Note:** Any children not wrapped in a slot will render inside `<Modal.Body>` automatically.\n\n---\n\n## Accessibility\n\n- Uses native `<dialog>` with `role=\"dialog\"` and `aria-modal=\"true\"`.\n- **Focus Management**:\n  - Saves the previously focused element.\n  - Moves focus into the dialog on open.\n  - Restores focus on close.\n- **Keyboard**:\n  - **ESC key** closes the modal.\n  - **Backdrop click** closes the modal (unless `disableBackdropClick` is `true`).\n\n---\n\n## Styling\n\nThis component is **unstyled by design**. Apply your own CSS via `className` or `style`, for example:\n\n```css\n/* Example dialog style */\n#modal dialog {\n  padding: 1.5rem;\n  border: none;\n  border-radius: 0.5rem;\n  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);\n}\n\n/* Example overlay */\n#modal .custom-overlay {\n  position: fixed;\n  inset: 0;\n  background: rgba(0, 0, 0, 0.5);\n}\n```\n\n---\n\n## Usage Patterns & Edge Cases\n\n1. **Orphan children auto-wrap**\n\n   ```jsx\n   <Modal isOpen onClose={...}>\n     <p>This paragraph isn’t wrapped in `<Modal.Body>`.</p>\n   </Modal>\n   // Renders the paragraph inside Modal.Body automatically.\n   ```\n\n2. **Custom Backdrop**\n\n   ```jsx\n   <Modal isOpen onClose={...}>\n     <Modal.Overlay className=\"fixed inset-0 bg-black/50 animate-fadeIn\" />\n     <Modal.Body>…</Modal.Body>\n   </Modal>\n   ```\n\n3. **ARIA & ID props**\n\n   ```jsx\n   <Modal\n     isOpen\n     onClose={...}\n     aria-labelledby=\"confirm-title\"\n     aria-describedby=\"confirm-desc\"\n   >\n     <Modal.Header>\n       <h2 id=\"confirm-title\">Confirm Action</h2>\n     </Modal.Header>\n     <Modal.Body>\n       <p id=\"confirm-desc\">Are you sure you want to proceed?</p>\n     </Modal.Body>\n   </Modal>\n   ```\n\n4. **Scrollable Content**\n\n   ```css\n   .modal-body--scroll {\n     max-height: 60vh;\n     overflow-y: auto;\n   }\n   ```\n\n   ```jsx\n   <Modal isOpen onClose={...}>\n     <Modal.Body className=\"modal-body--scroll\">\n       {/* Long form or list */}\n     </Modal.Body>\n   </Modal>\n   ```\n\n5. **Nested / Stacked Modals**\n\n   - Ensure a single `#modal` portal target—or separate containers—and manage `z-index` in your CSS.\n\n6. **Server-Side Rendering (SSR)**\n   - On SSR, `document.getElementById(\"modal\")` may be `null`; the component returns `null` until hydration.\n\n---\n\n## Building\n\n```bash\ngit clone https://github.com/alexiGrigorov/OCPR13-WealthHealth-Modal.git\ncd OCPR13-WealthHealth-Modal\nnpm install\nnpm run build\n# Output in /dist\n```\n\n---\n\n## Contributing\n\n- **Issues & Discussions:**  \n  https://github.com/alexiGrigorov/OCPR13-WealthHealth-Modal/issues\n- **Pull Requests:** Welcome! Please follow existing code style and add tests where applicable.\n\n---\n\n## License\n\n[ISC](LICENSE)\n","readmeFilename":"README.md","_rev":"1-dd43574a003514ac27da691205d75362"}