@remyxjs/react 1.0.0-beta → 1.0.4-beta

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.
Files changed (64) hide show
  1. package/dist/{AttachmentModal-D-uxbXvb.cjs → AttachmentModal-BDFFiZJt.cjs} +2 -2
  2. package/dist/{AttachmentModal-D-uxbXvb.cjs.map → AttachmentModal-BDFFiZJt.cjs.map} +1 -1
  3. package/dist/{AttachmentModal--6T-vYJt.js → AttachmentModal-Di5V6QX-.js} +2 -2
  4. package/dist/{AttachmentModal--6T-vYJt.js.map → AttachmentModal-Di5V6QX-.js.map} +1 -1
  5. package/dist/{ContextMenu-B4K3Zbfp.cjs → ContextMenu-BafbP2Uh.cjs} +2 -2
  6. package/dist/{ContextMenu-B4K3Zbfp.cjs.map → ContextMenu-BafbP2Uh.cjs.map} +1 -1
  7. package/dist/{ContextMenu-D8wNSMc3.js → ContextMenu-DsA0YsY7.js} +2 -2
  8. package/dist/{ContextMenu-D8wNSMc3.js.map → ContextMenu-DsA0YsY7.js.map} +1 -1
  9. package/dist/{EmbedModal-Bh2Tcow9.cjs → EmbedModal-C73lODIT.cjs} +2 -2
  10. package/dist/{EmbedModal-Bh2Tcow9.cjs.map → EmbedModal-C73lODIT.cjs.map} +1 -1
  11. package/dist/{EmbedModal-cxE4maD2.js → EmbedModal-alpHQiAP.js} +2 -2
  12. package/dist/{EmbedModal-cxE4maD2.js.map → EmbedModal-alpHQiAP.js.map} +1 -1
  13. package/dist/{ExportModal-Cf1uE4r_.js → ExportModal-BN8LUaSR.js} +2 -2
  14. package/dist/{ExportModal-Cf1uE4r_.js.map → ExportModal-BN8LUaSR.js.map} +1 -1
  15. package/dist/{ExportModal-DwQVsrZE.cjs → ExportModal-Cu-cCwa6.cjs} +2 -2
  16. package/dist/{ExportModal-DwQVsrZE.cjs.map → ExportModal-Cu-cCwa6.cjs.map} +1 -1
  17. package/dist/{FindReplaceModal-Dgt_MrWb.js → FindReplaceModal-BqNcotUr.js} +2 -2
  18. package/dist/{FindReplaceModal-Dgt_MrWb.js.map → FindReplaceModal-BqNcotUr.js.map} +1 -1
  19. package/dist/{FindReplaceModal-DYL_2z8U.cjs → FindReplaceModal-DgysYT04.cjs} +2 -2
  20. package/dist/{FindReplaceModal-DYL_2z8U.cjs.map → FindReplaceModal-DgysYT04.cjs.map} +1 -1
  21. package/dist/{ImageModal-D39ywxqI.cjs → ImageModal-BzgYXY9y.cjs} +2 -2
  22. package/dist/{ImageModal-D39ywxqI.cjs.map → ImageModal-BzgYXY9y.cjs.map} +1 -1
  23. package/dist/{ImageModal-DqScpPrc.js → ImageModal-bCzSSTmd.js} +2 -2
  24. package/dist/{ImageModal-DqScpPrc.js.map → ImageModal-bCzSSTmd.js.map} +1 -1
  25. package/dist/{ImportDocumentModal-BKqMxO3z.js → ImportDocumentModal-BypTEn2i.js} +4 -4
  26. package/dist/{ImportDocumentModal-BKqMxO3z.js.map → ImportDocumentModal-BypTEn2i.js.map} +1 -1
  27. package/dist/{ImportDocumentModal-Bev9hp_J.cjs → ImportDocumentModal-gCFept9p.cjs} +2 -2
  28. package/dist/{ImportDocumentModal-Bev9hp_J.cjs.map → ImportDocumentModal-gCFept9p.cjs.map} +1 -1
  29. package/dist/{LinkModal-k9IeDtAb.js → LinkModal-CmkK4m-k.js} +3 -3
  30. package/dist/{LinkModal-k9IeDtAb.js.map → LinkModal-CmkK4m-k.js.map} +1 -1
  31. package/dist/{LinkModal-B-igSa-g.cjs → LinkModal-DPxg7YCE.cjs} +2 -2
  32. package/dist/{LinkModal-B-igSa-g.cjs.map → LinkModal-DPxg7YCE.cjs.map} +1 -1
  33. package/dist/{MenuBar-DWxJNHmb.js → MenuBar-DOv7JPwR.js} +2 -2
  34. package/dist/{MenuBar-DWxJNHmb.js.map → MenuBar-DOv7JPwR.js.map} +1 -1
  35. package/dist/{MenuBar-B-ZAX9rH.cjs → MenuBar-Lw_5Jp8u.cjs} +2 -2
  36. package/dist/{MenuBar-B-ZAX9rH.cjs.map → MenuBar-Lw_5Jp8u.cjs.map} +1 -1
  37. package/dist/{ModalOverlay-BDsGgv3_.cjs → ModalOverlay-Dh5quv7X.cjs} +2 -2
  38. package/dist/{ModalOverlay-BDsGgv3_.cjs.map → ModalOverlay-Dh5quv7X.cjs.map} +1 -1
  39. package/dist/{ModalOverlay-CLvRNHmp.js → ModalOverlay-Dt0JiW3M.js} +2 -2
  40. package/dist/{ModalOverlay-CLvRNHmp.js.map → ModalOverlay-Dt0JiW3M.js.map} +1 -1
  41. package/dist/{SourceModal-BNI_i4iW.cjs → SourceModal-CHKC5xcv.cjs} +2 -2
  42. package/dist/{SourceModal-BNI_i4iW.cjs.map → SourceModal-CHKC5xcv.cjs.map} +1 -1
  43. package/dist/{SourceModal-MdTGK3Uf.js → SourceModal-ChhNVz7y.js} +2 -2
  44. package/dist/{SourceModal-MdTGK3Uf.js.map → SourceModal-ChhNVz7y.js.map} +1 -1
  45. package/dist/{TablePickerModal-DYODWEA1.js → TablePickerModal-BnZHyMsk.js} +2 -2
  46. package/dist/{TablePickerModal-DYODWEA1.js.map → TablePickerModal-BnZHyMsk.js.map} +1 -1
  47. package/dist/{TablePickerModal-Do1QyoyM.cjs → TablePickerModal-Dr0wUx_h.cjs} +2 -2
  48. package/dist/{TablePickerModal-Do1QyoyM.cjs.map → TablePickerModal-Dr0wUx_h.cjs.map} +1 -1
  49. package/dist/index-Bg_uAWlM.js +3 -0
  50. package/dist/index-Bg_uAWlM.js.map +1 -0
  51. package/dist/index-DL-qBZZU.js +357 -0
  52. package/dist/index-DL-qBZZU.js.map +1 -0
  53. package/dist/index-OfJxpaev.cjs +2 -0
  54. package/dist/index-OfJxpaev.cjs.map +1 -0
  55. package/dist/index-qh1Yzh-l.cjs +2 -0
  56. package/dist/index-qh1Yzh-l.cjs.map +1 -0
  57. package/dist/remyx-react.cjs +1 -1
  58. package/dist/remyx-react.css +1 -1
  59. package/dist/remyx-react.js +1 -1
  60. package/package.json +3 -3
  61. package/dist/index-C720tbJA.js +0 -359
  62. package/dist/index-C720tbJA.js.map +0 -1
  63. package/dist/index-Dc63uIP0.cjs +0 -2
  64. package/dist/index-Dc63uIP0.cjs.map +0 -1
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),a=require("react"),t=require("./index-Dc63uIP0.cjs"),r=require("./ModalOverlay-BDsGgv3_.cjs"),l=/^\s*(javascript|vbscript|data\s*:\s*text\/html)\s*:/i;function s({open:t,onClose:s,engine:n}){const[o,i]=a.useState("url"),[m,d]=a.useState(""),[c,u]=a.useState(""),[p,x]=a.useState(null),[h,b]=a.useState(!1),[j,f]=a.useState(""),y=a.useRef(null),g=!!n?.options?.uploadHandler,N=()=>{s(),d(""),u(""),x(null),b(!1),f(""),i("url")};return e.jsxs(r.ModalOverlay,{title:"Attach File",open:t,onClose:N,children:[e.jsxs("div",{className:"rmx-tabs",children:[e.jsx("button",{type:"button",className:"rmx-tab "+("url"===o?"rmx-active":""),onClick:()=>i("url"),children:"URL"}),e.jsx("button",{type:"button",className:"rmx-tab "+("upload"===o?"rmx-active":""),onClick:()=>i("upload"),children:"Upload"})]}),"upload"===o&&e.jsx("div",{className:"rmx-upload-area",children:g?e.jsxs(e.Fragment,{children:[e.jsx("input",{ref:y,type:"file",onChange:e=>{const a=e.target.files[0];a&&(u(a.name),x(a.size),n.options.uploadHandler&&(b(!0),f(""),n.options.uploadHandler(a).then((e=>{d(e),i("url"),b(!1)})).catch((e=>{f(e.message||"File upload failed. Please try again."),b(!1)}))))},style:{display:"none"}}),e.jsx("button",{type:"button",className:"rmx-btn rmx-btn-upload",onClick:()=>y.current?.click(),disabled:h,children:h?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"rmx-spinner","aria-hidden":"true"})," Uploading…"]}):"Choose File"}),e.jsx("p",{className:"rmx-upload-hint",children:"or drag and drop a file into the editor"})]}):e.jsxs("p",{className:"rmx-upload-hint",children:["File upload is not available. Provide an ",e.jsx("code",{children:"uploadHandler"})," prop to enable uploads, or use the URL tab to link to a file directly."]})}),j&&e.jsx("div",{className:"rmx-form-group rmx-form-error",children:j}),e.jsxs("form",{onSubmit:e=>{if(e.preventDefault(),!m.trim())return;let a;try{a=decodeURIComponent(m.trim())}catch{a=m.trim()}l.test(a)||(n.executeCommand("insertAttachment",{url:m,filename:c||"file",filesize:p}),N())},className:"rmx-modal-form",children:["url"===o&&e.jsxs("div",{className:"rmx-form-group",children:[e.jsx("label",{className:"rmx-form-label",htmlFor:"rmx-attachment-url",children:"File URL"}),e.jsx("input",{id:"rmx-attachment-url",type:"url",className:"rmx-form-input",value:m,onChange:e=>d(e.target.value),placeholder:"https://example.com/document.pdf",required:!0,autoFocus:!0})]}),e.jsxs("div",{className:"rmx-form-group",children:[e.jsx("label",{className:"rmx-form-label",htmlFor:"rmx-attachment-name",children:"Display Name"}),e.jsx("input",{id:"rmx-attachment-name",type:"text",className:"rmx-form-input",value:c,onChange:e=>u(e.target.value),placeholder:"document.pdf"})]}),e.jsxs("div",{className:"rmx-modal-actions",children:[e.jsx("button",{type:"button",className:"rmx-btn",onClick:N,children:"Cancel"}),e.jsx("button",{type:"submit",className:"rmx-btn rmx-btn-primary",disabled:!m.trim()||h,children:h?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"rmx-spinner","aria-hidden":"true"})," Uploading…"]}):"Insert"})]})]})]})}s.propTypes={open:t.PropTypes.bool.isRequired,onClose:t.PropTypes.func.isRequired,engine:t.PropTypes.object},exports.AttachmentModal=s;
2
- //# sourceMappingURL=AttachmentModal-D-uxbXvb.cjs.map
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),a=require("react"),t=require("./index-qh1Yzh-l.cjs"),r=require("./ModalOverlay-Dh5quv7X.cjs"),l=/^\s*(javascript|vbscript|data\s*:\s*text\/html)\s*:/i;function s({open:t,onClose:s,engine:n}){const[o,i]=a.useState("url"),[m,d]=a.useState(""),[c,u]=a.useState(""),[p,x]=a.useState(null),[h,b]=a.useState(!1),[j,f]=a.useState(""),y=a.useRef(null),g=!!n?.options?.uploadHandler,N=()=>{s(),d(""),u(""),x(null),b(!1),f(""),i("url")};return e.jsxs(r.ModalOverlay,{title:"Attach File",open:t,onClose:N,children:[e.jsxs("div",{className:"rmx-tabs",children:[e.jsx("button",{type:"button",className:"rmx-tab "+("url"===o?"rmx-active":""),onClick:()=>i("url"),children:"URL"}),e.jsx("button",{type:"button",className:"rmx-tab "+("upload"===o?"rmx-active":""),onClick:()=>i("upload"),children:"Upload"})]}),"upload"===o&&e.jsx("div",{className:"rmx-upload-area",children:g?e.jsxs(e.Fragment,{children:[e.jsx("input",{ref:y,type:"file",onChange:e=>{const a=e.target.files[0];a&&(u(a.name),x(a.size),n.options.uploadHandler&&(b(!0),f(""),n.options.uploadHandler(a).then((e=>{d(e),i("url"),b(!1)})).catch((e=>{f(e.message||"File upload failed. Please try again."),b(!1)}))))},style:{display:"none"}}),e.jsx("button",{type:"button",className:"rmx-btn rmx-btn-upload",onClick:()=>y.current?.click(),disabled:h,children:h?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"rmx-spinner","aria-hidden":"true"})," Uploading…"]}):"Choose File"}),e.jsx("p",{className:"rmx-upload-hint",children:"or drag and drop a file into the editor"})]}):e.jsxs("p",{className:"rmx-upload-hint",children:["File upload is not available. Provide an ",e.jsx("code",{children:"uploadHandler"})," prop to enable uploads, or use the URL tab to link to a file directly."]})}),j&&e.jsx("div",{className:"rmx-form-group rmx-form-error",children:j}),e.jsxs("form",{onSubmit:e=>{if(e.preventDefault(),!m.trim())return;let a;try{a=decodeURIComponent(m.trim())}catch{a=m.trim()}l.test(a)||(n.executeCommand("insertAttachment",{url:m,filename:c||"file",filesize:p}),N())},className:"rmx-modal-form",children:["url"===o&&e.jsxs("div",{className:"rmx-form-group",children:[e.jsx("label",{className:"rmx-form-label",htmlFor:"rmx-attachment-url",children:"File URL"}),e.jsx("input",{id:"rmx-attachment-url",type:"url",className:"rmx-form-input",value:m,onChange:e=>d(e.target.value),placeholder:"https://example.com/document.pdf",required:!0,autoFocus:!0})]}),e.jsxs("div",{className:"rmx-form-group",children:[e.jsx("label",{className:"rmx-form-label",htmlFor:"rmx-attachment-name",children:"Display Name"}),e.jsx("input",{id:"rmx-attachment-name",type:"text",className:"rmx-form-input",value:c,onChange:e=>u(e.target.value),placeholder:"document.pdf"})]}),e.jsxs("div",{className:"rmx-modal-actions",children:[e.jsx("button",{type:"button",className:"rmx-btn",onClick:N,children:"Cancel"}),e.jsx("button",{type:"submit",className:"rmx-btn rmx-btn-primary",disabled:!m.trim()||h,children:h?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"rmx-spinner","aria-hidden":"true"})," Uploading…"]}):"Insert"})]})]})]})}s.propTypes={open:t.PropTypes.bool.isRequired,onClose:t.PropTypes.func.isRequired,engine:t.PropTypes.object},exports.AttachmentModal=s;
2
+ //# sourceMappingURL=AttachmentModal-BDFFiZJt.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"AttachmentModal-D-uxbXvb.cjs","sources":["../src/components/Modals/AttachmentModal.jsx"],"sourcesContent":["import { useState, useRef } from 'react'\nimport PropTypes from 'prop-types'\nimport { ModalOverlay } from './ModalOverlay.jsx'\n\nconst DANGEROUS_PROTOCOL = /^\\s*(javascript|vbscript|data\\s*:\\s*text\\/html)\\s*:/i\n\nexport function AttachmentModal({ open, onClose, engine }) {\n const [tab, setTab] = useState('url')\n const [url, setUrl] = useState('')\n const [filename, setFilename] = useState('')\n const [filesize, setFilesize] = useState(null)\n const [uploading, setUploading] = useState(false)\n const [error, setError] = useState('')\n const fileInputRef = useRef(null)\n\n const hasUploadHandler = !!engine?.options?.uploadHandler\n\n const handleSubmit = (e) => {\n e.preventDefault()\n if (!url.trim()) return\n // Decode percent-encoding before validation to prevent bypasses like java%73cript:\n let decoded\n try {\n decoded = decodeURIComponent(url.trim())\n } catch {\n decoded = url.trim()\n }\n if (DANGEROUS_PROTOCOL.test(decoded)) return\n engine.executeCommand('insertAttachment', {\n url,\n filename: filename || 'file',\n filesize,\n })\n handleClose()\n }\n\n const handleClose = () => {\n onClose()\n setUrl('')\n setFilename('')\n setFilesize(null)\n setUploading(false)\n setError('')\n setTab('url')\n }\n\n const handleFileChange = (e) => {\n const file = e.target.files[0]\n if (!file) return\n\n setFilename(file.name)\n setFilesize(file.size)\n\n if (engine.options.uploadHandler) {\n setUploading(true)\n setError('')\n engine.options.uploadHandler(file)\n .then((resultUrl) => {\n setUrl(resultUrl)\n setTab('url')\n setUploading(false)\n })\n .catch((err) => {\n console.error('File upload failed:', err)\n setError(err.message || 'File upload failed. Please try again.')\n setUploading(false)\n })\n }\n }\n\n return (\n <ModalOverlay title=\"Attach File\" open={open} onClose={handleClose}>\n <div className=\"rmx-tabs\">\n <button\n type=\"button\"\n className={`rmx-tab ${tab === 'url' ? 'rmx-active' : ''}`}\n onClick={() => setTab('url')}\n >\n URL\n </button>\n <button\n type=\"button\"\n className={`rmx-tab ${tab === 'upload' ? 'rmx-active' : ''}`}\n onClick={() => setTab('upload')}\n >\n Upload\n </button>\n </div>\n\n {tab === 'upload' && (\n <div className=\"rmx-upload-area\">\n {hasUploadHandler ? (\n <>\n <input\n ref={fileInputRef}\n type=\"file\"\n onChange={handleFileChange}\n style={{ display: 'none' }}\n />\n <button\n type=\"button\"\n className=\"rmx-btn rmx-btn-upload\"\n onClick={() => fileInputRef.current?.click()}\n disabled={uploading}\n >\n {uploading ? (\n <>\n <span className=\"rmx-spinner\" aria-hidden=\"true\" />\n {' Uploading\\u2026'}\n </>\n ) : 'Choose File'}\n </button>\n <p className=\"rmx-upload-hint\">or drag and drop a file into the editor</p>\n </>\n ) : (\n <p className=\"rmx-upload-hint\">\n File upload is not available. Provide an <code>uploadHandler</code> prop to enable uploads, or use the URL tab to link to a file directly.\n </p>\n )}\n </div>\n )}\n\n {error && (\n <div className=\"rmx-form-group rmx-form-error\">\n {error}\n </div>\n )}\n\n <form onSubmit={handleSubmit} className=\"rmx-modal-form\">\n {tab === 'url' && (\n <div className=\"rmx-form-group\">\n <label className=\"rmx-form-label\" htmlFor=\"rmx-attachment-url\">File URL</label>\n <input\n id=\"rmx-attachment-url\"\n type=\"url\"\n className=\"rmx-form-input\"\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n placeholder=\"https://example.com/document.pdf\"\n required\n autoFocus\n />\n </div>\n )}\n <div className=\"rmx-form-group\">\n <label className=\"rmx-form-label\" htmlFor=\"rmx-attachment-name\">Display Name</label>\n <input\n id=\"rmx-attachment-name\"\n type=\"text\"\n className=\"rmx-form-input\"\n value={filename}\n onChange={(e) => setFilename(e.target.value)}\n placeholder=\"document.pdf\"\n />\n </div>\n <div className=\"rmx-modal-actions\">\n <button type=\"button\" className=\"rmx-btn\" onClick={handleClose}>Cancel</button>\n <button type=\"submit\" className=\"rmx-btn rmx-btn-primary\" disabled={!url.trim() || uploading}>\n {uploading ? (\n <>\n <span className=\"rmx-spinner\" aria-hidden=\"true\" />\n {' Uploading\\u2026'}\n </>\n ) : 'Insert'}\n </button>\n </div>\n </form>\n </ModalOverlay>\n )\n}\n\nAttachmentModal.propTypes = {\n open: PropTypes.bool.isRequired,\n onClose: PropTypes.func.isRequired,\n engine: PropTypes.object,\n}\n"],"names":["DANGEROUS_PROTOCOL","AttachmentModal","open","onClose","engine","tab","setTab","useState","url","setUrl","filename","setFilename","filesize","setFilesize","uploading","setUploading","error","setError","fileInputRef","useRef","hasUploadHandler","options","uploadHandler","handleClose","ModalOverlay","title","children","jsxs","className","jsx","type","onClick","Fragment","ref","onChange","e","file","target","files","name","size","then","resultUrl","catch","err","message","style","display","current","click","disabled","onSubmit","preventDefault","trim","decoded","decodeURIComponent","test","executeCommand","htmlFor","id","value","placeholder","required","autoFocus","propTypes","PropTypes","bool","isRequired","func","object"],"mappings":"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"}
1
+ {"version":3,"file":"AttachmentModal-BDFFiZJt.cjs","sources":["../src/components/Modals/AttachmentModal.jsx"],"sourcesContent":["import { useState, useRef } from 'react'\nimport PropTypes from 'prop-types'\nimport { ModalOverlay } from './ModalOverlay.jsx'\n\nconst DANGEROUS_PROTOCOL = /^\\s*(javascript|vbscript|data\\s*:\\s*text\\/html)\\s*:/i\n\nexport function AttachmentModal({ open, onClose, engine }) {\n const [tab, setTab] = useState('url')\n const [url, setUrl] = useState('')\n const [filename, setFilename] = useState('')\n const [filesize, setFilesize] = useState(null)\n const [uploading, setUploading] = useState(false)\n const [error, setError] = useState('')\n const fileInputRef = useRef(null)\n\n const hasUploadHandler = !!engine?.options?.uploadHandler\n\n const handleSubmit = (e) => {\n e.preventDefault()\n if (!url.trim()) return\n // Decode percent-encoding before validation to prevent bypasses like java%73cript:\n let decoded\n try {\n decoded = decodeURIComponent(url.trim())\n } catch {\n decoded = url.trim()\n }\n if (DANGEROUS_PROTOCOL.test(decoded)) return\n engine.executeCommand('insertAttachment', {\n url,\n filename: filename || 'file',\n filesize,\n })\n handleClose()\n }\n\n const handleClose = () => {\n onClose()\n setUrl('')\n setFilename('')\n setFilesize(null)\n setUploading(false)\n setError('')\n setTab('url')\n }\n\n const handleFileChange = (e) => {\n const file = e.target.files[0]\n if (!file) return\n\n setFilename(file.name)\n setFilesize(file.size)\n\n if (engine.options.uploadHandler) {\n setUploading(true)\n setError('')\n engine.options.uploadHandler(file)\n .then((resultUrl) => {\n setUrl(resultUrl)\n setTab('url')\n setUploading(false)\n })\n .catch((err) => {\n console.error('File upload failed:', err)\n setError(err.message || 'File upload failed. Please try again.')\n setUploading(false)\n })\n }\n }\n\n return (\n <ModalOverlay title=\"Attach File\" open={open} onClose={handleClose}>\n <div className=\"rmx-tabs\">\n <button\n type=\"button\"\n className={`rmx-tab ${tab === 'url' ? 'rmx-active' : ''}`}\n onClick={() => setTab('url')}\n >\n URL\n </button>\n <button\n type=\"button\"\n className={`rmx-tab ${tab === 'upload' ? 'rmx-active' : ''}`}\n onClick={() => setTab('upload')}\n >\n Upload\n </button>\n </div>\n\n {tab === 'upload' && (\n <div className=\"rmx-upload-area\">\n {hasUploadHandler ? (\n <>\n <input\n ref={fileInputRef}\n type=\"file\"\n onChange={handleFileChange}\n style={{ display: 'none' }}\n />\n <button\n type=\"button\"\n className=\"rmx-btn rmx-btn-upload\"\n onClick={() => fileInputRef.current?.click()}\n disabled={uploading}\n >\n {uploading ? (\n <>\n <span className=\"rmx-spinner\" aria-hidden=\"true\" />\n {' Uploading\\u2026'}\n </>\n ) : 'Choose File'}\n </button>\n <p className=\"rmx-upload-hint\">or drag and drop a file into the editor</p>\n </>\n ) : (\n <p className=\"rmx-upload-hint\">\n File upload is not available. Provide an <code>uploadHandler</code> prop to enable uploads, or use the URL tab to link to a file directly.\n </p>\n )}\n </div>\n )}\n\n {error && (\n <div className=\"rmx-form-group rmx-form-error\">\n {error}\n </div>\n )}\n\n <form onSubmit={handleSubmit} className=\"rmx-modal-form\">\n {tab === 'url' && (\n <div className=\"rmx-form-group\">\n <label className=\"rmx-form-label\" htmlFor=\"rmx-attachment-url\">File URL</label>\n <input\n id=\"rmx-attachment-url\"\n type=\"url\"\n className=\"rmx-form-input\"\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n placeholder=\"https://example.com/document.pdf\"\n required\n autoFocus\n />\n </div>\n )}\n <div className=\"rmx-form-group\">\n <label className=\"rmx-form-label\" htmlFor=\"rmx-attachment-name\">Display Name</label>\n <input\n id=\"rmx-attachment-name\"\n type=\"text\"\n className=\"rmx-form-input\"\n value={filename}\n onChange={(e) => setFilename(e.target.value)}\n placeholder=\"document.pdf\"\n />\n </div>\n <div className=\"rmx-modal-actions\">\n <button type=\"button\" className=\"rmx-btn\" onClick={handleClose}>Cancel</button>\n <button type=\"submit\" className=\"rmx-btn rmx-btn-primary\" disabled={!url.trim() || uploading}>\n {uploading ? (\n <>\n <span className=\"rmx-spinner\" aria-hidden=\"true\" />\n {' Uploading\\u2026'}\n </>\n ) : 'Insert'}\n </button>\n </div>\n </form>\n </ModalOverlay>\n )\n}\n\nAttachmentModal.propTypes = {\n open: PropTypes.bool.isRequired,\n onClose: PropTypes.func.isRequired,\n engine: PropTypes.object,\n}\n"],"names":["DANGEROUS_PROTOCOL","AttachmentModal","open","onClose","engine","tab","setTab","useState","url","setUrl","filename","setFilename","filesize","setFilesize","uploading","setUploading","error","setError","fileInputRef","useRef","hasUploadHandler","options","uploadHandler","handleClose","ModalOverlay","title","children","jsxs","className","jsx","type","onClick","Fragment","ref","onChange","e","file","target","files","name","size","then","resultUrl","catch","err","message","style","display","current","click","disabled","onSubmit","preventDefault","trim","decoded","decodeURIComponent","test","executeCommand","htmlFor","id","value","placeholder","required","autoFocus","propTypes","PropTypes","bool","isRequired","func","object"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import{jsxs as e,jsx as a,Fragment as r}from"react/jsx-runtime";import{useState as l,useRef as t}from"react";import{P as n}from"./index-C720tbJA.js";import{M as o}from"./ModalOverlay-CLvRNHmp.js";const i=/^\s*(javascript|vbscript|data\s*:\s*text\/html)\s*:/i;function m({open:n,onClose:m,engine:s}){const[d,c]=l("url"),[p,u]=l(""),[h,x]=l(""),[b,f]=l(null),[N,v]=l(!1),[y,g]=l(""),C=t(null),F=!!s?.options?.uploadHandler,U=()=>{m(),u(""),x(""),f(null),v(!1),g(""),c("url")};/* @__PURE__ */
1
+ import{jsxs as e,jsx as a,Fragment as r}from"react/jsx-runtime";import{useState as l,useRef as t}from"react";import{P as n}from"./index-DL-qBZZU.js";import{M as o}from"./ModalOverlay-Dt0JiW3M.js";const i=/^\s*(javascript|vbscript|data\s*:\s*text\/html)\s*:/i;function m({open:n,onClose:m,engine:s}){const[d,c]=l("url"),[p,u]=l(""),[h,x]=l(""),[b,f]=l(null),[N,v]=l(!1),[y,g]=l(""),C=t(null),F=!!s?.options?.uploadHandler,U=()=>{m(),u(""),x(""),f(null),v(!1),g(""),c("url")};/* @__PURE__ */
2
2
  return e(o,{title:"Attach File",open:n,onClose:U,children:[
3
3
  /* @__PURE__ */e("div",{className:"rmx-tabs",children:[
4
4
  /* @__PURE__ */a("button",{type:"button",className:"rmx-tab "+("url"===d?"rmx-active":""),onClick:()=>c("url"),children:"URL"}),
@@ -18,4 +18,4 @@ return e(o,{title:"Attach File",open:n,onClose:U,children:[
18
18
  /* @__PURE__ */a("button",{type:"button",className:"rmx-btn",onClick:U,children:"Cancel"}),
19
19
  /* @__PURE__ */a("button",{type:"submit",className:"rmx-btn rmx-btn-primary",disabled:!p.trim()||N,children:N?/* @__PURE__ */e(r,{children:[
20
20
  /* @__PURE__ */a("span",{className:"rmx-spinner","aria-hidden":"true"})," Uploading…"]}):"Insert"})]})]})]})}m.propTypes={open:n.bool.isRequired,onClose:n.func.isRequired,engine:n.object};export{m as AttachmentModal};
21
- //# sourceMappingURL=AttachmentModal--6T-vYJt.js.map
21
+ //# sourceMappingURL=AttachmentModal-Di5V6QX-.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AttachmentModal--6T-vYJt.js","sources":["../src/components/Modals/AttachmentModal.jsx"],"sourcesContent":["import { useState, useRef } from 'react'\nimport PropTypes from 'prop-types'\nimport { ModalOverlay } from './ModalOverlay.jsx'\n\nconst DANGEROUS_PROTOCOL = /^\\s*(javascript|vbscript|data\\s*:\\s*text\\/html)\\s*:/i\n\nexport function AttachmentModal({ open, onClose, engine }) {\n const [tab, setTab] = useState('url')\n const [url, setUrl] = useState('')\n const [filename, setFilename] = useState('')\n const [filesize, setFilesize] = useState(null)\n const [uploading, setUploading] = useState(false)\n const [error, setError] = useState('')\n const fileInputRef = useRef(null)\n\n const hasUploadHandler = !!engine?.options?.uploadHandler\n\n const handleSubmit = (e) => {\n e.preventDefault()\n if (!url.trim()) return\n // Decode percent-encoding before validation to prevent bypasses like java%73cript:\n let decoded\n try {\n decoded = decodeURIComponent(url.trim())\n } catch {\n decoded = url.trim()\n }\n if (DANGEROUS_PROTOCOL.test(decoded)) return\n engine.executeCommand('insertAttachment', {\n url,\n filename: filename || 'file',\n filesize,\n })\n handleClose()\n }\n\n const handleClose = () => {\n onClose()\n setUrl('')\n setFilename('')\n setFilesize(null)\n setUploading(false)\n setError('')\n setTab('url')\n }\n\n const handleFileChange = (e) => {\n const file = e.target.files[0]\n if (!file) return\n\n setFilename(file.name)\n setFilesize(file.size)\n\n if (engine.options.uploadHandler) {\n setUploading(true)\n setError('')\n engine.options.uploadHandler(file)\n .then((resultUrl) => {\n setUrl(resultUrl)\n setTab('url')\n setUploading(false)\n })\n .catch((err) => {\n console.error('File upload failed:', err)\n setError(err.message || 'File upload failed. Please try again.')\n setUploading(false)\n })\n }\n }\n\n return (\n <ModalOverlay title=\"Attach File\" open={open} onClose={handleClose}>\n <div className=\"rmx-tabs\">\n <button\n type=\"button\"\n className={`rmx-tab ${tab === 'url' ? 'rmx-active' : ''}`}\n onClick={() => setTab('url')}\n >\n URL\n </button>\n <button\n type=\"button\"\n className={`rmx-tab ${tab === 'upload' ? 'rmx-active' : ''}`}\n onClick={() => setTab('upload')}\n >\n Upload\n </button>\n </div>\n\n {tab === 'upload' && (\n <div className=\"rmx-upload-area\">\n {hasUploadHandler ? (\n <>\n <input\n ref={fileInputRef}\n type=\"file\"\n onChange={handleFileChange}\n style={{ display: 'none' }}\n />\n <button\n type=\"button\"\n className=\"rmx-btn rmx-btn-upload\"\n onClick={() => fileInputRef.current?.click()}\n disabled={uploading}\n >\n {uploading ? (\n <>\n <span className=\"rmx-spinner\" aria-hidden=\"true\" />\n {' Uploading\\u2026'}\n </>\n ) : 'Choose File'}\n </button>\n <p className=\"rmx-upload-hint\">or drag and drop a file into the editor</p>\n </>\n ) : (\n <p className=\"rmx-upload-hint\">\n File upload is not available. Provide an <code>uploadHandler</code> prop to enable uploads, or use the URL tab to link to a file directly.\n </p>\n )}\n </div>\n )}\n\n {error && (\n <div className=\"rmx-form-group rmx-form-error\">\n {error}\n </div>\n )}\n\n <form onSubmit={handleSubmit} className=\"rmx-modal-form\">\n {tab === 'url' && (\n <div className=\"rmx-form-group\">\n <label className=\"rmx-form-label\" htmlFor=\"rmx-attachment-url\">File URL</label>\n <input\n id=\"rmx-attachment-url\"\n type=\"url\"\n className=\"rmx-form-input\"\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n placeholder=\"https://example.com/document.pdf\"\n required\n autoFocus\n />\n </div>\n )}\n <div className=\"rmx-form-group\">\n <label className=\"rmx-form-label\" htmlFor=\"rmx-attachment-name\">Display Name</label>\n <input\n id=\"rmx-attachment-name\"\n type=\"text\"\n className=\"rmx-form-input\"\n value={filename}\n onChange={(e) => setFilename(e.target.value)}\n placeholder=\"document.pdf\"\n />\n </div>\n <div className=\"rmx-modal-actions\">\n <button type=\"button\" className=\"rmx-btn\" onClick={handleClose}>Cancel</button>\n <button type=\"submit\" className=\"rmx-btn rmx-btn-primary\" disabled={!url.trim() || uploading}>\n {uploading ? (\n <>\n <span className=\"rmx-spinner\" aria-hidden=\"true\" />\n {' Uploading\\u2026'}\n </>\n ) : 'Insert'}\n </button>\n </div>\n </form>\n </ModalOverlay>\n )\n}\n\nAttachmentModal.propTypes = {\n open: PropTypes.bool.isRequired,\n onClose: PropTypes.func.isRequired,\n engine: PropTypes.object,\n}\n"],"names":["DANGEROUS_PROTOCOL","AttachmentModal","open","onClose","engine","tab","setTab","useState","url","setUrl","filename","setFilename","filesize","setFilesize","uploading","setUploading","error","setError","fileInputRef","useRef","hasUploadHandler","options","uploadHandler","handleClose","ModalOverlay","title","children","jsxs","className","jsx","type","onClick","Fragment","ref","onChange","e","file","target","files","name","size","then","resultUrl","catch","err","message","style","display","current","click","disabled","onSubmit","preventDefault","trim","decoded","decodeURIComponent","test","executeCommand","htmlFor","id","value","placeholder","required","autoFocus","propTypes","PropTypes","bool","isRequired","func","object"],"mappings":"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"}
1
+ {"version":3,"file":"AttachmentModal-Di5V6QX-.js","sources":["../src/components/Modals/AttachmentModal.jsx"],"sourcesContent":["import { useState, useRef } from 'react'\nimport PropTypes from 'prop-types'\nimport { ModalOverlay } from './ModalOverlay.jsx'\n\nconst DANGEROUS_PROTOCOL = /^\\s*(javascript|vbscript|data\\s*:\\s*text\\/html)\\s*:/i\n\nexport function AttachmentModal({ open, onClose, engine }) {\n const [tab, setTab] = useState('url')\n const [url, setUrl] = useState('')\n const [filename, setFilename] = useState('')\n const [filesize, setFilesize] = useState(null)\n const [uploading, setUploading] = useState(false)\n const [error, setError] = useState('')\n const fileInputRef = useRef(null)\n\n const hasUploadHandler = !!engine?.options?.uploadHandler\n\n const handleSubmit = (e) => {\n e.preventDefault()\n if (!url.trim()) return\n // Decode percent-encoding before validation to prevent bypasses like java%73cript:\n let decoded\n try {\n decoded = decodeURIComponent(url.trim())\n } catch {\n decoded = url.trim()\n }\n if (DANGEROUS_PROTOCOL.test(decoded)) return\n engine.executeCommand('insertAttachment', {\n url,\n filename: filename || 'file',\n filesize,\n })\n handleClose()\n }\n\n const handleClose = () => {\n onClose()\n setUrl('')\n setFilename('')\n setFilesize(null)\n setUploading(false)\n setError('')\n setTab('url')\n }\n\n const handleFileChange = (e) => {\n const file = e.target.files[0]\n if (!file) return\n\n setFilename(file.name)\n setFilesize(file.size)\n\n if (engine.options.uploadHandler) {\n setUploading(true)\n setError('')\n engine.options.uploadHandler(file)\n .then((resultUrl) => {\n setUrl(resultUrl)\n setTab('url')\n setUploading(false)\n })\n .catch((err) => {\n console.error('File upload failed:', err)\n setError(err.message || 'File upload failed. Please try again.')\n setUploading(false)\n })\n }\n }\n\n return (\n <ModalOverlay title=\"Attach File\" open={open} onClose={handleClose}>\n <div className=\"rmx-tabs\">\n <button\n type=\"button\"\n className={`rmx-tab ${tab === 'url' ? 'rmx-active' : ''}`}\n onClick={() => setTab('url')}\n >\n URL\n </button>\n <button\n type=\"button\"\n className={`rmx-tab ${tab === 'upload' ? 'rmx-active' : ''}`}\n onClick={() => setTab('upload')}\n >\n Upload\n </button>\n </div>\n\n {tab === 'upload' && (\n <div className=\"rmx-upload-area\">\n {hasUploadHandler ? (\n <>\n <input\n ref={fileInputRef}\n type=\"file\"\n onChange={handleFileChange}\n style={{ display: 'none' }}\n />\n <button\n type=\"button\"\n className=\"rmx-btn rmx-btn-upload\"\n onClick={() => fileInputRef.current?.click()}\n disabled={uploading}\n >\n {uploading ? (\n <>\n <span className=\"rmx-spinner\" aria-hidden=\"true\" />\n {' Uploading\\u2026'}\n </>\n ) : 'Choose File'}\n </button>\n <p className=\"rmx-upload-hint\">or drag and drop a file into the editor</p>\n </>\n ) : (\n <p className=\"rmx-upload-hint\">\n File upload is not available. Provide an <code>uploadHandler</code> prop to enable uploads, or use the URL tab to link to a file directly.\n </p>\n )}\n </div>\n )}\n\n {error && (\n <div className=\"rmx-form-group rmx-form-error\">\n {error}\n </div>\n )}\n\n <form onSubmit={handleSubmit} className=\"rmx-modal-form\">\n {tab === 'url' && (\n <div className=\"rmx-form-group\">\n <label className=\"rmx-form-label\" htmlFor=\"rmx-attachment-url\">File URL</label>\n <input\n id=\"rmx-attachment-url\"\n type=\"url\"\n className=\"rmx-form-input\"\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n placeholder=\"https://example.com/document.pdf\"\n required\n autoFocus\n />\n </div>\n )}\n <div className=\"rmx-form-group\">\n <label className=\"rmx-form-label\" htmlFor=\"rmx-attachment-name\">Display Name</label>\n <input\n id=\"rmx-attachment-name\"\n type=\"text\"\n className=\"rmx-form-input\"\n value={filename}\n onChange={(e) => setFilename(e.target.value)}\n placeholder=\"document.pdf\"\n />\n </div>\n <div className=\"rmx-modal-actions\">\n <button type=\"button\" className=\"rmx-btn\" onClick={handleClose}>Cancel</button>\n <button type=\"submit\" className=\"rmx-btn rmx-btn-primary\" disabled={!url.trim() || uploading}>\n {uploading ? (\n <>\n <span className=\"rmx-spinner\" aria-hidden=\"true\" />\n {' Uploading\\u2026'}\n </>\n ) : 'Insert'}\n </button>\n </div>\n </form>\n </ModalOverlay>\n )\n}\n\nAttachmentModal.propTypes = {\n open: PropTypes.bool.isRequired,\n onClose: PropTypes.func.isRequired,\n engine: PropTypes.object,\n}\n"],"names":["DANGEROUS_PROTOCOL","AttachmentModal","open","onClose","engine","tab","setTab","useState","url","setUrl","filename","setFilename","filesize","setFilesize","uploading","setUploading","error","setError","fileInputRef","useRef","hasUploadHandler","options","uploadHandler","handleClose","ModalOverlay","title","children","jsxs","className","jsx","type","onClick","Fragment","ref","onChange","e","file","target","files","name","size","then","resultUrl","catch","err","message","style","display","current","click","disabled","onSubmit","preventDefault","trim","decoded","decodeURIComponent","test","executeCommand","htmlFor","id","value","placeholder","required","autoFocus","propTypes","PropTypes","bool","isRequired","func","object"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("react"),r=require("./index-Dc63uIP0.cjs");const n=t.memo((function({contextMenu:r,onHide:n,onOpenModal:s}){const[o,a]=t.useState(-1),u=t.useRef(null),c=t.useRef([]),i=t.useMemo((()=>r.visible&&r.items?r.items.map(((e,t)=>e.separator?null:t)).filter((e=>null!==e)):[]),[r.visible,r.items]);t.useEffect((()=>{r.visible&&u.current&&(u.current.focus(),a(-1))}),[r.visible]),t.useEffect((()=>{o>=0&&c.current[o]&&c.current[o].focus()}),[o]);const l=t.useCallback((e=>{if("function"==typeof e.command)try{e.command()}catch(t){}else"editLinkModal"===e.command&&s?.("link",{href:e.data?.href,text:e.data?.textContent,target:e.data?.target});n()}),[n,s]),p=t.useCallback((e=>{if(!i.length)return;const t=i.indexOf(o);switch(e.key){case"ArrowDown":{e.preventDefault();const r=t<i.length-1?t+1:0;a(i[r]);break}case"ArrowUp":{e.preventDefault();const r=t>0?t-1:i.length-1;a(i[r]);break}case"Home":e.preventDefault(),a(i[0]);break;case"End":e.preventDefault(),a(i[i.length-1]);break;case"Enter":e.preventDefault(),o>=0&&r.items[o]&&l(r.items[o]);break;case"Escape":case"Tab":e.preventDefault(),n()}}),[i,o,r.items,l,n]);return r.visible?e.jsx("div",{ref:u,className:"rmx-context-menu",style:{top:r.y,left:r.x},role:"menu",tabIndex:-1,onKeyDown:p,children:r.items.map(((t,r)=>t.separator?e.jsx("div",{className:"rmx-context-menu-separator",role:"separator"},r):e.jsx("button",{ref:e=>{c.current[r]=e},className:"rmx-context-menu-item"+(o===r?" rmx-focused":""),onClick:()=>l(t),onMouseEnter:()=>a(r),type:"button",role:"menuitem",tabIndex:-1,children:t.label},r)))}):null}));n.propTypes={contextMenu:r.PropTypes.shape({visible:r.PropTypes.bool,x:r.PropTypes.number,y:r.PropTypes.number,items:r.PropTypes.array}).isRequired,onHide:r.PropTypes.func.isRequired,onOpenModal:r.PropTypes.func},exports.ContextMenu=n;
2
- //# sourceMappingURL=ContextMenu-B4K3Zbfp.cjs.map
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("react"),r=require("./index-qh1Yzh-l.cjs");const n=t.memo((function({contextMenu:r,onHide:n,onOpenModal:s}){const[o,a]=t.useState(-1),u=t.useRef(null),c=t.useRef([]),i=t.useMemo((()=>r.visible&&r.items?r.items.map(((e,t)=>e.separator?null:t)).filter((e=>null!==e)):[]),[r.visible,r.items]);t.useEffect((()=>{r.visible&&u.current&&(u.current.focus(),a(-1))}),[r.visible]),t.useEffect((()=>{o>=0&&c.current[o]&&c.current[o].focus()}),[o]);const l=t.useCallback((e=>{if("function"==typeof e.command)try{e.command()}catch(t){}else"editLinkModal"===e.command&&s?.("link",{href:e.data?.href,text:e.data?.textContent,target:e.data?.target});n()}),[n,s]),p=t.useCallback((e=>{if(!i.length)return;const t=i.indexOf(o);switch(e.key){case"ArrowDown":{e.preventDefault();const r=t<i.length-1?t+1:0;a(i[r]);break}case"ArrowUp":{e.preventDefault();const r=t>0?t-1:i.length-1;a(i[r]);break}case"Home":e.preventDefault(),a(i[0]);break;case"End":e.preventDefault(),a(i[i.length-1]);break;case"Enter":e.preventDefault(),o>=0&&r.items[o]&&l(r.items[o]);break;case"Escape":case"Tab":e.preventDefault(),n()}}),[i,o,r.items,l,n]);return r.visible?e.jsx("div",{ref:u,className:"rmx-context-menu",style:{top:r.y,left:r.x},role:"menu",tabIndex:-1,onKeyDown:p,children:r.items.map(((t,r)=>t.separator?e.jsx("div",{className:"rmx-context-menu-separator",role:"separator"},r):e.jsx("button",{ref:e=>{c.current[r]=e},className:"rmx-context-menu-item"+(o===r?" rmx-focused":""),onClick:()=>l(t),onMouseEnter:()=>a(r),type:"button",role:"menuitem",tabIndex:-1,children:t.label},r)))}):null}));n.propTypes={contextMenu:r.PropTypes.shape({visible:r.PropTypes.bool,x:r.PropTypes.number,y:r.PropTypes.number,items:r.PropTypes.array}).isRequired,onHide:r.PropTypes.func.isRequired,onOpenModal:r.PropTypes.func},exports.ContextMenu=n;
2
+ //# sourceMappingURL=ContextMenu-BafbP2Uh.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMenu-B4K3Zbfp.cjs","sources":["../src/components/ContextMenu/ContextMenu.jsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react'\nimport PropTypes from 'prop-types'\n\nfunction ContextMenuInner({ contextMenu, onHide, onOpenModal }) {\n const [focusedIndex, setFocusedIndex] = useState(-1)\n const menuRef = useRef(null)\n const itemRefs = useRef([])\n\n // Compute actionable (non-separator) item indices\n const actionableIndices = useMemo(() => {\n if (!contextMenu.visible || !contextMenu.items) return []\n return contextMenu.items\n .map((item, i) => (item.separator ? null : i))\n .filter((i) => i !== null)\n }, [contextMenu.visible, contextMenu.items])\n\n // Focus the menu container when it appears\n useEffect(() => {\n if (contextMenu.visible && menuRef.current) {\n menuRef.current.focus()\n setFocusedIndex(-1)\n }\n }, [contextMenu.visible])\n\n // Keep focused item in sync with DOM focus\n useEffect(() => {\n if (focusedIndex >= 0 && itemRefs.current[focusedIndex]) {\n itemRefs.current[focusedIndex].focus()\n }\n }, [focusedIndex])\n\n const executeItem = useCallback((item) => {\n if (typeof item.command === 'function') {\n try {\n item.command()\n } catch (err) {\n console.error('[Remyx] Context menu command failed:', err)\n }\n } else if (item.command === 'editLinkModal') {\n onOpenModal?.('link', {\n href: item.data?.href,\n text: item.data?.textContent,\n target: item.data?.target,\n })\n }\n onHide()\n }, [onHide, onOpenModal])\n\n const handleKeyDown = useCallback((e) => {\n if (!actionableIndices.length) return\n\n const currentPos = actionableIndices.indexOf(focusedIndex)\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const next = currentPos < actionableIndices.length - 1 ? currentPos + 1 : 0\n setFocusedIndex(actionableIndices[next])\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prev = currentPos > 0 ? currentPos - 1 : actionableIndices.length - 1\n setFocusedIndex(actionableIndices[prev])\n break\n }\n case 'Home': {\n e.preventDefault()\n setFocusedIndex(actionableIndices[0])\n break\n }\n case 'End': {\n e.preventDefault()\n setFocusedIndex(actionableIndices[actionableIndices.length - 1])\n break\n }\n case 'Enter': {\n e.preventDefault()\n if (focusedIndex >= 0 && contextMenu.items[focusedIndex]) {\n executeItem(contextMenu.items[focusedIndex])\n }\n break\n }\n case 'Escape': {\n e.preventDefault()\n onHide()\n break\n }\n case 'Tab': {\n e.preventDefault()\n onHide()\n break\n }\n default:\n break\n }\n }, [actionableIndices, focusedIndex, contextMenu.items, executeItem, onHide])\n\n if (!contextMenu.visible) return null\n\n return (\n <div\n ref={menuRef}\n className=\"rmx-context-menu\"\n style={{ top: contextMenu.y, left: contextMenu.x }}\n role=\"menu\"\n tabIndex={-1}\n onKeyDown={handleKeyDown}\n >\n {contextMenu.items.map((item, i) => {\n if (item.separator) {\n return <div key={i} className=\"rmx-context-menu-separator\" role=\"separator\" />\n }\n return (\n <button\n key={i}\n ref={(el) => { itemRefs.current[i] = el }}\n className={`rmx-context-menu-item${focusedIndex === i ? ' rmx-focused' : ''}`}\n onClick={() => executeItem(item)}\n onMouseEnter={() => setFocusedIndex(i)}\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n >\n {item.label}\n </button>\n )\n })}\n </div>\n )\n}\n\nexport const ContextMenu = React.memo(ContextMenuInner)\n\nContextMenu.propTypes = {\n contextMenu: PropTypes.shape({\n visible: PropTypes.bool,\n x: PropTypes.number,\n y: PropTypes.number,\n items: PropTypes.array,\n }).isRequired,\n onHide: PropTypes.func.isRequired,\n onOpenModal: PropTypes.func,\n}\n"],"names":["ContextMenu","React","memo","contextMenu","onHide","onOpenModal","focusedIndex","setFocusedIndex","useState","menuRef","useRef","itemRefs","actionableIndices","useMemo","visible","items","map","item","i","separator","filter","useEffect","current","focus","executeItem","useCallback","command","err","href","data","text","textContent","target","handleKeyDown","e","length","currentPos","indexOf","key","preventDefault","next","prev","jsx","ref","className","style","top","y","left","x","role","tabIndex","onKeyDown","children","el","onClick","onMouseEnter","type","label","propTypes","PropTypes","shape","bool","number","array","isRequired","func"],"mappings":"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"}
1
+ {"version":3,"file":"ContextMenu-BafbP2Uh.cjs","sources":["../src/components/ContextMenu/ContextMenu.jsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react'\nimport PropTypes from 'prop-types'\n\nfunction ContextMenuInner({ contextMenu, onHide, onOpenModal }) {\n const [focusedIndex, setFocusedIndex] = useState(-1)\n const menuRef = useRef(null)\n const itemRefs = useRef([])\n\n // Compute actionable (non-separator) item indices\n const actionableIndices = useMemo(() => {\n if (!contextMenu.visible || !contextMenu.items) return []\n return contextMenu.items\n .map((item, i) => (item.separator ? null : i))\n .filter((i) => i !== null)\n }, [contextMenu.visible, contextMenu.items])\n\n // Focus the menu container when it appears\n useEffect(() => {\n if (contextMenu.visible && menuRef.current) {\n menuRef.current.focus()\n setFocusedIndex(-1)\n }\n }, [contextMenu.visible])\n\n // Keep focused item in sync with DOM focus\n useEffect(() => {\n if (focusedIndex >= 0 && itemRefs.current[focusedIndex]) {\n itemRefs.current[focusedIndex].focus()\n }\n }, [focusedIndex])\n\n const executeItem = useCallback((item) => {\n if (typeof item.command === 'function') {\n try {\n item.command()\n } catch (err) {\n console.error('[Remyx] Context menu command failed:', err)\n }\n } else if (item.command === 'editLinkModal') {\n onOpenModal?.('link', {\n href: item.data?.href,\n text: item.data?.textContent,\n target: item.data?.target,\n })\n }\n onHide()\n }, [onHide, onOpenModal])\n\n const handleKeyDown = useCallback((e) => {\n if (!actionableIndices.length) return\n\n const currentPos = actionableIndices.indexOf(focusedIndex)\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const next = currentPos < actionableIndices.length - 1 ? currentPos + 1 : 0\n setFocusedIndex(actionableIndices[next])\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prev = currentPos > 0 ? currentPos - 1 : actionableIndices.length - 1\n setFocusedIndex(actionableIndices[prev])\n break\n }\n case 'Home': {\n e.preventDefault()\n setFocusedIndex(actionableIndices[0])\n break\n }\n case 'End': {\n e.preventDefault()\n setFocusedIndex(actionableIndices[actionableIndices.length - 1])\n break\n }\n case 'Enter': {\n e.preventDefault()\n if (focusedIndex >= 0 && contextMenu.items[focusedIndex]) {\n executeItem(contextMenu.items[focusedIndex])\n }\n break\n }\n case 'Escape': {\n e.preventDefault()\n onHide()\n break\n }\n case 'Tab': {\n e.preventDefault()\n onHide()\n break\n }\n default:\n break\n }\n }, [actionableIndices, focusedIndex, contextMenu.items, executeItem, onHide])\n\n if (!contextMenu.visible) return null\n\n return (\n <div\n ref={menuRef}\n className=\"rmx-context-menu\"\n style={{ top: contextMenu.y, left: contextMenu.x }}\n role=\"menu\"\n tabIndex={-1}\n onKeyDown={handleKeyDown}\n >\n {contextMenu.items.map((item, i) => {\n if (item.separator) {\n return <div key={i} className=\"rmx-context-menu-separator\" role=\"separator\" />\n }\n return (\n <button\n key={i}\n ref={(el) => { itemRefs.current[i] = el }}\n className={`rmx-context-menu-item${focusedIndex === i ? ' rmx-focused' : ''}`}\n onClick={() => executeItem(item)}\n onMouseEnter={() => setFocusedIndex(i)}\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n >\n {item.label}\n </button>\n )\n })}\n </div>\n )\n}\n\nexport const ContextMenu = React.memo(ContextMenuInner)\n\nContextMenu.propTypes = {\n contextMenu: PropTypes.shape({\n visible: PropTypes.bool,\n x: PropTypes.number,\n y: PropTypes.number,\n items: PropTypes.array,\n }).isRequired,\n onHide: PropTypes.func.isRequired,\n onOpenModal: PropTypes.func,\n}\n"],"names":["ContextMenu","React","memo","contextMenu","onHide","onOpenModal","focusedIndex","setFocusedIndex","useState","menuRef","useRef","itemRefs","actionableIndices","useMemo","visible","items","map","item","i","separator","filter","useEffect","current","focus","executeItem","useCallback","command","err","href","data","text","textContent","target","handleKeyDown","e","length","currentPos","indexOf","key","preventDefault","next","prev","jsx","ref","className","style","top","y","left","x","role","tabIndex","onKeyDown","children","el","onClick","onMouseEnter","type","label","propTypes","PropTypes","shape","bool","number","array","isRequired","func"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{jsx as e}from"react/jsx-runtime";import t,{useState as n,useRef as r,useMemo as a,useEffect as o,useCallback as s}from"react";import{P as i}from"./index-C720tbJA.js";const c=t.memo((function({contextMenu:t,onHide:i,onOpenModal:c}){const[l,m]=n(-1),u=r(null),p=r([]),f=a((()=>t.visible&&t.items?t.items.map(((e,t)=>e.separator?null:t)).filter((e=>null!==e)):[]),[t.visible,t.items]);o((()=>{t.visible&&u.current&&(u.current.focus(),m(-1))}),[t.visible]),o((()=>{l>=0&&p.current[l]&&p.current[l].focus()}),[l]);const d=s((e=>{if("function"==typeof e.command)try{e.command()}catch(t){}else"editLinkModal"===e.command&&c?.("link",{href:e.data?.href,text:e.data?.textContent,target:e.data?.target});i()}),[i,c]),b=s((e=>{if(!f.length)return;const n=f.indexOf(l);switch(e.key){case"ArrowDown":{e.preventDefault();const t=n<f.length-1?n+1:0;m(f[t]);break}case"ArrowUp":{e.preventDefault();const t=n>0?n-1:f.length-1;m(f[t]);break}case"Home":e.preventDefault(),m(f[0]);break;case"End":e.preventDefault(),m(f[f.length-1]);break;case"Enter":e.preventDefault(),l>=0&&t.items[l]&&d(t.items[l]);break;case"Escape":case"Tab":e.preventDefault(),i()}}),[f,l,t.items,d,i]);return t.visible?/* @__PURE__ */e("div",{ref:u,className:"rmx-context-menu",style:{top:t.y,left:t.x},role:"menu",tabIndex:-1,onKeyDown:b,children:t.items.map(((t,n)=>t.separator?/* @__PURE__ */e("div",{className:"rmx-context-menu-separator",role:"separator"},n):/* @__PURE__ */e("button",{ref:e=>{p.current[n]=e},className:"rmx-context-menu-item"+(l===n?" rmx-focused":""),onClick:()=>d(t),onMouseEnter:()=>m(n),type:"button",role:"menuitem",tabIndex:-1,children:t.label},n)))}):null}));c.propTypes={contextMenu:i.shape({visible:i.bool,x:i.number,y:i.number,items:i.array}).isRequired,onHide:i.func.isRequired,onOpenModal:i.func};export{c as ContextMenu};
2
- //# sourceMappingURL=ContextMenu-D8wNSMc3.js.map
1
+ import{jsx as e}from"react/jsx-runtime";import t,{useState as n,useRef as r,useMemo as a,useEffect as o,useCallback as s}from"react";import{P as i}from"./index-DL-qBZZU.js";const c=t.memo((function({contextMenu:t,onHide:i,onOpenModal:c}){const[l,m]=n(-1),u=r(null),p=r([]),f=a((()=>t.visible&&t.items?t.items.map(((e,t)=>e.separator?null:t)).filter((e=>null!==e)):[]),[t.visible,t.items]);o((()=>{t.visible&&u.current&&(u.current.focus(),m(-1))}),[t.visible]),o((()=>{l>=0&&p.current[l]&&p.current[l].focus()}),[l]);const d=s((e=>{if("function"==typeof e.command)try{e.command()}catch(t){}else"editLinkModal"===e.command&&c?.("link",{href:e.data?.href,text:e.data?.textContent,target:e.data?.target});i()}),[i,c]),b=s((e=>{if(!f.length)return;const n=f.indexOf(l);switch(e.key){case"ArrowDown":{e.preventDefault();const t=n<f.length-1?n+1:0;m(f[t]);break}case"ArrowUp":{e.preventDefault();const t=n>0?n-1:f.length-1;m(f[t]);break}case"Home":e.preventDefault(),m(f[0]);break;case"End":e.preventDefault(),m(f[f.length-1]);break;case"Enter":e.preventDefault(),l>=0&&t.items[l]&&d(t.items[l]);break;case"Escape":case"Tab":e.preventDefault(),i()}}),[f,l,t.items,d,i]);return t.visible?/* @__PURE__ */e("div",{ref:u,className:"rmx-context-menu",style:{top:t.y,left:t.x},role:"menu",tabIndex:-1,onKeyDown:b,children:t.items.map(((t,n)=>t.separator?/* @__PURE__ */e("div",{className:"rmx-context-menu-separator",role:"separator"},n):/* @__PURE__ */e("button",{ref:e=>{p.current[n]=e},className:"rmx-context-menu-item"+(l===n?" rmx-focused":""),onClick:()=>d(t),onMouseEnter:()=>m(n),type:"button",role:"menuitem",tabIndex:-1,children:t.label},n)))}):null}));c.propTypes={contextMenu:i.shape({visible:i.bool,x:i.number,y:i.number,items:i.array}).isRequired,onHide:i.func.isRequired,onOpenModal:i.func};export{c as ContextMenu};
2
+ //# sourceMappingURL=ContextMenu-DsA0YsY7.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMenu-D8wNSMc3.js","sources":["../src/components/ContextMenu/ContextMenu.jsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react'\nimport PropTypes from 'prop-types'\n\nfunction ContextMenuInner({ contextMenu, onHide, onOpenModal }) {\n const [focusedIndex, setFocusedIndex] = useState(-1)\n const menuRef = useRef(null)\n const itemRefs = useRef([])\n\n // Compute actionable (non-separator) item indices\n const actionableIndices = useMemo(() => {\n if (!contextMenu.visible || !contextMenu.items) return []\n return contextMenu.items\n .map((item, i) => (item.separator ? null : i))\n .filter((i) => i !== null)\n }, [contextMenu.visible, contextMenu.items])\n\n // Focus the menu container when it appears\n useEffect(() => {\n if (contextMenu.visible && menuRef.current) {\n menuRef.current.focus()\n setFocusedIndex(-1)\n }\n }, [contextMenu.visible])\n\n // Keep focused item in sync with DOM focus\n useEffect(() => {\n if (focusedIndex >= 0 && itemRefs.current[focusedIndex]) {\n itemRefs.current[focusedIndex].focus()\n }\n }, [focusedIndex])\n\n const executeItem = useCallback((item) => {\n if (typeof item.command === 'function') {\n try {\n item.command()\n } catch (err) {\n console.error('[Remyx] Context menu command failed:', err)\n }\n } else if (item.command === 'editLinkModal') {\n onOpenModal?.('link', {\n href: item.data?.href,\n text: item.data?.textContent,\n target: item.data?.target,\n })\n }\n onHide()\n }, [onHide, onOpenModal])\n\n const handleKeyDown = useCallback((e) => {\n if (!actionableIndices.length) return\n\n const currentPos = actionableIndices.indexOf(focusedIndex)\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const next = currentPos < actionableIndices.length - 1 ? currentPos + 1 : 0\n setFocusedIndex(actionableIndices[next])\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prev = currentPos > 0 ? currentPos - 1 : actionableIndices.length - 1\n setFocusedIndex(actionableIndices[prev])\n break\n }\n case 'Home': {\n e.preventDefault()\n setFocusedIndex(actionableIndices[0])\n break\n }\n case 'End': {\n e.preventDefault()\n setFocusedIndex(actionableIndices[actionableIndices.length - 1])\n break\n }\n case 'Enter': {\n e.preventDefault()\n if (focusedIndex >= 0 && contextMenu.items[focusedIndex]) {\n executeItem(contextMenu.items[focusedIndex])\n }\n break\n }\n case 'Escape': {\n e.preventDefault()\n onHide()\n break\n }\n case 'Tab': {\n e.preventDefault()\n onHide()\n break\n }\n default:\n break\n }\n }, [actionableIndices, focusedIndex, contextMenu.items, executeItem, onHide])\n\n if (!contextMenu.visible) return null\n\n return (\n <div\n ref={menuRef}\n className=\"rmx-context-menu\"\n style={{ top: contextMenu.y, left: contextMenu.x }}\n role=\"menu\"\n tabIndex={-1}\n onKeyDown={handleKeyDown}\n >\n {contextMenu.items.map((item, i) => {\n if (item.separator) {\n return <div key={i} className=\"rmx-context-menu-separator\" role=\"separator\" />\n }\n return (\n <button\n key={i}\n ref={(el) => { itemRefs.current[i] = el }}\n className={`rmx-context-menu-item${focusedIndex === i ? ' rmx-focused' : ''}`}\n onClick={() => executeItem(item)}\n onMouseEnter={() => setFocusedIndex(i)}\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n >\n {item.label}\n </button>\n )\n })}\n </div>\n )\n}\n\nexport const ContextMenu = React.memo(ContextMenuInner)\n\nContextMenu.propTypes = {\n contextMenu: PropTypes.shape({\n visible: PropTypes.bool,\n x: PropTypes.number,\n y: PropTypes.number,\n items: PropTypes.array,\n }).isRequired,\n onHide: PropTypes.func.isRequired,\n onOpenModal: PropTypes.func,\n}\n"],"names":["ContextMenu","React","memo","contextMenu","onHide","onOpenModal","focusedIndex","setFocusedIndex","useState","menuRef","useRef","itemRefs","actionableIndices","useMemo","visible","items","map","item","i","separator","filter","useEffect","current","focus","executeItem","useCallback","command","err","href","data","text","textContent","target","handleKeyDown","e","length","currentPos","indexOf","key","preventDefault","next","prev","jsx","ref","className","style","top","y","left","x","role","tabIndex","onKeyDown","children","el","onClick","onMouseEnter","type","label","propTypes","PropTypes","shape","bool","number","array","isRequired","func"],"mappings":"6KAoIO,MAAMA,EAAcC,EAAMC,MAjIjC,UAA0BC,YAAEA,EAAAC,OAAaA,EAAAC,YAAQA,IAC/C,MAAOC,EAAcC,GAAmBC,GAAS,GAC3CC,EAAUC,EAAO,MACjBC,EAAWD,EAAO,IAGlBE,EAAoBC,GAAQ,IAC3BV,EAAYW,SAAYX,EAAYY,MAClCZ,EAAYY,MAChBC,KAAI,CAACC,EAAMC,IAAOD,EAAKE,UAAY,KAAOD,IAC1CE,QAAQF,GAAY,OAANA,IAHsC,IAItD,CAACf,EAAYW,QAASX,EAAYY,QAGrCM,GAAU,KACJlB,EAAYW,SAAWL,EAAQa,UACjCb,EAAQa,QAAQC,QAChBhB,GAAgB,GAClB,GACC,CAACJ,EAAYW,UAGhBO,GAAU,KACJf,GAAgB,GAAKK,EAASW,QAAQhB,IACxCK,EAASW,QAAQhB,GAAciB,OACjC,GACC,CAACjB,IAEJ,MAAMkB,EAAcC,GAAaR,IAC/B,GAA4B,mBAAjBA,EAAKS,QACd,IACET,EAAKS,SACP,OAASC,GAET,KAC0B,kBAAjBV,EAAKS,SACdrB,IAAc,OAAQ,CACpBuB,KAAMX,EAAKY,MAAMD,KACjBE,KAAMb,EAAKY,MAAME,YACjBC,OAAQf,EAAKY,MAAMG,SAGvB5B,GAAA,GACC,CAACA,EAAQC,IAEN4B,EAAgBR,GAAaS,IACjC,IAAKtB,EAAkBuB,OAAQ,OAE/B,MAAMC,EAAaxB,EAAkByB,QAAQ/B,GAE7C,OAAQ4B,EAAEI,KACR,IAAK,YAAa,CAChBJ,EAAEK,iBACF,MAAMC,EAAOJ,EAAaxB,EAAkBuB,OAAS,EAAIC,EAAa,EAAI,EAC1E7B,EAAgBK,EAAkB4B,IAClC,KACF,CACA,IAAK,UAAW,CACdN,EAAEK,iBACF,MAAME,EAAOL,EAAa,EAAIA,EAAa,EAAIxB,EAAkBuB,OAAS,EAC1E5B,EAAgBK,EAAkB6B,IAClC,KACF,CACA,IAAK,OACHP,EAAEK,iBACFhC,EAAgBK,EAAkB,IAClC,MAEF,IAAK,MACHsB,EAAEK,iBACFhC,EAAgBK,EAAkBA,EAAkBuB,OAAS,IAC7D,MAEF,IAAK,QACHD,EAAEK,iBACEjC,GAAgB,GAAKH,EAAYY,MAAMT,IACzCkB,EAAYrB,EAAYY,MAAMT,IAEhC,MAEF,IAAK,SAKL,IAAK,MACH4B,EAAEK,iBACFnC,IAIA,GAEH,CAACQ,EAAmBN,EAAcH,EAAYY,MAAOS,EAAapB,IAErE,OAAKD,EAAYW,uBAGf4B,EAAC,MAAA,CACCC,IAAKlC,EACLmC,UAAU,mBACVC,MAAO,CAAEC,IAAK3C,EAAY4C,EAAGC,KAAM7C,EAAY8C,GAC/CC,KAAK,OACLC,UAAU,EACVC,UAAWnB,EAEVoB,SAAAlD,EAAYY,MAAMC,KAAI,CAACC,EAAMC,IACxBD,EAAKE,2BACC,MAAA,CAAYyB,UAAU,6BAA6BM,KAAK,aAA/ChC,kBAGjBwB,EAAC,SAAA,CAECC,IAAMW,IAAS3C,EAASW,QAAQJ,GAAKoC,CAAA,EACrCV,UAAW,yBAAwBtC,IAAiBY,EAAI,eAAiB,IACzEqC,QAAS,IAAM/B,EAAYP,GAC3BuC,aAAc,IAAMjD,EAAgBW,GACpCuC,KAAK,SACLP,KAAK,WACLC,UAAU,EAETE,SAAApC,EAAKyC,OATDxC,OAjBkB,IAgCnC,IAIAlB,EAAY2D,UAAY,CACtBxD,YAAayD,EAAUC,MAAM,CAC3B/C,QAAS8C,EAAUE,KACnBb,EAAGW,EAAUG,OACbhB,EAAGa,EAAUG,OACbhD,MAAO6C,EAAUI,QAChBC,WACH7D,OAAQwD,EAAUM,KAAKD,WACvB5D,YAAauD,EAAUM"}
1
+ {"version":3,"file":"ContextMenu-DsA0YsY7.js","sources":["../src/components/ContextMenu/ContextMenu.jsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react'\nimport PropTypes from 'prop-types'\n\nfunction ContextMenuInner({ contextMenu, onHide, onOpenModal }) {\n const [focusedIndex, setFocusedIndex] = useState(-1)\n const menuRef = useRef(null)\n const itemRefs = useRef([])\n\n // Compute actionable (non-separator) item indices\n const actionableIndices = useMemo(() => {\n if (!contextMenu.visible || !contextMenu.items) return []\n return contextMenu.items\n .map((item, i) => (item.separator ? null : i))\n .filter((i) => i !== null)\n }, [contextMenu.visible, contextMenu.items])\n\n // Focus the menu container when it appears\n useEffect(() => {\n if (contextMenu.visible && menuRef.current) {\n menuRef.current.focus()\n setFocusedIndex(-1)\n }\n }, [contextMenu.visible])\n\n // Keep focused item in sync with DOM focus\n useEffect(() => {\n if (focusedIndex >= 0 && itemRefs.current[focusedIndex]) {\n itemRefs.current[focusedIndex].focus()\n }\n }, [focusedIndex])\n\n const executeItem = useCallback((item) => {\n if (typeof item.command === 'function') {\n try {\n item.command()\n } catch (err) {\n console.error('[Remyx] Context menu command failed:', err)\n }\n } else if (item.command === 'editLinkModal') {\n onOpenModal?.('link', {\n href: item.data?.href,\n text: item.data?.textContent,\n target: item.data?.target,\n })\n }\n onHide()\n }, [onHide, onOpenModal])\n\n const handleKeyDown = useCallback((e) => {\n if (!actionableIndices.length) return\n\n const currentPos = actionableIndices.indexOf(focusedIndex)\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const next = currentPos < actionableIndices.length - 1 ? currentPos + 1 : 0\n setFocusedIndex(actionableIndices[next])\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prev = currentPos > 0 ? currentPos - 1 : actionableIndices.length - 1\n setFocusedIndex(actionableIndices[prev])\n break\n }\n case 'Home': {\n e.preventDefault()\n setFocusedIndex(actionableIndices[0])\n break\n }\n case 'End': {\n e.preventDefault()\n setFocusedIndex(actionableIndices[actionableIndices.length - 1])\n break\n }\n case 'Enter': {\n e.preventDefault()\n if (focusedIndex >= 0 && contextMenu.items[focusedIndex]) {\n executeItem(contextMenu.items[focusedIndex])\n }\n break\n }\n case 'Escape': {\n e.preventDefault()\n onHide()\n break\n }\n case 'Tab': {\n e.preventDefault()\n onHide()\n break\n }\n default:\n break\n }\n }, [actionableIndices, focusedIndex, contextMenu.items, executeItem, onHide])\n\n if (!contextMenu.visible) return null\n\n return (\n <div\n ref={menuRef}\n className=\"rmx-context-menu\"\n style={{ top: contextMenu.y, left: contextMenu.x }}\n role=\"menu\"\n tabIndex={-1}\n onKeyDown={handleKeyDown}\n >\n {contextMenu.items.map((item, i) => {\n if (item.separator) {\n return <div key={i} className=\"rmx-context-menu-separator\" role=\"separator\" />\n }\n return (\n <button\n key={i}\n ref={(el) => { itemRefs.current[i] = el }}\n className={`rmx-context-menu-item${focusedIndex === i ? ' rmx-focused' : ''}`}\n onClick={() => executeItem(item)}\n onMouseEnter={() => setFocusedIndex(i)}\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n >\n {item.label}\n </button>\n )\n })}\n </div>\n )\n}\n\nexport const ContextMenu = React.memo(ContextMenuInner)\n\nContextMenu.propTypes = {\n contextMenu: PropTypes.shape({\n visible: PropTypes.bool,\n x: PropTypes.number,\n y: PropTypes.number,\n items: PropTypes.array,\n }).isRequired,\n onHide: PropTypes.func.isRequired,\n onOpenModal: PropTypes.func,\n}\n"],"names":["ContextMenu","React","memo","contextMenu","onHide","onOpenModal","focusedIndex","setFocusedIndex","useState","menuRef","useRef","itemRefs","actionableIndices","useMemo","visible","items","map","item","i","separator","filter","useEffect","current","focus","executeItem","useCallback","command","err","href","data","text","textContent","target","handleKeyDown","e","length","currentPos","indexOf","key","preventDefault","next","prev","jsx","ref","className","style","top","y","left","x","role","tabIndex","onKeyDown","children","el","onClick","onMouseEnter","type","label","propTypes","PropTypes","shape","bool","number","array","isRequired","func"],"mappings":"6KAoIO,MAAMA,EAAcC,EAAMC,MAjIjC,UAA0BC,YAAEA,EAAAC,OAAaA,EAAAC,YAAQA,IAC/C,MAAOC,EAAcC,GAAmBC,GAAS,GAC3CC,EAAUC,EAAO,MACjBC,EAAWD,EAAO,IAGlBE,EAAoBC,GAAQ,IAC3BV,EAAYW,SAAYX,EAAYY,MAClCZ,EAAYY,MAChBC,KAAI,CAACC,EAAMC,IAAOD,EAAKE,UAAY,KAAOD,IAC1CE,QAAQF,GAAY,OAANA,IAHsC,IAItD,CAACf,EAAYW,QAASX,EAAYY,QAGrCM,GAAU,KACJlB,EAAYW,SAAWL,EAAQa,UACjCb,EAAQa,QAAQC,QAChBhB,GAAgB,GAClB,GACC,CAACJ,EAAYW,UAGhBO,GAAU,KACJf,GAAgB,GAAKK,EAASW,QAAQhB,IACxCK,EAASW,QAAQhB,GAAciB,OACjC,GACC,CAACjB,IAEJ,MAAMkB,EAAcC,GAAaR,IAC/B,GAA4B,mBAAjBA,EAAKS,QACd,IACET,EAAKS,SACP,OAASC,GAET,KAC0B,kBAAjBV,EAAKS,SACdrB,IAAc,OAAQ,CACpBuB,KAAMX,EAAKY,MAAMD,KACjBE,KAAMb,EAAKY,MAAME,YACjBC,OAAQf,EAAKY,MAAMG,SAGvB5B,GAAA,GACC,CAACA,EAAQC,IAEN4B,EAAgBR,GAAaS,IACjC,IAAKtB,EAAkBuB,OAAQ,OAE/B,MAAMC,EAAaxB,EAAkByB,QAAQ/B,GAE7C,OAAQ4B,EAAEI,KACR,IAAK,YAAa,CAChBJ,EAAEK,iBACF,MAAMC,EAAOJ,EAAaxB,EAAkBuB,OAAS,EAAIC,EAAa,EAAI,EAC1E7B,EAAgBK,EAAkB4B,IAClC,KACF,CACA,IAAK,UAAW,CACdN,EAAEK,iBACF,MAAME,EAAOL,EAAa,EAAIA,EAAa,EAAIxB,EAAkBuB,OAAS,EAC1E5B,EAAgBK,EAAkB6B,IAClC,KACF,CACA,IAAK,OACHP,EAAEK,iBACFhC,EAAgBK,EAAkB,IAClC,MAEF,IAAK,MACHsB,EAAEK,iBACFhC,EAAgBK,EAAkBA,EAAkBuB,OAAS,IAC7D,MAEF,IAAK,QACHD,EAAEK,iBACEjC,GAAgB,GAAKH,EAAYY,MAAMT,IACzCkB,EAAYrB,EAAYY,MAAMT,IAEhC,MAEF,IAAK,SAKL,IAAK,MACH4B,EAAEK,iBACFnC,IAIA,GAEH,CAACQ,EAAmBN,EAAcH,EAAYY,MAAOS,EAAapB,IAErE,OAAKD,EAAYW,uBAGf4B,EAAC,MAAA,CACCC,IAAKlC,EACLmC,UAAU,mBACVC,MAAO,CAAEC,IAAK3C,EAAY4C,EAAGC,KAAM7C,EAAY8C,GAC/CC,KAAK,OACLC,UAAU,EACVC,UAAWnB,EAEVoB,SAAAlD,EAAYY,MAAMC,KAAI,CAACC,EAAMC,IACxBD,EAAKE,2BACC,MAAA,CAAYyB,UAAU,6BAA6BM,KAAK,aAA/ChC,kBAGjBwB,EAAC,SAAA,CAECC,IAAMW,IAAS3C,EAASW,QAAQJ,GAAKoC,CAAA,EACrCV,UAAW,yBAAwBtC,IAAiBY,EAAI,eAAiB,IACzEqC,QAAS,IAAM/B,EAAYP,GAC3BuC,aAAc,IAAMjD,EAAgBW,GACpCuC,KAAK,SACLP,KAAK,WACLC,UAAU,EAETE,SAAApC,EAAKyC,OATDxC,OAjBkB,IAgCnC,IAIAlB,EAAY2D,UAAY,CACtBxD,YAAayD,EAAUC,MAAM,CAC3B/C,QAAS8C,EAAUE,KACnBb,EAAGW,EAAUG,OACbhB,EAAGa,EAAUG,OACbhD,MAAO6C,EAAUI,QAChBC,WACH7D,OAAQwD,EAAUM,KAAKD,WACvB5D,YAAauD,EAAUM"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("react"),r=require("./index-Dc63uIP0.cjs"),o=require("./ModalOverlay-BDsGgv3_.cjs"),i=/^\s*(javascript|vbscript|data\s*:\s*text\/html)\s*:/i,a=[{pattern:/(?:youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]+)/,toEmbed:e=>`https://www.youtube.com/embed/${e}`},{pattern:/vimeo\.com\/(\d+)/,toEmbed:e=>`https://player.vimeo.com/video/${e}`},{pattern:/dailymotion\.com\/video\/([a-zA-Z0-9]+)/,toEmbed:e=>`https://www.dailymotion.com/embed/video/${e}`}];function l({open:r,onClose:l,engine:s}){const[n,m]=t.useState(""),[c,d]=t.useState(null),[u,p]=t.useState(!1),b=t.useRef(null);t.useEffect((()=>{if(b.current&&clearTimeout(b.current),n.trim())return b.current=setTimeout((()=>{d(function(e){if(!e)return null;for(const t of a){const r=e.match(t.pattern);if(r)return t.toEmbed(r[1])}return null}(n.trim())),p(!1)}),500),()=>clearTimeout(b.current);d(null)}),[n]),t.useEffect((()=>{r||(m(""),d(null))}),[r]);return e.jsx(o.ModalOverlay,{title:"Embed Media",open:r,onClose:l,children:e.jsxs("form",{onSubmit:e=>{if(e.preventDefault(),!n.trim())return;let t;try{t=decodeURIComponent(n.trim())}catch{t=n.trim()}i.test(t)||(s.executeCommand("embedMedia",{url:n}),l(),m(""))},className:"rmx-modal-form",children:[e.jsxs("div",{className:"rmx-form-group",children:[e.jsx("label",{className:"rmx-form-label",htmlFor:"rmx-embed-url",children:"Video URL"}),e.jsx("input",{id:"rmx-embed-url",type:"url",className:"rmx-form-input",value:n,onChange:e=>m(e.target.value),placeholder:"https://www.youtube.com/watch?v=...",required:!0,autoFocus:!0})]}),e.jsx("p",{className:"rmx-form-hint",children:"Supports YouTube, Vimeo, and Dailymotion URLs"}),n.trim()&&e.jsx("div",{className:"rmx-embed-preview",children:c?e.jsxs("div",{className:"rmx-embed-loading-container",children:[!u&&e.jsx("div",{className:"rmx-embed-loading-text",children:"Loading preview..."}),e.jsx("iframe",{src:c,title:"Embed preview",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowFullScreen:!0,sandbox:"allow-scripts allow-same-origin allow-presentation",onLoad:()=>p(!0)})]}):e.jsx("div",{className:"rmx-embed-preview-placeholder",children:"Enter a valid YouTube, Vimeo, or Dailymotion URL to see a preview"})}),e.jsxs("div",{className:"rmx-modal-actions",children:[e.jsx("button",{type:"button",className:"rmx-btn",onClick:l,children:"Cancel"}),e.jsx("button",{type:"submit",className:"rmx-btn rmx-btn-primary",disabled:!n.trim(),children:"Embed"})]})]})})}l.propTypes={open:r.PropTypes.bool.isRequired,onClose:r.PropTypes.func.isRequired,engine:r.PropTypes.object},exports.EmbedModal=l;
2
- //# sourceMappingURL=EmbedModal-Bh2Tcow9.cjs.map
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("react"),r=require("./index-qh1Yzh-l.cjs"),o=require("./ModalOverlay-Dh5quv7X.cjs"),i=/^\s*(javascript|vbscript|data\s*:\s*text\/html)\s*:/i,a=[{pattern:/(?:youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]+)/,toEmbed:e=>`https://www.youtube.com/embed/${e}`},{pattern:/vimeo\.com\/(\d+)/,toEmbed:e=>`https://player.vimeo.com/video/${e}`},{pattern:/dailymotion\.com\/video\/([a-zA-Z0-9]+)/,toEmbed:e=>`https://www.dailymotion.com/embed/video/${e}`}];function l({open:r,onClose:l,engine:s}){const[n,m]=t.useState(""),[c,d]=t.useState(null),[u,p]=t.useState(!1),b=t.useRef(null);t.useEffect((()=>{if(b.current&&clearTimeout(b.current),n.trim())return b.current=setTimeout((()=>{d(function(e){if(!e)return null;for(const t of a){const r=e.match(t.pattern);if(r)return t.toEmbed(r[1])}return null}(n.trim())),p(!1)}),500),()=>clearTimeout(b.current);d(null)}),[n]),t.useEffect((()=>{r||(m(""),d(null))}),[r]);return e.jsx(o.ModalOverlay,{title:"Embed Media",open:r,onClose:l,children:e.jsxs("form",{onSubmit:e=>{if(e.preventDefault(),!n.trim())return;let t;try{t=decodeURIComponent(n.trim())}catch{t=n.trim()}i.test(t)||(s.executeCommand("embedMedia",{url:n}),l(),m(""))},className:"rmx-modal-form",children:[e.jsxs("div",{className:"rmx-form-group",children:[e.jsx("label",{className:"rmx-form-label",htmlFor:"rmx-embed-url",children:"Video URL"}),e.jsx("input",{id:"rmx-embed-url",type:"url",className:"rmx-form-input",value:n,onChange:e=>m(e.target.value),placeholder:"https://www.youtube.com/watch?v=...",required:!0,autoFocus:!0})]}),e.jsx("p",{className:"rmx-form-hint",children:"Supports YouTube, Vimeo, and Dailymotion URLs"}),n.trim()&&e.jsx("div",{className:"rmx-embed-preview",children:c?e.jsxs("div",{className:"rmx-embed-loading-container",children:[!u&&e.jsx("div",{className:"rmx-embed-loading-text",children:"Loading preview..."}),e.jsx("iframe",{src:c,title:"Embed preview",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowFullScreen:!0,sandbox:"allow-scripts allow-same-origin allow-presentation",onLoad:()=>p(!0)})]}):e.jsx("div",{className:"rmx-embed-preview-placeholder",children:"Enter a valid YouTube, Vimeo, or Dailymotion URL to see a preview"})}),e.jsxs("div",{className:"rmx-modal-actions",children:[e.jsx("button",{type:"button",className:"rmx-btn",onClick:l,children:"Cancel"}),e.jsx("button",{type:"submit",className:"rmx-btn rmx-btn-primary",disabled:!n.trim(),children:"Embed"})]})]})})}l.propTypes={open:r.PropTypes.bool.isRequired,onClose:r.PropTypes.func.isRequired,engine:r.PropTypes.object},exports.EmbedModal=l;
2
+ //# sourceMappingURL=EmbedModal-C73lODIT.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"EmbedModal-Bh2Tcow9.cjs","sources":["../src/components/Modals/EmbedModal.jsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react'\nimport PropTypes from 'prop-types'\nimport { ModalOverlay } from './ModalOverlay.jsx'\n\nconst DANGEROUS_PROTOCOL = /^\\s*(javascript|vbscript|data\\s*:\\s*text\\/html)\\s*:/i\n\nconst ALLOWED_EMBED_DOMAINS = [\n { pattern: /(?:youtube\\.com\\/watch\\?v=|youtu\\.be\\/)([a-zA-Z0-9_-]+)/, toEmbed: (id) => `https://www.youtube.com/embed/${id}` },\n { pattern: /vimeo\\.com\\/(\\d+)/, toEmbed: (id) => `https://player.vimeo.com/video/${id}` },\n { pattern: /dailymotion\\.com\\/video\\/([a-zA-Z0-9]+)/, toEmbed: (id) => `https://www.dailymotion.com/embed/video/${id}` },\n]\n\nfunction getEmbedUrl(url) {\n if (!url) return null\n for (const domain of ALLOWED_EMBED_DOMAINS) {\n const match = url.match(domain.pattern)\n if (match) return domain.toEmbed(match[1])\n }\n return null\n}\n\nexport function EmbedModal({ open, onClose, engine }) {\n const [url, setUrl] = useState('')\n const [previewUrl, setPreviewUrl] = useState(null)\n const [iframeLoaded, setIframeLoaded] = useState(false)\n const debounceRef = useRef(null)\n\n // Debounce the preview URL update\n useEffect(() => {\n if (debounceRef.current) clearTimeout(debounceRef.current)\n if (!url.trim()) {\n setPreviewUrl(null)\n return\n }\n debounceRef.current = setTimeout(() => {\n setPreviewUrl(getEmbedUrl(url.trim()))\n setIframeLoaded(false)\n }, 500)\n return () => clearTimeout(debounceRef.current)\n }, [url])\n\n // Reset state when modal closes\n useEffect(() => {\n if (!open) {\n setUrl('')\n setPreviewUrl(null)\n }\n }, [open])\n\n const handleSubmit = (e) => {\n e.preventDefault()\n if (!url.trim()) return\n // Decode percent-encoding before validation to prevent bypasses like java%73cript:\n let decoded\n try {\n decoded = decodeURIComponent(url.trim())\n } catch {\n decoded = url.trim()\n }\n if (DANGEROUS_PROTOCOL.test(decoded)) return\n engine.executeCommand('embedMedia', { url })\n onClose()\n setUrl('')\n }\n\n return (\n <ModalOverlay title=\"Embed Media\" open={open} onClose={onClose}>\n <form onSubmit={handleSubmit} className=\"rmx-modal-form\">\n <div className=\"rmx-form-group\">\n <label className=\"rmx-form-label\" htmlFor=\"rmx-embed-url\">Video URL</label>\n <input\n id=\"rmx-embed-url\"\n type=\"url\"\n className=\"rmx-form-input\"\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n placeholder=\"https://www.youtube.com/watch?v=...\"\n required\n autoFocus\n />\n </div>\n <p className=\"rmx-form-hint\">Supports YouTube, Vimeo, and Dailymotion URLs</p>\n\n {url.trim() && (\n <div className=\"rmx-embed-preview\">\n {previewUrl ? (\n <div className=\"rmx-embed-loading-container\">\n {!iframeLoaded && <div className=\"rmx-embed-loading-text\">Loading preview...</div>}\n <iframe\n src={previewUrl}\n title=\"Embed preview\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n allowFullScreen\n sandbox=\"allow-scripts allow-same-origin allow-presentation\"\n onLoad={() => setIframeLoaded(true)}\n />\n </div>\n ) : (\n <div className=\"rmx-embed-preview-placeholder\">\n Enter a valid YouTube, Vimeo, or Dailymotion URL to see a preview\n </div>\n )}\n </div>\n )}\n\n <div className=\"rmx-modal-actions\">\n <button type=\"button\" className=\"rmx-btn\" onClick={onClose}>Cancel</button>\n <button type=\"submit\" className=\"rmx-btn rmx-btn-primary\" disabled={!url.trim()}>Embed</button>\n </div>\n </form>\n </ModalOverlay>\n )\n}\n\nEmbedModal.propTypes = {\n open: PropTypes.bool.isRequired,\n onClose: PropTypes.func.isRequired,\n engine: PropTypes.object,\n}\n"],"names":["DANGEROUS_PROTOCOL","ALLOWED_EMBED_DOMAINS","pattern","toEmbed","id","EmbedModal","open","onClose","engine","url","setUrl","useState","previewUrl","setPreviewUrl","iframeLoaded","setIframeLoaded","debounceRef","useRef","useEffect","current","clearTimeout","trim","setTimeout","domain","match","getEmbedUrl","jsx","ModalOverlay","title","children","jsxs","onSubmit","e","preventDefault","decoded","decodeURIComponent","test","executeCommand","className","htmlFor","type","value","onChange","target","placeholder","required","autoFocus","src","allow","allowFullScreen","sandbox","onLoad","onClick","disabled","propTypes","PropTypes","bool","isRequired","func","object"],"mappings":"mNAIMA,EAAqB,uDAErBC,EAAwB,CAC5B,CAAEC,QAAS,0DAA2DC,QAAUC,GAAO,iCAAiCA,KACxH,CAAEF,QAAS,oBAAqBC,QAAUC,GAAO,kCAAkCA,KACnF,CAAEF,QAAS,0CAA2CC,QAAUC,GAAO,2CAA2CA,MAY7G,SAASC,GAAWC,KAAEA,EAAAC,QAAMA,EAAAC,OAASA,IAC1C,MAAOC,EAAKC,GAAUC,EAAAA,SAAS,KACxBC,EAAYC,GAAiBF,EAAAA,SAAS,OACtCG,EAAcC,GAAmBJ,EAAAA,UAAS,GAC3CK,EAAcC,EAAAA,OAAO,MAG3BC,EAAAA,WAAU,KAER,GADIF,EAAYG,SAASC,aAAaJ,EAAYG,SAC7CV,EAAIY,OAQT,OAJAL,EAAYG,QAAUG,YAAW,KAC/BT,EAvBN,SAAqBJ,GACnB,IAAKA,EAAK,OAAO,KACjB,IAAA,MAAWc,KAAUtB,EAAuB,CAC1C,MAAMuB,EAAQf,EAAIe,MAAMD,EAAOrB,SAC/B,GAAIsB,EAAO,OAAOD,EAAOpB,QAAQqB,EAAM,GACzC,CACA,OAAO,IACT,CAgBoBC,CAAYhB,EAAIY,SAC9BN,GAAgB,EAAK,GACpB,KACI,IAAMK,aAAaJ,EAAYG,SAPpCN,EAAc,KAO6B,GAC5C,CAACJ,IAGJS,EAAAA,WAAU,KACHZ,IACHI,EAAO,IACPG,EAAc,MAChB,GACC,CAACP,IAkBJ,SACEoB,IAACC,EAAAA,aAAA,CAAaC,MAAM,cAActB,OAAYC,UAC5CsB,SAAAC,EAAAA,KAAC,OAAA,CAAKC,SAlBYC,IAEpB,GADAA,EAAEC,kBACGxB,EAAIY,OAAQ,OAEjB,IAAIa,EACJ,IACEA,EAAUC,mBAAmB1B,EAAIY,OACnC,CAAA,MACEa,EAAUzB,EAAIY,MAChB,CACIrB,EAAmBoC,KAAKF,KAC5B1B,EAAO6B,eAAe,aAAc,CAAE5B,QACtCF,IACAG,EAAO,IAAE,EAKuB4B,UAAU,iBACtCT,SAAA,GAAAC,KAAC,MAAA,CAAIQ,UAAU,iBACbT,SAAA,CAAAH,MAAC,QAAA,CAAMY,UAAU,iBAAiBC,QAAQ,gBAAgBV,SAAA,cAC1DH,EAAAA,IAAC,QAAA,CACCtB,GAAG,gBACHoC,KAAK,MACLF,UAAU,iBACVG,MAAOhC,EACPiC,SAAWV,GAAMtB,EAAOsB,EAAEW,OAAOF,OACjCG,YAAY,sCACZC,UAAQ,EACRC,WAAS,OAGbpB,EAAAA,IAAC,IAAA,CAAEY,UAAU,gBAAgBT,SAAA,kDAE5BpB,EAAIY,QACHK,EAAAA,IAAC,MAAA,CAAIY,UAAU,oBACZT,SAAAjB,EACCkB,EAAAA,KAAC,MAAA,CAAIQ,UAAU,8BACZT,SAAA,EAACf,GAAgBY,EAAAA,IAAC,MAAA,CAAIY,UAAU,yBAAyBT,SAAA,uBAC1DH,EAAAA,IAAC,SAAA,CACCqB,IAAKnC,EACLgB,MAAM,gBACNoB,MAAM,2FACNC,iBAAe,EACfC,QAAQ,qDACRC,OAAQ,IAAMpC,GAAgB,QAIlCW,MAAC,MAAA,CAAIY,UAAU,gCAAgCT,mFAOrDC,KAAC,MAAA,CAAIQ,UAAU,oBACbT,SAAA,CAAAH,EAAAA,IAAC,UAAOc,KAAK,SAASF,UAAU,UAAUc,QAAS7C,EAASsB,SAAA,WAC5DH,EAAAA,IAAC,SAAA,CAAOc,KAAK,SAASF,UAAU,0BAA0Be,UAAW5C,EAAIY,OAAQQ,SAAA,iBAK3F,CAEAxB,EAAWiD,UAAY,CACrBhD,KAAMiD,EAAAA,UAAUC,KAAKC,WACrBlD,QAASgD,EAAAA,UAAUG,KAAKD,WACxBjD,OAAQ+C,EAAAA,UAAUI"}
1
+ {"version":3,"file":"EmbedModal-C73lODIT.cjs","sources":["../src/components/Modals/EmbedModal.jsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react'\nimport PropTypes from 'prop-types'\nimport { ModalOverlay } from './ModalOverlay.jsx'\n\nconst DANGEROUS_PROTOCOL = /^\\s*(javascript|vbscript|data\\s*:\\s*text\\/html)\\s*:/i\n\nconst ALLOWED_EMBED_DOMAINS = [\n { pattern: /(?:youtube\\.com\\/watch\\?v=|youtu\\.be\\/)([a-zA-Z0-9_-]+)/, toEmbed: (id) => `https://www.youtube.com/embed/${id}` },\n { pattern: /vimeo\\.com\\/(\\d+)/, toEmbed: (id) => `https://player.vimeo.com/video/${id}` },\n { pattern: /dailymotion\\.com\\/video\\/([a-zA-Z0-9]+)/, toEmbed: (id) => `https://www.dailymotion.com/embed/video/${id}` },\n]\n\nfunction getEmbedUrl(url) {\n if (!url) return null\n for (const domain of ALLOWED_EMBED_DOMAINS) {\n const match = url.match(domain.pattern)\n if (match) return domain.toEmbed(match[1])\n }\n return null\n}\n\nexport function EmbedModal({ open, onClose, engine }) {\n const [url, setUrl] = useState('')\n const [previewUrl, setPreviewUrl] = useState(null)\n const [iframeLoaded, setIframeLoaded] = useState(false)\n const debounceRef = useRef(null)\n\n // Debounce the preview URL update\n useEffect(() => {\n if (debounceRef.current) clearTimeout(debounceRef.current)\n if (!url.trim()) {\n setPreviewUrl(null)\n return\n }\n debounceRef.current = setTimeout(() => {\n setPreviewUrl(getEmbedUrl(url.trim()))\n setIframeLoaded(false)\n }, 500)\n return () => clearTimeout(debounceRef.current)\n }, [url])\n\n // Reset state when modal closes\n useEffect(() => {\n if (!open) {\n setUrl('')\n setPreviewUrl(null)\n }\n }, [open])\n\n const handleSubmit = (e) => {\n e.preventDefault()\n if (!url.trim()) return\n // Decode percent-encoding before validation to prevent bypasses like java%73cript:\n let decoded\n try {\n decoded = decodeURIComponent(url.trim())\n } catch {\n decoded = url.trim()\n }\n if (DANGEROUS_PROTOCOL.test(decoded)) return\n engine.executeCommand('embedMedia', { url })\n onClose()\n setUrl('')\n }\n\n return (\n <ModalOverlay title=\"Embed Media\" open={open} onClose={onClose}>\n <form onSubmit={handleSubmit} className=\"rmx-modal-form\">\n <div className=\"rmx-form-group\">\n <label className=\"rmx-form-label\" htmlFor=\"rmx-embed-url\">Video URL</label>\n <input\n id=\"rmx-embed-url\"\n type=\"url\"\n className=\"rmx-form-input\"\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n placeholder=\"https://www.youtube.com/watch?v=...\"\n required\n autoFocus\n />\n </div>\n <p className=\"rmx-form-hint\">Supports YouTube, Vimeo, and Dailymotion URLs</p>\n\n {url.trim() && (\n <div className=\"rmx-embed-preview\">\n {previewUrl ? (\n <div className=\"rmx-embed-loading-container\">\n {!iframeLoaded && <div className=\"rmx-embed-loading-text\">Loading preview...</div>}\n <iframe\n src={previewUrl}\n title=\"Embed preview\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n allowFullScreen\n sandbox=\"allow-scripts allow-same-origin allow-presentation\"\n onLoad={() => setIframeLoaded(true)}\n />\n </div>\n ) : (\n <div className=\"rmx-embed-preview-placeholder\">\n Enter a valid YouTube, Vimeo, or Dailymotion URL to see a preview\n </div>\n )}\n </div>\n )}\n\n <div className=\"rmx-modal-actions\">\n <button type=\"button\" className=\"rmx-btn\" onClick={onClose}>Cancel</button>\n <button type=\"submit\" className=\"rmx-btn rmx-btn-primary\" disabled={!url.trim()}>Embed</button>\n </div>\n </form>\n </ModalOverlay>\n )\n}\n\nEmbedModal.propTypes = {\n open: PropTypes.bool.isRequired,\n onClose: PropTypes.func.isRequired,\n engine: PropTypes.object,\n}\n"],"names":["DANGEROUS_PROTOCOL","ALLOWED_EMBED_DOMAINS","pattern","toEmbed","id","EmbedModal","open","onClose","engine","url","setUrl","useState","previewUrl","setPreviewUrl","iframeLoaded","setIframeLoaded","debounceRef","useRef","useEffect","current","clearTimeout","trim","setTimeout","domain","match","getEmbedUrl","jsx","ModalOverlay","title","children","jsxs","onSubmit","e","preventDefault","decoded","decodeURIComponent","test","executeCommand","className","htmlFor","type","value","onChange","target","placeholder","required","autoFocus","src","allow","allowFullScreen","sandbox","onLoad","onClick","disabled","propTypes","PropTypes","bool","isRequired","func","object"],"mappings":"mNAIMA,EAAqB,uDAErBC,EAAwB,CAC5B,CAAEC,QAAS,0DAA2DC,QAAUC,GAAO,iCAAiCA,KACxH,CAAEF,QAAS,oBAAqBC,QAAUC,GAAO,kCAAkCA,KACnF,CAAEF,QAAS,0CAA2CC,QAAUC,GAAO,2CAA2CA,MAY7G,SAASC,GAAWC,KAAEA,EAAAC,QAAMA,EAAAC,OAASA,IAC1C,MAAOC,EAAKC,GAAUC,EAAAA,SAAS,KACxBC,EAAYC,GAAiBF,EAAAA,SAAS,OACtCG,EAAcC,GAAmBJ,EAAAA,UAAS,GAC3CK,EAAcC,EAAAA,OAAO,MAG3BC,EAAAA,WAAU,KAER,GADIF,EAAYG,SAASC,aAAaJ,EAAYG,SAC7CV,EAAIY,OAQT,OAJAL,EAAYG,QAAUG,YAAW,KAC/BT,EAvBN,SAAqBJ,GACnB,IAAKA,EAAK,OAAO,KACjB,IAAA,MAAWc,KAAUtB,EAAuB,CAC1C,MAAMuB,EAAQf,EAAIe,MAAMD,EAAOrB,SAC/B,GAAIsB,EAAO,OAAOD,EAAOpB,QAAQqB,EAAM,GACzC,CACA,OAAO,IACT,CAgBoBC,CAAYhB,EAAIY,SAC9BN,GAAgB,EAAK,GACpB,KACI,IAAMK,aAAaJ,EAAYG,SAPpCN,EAAc,KAO6B,GAC5C,CAACJ,IAGJS,EAAAA,WAAU,KACHZ,IACHI,EAAO,IACPG,EAAc,MAChB,GACC,CAACP,IAkBJ,SACEoB,IAACC,EAAAA,aAAA,CAAaC,MAAM,cAActB,OAAYC,UAC5CsB,SAAAC,EAAAA,KAAC,OAAA,CAAKC,SAlBYC,IAEpB,GADAA,EAAEC,kBACGxB,EAAIY,OAAQ,OAEjB,IAAIa,EACJ,IACEA,EAAUC,mBAAmB1B,EAAIY,OACnC,CAAA,MACEa,EAAUzB,EAAIY,MAChB,CACIrB,EAAmBoC,KAAKF,KAC5B1B,EAAO6B,eAAe,aAAc,CAAE5B,QACtCF,IACAG,EAAO,IAAE,EAKuB4B,UAAU,iBACtCT,SAAA,GAAAC,KAAC,MAAA,CAAIQ,UAAU,iBACbT,SAAA,CAAAH,MAAC,QAAA,CAAMY,UAAU,iBAAiBC,QAAQ,gBAAgBV,SAAA,cAC1DH,EAAAA,IAAC,QAAA,CACCtB,GAAG,gBACHoC,KAAK,MACLF,UAAU,iBACVG,MAAOhC,EACPiC,SAAWV,GAAMtB,EAAOsB,EAAEW,OAAOF,OACjCG,YAAY,sCACZC,UAAQ,EACRC,WAAS,OAGbpB,EAAAA,IAAC,IAAA,CAAEY,UAAU,gBAAgBT,SAAA,kDAE5BpB,EAAIY,QACHK,EAAAA,IAAC,MAAA,CAAIY,UAAU,oBACZT,SAAAjB,EACCkB,EAAAA,KAAC,MAAA,CAAIQ,UAAU,8BACZT,SAAA,EAACf,GAAgBY,EAAAA,IAAC,MAAA,CAAIY,UAAU,yBAAyBT,SAAA,uBAC1DH,EAAAA,IAAC,SAAA,CACCqB,IAAKnC,EACLgB,MAAM,gBACNoB,MAAM,2FACNC,iBAAe,EACfC,QAAQ,qDACRC,OAAQ,IAAMpC,GAAgB,QAIlCW,MAAC,MAAA,CAAIY,UAAU,gCAAgCT,mFAOrDC,KAAC,MAAA,CAAIQ,UAAU,oBACbT,SAAA,CAAAH,EAAAA,IAAC,UAAOc,KAAK,SAASF,UAAU,UAAUc,QAAS7C,EAASsB,SAAA,WAC5DH,EAAAA,IAAC,SAAA,CAAOc,KAAK,SAASF,UAAU,0BAA0Be,UAAW5C,EAAIY,OAAQQ,SAAA,iBAK3F,CAEAxB,EAAWiD,UAAY,CACrBhD,KAAMiD,EAAAA,UAAUC,KAAKC,WACrBlD,QAASgD,EAAAA,UAAUG,KAAKD,WACxBjD,OAAQ+C,EAAAA,UAAUI"}
@@ -1,4 +1,4 @@
1
- import{jsx as e,jsxs as r}from"react/jsx-runtime";import{useState as t,useRef as o,useEffect as i}from"react";import{P as m}from"./index-C720tbJA.js";import{M as a}from"./ModalOverlay-CLvRNHmp.js";const l=/^\s*(javascript|vbscript|data\s*:\s*text\/html)\s*:/i,n=[{pattern:/(?:youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]+)/,toEmbed:e=>`https://www.youtube.com/embed/${e}`},{pattern:/vimeo\.com\/(\d+)/,toEmbed:e=>`https://player.vimeo.com/video/${e}`},{pattern:/dailymotion\.com\/video\/([a-zA-Z0-9]+)/,toEmbed:e=>`https://www.dailymotion.com/embed/video/${e}`}];function c({open:m,onClose:c,engine:d}){const[s,u]=t(""),[p,b]=t(null),[h,v]=t(!1),w=o(null);i((()=>{if(w.current&&clearTimeout(w.current),s.trim())return w.current=setTimeout((()=>{b(function(e){if(!e)return null;for(const r of n){const t=e.match(r.pattern);if(t)return r.toEmbed(t[1])}return null}(s.trim())),v(!1)}),500),()=>clearTimeout(w.current);b(null)}),[s]),i((()=>{m||(u(""),b(null))}),[m]);/* @__PURE__ */
1
+ import{jsx as e,jsxs as r}from"react/jsx-runtime";import{useState as t,useRef as o,useEffect as i}from"react";import{P as m}from"./index-DL-qBZZU.js";import{M as a}from"./ModalOverlay-Dt0JiW3M.js";const l=/^\s*(javascript|vbscript|data\s*:\s*text\/html)\s*:/i,n=[{pattern:/(?:youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]+)/,toEmbed:e=>`https://www.youtube.com/embed/${e}`},{pattern:/vimeo\.com\/(\d+)/,toEmbed:e=>`https://player.vimeo.com/video/${e}`},{pattern:/dailymotion\.com\/video\/([a-zA-Z0-9]+)/,toEmbed:e=>`https://www.dailymotion.com/embed/video/${e}`}];function c({open:m,onClose:c,engine:d}){const[s,u]=t(""),[p,b]=t(null),[h,v]=t(!1),f=o(null);i((()=>{if(f.current&&clearTimeout(f.current),s.trim())return f.current=setTimeout((()=>{b(function(e){if(!e)return null;for(const r of n){const t=e.match(r.pattern);if(t)return r.toEmbed(t[1])}return null}(s.trim())),v(!1)}),500),()=>clearTimeout(f.current);b(null)}),[s]),i((()=>{m||(u(""),b(null))}),[m]);/* @__PURE__ */
2
2
  return e(a,{title:"Embed Media",open:m,onClose:c,children:/* @__PURE__ */r("form",{onSubmit:e=>{if(e.preventDefault(),!s.trim())return;let r;try{r=decodeURIComponent(s.trim())}catch{r=s.trim()}l.test(r)||(d.executeCommand("embedMedia",{url:s}),c(),u(""))},className:"rmx-modal-form",children:[
3
3
  /* @__PURE__ */r("div",{className:"rmx-form-group",children:[
4
4
  /* @__PURE__ */e("label",{className:"rmx-form-label",htmlFor:"rmx-embed-url",children:"Video URL"}),
@@ -8,4 +8,4 @@ return e(a,{title:"Embed Media",open:m,onClose:c,children:/* @__PURE__ */r("form
8
8
  /* @__PURE__ */r("div",{className:"rmx-modal-actions",children:[
9
9
  /* @__PURE__ */e("button",{type:"button",className:"rmx-btn",onClick:c,children:"Cancel"}),
10
10
  /* @__PURE__ */e("button",{type:"submit",className:"rmx-btn rmx-btn-primary",disabled:!s.trim(),children:"Embed"})]})]})})}c.propTypes={open:m.bool.isRequired,onClose:m.func.isRequired,engine:m.object};export{c as EmbedModal};
11
- //# sourceMappingURL=EmbedModal-cxE4maD2.js.map
11
+ //# sourceMappingURL=EmbedModal-alpHQiAP.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EmbedModal-cxE4maD2.js","sources":["../src/components/Modals/EmbedModal.jsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react'\nimport PropTypes from 'prop-types'\nimport { ModalOverlay } from './ModalOverlay.jsx'\n\nconst DANGEROUS_PROTOCOL = /^\\s*(javascript|vbscript|data\\s*:\\s*text\\/html)\\s*:/i\n\nconst ALLOWED_EMBED_DOMAINS = [\n { pattern: /(?:youtube\\.com\\/watch\\?v=|youtu\\.be\\/)([a-zA-Z0-9_-]+)/, toEmbed: (id) => `https://www.youtube.com/embed/${id}` },\n { pattern: /vimeo\\.com\\/(\\d+)/, toEmbed: (id) => `https://player.vimeo.com/video/${id}` },\n { pattern: /dailymotion\\.com\\/video\\/([a-zA-Z0-9]+)/, toEmbed: (id) => `https://www.dailymotion.com/embed/video/${id}` },\n]\n\nfunction getEmbedUrl(url) {\n if (!url) return null\n for (const domain of ALLOWED_EMBED_DOMAINS) {\n const match = url.match(domain.pattern)\n if (match) return domain.toEmbed(match[1])\n }\n return null\n}\n\nexport function EmbedModal({ open, onClose, engine }) {\n const [url, setUrl] = useState('')\n const [previewUrl, setPreviewUrl] = useState(null)\n const [iframeLoaded, setIframeLoaded] = useState(false)\n const debounceRef = useRef(null)\n\n // Debounce the preview URL update\n useEffect(() => {\n if (debounceRef.current) clearTimeout(debounceRef.current)\n if (!url.trim()) {\n setPreviewUrl(null)\n return\n }\n debounceRef.current = setTimeout(() => {\n setPreviewUrl(getEmbedUrl(url.trim()))\n setIframeLoaded(false)\n }, 500)\n return () => clearTimeout(debounceRef.current)\n }, [url])\n\n // Reset state when modal closes\n useEffect(() => {\n if (!open) {\n setUrl('')\n setPreviewUrl(null)\n }\n }, [open])\n\n const handleSubmit = (e) => {\n e.preventDefault()\n if (!url.trim()) return\n // Decode percent-encoding before validation to prevent bypasses like java%73cript:\n let decoded\n try {\n decoded = decodeURIComponent(url.trim())\n } catch {\n decoded = url.trim()\n }\n if (DANGEROUS_PROTOCOL.test(decoded)) return\n engine.executeCommand('embedMedia', { url })\n onClose()\n setUrl('')\n }\n\n return (\n <ModalOverlay title=\"Embed Media\" open={open} onClose={onClose}>\n <form onSubmit={handleSubmit} className=\"rmx-modal-form\">\n <div className=\"rmx-form-group\">\n <label className=\"rmx-form-label\" htmlFor=\"rmx-embed-url\">Video URL</label>\n <input\n id=\"rmx-embed-url\"\n type=\"url\"\n className=\"rmx-form-input\"\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n placeholder=\"https://www.youtube.com/watch?v=...\"\n required\n autoFocus\n />\n </div>\n <p className=\"rmx-form-hint\">Supports YouTube, Vimeo, and Dailymotion URLs</p>\n\n {url.trim() && (\n <div className=\"rmx-embed-preview\">\n {previewUrl ? (\n <div className=\"rmx-embed-loading-container\">\n {!iframeLoaded && <div className=\"rmx-embed-loading-text\">Loading preview...</div>}\n <iframe\n src={previewUrl}\n title=\"Embed preview\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n allowFullScreen\n sandbox=\"allow-scripts allow-same-origin allow-presentation\"\n onLoad={() => setIframeLoaded(true)}\n />\n </div>\n ) : (\n <div className=\"rmx-embed-preview-placeholder\">\n Enter a valid YouTube, Vimeo, or Dailymotion URL to see a preview\n </div>\n )}\n </div>\n )}\n\n <div className=\"rmx-modal-actions\">\n <button type=\"button\" className=\"rmx-btn\" onClick={onClose}>Cancel</button>\n <button type=\"submit\" className=\"rmx-btn rmx-btn-primary\" disabled={!url.trim()}>Embed</button>\n </div>\n </form>\n </ModalOverlay>\n )\n}\n\nEmbedModal.propTypes = {\n open: PropTypes.bool.isRequired,\n onClose: PropTypes.func.isRequired,\n engine: PropTypes.object,\n}\n"],"names":["DANGEROUS_PROTOCOL","ALLOWED_EMBED_DOMAINS","pattern","toEmbed","id","EmbedModal","open","onClose","engine","url","setUrl","useState","previewUrl","setPreviewUrl","iframeLoaded","setIframeLoaded","debounceRef","useRef","useEffect","current","clearTimeout","trim","setTimeout","domain","match","getEmbedUrl","jsx","ModalOverlay","title","children","jsxs","onSubmit","e","preventDefault","decoded","decodeURIComponent","test","executeCommand","className","htmlFor","type","value","onChange","target","placeholder","required","autoFocus","src","allow","allowFullScreen","sandbox","onLoad","onClick","disabled","propTypes","PropTypes","bool","isRequired","func","object"],"mappings":"qMAIA,MAAMA,EAAqB,uDAErBC,EAAwB,CAC5B,CAAEC,QAAS,0DAA2DC,QAAUC,GAAO,iCAAiCA,KACxH,CAAEF,QAAS,oBAAqBC,QAAUC,GAAO,kCAAkCA,KACnF,CAAEF,QAAS,0CAA2CC,QAAUC,GAAO,2CAA2CA,MAY7G,SAASC,GAAWC,KAAEA,EAAAC,QAAMA,EAAAC,OAASA,IAC1C,MAAOC,EAAKC,GAAUC,EAAS,KACxBC,EAAYC,GAAiBF,EAAS,OACtCG,EAAcC,GAAmBJ,GAAS,GAC3CK,EAAcC,EAAO,MAG3BC,GAAU,KAER,GADIF,EAAYG,SAASC,aAAaJ,EAAYG,SAC7CV,EAAIY,OAQT,OAJAL,EAAYG,QAAUG,YAAW,KAC/BT,EAvBN,SAAqBJ,GACnB,IAAKA,EAAK,OAAO,KACjB,IAAA,MAAWc,KAAUtB,EAAuB,CAC1C,MAAMuB,EAAQf,EAAIe,MAAMD,EAAOrB,SAC/B,GAAIsB,EAAO,OAAOD,EAAOpB,QAAQqB,EAAM,GACzC,CACA,OAAO,IACT,CAgBoBC,CAAYhB,EAAIY,SAC9BN,GAAgB,EAAK,GACpB,KACI,IAAMK,aAAaJ,EAAYG,SAPpCN,EAAc,KAO6B,GAC5C,CAACJ,IAGJS,GAAU,KACHZ,IACHI,EAAO,IACPG,EAAc,MAChB,GACC,CAACP;AAkBJ,OACEoB,EAACC,EAAA,CAAaC,MAAM,cAActB,OAAYC,UAC5CsB,wBAAAC,EAAC,OAAA,CAAKC,SAlBYC,IAEpB,GADAA,EAAEC,kBACGxB,EAAIY,OAAQ,OAEjB,IAAIa,EACJ,IACEA,EAAUC,mBAAmB1B,EAAIY,OACnC,CAAA,MACEa,EAAUzB,EAAIY,MAChB,CACIrB,EAAmBoC,KAAKF,KAC5B1B,EAAO6B,eAAe,aAAc,CAAE5B,QACtCF,IACAG,EAAO,IAAE,EAKuB4B,UAAU,iBACtCT,SAAA;eAAAC,EAAC,MAAA,CAAIQ,UAAU,iBACbT,SAAA;eAAAH,EAAC,QAAA,CAAMY,UAAU,iBAAiBC,QAAQ,gBAAgBV,SAAA;eAC1DH,EAAC,QAAA,CACCtB,GAAG,gBACHoC,KAAK,MACLF,UAAU,iBACVG,MAAOhC,EACPiC,SAAWV,GAAMtB,EAAOsB,EAAEW,OAAOF,OACjCG,YAAY,sCACZC,UAAQ,EACRC,WAAS;iBAGZ,IAAA,CAAER,UAAU,gBAAgBT,SAAA,kDAE5BpB,EAAIY,uBACHK,EAAC,MAAA,CAAIY,UAAU,oBACZT,SAAAjB,iBACCkB,EAAC,MAAA,CAAIQ,UAAU,8BACZT,SAAA,EAACf,kBAAgBY,EAAC,MAAA,CAAIY,UAAU,yBAAyBT,SAAA;eAC1DH,EAAC,SAAA,CACCqB,IAAKnC,EACLgB,MAAM,gBACNoB,MAAM,2FACNC,iBAAe,EACfC,QAAQ,qDACRC,OAAQ,IAAMpC,GAAgB,uBAIlCW,EAAC,MAAA,CAAIY,UAAU,gCAAgCT;eAOrDC,EAAC,MAAA,CAAIQ,UAAU,oBACbT,SAAA;eAAAH,EAAC,UAAOc,KAAK,SAASF,UAAU,UAAUc,QAAS7C,EAASsB,SAAA;eAC5DH,EAAC,SAAA,CAAOc,KAAK,SAASF,UAAU,0BAA0Be,UAAW5C,EAAIY,OAAQQ,SAAA,iBAK3F,CAEAxB,EAAWiD,UAAY,CACrBhD,KAAMiD,EAAUC,KAAKC,WACrBlD,QAASgD,EAAUG,KAAKD,WACxBjD,OAAQ+C,EAAUI"}
1
+ {"version":3,"file":"EmbedModal-alpHQiAP.js","sources":["../src/components/Modals/EmbedModal.jsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react'\nimport PropTypes from 'prop-types'\nimport { ModalOverlay } from './ModalOverlay.jsx'\n\nconst DANGEROUS_PROTOCOL = /^\\s*(javascript|vbscript|data\\s*:\\s*text\\/html)\\s*:/i\n\nconst ALLOWED_EMBED_DOMAINS = [\n { pattern: /(?:youtube\\.com\\/watch\\?v=|youtu\\.be\\/)([a-zA-Z0-9_-]+)/, toEmbed: (id) => `https://www.youtube.com/embed/${id}` },\n { pattern: /vimeo\\.com\\/(\\d+)/, toEmbed: (id) => `https://player.vimeo.com/video/${id}` },\n { pattern: /dailymotion\\.com\\/video\\/([a-zA-Z0-9]+)/, toEmbed: (id) => `https://www.dailymotion.com/embed/video/${id}` },\n]\n\nfunction getEmbedUrl(url) {\n if (!url) return null\n for (const domain of ALLOWED_EMBED_DOMAINS) {\n const match = url.match(domain.pattern)\n if (match) return domain.toEmbed(match[1])\n }\n return null\n}\n\nexport function EmbedModal({ open, onClose, engine }) {\n const [url, setUrl] = useState('')\n const [previewUrl, setPreviewUrl] = useState(null)\n const [iframeLoaded, setIframeLoaded] = useState(false)\n const debounceRef = useRef(null)\n\n // Debounce the preview URL update\n useEffect(() => {\n if (debounceRef.current) clearTimeout(debounceRef.current)\n if (!url.trim()) {\n setPreviewUrl(null)\n return\n }\n debounceRef.current = setTimeout(() => {\n setPreviewUrl(getEmbedUrl(url.trim()))\n setIframeLoaded(false)\n }, 500)\n return () => clearTimeout(debounceRef.current)\n }, [url])\n\n // Reset state when modal closes\n useEffect(() => {\n if (!open) {\n setUrl('')\n setPreviewUrl(null)\n }\n }, [open])\n\n const handleSubmit = (e) => {\n e.preventDefault()\n if (!url.trim()) return\n // Decode percent-encoding before validation to prevent bypasses like java%73cript:\n let decoded\n try {\n decoded = decodeURIComponent(url.trim())\n } catch {\n decoded = url.trim()\n }\n if (DANGEROUS_PROTOCOL.test(decoded)) return\n engine.executeCommand('embedMedia', { url })\n onClose()\n setUrl('')\n }\n\n return (\n <ModalOverlay title=\"Embed Media\" open={open} onClose={onClose}>\n <form onSubmit={handleSubmit} className=\"rmx-modal-form\">\n <div className=\"rmx-form-group\">\n <label className=\"rmx-form-label\" htmlFor=\"rmx-embed-url\">Video URL</label>\n <input\n id=\"rmx-embed-url\"\n type=\"url\"\n className=\"rmx-form-input\"\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n placeholder=\"https://www.youtube.com/watch?v=...\"\n required\n autoFocus\n />\n </div>\n <p className=\"rmx-form-hint\">Supports YouTube, Vimeo, and Dailymotion URLs</p>\n\n {url.trim() && (\n <div className=\"rmx-embed-preview\">\n {previewUrl ? (\n <div className=\"rmx-embed-loading-container\">\n {!iframeLoaded && <div className=\"rmx-embed-loading-text\">Loading preview...</div>}\n <iframe\n src={previewUrl}\n title=\"Embed preview\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n allowFullScreen\n sandbox=\"allow-scripts allow-same-origin allow-presentation\"\n onLoad={() => setIframeLoaded(true)}\n />\n </div>\n ) : (\n <div className=\"rmx-embed-preview-placeholder\">\n Enter a valid YouTube, Vimeo, or Dailymotion URL to see a preview\n </div>\n )}\n </div>\n )}\n\n <div className=\"rmx-modal-actions\">\n <button type=\"button\" className=\"rmx-btn\" onClick={onClose}>Cancel</button>\n <button type=\"submit\" className=\"rmx-btn rmx-btn-primary\" disabled={!url.trim()}>Embed</button>\n </div>\n </form>\n </ModalOverlay>\n )\n}\n\nEmbedModal.propTypes = {\n open: PropTypes.bool.isRequired,\n onClose: PropTypes.func.isRequired,\n engine: PropTypes.object,\n}\n"],"names":["DANGEROUS_PROTOCOL","ALLOWED_EMBED_DOMAINS","pattern","toEmbed","id","EmbedModal","open","onClose","engine","url","setUrl","useState","previewUrl","setPreviewUrl","iframeLoaded","setIframeLoaded","debounceRef","useRef","useEffect","current","clearTimeout","trim","setTimeout","domain","match","getEmbedUrl","jsx","ModalOverlay","title","children","jsxs","onSubmit","e","preventDefault","decoded","decodeURIComponent","test","executeCommand","className","htmlFor","type","value","onChange","target","placeholder","required","autoFocus","src","allow","allowFullScreen","sandbox","onLoad","onClick","disabled","propTypes","PropTypes","bool","isRequired","func","object"],"mappings":"qMAIA,MAAMA,EAAqB,uDAErBC,EAAwB,CAC5B,CAAEC,QAAS,0DAA2DC,QAAUC,GAAO,iCAAiCA,KACxH,CAAEF,QAAS,oBAAqBC,QAAUC,GAAO,kCAAkCA,KACnF,CAAEF,QAAS,0CAA2CC,QAAUC,GAAO,2CAA2CA,MAY7G,SAASC,GAAWC,KAAEA,EAAAC,QAAMA,EAAAC,OAASA,IAC1C,MAAOC,EAAKC,GAAUC,EAAS,KACxBC,EAAYC,GAAiBF,EAAS,OACtCG,EAAcC,GAAmBJ,GAAS,GAC3CK,EAAcC,EAAO,MAG3BC,GAAU,KAER,GADIF,EAAYG,SAASC,aAAaJ,EAAYG,SAC7CV,EAAIY,OAQT,OAJAL,EAAYG,QAAUG,YAAW,KAC/BT,EAvBN,SAAqBJ,GACnB,IAAKA,EAAK,OAAO,KACjB,IAAA,MAAWc,KAAUtB,EAAuB,CAC1C,MAAMuB,EAAQf,EAAIe,MAAMD,EAAOrB,SAC/B,GAAIsB,EAAO,OAAOD,EAAOpB,QAAQqB,EAAM,GACzC,CACA,OAAO,IACT,CAgBoBC,CAAYhB,EAAIY,SAC9BN,GAAgB,EAAK,GACpB,KACI,IAAMK,aAAaJ,EAAYG,SAPpCN,EAAc,KAO6B,GAC5C,CAACJ,IAGJS,GAAU,KACHZ,IACHI,EAAO,IACPG,EAAc,MAChB,GACC,CAACP;AAkBJ,OACEoB,EAACC,EAAA,CAAaC,MAAM,cAActB,OAAYC,UAC5CsB,wBAAAC,EAAC,OAAA,CAAKC,SAlBYC,IAEpB,GADAA,EAAEC,kBACGxB,EAAIY,OAAQ,OAEjB,IAAIa,EACJ,IACEA,EAAUC,mBAAmB1B,EAAIY,OACnC,CAAA,MACEa,EAAUzB,EAAIY,MAChB,CACIrB,EAAmBoC,KAAKF,KAC5B1B,EAAO6B,eAAe,aAAc,CAAE5B,QACtCF,IACAG,EAAO,IAAE,EAKuB4B,UAAU,iBACtCT,SAAA;eAAAC,EAAC,MAAA,CAAIQ,UAAU,iBACbT,SAAA;eAAAH,EAAC,QAAA,CAAMY,UAAU,iBAAiBC,QAAQ,gBAAgBV,SAAA;eAC1DH,EAAC,QAAA,CACCtB,GAAG,gBACHoC,KAAK,MACLF,UAAU,iBACVG,MAAOhC,EACPiC,SAAWV,GAAMtB,EAAOsB,EAAEW,OAAOF,OACjCG,YAAY,sCACZC,UAAQ,EACRC,WAAS;iBAGZ,IAAA,CAAER,UAAU,gBAAgBT,SAAA,kDAE5BpB,EAAIY,uBACHK,EAAC,MAAA,CAAIY,UAAU,oBACZT,SAAAjB,iBACCkB,EAAC,MAAA,CAAIQ,UAAU,8BACZT,SAAA,EAACf,kBAAgBY,EAAC,MAAA,CAAIY,UAAU,yBAAyBT,SAAA;eAC1DH,EAAC,SAAA,CACCqB,IAAKnC,EACLgB,MAAM,gBACNoB,MAAM,2FACNC,iBAAe,EACfC,QAAQ,qDACRC,OAAQ,IAAMpC,GAAgB,uBAIlCW,EAAC,MAAA,CAAIY,UAAU,gCAAgCT;eAOrDC,EAAC,MAAA,CAAIQ,UAAU,oBACbT,SAAA;eAAAH,EAAC,UAAOc,KAAK,SAASF,UAAU,UAAUc,QAAS7C,EAASsB,SAAA;eAC5DH,EAAC,SAAA,CAAOc,KAAK,SAASF,UAAU,0BAA0Be,UAAW5C,EAAIY,OAAQQ,SAAA,iBAK3F,CAEAxB,EAAWiD,UAAY,CACrBhD,KAAMiD,EAAUC,KAAKC,WACrBlD,QAASgD,EAAUG,KAAKD,WACxBjD,OAAQ+C,EAAUI"}
@@ -1,4 +1,4 @@
1
- import{jsxs as e,jsx as o}from"react/jsx-runtime";import{useState as r}from"react";import{P as n}from"./index-C720tbJA.js";import{M as t}from"./ModalOverlay-CLvRNHmp.js";import{exportAsPDF as a,exportAsMarkdown as l,exportAsDocx as s}from"@remyxjs/core";function i({open:n,onClose:i,engine:m}){const[p,c]=r(""),d=e=>{try{c(""),e(m.getHTML()),i()}catch(o){c(o.message||"Export failed. Please try again.")}};/* @__PURE__ */
1
+ import{jsxs as e,jsx as o}from"react/jsx-runtime";import{useState as r}from"react";import{P as n}from"./index-DL-qBZZU.js";import{M as t}from"./ModalOverlay-Dt0JiW3M.js";import{exportAsPDF as a,exportAsMarkdown as l,exportAsDocx as s}from"@remyxjs/core";function i({open:n,onClose:i,engine:m}){const[p,c]=r(""),d=e=>{try{c(""),e(m.getHTML()),i()}catch(o){c(o.message||"Export failed. Please try again.")}};/* @__PURE__ */
2
2
  return e(t,{title:"Export Document",open:n,onClose:()=>{c(""),i()},width:360,children:[p&&/* @__PURE__ */o("div",{className:"rmx-form-group rmx-form-error",children:p}),
3
3
  /* @__PURE__ */e("div",{className:"rmx-export-options",children:[
4
4
  /* @__PURE__ */e("button",{type:"button",className:"rmx-export-btn",onClick:()=>d(a),"aria-label":"Export as PDF — Opens print dialog",children:[
@@ -10,4 +10,4 @@ return e(t,{title:"Export Document",open:n,onClose:()=>{c(""),i()},width:360,chi
10
10
  /* @__PURE__ */e("button",{type:"button",className:"rmx-export-btn",onClick:()=>d(s),"aria-label":"Export as Word Document — Downloads .doc file",children:[
11
11
  /* @__PURE__ */o("span",{className:"rmx-export-btn-label",children:"Word Document"}),
12
12
  /* @__PURE__ */o("span",{className:"rmx-export-btn-hint",children:"Downloads .doc file"})]})]})]})}i.propTypes={open:n.bool.isRequired,onClose:n.func.isRequired,engine:n.object};export{i as ExportModal};
13
- //# sourceMappingURL=ExportModal-Cf1uE4r_.js.map
13
+ //# sourceMappingURL=ExportModal-BN8LUaSR.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExportModal-Cf1uE4r_.js","sources":["../src/components/Modals/ExportModal.jsx"],"sourcesContent":["import React, { useState } from 'react'\nimport PropTypes from 'prop-types'\nimport { ModalOverlay } from './ModalOverlay.jsx'\nimport { exportAsMarkdown, exportAsPDF, exportAsDocx } from '@remyxjs/core'\n\nexport function ExportModal({ open, onClose, engine }) {\n const [error, setError] = useState('')\n\n const handleExport = (exportFn) => {\n try {\n setError('')\n exportFn(engine.getHTML())\n onClose()\n } catch (err) {\n console.error('Export failed:', err)\n setError(err.message || 'Export failed. Please try again.')\n }\n }\n\n const handleClose = () => {\n setError('')\n onClose()\n }\n\n return (\n <ModalOverlay title=\"Export Document\" open={open} onClose={handleClose} width={360}>\n {error && (\n <div className=\"rmx-form-group rmx-form-error\">\n {error}\n </div>\n )}\n <div className=\"rmx-export-options\">\n <button\n type=\"button\"\n className=\"rmx-export-btn\"\n onClick={() => handleExport(exportAsPDF)}\n aria-label=\"Export as PDF — Opens print dialog\"\n >\n <span className=\"rmx-export-btn-label\">PDF</span>\n <span className=\"rmx-export-btn-hint\">Opens print dialog to save as PDF</span>\n </button>\n <button\n type=\"button\"\n className=\"rmx-export-btn\"\n onClick={() => handleExport(exportAsMarkdown)}\n aria-label=\"Export as Markdown — Downloads .md file\"\n >\n <span className=\"rmx-export-btn-label\">Markdown</span>\n <span className=\"rmx-export-btn-hint\">Downloads .md file</span>\n </button>\n <button\n type=\"button\"\n className=\"rmx-export-btn\"\n onClick={() => handleExport(exportAsDocx)}\n aria-label=\"Export as Word Document — Downloads .doc file\"\n >\n <span className=\"rmx-export-btn-label\">Word Document</span>\n <span className=\"rmx-export-btn-hint\">Downloads .doc file</span>\n </button>\n </div>\n </ModalOverlay>\n )\n}\n\nExportModal.propTypes = {\n open: PropTypes.bool.isRequired,\n onClose: PropTypes.func.isRequired,\n engine: PropTypes.object,\n}\n"],"names":["ExportModal","open","onClose","engine","error","setError","useState","handleExport","exportFn","getHTML","err","message","jsxs","ModalOverlay","title","width","children","className","type","onClick","exportAsPDF","exportAsMarkdown","exportAsDocx","propTypes","PropTypes","bool","isRequired","func","object"],"mappings":"8PAKO,SAASA,GAAYC,KAAEA,EAAAC,QAAMA,EAAAC,OAASA,IAC3C,MAAOC,EAAOC,GAAYC,EAAS,IAE7BC,EAAgBC,IACpB,IACEH,EAAS,IACTG,EAASL,EAAOM,WAChBP,GACF,OAASQ,GAEPL,EAASK,EAAIC,SAAW,mCAC1B;AAQF,OACEC,EAACC,GAAaC,MAAM,kBAAkBb,OAAYC,QANhC,KAClBG,EAAS,IACTH,GAAA,EAIwEa,MAAO,IAC5EC,SAAA,CAAAZ,oBACE,MAAA,CAAIa,UAAU,gCACZD,SAAAZ;eAGLQ,EAAC,MAAA,CAAIK,UAAU,qBACbD,SAAA;eAAAJ,EAAC,SAAA,CACCM,KAAK,SACLD,UAAU,iBACVE,QAAS,IAAMZ,EAAaa,GAC5B,aAAW,qCAEXJ,SAAA;iBAAC,OAAA,CAAKC,UAAU,uBAAuBD,SAAA;iBACtC,OAAA,CAAKC,UAAU,sBAAsBD,SAAA;eAExCJ,EAAC,SAAA,CACCM,KAAK,SACLD,UAAU,iBACVE,QAAS,IAAMZ,EAAac,GAC5B,aAAW,0CAEXL,SAAA;iBAAC,OAAA,CAAKC,UAAU,uBAAuBD,SAAA;iBACtC,OAAA,CAAKC,UAAU,sBAAsBD,SAAA;eAExCJ,EAAC,SAAA,CACCM,KAAK,SACLD,UAAU,iBACVE,QAAS,IAAMZ,EAAae,GAC5B,aAAW,gDAEXN,SAAA;iBAAC,OAAA,CAAKC,UAAU,uBAAuBD,SAAA;iBACtC,OAAA,CAAKC,UAAU,sBAAsBD,SAAA,gCAKhD,CAEAhB,EAAYuB,UAAY,CACtBtB,KAAMuB,EAAUC,KAAKC,WACrBxB,QAASsB,EAAUG,KAAKD,WACxBvB,OAAQqB,EAAUI"}
1
+ {"version":3,"file":"ExportModal-BN8LUaSR.js","sources":["../src/components/Modals/ExportModal.jsx"],"sourcesContent":["import React, { useState } from 'react'\nimport PropTypes from 'prop-types'\nimport { ModalOverlay } from './ModalOverlay.jsx'\nimport { exportAsMarkdown, exportAsPDF, exportAsDocx } from '@remyxjs/core'\n\nexport function ExportModal({ open, onClose, engine }) {\n const [error, setError] = useState('')\n\n const handleExport = (exportFn) => {\n try {\n setError('')\n exportFn(engine.getHTML())\n onClose()\n } catch (err) {\n console.error('Export failed:', err)\n setError(err.message || 'Export failed. Please try again.')\n }\n }\n\n const handleClose = () => {\n setError('')\n onClose()\n }\n\n return (\n <ModalOverlay title=\"Export Document\" open={open} onClose={handleClose} width={360}>\n {error && (\n <div className=\"rmx-form-group rmx-form-error\">\n {error}\n </div>\n )}\n <div className=\"rmx-export-options\">\n <button\n type=\"button\"\n className=\"rmx-export-btn\"\n onClick={() => handleExport(exportAsPDF)}\n aria-label=\"Export as PDF — Opens print dialog\"\n >\n <span className=\"rmx-export-btn-label\">PDF</span>\n <span className=\"rmx-export-btn-hint\">Opens print dialog to save as PDF</span>\n </button>\n <button\n type=\"button\"\n className=\"rmx-export-btn\"\n onClick={() => handleExport(exportAsMarkdown)}\n aria-label=\"Export as Markdown — Downloads .md file\"\n >\n <span className=\"rmx-export-btn-label\">Markdown</span>\n <span className=\"rmx-export-btn-hint\">Downloads .md file</span>\n </button>\n <button\n type=\"button\"\n className=\"rmx-export-btn\"\n onClick={() => handleExport(exportAsDocx)}\n aria-label=\"Export as Word Document — Downloads .doc file\"\n >\n <span className=\"rmx-export-btn-label\">Word Document</span>\n <span className=\"rmx-export-btn-hint\">Downloads .doc file</span>\n </button>\n </div>\n </ModalOverlay>\n )\n}\n\nExportModal.propTypes = {\n open: PropTypes.bool.isRequired,\n onClose: PropTypes.func.isRequired,\n engine: PropTypes.object,\n}\n"],"names":["ExportModal","open","onClose","engine","error","setError","useState","handleExport","exportFn","getHTML","err","message","jsxs","ModalOverlay","title","width","children","className","type","onClick","exportAsPDF","exportAsMarkdown","exportAsDocx","propTypes","PropTypes","bool","isRequired","func","object"],"mappings":"8PAKO,SAASA,GAAYC,KAAEA,EAAAC,QAAMA,EAAAC,OAASA,IAC3C,MAAOC,EAAOC,GAAYC,EAAS,IAE7BC,EAAgBC,IACpB,IACEH,EAAS,IACTG,EAASL,EAAOM,WAChBP,GACF,OAASQ,GAEPL,EAASK,EAAIC,SAAW,mCAC1B;AAQF,OACEC,EAACC,GAAaC,MAAM,kBAAkBb,OAAYC,QANhC,KAClBG,EAAS,IACTH,GAAA,EAIwEa,MAAO,IAC5EC,SAAA,CAAAZ,oBACE,MAAA,CAAIa,UAAU,gCACZD,SAAAZ;eAGLQ,EAAC,MAAA,CAAIK,UAAU,qBACbD,SAAA;eAAAJ,EAAC,SAAA,CACCM,KAAK,SACLD,UAAU,iBACVE,QAAS,IAAMZ,EAAaa,GAC5B,aAAW,qCAEXJ,SAAA;iBAAC,OAAA,CAAKC,UAAU,uBAAuBD,SAAA;iBACtC,OAAA,CAAKC,UAAU,sBAAsBD,SAAA;eAExCJ,EAAC,SAAA,CACCM,KAAK,SACLD,UAAU,iBACVE,QAAS,IAAMZ,EAAac,GAC5B,aAAW,0CAEXL,SAAA;iBAAC,OAAA,CAAKC,UAAU,uBAAuBD,SAAA;iBACtC,OAAA,CAAKC,UAAU,sBAAsBD,SAAA;eAExCJ,EAAC,SAAA,CACCM,KAAK,SACLD,UAAU,iBACVE,QAAS,IAAMZ,EAAae,GAC5B,aAAW,gDAEXN,SAAA;iBAAC,OAAA,CAAKC,UAAU,uBAAuBD,SAAA;iBACtC,OAAA,CAAKC,UAAU,sBAAsBD,SAAA,gCAKhD,CAEAhB,EAAYuB,UAAY,CACtBtB,KAAMuB,EAAUC,KAAKC,WACrBxB,QAASsB,EAAUG,KAAKD,WACxBvB,OAAQqB,EAAUI"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),r=require("react"),o=require("./index-Dc63uIP0.cjs"),s=require("./ModalOverlay-BDsGgv3_.cjs"),t=require("@remyxjs/core");function n({open:o,onClose:n,engine:a}){const[l,i]=r.useState(""),p=e=>{try{i(""),e(a.getHTML()),n()}catch(r){i(r.message||"Export failed. Please try again.")}};return e.jsxs(s.ModalOverlay,{title:"Export Document",open:o,onClose:()=>{i(""),n()},width:360,children:[l&&e.jsx("div",{className:"rmx-form-group rmx-form-error",children:l}),e.jsxs("div",{className:"rmx-export-options",children:[e.jsxs("button",{type:"button",className:"rmx-export-btn",onClick:()=>p(t.exportAsPDF),"aria-label":"Export as PDF — Opens print dialog",children:[e.jsx("span",{className:"rmx-export-btn-label",children:"PDF"}),e.jsx("span",{className:"rmx-export-btn-hint",children:"Opens print dialog to save as PDF"})]}),e.jsxs("button",{type:"button",className:"rmx-export-btn",onClick:()=>p(t.exportAsMarkdown),"aria-label":"Export as Markdown — Downloads .md file",children:[e.jsx("span",{className:"rmx-export-btn-label",children:"Markdown"}),e.jsx("span",{className:"rmx-export-btn-hint",children:"Downloads .md file"})]}),e.jsxs("button",{type:"button",className:"rmx-export-btn",onClick:()=>p(t.exportAsDocx),"aria-label":"Export as Word Document — Downloads .doc file",children:[e.jsx("span",{className:"rmx-export-btn-label",children:"Word Document"}),e.jsx("span",{className:"rmx-export-btn-hint",children:"Downloads .doc file"})]})]})]})}n.propTypes={open:o.PropTypes.bool.isRequired,onClose:o.PropTypes.func.isRequired,engine:o.PropTypes.object},exports.ExportModal=n;
2
- //# sourceMappingURL=ExportModal-DwQVsrZE.cjs.map
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),r=require("react"),o=require("./index-qh1Yzh-l.cjs"),s=require("./ModalOverlay-Dh5quv7X.cjs"),t=require("@remyxjs/core");function n({open:o,onClose:n,engine:a}){const[l,i]=r.useState(""),p=e=>{try{i(""),e(a.getHTML()),n()}catch(r){i(r.message||"Export failed. Please try again.")}};return e.jsxs(s.ModalOverlay,{title:"Export Document",open:o,onClose:()=>{i(""),n()},width:360,children:[l&&e.jsx("div",{className:"rmx-form-group rmx-form-error",children:l}),e.jsxs("div",{className:"rmx-export-options",children:[e.jsxs("button",{type:"button",className:"rmx-export-btn",onClick:()=>p(t.exportAsPDF),"aria-label":"Export as PDF — Opens print dialog",children:[e.jsx("span",{className:"rmx-export-btn-label",children:"PDF"}),e.jsx("span",{className:"rmx-export-btn-hint",children:"Opens print dialog to save as PDF"})]}),e.jsxs("button",{type:"button",className:"rmx-export-btn",onClick:()=>p(t.exportAsMarkdown),"aria-label":"Export as Markdown — Downloads .md file",children:[e.jsx("span",{className:"rmx-export-btn-label",children:"Markdown"}),e.jsx("span",{className:"rmx-export-btn-hint",children:"Downloads .md file"})]}),e.jsxs("button",{type:"button",className:"rmx-export-btn",onClick:()=>p(t.exportAsDocx),"aria-label":"Export as Word Document — Downloads .doc file",children:[e.jsx("span",{className:"rmx-export-btn-label",children:"Word Document"}),e.jsx("span",{className:"rmx-export-btn-hint",children:"Downloads .doc file"})]})]})]})}n.propTypes={open:o.PropTypes.bool.isRequired,onClose:o.PropTypes.func.isRequired,engine:o.PropTypes.object},exports.ExportModal=n;
2
+ //# sourceMappingURL=ExportModal-Cu-cCwa6.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExportModal-DwQVsrZE.cjs","sources":["../src/components/Modals/ExportModal.jsx"],"sourcesContent":["import React, { useState } from 'react'\nimport PropTypes from 'prop-types'\nimport { ModalOverlay } from './ModalOverlay.jsx'\nimport { exportAsMarkdown, exportAsPDF, exportAsDocx } from '@remyxjs/core'\n\nexport function ExportModal({ open, onClose, engine }) {\n const [error, setError] = useState('')\n\n const handleExport = (exportFn) => {\n try {\n setError('')\n exportFn(engine.getHTML())\n onClose()\n } catch (err) {\n console.error('Export failed:', err)\n setError(err.message || 'Export failed. Please try again.')\n }\n }\n\n const handleClose = () => {\n setError('')\n onClose()\n }\n\n return (\n <ModalOverlay title=\"Export Document\" open={open} onClose={handleClose} width={360}>\n {error && (\n <div className=\"rmx-form-group rmx-form-error\">\n {error}\n </div>\n )}\n <div className=\"rmx-export-options\">\n <button\n type=\"button\"\n className=\"rmx-export-btn\"\n onClick={() => handleExport(exportAsPDF)}\n aria-label=\"Export as PDF — Opens print dialog\"\n >\n <span className=\"rmx-export-btn-label\">PDF</span>\n <span className=\"rmx-export-btn-hint\">Opens print dialog to save as PDF</span>\n </button>\n <button\n type=\"button\"\n className=\"rmx-export-btn\"\n onClick={() => handleExport(exportAsMarkdown)}\n aria-label=\"Export as Markdown — Downloads .md file\"\n >\n <span className=\"rmx-export-btn-label\">Markdown</span>\n <span className=\"rmx-export-btn-hint\">Downloads .md file</span>\n </button>\n <button\n type=\"button\"\n className=\"rmx-export-btn\"\n onClick={() => handleExport(exportAsDocx)}\n aria-label=\"Export as Word Document — Downloads .doc file\"\n >\n <span className=\"rmx-export-btn-label\">Word Document</span>\n <span className=\"rmx-export-btn-hint\">Downloads .doc file</span>\n </button>\n </div>\n </ModalOverlay>\n )\n}\n\nExportModal.propTypes = {\n open: PropTypes.bool.isRequired,\n onClose: PropTypes.func.isRequired,\n engine: PropTypes.object,\n}\n"],"names":["ExportModal","open","onClose","engine","error","setError","useState","handleExport","exportFn","getHTML","err","message","jsxs","ModalOverlay","title","width","children","jsx","className","type","onClick","exportAsPDF","exportAsMarkdown","exportAsDocx","propTypes","PropTypes","bool","isRequired","func","object"],"mappings":"8OAKO,SAASA,GAAYC,KAAEA,EAAAC,QAAMA,EAAAC,OAASA,IAC3C,MAAOC,EAAOC,GAAYC,EAAAA,SAAS,IAE7BC,EAAgBC,IACpB,IACEH,EAAS,IACTG,EAASL,EAAOM,WAChBP,GACF,OAASQ,GAEPL,EAASK,EAAIC,SAAW,mCAC1B,GAQF,OACEC,OAACC,EAAAA,cAAaC,MAAM,kBAAkBb,OAAYC,QANhC,KAClBG,EAAS,IACTH,GAAA,EAIwEa,MAAO,IAC5EC,SAAA,CAAAZ,KACCa,IAAC,MAAA,CAAIC,UAAU,gCACZF,SAAAZ,MAGLQ,KAAC,MAAA,CAAIM,UAAU,qBACbF,SAAA,CAAAJ,EAAAA,KAAC,SAAA,CACCO,KAAK,SACLD,UAAU,iBACVE,QAAS,IAAMb,EAAac,eAC5B,aAAW,qCAEXL,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAKC,UAAU,uBAAuBF,SAAA,QACvCC,EAAAA,IAAC,OAAA,CAAKC,UAAU,sBAAsBF,SAAA,yCAExCJ,EAAAA,KAAC,SAAA,CACCO,KAAK,SACLD,UAAU,iBACVE,QAAS,IAAMb,EAAae,oBAC5B,aAAW,0CAEXN,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAKC,UAAU,uBAAuBF,SAAA,aACvCC,EAAAA,IAAC,OAAA,CAAKC,UAAU,sBAAsBF,SAAA,0BAExCJ,EAAAA,KAAC,SAAA,CACCO,KAAK,SACLD,UAAU,iBACVE,QAAS,IAAMb,EAAagB,gBAC5B,aAAW,gDAEXP,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAKC,UAAU,uBAAuBF,SAAA,kBACvCC,EAAAA,IAAC,OAAA,CAAKC,UAAU,sBAAsBF,SAAA,gCAKhD,CAEAhB,EAAYwB,UAAY,CACtBvB,KAAMwB,EAAAA,UAAUC,KAAKC,WACrBzB,QAASuB,EAAAA,UAAUG,KAAKD,WACxBxB,OAAQsB,EAAAA,UAAUI"}
1
+ {"version":3,"file":"ExportModal-Cu-cCwa6.cjs","sources":["../src/components/Modals/ExportModal.jsx"],"sourcesContent":["import React, { useState } from 'react'\nimport PropTypes from 'prop-types'\nimport { ModalOverlay } from './ModalOverlay.jsx'\nimport { exportAsMarkdown, exportAsPDF, exportAsDocx } from '@remyxjs/core'\n\nexport function ExportModal({ open, onClose, engine }) {\n const [error, setError] = useState('')\n\n const handleExport = (exportFn) => {\n try {\n setError('')\n exportFn(engine.getHTML())\n onClose()\n } catch (err) {\n console.error('Export failed:', err)\n setError(err.message || 'Export failed. Please try again.')\n }\n }\n\n const handleClose = () => {\n setError('')\n onClose()\n }\n\n return (\n <ModalOverlay title=\"Export Document\" open={open} onClose={handleClose} width={360}>\n {error && (\n <div className=\"rmx-form-group rmx-form-error\">\n {error}\n </div>\n )}\n <div className=\"rmx-export-options\">\n <button\n type=\"button\"\n className=\"rmx-export-btn\"\n onClick={() => handleExport(exportAsPDF)}\n aria-label=\"Export as PDF — Opens print dialog\"\n >\n <span className=\"rmx-export-btn-label\">PDF</span>\n <span className=\"rmx-export-btn-hint\">Opens print dialog to save as PDF</span>\n </button>\n <button\n type=\"button\"\n className=\"rmx-export-btn\"\n onClick={() => handleExport(exportAsMarkdown)}\n aria-label=\"Export as Markdown — Downloads .md file\"\n >\n <span className=\"rmx-export-btn-label\">Markdown</span>\n <span className=\"rmx-export-btn-hint\">Downloads .md file</span>\n </button>\n <button\n type=\"button\"\n className=\"rmx-export-btn\"\n onClick={() => handleExport(exportAsDocx)}\n aria-label=\"Export as Word Document — Downloads .doc file\"\n >\n <span className=\"rmx-export-btn-label\">Word Document</span>\n <span className=\"rmx-export-btn-hint\">Downloads .doc file</span>\n </button>\n </div>\n </ModalOverlay>\n )\n}\n\nExportModal.propTypes = {\n open: PropTypes.bool.isRequired,\n onClose: PropTypes.func.isRequired,\n engine: PropTypes.object,\n}\n"],"names":["ExportModal","open","onClose","engine","error","setError","useState","handleExport","exportFn","getHTML","err","message","jsxs","ModalOverlay","title","width","children","jsx","className","type","onClick","exportAsPDF","exportAsMarkdown","exportAsDocx","propTypes","PropTypes","bool","isRequired","func","object"],"mappings":"8OAKO,SAASA,GAAYC,KAAEA,EAAAC,QAAMA,EAAAC,OAASA,IAC3C,MAAOC,EAAOC,GAAYC,EAAAA,SAAS,IAE7BC,EAAgBC,IACpB,IACEH,EAAS,IACTG,EAASL,EAAOM,WAChBP,GACF,OAASQ,GAEPL,EAASK,EAAIC,SAAW,mCAC1B,GAQF,OACEC,OAACC,EAAAA,cAAaC,MAAM,kBAAkBb,OAAYC,QANhC,KAClBG,EAAS,IACTH,GAAA,EAIwEa,MAAO,IAC5EC,SAAA,CAAAZ,KACCa,IAAC,MAAA,CAAIC,UAAU,gCACZF,SAAAZ,MAGLQ,KAAC,MAAA,CAAIM,UAAU,qBACbF,SAAA,CAAAJ,EAAAA,KAAC,SAAA,CACCO,KAAK,SACLD,UAAU,iBACVE,QAAS,IAAMb,EAAac,eAC5B,aAAW,qCAEXL,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAKC,UAAU,uBAAuBF,SAAA,QACvCC,EAAAA,IAAC,OAAA,CAAKC,UAAU,sBAAsBF,SAAA,yCAExCJ,EAAAA,KAAC,SAAA,CACCO,KAAK,SACLD,UAAU,iBACVE,QAAS,IAAMb,EAAae,oBAC5B,aAAW,0CAEXN,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAKC,UAAU,uBAAuBF,SAAA,aACvCC,EAAAA,IAAC,OAAA,CAAKC,UAAU,sBAAsBF,SAAA,0BAExCJ,EAAAA,KAAC,SAAA,CACCO,KAAK,SACLD,UAAU,iBACVE,QAAS,IAAMb,EAAagB,gBAC5B,aAAW,gDAEXP,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAKC,UAAU,uBAAuBF,SAAA,kBACvCC,EAAAA,IAAC,OAAA,CAAKC,UAAU,sBAAsBF,SAAA,gCAKhD,CAEAhB,EAAYwB,UAAY,CACtBvB,KAAMwB,EAAAA,UAAUC,KAAKC,WACrBzB,QAASuB,EAAAA,UAAUG,KAAKD,WACxBxB,OAAQsB,EAAAA,UAAUI"}
@@ -1,4 +1,4 @@
1
- import{jsxs as e,jsx as t}from"react/jsx-runtime";import{useState as n,useRef as r,useEffect as a,useCallback as l}from"react";import{P as c}from"./index-C720tbJA.js";function o({open:c,onClose:o,engine:i}){const[m,s]=n(""),[u,d]=n(""),[p,x]=n(!1),[b,f]=n({total:0,current:0}),[h,y]=n(""),v=r(null);a((()=>{if(!i)return;return i.eventBus.on("find:results",f)}),[i]),a((()=>{c||(i?.executeCommand("clearFind"),s(""),d(""),f({total:0,current:0}),y(""))}),[c,i]);const C=()=>{if(m.trim())try{i.executeCommand("find",{text:m,caseSensitive:p})}catch(e){}},N=l((()=>{const e=b.total;i.executeCommand("replaceAll",{replaceText:u}),y(`Replaced ${e} occurrence${1!==e?"s":""}`),setTimeout((()=>y("")),3e3)}),[i,u,b.total]),k=l((e=>{if("Escape"===e.key)return e.preventDefault(),void o();if("Tab"===e.key&&v.current){const t=Array.from(v.current.querySelectorAll('input, button:not([disabled]), [tabindex]:not([tabindex="-1"])'));if(0===t.length)return void e.preventDefault();const n=t[0],r=t[t.length-1];e.shiftKey?document.activeElement===n&&(e.preventDefault(),r.focus()):document.activeElement===r&&(e.preventDefault(),n.focus())}}),[o]);return c?/* @__PURE__ */e("div",{className:"rmx-find-replace-panel",onMouseDown:e=>e.stopPropagation(),onKeyDown:k,ref:v,role:"search","aria-label":"Find and replace",children:[
1
+ import{jsxs as e,jsx as t}from"react/jsx-runtime";import{useState as n,useRef as r,useEffect as a,useCallback as l}from"react";import{P as c}from"./index-DL-qBZZU.js";function o({open:c,onClose:o,engine:i}){const[m,s]=n(""),[u,d]=n(""),[p,x]=n(!1),[b,f]=n({total:0,current:0}),[h,y]=n(""),v=r(null);a((()=>{if(!i)return;return i.eventBus.on("find:results",f)}),[i]),a((()=>{c||(i?.executeCommand("clearFind"),s(""),d(""),f({total:0,current:0}),y(""))}),[c,i]);const C=()=>{if(m.trim())try{i.executeCommand("find",{text:m,caseSensitive:p})}catch(e){}},N=l((()=>{const e=b.total;i.executeCommand("replaceAll",{replaceText:u}),y(`Replaced ${e} occurrence${1!==e?"s":""}`),setTimeout((()=>y("")),3e3)}),[i,u,b.total]),k=l((e=>{if("Escape"===e.key)return e.preventDefault(),void o();if("Tab"===e.key&&v.current){const t=Array.from(v.current.querySelectorAll('input, button:not([disabled]), [tabindex]:not([tabindex="-1"])'));if(0===t.length)return void e.preventDefault();const n=t[0],r=t[t.length-1];e.shiftKey?document.activeElement===n&&(e.preventDefault(),r.focus()):document.activeElement===r&&(e.preventDefault(),n.focus())}}),[o]);return c?/* @__PURE__ */e("div",{className:"rmx-find-replace-panel",onMouseDown:e=>e.stopPropagation(),onKeyDown:k,ref:v,role:"search","aria-label":"Find and replace",children:[
2
2
  /* @__PURE__ */e("div",{className:"rmx-find-row",children:[
3
3
  /* @__PURE__ */t("label",{htmlFor:"rmx-find-input",className:"rmx-sr-only",children:"Find text"}),
4
4
  /* @__PURE__ */t("input",{id:"rmx-find-input",type:"text",className:"rmx-form-input rmx-find-input",value:m,onChange:e=>s(e.target.value),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),b.total>0?i.executeCommand("findNext"):C())},placeholder:"Find...",autoFocus:!0}),
@@ -14,4 +14,4 @@ import{jsxs as e,jsx as t}from"react/jsx-runtime";import{useState as n,useRef as
14
14
  /* @__PURE__ */t("input",{id:"rmx-replace-input",type:"text",className:"rmx-form-input rmx-find-input",value:u,onChange:e=>d(e.target.value),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),i.executeCommand("replace",{replaceText:u}))},placeholder:"Replace..."}),
15
15
  /* @__PURE__ */t("button",{type:"button",className:"rmx-btn rmx-btn-sm",onClick:()=>i.executeCommand("replace",{replaceText:u}),children:"Replace"}),
16
16
  /* @__PURE__ */t("button",{type:"button",className:"rmx-btn rmx-btn-sm",onClick:N,children:"All"}),h&&/* @__PURE__ */t("span",{className:"rmx-find-count",role:"status",children:h})]})]}):null}o.propTypes={open:c.bool.isRequired,onClose:c.func.isRequired,engine:c.object};export{o as FindReplacePanel};
17
- //# sourceMappingURL=FindReplaceModal-Dgt_MrWb.js.map
17
+ //# sourceMappingURL=FindReplaceModal-BqNcotUr.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FindReplaceModal-Dgt_MrWb.js","sources":["../src/components/Modals/FindReplaceModal.jsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react'\nimport PropTypes from 'prop-types'\n\nconst FOCUSABLE_SELECTOR = 'input, button:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n\nexport function FindReplacePanel({ open, onClose, engine }) {\n const [findText, setFindText] = useState('')\n const [replaceText, setReplaceText] = useState('')\n const [caseSensitive, setCaseSensitive] = useState(false)\n const [results, setResults] = useState({ total: 0, current: 0 })\n const [replaceAllMsg, setReplaceAllMsg] = useState('')\n const containerRef = useRef(null)\n\n useEffect(() => {\n if (!engine) return\n const unsub = engine.eventBus.on('find:results', setResults)\n return unsub\n }, [engine])\n\n useEffect(() => {\n if (!open) {\n engine?.executeCommand('clearFind')\n setFindText('')\n setReplaceText('')\n setResults({ total: 0, current: 0 })\n setReplaceAllMsg('')\n }\n }, [open, engine])\n\n const handleFind = () => {\n if (!findText.trim()) return\n try {\n engine.executeCommand('find', { text: findText, caseSensitive })\n } catch (err) {\n console.error('Find command failed:', err)\n }\n }\n\n // #32: Replace All with count feedback\n const handleReplaceAll = useCallback(() => {\n const count = results.total\n engine.executeCommand('replaceAll', { replaceText })\n setReplaceAllMsg(`Replaced ${count} occurrence${count !== 1 ? 's' : ''}`)\n setTimeout(() => setReplaceAllMsg(''), 3000)\n }, [engine, replaceText, results.total])\n\n // #31: Escape key handler + focus trap\n const handleKeyDown = useCallback((e) => {\n if (e.key === 'Escape') {\n e.preventDefault()\n onClose()\n return\n }\n\n // Focus trap\n if (e.key === 'Tab' && containerRef.current) {\n const focusable = Array.from(containerRef.current.querySelectorAll(FOCUSABLE_SELECTOR))\n if (focusable.length === 0) { e.preventDefault(); return }\n\n const first = focusable[0]\n const last = focusable[focusable.length - 1]\n\n if (e.shiftKey) {\n if (document.activeElement === first) {\n e.preventDefault()\n last.focus()\n }\n } else {\n if (document.activeElement === last) {\n e.preventDefault()\n first.focus()\n }\n }\n }\n }, [onClose])\n\n if (!open) return null\n\n return (\n <div\n className=\"rmx-find-replace-panel\"\n onMouseDown={(e) => e.stopPropagation()}\n onKeyDown={handleKeyDown}\n ref={containerRef}\n role=\"search\"\n aria-label=\"Find and replace\"\n >\n <div className=\"rmx-find-row\">\n <label htmlFor=\"rmx-find-input\" className=\"rmx-sr-only\">Find text</label>\n <input\n id=\"rmx-find-input\"\n type=\"text\"\n className=\"rmx-form-input rmx-find-input\"\n value={findText}\n onChange={(e) => setFindText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault()\n if (results.total > 0) {\n engine.executeCommand('findNext')\n } else {\n handleFind()\n }\n }\n }}\n placeholder=\"Find...\"\n autoFocus\n />\n <span className=\"rmx-find-count\">\n {results.total > 0 ? `${results.current}/${results.total}` : 'No results'}\n </span>\n <button type=\"button\" className=\"rmx-btn rmx-btn-sm\" onClick={handleFind}>Find</button>\n <button type=\"button\" className=\"rmx-btn rmx-btn-sm\" onClick={() => engine.executeCommand('findPrev')} aria-label=\"Previous match\">&#9650;</button>\n <button type=\"button\" className=\"rmx-btn rmx-btn-sm\" onClick={() => engine.executeCommand('findNext')} aria-label=\"Next match\">&#9660;</button>\n <label className=\"rmx-form-checkbox rmx-find-case\">\n <input\n type=\"checkbox\"\n checked={caseSensitive}\n onChange={(e) => setCaseSensitive(e.target.checked)}\n aria-label=\"Toggle case sensitive search\"\n />\n Aa\n </label>\n <button type=\"button\" className=\"rmx-btn rmx-btn-sm\" onClick={onClose} aria-label=\"Close find and replace\">&times;</button>\n </div>\n <div className=\"rmx-find-row\">\n <label htmlFor=\"rmx-replace-input\" className=\"rmx-sr-only\">Replace text</label>\n <input\n id=\"rmx-replace-input\"\n type=\"text\"\n className=\"rmx-form-input rmx-find-input\"\n value={replaceText}\n onChange={(e) => setReplaceText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault()\n engine.executeCommand('replace', { replaceText })\n }\n }}\n placeholder=\"Replace...\"\n />\n <button type=\"button\" className=\"rmx-btn rmx-btn-sm\" onClick={() => engine.executeCommand('replace', { replaceText })}>Replace</button>\n <button type=\"button\" className=\"rmx-btn rmx-btn-sm\" onClick={handleReplaceAll}>All</button>\n {replaceAllMsg && <span className=\"rmx-find-count\" role=\"status\">{replaceAllMsg}</span>}\n </div>\n </div>\n )\n}\n\nFindReplacePanel.propTypes = {\n open: PropTypes.bool.isRequired,\n onClose: PropTypes.func.isRequired,\n engine: PropTypes.object,\n}\n"],"names":["FindReplacePanel","open","onClose","engine","findText","setFindText","useState","replaceText","setReplaceText","caseSensitive","setCaseSensitive","results","setResults","total","current","replaceAllMsg","setReplaceAllMsg","containerRef","useRef","useEffect","eventBus","on","executeCommand","handleFind","trim","text","err","handleReplaceAll","useCallback","count","setTimeout","handleKeyDown","e","key","preventDefault","focusable","Array","from","querySelectorAll","length","first","last","shiftKey","document","activeElement","focus","jsxs","className","onMouseDown","stopPropagation","onKeyDown","ref","role","children","jsx","htmlFor","id","type","value","onChange","target","placeholder","autoFocus","onClick","checked","propTypes","PropTypes","bool","isRequired","func","object"],"mappings":"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"}
1
+ {"version":3,"file":"FindReplaceModal-BqNcotUr.js","sources":["../src/components/Modals/FindReplaceModal.jsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react'\nimport PropTypes from 'prop-types'\n\nconst FOCUSABLE_SELECTOR = 'input, button:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n\nexport function FindReplacePanel({ open, onClose, engine }) {\n const [findText, setFindText] = useState('')\n const [replaceText, setReplaceText] = useState('')\n const [caseSensitive, setCaseSensitive] = useState(false)\n const [results, setResults] = useState({ total: 0, current: 0 })\n const [replaceAllMsg, setReplaceAllMsg] = useState('')\n const containerRef = useRef(null)\n\n useEffect(() => {\n if (!engine) return\n const unsub = engine.eventBus.on('find:results', setResults)\n return unsub\n }, [engine])\n\n useEffect(() => {\n if (!open) {\n engine?.executeCommand('clearFind')\n setFindText('')\n setReplaceText('')\n setResults({ total: 0, current: 0 })\n setReplaceAllMsg('')\n }\n }, [open, engine])\n\n const handleFind = () => {\n if (!findText.trim()) return\n try {\n engine.executeCommand('find', { text: findText, caseSensitive })\n } catch (err) {\n console.error('Find command failed:', err)\n }\n }\n\n // #32: Replace All with count feedback\n const handleReplaceAll = useCallback(() => {\n const count = results.total\n engine.executeCommand('replaceAll', { replaceText })\n setReplaceAllMsg(`Replaced ${count} occurrence${count !== 1 ? 's' : ''}`)\n setTimeout(() => setReplaceAllMsg(''), 3000)\n }, [engine, replaceText, results.total])\n\n // #31: Escape key handler + focus trap\n const handleKeyDown = useCallback((e) => {\n if (e.key === 'Escape') {\n e.preventDefault()\n onClose()\n return\n }\n\n // Focus trap\n if (e.key === 'Tab' && containerRef.current) {\n const focusable = Array.from(containerRef.current.querySelectorAll(FOCUSABLE_SELECTOR))\n if (focusable.length === 0) { e.preventDefault(); return }\n\n const first = focusable[0]\n const last = focusable[focusable.length - 1]\n\n if (e.shiftKey) {\n if (document.activeElement === first) {\n e.preventDefault()\n last.focus()\n }\n } else {\n if (document.activeElement === last) {\n e.preventDefault()\n first.focus()\n }\n }\n }\n }, [onClose])\n\n if (!open) return null\n\n return (\n <div\n className=\"rmx-find-replace-panel\"\n onMouseDown={(e) => e.stopPropagation()}\n onKeyDown={handleKeyDown}\n ref={containerRef}\n role=\"search\"\n aria-label=\"Find and replace\"\n >\n <div className=\"rmx-find-row\">\n <label htmlFor=\"rmx-find-input\" className=\"rmx-sr-only\">Find text</label>\n <input\n id=\"rmx-find-input\"\n type=\"text\"\n className=\"rmx-form-input rmx-find-input\"\n value={findText}\n onChange={(e) => setFindText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault()\n if (results.total > 0) {\n engine.executeCommand('findNext')\n } else {\n handleFind()\n }\n }\n }}\n placeholder=\"Find...\"\n autoFocus\n />\n <span className=\"rmx-find-count\">\n {results.total > 0 ? `${results.current}/${results.total}` : 'No results'}\n </span>\n <button type=\"button\" className=\"rmx-btn rmx-btn-sm\" onClick={handleFind}>Find</button>\n <button type=\"button\" className=\"rmx-btn rmx-btn-sm\" onClick={() => engine.executeCommand('findPrev')} aria-label=\"Previous match\">&#9650;</button>\n <button type=\"button\" className=\"rmx-btn rmx-btn-sm\" onClick={() => engine.executeCommand('findNext')} aria-label=\"Next match\">&#9660;</button>\n <label className=\"rmx-form-checkbox rmx-find-case\">\n <input\n type=\"checkbox\"\n checked={caseSensitive}\n onChange={(e) => setCaseSensitive(e.target.checked)}\n aria-label=\"Toggle case sensitive search\"\n />\n Aa\n </label>\n <button type=\"button\" className=\"rmx-btn rmx-btn-sm\" onClick={onClose} aria-label=\"Close find and replace\">&times;</button>\n </div>\n <div className=\"rmx-find-row\">\n <label htmlFor=\"rmx-replace-input\" className=\"rmx-sr-only\">Replace text</label>\n <input\n id=\"rmx-replace-input\"\n type=\"text\"\n className=\"rmx-form-input rmx-find-input\"\n value={replaceText}\n onChange={(e) => setReplaceText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault()\n engine.executeCommand('replace', { replaceText })\n }\n }}\n placeholder=\"Replace...\"\n />\n <button type=\"button\" className=\"rmx-btn rmx-btn-sm\" onClick={() => engine.executeCommand('replace', { replaceText })}>Replace</button>\n <button type=\"button\" className=\"rmx-btn rmx-btn-sm\" onClick={handleReplaceAll}>All</button>\n {replaceAllMsg && <span className=\"rmx-find-count\" role=\"status\">{replaceAllMsg}</span>}\n </div>\n </div>\n )\n}\n\nFindReplacePanel.propTypes = {\n open: PropTypes.bool.isRequired,\n onClose: PropTypes.func.isRequired,\n engine: PropTypes.object,\n}\n"],"names":["FindReplacePanel","open","onClose","engine","findText","setFindText","useState","replaceText","setReplaceText","caseSensitive","setCaseSensitive","results","setResults","total","current","replaceAllMsg","setReplaceAllMsg","containerRef","useRef","useEffect","eventBus","on","executeCommand","handleFind","trim","text","err","handleReplaceAll","useCallback","count","setTimeout","handleKeyDown","e","key","preventDefault","focusable","Array","from","querySelectorAll","length","first","last","shiftKey","document","activeElement","focus","jsxs","className","onMouseDown","stopPropagation","onKeyDown","ref","role","children","jsx","htmlFor","id","type","value","onChange","target","placeholder","autoFocus","onClick","checked","propTypes","PropTypes","bool","isRequired","func","object"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("react"),n=require("./index-Dc63uIP0.cjs");function r({open:n,onClose:r,engine:a}){const[l,s]=t.useState(""),[c,o]=t.useState(""),[i,u]=t.useState(!1),[m,x]=t.useState({total:0,current:0}),[d,p]=t.useState(""),b=t.useRef(null);t.useEffect((()=>{if(!a)return;return a.eventBus.on("find:results",x)}),[a]),t.useEffect((()=>{n||(a?.executeCommand("clearFind"),s(""),o(""),x({total:0,current:0}),p(""))}),[n,a]);const f=()=>{if(l.trim())try{a.executeCommand("find",{text:l,caseSensitive:i})}catch(e){}},h=t.useCallback((()=>{const e=m.total;a.executeCommand("replaceAll",{replaceText:c}),p(`Replaced ${e} occurrence${1!==e?"s":""}`),setTimeout((()=>p("")),3e3)}),[a,c,m.total]),y=t.useCallback((e=>{if("Escape"===e.key)return e.preventDefault(),void r();if("Tab"===e.key&&b.current){const t=Array.from(b.current.querySelectorAll('input, button:not([disabled]), [tabindex]:not([tabindex="-1"])'));if(0===t.length)return void e.preventDefault();const n=t[0],r=t[t.length-1];e.shiftKey?document.activeElement===n&&(e.preventDefault(),r.focus()):document.activeElement===r&&(e.preventDefault(),n.focus())}}),[r]);return n?e.jsxs("div",{className:"rmx-find-replace-panel",onMouseDown:e=>e.stopPropagation(),onKeyDown:y,ref:b,role:"search","aria-label":"Find and replace",children:[e.jsxs("div",{className:"rmx-find-row",children:[e.jsx("label",{htmlFor:"rmx-find-input",className:"rmx-sr-only",children:"Find text"}),e.jsx("input",{id:"rmx-find-input",type:"text",className:"rmx-form-input rmx-find-input",value:l,onChange:e=>s(e.target.value),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),m.total>0?a.executeCommand("findNext"):f())},placeholder:"Find...",autoFocus:!0}),e.jsx("span",{className:"rmx-find-count",children:m.total>0?`${m.current}/${m.total}`:"No results"}),e.jsx("button",{type:"button",className:"rmx-btn rmx-btn-sm",onClick:f,children:"Find"}),e.jsx("button",{type:"button",className:"rmx-btn rmx-btn-sm",onClick:()=>a.executeCommand("findPrev"),"aria-label":"Previous match",children:"▲"}),e.jsx("button",{type:"button",className:"rmx-btn rmx-btn-sm",onClick:()=>a.executeCommand("findNext"),"aria-label":"Next match",children:"▼"}),e.jsxs("label",{className:"rmx-form-checkbox rmx-find-case",children:[e.jsx("input",{type:"checkbox",checked:i,onChange:e=>u(e.target.checked),"aria-label":"Toggle case sensitive search"}),"Aa"]}),e.jsx("button",{type:"button",className:"rmx-btn rmx-btn-sm",onClick:r,"aria-label":"Close find and replace",children:"×"})]}),e.jsxs("div",{className:"rmx-find-row",children:[e.jsx("label",{htmlFor:"rmx-replace-input",className:"rmx-sr-only",children:"Replace text"}),e.jsx("input",{id:"rmx-replace-input",type:"text",className:"rmx-form-input rmx-find-input",value:c,onChange:e=>o(e.target.value),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),a.executeCommand("replace",{replaceText:c}))},placeholder:"Replace..."}),e.jsx("button",{type:"button",className:"rmx-btn rmx-btn-sm",onClick:()=>a.executeCommand("replace",{replaceText:c}),children:"Replace"}),e.jsx("button",{type:"button",className:"rmx-btn rmx-btn-sm",onClick:h,children:"All"}),d&&e.jsx("span",{className:"rmx-find-count",role:"status",children:d})]})]}):null}r.propTypes={open:n.PropTypes.bool.isRequired,onClose:n.PropTypes.func.isRequired,engine:n.PropTypes.object},exports.FindReplacePanel=r;
2
- //# sourceMappingURL=FindReplaceModal-DYL_2z8U.cjs.map
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("react"),n=require("./index-qh1Yzh-l.cjs");function r({open:n,onClose:r,engine:a}){const[l,s]=t.useState(""),[c,o]=t.useState(""),[i,u]=t.useState(!1),[m,x]=t.useState({total:0,current:0}),[d,p]=t.useState(""),b=t.useRef(null);t.useEffect((()=>{if(!a)return;return a.eventBus.on("find:results",x)}),[a]),t.useEffect((()=>{n||(a?.executeCommand("clearFind"),s(""),o(""),x({total:0,current:0}),p(""))}),[n,a]);const f=()=>{if(l.trim())try{a.executeCommand("find",{text:l,caseSensitive:i})}catch(e){}},h=t.useCallback((()=>{const e=m.total;a.executeCommand("replaceAll",{replaceText:c}),p(`Replaced ${e} occurrence${1!==e?"s":""}`),setTimeout((()=>p("")),3e3)}),[a,c,m.total]),y=t.useCallback((e=>{if("Escape"===e.key)return e.preventDefault(),void r();if("Tab"===e.key&&b.current){const t=Array.from(b.current.querySelectorAll('input, button:not([disabled]), [tabindex]:not([tabindex="-1"])'));if(0===t.length)return void e.preventDefault();const n=t[0],r=t[t.length-1];e.shiftKey?document.activeElement===n&&(e.preventDefault(),r.focus()):document.activeElement===r&&(e.preventDefault(),n.focus())}}),[r]);return n?e.jsxs("div",{className:"rmx-find-replace-panel",onMouseDown:e=>e.stopPropagation(),onKeyDown:y,ref:b,role:"search","aria-label":"Find and replace",children:[e.jsxs("div",{className:"rmx-find-row",children:[e.jsx("label",{htmlFor:"rmx-find-input",className:"rmx-sr-only",children:"Find text"}),e.jsx("input",{id:"rmx-find-input",type:"text",className:"rmx-form-input rmx-find-input",value:l,onChange:e=>s(e.target.value),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),m.total>0?a.executeCommand("findNext"):f())},placeholder:"Find...",autoFocus:!0}),e.jsx("span",{className:"rmx-find-count",children:m.total>0?`${m.current}/${m.total}`:"No results"}),e.jsx("button",{type:"button",className:"rmx-btn rmx-btn-sm",onClick:f,children:"Find"}),e.jsx("button",{type:"button",className:"rmx-btn rmx-btn-sm",onClick:()=>a.executeCommand("findPrev"),"aria-label":"Previous match",children:"▲"}),e.jsx("button",{type:"button",className:"rmx-btn rmx-btn-sm",onClick:()=>a.executeCommand("findNext"),"aria-label":"Next match",children:"▼"}),e.jsxs("label",{className:"rmx-form-checkbox rmx-find-case",children:[e.jsx("input",{type:"checkbox",checked:i,onChange:e=>u(e.target.checked),"aria-label":"Toggle case sensitive search"}),"Aa"]}),e.jsx("button",{type:"button",className:"rmx-btn rmx-btn-sm",onClick:r,"aria-label":"Close find and replace",children:"×"})]}),e.jsxs("div",{className:"rmx-find-row",children:[e.jsx("label",{htmlFor:"rmx-replace-input",className:"rmx-sr-only",children:"Replace text"}),e.jsx("input",{id:"rmx-replace-input",type:"text",className:"rmx-form-input rmx-find-input",value:c,onChange:e=>o(e.target.value),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),a.executeCommand("replace",{replaceText:c}))},placeholder:"Replace..."}),e.jsx("button",{type:"button",className:"rmx-btn rmx-btn-sm",onClick:()=>a.executeCommand("replace",{replaceText:c}),children:"Replace"}),e.jsx("button",{type:"button",className:"rmx-btn rmx-btn-sm",onClick:h,children:"All"}),d&&e.jsx("span",{className:"rmx-find-count",role:"status",children:d})]})]}):null}r.propTypes={open:n.PropTypes.bool.isRequired,onClose:n.PropTypes.func.isRequired,engine:n.PropTypes.object},exports.FindReplacePanel=r;
2
+ //# sourceMappingURL=FindReplaceModal-DgysYT04.cjs.map