{"_id":"dialog-closedby-polyfill","_rev":"6-f5ac0ea37e9975a3e1df136831680e1c","name":"dialog-closedby-polyfill","dist-tags":{"latest":"1.3.0"},"versions":{"1.0.0":{"name":"dialog-closedby-polyfill","version":"1.0.0","keywords":["dialog","closedby","polyfill","html5","web-components"],"author":{"url":"https://www.tak-dcxi.com","name":"Takahiro Arai"},"license":"MIT","_id":"dialog-closedby-polyfill@1.0.0","maintainers":[{"name":"takahiro_arai","email":"tak.a.dcxi@gmail.com"}],"homepage":"https://github.com/tak-dcxi/dialog-closedby-polyfill#readme","bugs":{"url":"https://github.com/tak-dcxi/dialog-closedby-polyfill/issues"},"dist":{"shasum":"72eb17891165960c74fa6479d15cee7532e95e1c","tarball":"https://registry.npmjs.org/dialog-closedby-polyfill/-/dialog-closedby-polyfill-1.0.0.tgz","fileCount":4,"integrity":"sha512-dM6aENrOkdp8jlzo0y14dV1g3HnRPpgGiWYmWCbzLBZB2Nguk4mzCK+4JR8ic1L5zkDeRqAe1d8EO4eOPy7tfw==","signatures":[{"sig":"MEUCIQDXchHM2fDbNiQ4ZmUXRfux30ERihNCyBVWFJ3dmdq85wIgE+GsiyeWdQaV9z4w49O9ttkMBMABTrLjM65mcFzP1Gk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":15433},"main":"index.js","types":"index.d.ts","exports":{".":{"types":"./index.d.ts","import":"./index.js","require":"./index.js"}},"gitHead":"2a7055afa7d4c8445eb795086cedf2e42dea6790","scripts":{"test":"echo \"Open test/index.html in a browser to test\"","build":"esbuild src/index.ts --bundle --format=esm --outfile=index.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"takahiro_arai","email":"tak.a.dcxi@gmail.com"},"repository":{"url":"git+https://github.com/tak-dcxi/dialog-closedby-polyfill.git","type":"git"},"_npmVersion":"10.9.2","description":"Polyfill for the HTMLDialogElement closedBy attribute","directories":{},"_nodeVersion":"23.9.0","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.4","typescript":"^5.0.0","@types/node":"^20.0.0"},"_npmOperationalInternal":{"tmp":"tmp/dialog-closedby-polyfill_1.0.0_1748037348917_0.47713400969421005","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"dialog-closedby-polyfill","version":"1.0.1","keywords":["dialog","closedby","polyfill","html5","web-components"],"author":{"url":"https://www.tak-dcxi.com","name":"Takahiro Arai"},"license":"MIT","_id":"dialog-closedby-polyfill@1.0.1","maintainers":[{"name":"takahiro_arai","email":"tak.a.dcxi@gmail.com"}],"homepage":"https://github.com/tak-dcxi/dialog-closedby-polyfill#readme","bugs":{"url":"https://github.com/tak-dcxi/dialog-closedby-polyfill/issues"},"dist":{"shasum":"741bfceca4e218b244b9ec651f45171a6b2883e5","tarball":"https://registry.npmjs.org/dialog-closedby-polyfill/-/dialog-closedby-polyfill-1.0.1.tgz","fileCount":5,"integrity":"sha512-UnfIXsn8d5SB049VwAziKays5Z755KHQi5DUpI1AilQJyBAQ8GfHC19W7nz7zmkut0larMVwi8tA4+C8ITSZlw==","signatures":[{"sig":"MEYCIQCj6MZPXaMVh4bWMHRnw7arwKewXvk0h+DuUNvHYklIoAIhANnSVa9U16sAgn3hh8okGgx+Nrg1DabkllwhtsOGg1+H","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":16456},"main":"index.js","types":"index.d.ts","exports":{".":{"types":"./index.d.ts","import":"./index.js","require":"./index.js"}},"gitHead":"60316f68bf87216af447bb8bf0353c9373c8c280","scripts":{"build":"esbuild src/index.ts --bundle --format=esm --outfile=index.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"takahiro_arai","email":"tak.a.dcxi@gmail.com"},"repository":{"url":"git+https://github.com/tak-dcxi/dialog-closedby-polyfill.git","type":"git"},"_npmVersion":"10.9.2","description":"Polyfill for the HTMLDialogElement closedBy attribute","directories":{},"_nodeVersion":"23.9.0","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.4","typescript":"^5.0.0","@types/node":"^20.0.0"},"_npmOperationalInternal":{"tmp":"tmp/dialog-closedby-polyfill_1.0.1_1748042879261_0.04174548890684626","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"dialog-closedby-polyfill","version":"1.1.0","keywords":["dialog","closedby","polyfill","html5","web-components"],"author":{"url":"https://www.tak-dcxi.com","name":"Takahiro Arai"},"license":"MIT","_id":"dialog-closedby-polyfill@1.1.0","maintainers":[{"name":"takahiro_arai","email":"tak.a.dcxi@gmail.com"}],"homepage":"https://github.com/tak-dcxi/dialog-closedby-polyfill#readme","bugs":{"url":"https://github.com/tak-dcxi/dialog-closedby-polyfill/issues"},"dist":{"shasum":"38d3e11a5f0abd298a59e9d129cf848d36ed1d47","tarball":"https://registry.npmjs.org/dialog-closedby-polyfill/-/dialog-closedby-polyfill-1.1.0.tgz","fileCount":5,"integrity":"sha512-A/7THz1NUfErs+Dh+4mza2uRaNe4rD5PaXVSetEOTXF9kSwFanmwV0RjHRrojXjxPk54pwxX19njKMq246IIGA==","signatures":[{"sig":"MEUCIAoyFiBaa4iMOGR4rRvArvRb+EwPpvcFXnXwEIHctql9AiEA5dfh8nQCIvUERhFIDtTiLkAwLApdzXveHZzs92A2NLM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17574},"main":"index.js","types":"index.d.ts","exports":{".":{"types":"./index.d.ts","import":"./index.js","require":"./index.js"}},"gitHead":"049b155ff72bf72c286ae3e5b2d4bfd8a5312f3f","scripts":{"build":"esbuild src/index.ts --bundle --format=esm --outfile=index.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"takahiro_arai","email":"tak.a.dcxi@gmail.com"},"repository":{"url":"git+https://github.com/tak-dcxi/dialog-closedby-polyfill.git","type":"git"},"_npmVersion":"10.9.2","description":"Polyfill for the HTMLDialogElement closedBy attribute","directories":{},"_nodeVersion":"23.9.0","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.4","typescript":"^5.0.0","@types/node":"^20.0.0"},"_npmOperationalInternal":{"tmp":"tmp/dialog-closedby-polyfill_1.1.0_1748138637275_0.8560733719631599","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"dialog-closedby-polyfill","version":"1.1.1","keywords":["dialog","closedby","polyfill","html5","web-components"],"author":{"url":"https://www.tak-dcxi.com","name":"Takahiro Arai"},"license":"MIT","_id":"dialog-closedby-polyfill@1.1.1","maintainers":[{"name":"takahiro_arai","email":"tak.a.dcxi@gmail.com"}],"homepage":"https://github.com/tak-dcxi/dialog-closedby-polyfill#readme","bugs":{"url":"https://github.com/tak-dcxi/dialog-closedby-polyfill/issues"},"dist":{"shasum":"9ff29106489eb6098e462cc90b034883fabffb28","tarball":"https://registry.npmjs.org/dialog-closedby-polyfill/-/dialog-closedby-polyfill-1.1.1.tgz","fileCount":5,"integrity":"sha512-oXPL9U5EhT9f6yia9ziZzlOLQDh6hU3CIJD29To69CmWMw1nwi7b6TrY1WBeE8Bd1KdwcLJx626AObFpzLtAlA==","signatures":[{"sig":"MEUCIQDxIwTCROKYTIQxdACHf2OyBEHZfyjoqv2r3jpyhvdyiAIgUj8nrp0cX3xT64Wn59KIlJzYJBvO1kZgRA6pgTFTwBw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":18236},"main":"index.js","types":"index.d.ts","exports":{".":{"types":"./index.d.ts","import":"./index.js","require":"./index.js"}},"gitHead":"0798ad92bd49a537c30f634ffea06bc279fdcd1f","scripts":{"build":"esbuild src/index.ts --bundle --format=esm --outfile=index.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"takahiro_arai","email":"tak.a.dcxi@gmail.com"},"repository":{"url":"git+https://github.com/tak-dcxi/dialog-closedby-polyfill.git","type":"git"},"_npmVersion":"10.9.2","description":"Polyfill for the HTMLDialogElement closedBy attribute","directories":{},"_nodeVersion":"23.9.0","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.4","typescript":"^5.0.0","@types/node":"^20.0.0"},"_npmOperationalInternal":{"tmp":"tmp/dialog-closedby-polyfill_1.1.1_1770711445350_0.3414673389192988","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"dialog-closedby-polyfill","version":"1.2.0","keywords":["dialog","closedby","polyfill","html5","web-components"],"author":{"url":"https://www.tak-dcxi.com","name":"Takahiro Arai"},"license":"MIT","_id":"dialog-closedby-polyfill@1.2.0","maintainers":[{"name":"takahiro_arai","email":"tak.a.dcxi@gmail.com"}],"homepage":"https://github.com/tak-dcxi/dialog-closedby-polyfill#readme","bugs":{"url":"https://github.com/tak-dcxi/dialog-closedby-polyfill/issues"},"dist":{"shasum":"4df6e4c64ec497283a9d6d7ea97f691fcd40ff43","tarball":"https://registry.npmjs.org/dialog-closedby-polyfill/-/dialog-closedby-polyfill-1.2.0.tgz","fileCount":5,"integrity":"sha512-QYqiWCpHQWGv82NgD8e7lJBQrorpRbE7D6i0bIVsurSvwdC0I9S1pNwZZmnwS5DiWseJc8CKPtb6B6DBp4+Waw==","signatures":[{"sig":"MEUCIQDvs9sq2QE0tZgsOJOusI3rE3jA9BOv9aC2kXxDVhkAXwIgEnzgxWcX9eMNXYMui6ZIyhUQdtguFcDRGNEWVsfjsjc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":18236},"main":"index.js","types":"index.d.ts","exports":{".":{"types":"./index.d.ts","import":"./index.js","require":"./index.js"}},"gitHead":"6412b054e2e88413e57d553a788a04fb435ef1e4","scripts":{"build":"esbuild src/index.ts --bundle --format=esm --outfile=index.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"takahiro_arai","email":"tak.a.dcxi@gmail.com"},"repository":{"url":"git+https://github.com/tak-dcxi/dialog-closedby-polyfill.git","type":"git"},"_npmVersion":"10.9.2","description":"Polyfill for the HTMLDialogElement closedBy attribute","directories":{},"_nodeVersion":"23.9.0","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.4","typescript":"^5.0.0","@types/node":"^20.0.0"},"_npmOperationalInternal":{"tmp":"tmp/dialog-closedby-polyfill_1.2.0_1770711571741_0.1189772097261328","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"dialog-closedby-polyfill","version":"1.3.0","description":"Polyfill for the HTMLDialogElement closedBy attribute","main":"index.js","types":"index.d.ts","exports":{".":{"types":"./index.d.ts","import":"./index.js","require":"./index.js"}},"scripts":{"build":"esbuild src/index.ts --bundle --format=esm --outfile=index.js","prepublishOnly":"npm run build"},"keywords":["dialog","closedby","polyfill","html5","web-components"],"author":{"name":"Takahiro Arai","url":"https://www.tak-dcxi.com"},"license":"MIT","devDependencies":{"@types/node":"^20.0.0","esbuild":"^0.25.4","typescript":"^5.0.0"},"repository":{"type":"git","url":"git+https://github.com/tak-dcxi/dialog-closedby-polyfill.git"},"bugs":{"url":"https://github.com/tak-dcxi/dialog-closedby-polyfill/issues"},"homepage":"https://github.com/tak-dcxi/dialog-closedby-polyfill#readme","_id":"dialog-closedby-polyfill@1.3.0","gitHead":"d341e63770ab654307f5995b30a869497f3d96aa","_nodeVersion":"23.9.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-II3pxe/zr5OLhbqrkjQgXDFp61ICPlGZspNIgERwUUCLLHgQzPjv3VTStGD4W+ujwR5zMCZAdcWgu5nTmOIUYQ==","shasum":"9c4cbc7dabac302942a69975788ff08e6084eb69","tarball":"https://registry.npmjs.org/dialog-closedby-polyfill/-/dialog-closedby-polyfill-1.3.0.tgz","fileCount":5,"unpackedSize":21659,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFvJEn2Fvd4CfirEhH6J4hrqBkpwQPuhC/PW4ztYAIQkAiEA/iqWuz2YZs0eoxBj17F9ztqexUZ79VCsbWmybNO0Krw="}]},"_npmUser":{"name":"takahiro_arai","email":"tak.a.dcxi@gmail.com"},"directories":{},"maintainers":[{"name":"takahiro_arai","email":"tak.a.dcxi@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/dialog-closedby-polyfill_1.3.0_1770716359692_0.2962941792744862"},"_hasShrinkwrap":false}},"time":{"created":"2025-05-23T21:55:48.916Z","modified":"2026-02-10T09:39:19.963Z","1.0.0":"2025-05-23T21:55:49.097Z","1.0.1":"2025-05-23T23:27:59.431Z","1.1.0":"2025-05-25T02:03:57.541Z","1.1.1":"2026-02-10T08:17:25.512Z","1.2.0":"2026-02-10T08:19:31.907Z","1.3.0":"2026-02-10T09:39:19.839Z"},"bugs":{"url":"https://github.com/tak-dcxi/dialog-closedby-polyfill/issues"},"author":{"name":"Takahiro Arai","url":"https://www.tak-dcxi.com"},"license":"MIT","homepage":"https://github.com/tak-dcxi/dialog-closedby-polyfill#readme","keywords":["dialog","closedby","polyfill","html5","web-components"],"repository":{"type":"git","url":"git+https://github.com/tak-dcxi/dialog-closedby-polyfill.git"},"description":"Polyfill for the HTMLDialogElement closedBy attribute","maintainers":[{"name":"takahiro_arai","email":"tak.a.dcxi@gmail.com"}],"readme":"# dialog-closedby-polyfill\n\nA polyfill for the HTMLDialogElement `closedby` attribute, providing control over how modal dialogs can be dismissed.\n\n> **Note**: The HTML attribute is `closedby` (lowercase), while the JavaScript property is `closedBy` (camelCase).\n\n## Features\n\n- 🎯 Implements the `closedby` attribute for `<dialog>` elements\n- 🔒 Three closing modes: `any`, `closerequest`, and `none`\n- 🚀 Zero dependencies\n- 📦 TypeScript support included\n- 🌐 Works in all modern browsers with `<dialog>` support\n- ✨ Automatically detects native support\n\n## Installation\n\n```bash\nnpm install dialog-closedby-polyfill\n```\n\n## Usage\n\nThe polyfill is automatically applied when imported:\n\n```javascript\n// ES Modules (auto-applies if needed)\nimport \"dialog-closedby-polyfill\";\n\n// CommonJS (auto-applies if needed)\nrequire(\"dialog-closedby-polyfill\");\n```\n\n### Manual Control\n\nIf you need more control over when the polyfill is applied:\n\n```javascript\nimport { apply, isSupported } from \"dialog-closedby-polyfill\";\n\nif (!isSupported()) {\n  apply();\n}\n```\n\nOr include it via CDN:\n\n```html\n<!-- Polyfill applied automatically -->\n<script\n  type=\"module\"\n  src=\"https://cdn.jsdelivr.net/npm/dialog-closedby-polyfill/index.js\"\n></script>\n\n<!-- polyfill manually -->\n<script type=\"module\">\n  import {\n    isSupported,\n    apply,\n  } from \"https://cdn.jsdelivr.net/npm/dialog-closedby-polyfill/index.js\";\n  if (!isSupported()) apply();\n</script>\n```\n\n## Demo\n\nhttps://tak-dcxi.github.io/github-pages-demo/closedby.html\n\n## How it works\n\nThe `closedby` attribute controls how a modal dialog can be dismissed:\n\n### Closing Behavior Matrix\n\n| `closedby` value | ESC key | Backdrop click | `close()` method |\n| ---------------- | ------- | -------------- | ---------------- |\n| `\"any\"`          | ✅      | ✅             | ✅               |\n| `\"closerequest\"` | ✅      | ❌             | ✅               |\n| `\"none\"`         | ❌      | ❌             | ✅               |\n\n### `closedby=\"any\"` (default)\n\nThe dialog can be closed by:\n\n- Pressing the ESC key\n- Clicking the backdrop\n- Calling the `close()` method\n\n```html\n<dialog\n  id=\"dialog-any\"\n  closedby=\"any\"\n  aria-labelledby=\"dialog-any-title\"\n  autofocus\n>\n  <h1 id=\"dialog-any-title\">any</h1>\n  <p>This dialog can be closed in any way</p>\n  <button type=\"button\" commandfor=\"dialog-any\" command=\"close\">Close</button>\n</dialog>\n```\n\n### `closedby=\"closerequest\"`\n\nThe dialog can be closed by:\n\n- Pressing the ESC key\n- Calling the `close()` method\n- ❌ Clicking the backdrop (disabled)\n\n```html\n<dialog\n  id=\"dialog-closerequest\"\n  closedby=\"closerequest\"\n  aria-labelledby=\"dialog-closerequest-title\"\n  autofocus\n>\n  <h1 id=\"dialog-closerequest-title\">closerequest</h1>\n  <p>This dialog cannot be closed by clicking outside</p>\n  <button type=\"button\" commandfor=\"dialog-closerequest\" command=\"close\">\n    Close\n  </button>\n</dialog>\n```\n\n### `closedby=\"none\"`\n\nThe dialog can only be closed by:\n\n- Calling the `close()` method\n- ❌ Pressing the ESC key (disabled)\n- ❌ Clicking the backdrop (disabled)\n\n```html\n<dialog\n  id=\"dialog-none\"\n  closedby=\"none\"\n  aria-labelledby=\"dialog-none-title\"\n  autofocus\n>\n  <h1 id=\"dialog-none-title\">none</h1>\n  <p>This dialog can only be closed programmatically</p>\n  <button type=\"button\" commandfor=\"dialog-none\" command=\"close\">Close</button>\n</dialog>\n```\n\n## JavaScript API\n\nYou can also set the attribute via JavaScript:\n\n```javascript\nconst dialog = document.querySelector(\"dialog\");\n\n// Using setAttribute\ndialog.setAttribute(\"closedby\", \"none\");\n\n// Using the property (when polyfill is loaded)\ndialog.closedBy = \"closerequest\";\n```\n\n## Dynamic Changes\n\nThe `closedby` attribute can be changed while the dialog is open:\n\n```javascript\nconst dialog = document.querySelector(\"dialog\");\ndialog.showModal();\n\n// Change behavior while dialog is open\nsetTimeout(() => {\n  dialog.closedBy = \"none\"; // Now only closeable via close() method\n}, 3000);\n```\n\n## Browser Support\n\nThis polyfill works in all browsers that support the native `<dialog>` element.\n\n**Native `closedby` support:**\n\n- Chrome 134+\n- Safari: Not implemented yet\n- Firefox: 141+\n- Edge: 134+\n\n**Dialog element support (required for polyfill):**\n\n- Chrome 37+\n- Firefox 98+\n- Safari 15.4+\n- Edge 79+\n\n> **Note**: For browsers without native `closedby` support, this polyfill provides the functionality. For older browsers without `<dialog>` element support, you'll also need a dialog element polyfill.\n\n## API\n\n### Functions\n\n#### `isSupported(): boolean`\n\nCheck if the browser natively supports the `closedby` attribute.\n\n```javascript\nimport { isSupported } from \"dialog-closedby-polyfill\";\n\nif (isSupported()) {\n  console.log(\"Native closedby support available!\");\n}\n```\n\n#### `isPolyfilled(): boolean`\n\nCheck if the polyfill has already been applied.\n\n```javascript\nimport { isPolyfilled } from \"dialog-closedby-polyfill\";\n\nif (isPolyfilled()) {\n  console.log(\"Polyfill has been applied\");\n}\n```\n\n#### `apply(): void`\n\nManually apply the polyfill. This is called automatically when importing the main module.\n\n```javascript\nimport { apply } from \"dialog-closedby-polyfill\";\n\napply(); // Apply the polyfill\n```\n\n#### `teardown(): void`\n\nTears down the polyfill, removing all event listeners and observers. Useful for cleanup in tests or when dynamically unloading the polyfill.\n\n```javascript\nimport { teardown } from \"dialog-closedby-polyfill\";\n\nteardown(); // Remove all listeners and observers\n```\n\n> **Note**: This does NOT restore the original `showModal`, `show`, or `closedBy` implementations on the prototype. It only cleans up observers and listeners.\n\n## TypeScript Support\n\nTypeScript definitions are included. The polyfill extends the `HTMLDialogElement` interface:\n\n```typescript\ninterface HTMLDialogElement {\n  closedBy: \"any\" | \"closerequest\" | \"none\";\n}\n```\n\n## Implementation Details\n\nThe polyfill works by:\n\n1. **Extending HTMLDialogElement**: Adds the `closedBy` property to dialog elements\n1. **Intercepting `showModal()` and `show()`**: Sets up event listeners when a dialog is opened\n1. **Handling Events**:\n   - `keydown` event for ESC key detection\n   - `click` event on the dialog for backdrop clicks\n   - `close` event for cleanup\n1. **Observing Changes**: Uses MutationObserver to watch for `closedby` attribute additions\n1. **Cleanup**: Removes event listeners when dialog is closed\n\n## Differences from Native Implementation\n\nThis polyfill aims to match the native implementation as closely as possible. However, there might be minor differences in edge cases. Please report any discrepancies you find.\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add some amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n## License\n\nMIT License - see the [LICENSE](LICENSE) file for details\n\n## Recommended Polyfills\n\n### Invokers Polyfill\n\nDeclarative `command/commandfor` attributes to provide dialog button operations with markup only.\n\n- **GitHub**: [keithamus/invokers-polyfill](https://github.com/keithamus/invokers-polyfill)\n- **Use case**: Simplifies dialog controls without requiring JavaScript event handlers\n\n```html\n<!-- Works seamlessly with this polyfill -->\n<button type=\"button\" commandfor=\"my-dialog\" command=\"show-modal\">\n  Open Dialog\n</button>\n<dialog\n  id=\"my-dialog\"\n  closedby=\"closerequest\"\n  aria-labelledby=\"my-dialog-heading\"\n  autofocus\n>\n  <h1 id=\"my-dialog-heading\">Heading</h1>\n  <p>Content</p>\n  <button type=\"button\" commandfor=\"my-dialog\" command=\"close\">Close</button>\n</dialog>\n```\n\n## Release Notes\n\n### v1.3.0\n\n- **New**: `teardown()` function to clean up observers and event listeners\n- **New**: Support for modeless dialogs (`show()` method)\n- **New**: Case-insensitive `closedby` attribute handling\n- **Improved**: Internal architecture refactoring\n  - Lazy registration for escape handler\n  - Prevent duplicate observers for the same root\n  - Handle `DOMContentLoaded` for scripts in `<head>`\n\n### v1.2.0\n\n- **Fixed**: Prevent immediate close when reopening dialog after form submission\n  - Added `close` event listener to ensure cleanup regardless of how the dialog was closed\n  - Added `openedAt` timestamp to track when dialog was opened\n  - Use `event.timeStamp` comparison to ignore clicks from before dialog opened\n\n### v1.1.0\n\n- **Fixed**: Using ESC key no longer exits fullscreen mode in Safari/Firefox\n- **Fixed**: Dialog now closes on backdrop click even when `::backdrop` is set to `display: none`\n- **Fixed**: Safari 26.2 false positive detection\n  - Safari 26.2 exposes `closedBy` on `HTMLDialogElement.prototype` but the implementation is incomplete\n  - Changed `isSupported()` to use behavioral test instead of property existence check\n\n### v1.0.0\n\n- Initial release\n- Implements `closedby` attribute polyfill for `<dialog>` elements\n- Three closing modes: `any`, `closerequest`, and `none`\n- TypeScript support included\n\n## Related Links\n\n- [MDN Documentation for closedBy](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/closedBy)\n- [Chrome Platform Status](https://chromestatus.com/feature/5097714453725184)\n- [HTML Specification](https://html.spec.whatwg.org/multipage/interactive-elements.html#the-dialog-element)\n\n## Acknowledgments\n\nThis polyfill is inspired by the native implementation and the work of the web standards community.\n","readmeFilename":"README.md"}