panda_cms 0.5.10 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -1
  3. data/Rakefile +0 -1
  4. data/app/assets/builds/panda_cms.css +2432 -1
  5. data/app/assets/config/panda_cms_manifest.js +3 -0
  6. data/app/assets/stylesheets/panda_cms/application.tailwind.css +3 -27
  7. data/app/builders/panda_cms/form_builder.rb +1 -1
  8. data/app/components/panda_cms/admin/button_component.rb +6 -3
  9. data/app/components/panda_cms/admin/flash_message_component.rb +1 -1
  10. data/app/components/panda_cms/admin/tag_component.rb +1 -1
  11. data/app/components/panda_cms/code_component.rb +62 -0
  12. data/app/components/panda_cms/menu_component.html.erb +3 -0
  13. data/app/components/panda_cms/menu_component.rb +8 -1
  14. data/app/components/panda_cms/page_menu_component.html.erb +12 -8
  15. data/app/components/panda_cms/page_menu_component.rb +24 -13
  16. data/app/components/panda_cms/rich_text_component.html.erb +6 -38
  17. data/app/components/panda_cms/rich_text_component.rb +32 -7
  18. data/app/components/panda_cms/text_component.rb +25 -22
  19. data/app/controllers/panda_cms/admin/block_contents_controller.rb +1 -1
  20. data/app/controllers/panda_cms/admin/dashboard_controller.rb +14 -6
  21. data/app/controllers/panda_cms/admin/menus_controller.rb +1 -54
  22. data/app/controllers/panda_cms/admin/pages_controller.rb +2 -1
  23. data/app/controllers/panda_cms/admin/sessions_controller.rb +13 -6
  24. data/app/controllers/panda_cms/application_controller.rb +1 -1
  25. data/app/controllers/panda_cms/pages_controller.rb +1 -1
  26. data/app/controllers/panda_cms/posts_controller.rb +1 -1
  27. data/app/helpers/panda_cms/application_helper.rb +2 -2
  28. data/app/javascript/panda_cms/@editorjs--editorjs.js +2577 -0
  29. data/app/javascript/panda_cms/@hotwired--stimulus.js +4 -0
  30. data/app/javascript/panda_cms/@hotwired--turbo.js +160 -0
  31. data/app/javascript/panda_cms/@rails--actioncable--src.js +4 -0
  32. data/app/javascript/panda_cms/application_panda_cms.js +4 -0
  33. data/app/javascript/panda_cms/controllers/dashboard_controller.js +7 -0
  34. data/app/javascript/panda_cms/controllers/editor_controller.js +247 -0
  35. data/app/javascript/panda_cms/controllers/index.js +45 -0
  36. data/app/javascript/panda_cms/controllers/slug_controller.js +48 -0
  37. data/app/javascript/panda_cms/editor/plain_text_editor.js +102 -0
  38. data/app/javascript/panda_cms/editor/resource_loader.js +69 -0
  39. data/app/javascript/panda_cms/editor/rich_text_editor.js +89 -0
  40. data/app/javascript/panda_cms/tailwindcss-stimulus-components.js +4 -0
  41. data/app/lib/panda_cms/demo_site_generator.rb +1 -3
  42. data/app/lib/panda_cms/editor_js/blocks/alert.rb +32 -0
  43. data/app/lib/panda_cms/editor_js/blocks/base.rb +28 -0
  44. data/app/lib/panda_cms/editor_js/blocks/header.rb +13 -0
  45. data/app/lib/panda_cms/editor_js/blocks/image.rb +34 -0
  46. data/app/lib/panda_cms/editor_js/blocks/list.rb +30 -0
  47. data/app/lib/panda_cms/editor_js/blocks/paragraph.rb +13 -0
  48. data/app/lib/panda_cms/editor_js/blocks/quote.rb +27 -0
  49. data/app/lib/panda_cms/editor_js/blocks/table.rb +48 -0
  50. data/app/lib/panda_cms/editor_js/renderer.rb +120 -0
  51. data/app/lib/panda_cms/slug.rb +1 -1
  52. data/app/models/panda_cms/block.rb +2 -2
  53. data/app/models/panda_cms/block_content.rb +12 -2
  54. data/app/models/panda_cms/page.rb +9 -3
  55. data/app/models/panda_cms/post.rb +1 -1
  56. data/app/models/panda_cms/template.rb +4 -2
  57. data/app/models/panda_cms/user.rb +9 -1
  58. data/app/views/panda_cms/admin/dashboard/show.html.erb +11 -9
  59. data/app/views/panda_cms/admin/forms/new.html.erb +6 -7
  60. data/app/views/panda_cms/admin/menus/index.html.erb +0 -2
  61. data/app/views/panda_cms/admin/pages/edit.html.erb +22 -19
  62. data/app/views/panda_cms/admin/pages/new.html.erb +6 -7
  63. data/app/views/panda_cms/admin/posts/_form.html.erb +4 -4
  64. data/app/views/panda_cms/admin/sessions/new.html.erb +1 -2
  65. data/app/views/panda_cms/admin/shared/_sidebar.html.erb +12 -16
  66. data/app/views/panda_cms/shared/_header.html.erb +13 -14
  67. data/app/views/panda_cms/shared/_importmap.html.erb +32 -0
  68. data/config/importmap.rb +13 -10
  69. data/config/initializers/panda_cms.rb +57 -55
  70. data/config/routes.rb +9 -9
  71. data/config/tailwind.config.js +1 -0
  72. data/db/migrate/20240205223709_create_panda_cms_pages.rb +6 -4
  73. data/db/migrate/20240315125411_add_status_to_panda_cms_pages.rb +9 -0
  74. data/db/migrate/20241031205109_add_cached_content_to_panda_cms_block_contents.rb +5 -0
  75. data/db/seeds.rb +1 -0
  76. data/lib/generators/panda_cms/install_generator.rb +3 -0
  77. data/lib/panda_cms/engine.rb +42 -29
  78. data/lib/panda_cms/version.rb +1 -1
  79. data/lib/panda_cms.rb +58 -10
  80. data/lib/tasks/panda_cms.rake +41 -57
  81. data/public/panda-cms-assets/rich_text_editor.css +568 -0
  82. metadata +228 -304
  83. data/app/javascript/base.js +0 -37
  84. data/app/javascript/controllers/menu_controller.js +0 -19
  85. data/app/javascript/controllers/text_controller.js +0 -78
  86. data/app/javascript/controllers/text_field_update_controller.js +0 -51
  87. data/app/javascript/vendor/stimulus-components-rails-nested-form.js +0 -2
  88. data/app/javascript/vendor/tailwindcss-stimulus-components.js +0 -2
  89. data/app/views/panda_cms/admin/menus/_form.html.erb +0 -21
  90. data/app/views/panda_cms/admin/menus/_menu_item_fields.html.erb +0 -7
  91. data/app/views/panda_cms/admin/menus/edit.html.erb +0 -58
  92. data/app/views/panda_cms/admin/menus/new.html.erb +0 -5
  93. data/db/migrate/20240804110225_add_status_to_panda_cms_pages.rb +0 -7
  94. data/public/panda-cms-assets/javascripts/base.js +0 -37
  95. data/public/panda-cms-assets/javascripts/controllers/menu_controller.js +0 -19
  96. data/public/panda-cms-assets/javascripts/controllers/text_field_update_controller.js +0 -23
  97. data/public/panda-cms-assets/javascripts/embed/editable.js +0 -358
  98. data/public/panda-cms-assets/javascripts/embed/rich_text.css +0 -1294
  99. data/public/panda-cms-assets/javascripts/vendor/stimulus-components-rails-nested-form.js +0 -2
  100. data/public/panda-cms-assets/javascripts/vendor/stimulus-loading.js +0 -113
  101. data/public/panda-cms-assets/javascripts/vendor/tailwindcss-stimulus-components.js +0 -2
@@ -0,0 +1,2577 @@
1
+ // @editorjs/editorjs@2.30.6 downloaded from https://ga.jspm.io/npm:@editorjs/editorjs@2.30.6/dist/editorjs.mjs
2
+
3
+ (function(){try{if(typeof document<"u"){var n=document.createElement("style");n.appendChild(document.createTextNode(".ce-hint--align-start{text-align:left}.ce-hint--align-center{text-align:center}.ce-hint__description{opacity:.6;margin-top:3px}")),document.head.appendChild(n)}}catch(n){console.error("vite-plugin-css-injected-by-js",n)}})();typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"&&self;function Fe(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n}function ze(){}Object.assign(ze,{default:ze,register:ze,revert:function(){},__esModule:!0});Element.prototype.matches||(Element.prototype.matches=Element.prototype.matchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector||Element.prototype.webkitMatchesSelector||function(n){const h=(this.document||this.ownerDocument).querySelectorAll(n);let p=h.length;for(;--p>=0&&h.item(p)!==this;);return p>-1});Element.prototype.closest||(Element.prototype.closest=function(n){let h=this;if(!document.documentElement.contains(h))return null;do{if(h.matches(n))return h;h=h.parentElement||h.parentNode}while(h!==null);return null});Element.prototype.prepend||(Element.prototype.prepend=function(n){const h=document.createDocumentFragment();Array.isArray(n)||(n=[n]),n.forEach((n=>{const p=n instanceof Node;h.appendChild(p?n:document.createTextNode(n))})),this.insertBefore(h,this.firstChild)});Element.prototype.scrollIntoViewIfNeeded||(Element.prototype.scrollIntoViewIfNeeded=function(n){n=arguments.length===0||!!n;const h=this.parentNode,p=window.getComputedStyle(h,null),g=parseInt(p.getPropertyValue("border-top-width")),m=parseInt(p.getPropertyValue("border-left-width")),v=this.offsetTop-h.offsetTop<h.scrollTop,x=this.offsetTop-h.offsetTop+this.clientHeight-g>h.scrollTop+h.clientHeight,w=this.offsetLeft-h.offsetLeft<h.scrollLeft,E=this.offsetLeft-h.offsetLeft+this.clientWidth-m>h.scrollLeft+h.clientWidth,B=v&&!x;(v||x)&&n&&(h.scrollTop=this.offsetTop-h.offsetTop-h.clientHeight/2-g+this.clientHeight/2),(w||E)&&n&&(h.scrollLeft=this.offsetLeft-h.offsetLeft-h.clientWidth/2-m+this.clientWidth/2),(v||x||w||E)&&!n&&this.scrollIntoView(B)});window.requestIdleCallback=window.requestIdleCallback||function(n){const h=Date.now();return setTimeout((function(){n({didTimeout:!1,timeRemaining:function(){return Math.max(0,50-(Date.now()-h))}})}),1)};window.cancelIdleCallback=window.cancelIdleCallback||function(n){clearTimeout(n)};let vo=(n=21)=>crypto.getRandomValues(new Uint8Array(n)).reduce(((n,h)=>(h&=63,n+=h<36?h.toString(36):h<62?(h-26).toString(36).toUpperCase():h>62?"-":"_",n)),"");var n=(n=>(n.VERBOSE="VERBOSE",n.INFO="INFO",n.WARN="WARN",n.ERROR="ERROR",n))(n||{});const h={BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,LEFT:37,UP:38,DOWN:40,RIGHT:39,DELETE:46,META:91,SLASH:191},p={LEFT:0,WHEEL:1,RIGHT:2,BACKWARD:3,FORWARD:4};function Be(n,h,p="log",g,m="color: inherit"){if(!("console"in window)||!window.console[p])return;const v=["info","log","warn","error"].includes(p),x=[];switch(Be.logLevel){case"ERROR":if(p!=="error")return;break;case"WARN":if(!["error","warn"].includes(p))return;break;case"INFO":if(!v||n)return;break}g&&x.push(g);const w="Editor.js 2.30.6",E="line-height: 1em;\n color: #006FEA;\n display: inline-block;\n font-size: 11px;\n line-height: 1em;\n background-color: #fff;\n padding: 4px 9px;\n border-radius: 30px;\n border: 1px solid rgba(56, 138, 229, 0.16);\n margin: 4px 5px 4px 0;";n&&(v?(x.unshift(E,m),h=`%c${w}%c ${h}`):h=`( ${w} )${h}`);try{v?g?console[p](`${h} %o`,...x):console[p](h,...x):console[p](h)}catch{}}Be.logLevel="VERBOSE";function xo(n){Be.logLevel=n}const g=Be.bind(window,!1),m=Be.bind(window,!0);function re(n){return Object.prototype.toString.call(n).match(/\s([a-zA-Z]+)/)[1].toLowerCase()}function O(n){return re(n)==="function"||re(n)==="asyncfunction"}function R(n){return re(n)==="object"}function Q(n){return re(n)==="string"}function yo(n){return re(n)==="boolean"}function bt(n){return re(n)==="number"}function kt(n){return re(n)==="undefined"}function V(n){return!n||Object.keys(n).length===0&&n.constructor===Object}function Mt(n){return n>47&&n<58||n===32||n===13||n===229||n>64&&n<91||n>95&&n<112||n>185&&n<193||n>218&&n<223}async function Eo(n,h=(()=>{}),p=(()=>{})){async function o(n,h,p){try{await n.function(n.data),await h(kt(n.data)?{}:n.data)}catch{p(kt(n.data)?{}:n.data)}}return n.reduce((async(n,g)=>(await n,o(g,h,p))),Promise.resolve())}function At(n){return Array.prototype.slice.call(n)}function Oe(n,h){return function(){const p=this,g=arguments;window.setTimeout((()=>n.apply(p,g)),h)}}function Bo(n){return n.name.split(".").pop()}function To(n){return/^[-\w]+\/([-+\w]+|\*)$/.test(n)}function vt(n,h,p){let g;return(...m)=>{const v=this,r=()=>{g=null,p||n.apply(v,m)},x=p&&!g;window.clearTimeout(g),g=window.setTimeout(r,h),x&&n.apply(v,m)}}function Ve(n,h,p=void 0){let g,m,v,x=null,w=0;p||(p={});const a=function(){w=p.leading===!1?0:Date.now(),x=null,v=n.apply(g,m),x||(g=m=null)};return function(){const E=Date.now();!w&&p.leading===!1&&(w=E);const B=h-(E-w);return g=this,m=arguments,B<=0||B>h?(x&&(clearTimeout(x),x=null),w=E,v=n.apply(g,m),x||(g=m=null)):!x&&p.trailing!==!1&&(x=setTimeout(a,B)),v}}function Co(){const n={win:!1,mac:!1,x11:!1,linux:!1},h=Object.keys(n).find((n=>window.navigator.appVersion.toLowerCase().indexOf(n)!==-1));return h&&(n[h]=!0),n}function Le(n){return n[0].toUpperCase()+n.slice(1)}function qe(n,...h){if(!h.length)return n;const p=h.shift();if(R(n)&&R(p))for(const h in p)R(p[h])?(n[h]||Object.assign(n,{[h]:{}}),qe(n[h],p[h])):Object.assign(n,{[h]:p[h]});return qe(n,...h)}function tt(n){const h=Co();return n=n.replace(/shift/gi,"⇧").replace(/backspace/gi,"⌫").replace(/enter/gi,"⏎").replace(/up/gi,"↑").replace(/left/gi,"→").replace(/down/gi,"↓").replace(/right/gi,"←").replace(/escape/gi,"⎋").replace(/insert/gi,"Ins").replace(/delete/gi,"␡").replace(/\+/gi," + "),n=h.mac?n.replace(/ctrl|cmd/gi,"⌘").replace(/alt/gi,"⌥"):n.replace(/cmd/gi,"Ctrl").replace(/windows/gi,"WIN"),n}function So(n){try{return new URL(n).href}catch{}return n.substring(0,2)==="//"?window.location.protocol+n:window.location.origin+n}function Io(){return vo(10)}function Mo(n){window.open(n,"_blank")}function Ao(n=""){return`${n}${Math.floor(Math.random()*1e8).toString(16)}`}function Ze(n,h,p){const g=`«${h}» is deprecated and will be removed in the next major release. Please use the «${p}» instead.`;n&&m(g,"warn")}function ue(n,h,p){const g=p.value?"value":"get",m=p[g],v=`#${h}Cache`;if(p[g]=function(...n){return this[v]===void 0&&(this[v]=m.apply(this,...n)),this[v]},g==="get"&&p.set){const h=p.set;p.set=function(p){delete n[v],h.apply(this,p)}}return p}const v=650;function pe(){return window.matchMedia(`(max-width: ${v}px)`).matches}const x=typeof window<"u"&&window.navigator&&window.navigator.platform&&(/iP(ad|hone|od)/.test(window.navigator.platform)||window.navigator.platform==="MacIntel"&&window.navigator.maxTouchPoints>1);function Oo(n,h){const p=Array.isArray(n)||R(n),g=Array.isArray(h)||R(h);return p||g?JSON.stringify(n)===JSON.stringify(h):n===h}class d{
4
+ /**
5
+ * Check if passed tag has no closed tag
6
+ *
7
+ * @param {HTMLElement} tag - element to check
8
+ * @returns {boolean}
9
+ */
10
+ static isSingleTag(n){return n.tagName&&["AREA","BASE","BR","COL","COMMAND","EMBED","HR","IMG","INPUT","KEYGEN","LINK","META","PARAM","SOURCE","TRACK","WBR"].includes(n.tagName)}
11
+ /**
12
+ * Check if element is BR or WBR
13
+ *
14
+ * @param {HTMLElement} element - element to check
15
+ * @returns {boolean}
16
+ */static isLineBreakTag(n){return n&&n.tagName&&["BR","WBR"].includes(n.tagName)}
17
+ /**
18
+ * Helper for making Elements with class name and attributes
19
+ *
20
+ * @param {string} tagName - new Element tag name
21
+ * @param {string[]|string} [classNames] - list or name of CSS class name(s)
22
+ * @param {object} [attributes] - any attributes
23
+ * @returns {HTMLElement}
24
+ */static make(n,h=null,p={}){const g=document.createElement(n);if(Array.isArray(h)){const n=h.filter((n=>n!==void 0));g.classList.add(...n)}else h&&g.classList.add(h);for(const n in p)Object.prototype.hasOwnProperty.call(p,n)&&(g[n]=p[n]);return g}
25
+ /**
26
+ * Creates Text Node with the passed content
27
+ *
28
+ * @param {string} content - text content
29
+ * @returns {Text}
30
+ */static text(n){return document.createTextNode(n)}
31
+ /**
32
+ * Append one or several elements to the parent
33
+ *
34
+ * @param {Element|DocumentFragment} parent - where to append
35
+ * @param {Element|Element[]|DocumentFragment|Text|Text[]} elements - element or elements list
36
+ */static append(n,h){Array.isArray(h)?h.forEach((h=>n.appendChild(h))):n.appendChild(h)}
37
+ /**
38
+ * Append element or a couple to the beginning of the parent elements
39
+ *
40
+ * @param {Element} parent - where to append
41
+ * @param {Element|Element[]} elements - element or elements list
42
+ */static prepend(n,h){Array.isArray(h)?(h=h.reverse(),h.forEach((h=>n.prepend(h)))):n.prepend(h)}
43
+ /**
44
+ * Swap two elements in parent
45
+ *
46
+ * @param {HTMLElement} el1 - from
47
+ * @param {HTMLElement} el2 - to
48
+ * @deprecated
49
+ */static swap(n,h){const p=document.createElement("div"),g=n.parentNode;g.insertBefore(p,n),g.insertBefore(n,h),g.insertBefore(h,p),g.removeChild(p)
50
+ /**
51
+ * Selector Decorator
52
+ *
53
+ * Returns first match
54
+ *
55
+ * @param {Element} el - element we searching inside. Default - DOM Document
56
+ * @param {string} selector - searching string
57
+ * @returns {Element}
58
+ */}static find(n=document,h){return n.querySelector(h)}
59
+ /**
60
+ * Get Element by Id
61
+ *
62
+ * @param {string} id - id to find
63
+ * @returns {HTMLElement | null}
64
+ */static get(n){return document.getElementById(n)}
65
+ /**
66
+ * Selector Decorator.
67
+ *
68
+ * Returns all matches
69
+ *
70
+ * @param {Element|Document} el - element we searching inside. Default - DOM Document
71
+ * @param {string} selector - searching string
72
+ * @returns {NodeList}
73
+ */static findAll(n=document,h){return n.querySelectorAll(h)}static get allInputsSelector(){return"[contenteditable=true], textarea, input:not([type]), "+["text","password","email","number","search","tel","url"].map((n=>`input[type="${n}"]`)).join(", ")}
74
+ /**
75
+ * Find all contenteditable, textarea and editable input elements passed holder contains
76
+ *
77
+ * @param holder - element where to find inputs
78
+ */static findAllInputs(n){return At(n.querySelectorAll(d.allInputsSelector)).reduce(((n,h)=>d.isNativeInput(h)||d.containsOnlyInlineElements(h)?[...n,h]:[...n,...d.getDeepestBlockElements(h)]),[])}
79
+ /**
80
+ * Search for deepest node which is Leaf.
81
+ * Leaf is the vertex that doesn't have any child nodes
82
+ *
83
+ * @description Method recursively goes throw the all Node until it finds the Leaf
84
+ * @param {Node} node - root Node. From this vertex we start Deep-first search
85
+ * {@link https://en.wikipedia.org/wiki/Depth-first_search}
86
+ * @param {boolean} [atLast] - find last text node
87
+ * @returns - it can be text Node or Element Node, so that caret will able to work with it
88
+ * Can return null if node is Document or DocumentFragment, or node is not attached to the DOM
89
+ */static getDeepestNode(n,h=!1){const p=h?"lastChild":"firstChild",g=h?"previousSibling":"nextSibling";if(n&&n.nodeType===Node.ELEMENT_NODE&&n[p]){let m=n[p];if(d.isSingleTag(m)&&!d.isNativeInput(m)&&!d.isLineBreakTag(m))if(m[g])m=m[g];else{if(!m.parentNode[g])return m.parentNode;m=m.parentNode[g]}return this.getDeepestNode(m,h)}return n}
90
+ /**
91
+ * Check if object is DOM node
92
+ *
93
+ * @param {*} node - object to check
94
+ * @returns {boolean}
95
+ */
96
+ static isElement(n){return!bt(n)&&(n&&n.nodeType&&n.nodeType===Node.ELEMENT_NODE)}
97
+ /**
98
+ * Check if object is DocumentFragment node
99
+ *
100
+ * @param {object} node - object to check
101
+ * @returns {boolean}
102
+ */
103
+ static isFragment(n){return!bt(n)&&(n&&n.nodeType&&n.nodeType===Node.DOCUMENT_FRAGMENT_NODE)}
104
+ /**
105
+ * Check if passed element is contenteditable
106
+ *
107
+ * @param {HTMLElement} element - html element to check
108
+ * @returns {boolean}
109
+ */static isContentEditable(n){return n.contentEditable==="true"}
110
+ /**
111
+ * Checks target if it is native input
112
+ *
113
+ * @param {*} target - HTML element or string
114
+ * @returns {boolean}
115
+ */
116
+ static isNativeInput(n){const h=["INPUT","TEXTAREA"];return!(!n||!n.tagName)&&h.includes(n.tagName)}
117
+ /**
118
+ * Checks if we can set caret
119
+ *
120
+ * @param {HTMLElement} target - target to check
121
+ * @returns {boolean}
122
+ */static canSetCaret(n){let h=!0;if(d.isNativeInput(n))switch(n.type){case"file":case"checkbox":case"radio":case"hidden":case"submit":case"button":case"image":case"reset":h=!1;break}else h=d.isContentEditable(n);return h}
123
+ /**
124
+ * Checks node if it is empty
125
+ *
126
+ * @description Method checks simple Node without any childs for emptiness
127
+ * If you have Node with 2 or more children id depth, you better use {@link Dom#isEmpty} method
128
+ * @param {Node} node - node to check
129
+ * @param {string} [ignoreChars] - char or substring to treat as empty
130
+ * @returns {boolean} true if it is empty
131
+ */static isNodeEmpty(n,h){let p;return!(this.isSingleTag(n)&&!this.isLineBreakTag(n))&&(p=this.isElement(n)&&this.isNativeInput(n)?n.value:n.textContent.replace("​",""),h&&(p=p.replace(new RegExp(h,"g"),"")),p.trim().length===0
132
+ /**
133
+ * checks node if it is doesn't have any child nodes
134
+ *
135
+ * @param {Node} node - node to check
136
+ * @returns {boolean}
137
+ */)}static isLeaf(n){return!!n&&n.childNodes.length===0}
138
+ /**
139
+ * breadth-first search (BFS)
140
+ * {@link https://en.wikipedia.org/wiki/Breadth-first_search}
141
+ *
142
+ * @description Pushes to stack all DOM leafs and checks for emptiness
143
+ * @param {Node} node - node to check
144
+ * @param {string} [ignoreChars] - char or substring to treat as empty
145
+ * @returns {boolean}
146
+ */static isEmpty(n,h){n.normalize();const p=[n];for(;p.length>0;)if(n=p.shift(),!!n){if(this.isLeaf(n)&&!this.isNodeEmpty(n,h))return!1;n.childNodes&&p.push(...Array.from(n.childNodes))}return!0}
147
+ /**
148
+ * Check if string contains html elements
149
+ *
150
+ * @param {string} str - string to check
151
+ * @returns {boolean}
152
+ */static isHTMLString(n){const h=d.make("div");return h.innerHTML=n,h.childElementCount>0
153
+ /**
154
+ * Return length of node`s text content
155
+ *
156
+ * @param {Node} node - node with content
157
+ * @returns {number}
158
+ */}static getContentLength(n){return d.isNativeInput(n)?n.value.length:n.nodeType===Node.TEXT_NODE?n.length:n.textContent.length}
159
+ /**
160
+ * Return array of names of block html elements
161
+ *
162
+ * @returns {string[]}
163
+ */static get blockElements(){return["address","article","aside","blockquote","canvas","div","dl","dt","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","li","main","nav","noscript","ol","output","p","pre","ruby","section","table","tbody","thead","tr","tfoot","ul","video"]}
164
+ /**
165
+ * Check if passed content includes only inline elements
166
+ *
167
+ * @param {string|HTMLElement} data - element or html string
168
+ * @returns {boolean}
169
+ */static containsOnlyInlineElements(n){let h;Q(n)?(h=document.createElement("div"),h.innerHTML=n):h=n;const o=n=>!d.blockElements.includes(n.tagName.toLowerCase())&&Array.from(n.children).every(o);return Array.from(h.children).every(o)}
170
+ /**
171
+ * Find and return all block elements in the passed parent (including subtree)
172
+ *
173
+ * @param {HTMLElement} parent - root element
174
+ * @returns {HTMLElement[]}
175
+ */static getDeepestBlockElements(n){return d.containsOnlyInlineElements(n)?[n]:Array.from(n.children).reduce(((n,h)=>[...n,...d.getDeepestBlockElements(h)]),[])}
176
+ /**
177
+ * Helper for get holder from {string} or return HTMLElement
178
+ *
179
+ * @param {string | HTMLElement} element - holder's id or holder's HTML Element
180
+ * @returns {HTMLElement}
181
+ */static getHolder(n){return Q(n)?document.getElementById(n):n}
182
+ /**
183
+ * Returns true if element is anchor (is A tag)
184
+ *
185
+ * @param {Element} element - element to check
186
+ * @returns {boolean}
187
+ */static isAnchor(n){return n.tagName.toLowerCase()==="a"}
188
+ /**
189
+ * Return element's offset related to the document
190
+ *
191
+ * @todo handle case when editor initialized in scrollable popup
192
+ * @param el - element to compute offset
193
+ */static offset(n){const h=n.getBoundingClientRect(),p=window.pageXOffset||document.documentElement.scrollLeft,g=window.pageYOffset||document.documentElement.scrollTop,m=h.top+g,v=h.left+p;return{top:m,left:v,bottom:m+h.height,right:v+h.width}}}function Lo(n){return!/[^\t\n\r ]/.test(n)}function _o(n){const h=window.getComputedStyle(n),p=parseFloat(h.fontSize),g=parseFloat(h.lineHeight)||p*1.2,m=parseFloat(h.paddingTop),v=parseFloat(h.borderTopWidth),x=parseFloat(h.marginTop),w=p*.8,E=(g-p)/2;return x+v+m+E+w}function Lt(n){n.dataset.empty=d.isEmpty(n)?"true":"false"}const w={blockTunes:{toggler:{"Click to tune":"","or drag to move":""}},inlineToolbar:{converter:{"Convert to":""}},toolbar:{toolbox:{Add:""}},popover:{Filter:"","Nothing found":"","Convert to":""}},E={Text:"",Link:"",Bold:"",Italic:""},B={link:{"Add a link":""},stub:{"The block can not be displayed correctly.":""}},T={delete:{Delete:"","Click to delete":""},moveUp:{"Move up":""},moveDown:{"Move down":""}},I={ui:w,toolNames:E,tools:B,blockTunes:T},M=class ae{
194
+ /**
195
+ * Type-safe translation for internal UI texts:
196
+ * Perform translation of the string by namespace and a key
197
+ *
198
+ * @example I18n.ui(I18nInternalNS.ui.blockTunes.toggler, 'Click to tune')
199
+ * @param internalNamespace - path to translated string in dictionary
200
+ * @param dictKey - dictionary key. Better to use default locale original text
201
+ */
202
+ static ui(n,h){return ae._t(n,h)}
203
+ /**
204
+ * Translate for external strings that is not presented in default dictionary.
205
+ * For example, for user-specified tool names
206
+ *
207
+ * @param namespace - path to translated string in dictionary
208
+ * @param dictKey - dictionary key. Better to use default locale original text
209
+ */static t(n,h){return ae._t(n,h)}
210
+ /**
211
+ * Adjust module for using external dictionary
212
+ *
213
+ * @param dictionary - new messages list to override default
214
+ */static setDictionary(n){ae.currentDictionary=n}
215
+ /**
216
+ * Perform translation both for internal and external namespaces
217
+ * If there is no translation found, returns passed key as a translated message
218
+ *
219
+ * @param namespace - path to translated string in dictionary
220
+ * @param dictKey - dictionary key. Better to use default locale original text
221
+ */static _t(n,h){const p=ae.getNamespace(n);return p&&p[h]?p[h]:h}
222
+ /**
223
+ * Find messages section by namespace path
224
+ *
225
+ * @param namespace - path to section
226
+ */static getNamespace(n){return n.split(".").reduce(((n,h)=>n&&Object.keys(n).length?n[h]:{}),ae.currentDictionary)}};M.currentDictionary=I;let A=M;class Pt extends Error{}class Te{constructor(){this.subscribers={}}
227
+ /**
228
+ * Subscribe any event on callback
229
+ *
230
+ * @param eventName - event name
231
+ * @param callback - subscriber
232
+ */on(n,h){n in this.subscribers||(this.subscribers[n]=[]),this.subscribers[n].push(h)
233
+ /**
234
+ * Subscribe any event on callback. Callback will be called once and be removed from subscribers array after call.
235
+ *
236
+ * @param eventName - event name
237
+ * @param callback - subscriber
238
+ */}once(n,h){n in this.subscribers||(this.subscribers[n]=[]);const o=p=>{const g=h(p),m=this.subscribers[n].indexOf(o);return m!==-1&&this.subscribers[n].splice(m,1),g};this.subscribers[n].push(o)}
239
+ /**
240
+ * Emit callbacks with passed data
241
+ *
242
+ * @param eventName - event name
243
+ * @param data - subscribers get this data when they were fired
244
+ */emit(n,h){V(this.subscribers)||!this.subscribers[n]||this.subscribers[n].reduce(((n,h)=>{const p=h(n);return p!==void 0?p:n}),h)}
245
+ /**
246
+ * Unsubscribe callback from event
247
+ *
248
+ * @param eventName - event name
249
+ * @param callback - event handler
250
+ */off(n,h){if(this.subscribers[n]!==void 0){for(let p=0;p<this.subscribers[n].length;p++)if(this.subscribers[n][p]===h){delete this.subscribers[n][p];break}}else console.warn(`EventDispatcher .off(): there is no subscribers for event "${n.toString()}". Probably, .off() called before .on()`)}destroy(){this.subscribers={}}}function G(n){Object.setPrototypeOf(this,{
251
+ /**
252
+ * Block id
253
+ *
254
+ * @returns {string}
255
+ */
256
+ get id(){return n.id},
257
+ /**
258
+ * Tool name
259
+ *
260
+ * @returns {string}
261
+ */
262
+ get name(){return n.name},
263
+ /**
264
+ * Tool config passed on Editor's initialization
265
+ *
266
+ * @returns {ToolConfig}
267
+ */
268
+ get config(){return n.config},
269
+ /**
270
+ * .ce-block element, that wraps plugin contents
271
+ *
272
+ * @returns {HTMLElement}
273
+ */
274
+ get holder(){return n.holder},
275
+ /**
276
+ * True if Block content is empty
277
+ *
278
+ * @returns {boolean}
279
+ */
280
+ get isEmpty(){return n.isEmpty},
281
+ /**
282
+ * True if Block is selected with Cross-Block selection
283
+ *
284
+ * @returns {boolean}
285
+ */
286
+ get selected(){return n.selected},
287
+ /**
288
+ * Set Block's stretch state
289
+ *
290
+ * @param {boolean} state — state to set
291
+ */
292
+ set stretched(h){n.stretched=h},
293
+ /**
294
+ * True if Block is stretched
295
+ *
296
+ * @returns {boolean}
297
+ */
298
+ get stretched(){return n.stretched},get focusable(){return n.focusable},
299
+ /**
300
+ * Call Tool method with errors handler under-the-hood
301
+ *
302
+ * @param {string} methodName - method to call
303
+ * @param {object} param - object with parameters
304
+ * @returns {unknown}
305
+ */
306
+ call(h,p){return n.call(h,p)},
307
+ /**
308
+ * Save Block content
309
+ *
310
+ * @returns {Promise<void|SavedData>}
311
+ */
312
+ save(){return n.save()},
313
+ /**
314
+ * Validate Block data
315
+ *
316
+ * @param {BlockToolData} data - data to validate
317
+ * @returns {Promise<boolean>}
318
+ */
319
+ validate(h){return n.validate(h)},dispatchChange(){n.dispatchChange()},getActiveToolboxEntry(){return n.getActiveToolboxEntry()}})}class Ce{constructor(){this.allListeners=[]}
320
+ /**
321
+ * Assigns event listener on element and returns unique identifier
322
+ *
323
+ * @param {EventTarget} element - DOM element that needs to be listened
324
+ * @param {string} eventType - event type
325
+ * @param {Function} handler - method that will be fired on event
326
+ * @param {boolean|AddEventListenerOptions} options - useCapture or {capture, passive, once}
327
+ */on(n,h,p,g=!1){const m=Ao("l"),v={id:m,element:n,eventType:h,handler:p,options:g};if(!this.findOne(n,h,p))return this.allListeners.push(v),n.addEventListener(h,p,g),m
328
+ /**
329
+ * Removes event listener from element
330
+ *
331
+ * @param {EventTarget} element - DOM element that we removing listener
332
+ * @param {string} eventType - event type
333
+ * @param {Function} handler - remove handler, if element listens several handlers on the same event type
334
+ * @param {boolean|AddEventListenerOptions} options - useCapture or {capture, passive, once}
335
+ */}off(n,h,p,g){const m=this.findAll(n,h,p);m.forEach(((n,h)=>{const p=this.allListeners.indexOf(m[h]);p>-1&&(this.allListeners.splice(p,1),n.element.removeEventListener(n.eventType,n.handler,n.options))}))}
336
+ /**
337
+ * Removes listener by id
338
+ *
339
+ * @param {string} id - listener identifier
340
+ */offById(n){const h=this.findById(n);h&&h.element.removeEventListener(h.eventType,h.handler,h.options)}
341
+ /**
342
+ * Finds and returns first listener by passed params
343
+ *
344
+ * @param {EventTarget} element - event target
345
+ * @param {string} [eventType] - event type
346
+ * @param {Function} [handler] - event handler
347
+ * @returns {ListenerData|null}
348
+ */findOne(n,h,p){const g=this.findAll(n,h,p);return g.length>0?g[0]:null}
349
+ /**
350
+ * Return all stored listeners by passed params
351
+ *
352
+ * @param {EventTarget} element - event target
353
+ * @param {string} eventType - event type
354
+ * @param {Function} handler - event handler
355
+ * @returns {ListenerData[]}
356
+ */findAll(n,h,p){let g;const m=n?this.findByEventTarget(n):[];return g=n&&h&&p?m.filter((n=>n.eventType===h&&n.handler===p)):n&&h?m.filter((n=>n.eventType===h)):m,g}removeAll(){this.allListeners.map((n=>{n.element.removeEventListener(n.eventType,n.handler,n.options)})),this.allListeners=[]}destroy(){this.removeAll()}
357
+ /**
358
+ * Search method: looks for listener by passed element
359
+ *
360
+ * @param {EventTarget} element - searching element
361
+ * @returns {Array} listeners that found on element
362
+ */findByEventTarget(n){return this.allListeners.filter((h=>{if(h.element===n)return h}))}
363
+ /**
364
+ * Search method: looks for listener by passed event type
365
+ *
366
+ * @param {string} eventType - event type
367
+ * @returns {ListenerData[]} listeners that found on element
368
+ */findByType(n){return this.allListeners.filter((h=>{if(h.eventType===n)return h}))}
369
+ /**
370
+ * Search method: looks for listener by passed handler
371
+ *
372
+ * @param {Function} handler - event handler
373
+ * @returns {ListenerData[]} listeners that found on element
374
+ */findByHandler(n){return this.allListeners.filter((h=>{if(h.handler===n)return h}))}
375
+ /**
376
+ * Returns listener data found by id
377
+ *
378
+ * @param {string} id - listener identifier
379
+ * @returns {ListenerData}
380
+ */findById(n){return this.allListeners.find((h=>h.id===n))}}class y{
381
+ /**
382
+ * @class
383
+ * @param options - Module options
384
+ * @param options.config - Module config
385
+ * @param options.eventsDispatcher - Common event bus
386
+ */
387
+ constructor({config:n,eventsDispatcher:h}){if(this.nodes={},this.listeners=new Ce,this.readOnlyMutableListeners={
388
+ /**
389
+ * Assigns event listener on DOM element and pushes into special array that might be removed
390
+ *
391
+ * @param {EventTarget} element - DOM Element
392
+ * @param {string} eventType - Event name
393
+ * @param {Function} handler - Event handler
394
+ * @param {boolean|AddEventListenerOptions} options - Listening options
395
+ */
396
+ on:(n,h,p,g=!1)=>{this.mutableListenerIds.push(this.listeners.on(n,h,p,g))},clearAll:()=>{for(const n of this.mutableListenerIds)this.listeners.offById(n);this.mutableListenerIds=[]}},this.mutableListenerIds=[],new.target===y)throw new TypeError("Constructors for abstract class Module are not allowed.");this.config=n,this.eventsDispatcher=h
397
+ /**
398
+ * Editor modules setter
399
+ *
400
+ * @param {EditorModules} Editor - Editor's Modules
401
+ */}set state(n){this.Editor=n}removeAllNodes(){for(const n in this.nodes){const h=this.nodes[n];h instanceof HTMLElement&&h.remove()}}get isRtl(){return this.config.i18n.direction==="rtl"}}class b{constructor(){this.instance=null,this.selection=null,this.savedSelectionRange=null,this.isFakeBackgroundEnabled=!1,this.commandBackground="backColor",this.commandRemoveFormat="removeFormat"
402
+ /**
403
+ * Editor styles
404
+ *
405
+ * @returns {{editorWrapper: string, editorZone: string}}
406
+ */}static get CSS(){return{editorWrapper:"codex-editor",editorZone:"codex-editor__redactor"}}
407
+ /**
408
+ * Returns selected anchor
409
+ * {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorNode}
410
+ *
411
+ * @returns {Node|null}
412
+ */static get anchorNode(){const n=window.getSelection();return n?n.anchorNode:null}
413
+ /**
414
+ * Returns selected anchor element
415
+ *
416
+ * @returns {Element|null}
417
+ */static get anchorElement(){const n=window.getSelection();if(!n)return null;const h=n.anchorNode;return h?d.isElement(h)?h:h.parentElement:null}
418
+ /**
419
+ * Returns selection offset according to the anchor node
420
+ * {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorOffset}
421
+ *
422
+ * @returns {number|null}
423
+ */static get anchorOffset(){const n=window.getSelection();return n?n.anchorOffset:null}
424
+ /**
425
+ * Is current selection range collapsed
426
+ *
427
+ * @returns {boolean|null}
428
+ */static get isCollapsed(){const n=window.getSelection();return n?n.isCollapsed:null}
429
+ /**
430
+ * Check current selection if it is at Editor's zone
431
+ *
432
+ * @returns {boolean}
433
+ */static get isAtEditor(){return this.isSelectionAtEditor(b.get())}
434
+ /**
435
+ * Check if passed selection is at Editor's zone
436
+ *
437
+ * @param selection - Selection object to check
438
+ */static isSelectionAtEditor(n){if(!n)return!1;let h=n.anchorNode||n.focusNode;h&&h.nodeType===Node.TEXT_NODE&&(h=h.parentNode);let p=null;return h&&h instanceof Element&&(p=h.closest(`.${b.CSS.editorZone}`)),!!p&&p.nodeType===Node.ELEMENT_NODE
439
+ /**
440
+ * Check if passed range at Editor zone
441
+ *
442
+ * @param range - range to check
443
+ */}static isRangeAtEditor(n){if(!n)return;let h=n.startContainer;h&&h.nodeType===Node.TEXT_NODE&&(h=h.parentNode);let p=null;return h&&h instanceof Element&&(p=h.closest(`.${b.CSS.editorZone}`)),!!p&&p.nodeType===Node.ELEMENT_NODE}static get isSelectionExists(){return!!b.get().anchorNode}
444
+ /**
445
+ * Return first range
446
+ *
447
+ * @returns {Range|null}
448
+ */static get range(){return this.getRangeFromSelection(this.get())}
449
+ /**
450
+ * Returns range from passed Selection object
451
+ *
452
+ * @param selection - Selection object to get Range from
453
+ */static getRangeFromSelection(n){return n&&n.rangeCount?n.getRangeAt(0):null}
454
+ /**
455
+ * Calculates position and size of selected text
456
+ *
457
+ * @returns {DOMRect | ClientRect}
458
+ */static get rect(){let n,h=document.selection,p={x:0,y:0,width:0,height:0};if(h&&h.type!=="Control")return h,n=h.createRange(),p.x=n.boundingLeft,p.y=n.boundingTop,p.width=n.boundingWidth,p.height=n.boundingHeight,p;if(!window.getSelection)return g("Method window.getSelection is not supported","warn"),p;if(h=window.getSelection(),h.rangeCount===null||isNaN(h.rangeCount))return g("Method SelectionUtils.rangeCount is not supported","warn"),p;if(h.rangeCount===0)return p;if(n=h.getRangeAt(0).cloneRange(),n.getBoundingClientRect&&(p=n.getBoundingClientRect()),p.x===0&&p.y===0){const h=document.createElement("span");if(h.getBoundingClientRect){h.appendChild(document.createTextNode("​")),n.insertNode(h),p=h.getBoundingClientRect();const g=h.parentNode;g.removeChild(h),g.normalize()}}return p}
459
+ /**
460
+ * Returns selected text as String
461
+ *
462
+ * @returns {string}
463
+ */static get text(){return window.getSelection?window.getSelection().toString():""}
464
+ /**
465
+ * Returns window SelectionUtils
466
+ * {@link https://developer.mozilla.org/ru/docs/Web/API/Window/getSelection}
467
+ *
468
+ * @returns {Selection}
469
+ */static get(){return window.getSelection()}
470
+ /**
471
+ * Set focus to contenteditable or native input element
472
+ *
473
+ * @param element - element where to set focus
474
+ * @param offset - offset of cursor
475
+ */static setCursor(n,h=0){const p=document.createRange(),g=window.getSelection();return d.isNativeInput(n)?d.canSetCaret(n)?(n.focus(),n.selectionStart=n.selectionEnd=h,n.getBoundingClientRect()):void 0:(p.setStart(n,h),p.setEnd(n,h),g.removeAllRanges(),g.addRange(p),p.getBoundingClientRect()
476
+ /**
477
+ * Check if current range exists and belongs to container
478
+ *
479
+ * @param container - where range should be
480
+ */)}static isRangeInsideContainer(n){const h=b.range;return h!==null&&n.contains(h.startContainer)}static addFakeCursor(){const n=b.range;if(n===null)return;const h=d.make("span","codex-editor__fake-cursor");h.dataset.mutationFree="true",n.collapse(),n.insertNode(h)
481
+ /**
482
+ * Check if passed element contains a fake cursor
483
+ *
484
+ * @param el - where to check
485
+ */}static isFakeCursorInsideContainer(n){return d.find(n,".codex-editor__fake-cursor")!==null}
486
+ /**
487
+ * Removes fake cursor from a container
488
+ *
489
+ * @param container - container to look for
490
+ */static removeFakeCursor(n=document.body){const h=d.find(n,".codex-editor__fake-cursor");h&&h.remove()}removeFakeBackground(){this.isFakeBackgroundEnabled&&(this.isFakeBackgroundEnabled=!1,document.execCommand(this.commandRemoveFormat))}setFakeBackground(){document.execCommand(this.commandBackground,!1,"#a8d6ff"),this.isFakeBackgroundEnabled=!0}save(){this.savedSelectionRange=b.range}restore(){if(!this.savedSelectionRange)return;const n=window.getSelection();n.removeAllRanges(),n.addRange(this.savedSelectionRange)}clearSaved(){this.savedSelectionRange=null}collapseToEnd(){const n=window.getSelection(),h=document.createRange();h.selectNodeContents(n.focusNode),h.collapse(!1),n.removeAllRanges(),n.addRange(h)
491
+ /**
492
+ * Looks ahead to find passed tag from current selection
493
+ *
494
+ * @param {string} tagName - tag to found
495
+ * @param {string} [className] - tag's class name
496
+ * @param {number} [searchDepth] - count of tags that can be included. For better performance.
497
+ * @returns {HTMLElement|null}
498
+ */}findParentTag(n,h,p=10){const g=window.getSelection();let m=null;return g&&g.anchorNode&&g.focusNode?([g.anchorNode,g.focusNode].forEach((g=>{let v=p;for(;v>0&&g.parentNode&&!(g.tagName===n&&(m=g,h&&g.classList&&!g.classList.contains(h)&&(m=null),m));)g=g.parentNode,v--})),m
499
+ /**
500
+ * Expands selection range to the passed parent node
501
+ *
502
+ * @param {HTMLElement} element - element which contents should be selected
503
+ */):null}expandToTag(n){const h=window.getSelection();h.removeAllRanges();const p=document.createRange();p.selectNodeContents(n),h.addRange(p)}}function Fo(n,h){const{type:p,target:g,addedNodes:m,removedNodes:v}=n;return(n.type!=="attributes"||n.attributeName!=="data-empty")&&!!(h.contains(g)||p==="childList"&&(Array.from(m).some((n=>n===h))||Array.from(v).some((n=>n===h))))}const L="redactor dom changed",N="block changed",P="fake cursor is about to be toggled",H="fake cursor have been set",z="editor mobile layout toggled";function Qe(n,h){if(!n.conversionConfig)return!1;const p=n.conversionConfig[h];return O(p)||Q(p)}function _e(n,h){return Qe(n.tool,h)}function Ht(n,h){return Object.entries(n).some((([n,p])=>h[n]&&Oo(h[n],p)))}async function zt(n,h){const p=(await n.save()).data,g=h.find((h=>h.name===n.name));return g===void 0||Qe(g,"export")?h.reduce(((h,g)=>{if(!Qe(g,"import")||g.toolbox===void 0)return h;const m=g.toolbox.filter((h=>{if(V(h)||h.icon===void 0)return!1;if(h.data!==void 0){if(Ht(h.data,p))return!1}else if(g.name===n.name)return!1;return!0}));return h.push({...g,toolbox:m}),h}),[]):[]}function wt(n,h){return!!n.mergeable&&(n.name===h.name||_e(h,"export")&&_e(n,"import"))}function Ho(n,h){const p=h==null?void 0:h.export;return O(p)?p(n):Q(p)?n[p]:(p!==void 0&&g("Conversion «export» property must be a string or function. String means key of saved data object to export. Function should export processed string to export."),"")}function xt(n,h){const p=h==null?void 0:h.import;return O(p)?p(n):Q(p)?{[p]:n}:(p!==void 0&&g("Conversion «import» property must be a string or function. String means key of tool data to import. Function accepts a imported string and return composed tool data."),{})}var U=(n=>(n.Default="default",n.Separator="separator",n.Html="html",n))(U||{}),$=(n=>(n.APPEND_CALLBACK="appendCallback",n.RENDERED="rendered",n.MOVED="moved",n.UPDATED="updated",n.REMOVED="removed",n.ON_PASTE="onPaste",n))($||{});class D extends Te{
504
+ /**
505
+ * @param options - block constructor options
506
+ * @param [options.id] - block's id. Will be generated if omitted.
507
+ * @param options.data - Tool's initial data
508
+ * @param options.tool — block's tool
509
+ * @param options.api - Editor API module for pass it to the Block Tunes
510
+ * @param options.readOnly - Read-Only flag
511
+ * @param [eventBus] - Editor common event bus. Allows to subscribe on some Editor events. Could be omitted when "virtual" Block is created. See BlocksAPI@composeBlockData.
512
+ */
513
+ constructor({id:n=Io(),data:h,tool:p,readOnly:g,tunesData:m},v){super(),this.cachedInputs=[],this.toolRenderedElement=null,this.tunesInstances=new Map,this.defaultTunesInstances=new Map,this.unavailableTunesData={},this.inputIndex=0,this.editorEventBus=null,this.handleFocus=()=>{this.dropInputsCache(),this.updateCurrentInput()},this.didMutated=(n=void 0)=>{const h=n===void 0,p=n instanceof InputEvent;!h&&!p&&this.detectToolRootChange(n);let g;g=!(!h&&!p)||!(n.length>0&&n.every((n=>{const{addedNodes:h,removedNodes:p,target:g}=n;return[...Array.from(h),...Array.from(p),g].some((n=>(d.isElement(n)||(n=n.parentElement),n&&n.closest('[data-mutation-free="true"]')!==null)))}))),g&&(this.dropInputsCache(),this.updateCurrentInput(),this.toggleInputsEmptyMark(),this.call("updated"),this.emit("didMutated",this))},this.name=p.name,this.id=n,this.settings=p.settings,this.config=p.settings.config||{},this.editorEventBus=v||null,this.blockAPI=new G(this),this.tool=p,this.toolInstance=p.create(h,this.blockAPI,g),this.tunes=p.tunes,this.composeTunes(m),this.holder=this.compose(),window.requestIdleCallback((()=>{this.watchBlockMutations(),this.addInputEvents(),this.toggleInputsEmptyMark()}))
514
+ /**
515
+ * CSS classes for the Block
516
+ *
517
+ * @returns {{wrapper: string, content: string}}
518
+ */}static get CSS(){return{wrapper:"ce-block",wrapperStretched:"ce-block--stretched",content:"ce-block__content",selected:"ce-block--selected",dropTarget:"ce-block--drop-target"}}get inputs(){if(this.cachedInputs.length!==0)return this.cachedInputs;const n=d.findAllInputs(this.holder);return this.inputIndex>n.length-1&&(this.inputIndex=n.length-1),this.cachedInputs=n,n}get currentInput(){return this.inputs[this.inputIndex]}
519
+ /**
520
+ * Set input index to the passed element
521
+ *
522
+ * @param element - HTML Element to set as current input
523
+ */set currentInput(n){const h=this.inputs.findIndex((h=>h===n||h.contains(n)));h!==-1&&(this.inputIndex=h)}get firstInput(){return this.inputs[0]}get lastInput(){const n=this.inputs;return n[n.length-1]}get nextInput(){return this.inputs[this.inputIndex+1]}get previousInput(){return this.inputs[this.inputIndex-1]}
524
+ /**
525
+ * Get Block's JSON data
526
+ *
527
+ * @returns {object}
528
+ */get data(){return this.save().then((n=>n&&!V(n.data)?n.data:{}))}
529
+ /**
530
+ * Returns tool's sanitizer config
531
+ *
532
+ * @returns {object}
533
+ */get sanitize(){return this.tool.sanitizeConfig}
534
+ /**
535
+ * is block mergeable
536
+ * We plugin have merge function then we call it mergeable
537
+ *
538
+ * @returns {boolean}
539
+ */get mergeable(){return O(this.toolInstance.merge)}get focusable(){return this.inputs.length!==0}
540
+ /**
541
+ * Check block for emptiness
542
+ *
543
+ * @returns {boolean}
544
+ */get isEmpty(){const n=d.isEmpty(this.pluginsContent,"/"),h=!this.hasMedia;return n&&h}
545
+ /**
546
+ * Check if block has a media content such as images, iframe and other
547
+ *
548
+ * @returns {boolean}
549
+ */get hasMedia(){const n=["img","iframe","video","audio","source","input","textarea","twitterwidget"];return!!this.holder.querySelector(n.join(","))}
550
+ /**
551
+ * Set selected state
552
+ * We don't need to mark Block as Selected when it is empty
553
+ *
554
+ * @param {boolean} state - 'true' to select, 'false' to remove selection
555
+ */set selected(n){var h,p;this.holder.classList.toggle(D.CSS.selected,n);const g=n===!0&&b.isRangeInsideContainer(this.holder),m=n===!1&&b.isFakeCursorInsideContainer(this.holder);(g||m)&&((h=this.editorEventBus)==null||h.emit(P,{state:n}),g?b.addFakeCursor():b.removeFakeCursor(this.holder),(p=this.editorEventBus)==null||p.emit(H,{state:n})
556
+ /**
557
+ * Returns True if it is Selected
558
+ *
559
+ * @returns {boolean}
560
+ */)}get selected(){return this.holder.classList.contains(D.CSS.selected)}
561
+ /**
562
+ * Set stretched state
563
+ *
564
+ * @param {boolean} state - 'true' to enable, 'false' to disable stretched state
565
+ */set stretched(n){this.holder.classList.toggle(D.CSS.wrapperStretched,n)}
566
+ /**
567
+ * Return Block's stretched state
568
+ *
569
+ * @returns {boolean}
570
+ */get stretched(){return this.holder.classList.contains(D.CSS.wrapperStretched)}
571
+ /**
572
+ * Toggle drop target state
573
+ *
574
+ * @param {boolean} state - 'true' if block is drop target, false otherwise
575
+ */set dropTarget(n){this.holder.classList.toggle(D.CSS.dropTarget,n)}
576
+ /**
577
+ * Returns Plugins content
578
+ *
579
+ * @returns {HTMLElement}
580
+ */get pluginsContent(){return this.toolRenderedElement}
581
+ /**
582
+ * Calls Tool's method
583
+ *
584
+ * Method checks tool property {MethodName}. Fires method with passes params If it is instance of Function
585
+ *
586
+ * @param {string} methodName - method to call
587
+ * @param {object} params - method argument
588
+ */call(n,h){if(O(this.toolInstance[n])){n==="appendCallback"&&g("`appendCallback` hook is deprecated and will be removed in the next major release. Use `rendered` hook instead","warn");try{this.toolInstance[n].call(this.toolInstance,h)}catch(h){g(`Error during '${n}' call: ${h.message}`,"error")}}}
589
+ /**
590
+ * Call plugins merge method
591
+ *
592
+ * @param {BlockToolData} data - data to merge
593
+ */async mergeWith(n){await this.toolInstance.merge(n)}
594
+ /**
595
+ * Extracts data from Block
596
+ * Groups Tool's save processing time
597
+ *
598
+ * @returns {object}
599
+ */async save(){const n=await this.toolInstance.save(this.pluginsContent),h=this.unavailableTunesData;[...this.tunesInstances.entries(),...this.defaultTunesInstances.entries()].forEach((([n,p])=>{if(O(p.save))try{h[n]=p.save()}catch(n){g(`Tune ${p.constructor.name} save method throws an Error %o`,"warn",n)}}));const p=window.performance.now();let m;return Promise.resolve(n).then((n=>(m=window.performance.now(),{id:this.id,tool:this.name,data:n,tunes:h,time:m-p}))).catch((n=>{g(`Saving process for ${this.name} tool failed due to the ${n}`,"log","red")}))}
600
+ /**
601
+ * Uses Tool's validation method to check the correctness of output data
602
+ * Tool's validation method is optional
603
+ *
604
+ * @description Method returns true|false whether data passed the validation or not
605
+ * @param {BlockToolData} data - data to validate
606
+ * @returns {Promise<boolean>} valid
607
+ */async validate(n){let h=!0;return this.toolInstance.validate instanceof Function&&(h=await this.toolInstance.validate(n)),h}getTunes(){const n=[],h=[],p=typeof this.toolInstance.renderSettings=="function"?this.toolInstance.renderSettings():[];return d.isElement(p)?n.push({type:U.Html,element:p}):Array.isArray(p)?n.push(...p):n.push(p),[...this.tunesInstances.values(),...this.defaultTunesInstances.values()].map((n=>n.render())).forEach((n=>{d.isElement(n)?h.push({type:U.Html,element:n}):Array.isArray(n)?h.push(...n):h.push(n)})),{toolTunes:n,commonTunes:h}}updateCurrentInput(){this.currentInput=d.isNativeInput(document.activeElement)||!b.anchorNode?document.activeElement:b.anchorNode}dispatchChange(){this.didMutated()}destroy(){this.unwatchBlockMutations(),this.removeInputEvents(),super.destroy(),O(this.toolInstance.destroy)&&this.toolInstance.destroy()}async getActiveToolboxEntry(){const n=this.tool.toolbox;if(n.length===1)return Promise.resolve(this.tool.toolbox[0]);const h=await this.data,p=n;return p==null?void 0:p.find((n=>Ht(n.data,h)))}async exportDataAsString(){const n=await this.data;return Ho(n,this.tool.conversionConfig)}
608
+ /**
609
+ * Make default Block wrappers and put Tool`s content there
610
+ *
611
+ * @returns {HTMLDivElement}
612
+ */compose(){const n=d.make("div",D.CSS.wrapper),h=d.make("div",D.CSS.content),p=this.toolInstance.render();n.dataset.id=this.id,this.toolRenderedElement=p,h.appendChild(this.toolRenderedElement);let m=h;return[...this.tunesInstances.values(),...this.defaultTunesInstances.values()].forEach((n=>{if(O(n.wrap))try{m=n.wrap(m)}catch(h){g(`Tune ${n.constructor.name} wrap method throws an Error %o`,"warn",h)}})),n.appendChild(m),n
613
+ /**
614
+ * Instantiate Block Tunes
615
+ *
616
+ * @param tunesData - current Block tunes data
617
+ * @private
618
+ */}composeTunes(n){Array.from(this.tunes.values()).forEach((h=>{(h.isInternal?this.defaultTunesInstances:this.tunesInstances).set(h.name,h.create(n[h.name],this.blockAPI))})),Object.entries(n).forEach((([n,h])=>{this.tunesInstances.has(n)||(this.unavailableTunesData[n]=h)}))}addInputEvents(){this.inputs.forEach((n=>{n.addEventListener("focus",this.handleFocus),d.isNativeInput(n)&&n.addEventListener("input",this.didMutated)}))}removeInputEvents(){this.inputs.forEach((n=>{n.removeEventListener("focus",this.handleFocus),d.isNativeInput(n)&&n.removeEventListener("input",this.didMutated)}))}watchBlockMutations(){var n;this.redactorDomChangedCallback=n=>{const{mutations:h}=n;h.some((n=>Fo(n,this.toolRenderedElement)))&&this.didMutated(h)},(n=this.editorEventBus)==null||n.on(L,this.redactorDomChangedCallback)}unwatchBlockMutations(){var n;(n=this.editorEventBus)==null||n.off(L,this.redactorDomChangedCallback)}
619
+ /**
620
+ * Sometimes Tool can replace own main element, for example H2 -> H4 or UL -> OL
621
+ * We need to detect such changes and update a link to tools main element with the new one
622
+ *
623
+ * @param mutations - records of block content mutations
624
+ */detectToolRootChange(n){n.forEach((n=>{if(Array.from(n.removedNodes).includes(this.toolRenderedElement)){const h=n.addedNodes[n.addedNodes.length-1];this.toolRenderedElement=h}}))}dropInputsCache(){this.cachedInputs=[]}toggleInputsEmptyMark(){this.inputs.forEach(Lt)}}class zo extends y{constructor(){super(...arguments),this.insert=(n=this.config.defaultBlock,h={},p={},g,m,v,x)=>{const w=this.Editor.BlockManager.insert({id:x,tool:n,data:h,index:g,needToFocus:m,replace:v});return new G(w)},this.composeBlockData=async n=>{const h=this.Editor.Tools.blockTools.get(n);return new D({tool:h,api:this.Editor.API,readOnly:!0,data:{},tunesData:{}}).data},this.update=async(n,h,p)=>{const{BlockManager:g}=this.Editor,m=g.getBlockById(n);if(m===void 0)throw new Error(`Block with id "${n}" not found`);const v=await g.update(m,h,p);return new G(v)},this.convert=async(n,h,p)=>{var g,m;const{BlockManager:v,Tools:x}=this.Editor,w=v.getBlockById(n);if(!w)throw new Error(`Block with id "${n}" not found`);const E=x.blockTools.get(w.name),B=x.blockTools.get(h);if(!B)throw new Error(`Block Tool with type "${h}" not found`);const T=((g=E==null?void 0:E.conversionConfig)==null?void 0:g.export)!==void 0,I=((m=B.conversionConfig)==null?void 0:m.import)!==void 0;if(T&&I){const n=await v.convert(w,h,p);return new G(n)}{const n=[!T&&Le(w.name),!I&&Le(h)].filter(Boolean).join(" and ");throw new Error(`Conversion from "${w.name}" to "${h}" is not possible. ${n} tool(s) should provide a "conversionConfig"`)}},this.insertMany=(n,h=this.Editor.BlockManager.blocks.length-1)=>{this.validateIndex(h);const p=n.map((({id:n,type:h,data:p})=>this.Editor.BlockManager.composeBlock({id:n,tool:h||this.config.defaultBlock,data:p})));return this.Editor.BlockManager.insertMany(p,h),p.map((n=>new G(n)))}
625
+ /**
626
+ * Available methods
627
+ *
628
+ * @returns {Blocks}
629
+ */}get methods(){return{clear:()=>this.clear(),render:n=>this.render(n),renderFromHTML:n=>this.renderFromHTML(n),delete:n=>this.delete(n),swap:(n,h)=>this.swap(n,h),move:(n,h)=>this.move(n,h),getBlockByIndex:n=>this.getBlockByIndex(n),getById:n=>this.getById(n),getCurrentBlockIndex:()=>this.getCurrentBlockIndex(),getBlockIndex:n=>this.getBlockIndex(n),getBlocksCount:()=>this.getBlocksCount(),getBlockByElement:n=>this.getBlockByElement(n),stretchBlock:(n,h=!0)=>this.stretchBlock(n,h),insertNewBlock:()=>this.insertNewBlock(),insert:this.insert,insertMany:this.insertMany,update:this.update,composeBlockData:this.composeBlockData,convert:this.convert}}
630
+ /**
631
+ * Returns Blocks count
632
+ *
633
+ * @returns {number}
634
+ */getBlocksCount(){return this.Editor.BlockManager.blocks.length}
635
+ /**
636
+ * Returns current block index
637
+ *
638
+ * @returns {number}
639
+ */getCurrentBlockIndex(){return this.Editor.BlockManager.currentBlockIndex}
640
+ /**
641
+ * Returns the index of Block by id;
642
+ *
643
+ * @param id - block id
644
+ */getBlockIndex(n){const h=this.Editor.BlockManager.getBlockById(n);if(h)return this.Editor.BlockManager.getBlockIndex(h);m("There is no block with id `"+n+"`","warn")}
645
+ /**
646
+ * Returns BlockAPI object by Block index
647
+ *
648
+ * @param {number} index - index to get
649
+ */getBlockByIndex(n){const h=this.Editor.BlockManager.getBlockByIndex(n);if(h!==void 0)return new G(h);m("There is no block at index `"+n+"`","warn")}
650
+ /**
651
+ * Returns BlockAPI object by Block id
652
+ *
653
+ * @param id - id of block to get
654
+ */getById(n){const h=this.Editor.BlockManager.getBlockById(n);return h===void 0?(m("There is no block with id `"+n+"`","warn"),null):new G(h)}
655
+ /**
656
+ * Get Block API object by any child html element
657
+ *
658
+ * @param element - html element to get Block by
659
+ */getBlockByElement(n){const h=this.Editor.BlockManager.getBlock(n);if(h!==void 0)return new G(h);m("There is no block corresponding to element `"+n+"`","warn")}
660
+ /**
661
+ * Call Block Manager method that swap Blocks
662
+ *
663
+ * @param {number} fromIndex - position of first Block
664
+ * @param {number} toIndex - position of second Block
665
+ * @deprecated — use 'move' instead
666
+ */swap(n,h){g("`blocks.swap()` method is deprecated and will be removed in the next major release. Use `block.move()` method instead","info"),this.Editor.BlockManager.swap(n,h)
667
+ /**
668
+ * Move block from one index to another
669
+ *
670
+ * @param {number} toIndex - index to move to
671
+ * @param {number} fromIndex - index to move from
672
+ */}move(n,h){this.Editor.BlockManager.move(n,h)}
673
+ /**
674
+ * Deletes Block
675
+ *
676
+ * @param {number} blockIndex - index of Block to delete
677
+ */delete(n=this.Editor.BlockManager.currentBlockIndex){try{const h=this.Editor.BlockManager.getBlockByIndex(n);this.Editor.BlockManager.removeBlock(h)}catch(n){m(n,"warn");return}this.Editor.BlockManager.blocks.length===0&&this.Editor.BlockManager.insert(),this.Editor.BlockManager.currentBlock&&this.Editor.Caret.setToBlock(this.Editor.BlockManager.currentBlock,this.Editor.Caret.positions.END),this.Editor.Toolbar.close()}async clear(){await this.Editor.BlockManager.clear(!0),this.Editor.InlineToolbar.close()
678
+ /**
679
+ * Fills Editor with Blocks data
680
+ *
681
+ * @param {OutputData} data — Saved Editor data
682
+ */}async render(n){if(n===void 0||n.blocks===void 0)throw new Error("Incorrect data passed to the render() method");this.Editor.ModificationsObserver.disable(),await this.Editor.BlockManager.clear(),await this.Editor.Renderer.render(n.blocks),this.Editor.ModificationsObserver.enable()
683
+ /**
684
+ * Render passed HTML string
685
+ *
686
+ * @param {string} data - HTML string to render
687
+ * @returns {Promise<void>}
688
+ */}renderFromHTML(n){return this.Editor.BlockManager.clear(),this.Editor.Paste.processText(n,!0)
689
+ /**
690
+ * Stretch Block's content
691
+ *
692
+ * @param {number} index - index of Block to stretch
693
+ * @param {boolean} status - true to enable, false to disable
694
+ * @deprecated Use BlockAPI interface to stretch Blocks
695
+ */}stretchBlock(n,h=!0){Ze(!0,"blocks.stretchBlock()","BlockAPI");const p=this.Editor.BlockManager.getBlockByIndex(n);p&&(p.stretched=h)}
696
+ /**
697
+ * Insert new Block
698
+ * After set caret to this Block
699
+ *
700
+ * @todo remove in 3.0.0
701
+ * @deprecated with insert() method
702
+ */insertNewBlock(){g("Method blocks.insertNewBlock() is deprecated and it will be removed in the next major release. Use blocks.insert() instead.","warn"),this.insert()
703
+ /**
704
+ * Validated block index and throws an error if it's invalid
705
+ *
706
+ * @param index - index to validate
707
+ */}validateIndex(n){if(typeof n!="number")throw new Error("Index should be a number");if(n<0)throw new Error("Index should be greater than or equal to 0");if(n===null)throw new Error("Index should be greater than or equal to 0")}}function Uo(n,h){return typeof n=="number"?h.BlockManager.getBlockByIndex(n):typeof n=="string"?h.BlockManager.getBlockById(n):h.BlockManager.getBlockById(n.id)}class jo extends y{constructor(){super(...arguments),this.setToFirstBlock=(n=this.Editor.Caret.positions.DEFAULT,h=0)=>!!this.Editor.BlockManager.firstBlock&&(this.Editor.Caret.setToBlock(this.Editor.BlockManager.firstBlock,n,h),!0),this.setToLastBlock=(n=this.Editor.Caret.positions.DEFAULT,h=0)=>!!this.Editor.BlockManager.lastBlock&&(this.Editor.Caret.setToBlock(this.Editor.BlockManager.lastBlock,n,h),!0),this.setToPreviousBlock=(n=this.Editor.Caret.positions.DEFAULT,h=0)=>!!this.Editor.BlockManager.previousBlock&&(this.Editor.Caret.setToBlock(this.Editor.BlockManager.previousBlock,n,h),!0),this.setToNextBlock=(n=this.Editor.Caret.positions.DEFAULT,h=0)=>!!this.Editor.BlockManager.nextBlock&&(this.Editor.Caret.setToBlock(this.Editor.BlockManager.nextBlock,n,h),!0),this.setToBlock=(n,h=this.Editor.Caret.positions.DEFAULT,p=0)=>{const g=Uo(n,this.Editor);return g!==void 0&&(this.Editor.Caret.setToBlock(g,h,p),!0)},this.focus=(n=!1)=>n?this.setToLastBlock(this.Editor.Caret.positions.END):this.setToFirstBlock(this.Editor.Caret.positions.START)
708
+ /**
709
+ * Available methods
710
+ *
711
+ * @returns {Caret}
712
+ */}get methods(){return{setToFirstBlock:this.setToFirstBlock,setToLastBlock:this.setToLastBlock,setToPreviousBlock:this.setToPreviousBlock,setToNextBlock:this.setToNextBlock,setToBlock:this.setToBlock,focus:this.focus}}}class $o extends y{
713
+ /**
714
+ * Available methods
715
+ *
716
+ * @returns {Events}
717
+ */
718
+ get methods(){return{emit:(n,h)=>this.emit(n,h),off:(n,h)=>this.off(n,h),on:(n,h)=>this.on(n,h)}}
719
+ /**
720
+ * Subscribe on Events
721
+ *
722
+ * @param {string} eventName - event name to subscribe
723
+ * @param {Function} callback - event handler
724
+ */on(n,h){this.eventsDispatcher.on(n,h)}
725
+ /**
726
+ * Emit event with data
727
+ *
728
+ * @param {string} eventName - event to emit
729
+ * @param {object} data - event's data
730
+ */emit(n,h){this.eventsDispatcher.emit(n,h)}
731
+ /**
732
+ * Unsubscribe from Event
733
+ *
734
+ * @param {string} eventName - event to unsubscribe
735
+ * @param {Function} callback - event handler
736
+ */off(n,h){this.eventsDispatcher.off(n,h)}}class ot extends y{
737
+ /**
738
+ * Return namespace section for tool or block tune
739
+ *
740
+ * @param toolName - tool name
741
+ * @param isTune - is tool a block tune
742
+ */
743
+ static getNamespace(n,h){return h?`blockTunes.${n}`:`tools.${n}`}get methods(){return{t:()=>{m("I18n.t() method can be accessed only from Tools","warn")}}}
744
+ /**
745
+ * Return I18n API methods with tool namespaced dictionary
746
+ *
747
+ * @param toolName - tool name
748
+ * @param isTune - is tool a block tune
749
+ */getMethodsForTool(n,h){return Object.assign(this.methods,{t:p=>A.t(ot.getNamespace(n,h),p)})}}class Yo extends y{get methods(){return{blocks:this.Editor.BlocksAPI.methods,caret:this.Editor.CaretAPI.methods,tools:this.Editor.ToolsAPI.methods,events:this.Editor.EventsAPI.methods,listeners:this.Editor.ListenersAPI.methods,notifier:this.Editor.NotifierAPI.methods,sanitizer:this.Editor.SanitizerAPI.methods,saver:this.Editor.SaverAPI.methods,selection:this.Editor.SelectionAPI.methods,styles:this.Editor.StylesAPI.classes,toolbar:this.Editor.ToolbarAPI.methods,inlineToolbar:this.Editor.InlineToolbarAPI.methods,tooltip:this.Editor.TooltipAPI.methods,i18n:this.Editor.I18nAPI.methods,readOnly:this.Editor.ReadOnlyAPI.methods,ui:this.Editor.UiAPI.methods}}
750
+ /**
751
+ * Returns Editor.js Core API methods for passed tool
752
+ *
753
+ * @param toolName - tool name
754
+ * @param isTune - is tool a block tune
755
+ */getMethodsForTool(n,h){return Object.assign(this.methods,{i18n:this.Editor.I18nAPI.getMethodsForTool(n,h)})}}class Wo extends y{
756
+ /**
757
+ * Available methods
758
+ *
759
+ * @returns {InlineToolbar}
760
+ */
761
+ get methods(){return{close:()=>this.close(),open:()=>this.open()}}open(){this.Editor.InlineToolbar.tryToShow()}close(){this.Editor.InlineToolbar.close()}}class Ko extends y{
762
+ /**
763
+ * Available methods
764
+ *
765
+ * @returns {Listeners}
766
+ */
767
+ get methods(){return{on:(n,h,p,g)=>this.on(n,h,p,g),off:(n,h,p,g)=>this.off(n,h,p,g),offById:n=>this.offById(n)}}
768
+ /**
769
+ * Ads a DOM event listener. Return it's id.
770
+ *
771
+ * @param {HTMLElement} element - Element to set handler to
772
+ * @param {string} eventType - event type
773
+ * @param {() => void} handler - event handler
774
+ * @param {boolean} useCapture - capture event or not
775
+ */on(n,h,p,g){return this.listeners.on(n,h,p,g)}
776
+ /**
777
+ * Removes DOM listener from element
778
+ *
779
+ * @param {Element} element - Element to remove handler from
780
+ * @param eventType - event type
781
+ * @param handler - event handler
782
+ * @param {boolean} useCapture - capture event or not
783
+ */off(n,h,p,g){this.listeners.off(n,h,p,g)}
784
+ /**
785
+ * Removes DOM listener by the listener id
786
+ *
787
+ * @param id - id of the listener to remove
788
+ */offById(n){this.listeners.offById(n)}}var Y={exports:{}};(function(n,h){(function(h,p){n.exports=p()})(window,(function(){return function(n){var h={};function i(p){if(h[p])return h[p].exports;var g=h[p]={i:p,l:!1,exports:{}};return n[p].call(g.exports,g,g.exports,i),g.l=!0,g.exports}return i.m=n,i.c=h,i.d=function(n,h,p){i.o(n,h)||Object.defineProperty(n,h,{enumerable:!0,get:p})},i.r=function(n){typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,h){if(1&h&&(n=i(n)),8&h||4&h&&typeof n=="object"&&n&&n.__esModule)return n;var p=Object.create(null);if(i.r(p),Object.defineProperty(p,"default",{enumerable:!0,value:n}),2&h&&typeof n!="string")for(var g in n)i.d(p,g,function(h){return n[h]}.bind(null,g));return p},i.n=function(n){var h=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(h,"a",h),h},i.o=function(n,h){return Object.prototype.hasOwnProperty.call(n,h)},i.p="/",i(i.s=0)}([function(n,h,p){p(1),n.exports=function(){var n=p(6),h="cdx-notify--bounce-in",g=null;return{show:function(p){if(p.message){(function(){if(g)return!0;g=n.getWrapper(),document.body.appendChild(g)})();var m=null,v=p.time||8e3;switch(p.type){case"confirm":m=n.confirm(p);break;case"prompt":m=n.prompt(p);break;default:m=n.alert(p),window.setTimeout((function(){m.remove()}),v)}g.appendChild(m),m.classList.add(h)}}}}()},function(n,h,p){var g=p(2);typeof g=="string"&&(g=[[n.i,g,""]]);var m={hmr:!0,transform:void 0,insertInto:void 0};p(4)(g,m),g.locals&&(n.exports=g.locals)},function(n,h,p){(n.exports=p(3)(!1)).push([n.i,'.cdx-notify--error{background:#fffbfb!important}.cdx-notify--error::before{background:#fb5d5d!important}.cdx-notify__input{max-width:130px;padding:5px 10px;background:#f7f7f7;border:0;border-radius:3px;font-size:13px;color:#656b7c;outline:0}.cdx-notify__input:-ms-input-placeholder{color:#656b7c}.cdx-notify__input::placeholder{color:#656b7c}.cdx-notify__input:focus:-ms-input-placeholder{color:rgba(101,107,124,.3)}.cdx-notify__input:focus::placeholder{color:rgba(101,107,124,.3)}.cdx-notify__button{border:none;border-radius:3px;font-size:13px;padding:5px 10px;cursor:pointer}.cdx-notify__button:last-child{margin-left:10px}.cdx-notify__button--cancel{background:#f2f5f7;box-shadow:0 2px 1px 0 rgba(16,19,29,0);color:#656b7c}.cdx-notify__button--cancel:hover{background:#eee}.cdx-notify__button--confirm{background:#34c992;box-shadow:0 1px 1px 0 rgba(18,49,35,.05);color:#fff}.cdx-notify__button--confirm:hover{background:#33b082}.cdx-notify__btns-wrapper{display:-ms-flexbox;display:flex;-ms-flex-flow:row nowrap;flex-flow:row nowrap;margin-top:5px}.cdx-notify__cross{position:absolute;top:5px;right:5px;width:10px;height:10px;padding:5px;opacity:.54;cursor:pointer}.cdx-notify__cross::after,.cdx-notify__cross::before{content:\'\';position:absolute;left:9px;top:5px;height:12px;width:2px;background:#575d67}.cdx-notify__cross::before{transform:rotate(-45deg)}.cdx-notify__cross::after{transform:rotate(45deg)}.cdx-notify__cross:hover{opacity:1}.cdx-notifies{position:fixed;z-index:2;bottom:20px;left:20px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",sans-serif}.cdx-notify{position:relative;width:220px;margin-top:15px;padding:13px 16px;background:#fff;box-shadow:0 11px 17px 0 rgba(23,32,61,.13);border-radius:5px;font-size:14px;line-height:1.4em;word-wrap:break-word}.cdx-notify::before{content:\'\';position:absolute;display:block;top:0;left:0;width:3px;height:calc(100% - 6px);margin:3px;border-radius:5px;background:0 0}@keyframes bounceIn{0%{opacity:0;transform:scale(.3)}50%{opacity:1;transform:scale(1.05)}70%{transform:scale(.9)}100%{transform:scale(1)}}.cdx-notify--bounce-in{animation-name:bounceIn;animation-duration:.6s;animation-iteration-count:1}.cdx-notify--success{background:#fafffe!important}.cdx-notify--success::before{background:#41ffb1!important}',""])},function(n,h){n.exports=function(n){var h=[];return h.toString=function(){return this.map((function(h){var p=function(n,h){var p=n[1]||"",g=n[3];if(!g)return p;if(h&&typeof btoa=="function"){var m=(x=g,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(x))))+" */"),v=g.sources.map((function(n){return"/*# sourceURL="+g.sourceRoot+n+" */"}));return[p].concat(v).concat([m]).join("\n")}var x;return[p].join("\n")}(h,n);return h[2]?"@media "+h[2]+"{"+p+"}":p})).join("")},h.i=function(n,p){typeof n=="string"&&(n=[[null,n,""]]);for(var g={},m=0;m<this.length;m++){var v=this[m][0];typeof v=="number"&&(g[v]=!0)}for(m=0;m<n.length;m++){var x=n[m];typeof x[0]=="number"&&g[x[0]]||(p&&!x[2]?x[2]=p:p&&(x[2]="("+x[2]+") and ("+p+")"),h.push(x))}},h}},function(n,h,p){var g,m,v={},x=(g=function(){return window&&document&&document.all&&!window.atob},function(){return m===void 0&&(m=g.apply(this,arguments)),m}),w=function(n){var h={};return function(n){if(typeof n=="function")return n();if(h[n]===void 0){var p=function(n){return document.querySelector(n)}.call(this,n);if(window.HTMLIFrameElement&&p instanceof window.HTMLIFrameElement)try{p=p.contentDocument.head}catch{p=null}h[n]=p}return h[n]}}(),E=null,B=0,T=[],I=p(5);function f(n,h){for(var p=0;p<n.length;p++){var g=n[p],m=v[g.id];if(m){m.refs++;for(var x=0;x<m.parts.length;x++)m.parts[x](g.parts[x]);for(;x<g.parts.length;x++)m.parts.push(j(g.parts[x],h))}else{var w=[];for(x=0;x<g.parts.length;x++)w.push(j(g.parts[x],h));v[g.id]={id:g.id,refs:1,parts:w}}}}function k(n,h){for(var p=[],g={},m=0;m<n.length;m++){var v=n[m],x=h.base?v[0]+h.base:v[0],w={css:v[1],media:v[2],sourceMap:v[3]};g[x]?g[x].parts.push(w):p.push(g[x]={id:x,parts:[w]})}return p}function C(n,h){var p=w(n.insertInto);if(!p)throw new Error("Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid.");var g=T[T.length-1];if(n.insertAt==="top")g?g.nextSibling?p.insertBefore(h,g.nextSibling):p.appendChild(h):p.insertBefore(h,p.firstChild),T.push(h);else if(n.insertAt==="bottom")p.appendChild(h);else{if(typeof n.insertAt!="object"||!n.insertAt.before)throw new Error("[Style Loader]\n\n Invalid value for parameter 'insertAt' ('options.insertAt') found.\n Must be 'top', 'bottom', or Object.\n (https://github.com/webpack-contrib/style-loader#insertat)\n");var m=w(n.insertInto+" "+n.insertAt.before);p.insertBefore(h,m)}}function S(n){if(n.parentNode===null)return!1;n.parentNode.removeChild(n);var h=T.indexOf(n);h>=0&&T.splice(h,1)}function _(n){var h=document.createElement("style");return n.attrs.type===void 0&&(n.attrs.type="text/css"),ee(h,n.attrs),C(n,h),h}function ee(n,h){Object.keys(h).forEach((function(p){n.setAttribute(p,h[p])}))}function j(n,h){var p,g,m,v;if(h.transform&&n.css){if(!(v=h.transform(n.css)))return function(){};n.css=v}if(h.singleton){var x=B++;p=E||(E=_(h)),g=fe.bind(null,p,x,!1),m=fe.bind(null,p,x,!0)}else n.sourceMap&&typeof URL=="function"&&typeof URL.createObjectURL=="function"&&typeof URL.revokeObjectURL=="function"&&typeof Blob=="function"&&typeof btoa=="function"?(p=function(n){var h=document.createElement("link");return n.attrs.type===void 0&&(n.attrs.type="text/css"),n.attrs.rel="stylesheet",ee(h,n.attrs),C(n,h),h}(h),g=function(n,h,p){var g=p.css,m=p.sourceMap,v=h.convertToAbsoluteUrls===void 0&&m;(h.convertToAbsoluteUrls||v)&&(g=I(g)),m&&(g+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(m))))+" */");var x=new Blob([g],{type:"text/css"}),w=n.href;n.href=URL.createObjectURL(x),w&&URL.revokeObjectURL(w)}.bind(null,p,h),m=function(){S(p),p.href&&URL.revokeObjectURL(p.href)}):(p=_(h),g=function(n,h){var p=h.css,g=h.media;if(g&&n.setAttribute("media",g),n.styleSheet)n.styleSheet.cssText=p;else{for(;n.firstChild;)n.removeChild(n.firstChild);n.appendChild(document.createTextNode(p))}}.bind(null,p),m=function(){S(p)});return g(n),function(h){if(h){if(h.css===n.css&&h.media===n.media&&h.sourceMap===n.sourceMap)return;g(n=h)}else m()}}n.exports=function(n,h){if(typeof DEBUG<"u"&&DEBUG&&typeof document!="object")throw new Error("The style-loader cannot be used in a non-browser environment");(h=h||{}).attrs=typeof h.attrs=="object"?h.attrs:{},h.singleton||typeof h.singleton=="boolean"||(h.singleton=x()),h.insertInto||(h.insertInto="head"),h.insertAt||(h.insertAt="bottom");var p=k(n,h);return f(p,h),function(n){for(var g=[],m=0;m<p.length;m++){var x=p[m];(w=v[x.id]).refs--,g.push(w)}for(n&&f(k(n,h),h),m=0;m<g.length;m++){var w;if((w=g[m]).refs===0){for(var E=0;E<w.parts.length;E++)w.parts[E]();delete v[w.id]}}}};var M,A=(M=[],function(n,h){return M[n]=h,M.filter(Boolean).join("\n")});function fe(n,h,p,g){var m=p?"":g.css;if(n.styleSheet)n.styleSheet.cssText=A(h,m);else{var v=document.createTextNode(m),x=n.childNodes;x[h]&&n.removeChild(x[h]),x.length?n.insertBefore(v,x[h]):n.appendChild(v)}}},function(n,h){n.exports=function(n){var h=typeof window<"u"&&window.location;if(!h)throw new Error("fixUrls requires window.location");if(!n||typeof n!="string")return n;var p=h.protocol+"//"+h.host,g=p+h.pathname.replace(/\/[^\/]*$/,"/");return n.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi,(function(n,h){var m,v=h.trim().replace(/^"(.*)"$/,(function(n,h){return h})).replace(/^'(.*)'$/,(function(n,h){return h}));return/^(#|data:|http:\/\/|https:\/\/|file:\/\/\/|\s*$)/i.test(v)?n:(m=v.indexOf("//")===0?v:v.indexOf("/")===0?p+v:g+v.replace(/^\.\//,""),"url("+JSON.stringify(m)+")")}))}},function(n,h,p){var g,m,v,x,w,E,B,T,I;n.exports=(g="cdx-notifies",m="cdx-notify",v="cdx-notify__cross",x="cdx-notify__button--confirm",w="cdx-notify__button--cancel",E="cdx-notify__input",B="cdx-notify__button",T="cdx-notify__btns-wrapper",{alert:I=function(n){var h=document.createElement("DIV"),p=document.createElement("DIV"),g=n.message,x=n.style;return h.classList.add(m),x&&h.classList.add(m+"--"+x),h.innerHTML=g,p.classList.add(v),p.addEventListener("click",h.remove.bind(h)),h.appendChild(p),h},confirm:function(n){var h=I(n),p=document.createElement("div"),g=document.createElement("button"),m=document.createElement("button"),E=h.querySelector("."+v),M=n.cancelHandler,A=n.okHandler;return p.classList.add(T),g.innerHTML=n.okText||"Confirm",m.innerHTML=n.cancelText||"Cancel",g.classList.add(B),m.classList.add(B),g.classList.add(x),m.classList.add(w),M&&typeof M=="function"&&(m.addEventListener("click",M),E.addEventListener("click",M)),A&&typeof A=="function"&&g.addEventListener("click",A),g.addEventListener("click",h.remove.bind(h)),m.addEventListener("click",h.remove.bind(h)),p.appendChild(g),p.appendChild(m),h.appendChild(p),h},prompt:function(n){var h=I(n),p=document.createElement("div"),g=document.createElement("button"),m=document.createElement("input"),w=h.querySelector("."+v),M=n.cancelHandler,A=n.okHandler;return p.classList.add(T),g.innerHTML=n.okText||"Ok",g.classList.add(B),g.classList.add(x),m.classList.add(E),n.placeholder&&m.setAttribute("placeholder",n.placeholder),n.default&&(m.value=n.default),n.inputType&&(m.type=n.inputType),M&&typeof M=="function"&&w.addEventListener("click",M),A&&typeof A=="function"&&g.addEventListener("click",(function(){A(m.value)})),g.addEventListener("click",h.remove.bind(h)),p.appendChild(m),p.appendChild(g),h.appendChild(p),h},getWrapper:function(){var n=document.createElement("DIV");return n.classList.add(g),n}})}])}))})(Y);var K=Y.exports;const W=Fe(K);class qo{
789
+ /**
790
+ * Show web notification
791
+ *
792
+ * @param {NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions} options - notification options
793
+ */
794
+ show(n){W.show(n)}}class Zo extends y{
795
+ /**
796
+ * @param moduleConfiguration - Module Configuration
797
+ * @param moduleConfiguration.config - Editor's config
798
+ * @param moduleConfiguration.eventsDispatcher - Editor's event dispatcher
799
+ */
800
+ constructor({config:n,eventsDispatcher:h}){super({config:n,eventsDispatcher:h}),this.notifier=new qo}get methods(){return{show:n=>this.show(n)}}
801
+ /**
802
+ * Show notification
803
+ *
804
+ * @param {NotifierOptions} options - message option
805
+ */show(n){return this.notifier.show(n)}}class Go extends y{get methods(){const e=()=>this.isEnabled;return{toggle:n=>this.toggle(n),get isEnabled(){return e()}}}
806
+ /**
807
+ * Set or toggle read-only state
808
+ *
809
+ * @param {boolean|undefined} state - set or toggle state
810
+ * @returns {boolean} current value
811
+ */toggle(n){return this.Editor.ReadOnly.toggle(n)}get isEnabled(){return this.Editor.ReadOnly.isEnabled}}var X={exports:{}};(function(n,h){(function(h,p){n.exports=p()})(0,(function(){function t(n){var h=n.tags,p=Object.keys(h),g=p.map((function(n){return typeof h[n]})).every((function(n){return n==="object"||n==="boolean"||n==="function"}));if(!g)throw new Error("The configuration was invalid");this.config=n}var n=["P","LI","TD","TH","DIV","H1","H2","H3","H4","H5","H6","PRE"];function i(h){return n.indexOf(h.nodeName)!==-1}var h=["A","B","STRONG","I","EM","SUB","SUP","U","STRIKE"];function r(n){return h.indexOf(n.nodeName)!==-1}t.prototype.clean=function(n){const h=document.implementation.createHTMLDocument(),p=h.createElement("div");return p.innerHTML=n,this._sanitize(h,p),p.innerHTML},t.prototype._sanitize=function(n,h){var p=l(n,h),g=p.firstChild();if(g)do{if(g.nodeType!==Node.TEXT_NODE){if(g.nodeType===Node.COMMENT_NODE){h.removeChild(g),this._sanitize(n,h);break}var m,v=r(g);v&&(m=Array.prototype.some.call(g.childNodes,i));var x=!!h.parentNode,w=i(h)&&i(g)&&x,E=g.nodeName.toLowerCase(),B=a(this.config,E,g),T=v&&m;if(T||c(g,B)||!this.config.keepNestedBlockElements&&w){if(!(g.nodeName==="SCRIPT"||g.nodeName==="STYLE"))for(;g.childNodes.length>0;)h.insertBefore(g.childNodes[0],g);h.removeChild(g),this._sanitize(n,h);break}for(var I=0;I<g.attributes.length;I+=1){var M=g.attributes[I];u(M,B,g)&&(g.removeAttribute(M.name),I-=1)}this._sanitize(n,g)}else if(g.data.trim()===""&&(g.previousElementSibling&&i(g.previousElementSibling)||g.nextElementSibling&&i(g.nextElementSibling))){h.removeChild(g),this._sanitize(n,h);break}}while(g=p.nextSibling())};function l(n,h){return n.createTreeWalker(h,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_COMMENT,null,!1)}function a(n,h,p){return typeof n.tags[h]=="function"?n.tags[h](p):n.tags[h]}function c(n,h){return typeof h>"u"||typeof h=="boolean"&&!h}function u(n,h,p){var g=n.name.toLowerCase();return h!==!0&&(typeof h[g]=="function"?!h[g](n.value,p):typeof h[g]>"u"||h[g]===!1||typeof h[g]=="string"&&h[g]!==n.value)}return t}))})(X);var Z=X.exports;const J=Fe(Z);function it(n,h){return n.map((n=>{const p=O(h)?h(n.tool):h;return V(p)||(n.data=st(n.data,p)),n}))}function q(n,h={}){const p={tags:h};return new J(p).clean(n)}function st(n,h){return Array.isArray(n)?ei(n,h):R(n)?ti(n,h):Q(n)?oi(n,h):n}function ei(n,h){return n.map((n=>st(n,h)))}function ti(n,h){const p={};for(const g in n){if(!Object.prototype.hasOwnProperty.call(n,g))continue;const m=n[g],v=ii(h[g])?h[g]:h;p[g]=st(m,v)}return p}function oi(n,h){return R(h)?q(n,h):h===!1?q(n,{}):n}function ii(n){return R(n)||yo(n)||O(n)}class si extends y{
812
+ /**
813
+ * Available methods
814
+ *
815
+ * @returns {SanitizerConfig}
816
+ */
817
+ get methods(){return{clean:(n,h)=>this.clean(n,h)}}
818
+ /**
819
+ * Perform sanitizing of a string
820
+ *
821
+ * @param {string} taintString - what to sanitize
822
+ * @param {SanitizerConfig} config - sanitizer config
823
+ * @returns {string}
824
+ */clean(n,h){return q(n,h)}}class ni extends y{
825
+ /**
826
+ * Available methods
827
+ *
828
+ * @returns {Saver}
829
+ */
830
+ get methods(){return{save:()=>this.save()}}
831
+ /**
832
+ * Return Editor's data
833
+ *
834
+ * @returns {OutputData}
835
+ */save(){const n="Editor's content can not be saved in read-only mode";return this.Editor.ReadOnly.isEnabled?(m(n,"warn"),Promise.reject(new Error(n))):this.Editor.Saver.save()}}class ri extends y{constructor(){super(...arguments),this.selectionUtils=new b
836
+ /**
837
+ * Available methods
838
+ *
839
+ * @returns {SelectionAPIInterface}
840
+ */}get methods(){return{findParentTag:(n,h)=>this.findParentTag(n,h),expandToTag:n=>this.expandToTag(n),save:()=>this.selectionUtils.save(),restore:()=>this.selectionUtils.restore(),setFakeBackground:()=>this.selectionUtils.setFakeBackground(),removeFakeBackground:()=>this.selectionUtils.removeFakeBackground()}}
841
+ /**
842
+ * Looks ahead from selection and find passed tag with class name
843
+ *
844
+ * @param {string} tagName - tag to find
845
+ * @param {string} className - tag's class name
846
+ * @returns {HTMLElement|null}
847
+ */findParentTag(n,h){return this.selectionUtils.findParentTag(n,h)}
848
+ /**
849
+ * Expand selection to passed tag
850
+ *
851
+ * @param {HTMLElement} node - tag that should contain selection
852
+ */expandToTag(n){this.selectionUtils.expandToTag(n)}}class li extends y{get methods(){return{getBlockTools:()=>Array.from(this.Editor.Tools.blockTools.values())}}}class ai extends y{get classes(){return{block:"cdx-block",inlineToolButton:"ce-inline-tool",inlineToolButtonActive:"ce-inline-tool--active",input:"cdx-input",loader:"cdx-loader",button:"cdx-button",settingsButton:"cdx-settings-button",settingsButtonActive:"cdx-settings-button--active"}}}class ci extends y{
853
+ /**
854
+ * Available methods
855
+ *
856
+ * @returns {Toolbar}
857
+ */
858
+ get methods(){return{close:()=>this.close(),open:()=>this.open(),toggleBlockSettings:n=>this.toggleBlockSettings(n),toggleToolbox:n=>this.toggleToolbox(n)}}open(){this.Editor.Toolbar.moveAndOpen()}close(){this.Editor.Toolbar.close()}
859
+ /**
860
+ * Toggles Block Setting of the current block
861
+ *
862
+ * @param {boolean} openingState — opening state of Block Setting
863
+ */toggleBlockSettings(n){this.Editor.BlockManager.currentBlockIndex!==-1?n??!this.Editor.BlockSettings.opened?(this.Editor.Toolbar.moveAndOpen(),this.Editor.BlockSettings.open()):this.Editor.BlockSettings.close():m("Could't toggle the Toolbar because there is no block selected ","warn")}
864
+ /**
865
+ * Open toolbox
866
+ *
867
+ * @param {boolean} openingState - Opening state of toolbox
868
+ */toggleToolbox(n){this.Editor.BlockManager.currentBlockIndex!==-1?n??!this.Editor.Toolbar.toolbox.opened?(this.Editor.Toolbar.moveAndOpen(),this.Editor.Toolbar.toolbox.open()):this.Editor.Toolbar.toolbox.close():m("Could't toggle the Toolbox because there is no block selected ","warn")}}var oe={exports:{}};(function(n,h){(function(h,p){n.exports=p()})(window,(function(){return function(n){var h={};function i(p){if(h[p])return h[p].exports;var g=h[p]={i:p,l:!1,exports:{}};return n[p].call(g.exports,g,g.exports,i),g.l=!0,g.exports}return i.m=n,i.c=h,i.d=function(n,h,p){i.o(n,h)||Object.defineProperty(n,h,{enumerable:!0,get:p})},i.r=function(n){typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,h){if(1&h&&(n=i(n)),8&h||4&h&&typeof n=="object"&&n&&n.__esModule)return n;var p=Object.create(null);if(i.r(p),Object.defineProperty(p,"default",{enumerable:!0,value:n}),2&h&&typeof n!="string")for(var g in n)i.d(p,g,function(h){return n[h]}.bind(null,g));return p},i.n=function(n){var h=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(h,"a",h),h},i.o=function(n,h){return Object.prototype.hasOwnProperty.call(n,h)},i.p="",i(i.s=0)}([function(n,h,p){n.exports=p(1)},function(n,h,p){p.r(h),p.d(h,"default",(function(){return s}));class s{constructor(){this.nodes={wrapper:null,content:null},this.showed=!1,this.offsetTop=10,this.offsetLeft=10,this.offsetRight=10,this.hidingDelay=0,this.handleWindowScroll=()=>{this.showed&&this.hide(!0)},this.loadStyles(),this.prepare(),window.addEventListener("scroll",this.handleWindowScroll,{passive:!0})}get CSS(){return{tooltip:"ct",tooltipContent:"ct__content",tooltipShown:"ct--shown",placement:{left:"ct--left",bottom:"ct--bottom",right:"ct--right",top:"ct--top"}}}show(n,h,p){this.nodes.wrapper||this.prepare(),this.hidingTimeout&&clearTimeout(this.hidingTimeout);const g=Object.assign({placement:"bottom",marginTop:0,marginLeft:0,marginRight:0,marginBottom:0,delay:70,hidingDelay:0},p);if(g.hidingDelay&&(this.hidingDelay=g.hidingDelay),this.nodes.content.innerHTML="",typeof h=="string")this.nodes.content.appendChild(document.createTextNode(h));else{if(!(h instanceof Node))throw Error("[CodeX Tooltip] Wrong type of «content» passed. It should be an instance of Node or String. But "+typeof h+" given.");this.nodes.content.appendChild(h)}switch(this.nodes.wrapper.classList.remove(...Object.values(this.CSS.placement)),g.placement){case"top":this.placeTop(n,g);break;case"left":this.placeLeft(n,g);break;case"right":this.placeRight(n,g);break;case"bottom":default:this.placeBottom(n,g)}g&&g.delay?this.showingTimeout=setTimeout((()=>{this.nodes.wrapper.classList.add(this.CSS.tooltipShown),this.showed=!0}),g.delay):(this.nodes.wrapper.classList.add(this.CSS.tooltipShown),this.showed=!0)}hide(n=!1){if(this.hidingDelay&&!n)return this.hidingTimeout&&clearTimeout(this.hidingTimeout),void(this.hidingTimeout=setTimeout((()=>{this.hide(!0)}),this.hidingDelay));this.nodes.wrapper.classList.remove(this.CSS.tooltipShown),this.showed=!1,this.showingTimeout&&clearTimeout(this.showingTimeout)}onHover(n,h,p){n.addEventListener("mouseenter",(()=>{this.show(n,h,p)})),n.addEventListener("mouseleave",(()=>{this.hide()}))}destroy(){this.nodes.wrapper.remove(),window.removeEventListener("scroll",this.handleWindowScroll)}prepare(){this.nodes.wrapper=this.make("div",this.CSS.tooltip),this.nodes.content=this.make("div",this.CSS.tooltipContent),this.append(this.nodes.wrapper,this.nodes.content),this.append(document.body,this.nodes.wrapper)}loadStyles(){const n="codex-tooltips-style";if(document.getElementById(n))return;const h=p(2),g=this.make("style",null,{textContent:h.toString(),id:n});this.prepend(document.head,g)}placeBottom(n,h){const p=n.getBoundingClientRect(),g=p.left+n.clientWidth/2-this.nodes.wrapper.offsetWidth/2,m=p.bottom+window.pageYOffset+this.offsetTop+h.marginTop;this.applyPlacement("bottom",g,m)}placeTop(n,h){const p=n.getBoundingClientRect(),g=p.left+n.clientWidth/2-this.nodes.wrapper.offsetWidth/2,m=p.top+window.pageYOffset-this.nodes.wrapper.clientHeight-this.offsetTop;this.applyPlacement("top",g,m)}placeLeft(n,h){const p=n.getBoundingClientRect(),g=p.left-this.nodes.wrapper.offsetWidth-this.offsetLeft-h.marginLeft,m=p.top+window.pageYOffset+n.clientHeight/2-this.nodes.wrapper.offsetHeight/2;this.applyPlacement("left",g,m)}placeRight(n,h){const p=n.getBoundingClientRect(),g=p.right+this.offsetRight+h.marginRight,m=p.top+window.pageYOffset+n.clientHeight/2-this.nodes.wrapper.offsetHeight/2;this.applyPlacement("right",g,m)}applyPlacement(n,h,p){this.nodes.wrapper.classList.add(this.CSS.placement[n]),this.nodes.wrapper.style.left=h+"px",this.nodes.wrapper.style.top=p+"px"}make(n,h=null,p={}){const g=document.createElement(n);Array.isArray(h)?g.classList.add(...h):h&&g.classList.add(h);for(const n in p)p.hasOwnProperty(n)&&(g[n]=p[n]);return g}append(n,h){Array.isArray(h)?h.forEach((h=>n.appendChild(h))):n.appendChild(h)}prepend(n,h){Array.isArray(h)?(h=h.reverse()).forEach((h=>n.prepend(h))):n.prepend(h)}}},function(n,h){n.exports='.ct{z-index:999;opacity:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none;-webkit-transition:opacity 50ms ease-in,-webkit-transform 70ms cubic-bezier(.215,.61,.355,1);transition:opacity 50ms ease-in,-webkit-transform 70ms cubic-bezier(.215,.61,.355,1);transition:opacity 50ms ease-in,transform 70ms cubic-bezier(.215,.61,.355,1);transition:opacity 50ms ease-in,transform 70ms cubic-bezier(.215,.61,.355,1),-webkit-transform 70ms cubic-bezier(.215,.61,.355,1);will-change:opacity,top,left;-webkit-box-shadow:0 8px 12px 0 rgba(29,32,43,.17),0 4px 5px -3px rgba(5,6,12,.49);box-shadow:0 8px 12px 0 rgba(29,32,43,.17),0 4px 5px -3px rgba(5,6,12,.49);border-radius:9px}.ct,.ct:before{position:absolute;top:0;left:0}.ct:before{content:"";bottom:0;right:0;background-color:#1d202b;z-index:-1;border-radius:4px}@supports(-webkit-mask-box-image:url("")){.ct:before{border-radius:0;-webkit-mask-box-image:url(\'data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M10.71 0h2.58c3.02 0 4.64.42 6.1 1.2a8.18 8.18 0 013.4 3.4C23.6 6.07 24 7.7 24 10.71v2.58c0 3.02-.42 4.64-1.2 6.1a8.18 8.18 0 01-3.4 3.4c-1.47.8-3.1 1.21-6.11 1.21H10.7c-3.02 0-4.64-.42-6.1-1.2a8.18 8.18 0 01-3.4-3.4C.4 17.93 0 16.3 0 13.29V10.7c0-3.02.42-4.64 1.2-6.1a8.18 8.18 0 013.4-3.4C6.07.4 7.7 0 10.71 0z"/></svg>\') 48% 41% 37.9% 53.3%}}@media (--mobile){.ct{display:none}}.ct__content{padding:6px 10px;color:#cdd1e0;font-size:12px;text-align:center;letter-spacing:.02em;line-height:1em}.ct:after{content:"";width:8px;height:8px;position:absolute;background-color:#1d202b;z-index:-1}.ct--bottom{-webkit-transform:translateY(5px);transform:translateY(5px)}.ct--bottom:after{top:-3px;left:50%;-webkit-transform:translateX(-50%) rotate(-45deg);transform:translateX(-50%) rotate(-45deg)}.ct--top{-webkit-transform:translateY(-5px);transform:translateY(-5px)}.ct--top:after{top:auto;bottom:-3px;left:50%;-webkit-transform:translateX(-50%) rotate(-45deg);transform:translateX(-50%) rotate(-45deg)}.ct--left{-webkit-transform:translateX(-5px);transform:translateX(-5px)}.ct--left:after{top:50%;left:auto;right:0;-webkit-transform:translate(41.6%,-50%) rotate(-45deg);transform:translate(41.6%,-50%) rotate(-45deg)}.ct--right{-webkit-transform:translateX(5px);transform:translateX(5px)}.ct--right:after{top:50%;left:0;-webkit-transform:translate(-41.6%,-50%) rotate(-45deg);transform:translate(-41.6%,-50%) rotate(-45deg)}.ct--shown{opacity:1;-webkit-transform:none;transform:none}'}]).default}))})(oe);var ie=oe.exports;const ne=Fe(ie);let ce=null;function nt(){ce||(ce=new ne)}function ui(n,h,p){nt(),ce==null||ce.show(n,h,p)}function Ne(n=!1){nt(),ce==null||ce.hide(n)}function Pe(n,h,p){nt(),ce==null||ce.onHover(n,h,p)}function pi(){ce==null||ce.destroy(),ce=null}class fi extends y{
869
+ /**
870
+ * @class
871
+ * @param moduleConfiguration - Module Configuration
872
+ * @param moduleConfiguration.config - Editor's config
873
+ * @param moduleConfiguration.eventsDispatcher - Editor's event dispatcher
874
+ */
875
+ constructor({config:n,eventsDispatcher:h}){super({config:n,eventsDispatcher:h})}get methods(){return{show:(n,h,p)=>this.show(n,h,p),hide:()=>this.hide(),onHover:(n,h,p)=>this.onHover(n,h,p)}}
876
+ /**
877
+ * Method show tooltip on element with passed HTML content
878
+ *
879
+ * @param {HTMLElement} element - element on which tooltip should be shown
880
+ * @param {TooltipContent} content - tooltip content
881
+ * @param {TooltipOptions} options - tooltip options
882
+ */show(n,h,p){ui(n,h,p)}hide(){Ne()}
883
+ /**
884
+ * Decorator for showing Tooltip by mouseenter/mouseleave
885
+ *
886
+ * @param {HTMLElement} element - element on which tooltip should be shown
887
+ * @param {TooltipContent} content - tooltip content
888
+ * @param {TooltipOptions} options - tooltip options
889
+ */onHover(n,h,p){Pe(n,h,p)}}class gi extends y{get methods(){return{nodes:this.editorNodes}}get editorNodes(){return{wrapper:this.Editor.UI.nodes.wrapper,redactor:this.Editor.UI.nodes.redactor}}}function Yt(n,h){const p={};return Object.entries(n).forEach((([n,g])=>{if(R(g)){const m=h?`${h}.${n}`:n;Object.values(g).every((n=>Q(n)))?p[n]=m:p[n]=Yt(g,m)}else p[n]=g})),p}const de=Yt(I);function mi(n,h){const p={};return Object.keys(n).forEach((g=>{const m=h[g];m!==void 0?p[m]=n[g]:p[g]=n[g]})),p}const he=class ve{
890
+ /**
891
+ * @param {HTMLElement[]} nodeList — the list of iterable HTML-items
892
+ * @param {string} focusedCssClass - user-provided CSS-class that will be set in flipping process
893
+ */
894
+ constructor(n,h){this.cursor=-1,this.items=[],this.items=n||[],this.focusedCssClass=h
895
+ /**
896
+ * Returns Focused button Node
897
+ *
898
+ * @returns {HTMLElement}
899
+ */}get currentItem(){return this.cursor===-1?null:this.items[this.cursor]}
900
+ /**
901
+ * Sets cursor to specified position
902
+ *
903
+ * @param cursorPosition - new cursor position
904
+ */setCursor(n){n<this.items.length&&n>=-1&&(this.dropCursor(),this.cursor=n,this.items[this.cursor].classList.add(this.focusedCssClass)
905
+ /**
906
+ * Sets items. Can be used when iterable items changed dynamically
907
+ *
908
+ * @param {HTMLElement[]} nodeList - nodes to iterate
909
+ */)}setItems(n){this.items=n}next(){this.cursor=this.leafNodesAndReturnIndex(ve.directions.RIGHT)}previous(){this.cursor=this.leafNodesAndReturnIndex(ve.directions.LEFT)}dropCursor(){this.cursor!==-1&&(this.items[this.cursor].classList.remove(this.focusedCssClass),this.cursor=-1
910
+ /**
911
+ * Leafs nodes inside the target list from active element
912
+ *
913
+ * @param {string} direction - leaf direction. Can be 'left' or 'right'
914
+ * @returns {number} index of focused node
915
+ */)}leafNodesAndReturnIndex(n){if(this.items.length===0)return this.cursor;let h=this.cursor;return h===-1?h=n===ve.directions.RIGHT?-1:0:this.items[h].classList.remove(this.focusedCssClass),h=n===ve.directions.RIGHT?(h+1)%this.items.length:(this.items.length+h-1)%this.items.length,d.canSetCaret(this.items[h])&&Oe((()=>b.setCursor(this.items[h])),50)(),this.items[h].classList.add(this.focusedCssClass),h}};he.directions={RIGHT:"right",LEFT:"left"};let ge=he;class le{
916
+ /**
917
+ * @param options - different constructing settings
918
+ */
919
+ constructor(n){this.iterator=null,this.activated=!1,this.flipCallbacks=[],this.onKeyDown=n=>{if(this.isEventReadyForHandling(n))switch(le.usedKeys.includes(n.keyCode)&&n.preventDefault(),n.keyCode){case h.TAB:this.handleTabPress(n);break;case h.LEFT:case h.UP:this.flipLeft();break;case h.RIGHT:case h.DOWN:this.flipRight();break;case h.ENTER:this.handleEnterPress(n);break}},this.iterator=new ge(n.items,n.focusedItemClass),this.activateCallback=n.activateCallback,this.allowedKeys=n.allowedKeys||le.usedKeys}get isActivated(){return this.activated}static get usedKeys(){return[h.TAB,h.LEFT,h.RIGHT,h.ENTER,h.UP,h.DOWN]}
920
+ /**
921
+ * Active tab/arrows handling by flipper
922
+ *
923
+ * @param items - Some modules (like, InlineToolbar, BlockSettings) might refresh buttons dynamically
924
+ * @param cursorPosition - index of the item that should be focused once flipper is activated
925
+ */activate(n,h){this.activated=!0,n&&this.iterator.setItems(n),h!==void 0&&this.iterator.setCursor(h),document.addEventListener("keydown",this.onKeyDown,!0)}deactivate(){this.activated=!1,this.dropCursor(),document.removeEventListener("keydown",this.onKeyDown)}focusFirst(){this.dropCursor(),this.flipRight()}flipLeft(){this.iterator.previous(),this.flipCallback()}flipRight(){this.iterator.next(),this.flipCallback()}hasFocus(){return!!this.iterator.currentItem}
926
+ /**
927
+ * Registeres function that should be executed on each navigation action
928
+ *
929
+ * @param cb - function to execute
930
+ */onFlip(n){this.flipCallbacks.push(n)}
931
+ /**
932
+ * Unregisteres function that is executed on each navigation action
933
+ *
934
+ * @param cb - function to stop executing
935
+ */removeOnFlip(n){this.flipCallbacks=this.flipCallbacks.filter((h=>h!==n))}dropCursor(){this.iterator.dropCursor()}
936
+ /**
937
+ * This function is fired before handling flipper keycodes
938
+ * The result of this function defines if it is need to be handled or not
939
+ *
940
+ * @param {KeyboardEvent} event - keydown keyboard event
941
+ * @returns {boolean}
942
+ */isEventReadyForHandling(n){return this.activated&&this.allowedKeys.includes(n.keyCode)}
943
+ /**
944
+ * When flipper is activated tab press will leaf the items
945
+ *
946
+ * @param {KeyboardEvent} event - tab keydown event
947
+ */handleTabPress(n){switch(n.shiftKey?ge.directions.LEFT:ge.directions.RIGHT){case ge.directions.RIGHT:this.flipRight();break;case ge.directions.LEFT:this.flipLeft();break}}
948
+ /**
949
+ * Enter press will click current item if flipper is activated
950
+ *
951
+ * @param {KeyboardEvent} event - enter keydown event
952
+ */handleEnterPress(n){this.activated&&(this.iterator.currentItem&&(n.stopPropagation(),n.preventDefault(),this.iterator.currentItem.click()),O(this.activateCallback)&&this.activateCallback(this.iterator.currentItem))}flipCallback(){this.iterator.currentItem&&this.iterator.currentItem.scrollIntoViewIfNeeded(),this.flipCallbacks.forEach((n=>n()))}}const me='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M9 12L9 7.1C9 7.04477 9.04477 7 9.1 7H10.4C11.5 7 14 7.1 14 9.5C14 9.5 14 12 11 12M9 12V16.8C9 16.9105 9.08954 17 9.2 17H12.5C14 17 15 16 15 14.5C15 11.7046 11 12 11 12M9 12H11"/></svg>',be='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M7 10L11.8586 14.8586C11.9367 14.9367 12.0633 14.9367 12.1414 14.8586L17 10"/></svg>',ke='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M14.5 17.5L9.64142 12.6414C9.56331 12.5633 9.56331 12.4367 9.64142 12.3586L14.5 7.5"/></svg>',ye='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M9.58284 17.5L14.4414 12.6414C14.5195 12.5633 14.5195 12.4367 14.4414 12.3586L9.58284 7.5"/></svg>',Se='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M7 15L11.8586 10.1414C11.9367 10.0633 12.0633 10.0633 12.1414 10.1414L17 15"/></svg>',Ie='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M8 8L12 12M12 12L16 16M12 12L16 8M12 12L8 16"/></svg>',De='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><circle cx="12" cy="12" r="4" stroke="currentColor" stroke-width="2"/></svg>',He='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M13.34 10C12.4223 12.7337 11 17 11 17"/><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M14.21 7H14.2"/></svg>',Ue='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M7.69998 12.6L7.67896 12.62C6.53993 13.7048 6.52012 15.5155 7.63516 16.625V16.625C8.72293 17.7073 10.4799 17.7102 11.5712 16.6314L13.0263 15.193C14.0703 14.1609 14.2141 12.525 13.3662 11.3266L13.22 11.12"/><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M16.22 11.12L16.3564 10.9805C17.2895 10.0265 17.3478 8.5207 16.4914 7.49733V7.49733C15.5691 6.39509 13.9269 6.25143 12.8271 7.17675L11.3901 8.38588C10.0935 9.47674 9.95706 11.4241 11.0888 12.6852L11.12 12.72"/></svg>',je='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2.6" d="M9.40999 7.29999H9.4"/><path stroke="currentColor" stroke-linecap="round" stroke-width="2.6" d="M14.6 7.29999H14.59"/><path stroke="currentColor" stroke-linecap="round" stroke-width="2.6" d="M9.30999 12H9.3"/><path stroke="currentColor" stroke-linecap="round" stroke-width="2.6" d="M14.6 12H14.59"/><path stroke="currentColor" stroke-linecap="round" stroke-width="2.6" d="M9.40999 16.7H9.4"/><path stroke="currentColor" stroke-linecap="round" stroke-width="2.6" d="M14.6 16.7H14.59"/></svg>',$e='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M12 7V12M12 17V12M17 12H12M12 12H7"/></svg>',Ye='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M11.5 17.5L5 11M5 11V15.5M5 11H9.5"/><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M12.5 6.5L19 13M19 13V8.5M19 13H14.5"/></svg>',Ke='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><circle cx="10.5" cy="10.5" r="5.5" stroke="currentColor" stroke-width="2"/><line x1="15.4142" x2="19" y1="15" y2="18.5858" stroke="currentColor" stroke-linecap="round" stroke-width="2"/></svg>',We='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M15.7795 11.5C15.7795 11.5 16.053 11.1962 16.5497 10.6722C17.4442 9.72856 17.4701 8.2475 16.5781 7.30145V7.30145C15.6482 6.31522 14.0873 6.29227 13.1288 7.25073L11.8796 8.49999"/><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M8.24517 12.3883C8.24517 12.3883 7.97171 12.6922 7.47504 13.2161C6.58051 14.1598 6.55467 15.6408 7.44666 16.5869V16.5869C8.37653 17.5731 9.93744 17.5961 10.8959 16.6376L12.1452 15.3883"/><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M17.7802 15.1032L16.597 14.9422C16.0109 14.8624 15.4841 15.3059 15.4627 15.8969L15.4199 17.0818"/><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M6.39064 9.03238L7.58432 9.06668C8.17551 9.08366 8.6522 8.58665 8.61056 7.99669L8.5271 6.81397"/><line x1="12.1142" x2="11.7" y1="12.2" y2="11.7858" stroke="currentColor" stroke-linecap="round" stroke-width="2"/></svg>',Ge='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><rect width="14" height="14" x="5" y="5" stroke="currentColor" stroke-width="2" rx="4"/><line x1="12" x2="12" y1="9" y2="12" stroke="currentColor" stroke-linecap="round" stroke-width="2"/><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M12 15.02V15.01"/></svg>',Je="__",et="--";function te(n){return(h,p)=>[[n,h].filter((n=>!!n)).join(Je),p].filter((n=>!!n)).join(et)}const at=te("ce-hint"),lt={root:at(),alignedStart:at(null,"align-left"),alignedCenter:at(null,"align-center"),title:at("title"),description:at("description")};class Li{
953
+ /**
954
+ * Constructs the hint content instance
955
+ *
956
+ * @param params - hint content parameters
957
+ */
958
+ constructor(n){this.nodes={root:d.make("div",[lt.root,n.alignment==="center"?lt.alignedCenter:lt.alignedStart]),title:d.make("div",lt.title,{textContent:n.title})},this.nodes.root.appendChild(this.nodes.title),n.description!==void 0&&(this.nodes.description=d.make("div",lt.description,{textContent:n.description}),this.nodes.root.appendChild(this.nodes.description))}getElement(){return this.nodes.root}}class rt{
959
+ /**
960
+ * Constructs the instance
961
+ *
962
+ * @param params - instance parameters
963
+ */
964
+ constructor(n){this.params=n}get name(){if(this.params!==void 0&&"name"in this.params)return this.params.name}destroy(){Ne()}onChildrenOpen(){var n;this.params!==void 0&&"children"in this.params&&typeof((n=this.params.children)==null?void 0:n.onOpen)=="function"&&this.params.children.onOpen()}onChildrenClose(){var n;this.params!==void 0&&"children"in this.params&&typeof((n=this.params.children)==null?void 0:n.onClose)=="function"&&this.params.children.onClose()}handleClick(){var n,h;this.params!==void 0&&"onActivate"in this.params&&((h=(n=this.params).onActivate)==null||h.call(n,this.params))}
965
+ /**
966
+ * Adds hint to the item element if hint data is provided
967
+ *
968
+ * @param itemElement - popover item root element to add hint to
969
+ * @param hintData - hint data
970
+ */addHint(n,h){const p=new Li(h);Pe(n,p.getElement(),{placement:h.position,hidingDelay:100})}get children(){var n;return this.params!==void 0&&"children"in this.params&&((n=this.params.children)==null?void 0:n.items)!==void 0?this.params.children.items:[]}get hasChildren(){return this.children.length>0}get isChildrenOpen(){var n;return this.params!==void 0&&"children"in this.params&&((n=this.params.children)==null?void 0:n.isOpen)===!0}get isChildrenFlippable(){var n;return!(this.params===void 0||!("children"in this.params)||((n=this.params.children)==null?void 0:n.isFlippable)===!1)}get isChildrenSearchable(){var n;return this.params!==void 0&&"children"in this.params&&((n=this.params.children)==null?void 0:n.searchable)===!0}get closeOnActivate(){return this.params!==void 0&&"closeOnActivate"in this.params&&this.params.closeOnActivate}get isActive(){return this.params!==void 0&&"isActive"in this.params&&(typeof this.params.isActive=="function"?this.params.isActive():this.params.isActive===!0)}}const ct=te("ce-popover-item"),mt={container:ct(),active:ct(null,"active"),disabled:ct(null,"disabled"),focused:ct(null,"focused"),hidden:ct(null,"hidden"),confirmationState:ct(null,"confirmation"),noHover:ct(null,"no-hover"),noFocus:ct(null,"no-focus"),title:ct("title"),secondaryTitle:ct("secondary-title"),icon:ct("icon"),iconTool:ct("icon","tool"),iconChevronRight:ct("icon","chevron-right"),wobbleAnimation:te("wobble")()};class se extends rt{
971
+ /**
972
+ * Constructs popover item instance
973
+ *
974
+ * @param params - popover item construction params
975
+ * @param renderParams - popover item render params.
976
+ * The parameters that are not set by user via popover api but rather depend on technical implementation
977
+ */
978
+ constructor(n,h){super(n),this.params=n,this.nodes={root:null,icon:null},this.confirmationState=null,this.removeSpecialFocusBehavior=()=>{var n;(n=this.nodes.root)==null||n.classList.remove(mt.noFocus)},this.removeSpecialHoverBehavior=()=>{var n;(n=this.nodes.root)==null||n.classList.remove(mt.noHover)},this.onErrorAnimationEnd=()=>{var n,h;(n=this.nodes.icon)==null||n.classList.remove(mt.wobbleAnimation),(h=this.nodes.icon)==null||h.removeEventListener("animationend",this.onErrorAnimationEnd)},this.nodes.root=this.make(n,h)}get isDisabled(){return this.params.isDisabled===!0}get toggle(){return this.params.toggle}get title(){return this.params.title}get isConfirmationStateEnabled(){return this.confirmationState!==null}get isFocused(){return this.nodes.root!==null&&this.nodes.root.classList.contains(mt.focused)}getElement(){return this.nodes.root}handleClick(){this.isConfirmationStateEnabled&&this.confirmationState!==null?this.activateOrEnableConfirmationMode(this.confirmationState):this.activateOrEnableConfirmationMode(this.params)}
979
+ /**
980
+ * Toggles item active state
981
+ *
982
+ * @param isActive - true if item should strictly should become active
983
+ */toggleActive(n){var h;(h=this.nodes.root)==null||h.classList.toggle(mt.active,n)}
984
+ /**
985
+ * Toggles item hidden state
986
+ *
987
+ * @param isHidden - true if item should be hidden
988
+ */toggleHidden(n){var h;(h=this.nodes.root)==null||h.classList.toggle(mt.hidden,n)}reset(){this.isConfirmationStateEnabled&&this.disableConfirmationMode()}onFocus(){this.disableSpecialHoverAndFocusBehavior()}
989
+ /**
990
+ * Constructs HTML element corresponding to popover item params
991
+ *
992
+ * @param params - item construction params
993
+ * @param renderParams - popover item render params
994
+ */make(n,h){var p,g;const m=(h==null?void 0:h.wrapperTag)||"div",v=d.make(m,mt.container,{type:m==="button"?"button":void 0});return n.name&&(v.dataset.itemName=n.name),this.nodes.icon=d.make("div",[mt.icon,mt.iconTool],{innerHTML:n.icon||De}),v.appendChild(this.nodes.icon),n.title!==void 0&&v.appendChild(d.make("div",mt.title,{innerHTML:n.title||""})),n.secondaryLabel&&v.appendChild(d.make("div",mt.secondaryTitle,{textContent:n.secondaryLabel})),this.hasChildren&&v.appendChild(d.make("div",[mt.icon,mt.iconChevronRight],{innerHTML:ye})),this.isActive&&v.classList.add(mt.active),n.isDisabled&&v.classList.add(mt.disabled),n.hint!==void 0&&((p=h==null?void 0:h.hint)==null?void 0:p.enabled)!==!1&&this.addHint(v,{...n.hint,position:((g=h==null?void 0:h.hint)==null?void 0:g.position)||"right"}),v
995
+ /**
996
+ * Activates confirmation mode for the item.
997
+ *
998
+ * @param newState - new popover item params that should be applied
999
+ */}enableConfirmationMode(n){if(this.nodes.root===null)return;const h={...this.params,...n,confirmation:"confirmation"in n?n.confirmation:void 0},p=this.make(h);this.nodes.root.innerHTML=p.innerHTML,this.nodes.root.classList.add(mt.confirmationState),this.confirmationState=n,this.enableSpecialHoverAndFocusBehavior()}disableConfirmationMode(){if(this.nodes.root===null)return;const n=this.make(this.params);this.nodes.root.innerHTML=n.innerHTML,this.nodes.root.classList.remove(mt.confirmationState),this.confirmationState=null,this.disableSpecialHoverAndFocusBehavior()}enableSpecialHoverAndFocusBehavior(){var n,h,p;(n=this.nodes.root)==null||n.classList.add(mt.noHover),(h=this.nodes.root)==null||h.classList.add(mt.noFocus),(p=this.nodes.root)==null||p.addEventListener("mouseleave",this.removeSpecialHoverBehavior,{once:!0})}disableSpecialHoverAndFocusBehavior(){var n;this.removeSpecialFocusBehavior(),this.removeSpecialHoverBehavior(),(n=this.nodes.root)==null||n.removeEventListener("mouseleave",this.removeSpecialHoverBehavior)
1000
+ /**
1001
+ * Executes item's onActivate callback if the item has no confirmation configured
1002
+ *
1003
+ * @param item - item to activate or bring to confirmation mode
1004
+ */}activateOrEnableConfirmationMode(n){var h;if("confirmation"in n&&n.confirmation!==void 0)this.enableConfirmationMode(n.confirmation);else try{(h=n.onActivate)==null||h.call(n,n),this.disableConfirmationMode()}catch{this.animateError()}}animateError(){var n,h,p;(n=this.nodes.icon)!=null&&n.classList.contains(mt.wobbleAnimation)||((h=this.nodes.icon)==null||h.classList.add(mt.wobbleAnimation),(p=this.nodes.icon)==null||p.addEventListener("animationend",this.onErrorAnimationEnd))}}const yt=te("ce-popover-item-separator"),Et={container:yt(),line:yt("line"),hidden:yt(null,"hidden")};class Xt extends rt{constructor(){super(),this.nodes={root:d.make("div",Et.container),line:d.make("div",Et.line)},this.nodes.root.appendChild(this.nodes.line)}getElement(){return this.nodes.root}
1005
+ /**
1006
+ * Toggles item hidden state
1007
+ *
1008
+ * @param isHidden - true if item should be hidden
1009
+ */toggleHidden(n){var h;(h=this.nodes.root)==null||h.classList.toggle(Et.hidden,n)}}var Bt=(n=>(n.Closed="closed",n.ClosedOnActivate="closed-on-activate",n))(Bt||{});const Ct=te("ce-popover"),Tt={popover:Ct(),popoverContainer:Ct("container"),popoverOpenTop:Ct(null,"open-top"),popoverOpenLeft:Ct(null,"open-left"),popoverOpened:Ct(null,"opened"),search:Ct("search"),nothingFoundMessage:Ct("nothing-found-message"),nothingFoundMessageDisplayed:Ct("nothing-found-message","displayed"),items:Ct("items"),overlay:Ct("overlay"),overlayHidden:Ct("overlay","hidden"),popoverNested:Ct(null,"nested"),getPopoverNestedClass:n=>Ct(null,`nested-level-${n.toString()}`),popoverInline:Ct(null,"inline"),popoverHeader:Ct("header")};var St=(n=>(n.NestingLevel="--nesting-level",n.PopoverHeight="--popover-height",n.InlinePopoverWidth="--inline-popover-width",n.TriggerItemLeft="--trigger-item-left",n.TriggerItemTop="--trigger-item-top",n))(St||{});const It=te("ce-popover-item-html"),Ot={root:It(),hidden:It(null,"hidden")};class Ee extends rt{
1010
+ /**
1011
+ * Constructs the instance
1012
+ *
1013
+ * @param params – instance parameters
1014
+ * @param renderParams – popover item render params.
1015
+ * The parameters that are not set by user via popover api but rather depend on technical implementation
1016
+ */
1017
+ constructor(n,h){var p,g;super(n),this.nodes={root:d.make("div",Ot.root)},this.nodes.root.appendChild(n.element),n.name&&(this.nodes.root.dataset.itemName=n.name),n.hint!==void 0&&((p=h==null?void 0:h.hint)==null?void 0:p.enabled)!==!1&&this.addHint(this.nodes.root,{...n.hint,position:((g=h==null?void 0:h.hint)==null?void 0:g.position)||"right"})}getElement(){return this.nodes.root}
1018
+ /**
1019
+ * Toggles item hidden state
1020
+ *
1021
+ * @param isHidden - true if item should be hidden
1022
+ */toggleHidden(n){var h;(h=this.nodes.root)==null||h.classList.toggle(Ot.hidden,n)}getControls(){const n=this.nodes.root.querySelectorAll(`button, ${d.allInputsSelector}`);return Array.from(n)}}class Vt extends Te{
1023
+ /**
1024
+ * Constructs the instance
1025
+ *
1026
+ * @param params - popover construction params
1027
+ * @param itemsRenderParams - popover item render params.
1028
+ * The parameters that are not set by user via popover api but rather depend on technical implementation
1029
+ */
1030
+ constructor(n,h={}){super(),this.params=n,this.itemsRenderParams=h,this.listeners=new Ce,this.messages={nothingFound:"Nothing found",search:"Search"},this.items=this.buildItems(n.items),n.messages&&(this.messages={...this.messages,...n.messages}),this.nodes={},this.nodes.popoverContainer=d.make("div",[Tt.popoverContainer]),this.nodes.nothingFoundMessage=d.make("div",[Tt.nothingFoundMessage],{textContent:this.messages.nothingFound}),this.nodes.popoverContainer.appendChild(this.nodes.nothingFoundMessage),this.nodes.items=d.make("div",[Tt.items]),this.items.forEach((n=>{const h=n.getElement();h!==null&&this.nodes.items.appendChild(h)})),this.nodes.popoverContainer.appendChild(this.nodes.items),this.listeners.on(this.nodes.popoverContainer,"click",(n=>this.handleClick(n))),this.nodes.popover=d.make("div",[Tt.popover,this.params.class]),this.nodes.popover.appendChild(this.nodes.popoverContainer)}get itemsDefault(){return this.items.filter((n=>n instanceof se))}getElement(){return this.nodes.popover}show(){this.nodes.popover.classList.add(Tt.popoverOpened),this.search!==void 0&&this.search.focus()}hide(){this.nodes.popover.classList.remove(Tt.popoverOpened),this.nodes.popover.classList.remove(Tt.popoverOpenTop),this.itemsDefault.forEach((n=>n.reset())),this.search!==void 0&&this.search.clear(),this.emit(Bt.Closed)}destroy(){var n;this.items.forEach((n=>n.destroy())),this.nodes.popover.remove(),this.listeners.removeAll(),(n=this.search)==null||n.destroy()
1031
+ /**
1032
+ * Looks for the item by name and imitates click on it
1033
+ *
1034
+ * @param name - name of the item to activate
1035
+ */}activateItemByName(n){const h=this.items.find((h=>h.name===n));this.handleItemClick(h)}
1036
+ /**
1037
+ * Factory method for creating popover items
1038
+ *
1039
+ * @param items - list of items params
1040
+ */buildItems(n){return n.map((n=>{switch(n.type){case U.Separator:return new Xt;case U.Html:return new Ee(n,this.itemsRenderParams[U.Html]);default:return new se(n,this.itemsRenderParams[U.Default])}}))}
1041
+ /**
1042
+ * Retrieves popover item that is the target of the specified event
1043
+ *
1044
+ * @param event - event to retrieve popover item from
1045
+ */getTargetItem(n){return this.items.filter((n=>n instanceof se||n instanceof Ee)).find((h=>{const p=h.getElement();return p!==null&&n.composedPath().includes(p)}))}
1046
+ /**
1047
+ * Handles popover item click
1048
+ *
1049
+ * @param item - item to handle click of
1050
+ */handleItemClick(n){if(!("isDisabled"in n&&n.isDisabled)){if(n.hasChildren){this.showNestedItems(n),"handleClick"in n&&typeof n.handleClick=="function"&&n.handleClick();return}this.itemsDefault.filter((h=>h!==n)).forEach((n=>n.reset())),"handleClick"in n&&typeof n.handleClick=="function"&&n.handleClick(),this.toggleItemActivenessIfNeeded(n),n.closeOnActivate&&(this.hide(),this.emit(Bt.ClosedOnActivate))}}
1051
+ /**
1052
+ * Handles clicks inside popover
1053
+ *
1054
+ * @param event - item to handle click of
1055
+ */handleClick(n){const h=this.getTargetItem(n);h!==void 0&&this.handleItemClick(h)}
1056
+ /**
1057
+ * - Toggles item active state, if clicked popover item has property 'toggle' set to true.
1058
+ *
1059
+ * - Performs radiobutton-like behavior if the item has property 'toggle' set to string key.
1060
+ * (All the other items with the same key get inactive, and the item gets active)
1061
+ *
1062
+ * @param clickedItem - popover item that was clicked
1063
+ */toggleItemActivenessIfNeeded(n){if(n instanceof se&&(n.toggle===!0&&n.toggleActive(),typeof n.toggle=="string")){const h=this.itemsDefault.filter((h=>h.toggle===n.toggle));if(h.length===1){n.toggleActive();return}h.forEach((h=>{h.toggleActive(h===n)}))}}}var _t=(n=>(n.Search="search",n))(_t||{});const Nt=te("cdx-search-field"),Dt={wrapper:Nt(),icon:Nt("icon"),input:Nt("input")};class _i extends Te{
1064
+ /**
1065
+ * @param options - available config
1066
+ * @param options.items - searchable items list
1067
+ * @param options.placeholder - input placeholder
1068
+ */
1069
+ constructor({items:n,placeholder:h}){super(),this.listeners=new Ce,this.items=n,this.wrapper=d.make("div",Dt.wrapper);const p=d.make("div",Dt.icon,{innerHTML:Ke});this.input=d.make("input",Dt.input,{placeholder:h,tabIndex:-1}),this.wrapper.appendChild(p),this.wrapper.appendChild(this.input),this.listeners.on(this.input,"input",(()=>{this.searchQuery=this.input.value,this.emit(_t.Search,{query:this.searchQuery,items:this.foundItems})}))}getElement(){return this.wrapper}focus(){this.input.focus()}clear(){this.input.value="",this.searchQuery="",this.emit(_t.Search,{query:"",items:this.foundItems})}destroy(){this.listeners.removeAll()}get foundItems(){return this.items.filter((n=>this.checkItem(n)))}
1070
+ /**
1071
+ * Contains logic for checking whether passed item conforms the search query
1072
+ *
1073
+ * @param item - item to be checked
1074
+ */checkItem(n){var h,p;const g=((h=n.title)==null?void 0:h.toLowerCase())||"",m=(p=this.searchQuery)==null?void 0:p.toLowerCase();return m!==void 0&&g.includes(m)}}var Rt=Object.defineProperty,Ft=Object.getOwnPropertyDescriptor,Di=(n,h,p,g)=>{for(var m,v=g>1?void 0:g?Ft(h,p):h,x=n.length-1;x>=0;x--)(m=n[x])&&(v=(g?m(h,p,v):m(v))||v);return g&&v&&Rt(h,p,v),v};const Ut=class Zt extends Vt{
1075
+ /**
1076
+ * Construct the instance
1077
+ *
1078
+ * @param params - popover params
1079
+ * @param itemsRenderParams – popover item render params.
1080
+ * The parameters that are not set by user via popover api but rather depend on technical implementation
1081
+ */
1082
+ constructor(n,p){super(n,p),this.nestingLevel=0,this.nestedPopoverTriggerItem=null,this.previouslyHoveredItem=null,this.scopeElement=document.body,this.hide=()=>{var n;super.hide(),this.destroyNestedPopoverIfExists(),(n=this.flipper)==null||n.deactivate(),this.previouslyHoveredItem=null},this.onFlip=()=>{const n=this.itemsDefault.find((n=>n.isFocused));n==null||n.onFocus()},this.onSearch=n=>{var h;const p=n.query==="",g=n.items.length===0;this.items.forEach((h=>{let m=!1;h instanceof se?m=!n.items.includes(h):(h instanceof Xt||h instanceof Ee)&&(m=g||!p),h.toggleHidden(m)})),this.toggleNothingFoundMessage(g);const m=n.query===""?this.flippableElements:n.items.map((n=>n.getElement()));(h=this.flipper)!=null&&h.isActivated&&(this.flipper.deactivate(),this.flipper.activate(m))},n.nestingLevel!==void 0&&(this.nestingLevel=n.nestingLevel),this.nestingLevel>0&&this.nodes.popover.classList.add(Tt.popoverNested),n.scopeElement!==void 0&&(this.scopeElement=n.scopeElement),this.nodes.popoverContainer!==null&&this.listeners.on(this.nodes.popoverContainer,"mouseover",(n=>this.handleHover(n))),n.searchable&&this.addSearch(),n.flippable!==!1&&(this.flipper=new le({items:this.flippableElements,focusedItemClass:mt.focused,allowedKeys:[h.TAB,h.UP,h.DOWN,h.ENTER]}),this.flipper.onFlip(this.onFlip))}hasFocus(){return this.flipper!==void 0&&this.flipper.hasFocus()}get scrollTop(){return this.nodes.items===null?0:this.nodes.items.scrollTop}get offsetTop(){return this.nodes.popoverContainer===null?0:this.nodes.popoverContainer.offsetTop}show(){var n;this.nodes.popover.style.setProperty(St.PopoverHeight,this.size.height+"px"),this.shouldOpenBottom||this.nodes.popover.classList.add(Tt.popoverOpenTop),this.shouldOpenRight||this.nodes.popover.classList.add(Tt.popoverOpenLeft),super.show(),(n=this.flipper)==null||n.activate(this.flippableElements)}destroy(){this.hide(),super.destroy()
1083
+ /**
1084
+ * Handles displaying nested items for the item.
1085
+ *
1086
+ * @param item – item to show nested popover for
1087
+ */}showNestedItems(n){this.nestedPopover!==null&&this.nestedPopover!==void 0||(this.nestedPopoverTriggerItem=n,this.showNestedPopoverForItem(n)
1088
+ /**
1089
+ * Handles hover events inside popover items container
1090
+ *
1091
+ * @param event - hover event data
1092
+ */)}handleHover(n){const h=this.getTargetItem(n);h!==void 0&&this.previouslyHoveredItem!==h&&(this.destroyNestedPopoverIfExists(),this.previouslyHoveredItem=h,h.hasChildren&&this.showNestedPopoverForItem(h)
1093
+ /**
1094
+ * Sets CSS variable with position of item near which nested popover should be displayed.
1095
+ * Is used for correct positioning of the nested popover
1096
+ *
1097
+ * @param nestedPopoverEl - nested popover element
1098
+ * @param item – item near which nested popover should be displayed
1099
+ */)}setTriggerItemPosition(n,h){const p=h.getElement(),g=(p?p.offsetTop:0)-this.scrollTop,m=this.offsetTop+g;n.style.setProperty(St.TriggerItemTop,m+"px")}destroyNestedPopoverIfExists(){var n,h;this.nestedPopover===void 0||this.nestedPopover===null||(this.nestedPopover.off(Bt.ClosedOnActivate,this.hide),this.nestedPopover.hide(),this.nestedPopover.destroy(),this.nestedPopover.getElement().remove(),this.nestedPopover=null,(n=this.flipper)==null||n.activate(this.flippableElements),(h=this.nestedPopoverTriggerItem)==null||h.onChildrenClose()
1100
+ /**
1101
+ * Creates and displays nested popover for specified item.
1102
+ * Is used only on desktop
1103
+ *
1104
+ * @param item - item to display nested popover by
1105
+ */)}showNestedPopoverForItem(n){var h;this.nestedPopover=new Zt({searchable:n.isChildrenSearchable,items:n.children,nestingLevel:this.nestingLevel+1,flippable:n.isChildrenFlippable,messages:this.messages}),n.onChildrenOpen(),this.nestedPopover.on(Bt.ClosedOnActivate,this.hide);const p=this.nestedPopover.getElement();return this.nodes.popover.appendChild(p),this.setTriggerItemPosition(p,n),p.style.setProperty(St.NestingLevel,this.nestedPopover.nestingLevel.toString()),this.nestedPopover.show(),(h=this.flipper)==null||h.deactivate(),this.nestedPopover}get shouldOpenBottom(){if(this.nodes.popover===void 0||this.nodes.popover===null)return!1;const n=this.nodes.popoverContainer.getBoundingClientRect(),h=this.scopeElement.getBoundingClientRect(),p=this.size.height,g=n.top+p,m=n.top-p,v=Math.min(window.innerHeight,h.bottom);return m<h.top||g<=v}get shouldOpenRight(){if(this.nodes.popover===void 0||this.nodes.popover===null)return!1;const n=this.nodes.popover.getBoundingClientRect(),h=this.scopeElement.getBoundingClientRect(),p=this.size.width,g=n.right+p,m=n.left-p,v=Math.min(window.innerWidth,h.right);return m<h.left||g<=v}get size(){var n;const h={height:0,width:0};if(this.nodes.popover===null)return h;const p=this.nodes.popover.cloneNode(!0);p.style.visibility="hidden",p.style.position="absolute",p.style.top="-1000px",p.classList.add(Tt.popoverOpened),(n=p.querySelector("."+Tt.popoverNested))==null||n.remove(),document.body.appendChild(p);const g=p.querySelector("."+Tt.popoverContainer);return h.height=g.offsetHeight,h.width=g.offsetWidth,p.remove(),h}get flippableElements(){return this.items.map((n=>n instanceof se?n.getElement():n instanceof Ee?n.getControls():void 0)).flat().filter((n=>n!=null))}addSearch(){this.search=new _i({items:this.itemsDefault,placeholder:this.messages.search}),this.search.on(_t.Search,this.onSearch);const n=this.search.getElement();n.classList.add(Tt.search),this.nodes.popoverContainer.insertBefore(n,this.nodes.popoverContainer.firstChild)
1106
+ /**
1107
+ * Toggles nothing found message visibility
1108
+ *
1109
+ * @param isDisplayed - true if the message should be displayed
1110
+ */}toggleNothingFoundMessage(n){this.nodes.nothingFoundMessage.classList.toggle(Tt.nothingFoundMessageDisplayed,n)}};Di([ue],Ut.prototype,"size",1);let jt=Ut;class Ri extends jt{
1111
+ /**
1112
+ * Constructs the instance
1113
+ *
1114
+ * @param params - instance parameters
1115
+ */
1116
+ constructor(n){const h=!pe();super({...n,class:Tt.popoverInline},{[U.Default]:{wrapperTag:"button",hint:{position:"top",alignment:"center",enabled:h}},[U.Html]:{hint:{position:"top",alignment:"center",enabled:h}}}),this.items.forEach((n=>{!(n instanceof se)&&!(n instanceof Ee)||n.hasChildren&&n.isChildrenOpen&&this.showNestedItems(n)}))}get offsetLeft(){return this.nodes.popoverContainer===null?0:this.nodes.popoverContainer.offsetLeft}show(){this.nestingLevel===0&&this.nodes.popover.style.setProperty(St.InlinePopoverWidth,this.size.width+"px"),super.show()}handleHover(){}
1117
+ /**
1118
+ * Sets CSS variable with position of item near which nested popover should be displayed.
1119
+ * Is used to position nested popover right below clicked item
1120
+ *
1121
+ * @param nestedPopoverEl - nested popover element
1122
+ * @param item – item near which nested popover should be displayed
1123
+ */setTriggerItemPosition(n,h){const p=h.getElement(),g=p?p.offsetLeft:0,m=this.offsetLeft+g;n.style.setProperty(St.TriggerItemLeft,m+"px")}
1124
+ /**
1125
+ * Handles displaying nested items for the item.
1126
+ * Overriding in order to add toggling behaviour
1127
+ *
1128
+ * @param item – item to toggle nested popover for
1129
+ */showNestedItems(n){this.nestedPopoverTriggerItem!==n?super.showNestedItems(n):(this.destroyNestedPopoverIfExists(),this.nestedPopoverTriggerItem=null)}
1130
+ /**
1131
+ * Creates and displays nested popover for specified item.
1132
+ * Is used only on desktop
1133
+ *
1134
+ * @param item - item to display nested popover by
1135
+ */showNestedPopoverForItem(n){const h=super.showNestedPopoverForItem(n);return h.getElement().classList.add(Tt.getPopoverNestedClass(h.nestingLevel)),h
1136
+ /**
1137
+ * Overrides default item click handling.
1138
+ * Helps to close nested popover once other item is clicked.
1139
+ *
1140
+ * @param item - clicked item
1141
+ */}handleItemClick(n){var h;n!==this.nestedPopoverTriggerItem&&((h=this.nestedPopoverTriggerItem)==null||h.handleClick(),super.destroyNestedPopoverIfExists()),super.handleItemClick(n)}}const $t=class we{constructor(){this.scrollPosition=null}lock(){x?this.lockHard():document.body.classList.add(we.CSS.scrollLocked)}unlock(){x?this.unlockHard():document.body.classList.remove(we.CSS.scrollLocked)}lockHard(){this.scrollPosition=window.pageYOffset,document.documentElement.style.setProperty("--window-scroll-offset",`${this.scrollPosition}px`),document.body.classList.add(we.CSS.scrollLockedHard)}unlockHard(){document.body.classList.remove(we.CSS.scrollLockedHard),this.scrollPosition!==null&&window.scrollTo(0,this.scrollPosition),this.scrollPosition=null}};$t.CSS={scrollLocked:"ce-scroll-locked",scrollLockedHard:"ce-scroll-locked--hard"};let Kt=$t;const Wt=te("ce-popover-header"),qt={root:Wt(),text:Wt("text"),backButton:Wt("back-button")};class Hi{
1142
+ /**
1143
+ * Constructs the instance
1144
+ *
1145
+ * @param params - popover header params
1146
+ */
1147
+ constructor({text:n,onBackButtonClick:h}){this.listeners=new Ce,this.text=n,this.onBackButtonClick=h,this.nodes={root:d.make("div",[qt.root]),backButton:d.make("button",[qt.backButton]),text:d.make("div",[qt.text])},this.nodes.backButton.innerHTML=ke,this.nodes.root.appendChild(this.nodes.backButton),this.listeners.on(this.nodes.backButton,"click",this.onBackButtonClick),this.nodes.text.innerText=this.text,this.nodes.root.appendChild(this.nodes.text)}getElement(){return this.nodes.root}destroy(){this.nodes.root.remove(),this.listeners.destroy()}}class zi{constructor(){this.history=[]}
1148
+ /**
1149
+ * Push new popover state
1150
+ *
1151
+ * @param state - new state
1152
+ */push(n){this.history.push(n)}pop(){return this.history.pop()}get currentTitle(){return this.history.length===0?"":this.history[this.history.length-1].title}get currentItems(){return this.history.length===0?[]:this.history[this.history.length-1].items}reset(){for(;this.history.length>1;)this.pop()}}class Jt extends Vt{
1153
+ /**
1154
+ * Construct the instance
1155
+ *
1156
+ * @param params - popover params
1157
+ */
1158
+ constructor(n){super(n,{[U.Default]:{hint:{enabled:!1}},[U.Html]:{hint:{enabled:!1}}}),this.scrollLocker=new Kt,this.history=new zi,this.isHidden=!0,this.nodes.overlay=d.make("div",[Tt.overlay,Tt.overlayHidden]),this.nodes.popover.insertBefore(this.nodes.overlay,this.nodes.popover.firstChild),this.listeners.on(this.nodes.overlay,"click",(()=>{this.hide()})),this.history.push({items:n.items})}show(){this.nodes.overlay.classList.remove(Tt.overlayHidden),super.show(),this.scrollLocker.lock(),this.isHidden=!1}hide(){this.isHidden||(super.hide(),this.nodes.overlay.classList.add(Tt.overlayHidden),this.scrollLocker.unlock(),this.history.reset(),this.isHidden=!0)}destroy(){super.destroy(),this.scrollLocker.unlock()
1159
+ /**
1160
+ * Handles displaying nested items for the item
1161
+ *
1162
+ * @param item – item to show nested popover for
1163
+ */}showNestedItems(n){this.updateItemsAndHeader(n.children,n.title),this.history.push({title:n.title,items:n.children})
1164
+ /**
1165
+ * Removes rendered popover items and header and displays new ones
1166
+ *
1167
+ * @param items - new popover items
1168
+ * @param title - new popover header text
1169
+ */}updateItemsAndHeader(n,h){if(this.header!==null&&this.header!==void 0&&(this.header.destroy(),this.header=null),h!==void 0){this.header=new Hi({text:h,onBackButtonClick:()=>{this.history.pop(),this.updateItemsAndHeader(this.history.currentItems,this.history.currentTitle)}});const n=this.header.getElement();n!==null&&this.nodes.popoverContainer.insertBefore(n,this.nodes.popoverContainer.firstChild)}this.items.forEach((n=>{var h;return(h=n.getElement())==null?void 0:h.remove()})),this.items=this.buildItems(n),this.items.forEach((n=>{var h;const p=n.getElement();p!==null&&((h=this.nodes.items)==null||h.appendChild(p))}))}}class Ui extends y{constructor(){super(...arguments),this.opened=!1,this.selection=new b,this.popover=null,this.close=()=>{this.opened&&(this.opened=!1,b.isAtEditor||this.selection.restore(),this.selection.clearSaved(),!this.Editor.CrossBlockSelection.isCrossBlockSelectionStarted&&this.Editor.BlockManager.currentBlock&&this.Editor.BlockSelection.unselectBlock(this.Editor.BlockManager.currentBlock),this.eventsDispatcher.emit(this.events.closed),this.popover&&(this.popover.off(Bt.Closed,this.onPopoverClose),this.popover.destroy(),this.popover.getElement().remove(),this.popover=null))},this.onPopoverClose=()=>{this.close()}}get events(){return{opened:"block-settings-opened",closed:"block-settings-closed"}}get CSS(){return{settings:"ce-settings"}}get flipper(){var n;if(this.popover!==null)return"flipper"in this.popover?(n=this.popover)==null?void 0:n.flipper:void 0}make(){this.nodes.wrapper=d.make("div",[this.CSS.settings]),this.eventsDispatcher.on(z,this.close)}destroy(){this.removeAllNodes(),this.listeners.destroy(),this.eventsDispatcher.off(z,this.close)
1170
+ /**
1171
+ * Open Block Settings pane
1172
+ *
1173
+ * @param targetBlock - near which Block we should open BlockSettings
1174
+ */}async open(n=this.Editor.BlockManager.currentBlock){var h;this.opened=!0,this.selection.save(),this.Editor.BlockSelection.selectBlock(n),this.Editor.BlockSelection.clearCache();const{toolTunes:p,commonTunes:g}=n.getTunes();this.eventsDispatcher.emit(this.events.opened);const m=pe()?Jt:jt;this.popover=new m({searchable:!0,items:await this.getTunesItems(n,g,p),scopeElement:this.Editor.API.methods.ui.nodes.redactor,messages:{nothingFound:A.ui(de.ui.popover,"Nothing found"),search:A.ui(de.ui.popover,"Filter")}}),this.popover.on(Bt.Closed,this.onPopoverClose),(h=this.nodes.wrapper)==null||h.append(this.popover.getElement()),this.popover.show()}getElement(){return this.nodes.wrapper}
1175
+ /**
1176
+ * Returns list of items to be displayed in block tunes menu.
1177
+ * Merges tool specific tunes, conversion menu and common tunes in one list in predefined order
1178
+ *
1179
+ * @param currentBlock – block we are about to open block tunes for
1180
+ * @param commonTunes – common tunes
1181
+ * @param toolTunes - tool specific tunes
1182
+ */async getTunesItems(n,h,p){const g=[];p!==void 0&&p.length>0&&(g.push(...p),g.push({type:U.Separator}));const m=Array.from(this.Editor.Tools.blockTools.values()),v=(await zt(n,m)).reduce(((h,p)=>(p.toolbox.forEach((g=>{h.push({icon:g.icon,title:A.t(de.toolNames,g.title),name:p.name,closeOnActivate:!0,onActivate:async()=>{const{BlockManager:h,Caret:m,Toolbar:v}=this.Editor,x=await h.convert(n,p.name,g.data);v.close(),m.setToBlock(x,m.positions.END)}})})),h)),[]);return v.length>0&&(g.push({icon:Ye,name:"convert-to",title:A.ui(de.ui.popover,"Convert to"),children:{searchable:!0,items:v}}),g.push({type:U.Separator})),g.push(...h),g.map((n=>this.resolveTuneAliases(n)))
1183
+ /**
1184
+ * Resolves aliases in tunes menu items
1185
+ *
1186
+ * @param item - item with resolved aliases
1187
+ */}resolveTuneAliases(n){if(n.type===U.Separator||n.type===U.Html)return n;const h=mi(n,{label:"title"});return n.confirmation&&(h.confirmation=this.resolveTuneAliases(n.confirmation)),h}}var Gt={exports:{}};
1188
+ /*!
1189
+ * Library for handling keyboard shortcuts
1190
+ * @copyright CodeX (https://codex.so)
1191
+ * @license MIT
1192
+ * @author CodeX (https://codex.so)
1193
+ * @version 1.2.0
1194
+ */(function(n,h){(function(h,p){n.exports=p()})(window,(function(){return function(n){var h={};function i(p){if(h[p])return h[p].exports;var g=h[p]={i:p,l:!1,exports:{}};return n[p].call(g.exports,g,g.exports,i),g.l=!0,g.exports}return i.m=n,i.c=h,i.d=function(n,h,p){i.o(n,h)||Object.defineProperty(n,h,{enumerable:!0,get:p})},i.r=function(n){typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,h){if(1&h&&(n=i(n)),8&h||4&h&&typeof n=="object"&&n&&n.__esModule)return n;var p=Object.create(null);if(i.r(p),Object.defineProperty(p,"default",{enumerable:!0,value:n}),2&h&&typeof n!="string")for(var g in n)i.d(p,g,function(h){return n[h]}.bind(null,g));return p},i.n=function(n){var h=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(h,"a",h),h},i.o=function(n,h){return Object.prototype.hasOwnProperty.call(n,h)},i.p="",i(i.s=0)}([function(n,h,p){function s(n,h){for(var p=0;p<h.length;p++){var g=h[p];g.enumerable=g.enumerable||!1,g.configurable=!0,"value"in g&&(g.writable=!0),Object.defineProperty(n,g.key,g)}}function r(n,h,p){return h&&s(n.prototype,h),p&&s(n,p),n}p.r(h);var g=function(){function a(n){var h=this;(function(n,h){if(!(n instanceof h))throw new TypeError("Cannot call a class as a function")})(this,a),this.commands={},this.keys={},this.name=n.name,this.parseShortcutName(n.name),this.element=n.on,this.callback=n.callback,this.executeShortcut=function(n){h.execute(n)},this.element.addEventListener("keydown",this.executeShortcut,!1)}return r(a,null,[{key:"supportedCommands",get:function(){return{SHIFT:["SHIFT"],CMD:["CMD","CONTROL","COMMAND","WINDOWS","CTRL"],ALT:["ALT","OPTION"]}}},{key:"keyCodes",get:function(){return{0:48,1:49,2:50,3:51,4:52,5:53,6:54,7:55,8:56,9:57,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,BACKSPACE:8,ENTER:13,ESCAPE:27,LEFT:37,UP:38,RIGHT:39,DOWN:40,INSERT:45,DELETE:46,".":190}}}]),r(a,[{key:"parseShortcutName",value:function(n){n=n.split("+");for(var h=0;h<n.length;h++){n[h]=n[h].toUpperCase();var p=!1;for(var g in a.supportedCommands)if(a.supportedCommands[g].includes(n[h])){p=this.commands[g]=!0;break}p||(this.keys[n[h]]=!0)}for(var m in a.supportedCommands)this.commands[m]||(this.commands[m]=!1)}},{key:"execute",value:function(n){var h,p={CMD:n.ctrlKey||n.metaKey,SHIFT:n.shiftKey,ALT:n.altKey},g=!0;for(h in this.commands)this.commands[h]!==p[h]&&(g=!1);var m,v=!0;for(m in this.keys)v=v&&n.keyCode===a.keyCodes[m];g&&v&&this.callback(n)}},{key:"remove",value:function(){this.element.removeEventListener("keydown",this.executeShortcut)}}]),a}();h.default=g}]).default}))})(Gt);var Qt=Gt.exports;const oo=Fe(Qt);class Yi{constructor(){this.registeredShortcuts=new Map}
1195
+ /**
1196
+ * Register shortcut
1197
+ *
1198
+ * @param shortcut - shortcut options
1199
+ */add(n){if(this.findShortcut(n.on,n.name))throw Error(`Shortcut ${n.name} is already registered for ${n.on}. Please remove it before add a new handler.`);const h=new oo({name:n.name,on:n.on,callback:n.handler}),p=this.registeredShortcuts.get(n.on)||[];this.registeredShortcuts.set(n.on,[...p,h])}
1200
+ /**
1201
+ * Remove shortcut
1202
+ *
1203
+ * @param element - Element shortcut is set for
1204
+ * @param name - shortcut name
1205
+ */remove(n,h){const p=this.findShortcut(n,h);if(!p)return;p.remove();const g=this.registeredShortcuts.get(n);this.registeredShortcuts.set(n,g.filter((n=>n!==p)))}
1206
+ /**
1207
+ * Get Shortcut instance if exist
1208
+ *
1209
+ * @param element - Element shorcut is set for
1210
+ * @param shortcut - shortcut name
1211
+ * @returns {number} index - shortcut index if exist
1212
+ */findShortcut(n,h){return(this.registeredShortcuts.get(n)||[]).find((({name:n})=>n===h))}}const io=new Yi;var ro=Object.defineProperty,mo=Object.getOwnPropertyDescriptor,eo=(n,h,p,g)=>{for(var m,v=g>1?void 0:g?mo(h,p):h,x=n.length-1;x>=0;x--)(m=n[x])&&(v=(g?m(h,p,v):m(v))||v);return g&&v&&ro(h,p,v),v},bo=(n=>(n.Opened="toolbox-opened",n.Closed="toolbox-closed",n.BlockAdded="toolbox-block-added",n))(bo||{});const ko=class to extends Te{
1213
+ /**
1214
+ * Toolbox constructor
1215
+ *
1216
+ * @param options - available parameters
1217
+ * @param options.api - Editor API methods
1218
+ * @param options.tools - Tools available to check whether some of them should be displayed at the Toolbox or not
1219
+ */
1220
+ constructor({api:n,tools:h,i18nLabels:p}){super(),this.opened=!1,this.listeners=new Ce,this.popover=null,this.handleMobileLayoutToggle=()=>{this.destroyPopover(),this.initPopover()},this.onPopoverClose=()=>{this.opened=!1,this.emit("toolbox-closed")},this.api=n,this.tools=h,this.i18nLabels=p,this.enableShortcuts(),this.nodes={toolbox:d.make("div",to.CSS.toolbox)},this.initPopover(),this.api.events.on(z,this.handleMobileLayoutToggle)
1221
+ /**
1222
+ * Returns True if Toolbox is Empty and nothing to show
1223
+ *
1224
+ * @returns {boolean}
1225
+ */}get isEmpty(){return this.toolsToBeDisplayed.length===0}static get CSS(){return{toolbox:"ce-toolbox"}}getElement(){return this.nodes.toolbox}hasFocus(){if(this.popover!==null)return"hasFocus"in this.popover?this.popover.hasFocus():void 0}destroy(){var n;super.destroy(),this.nodes&&this.nodes.toolbox&&this.nodes.toolbox.remove(),this.removeAllShortcuts(),(n=this.popover)==null||n.off(Bt.Closed,this.onPopoverClose),this.listeners.destroy(),this.api.events.off(z,this.handleMobileLayoutToggle)
1226
+ /**
1227
+ * Toolbox Tool's button click handler
1228
+ *
1229
+ * @param toolName - tool type to be activated
1230
+ * @param blockDataOverrides - Block data predefined by the activated Toolbox item
1231
+ */}toolButtonActivated(n,h){this.insertNewBlock(n,h)}open(){var n;this.isEmpty||((n=this.popover)==null||n.show(),this.opened=!0,this.emit("toolbox-opened"))}close(){var n;(n=this.popover)==null||n.hide(),this.opened=!1,this.emit("toolbox-closed")}toggle(){this.opened?this.close():this.open()}initPopover(){var n;const h=pe()?Jt:jt;this.popover=new h({scopeElement:this.api.ui.nodes.redactor,searchable:!0,messages:{nothingFound:this.i18nLabels.nothingFound,search:this.i18nLabels.filter},items:this.toolboxItemsToBeDisplayed}),this.popover.on(Bt.Closed,this.onPopoverClose),(n=this.nodes.toolbox)==null||n.append(this.popover.getElement())}destroyPopover(){this.popover!==null&&(this.popover.hide(),this.popover.off(Bt.Closed,this.onPopoverClose),this.popover.destroy(),this.popover=null),this.nodes.toolbox!==null&&(this.nodes.toolbox.innerHTML="")}get toolsToBeDisplayed(){const n=[];return this.tools.forEach((h=>{h.toolbox&&n.push(h)})),n}get toolboxItemsToBeDisplayed(){const e=(n,h)=>({icon:n.icon,title:A.t(de.toolNames,n.title||Le(h.name)),name:h.name,onActivate:()=>{this.toolButtonActivated(h.name,n.data)},secondaryLabel:h.shortcut?tt(h.shortcut):""});return this.toolsToBeDisplayed.reduce(((n,h)=>(Array.isArray(h.toolbox)?h.toolbox.forEach((p=>{n.push(e(p,h))})):h.toolbox!==void 0&&n.push(e(h.toolbox,h)),n)),[])}enableShortcuts(){this.toolsToBeDisplayed.forEach((n=>{const h=n.shortcut;h&&this.enableShortcutForTool(n.name,h)}))}
1232
+ /**
1233
+ * Enable shortcut Block Tool implemented shortcut
1234
+ *
1235
+ * @param {string} toolName - Tool name
1236
+ * @param {string} shortcut - shortcut according to the ShortcutData Module format
1237
+ */enableShortcutForTool(n,h){io.add({name:h,on:this.api.ui.nodes.redactor,handler:async h=>{h.preventDefault();const p=this.api.blocks.getCurrentBlockIndex(),g=this.api.blocks.getBlockByIndex(p);if(g)try{const h=await this.api.blocks.convert(g.id,n);this.api.caret.setToBlock(h,"end");return}catch{}this.insertNewBlock(n)}})}removeAllShortcuts(){this.toolsToBeDisplayed.forEach((n=>{const h=n.shortcut;h&&io.remove(this.api.ui.nodes.redactor,h)}))}
1238
+ /**
1239
+ * Inserts new block
1240
+ * Can be called when button clicked on Toolbox or by ShortcutData
1241
+ *
1242
+ * @param {string} toolName - Tool name
1243
+ * @param blockDataOverrides - predefined Block data
1244
+ */async insertNewBlock(n,h){const p=this.api.blocks.getCurrentBlockIndex(),g=this.api.blocks.getBlockByIndex(p);if(!g)return;const m=g.isEmpty?p:p+1;let v;if(h){const p=await this.api.blocks.composeBlockData(n);v=Object.assign(p,h)}const x=this.api.blocks.insert(n,v,void 0,m,void 0,g.isEmpty);x.call($.APPEND_CALLBACK),this.api.caret.setToBlock(m),this.emit("toolbox-block-added",{block:x}),this.api.toolbar.close()}};eo([ue],ko.prototype,"toolsToBeDisplayed",1);eo([ue],ko.prototype,"toolboxItemsToBeDisplayed",1);let wo=ko;const No="block hovered";async function Vi(n,h){const p=navigator.keyboard;if(!p)return h;try{return(await p.getLayoutMap()).get(n)||h}catch(n){return console.error(n),h}}class qi extends y{
1245
+ /**
1246
+ * @class
1247
+ * @param moduleConfiguration - Module Configuration
1248
+ * @param moduleConfiguration.config - Editor's config
1249
+ * @param moduleConfiguration.eventsDispatcher - Editor's event dispatcher
1250
+ */
1251
+ constructor({config:n,eventsDispatcher:h}){super({config:n,eventsDispatcher:h}),this.toolboxInstance=null
1252
+ /**
1253
+ * CSS styles
1254
+ *
1255
+ * @returns {object}
1256
+ */}get CSS(){return{toolbar:"ce-toolbar",content:"ce-toolbar__content",actions:"ce-toolbar__actions",actionsOpened:"ce-toolbar__actions--opened",toolbarOpened:"ce-toolbar--opened",openedToolboxHolderModifier:"codex-editor--toolbox-opened",plusButton:"ce-toolbar__plus",plusButtonShortcut:"ce-toolbar__plus-shortcut",settingsToggler:"ce-toolbar__settings-btn",settingsTogglerHidden:"ce-toolbar__settings-btn--hidden"}}
1257
+ /**
1258
+ * Returns the Toolbar opening state
1259
+ *
1260
+ * @returns {boolean}
1261
+ */get opened(){return this.nodes.wrapper.classList.contains(this.CSS.toolbarOpened)}get toolbox(){var n;return{opened:(n=this.toolboxInstance)==null?void 0:n.opened,close:()=>{var n;(n=this.toolboxInstance)==null||n.close()},open:()=>{this.toolboxInstance!==null?(this.Editor.BlockManager.currentBlock=this.hoveredBlock,this.toolboxInstance.open()):g("toolbox.open() called before initialization is finished","warn")},toggle:()=>{this.toolboxInstance!==null?this.toolboxInstance.toggle():g("toolbox.toggle() called before initialization is finished","warn")},hasFocus:()=>{var n;return(n=this.toolboxInstance)==null?void 0:n.hasFocus()}}}get blockActions(){return{hide:()=>{this.nodes.actions.classList.remove(this.CSS.actionsOpened)},show:()=>{this.nodes.actions.classList.add(this.CSS.actionsOpened)}}}get blockTunesToggler(){return{hide:()=>this.nodes.settingsToggler.classList.add(this.CSS.settingsTogglerHidden),show:()=>this.nodes.settingsToggler.classList.remove(this.CSS.settingsTogglerHidden)}}
1262
+ /**
1263
+ * Toggles read-only mode
1264
+ *
1265
+ * @param {boolean} readOnlyEnabled - read-only mode
1266
+ */toggleReadOnly(n){n?(this.destroy(),this.Editor.BlockSettings.destroy(),this.disableModuleBindings()):window.requestIdleCallback((()=>{this.drawUI(),this.enableModuleBindings()}),{timeout:2e3})}
1267
+ /**
1268
+ * Move Toolbar to the passed (or current) Block
1269
+ *
1270
+ * @param block - block to move Toolbar near it
1271
+ */moveAndOpen(n=this.Editor.BlockManager.currentBlock){if(this.toolboxInstance===null){g("Can't open Toolbar since Editor initialization is not finished yet","warn");return}if(this.toolboxInstance.opened&&this.toolboxInstance.close(),this.Editor.BlockSettings.opened&&this.Editor.BlockSettings.close(),!n)return;this.hoveredBlock=n;const h=n.holder,{isMobile:p}=this.Editor.UI;let m;const v=20,x=n.firstInput,w=h.getBoundingClientRect(),E=x!==void 0?x.getBoundingClientRect():null,B=E!==null?E.top-w.top:null,T=B!==null?B>v:void 0;if(p)m=h.offsetTop+h.offsetHeight;else if(x===void 0||T){const p=parseInt(window.getComputedStyle(n.pluginsContent).paddingTop);m=h.offsetTop+p}else{const n=_o(x),p=parseInt(window.getComputedStyle(this.nodes.plusButton).height,10),g=8;m=h.offsetTop+n-p+g+B}this.nodes.wrapper.style.top=`${Math.floor(m)}px`,this.Editor.BlockManager.blocks.length===1&&n.isEmpty?this.blockTunesToggler.hide():this.blockTunesToggler.show(),this.open()}close(){var n,h;this.Editor.ReadOnly.isEnabled||((n=this.nodes.wrapper)==null||n.classList.remove(this.CSS.toolbarOpened),this.blockActions.hide(),(h=this.toolboxInstance)==null||h.close(),this.Editor.BlockSettings.close(),this.reset())}reset(){this.nodes.wrapper.style.top="unset"}
1272
+ /**
1273
+ * Open Toolbar with Plus Button and Actions
1274
+ *
1275
+ * @param {boolean} withBlockActions - by default, Toolbar opens with Block Actions.
1276
+ * This flag allows to open Toolbar without Actions.
1277
+ */open(n=!0){this.nodes.wrapper.classList.add(this.CSS.toolbarOpened),n?this.blockActions.show():this.blockActions.hide()}async make(){this.nodes.wrapper=d.make("div",this.CSS.toolbar),["content","actions"].forEach((n=>{this.nodes[n]=d.make("div",this.CSS[n])})),d.append(this.nodes.wrapper,this.nodes.content),d.append(this.nodes.content,this.nodes.actions),this.nodes.plusButton=d.make("div",this.CSS.plusButton,{innerHTML:$e}),d.append(this.nodes.actions,this.nodes.plusButton),this.readOnlyMutableListeners.on(this.nodes.plusButton,"click",(()=>{Ne(!0),this.plusButtonClicked()}),!1);const n=d.make("div");n.appendChild(document.createTextNode(A.ui(de.ui.toolbar.toolbox,"Add"))),n.appendChild(d.make("div",this.CSS.plusButtonShortcut,{textContent:"/"})),Pe(this.nodes.plusButton,n,{hidingDelay:400}),this.nodes.settingsToggler=d.make("span",this.CSS.settingsToggler,{innerHTML:je}),d.append(this.nodes.actions,this.nodes.settingsToggler);const h=d.make("div"),p=d.text(A.ui(de.ui.blockTunes.toggler,"Click to tune")),g=await Vi("Slash","/");h.appendChild(p),h.appendChild(d.make("div",this.CSS.plusButtonShortcut,{textContent:tt(`CMD + ${g}`)})),Pe(this.nodes.settingsToggler,h,{hidingDelay:400}),d.append(this.nodes.actions,this.makeToolbox()),d.append(this.nodes.actions,this.Editor.BlockSettings.getElement()),d.append(this.Editor.UI.nodes.wrapper,this.nodes.wrapper)}makeToolbox(){return this.toolboxInstance=new wo({api:this.Editor.API.methods,tools:this.Editor.Tools.blockTools,i18nLabels:{filter:A.ui(de.ui.popover,"Filter"),nothingFound:A.ui(de.ui.popover,"Nothing found")}}),this.toolboxInstance.on(bo.Opened,(()=>{this.Editor.UI.nodes.wrapper.classList.add(this.CSS.openedToolboxHolderModifier)})),this.toolboxInstance.on(bo.Closed,(()=>{this.Editor.UI.nodes.wrapper.classList.remove(this.CSS.openedToolboxHolderModifier)})),this.toolboxInstance.on(bo.BlockAdded,(({block:n})=>{const{BlockManager:h,Caret:p}=this.Editor,g=h.getBlockById(n.id);g.inputs.length===0&&(g===h.lastBlock?(h.insertAtEnd(),p.setToBlock(h.lastBlock)):p.setToBlock(h.nextBlock))})),this.toolboxInstance.getElement()}plusButtonClicked(){var n;this.Editor.BlockManager.currentBlock=this.hoveredBlock,(n=this.toolboxInstance)==null||n.toggle()}enableModuleBindings(){this.readOnlyMutableListeners.on(this.nodes.settingsToggler,"mousedown",(n=>{var h;n.stopPropagation(),this.settingsTogglerClicked(),(h=this.toolboxInstance)!=null&&h.opened&&this.toolboxInstance.close(),Ne(!0)}),!0),pe()||this.eventsDispatcher.on(No,(n=>{var h;this.Editor.BlockSettings.opened||(h=this.toolboxInstance)!=null&&h.opened||this.moveAndOpen(n.block)}))}disableModuleBindings(){this.readOnlyMutableListeners.clearAll()}settingsTogglerClicked(){this.Editor.BlockManager.currentBlock=this.hoveredBlock,this.Editor.BlockSettings.opened?this.Editor.BlockSettings.close():this.Editor.BlockSettings.open(this.hoveredBlock)}drawUI(){this.Editor.BlockSettings.make(),this.make()}destroy(){this.removeAllNodes(),this.toolboxInstance&&this.toolboxInstance.destroy()}}var Po=(n=>(n[n.Block=0]="Block",n[n.Inline=1]="Inline",n[n.Tune=2]="Tune",n))(Po||{}),Do=(n=>(n.Shortcut="shortcut",n.Toolbox="toolbox",n.EnabledInlineTools="inlineToolbar",n.EnabledBlockTunes="tunes",n.Config="config",n))(Do||{}),Ro=(n=>(n.Shortcut="shortcut",n.SanitizeConfig="sanitize",n))(Ro||{}),Vo=(n=>(n.IsEnabledLineBreaks="enableLineBreaks",n.Toolbox="toolbox",n.ConversionConfig="conversionConfig",n.IsReadOnlySupported="isReadOnlySupported",n.PasteConfig="pasteConfig",n))(Vo||{}),Xo=(n=>(n.IsInline="isInline",n.Title="title",n))(Xo||{}),Qo=(n=>(n.IsTune="isTune",n))(Qo||{});class dt{
1278
+ /**
1279
+ * @class
1280
+ * @param {ConstructorOptions} options - Constructor options
1281
+ */
1282
+ constructor({name:n,constructable:h,config:p,api:g,isDefault:m,isInternal:v=!1,defaultPlaceholder:x}){this.api=g,this.name=n,this.constructable=h,this.config=p,this.isDefault=m,this.isInternal=v,this.defaultPlaceholder=x}get settings(){const n=this.config.config||{};return this.isDefault&&!("placeholder"in n)&&this.defaultPlaceholder&&(n.placeholder=this.defaultPlaceholder),n}reset(){if(O(this.constructable.reset))return this.constructable.reset()}prepare(){if(O(this.constructable.prepare))return this.constructable.prepare({toolName:this.name,config:this.settings})}get shortcut(){const n=this.constructable.shortcut;return this.config.shortcut||n}get sanitizeConfig(){return this.constructable.sanitize||{}}isInline(){return this.type===Po.Inline}isBlock(){return this.type===Po.Block}isTune(){return this.type===Po.Tune}}class Zi extends y{
1283
+ /**
1284
+ * @param moduleConfiguration - Module Configuration
1285
+ * @param moduleConfiguration.config - Editor's config
1286
+ * @param moduleConfiguration.eventsDispatcher - Editor's event dispatcher
1287
+ */
1288
+ constructor({config:n,eventsDispatcher:h}){super({config:n,eventsDispatcher:h}),this.CSS={inlineToolbar:"ce-inline-toolbar"},this.opened=!1,this.popover=null,this.toolbarVerticalMargin=pe()?20:6,this.toolsInstances=new Map
1289
+ /**
1290
+ * Toggles read-only mode
1291
+ *
1292
+ * @param {boolean} readOnlyEnabled - read-only mode
1293
+ */}toggleReadOnly(n){n?this.destroy():window.requestIdleCallback((()=>{this.make()}),{timeout:2e3})}
1294
+ /**
1295
+ * Shows Inline Toolbar if something is selected
1296
+ *
1297
+ * @param [needToClose] - pass true to close toolbar if it is not allowed.
1298
+ * Avoid to use it just for closing IT, better call .close() clearly.
1299
+ */async tryToShow(n=!1){n&&this.close(),this.allowedToShow()&&(await this.open(),this.Editor.Toolbar.close())}close(){var n,h;this.opened&&(this.Editor.ReadOnly.isEnabled||(Array.from(this.toolsInstances.entries()).forEach((([n,h])=>{const p=this.getToolShortcut(n);p&&io.remove(this.Editor.UI.nodes.redactor,p),O(h.clear)&&h.clear()})),this.toolsInstances=null,this.reset(),this.opened=!1,(n=this.popover)==null||n.hide(),(h=this.popover)==null||h.destroy(),this.popover=null))}
1300
+ /**
1301
+ * Check if node is contained by Inline Toolbar
1302
+ *
1303
+ * @param {Node} node — node to check
1304
+ */containsNode(n){return this.nodes.wrapper!==void 0&&this.nodes.wrapper.contains(n)}destroy(){var n;this.removeAllNodes(),(n=this.popover)==null||n.destroy(),this.popover=null}make(){this.nodes.wrapper=d.make("div",[this.CSS.inlineToolbar,...this.isRtl?[this.Editor.UI.CSS.editorRtlFix]:[]]),d.append(this.Editor.UI.nodes.wrapper,this.nodes.wrapper)}async open(){var n;if(this.opened)return;this.opened=!0,this.popover!==null&&this.popover.destroy();const h=await this.getInlineTools();this.popover=new Ri({items:h,scopeElement:this.Editor.API.methods.ui.nodes.redactor,messages:{nothingFound:A.ui(de.ui.popover,"Nothing found"),search:A.ui(de.ui.popover,"Filter")}}),this.move(this.popover.size.width),(n=this.nodes.wrapper)==null||n.append(this.popover.getElement()),this.popover.show()
1305
+ /**
1306
+ * Move Toolbar to the selected text
1307
+ *
1308
+ * @param popoverWidth - width of the toolbar popover
1309
+ */}move(n){const h=b.rect,p=this.Editor.UI.nodes.wrapper.getBoundingClientRect(),g={x:h.x-p.x,y:h.y+h.height-p.top+this.toolbarVerticalMargin};g.x+n+p.x>this.Editor.UI.contentRect.right&&(g.x=this.Editor.UI.contentRect.right-n-p.x),this.nodes.wrapper.style.left=Math.floor(g.x)+"px",this.nodes.wrapper.style.top=Math.floor(g.y)+"px"}reset(){this.nodes.wrapper.style.left="0",this.nodes.wrapper.style.top="0"}allowedToShow(){const n=["IMG","INPUT"],h=b.get(),p=b.text;if(!h||!h.anchorNode||h.isCollapsed||p.length<1)return!1;const g=d.isElement(h.anchorNode)?h.anchorNode:h.anchorNode.parentElement;if(g===null||h&&n.includes(g.tagName)||g.closest('[contenteditable="true"]')===null)return!1;const m=this.Editor.BlockManager.getBlock(h.anchorNode);return!!m&&m.tool.inlineTools.size!==0}async getInlineTools(){const n=b.get(),h=this.Editor.BlockManager.getBlock(n.anchorNode),p=Array.from(h.tool.inlineTools.values()),g=[];this.toolsInstances===null&&(this.toolsInstances=new Map);for(let n=0;n<p.length;n++){const h=p[n],m=h.create(),v=await m.render();this.toolsInstances.set(h.name,m);const x=this.getToolShortcut(h.name);if(x)try{this.enableShortcuts(h.name,x)}catch{}const w=x!==void 0?tt(x):void 0,E=A.t(de.toolNames,h.title||Le(h.name));[v].flat().forEach((v=>{var x,B;const T={name:h.name,onActivate:()=>{this.toolClicked(m)},hint:{title:E,description:w}};if(d.isElement(v)){const n={...T,element:v,type:U.Html};if(O(m.renderActions)){const h=m.renderActions();n.children={isOpen:(x=m.checkState)==null?void 0:x.call(m,b.get()),isFlippable:!1,items:[{type:U.Html,element:h}]}}else(B=m.checkState)==null||B.call(m,b.get());g.push(n)}else if(v.type===U.Html)g.push({...T,...v,type:U.Html});else if(v.type===U.Separator)g.push({type:U.Separator});else{const h={...T,...v,type:U.Default};"children"in h&&n!==0&&g.push({type:U.Separator}),g.push(h),"children"in h&&n<p.length-1&&g.push({type:U.Separator})}}))}return g}
1310
+ /**
1311
+ * Get shortcut name for tool
1312
+ *
1313
+ * @param toolName — Tool name
1314
+ */getToolShortcut(n){const{Tools:h}=this.Editor,p=h.inlineTools.get(n),g=h.internal.inlineTools;return Array.from(g.keys()).includes(n)?this.inlineTools[n][Ro.Shortcut]:p==null?void 0:p.shortcut}
1315
+ /**
1316
+ * Enable Tool shortcut with Editor Shortcuts Module
1317
+ *
1318
+ * @param toolName - tool name
1319
+ * @param shortcut - shortcut according to the ShortcutData Module format
1320
+ */enableShortcuts(n,h){io.add({name:h,handler:h=>{var p;const{currentBlock:g}=this.Editor.BlockManager;g&&g.tool.enabledInlineTools&&(h.preventDefault(),(p=this.popover)==null||p.activateItemByName(n))},on:this.Editor.UI.nodes.redactor})}
1321
+ /**
1322
+ * Inline Tool button clicks
1323
+ *
1324
+ * @param tool - Tool's instance
1325
+ */toolClicked(n){var h;const p=b.range;(h=n.surround)==null||h.call(n,p),this.checkToolsState()}checkToolsState(){var n;(n=this.toolsInstances)==null||n.forEach((n=>{var h;(h=n.checkState)==null||h.call(n,b.get())}))}get inlineTools(){const n={};return Array.from(this.Editor.Tools.inlineTools.entries()).forEach((([h,p])=>{n[h]=p.create()})),n}}function so(){const n=window.getSelection();if(n===null)return[null,0];let h=n.focusNode,p=n.focusOffset;return h===null?[null,0]:(h.nodeType!==Node.TEXT_NODE&&h.childNodes.length>0&&(h.childNodes[p]?(h=h.childNodes[p],p=0):(h=h.childNodes[p-1],p=h.textContent.length)),[h,p])}function no(n,h,p,g){const m=document.createRange();g==="left"?(m.setStart(n,0),m.setEnd(h,p)):(m.setStart(h,p),m.setEnd(n,n.childNodes.length));const v=m.cloneContents(),x=document.createElement("div");x.appendChild(v);const w=x.textContent||"";return Lo(w)}function Me(n){const h=d.getDeepestNode(n);if(h===null||d.isEmpty(n))return!0;if(d.isNativeInput(h))return h.selectionEnd===0;if(d.isEmpty(n))return!0;const[p,g]=so();return p!==null&&no(n,p,g,"left")}function Ae(n){const h=d.getDeepestNode(n,!0);if(h===null)return!0;if(d.isNativeInput(h))return h.selectionEnd===h.value.length;const[p,g]=so();return p!==null&&no(n,p,g,"right")}class Gi extends y{
1326
+ /**
1327
+ * All keydowns on Block
1328
+ *
1329
+ * @param {KeyboardEvent} event - keydown
1330
+ */
1331
+ keydown(n){switch(this.beforeKeydownProcessing(n),n.keyCode){case h.BACKSPACE:this.backspace(n);break;case h.DELETE:this.delete(n);break;case h.ENTER:this.enter(n);break;case h.DOWN:case h.RIGHT:this.arrowRightAndDown(n);break;case h.UP:case h.LEFT:this.arrowLeftAndUp(n);break;case h.TAB:this.tabPressed(n);break}n.key==="/"&&!n.ctrlKey&&!n.metaKey&&this.slashPressed(n),n.code==="Slash"&&(n.ctrlKey||n.metaKey)&&(n.preventDefault(),this.commandSlashPressed()
1332
+ /**
1333
+ * Fires on keydown before event processing
1334
+ *
1335
+ * @param {KeyboardEvent} event - keydown
1336
+ */)}beforeKeydownProcessing(n){this.needToolbarClosing(n)&&Mt(n.keyCode)&&(this.Editor.Toolbar.close(),n.ctrlKey||n.metaKey||n.altKey||n.shiftKey||this.Editor.BlockSelection.clearSelection(n)
1337
+ /**
1338
+ * Key up on Block:
1339
+ * - shows Inline Toolbar if something selected
1340
+ * - shows conversion toolbar with 85% of block selection
1341
+ *
1342
+ * @param {KeyboardEvent} event - keyup event
1343
+ */)}keyup(n){n.shiftKey||this.Editor.UI.checkEmptiness()}
1344
+ /**
1345
+ * Add drop target styles
1346
+ *
1347
+ * @param {DragEvent} event - drag over event
1348
+ */dragOver(n){const h=this.Editor.BlockManager.getBlockByChildNode(n.target);h.dropTarget=!0}
1349
+ /**
1350
+ * Remove drop target style
1351
+ *
1352
+ * @param {DragEvent} event - drag leave event
1353
+ */dragLeave(n){const h=this.Editor.BlockManager.getBlockByChildNode(n.target);h.dropTarget=!1}
1354
+ /**
1355
+ * Copying selected blocks
1356
+ * Before putting to the clipboard we sanitize all blocks and then copy to the clipboard
1357
+ *
1358
+ * @param {ClipboardEvent} event - clipboard event
1359
+ */handleCommandC(n){const{BlockSelection:h}=this.Editor;h.anyBlockSelected&&h.copySelectedBlocks(n)}
1360
+ /**
1361
+ * Copy and Delete selected Blocks
1362
+ *
1363
+ * @param {ClipboardEvent} event - clipboard event
1364
+ */handleCommandX(n){const{BlockSelection:h,BlockManager:p,Caret:g}=this.Editor;h.anyBlockSelected&&h.copySelectedBlocks(n).then((()=>{const m=p.removeSelectedBlocks(),v=p.insertDefaultBlockAtIndex(m,!0);g.setToBlock(v,g.positions.START),h.clearSelection(n)}))}
1365
+ /**
1366
+ * Tab pressed inside a Block.
1367
+ *
1368
+ * @param {KeyboardEvent} event - keydown
1369
+ */tabPressed(n){const{InlineToolbar:h,Caret:p}=this.Editor;h.opened||(n.shiftKey?p.navigatePrevious(!0):p.navigateNext(!0))&&n.preventDefault()}commandSlashPressed(){this.Editor.BlockSelection.selectedBlocks.length>1||this.activateBlockSettings()}
1370
+ /**
1371
+ * '/' keydown inside a Block
1372
+ *
1373
+ * @param event - keydown
1374
+ */slashPressed(n){this.Editor.BlockManager.currentBlock.isEmpty&&(n.preventDefault(),this.Editor.Caret.insertContentAtCaretPosition("/"),this.activateToolbox()
1375
+ /**
1376
+ * ENTER pressed on block
1377
+ *
1378
+ * @param {KeyboardEvent} event - keydown
1379
+ */)}enter(n){const{BlockManager:h,UI:p}=this.Editor,g=h.currentBlock;if(g===void 0||g.tool.isLineBreaksEnabled||p.someToolbarOpened&&p.someFlipperButtonFocused||n.shiftKey&&!x)return;let m=g;g.currentInput!==void 0&&Me(g.currentInput)&&!g.hasMedia?this.Editor.BlockManager.insertDefaultBlockAtIndex(this.Editor.BlockManager.currentBlockIndex):m=g.currentInput&&Ae(g.currentInput)?this.Editor.BlockManager.insertDefaultBlockAtIndex(this.Editor.BlockManager.currentBlockIndex+1):this.Editor.BlockManager.split(),this.Editor.Caret.setToBlock(m),this.Editor.Toolbar.moveAndOpen(m),n.preventDefault()
1380
+ /**
1381
+ * Handle backspace keydown on Block
1382
+ *
1383
+ * @param {KeyboardEvent} event - keydown
1384
+ */}backspace(n){const{BlockManager:h,Caret:p}=this.Editor,{currentBlock:g,previousBlock:m}=h;if(g!==void 0&&b.isCollapsed&&g.currentInput&&Me(g.currentInput))if(n.preventDefault(),this.Editor.Toolbar.close(),g.currentInput===g.firstInput){if(m!==null)if(m.isEmpty)h.removeBlock(m);else if(g.isEmpty){h.removeBlock(g);const n=h.currentBlock;p.setToBlock(n,p.positions.END)}else wt(m,g)?this.mergeBlocks(m,g):p.setToBlock(m,p.positions.END)}else p.navigatePrevious()}
1385
+ /**
1386
+ * Handles delete keydown on Block
1387
+ * Removes char after the caret.
1388
+ * If caret is at the end of the block, merge next block with current
1389
+ *
1390
+ * @param {KeyboardEvent} event - keydown
1391
+ */delete(n){const{BlockManager:h,Caret:p}=this.Editor,{currentBlock:g,nextBlock:m}=h;b.isCollapsed&&Ae(g.currentInput)&&(n.preventDefault(),this.Editor.Toolbar.close(),g.currentInput===g.lastInput?m!==null&&(m.isEmpty?h.removeBlock(m):g.isEmpty?(h.removeBlock(g),p.setToBlock(m,p.positions.START)):wt(g,m)?this.mergeBlocks(g,m):p.setToBlock(m,p.positions.START)):p.navigateNext())}
1392
+ /**
1393
+ * Merge passed Blocks
1394
+ *
1395
+ * @param targetBlock - to which Block we want to merge
1396
+ * @param blockToMerge - what Block we want to merge
1397
+ */mergeBlocks(n,h){const{BlockManager:p,Caret:g,Toolbar:m}=this.Editor;g.createShadow(n.lastInput),p.mergeBlocks(n,h).then((()=>{g.restoreCaret(n.pluginsContent),m.close()}))
1398
+ /**
1399
+ * Handle right and down keyboard keys
1400
+ *
1401
+ * @param {KeyboardEvent} event - keyboard event
1402
+ */}arrowRightAndDown(n){const p=le.usedKeys.includes(n.keyCode)&&(!n.shiftKey||n.keyCode===h.TAB);if(this.Editor.UI.someToolbarOpened&&p)return;this.Editor.Toolbar.close();const{currentBlock:g}=this.Editor.BlockManager,m=((g==null?void 0:g.currentInput)!==void 0?Ae(g.currentInput):void 0)||this.Editor.BlockSelection.anyBlockSelected;n.shiftKey&&n.keyCode===h.DOWN&&m?this.Editor.CrossBlockSelection.toggleBlockSelectedState():(n.keyCode===h.DOWN||n.keyCode===h.RIGHT&&!this.isRtl?this.Editor.Caret.navigateNext():this.Editor.Caret.navigatePrevious())?n.preventDefault():(Oe((()=>{this.Editor.BlockManager.currentBlock&&this.Editor.BlockManager.currentBlock.updateCurrentInput()}),20)(),this.Editor.BlockSelection.clearSelection(n)
1403
+ /**
1404
+ * Handle left and up keyboard keys
1405
+ *
1406
+ * @param {KeyboardEvent} event - keyboard event
1407
+ */)}arrowLeftAndUp(n){if(this.Editor.UI.someToolbarOpened){if(le.usedKeys.includes(n.keyCode)&&(!n.shiftKey||n.keyCode===h.TAB))return;this.Editor.UI.closeAllToolbars()}this.Editor.Toolbar.close();const{currentBlock:p}=this.Editor.BlockManager,g=((p==null?void 0:p.currentInput)!==void 0?Me(p.currentInput):void 0)||this.Editor.BlockSelection.anyBlockSelected;n.shiftKey&&n.keyCode===h.UP&&g?this.Editor.CrossBlockSelection.toggleBlockSelectedState(!1):(n.keyCode===h.UP||n.keyCode===h.LEFT&&!this.isRtl?this.Editor.Caret.navigatePrevious():this.Editor.Caret.navigateNext())?n.preventDefault():(Oe((()=>{this.Editor.BlockManager.currentBlock&&this.Editor.BlockManager.currentBlock.updateCurrentInput()}),20)(),this.Editor.BlockSelection.clearSelection(n)
1408
+ /**
1409
+ * Cases when we need to close Toolbar
1410
+ *
1411
+ * @param {KeyboardEvent} event - keyboard event
1412
+ */)}needToolbarClosing(n){const p=n.keyCode===h.ENTER&&this.Editor.Toolbar.toolbox.opened,g=n.keyCode===h.ENTER&&this.Editor.BlockSettings.opened,m=n.keyCode===h.ENTER&&this.Editor.InlineToolbar.opened,v=n.keyCode===h.TAB;return!(n.shiftKey||v||p||g||m)}activateToolbox(){this.Editor.Toolbar.opened||this.Editor.Toolbar.moveAndOpen(),this.Editor.Toolbar.toolbox.open()}activateBlockSettings(){this.Editor.Toolbar.opened||this.Editor.Toolbar.moveAndOpen(),this.Editor.BlockSettings.opened||this.Editor.BlockSettings.open()}}class Xe{
1413
+ /**
1414
+ * @class
1415
+ * @param {HTMLElement} workingArea — editor`s working node
1416
+ */
1417
+ constructor(n){this.blocks=[],this.workingArea=n
1418
+ /**
1419
+ * Get length of Block instances array
1420
+ *
1421
+ * @returns {number}
1422
+ */}get length(){return this.blocks.length}
1423
+ /**
1424
+ * Get Block instances array
1425
+ *
1426
+ * @returns {Block[]}
1427
+ */get array(){return this.blocks}
1428
+ /**
1429
+ * Get blocks html elements array
1430
+ *
1431
+ * @returns {HTMLElement[]}
1432
+ */get nodes(){return At(this.workingArea.children)}
1433
+ /**
1434
+ * Proxy trap to implement array-like setter
1435
+ *
1436
+ * @example
1437
+ * blocks[0] = new Block(...)
1438
+ * @param {Blocks} instance — Blocks instance
1439
+ * @param {PropertyKey} property — block index or any Blocks class property key to set
1440
+ * @param {Block} value — value to set
1441
+ * @returns {boolean}
1442
+ */static set(n,h,p){return isNaN(Number(h))?(Reflect.set(n,h,p),!0):(n.insert(+h,p),!0
1443
+ /**
1444
+ * Proxy trap to implement array-like getter
1445
+ *
1446
+ * @param {Blocks} instance — Blocks instance
1447
+ * @param {PropertyKey} property — Blocks class property key
1448
+ * @returns {Block|*}
1449
+ */)}static get(n,h){return isNaN(Number(h))?Reflect.get(n,h):n.get(+h)}
1450
+ /**
1451
+ * Push new Block to the blocks array and append it to working area
1452
+ *
1453
+ * @param {Block} block - Block to add
1454
+ */push(n){this.blocks.push(n),this.insertToDOM(n)
1455
+ /**
1456
+ * Swaps blocks with indexes first and second
1457
+ *
1458
+ * @param {number} first - first block index
1459
+ * @param {number} second - second block index
1460
+ * @deprecated — use 'move' instead
1461
+ */}swap(n,h){const p=this.blocks[h];d.swap(this.blocks[n].holder,p.holder),this.blocks[h]=this.blocks[n],this.blocks[n]=p
1462
+ /**
1463
+ * Move a block from one to another index
1464
+ *
1465
+ * @param {number} toIndex - new index of the block
1466
+ * @param {number} fromIndex - block to move
1467
+ */}move(n,h){const p=this.blocks.splice(h,1)[0],g=n-1,m=Math.max(0,g),v=this.blocks[m];n>0?this.insertToDOM(p,"afterend",v):this.insertToDOM(p,"beforebegin",v),this.blocks.splice(n,0,p);const x=this.composeBlockEvent("move",{fromIndex:h,toIndex:n});p.call($.MOVED,x)}
1468
+ /**
1469
+ * Insert new Block at passed index
1470
+ *
1471
+ * @param {number} index — index to insert Block
1472
+ * @param {Block} block — Block to insert
1473
+ * @param {boolean} replace — it true, replace block on given index
1474
+ */insert(n,h,p=!1){if(!this.length){this.push(h);return}n>this.length&&(n=this.length),p&&(this.blocks[n].holder.remove(),this.blocks[n].call($.REMOVED));const g=p?1:0;if(this.blocks.splice(n,g,h),n>0){const p=this.blocks[n-1];this.insertToDOM(h,"afterend",p)}else{const p=this.blocks[n+1];p?this.insertToDOM(h,"beforebegin",p):this.insertToDOM(h)}}
1475
+ /**
1476
+ * Replaces block under passed index with passed block
1477
+ *
1478
+ * @param index - index of existed block
1479
+ * @param block - new block
1480
+ */replace(n,h){if(this.blocks[n]===void 0)throw Error("Incorrect index");this.blocks[n].holder.replaceWith(h.holder),this.blocks[n]=h
1481
+ /**
1482
+ * Inserts several blocks at once
1483
+ *
1484
+ * @param blocks - blocks to insert
1485
+ * @param index - index to insert blocks at
1486
+ */}insertMany(n,h){const p=new DocumentFragment;for(const h of n)p.appendChild(h.holder);if(this.length>0){if(h>0){const n=Math.min(h-1,this.length-1);this.blocks[n].holder.after(p)}else h===0&&this.workingArea.prepend(p);this.blocks.splice(h,0,...n)}else this.blocks.push(...n),this.workingArea.appendChild(p);n.forEach((n=>n.call($.RENDERED)))}
1487
+ /**
1488
+ * Remove block
1489
+ *
1490
+ * @param {number} index - index of Block to remove
1491
+ */remove(n){isNaN(n)&&(n=this.length-1),this.blocks[n].holder.remove(),this.blocks[n].call($.REMOVED),this.blocks.splice(n,1)}removeAll(){this.workingArea.innerHTML="",this.blocks.forEach((n=>n.call($.REMOVED))),this.blocks.length=0
1492
+ /**
1493
+ * Insert Block after passed target
1494
+ *
1495
+ * @todo decide if this method is necessary
1496
+ * @param {Block} targetBlock — target after which Block should be inserted
1497
+ * @param {Block} newBlock — Block to insert
1498
+ */}insertAfter(n,h){const p=this.blocks.indexOf(n);this.insert(p+1,h)}
1499
+ /**
1500
+ * Get Block by index
1501
+ *
1502
+ * @param {number} index — Block index
1503
+ * @returns {Block}
1504
+ */get(n){return this.blocks[n]}
1505
+ /**
1506
+ * Return index of passed Block
1507
+ *
1508
+ * @param {Block} block - Block to find
1509
+ * @returns {number}
1510
+ */indexOf(n){return this.blocks.indexOf(n)}
1511
+ /**
1512
+ * Insert new Block into DOM
1513
+ *
1514
+ * @param {Block} block - Block to insert
1515
+ * @param {InsertPosition} position — insert position (if set, will use insertAdjacentElement)
1516
+ * @param {Block} target — Block related to position
1517
+ */insertToDOM(n,h,p){h?p.holder.insertAdjacentElement(h,n.holder):this.workingArea.appendChild(n.holder),n.call($.RENDERED)
1518
+ /**
1519
+ * Composes Block event with passed type and details
1520
+ *
1521
+ * @param {string} type - event type
1522
+ * @param {object} detail - event detail
1523
+ */}composeBlockEvent(n,h){return new CustomEvent(n,{detail:h})}}const Jo="block-removed",di="block-added",hi="block-moved",bi="block-changed";class Qi{constructor(){this.completed=Promise.resolve()}
1524
+ /**
1525
+ * Add new promise to queue
1526
+ *
1527
+ * @param operation - promise should be added to queue
1528
+ */add(n){return new Promise(((h,p)=>{this.completed=this.completed.then(n).then(h).catch(p)}))}}class es extends y{constructor(){super(...arguments),this._currentBlockIndex=-1,this._blocks=null
1529
+ /**
1530
+ * Returns current Block index
1531
+ *
1532
+ * @returns {number}
1533
+ */}get currentBlockIndex(){return this._currentBlockIndex}
1534
+ /**
1535
+ * Set current Block index and fire Block lifecycle callbacks
1536
+ *
1537
+ * @param {number} newIndex - index of Block to set as current
1538
+ */set currentBlockIndex(n){this._currentBlockIndex=n}
1539
+ /**
1540
+ * returns first Block
1541
+ *
1542
+ * @returns {Block}
1543
+ */get firstBlock(){return this._blocks[0]}
1544
+ /**
1545
+ * returns last Block
1546
+ *
1547
+ * @returns {Block}
1548
+ */get lastBlock(){return this._blocks[this._blocks.length-1]}
1549
+ /**
1550
+ * Get current Block instance
1551
+ *
1552
+ * @returns {Block}
1553
+ */get currentBlock(){return this._blocks[this.currentBlockIndex]}
1554
+ /**
1555
+ * Set passed Block as a current
1556
+ *
1557
+ * @param block - block to set as a current
1558
+ */set currentBlock(n){this.currentBlockIndex=this.getBlockIndex(n)}
1559
+ /**
1560
+ * Returns next Block instance
1561
+ *
1562
+ * @returns {Block|null}
1563
+ */get nextBlock(){return this.currentBlockIndex===this._blocks.length-1?null:this._blocks[this.currentBlockIndex+1]}
1564
+ /**
1565
+ * Return first Block with inputs after current Block
1566
+ *
1567
+ * @returns {Block | undefined}
1568
+ */get nextContentfulBlock(){return this.blocks.slice(this.currentBlockIndex+1).find((n=>!!n.inputs.length))}
1569
+ /**
1570
+ * Return first Block with inputs before current Block
1571
+ *
1572
+ * @returns {Block | undefined}
1573
+ */get previousContentfulBlock(){return this.blocks.slice(0,this.currentBlockIndex).reverse().find((n=>!!n.inputs.length))}
1574
+ /**
1575
+ * Returns previous Block instance
1576
+ *
1577
+ * @returns {Block|null}
1578
+ */get previousBlock(){return this.currentBlockIndex===0?null:this._blocks[this.currentBlockIndex-1]}
1579
+ /**
1580
+ * Get array of Block instances
1581
+ *
1582
+ * @returns {Block[]} {@link Blocks#array}
1583
+ */get blocks(){return this._blocks.array}
1584
+ /**
1585
+ * Check if each Block is empty
1586
+ *
1587
+ * @returns {boolean}
1588
+ */get isEditorEmpty(){return this.blocks.every((n=>n.isEmpty))}prepare(){const n=new Xe(this.Editor.UI.nodes.redactor);this._blocks=new Proxy(n,{set:Xe.set,get:Xe.get}),this.listeners.on(document,"copy",(n=>this.Editor.BlockEvents.handleCommandC(n)))
1589
+ /**
1590
+ * Toggle read-only state
1591
+ *
1592
+ * If readOnly is true:
1593
+ * - Unbind event handlers from created Blocks
1594
+ *
1595
+ * if readOnly is false:
1596
+ * - Bind event handlers to all existing Blocks
1597
+ *
1598
+ * @param {boolean} readOnlyEnabled - "read only" state
1599
+ */}toggleReadOnly(n){n?this.disableModuleBindings():this.enableModuleBindings()}
1600
+ /**
1601
+ * Creates Block instance by tool name
1602
+ *
1603
+ * @param {object} options - block creation options
1604
+ * @param {string} options.tool - tools passed in editor config {@link EditorConfig#tools}
1605
+ * @param {string} [options.id] - unique id for this block
1606
+ * @param {BlockToolData} [options.data] - constructor params
1607
+ * @returns {Block}
1608
+ */composeBlock({tool:n,data:h={},id:p,tunes:g={}}){const m=this.Editor.ReadOnly.isEnabled,v=this.Editor.Tools.blockTools.get(n),x=new D({id:p,data:h,tool:v,api:this.Editor.API,readOnly:m,tunesData:g},this.eventsDispatcher);return m||window.requestIdleCallback((()=>{this.bindBlockEvents(x)}),{timeout:2e3}),x
1609
+ /**
1610
+ * Insert new block into _blocks
1611
+ *
1612
+ * @param {object} options - insert options
1613
+ * @param {string} [options.id] - block's unique id
1614
+ * @param {string} [options.tool] - plugin name, by default method inserts the default block type
1615
+ * @param {object} [options.data] - plugin data
1616
+ * @param {number} [options.index] - index where to insert new Block
1617
+ * @param {boolean} [options.needToFocus] - flag shows if needed to update current Block index
1618
+ * @param {boolean} [options.replace] - flag shows if block by passed index should be replaced with inserted one
1619
+ * @returns {Block}
1620
+ */}insert({id:n,tool:h=this.config.defaultBlock,data:p={},index:g,needToFocus:m=!0,replace:v=!1,tunes:x={}}={}){let w=g;w===void 0&&(w=this.currentBlockIndex+(v?0:1));const E=this.composeBlock({id:n,tool:h,data:p,tunes:x});return v&&this.blockDidMutated(Jo,this.getBlockByIndex(w),{index:w}),this._blocks.insert(w,E,v),this.blockDidMutated(di,E,{index:w}),m?this.currentBlockIndex=w:w<=this.currentBlockIndex&&this.currentBlockIndex++,E
1621
+ /**
1622
+ * Inserts several blocks at once
1623
+ *
1624
+ * @param blocks - blocks to insert
1625
+ * @param index - index where to insert
1626
+ */}insertMany(n,h=0){this._blocks.insertMany(n,h)}
1627
+ /**
1628
+ * Update Block data.
1629
+ *
1630
+ * Currently we don't have an 'update' method in the Tools API, so we just create a new block with the same id and type
1631
+ * Should not trigger 'block-removed' or 'block-added' events.
1632
+ *
1633
+ * If neither data nor tunes is provided, return the provided block instead.
1634
+ *
1635
+ * @param block - block to update
1636
+ * @param data - (optional) new data
1637
+ * @param tunes - (optional) tune data
1638
+ */async update(n,h,p){if(!h&&!p)return n;const g=await n.data,m=this.composeBlock({id:n.id,tool:n.name,data:Object.assign({},g,h??{}),tunes:p??n.tunes}),v=this.getBlockIndex(n);return this._blocks.replace(v,m),this.blockDidMutated(bi,m,{index:v}),m
1639
+ /**
1640
+ * Replace passed Block with the new one with specified Tool and data
1641
+ *
1642
+ * @param block - block to replace
1643
+ * @param newTool - new Tool name
1644
+ * @param data - new Tool data
1645
+ */}replace(n,h,p){const g=this.getBlockIndex(n);return this.insert({tool:h,data:p,index:g,replace:!0})}
1646
+ /**
1647
+ * Insert pasted content. Call onPaste callback after insert.
1648
+ *
1649
+ * @param {string} toolName - name of Tool to insert
1650
+ * @param {PasteEvent} pasteEvent - pasted data
1651
+ * @param {boolean} replace - should replace current block
1652
+ */paste(n,h,p=!1){const m=this.insert({tool:n,replace:p});try{window.requestIdleCallback((()=>{m.call($.ON_PASTE,h)}))}catch(h){g(`${n}: onPaste callback call is failed`,"error",h)}return m}
1653
+ /**
1654
+ * Insert new default block at passed index
1655
+ *
1656
+ * @param {number} index - index where Block should be inserted
1657
+ * @param {boolean} needToFocus - if true, updates current Block index
1658
+ *
1659
+ * TODO: Remove method and use insert() with index instead (?)
1660
+ * @returns {Block} inserted Block
1661
+ */insertDefaultBlockAtIndex(n,h=!1){const p=this.composeBlock({tool:this.config.defaultBlock});return this._blocks[n]=p,this.blockDidMutated(di,p,{index:n}),h?this.currentBlockIndex=n:n<=this.currentBlockIndex&&this.currentBlockIndex++,p
1662
+ /**
1663
+ * Always inserts at the end
1664
+ *
1665
+ * @returns {Block}
1666
+ */}insertAtEnd(){return this.currentBlockIndex=this.blocks.length-1,this.insert()
1667
+ /**
1668
+ * Merge two blocks
1669
+ *
1670
+ * @param {Block} targetBlock - previous block will be append to this block
1671
+ * @param {Block} blockToMerge - block that will be merged with target block
1672
+ * @returns {Promise} - the sequence that can be continued
1673
+ */}async mergeBlocks(n,h){let p;if(n.name===h.name&&n.mergeable){const g=await h.data;if(V(g)){console.error("Could not merge Block. Failed to extract original Block data.");return}const[m]=it([g],n.tool.sanitizeConfig);p=m}else if(n.mergeable&&_e(h,"export")&&_e(n,"import")){const g=await h.exportDataAsString(),m=q(g,n.tool.sanitizeConfig);p=xt(m,n.tool.conversionConfig)}p!==void 0&&(await n.mergeWith(p),this.removeBlock(h),this.currentBlockIndex=this._blocks.indexOf(n)
1674
+ /**
1675
+ * Remove passed Block
1676
+ *
1677
+ * @param block - Block to remove
1678
+ * @param addLastBlock - if true, adds new default block at the end. @todo remove this logic and use event-bus instead
1679
+ */)}removeBlock(n,h=!0){return new Promise((p=>{const g=this._blocks.indexOf(n);if(!this.validateIndex(g))throw new Error("Can't find a Block to remove");n.destroy(),this._blocks.remove(g),this.blockDidMutated(Jo,n,{index:g}),this.currentBlockIndex>=g&&this.currentBlockIndex--,this.blocks.length?g===0&&(this.currentBlockIndex=0):(this.unsetCurrentBlock(),h&&this.insert()),p()}))}
1680
+ /**
1681
+ * Remove only selected Blocks
1682
+ * and returns first Block index where started removing...
1683
+ *
1684
+ * @returns {number|undefined}
1685
+ */removeSelectedBlocks(){let n;for(let h=this.blocks.length-1;h>=0;h--)this.blocks[h].selected&&(this.removeBlock(this.blocks[h]),n=h);return n}removeAllBlocks(){for(let n=this.blocks.length-1;n>=0;n--)this._blocks.remove(n);this.unsetCurrentBlock(),this.insert(),this.currentBlock.firstInput.focus()
1686
+ /**
1687
+ * Split current Block
1688
+ * 1. Extract content from Caret position to the Block`s end
1689
+ * 2. Insert a new Block below current one with extracted content
1690
+ *
1691
+ * @returns {Block}
1692
+ */}split(){const n=this.Editor.Caret.extractFragmentFromCaretPosition(),h=d.make("div");h.appendChild(n);const p={text:d.isEmpty(h)?"":h.innerHTML};return this.insert({data:p})}
1693
+ /**
1694
+ * Returns Block by passed index
1695
+ *
1696
+ * @param {number} index - index to get. -1 to get last
1697
+ * @returns {Block}
1698
+ */getBlockByIndex(n){return n===-1&&(n=this._blocks.length-1),this._blocks[n]
1699
+ /**
1700
+ * Returns an index for passed Block
1701
+ *
1702
+ * @param block - block to find index
1703
+ */}getBlockIndex(n){return this._blocks.indexOf(n)}
1704
+ /**
1705
+ * Returns the Block by passed id
1706
+ *
1707
+ * @param id - id of block to get
1708
+ * @returns {Block}
1709
+ */getBlockById(n){return this._blocks.array.find((h=>h.id===n))}
1710
+ /**
1711
+ * Get Block instance by html element
1712
+ *
1713
+ * @param {Node} element - html element to get Block by
1714
+ */getBlock(n){d.isElement(n)||(n=n.parentNode);const h=this._blocks.nodes,p=n.closest(`.${D.CSS.wrapper}`),g=h.indexOf(p);if(g>=0)return this._blocks[g]}
1715
+ /**
1716
+ * 1) Find first-level Block from passed child Node
1717
+ * 2) Mark it as current
1718
+ *
1719
+ * @param {Node} childNode - look ahead from this node.
1720
+ * @returns {Block | undefined} can return undefined in case when the passed child note is not a part of the current editor instance
1721
+ */setCurrentBlockByChildNode(n){d.isElement(n)||(n=n.parentNode);const h=n.closest(`.${D.CSS.wrapper}`);if(!h)return;const p=h.closest(`.${this.Editor.UI.CSS.editorWrapper}`);return p!=null&&p.isEqualNode(this.Editor.UI.nodes.wrapper)?(this.currentBlockIndex=this._blocks.nodes.indexOf(h),this.currentBlock.updateCurrentInput(),this.currentBlock
1722
+ /**
1723
+ * Return block which contents passed node
1724
+ *
1725
+ * @param {Node} childNode - node to get Block by
1726
+ * @returns {Block}
1727
+ */):void 0}getBlockByChildNode(n){if(!n||!(n instanceof Node))return;d.isElement(n)||(n=n.parentNode);const h=n.closest(`.${D.CSS.wrapper}`);return this.blocks.find((n=>n.holder===h))}
1728
+ /**
1729
+ * Swap Blocks Position
1730
+ *
1731
+ * @param {number} fromIndex - index of first block
1732
+ * @param {number} toIndex - index of second block
1733
+ * @deprecated — use 'move' instead
1734
+ */swap(n,h){this._blocks.swap(n,h),this.currentBlockIndex=h
1735
+ /**
1736
+ * Move a block to a new index
1737
+ *
1738
+ * @param {number} toIndex - index where to move Block
1739
+ * @param {number} fromIndex - index of Block to move
1740
+ */}move(n,h=this.currentBlockIndex){isNaN(n)||isNaN(h)?g("Warning during 'move' call: incorrect indices provided.","warn"):this.validateIndex(n)&&this.validateIndex(h)?(this._blocks.move(n,h),this.currentBlockIndex=n,this.blockDidMutated(hi,this.currentBlock,{fromIndex:h,toIndex:n})
1741
+ /**
1742
+ * Converts passed Block to the new Tool
1743
+ * Uses Conversion Config
1744
+ *
1745
+ * @param blockToConvert - Block that should be converted
1746
+ * @param targetToolName - name of the Tool to convert to
1747
+ * @param blockDataOverrides - optional new Block data overrides
1748
+ */):g("Warning during 'move' call: indices cannot be lower than 0 or greater than the amount of blocks.","warn")}async convert(n,h,p){if(!await n.save())throw new Error("Could not convert Block. Failed to extract original Block data.");const g=this.Editor.Tools.blockTools.get(h);if(!g)throw new Error(`Could not convert Block. Tool «${h}» not found.`);const m=await n.exportDataAsString(),v=q(m,g.sanitizeConfig);let x=xt(v,g.conversionConfig);return p&&(x=Object.assign(x,p)),this.replace(n,g.name,x)}unsetCurrentBlock(){this.currentBlockIndex=-1}
1749
+ /**
1750
+ * Clears Editor
1751
+ *
1752
+ * @param {boolean} needToAddDefaultBlock - 1) in internal calls (for example, in api.blocks.render)
1753
+ * we don't need to add an empty default block
1754
+ * 2) in api.blocks.clear we should add empty block
1755
+ */async clear(n=!1){const h=new Qi;this.blocks.forEach((n=>{h.add((async()=>{await this.removeBlock(n,!1)}))})),await h.completed,this.unsetCurrentBlock(),n&&this.insert(),this.Editor.UI.checkEmptiness()}async destroy(){await Promise.all(this.blocks.map((n=>n.destroy())))}
1756
+ /**
1757
+ * Bind Block events
1758
+ *
1759
+ * @param {Block} block - Block to which event should be bound
1760
+ */bindBlockEvents(n){const{BlockEvents:h}=this.Editor;this.readOnlyMutableListeners.on(n.holder,"keydown",(n=>{h.keydown(n)})),this.readOnlyMutableListeners.on(n.holder,"keyup",(n=>{h.keyup(n)})),this.readOnlyMutableListeners.on(n.holder,"dragover",(n=>{h.dragOver(n)})),this.readOnlyMutableListeners.on(n.holder,"dragleave",(n=>{h.dragLeave(n)})),n.on("didMutated",(n=>this.blockDidMutated(bi,n,{index:this.getBlockIndex(n)})))}disableModuleBindings(){this.readOnlyMutableListeners.clearAll()}enableModuleBindings(){this.readOnlyMutableListeners.on(document,"cut",(n=>this.Editor.BlockEvents.handleCommandX(n))),this.blocks.forEach((n=>{this.bindBlockEvents(n)}))
1761
+ /**
1762
+ * Validates that the given index is not lower than 0 or higher than the amount of blocks
1763
+ *
1764
+ * @param {number} index - index of blocks array to validate
1765
+ * @returns {boolean}
1766
+ */}validateIndex(n){return!(n<0||n>=this._blocks.length)}
1767
+ /**
1768
+ * Block mutation callback
1769
+ *
1770
+ * @param mutationType - what happened with block
1771
+ * @param block - mutated block
1772
+ * @param detailData - additional data to pass with change event
1773
+ */blockDidMutated(n,h,p){const g=new CustomEvent(n,{detail:{target:new G(h),...p}});return this.eventsDispatcher.emit(N,{event:g}),h}}class ts extends y{constructor(){super(...arguments),this.anyBlockSelectedCache=null,this.needToSelectAll=!1,this.nativeInputSelected=!1,this.readyToBlockSelection=!1
1774
+ /**
1775
+ * Sanitizer Config
1776
+ *
1777
+ * @returns {SanitizerConfig}
1778
+ */}get sanitizerConfig(){return{p:{},h1:{},h2:{},h3:{},h4:{},h5:{},h6:{},ol:{},ul:{},li:{},br:!0,img:{src:!0,width:!0,height:!0},a:{href:!0},b:{},i:{},u:{}}}
1779
+ /**
1780
+ * Flag that identifies all Blocks selection
1781
+ *
1782
+ * @returns {boolean}
1783
+ */get allBlocksSelected(){const{BlockManager:n}=this.Editor;return n.blocks.every((n=>n.selected===!0))}
1784
+ /**
1785
+ * Set selected all blocks
1786
+ *
1787
+ * @param {boolean} state - state to set
1788
+ */set allBlocksSelected(n){const{BlockManager:h}=this.Editor;h.blocks.forEach((h=>{h.selected=n})),this.clearCache()
1789
+ /**
1790
+ * Flag that identifies any Block selection
1791
+ *
1792
+ * @returns {boolean}
1793
+ */}get anyBlockSelected(){const{BlockManager:n}=this.Editor;return this.anyBlockSelectedCache===null&&(this.anyBlockSelectedCache=n.blocks.some((n=>n.selected===!0))),this.anyBlockSelectedCache
1794
+ /**
1795
+ * Return selected Blocks array
1796
+ *
1797
+ * @returns {Block[]}
1798
+ */}get selectedBlocks(){return this.Editor.BlockManager.blocks.filter((n=>n.selected))}prepare(){this.selection=new b,io.add({name:"CMD+A",handler:n=>{const{BlockManager:h,ReadOnly:p}=this.Editor;p.isEnabled?(n.preventDefault(),this.selectAllBlocks()):h.currentBlock&&this.handleCommandA(n)},on:this.Editor.UI.nodes.redactor})}toggleReadOnly(){b.get().removeAllRanges(),this.allBlocksSelected=!1
1799
+ /**
1800
+ * Remove selection of Block
1801
+ *
1802
+ * @param {number?} index - Block index according to the BlockManager's indexes
1803
+ */}unSelectBlockByIndex(n){const{BlockManager:h}=this.Editor;let p;p=isNaN(n)?h.currentBlock:h.getBlockByIndex(n),p.selected=!1,this.clearCache()
1804
+ /**
1805
+ * Clear selection from Blocks
1806
+ *
1807
+ * @param {Event} reason - event caused clear of selection
1808
+ * @param {boolean} restoreSelection - if true, restore saved selection
1809
+ */}clearSelection(n,h=!1){const{BlockManager:p,Caret:g,RectangleSelection:m}=this.Editor;this.needToSelectAll=!1,this.nativeInputSelected=!1,this.readyToBlockSelection=!1;const v=n&&n instanceof KeyboardEvent,x=v&&Mt(n.keyCode);if(this.anyBlockSelected&&v&&x&&!b.isSelectionExists){const h=p.removeSelectedBlocks();p.insertDefaultBlockAtIndex(h,!0),g.setToBlock(p.currentBlock),Oe((()=>{const h=n.key;g.insertContentAtCaretPosition(h.length>1?"":h)}),20)()}this.Editor.CrossBlockSelection.clear(n),this.anyBlockSelected&&!m.isRectActivated()?(h&&this.selection.restore(),this.allBlocksSelected=!1
1810
+ /**
1811
+ * Reduce each Block and copy its content
1812
+ *
1813
+ * @param {ClipboardEvent} e - copy/cut event
1814
+ * @returns {Promise<void>}
1815
+ */):this.Editor.RectangleSelection.clearSelection()}copySelectedBlocks(n){n.preventDefault();const h=d.make("div");this.selectedBlocks.forEach((n=>{const p=q(n.holder.innerHTML,this.sanitizerConfig),g=d.make("p");g.innerHTML=p,h.appendChild(g)}));const p=Array.from(h.childNodes).map((n=>n.textContent)).join("\n\n"),g=h.innerHTML;return n.clipboardData.setData("text/plain",p),n.clipboardData.setData("text/html",g),Promise.all(this.selectedBlocks.map((n=>n.save()))).then((h=>{try{n.clipboardData.setData(this.Editor.Paste.MIME_TYPE,JSON.stringify(h))}catch{}}))
1816
+ /**
1817
+ * Select Block by its index
1818
+ *
1819
+ * @param {number?} index - Block index according to the BlockManager's indexes
1820
+ */}selectBlockByIndex(n){const{BlockManager:h}=this.Editor,p=h.getBlockByIndex(n);p!==void 0&&this.selectBlock(p)}
1821
+ /**
1822
+ * Select passed Block
1823
+ *
1824
+ * @param {Block} block - Block to select
1825
+ */selectBlock(n){this.selection.save(),b.get().removeAllRanges(),n.selected=!0,this.clearCache(),this.Editor.InlineToolbar.close()
1826
+ /**
1827
+ * Remove selection from passed Block
1828
+ *
1829
+ * @param {Block} block - Block to unselect
1830
+ */}unselectBlock(n){n.selected=!1,this.clearCache()}clearCache(){this.anyBlockSelectedCache=null}destroy(){io.remove(this.Editor.UI.nodes.redactor,"CMD+A")}
1831
+ /**
1832
+ * First CMD+A selects all input content by native behaviour,
1833
+ * next CMD+A keypress selects all blocks
1834
+ *
1835
+ * @param {KeyboardEvent} event - keyboard event
1836
+ */handleCommandA(n){if(this.Editor.RectangleSelection.clearSelection(),d.isNativeInput(n.target)&&!this.readyToBlockSelection){this.readyToBlockSelection=!0;return}const h=this.Editor.BlockManager.getBlock(n.target),p=h.inputs;p.length>1&&!this.readyToBlockSelection?this.readyToBlockSelection=!0:p.length!==1||this.needToSelectAll?this.needToSelectAll?(n.preventDefault(),this.selectAllBlocks(),this.needToSelectAll=!1,this.readyToBlockSelection=!1):this.readyToBlockSelection&&(n.preventDefault(),this.selectBlock(h),this.needToSelectAll=!0):this.needToSelectAll=!0}selectAllBlocks(){this.selection.save(),b.get().removeAllRanges(),this.allBlocksSelected=!0,this.Editor.InlineToolbar.close()}}class Re extends y{
1837
+ /**
1838
+ * Allowed caret positions in input
1839
+ *
1840
+ * @static
1841
+ * @returns {{START: string, END: string, DEFAULT: string}}
1842
+ */
1843
+ get positions(){return{START:"start",END:"end",DEFAULT:"default"}}static get CSS(){return{shadowCaret:"cdx-shadow-caret"}}
1844
+ /**
1845
+ * Method gets Block instance and puts caret to the text node with offset
1846
+ * There two ways that method applies caret position:
1847
+ * - first found text node: sets at the beginning, but you can pass an offset
1848
+ * - last found text node: sets at the end of the node. Also, you can customize the behaviour
1849
+ *
1850
+ * @param {Block} block - Block class
1851
+ * @param {string} position - position where to set caret.
1852
+ * If default - leave default behaviour and apply offset if it's passed
1853
+ * @param {number} offset - caret offset regarding to the text node
1854
+ */setToBlock(n,h=this.positions.DEFAULT,p=0){var g;const{BlockManager:m,BlockSelection:v}=this.Editor;if(v.clearSelection(),!n.focusable){(g=window.getSelection())==null||g.removeAllRanges(),v.selectBlock(n),m.currentBlock=n;return}let x;switch(h){case this.positions.START:x=n.firstInput;break;case this.positions.END:x=n.lastInput;break;default:x=n.currentInput}if(!x)return;const w=d.getDeepestNode(x,h===this.positions.END),E=d.getContentLength(w);switch(!0){case h===this.positions.START:p=0;break;case h===this.positions.END:case p>E:p=E;break}this.set(w,p),m.setCurrentBlockByChildNode(n.holder),m.currentBlock.currentInput=x
1855
+ /**
1856
+ * Set caret to the current input of current Block.
1857
+ *
1858
+ * @param {HTMLElement} input - input where caret should be set
1859
+ * @param {string} position - position of the caret.
1860
+ * If default - leave default behaviour and apply offset if it's passed
1861
+ * @param {number} offset - caret offset regarding to the text node
1862
+ */}setToInput(n,h=this.positions.DEFAULT,p=0){const{currentBlock:g}=this.Editor.BlockManager,m=d.getDeepestNode(n);switch(h){case this.positions.START:this.set(m,0);break;case this.positions.END:this.set(m,d.getContentLength(m));break;default:p&&this.set(m,p)}g.currentInput=n}
1863
+ /**
1864
+ * Creates Document Range and sets caret to the element with offset
1865
+ *
1866
+ * @param {HTMLElement} element - target node.
1867
+ * @param {number} offset - offset
1868
+ */set(n,h=0){const{top:p,bottom:g}=b.setCursor(n,h),{innerHeight:m}=window;p<0?window.scrollBy(0,p-30):g>m&&window.scrollBy(0,g-m+30)}setToTheLastBlock(){const n=this.Editor.BlockManager.lastBlock;if(n)if(n.tool.isDefault&&n.isEmpty)this.setToBlock(n);else{const n=this.Editor.BlockManager.insertAtEnd();this.setToBlock(n)}}extractFragmentFromCaretPosition(){const n=b.get();if(n.rangeCount){const h=n.getRangeAt(0),p=this.Editor.BlockManager.currentBlock.currentInput;if(h.deleteContents(),p){if(d.isNativeInput(p)){const n=p,h=document.createDocumentFragment(),g=n.value.substring(0,n.selectionStart),m=n.value.substring(n.selectionStart);return h.textContent=m,n.value=g,h}{const n=h.cloneRange();return n.selectNodeContents(p),n.setStart(h.endContainer,h.endOffset),n.extractContents()}}}}
1869
+ /**
1870
+ * Set's caret to the next Block or Tool`s input
1871
+ * Before moving caret, we should check if caret position is at the end of Plugins node
1872
+ * Using {@link Dom#getDeepestNode} to get a last node and match with current selection
1873
+ *
1874
+ * @param {boolean} force - pass true to skip check for caret position
1875
+ */navigateNext(n=!1){const{BlockManager:h}=this.Editor,{currentBlock:p,nextBlock:g}=h;if(p===void 0)return!1;const{nextInput:m,currentInput:v}=p,x=v!==void 0?Ae(v):void 0;let w=g;const E=n||x||!p.focusable;if(m&&E)return this.setToInput(m,this.positions.START),!0;if(w===null){if(p.tool.isDefault||!E)return!1;w=h.insertAtEnd()}return!!E&&(this.setToBlock(w,this.positions.START),!0)}
1876
+ /**
1877
+ * Set's caret to the previous Tool`s input or Block
1878
+ * Before moving caret, we should check if caret position is start of the Plugins node
1879
+ * Using {@link Dom#getDeepestNode} to get a last node and match with current selection
1880
+ *
1881
+ * @param {boolean} force - pass true to skip check for caret position
1882
+ */navigatePrevious(n=!1){const{currentBlock:h,previousBlock:p}=this.Editor.BlockManager;if(!h)return!1;const{previousInput:g,currentInput:m}=h,v=m!==void 0?Me(m):void 0,x=n||v||!h.focusable;return g&&x?(this.setToInput(g,this.positions.END),!0):!(p===null||!x)&&(this.setToBlock(p,this.positions.END),!0)}
1883
+ /**
1884
+ * Inserts shadow element after passed element where caret can be placed
1885
+ *
1886
+ * @param {Element} element - element after which shadow caret should be inserted
1887
+ */createShadow(n){const h=document.createElement("span");h.classList.add(Re.CSS.shadowCaret),n.insertAdjacentElement("beforeend",h)
1888
+ /**
1889
+ * Restores caret position
1890
+ *
1891
+ * @param {HTMLElement} element - element where caret should be restored
1892
+ */}restoreCaret(n){const h=n.querySelector(`.${Re.CSS.shadowCaret}`);if(!h)return;(new b).expandToTag(h);const p=document.createRange();p.selectNode(h),p.extractContents()
1893
+ /**
1894
+ * Inserts passed content at caret position
1895
+ *
1896
+ * @param {string} content - content to insert
1897
+ */}insertContentAtCaretPosition(n){const h=document.createDocumentFragment(),p=document.createElement("div"),g=b.get(),m=b.range;p.innerHTML=n,Array.from(p.childNodes).forEach((n=>h.appendChild(n))),h.childNodes.length===0&&h.appendChild(new Text);const v=h.lastChild;m.deleteContents(),m.insertNode(h);const x=document.createRange(),w=v.nodeType===Node.TEXT_NODE?v:v.firstChild;w!==null&&w.textContent!==null&&x.setStart(w,w.textContent.length),g.removeAllRanges(),g.addRange(x)}}class os extends y{constructor(){super(...arguments),this.onMouseUp=()=>{this.listeners.off(document,"mouseover",this.onMouseOver),this.listeners.off(document,"mouseup",this.onMouseUp)},this.onMouseOver=n=>{const{BlockManager:h,BlockSelection:p}=this.Editor;if(n.relatedTarget===null&&n.target===null)return;const g=h.getBlockByChildNode(n.relatedTarget)||this.lastSelectedBlock,m=h.getBlockByChildNode(n.target);if(!(!g||!m)&&m!==g){if(g===this.firstSelectedBlock){b.get().removeAllRanges(),g.selected=!0,m.selected=!0,p.clearCache();return}if(m===this.firstSelectedBlock){g.selected=!1,m.selected=!1,p.clearCache();return}this.Editor.InlineToolbar.close(),this.toggleBlocksSelectedState(g,m),this.lastSelectedBlock=m}}
1898
+ /**
1899
+ * Module preparation
1900
+ *
1901
+ * @returns {Promise}
1902
+ */}async prepare(){this.listeners.on(document,"mousedown",(n=>{this.enableCrossBlockSelection(n)}))}
1903
+ /**
1904
+ * Sets up listeners
1905
+ *
1906
+ * @param {MouseEvent} event - mouse down event
1907
+ */watchSelection(n){if(n.button!==p.LEFT)return;const{BlockManager:h}=this.Editor;this.firstSelectedBlock=h.getBlock(n.target),this.lastSelectedBlock=this.firstSelectedBlock,this.listeners.on(document,"mouseover",this.onMouseOver),this.listeners.on(document,"mouseup",this.onMouseUp)}get isCrossBlockSelectionStarted(){return!!this.firstSelectedBlock&&!!this.lastSelectedBlock&&this.firstSelectedBlock!==this.lastSelectedBlock}
1908
+ /**
1909
+ * Change selection state of the next Block
1910
+ * Used for CBS via Shift + arrow keys
1911
+ *
1912
+ * @param {boolean} next - if true, toggle next block. Previous otherwise
1913
+ */toggleBlockSelectedState(n=!0){const{BlockManager:h,BlockSelection:p}=this.Editor;this.lastSelectedBlock||(this.lastSelectedBlock=this.firstSelectedBlock=h.currentBlock),this.firstSelectedBlock===this.lastSelectedBlock&&(this.firstSelectedBlock.selected=!0,p.clearCache(),b.get().removeAllRanges());const g=h.blocks.indexOf(this.lastSelectedBlock)+(n?1:-1),m=h.blocks[g];m&&(this.lastSelectedBlock.selected!==m.selected?(m.selected=!0,p.clearCache()):(this.lastSelectedBlock.selected=!1,p.clearCache()),this.lastSelectedBlock=m,this.Editor.InlineToolbar.close(),m.holder.scrollIntoView({block:"nearest"})
1914
+ /**
1915
+ * Clear saved state
1916
+ *
1917
+ * @param {Event} reason - event caused clear of selection
1918
+ */)}clear(n){const{BlockManager:p,BlockSelection:g,Caret:m}=this.Editor,v=p.blocks.indexOf(this.firstSelectedBlock),x=p.blocks.indexOf(this.lastSelectedBlock);if(g.anyBlockSelected&&v>-1&&x>-1&&n&&n instanceof KeyboardEvent)switch(n.keyCode){case h.DOWN:case h.RIGHT:m.setToBlock(p.blocks[Math.max(v,x)],m.positions.END);break;case h.UP:case h.LEFT:m.setToBlock(p.blocks[Math.min(v,x)],m.positions.START);break;default:m.setToBlock(p.blocks[Math.max(v,x)],m.positions.END)}this.firstSelectedBlock=this.lastSelectedBlock=null}
1919
+ /**
1920
+ * Enables Cross Block Selection
1921
+ *
1922
+ * @param {MouseEvent} event - mouse down event
1923
+ */enableCrossBlockSelection(n){const{UI:h}=this.Editor;b.isCollapsed||this.Editor.BlockSelection.clearSelection(n),h.nodes.redactor.contains(n.target)?this.watchSelection(n):this.Editor.BlockSelection.clearSelection(n)
1924
+ /**
1925
+ * Change blocks selection state between passed two blocks.
1926
+ *
1927
+ * @param {Block} firstBlock - first block in range
1928
+ * @param {Block} lastBlock - last block in range
1929
+ */}toggleBlocksSelectedState(n,h){const{BlockManager:p,BlockSelection:g}=this.Editor,m=p.blocks.indexOf(n),v=p.blocks.indexOf(h),x=n.selected!==h.selected;for(let w=Math.min(m,v);w<=Math.max(m,v);w++){const m=p.blocks[w];m!==this.firstSelectedBlock&&m!==(x?n:h)&&(p.blocks[w].selected=!p.blocks[w].selected,g.clearCache())}}}class is extends y{constructor(){super(...arguments),this.isStartedAtEditor=!1
1930
+ /**
1931
+ * Toggle read-only state
1932
+ *
1933
+ * if state is true:
1934
+ * - disable all drag-n-drop event handlers
1935
+ *
1936
+ * if state is false:
1937
+ * - restore drag-n-drop event handlers
1938
+ *
1939
+ * @param {boolean} readOnlyEnabled - "read only" state
1940
+ */}toggleReadOnly(n){n?this.disableModuleBindings():this.enableModuleBindings()}enableModuleBindings(){const{UI:n}=this.Editor;this.readOnlyMutableListeners.on(n.nodes.holder,"drop",(async n=>{await this.processDrop(n)}),!0),this.readOnlyMutableListeners.on(n.nodes.holder,"dragstart",(()=>{this.processDragStart()})),this.readOnlyMutableListeners.on(n.nodes.holder,"dragover",(n=>{this.processDragOver(n)}),!0)}disableModuleBindings(){this.readOnlyMutableListeners.clearAll()}
1941
+ /**
1942
+ * Handle drop event
1943
+ *
1944
+ * @param {DragEvent} dropEvent - drop event
1945
+ */async processDrop(n){const{BlockManager:h,Paste:p,Caret:g}=this.Editor;n.preventDefault(),h.blocks.forEach((n=>{n.dropTarget=!1})),b.isAtEditor&&!b.isCollapsed&&this.isStartedAtEditor&&document.execCommand("delete"),this.isStartedAtEditor=!1;const m=h.setCurrentBlockByChildNode(n.target);if(m)this.Editor.Caret.setToBlock(m,g.positions.END);else{const n=h.setCurrentBlockByChildNode(h.lastBlock.holder);this.Editor.Caret.setToBlock(n,g.positions.END)}await p.processDataTransfer(n.dataTransfer,!0)}processDragStart(){b.isAtEditor&&!b.isCollapsed&&(this.isStartedAtEditor=!0),this.Editor.InlineToolbar.close()
1946
+ /**
1947
+ * @param {DragEvent} dragEvent - drag event
1948
+ */}processDragOver(n){n.preventDefault()}}const vi=180,ki=400;class rs extends y{
1949
+ /**
1950
+ * Prepare the module
1951
+ *
1952
+ * @param options - options used by the modification observer module
1953
+ * @param options.config - Editor configuration object
1954
+ * @param options.eventsDispatcher - common Editor event bus
1955
+ */
1956
+ constructor({config:n,eventsDispatcher:h}){super({config:n,eventsDispatcher:h}),this.disabled=!1,this.batchingTimeout=null,this.batchingOnChangeQueue=new Map,this.batchTime=ki,this.mutationObserver=new MutationObserver((n=>{this.redactorChanged(n)})),this.eventsDispatcher.on(N,(n=>{this.particularBlockChanged(n.event)})),this.eventsDispatcher.on(P,(()=>{this.disable()})),this.eventsDispatcher.on(H,(()=>{this.enable()}))}enable(){this.mutationObserver.observe(this.Editor.UI.nodes.redactor,{childList:!0,subtree:!0,characterData:!0,attributes:!0}),this.disabled=!1}disable(){this.mutationObserver.disconnect(),this.disabled=!0
1957
+ /**
1958
+ * Call onChange event passed to Editor.js configuration
1959
+ *
1960
+ * @param event - some of our custom change events
1961
+ */}particularBlockChanged(n){this.disabled||!O(this.config.onChange)||(this.batchingOnChangeQueue.set(`block:${n.detail.target.id}:event:${n.type}`,n),this.batchingTimeout&&clearTimeout(this.batchingTimeout),this.batchingTimeout=setTimeout((()=>{let n;n=this.batchingOnChangeQueue.size===1?this.batchingOnChangeQueue.values().next().value:Array.from(this.batchingOnChangeQueue.values()),this.config.onChange&&this.config.onChange(this.Editor.API.methods,n),this.batchingOnChangeQueue.clear()}),this.batchTime)
1962
+ /**
1963
+ * Fired on every blocks wrapper dom change
1964
+ *
1965
+ * @param mutations - mutations happened
1966
+ */)}redactorChanged(n){this.eventsDispatcher.emit(L,{mutations:n})}}const yi=class lo extends y{constructor(){super(...arguments),this.MIME_TYPE="application/x-editor-js",this.toolsTags={},this.tagsByTool={},this.toolsPatterns=[],this.toolsFiles={},this.exceptionList=[],this.processTool=n=>{try{const h=n.create({},{},!1);if(n.pasteConfig===!1){this.exceptionList.push(n.name);return}if(!O(h.onPaste))return;this.getTagsConfig(n),this.getFilesConfig(n),this.getPatternsConfig(n)}catch(h){g(`Paste handling for «${n.name}» Tool hasn't been set up because of the error`,"warn",h)}},this.handlePasteEvent=async n=>{const{BlockManager:h,Toolbar:p}=this.Editor,g=h.setCurrentBlockByChildNode(n.target);!g||this.isNativeBehaviour(n.target)&&!n.clipboardData.types.includes("Files")||g&&this.exceptionList.includes(g.name)||(n.preventDefault(),this.processDataTransfer(n.clipboardData),p.close())}}async prepare(){this.processTools()}
1967
+ /**
1968
+ * Set read-only state
1969
+ *
1970
+ * @param {boolean} readOnlyEnabled - read only flag value
1971
+ */toggleReadOnly(n){n?this.unsetCallback():this.setCallback()}
1972
+ /**
1973
+ * Handle pasted or dropped data transfer object
1974
+ *
1975
+ * @param {DataTransfer} dataTransfer - pasted or dropped data transfer object
1976
+ * @param {boolean} isDragNDrop - true if data transfer comes from drag'n'drop events
1977
+ */async processDataTransfer(n,h=!1){const{Tools:p}=this.Editor,g=n.types;if((g.includes?g.includes("Files"):g.contains("Files"))&&!V(this.toolsFiles)){await this.processFiles(n.files);return}const m=n.getData(this.MIME_TYPE),v=n.getData("text/plain");let x=n.getData("text/html");if(m)try{this.insertEditorJSData(JSON.parse(m));return}catch{}h&&v.trim()&&x.trim()&&(x="<p>"+(x.trim()?x:v)+"</p>");const w=Object.keys(this.toolsTags).reduce(((n,h)=>(n[h.toLowerCase()]=this.toolsTags[h].sanitizationConfig??{},n)),{}),E=Object.assign({},w,p.getAllInlineToolsSanitizeConfig(),{br:{}}),B=q(x,E);B.trim()&&B.trim()!==v&&d.isHTMLString(B)?await this.processText(B,!0):await this.processText(v)}
1978
+ /**
1979
+ * Process pasted text and divide them into Blocks
1980
+ *
1981
+ * @param {string} data - text to process. Can be HTML or plain.
1982
+ * @param {boolean} isHTML - if passed string is HTML, this parameter should be true
1983
+ */async processText(n,h=!1){const{Caret:p,BlockManager:g}=this.Editor,m=h?this.processHTML(n):this.processPlain(n);if(!m.length)return;if(m.length===1){m[0].isBlock?this.processSingleBlock(m.pop()):this.processInlinePaste(m.pop());return}const v=g.currentBlock&&g.currentBlock.tool.isDefault&&g.currentBlock.isEmpty;m.map((async(n,h)=>this.insertBlock(n,h===0&&v))),g.currentBlock&&p.setToBlock(g.currentBlock,p.positions.END)}setCallback(){this.listeners.on(this.Editor.UI.nodes.holder,"paste",this.handlePasteEvent)}unsetCallback(){this.listeners.off(this.Editor.UI.nodes.holder,"paste",this.handlePasteEvent)}processTools(){const n=this.Editor.Tools.blockTools;Array.from(n.values()).forEach(this.processTool)}
1984
+ /**
1985
+ * Get tags name list from either tag name or sanitization config.
1986
+ *
1987
+ * @param {string | object} tagOrSanitizeConfig - tag name or sanitize config object.
1988
+ * @returns {string[]} array of tags.
1989
+ */collectTagNames(n){return Q(n)?[n]:R(n)?Object.keys(n):[]}
1990
+ /**
1991
+ * Get tags to substitute by Tool
1992
+ *
1993
+ * @param tool - BlockTool object
1994
+ */getTagsConfig(n){if(n.pasteConfig===!1)return;const h=n.pasteConfig.tags||[],p=[];h.forEach((h=>{const m=this.collectTagNames(h);p.push(...m),m.forEach((p=>{if(Object.prototype.hasOwnProperty.call(this.toolsTags,p)){g(`Paste handler for «${n.name}» Tool on «${p}» tag is skipped because it is already used by «${this.toolsTags[p].tool.name}» Tool.`,"warn");return}const m=R(h)?h[p]:null;this.toolsTags[p.toUpperCase()]={tool:n,sanitizationConfig:m}}))})),this.tagsByTool[n.name]=p.map((n=>n.toUpperCase()))
1995
+ /**
1996
+ * Get files` types and extensions to substitute by Tool
1997
+ *
1998
+ * @param tool - BlockTool object
1999
+ */}getFilesConfig(n){if(n.pasteConfig===!1)return;const{files:h={}}=n.pasteConfig;let{extensions:p,mimeTypes:m}=h;!p&&!m||(p&&!Array.isArray(p)&&(g(`«extensions» property of the onDrop config for «${n.name}» Tool should be an array`),p=[]),m&&!Array.isArray(m)&&(g(`«mimeTypes» property of the onDrop config for «${n.name}» Tool should be an array`),m=[]),m&&(m=m.filter((h=>!!To(h)||(g(`MIME type value «${h}» for the «${n.name}» Tool is not a valid MIME type`,"warn"),!1)))),this.toolsFiles[n.name]={extensions:p||[],mimeTypes:m||[]}
2000
+ /**
2001
+ * Get RegExp patterns to substitute by Tool
2002
+ *
2003
+ * @param tool - BlockTool object
2004
+ */)}getPatternsConfig(n){n.pasteConfig===!1||!n.pasteConfig.patterns||V(n.pasteConfig.patterns)||Object.entries(n.pasteConfig.patterns).forEach((([h,p])=>{p instanceof RegExp||g(`Pattern ${p} for «${n.name}» Tool is skipped because it should be a Regexp instance.`,"warn"),this.toolsPatterns.push({key:h,pattern:p,tool:n})}))}
2005
+ /**
2006
+ * Check if browser behavior suits better
2007
+ *
2008
+ * @param {EventTarget} element - element where content has been pasted
2009
+ * @returns {boolean}
2010
+ */isNativeBehaviour(n){return d.isNativeInput(n)}
2011
+ /**
2012
+ * Get files from data transfer object and insert related Tools
2013
+ *
2014
+ * @param {FileList} items - pasted or dropped items
2015
+ */async processFiles(n){const{BlockManager:h}=this.Editor;let p;p=await Promise.all(Array.from(n).map((n=>this.processFile(n)))),p=p.filter((n=>!!n));const g=h.currentBlock.tool.isDefault&&h.currentBlock.isEmpty;p.forEach(((n,p)=>{h.paste(n.type,n.event,p===0&&g)}))}
2016
+ /**
2017
+ * Get information about file and find Tool to handle it
2018
+ *
2019
+ * @param {File} file - file to process
2020
+ */async processFile(n){const h=Bo(n),p=Object.entries(this.toolsFiles).find((([p,{mimeTypes:g,extensions:m}])=>{const[v,x]=n.type.split("/"),w=m.find((n=>n.toLowerCase()===h.toLowerCase())),E=g.find((n=>{const[h,p]=n.split("/");return h===v&&(p===x||p==="*")}));return!!w||!!E}));if(!p)return;const[g]=p;return{event:this.composePasteEvent("file",{file:n}),type:g}}
2021
+ /**
2022
+ * Split HTML string to blocks and return it as array of Block data
2023
+ *
2024
+ * @param {string} innerHTML - html string to process
2025
+ * @returns {PasteData[]}
2026
+ */processHTML(n){const{Tools:h}=this.Editor,p=d.make("DIV");return p.innerHTML=n,this.getNodes(p).map((n=>{let p,g=h.defaultTool,m=!1;switch(n.nodeType){case Node.DOCUMENT_FRAGMENT_NODE:p=d.make("div"),p.appendChild(n);break;case Node.ELEMENT_NODE:p=n,m=!0,this.toolsTags[p.tagName]&&(g=this.toolsTags[p.tagName].tool);break}const{tags:v}=g.pasteConfig||{tags:[]},x=v.reduce(((n,h)=>(this.collectTagNames(h).forEach((p=>{const g=R(h)?h[p]:null;n[p.toLowerCase()]=g||{}})),n)),{}),w=Object.assign({},x,g.baseSanitizeConfig);if(p.tagName.toLowerCase()==="table"){const n=q(p.outerHTML,w);p=d.make("div",void 0,{innerHTML:n}).firstChild}else p.innerHTML=q(p.innerHTML,w);const E=this.composePasteEvent("tag",{data:p});return{content:p,isBlock:m,tool:g.name,event:E}})).filter((n=>{const h=d.isEmpty(n.content),p=d.isSingleTag(n.content);return!h||p}))
2027
+ /**
2028
+ * Split plain text by new line symbols and return it as array of Block data
2029
+ *
2030
+ * @param {string} plain - string to process
2031
+ * @returns {PasteData[]}
2032
+ */}processPlain(n){const{defaultBlock:h}=this.config;if(!n)return[];const p=h;return n.split(/\r?\n/).filter((n=>n.trim())).map((n=>{const h=d.make("div");h.textContent=n;const g=this.composePasteEvent("tag",{data:h});return{content:h,tool:p,isBlock:!1,event:g}}))}
2033
+ /**
2034
+ * Process paste of single Block tool content
2035
+ *
2036
+ * @param {PasteData} dataToInsert - data of Block to insert
2037
+ */async processSingleBlock(n){const{Caret:h,BlockManager:p}=this.Editor,{currentBlock:g}=p;g&&n.tool===g.name&&d.containsOnlyInlineElements(n.content.innerHTML)?h.insertContentAtCaretPosition(n.content.innerHTML):this.insertBlock(n,(g==null?void 0:g.tool.isDefault)&&g.isEmpty)}
2038
+ /**
2039
+ * Process paste to single Block:
2040
+ * 1. Find patterns` matches
2041
+ * 2. Insert new block if it is not the same type as current one
2042
+ * 3. Just insert text if there is no substitutions
2043
+ *
2044
+ * @param {PasteData} dataToInsert - data of Block to insert
2045
+ */async processInlinePaste(n){const{BlockManager:h,Caret:p}=this.Editor,{content:g}=n;if(h.currentBlock&&h.currentBlock.tool.isDefault&&g.textContent.length<lo.PATTERN_PROCESSING_MAX_LENGTH){const n=await this.processPattern(g.textContent);if(n){const g=h.currentBlock&&h.currentBlock.tool.isDefault&&h.currentBlock.isEmpty,m=h.paste(n.tool,n.event,g);p.setToBlock(m,p.positions.END);return}}if(h.currentBlock&&h.currentBlock.currentInput){const n=h.currentBlock.tool.baseSanitizeConfig;document.execCommand("insertHTML",!1,q(g.innerHTML,n))}else this.insertBlock(n)}
2046
+ /**
2047
+ * Get patterns` matches
2048
+ *
2049
+ * @param {string} text - text to process
2050
+ * @returns {Promise<{event: PasteEvent, tool: string}>}
2051
+ */async processPattern(n){const h=this.toolsPatterns.find((h=>{const p=h.pattern.exec(n);return!!p&&n===p.shift()}));return h?{event:this.composePasteEvent("pattern",{key:h.key,data:n}),tool:h.tool.name}:void 0}
2052
+ /**
2053
+ * Insert pasted Block content to Editor
2054
+ *
2055
+ * @param {PasteData} data - data to insert
2056
+ * @param {boolean} canReplaceCurrentBlock - if true and is current Block is empty, will replace current Block
2057
+ * @returns {void}
2058
+ */insertBlock(n,h=!1){const{BlockManager:p,Caret:g}=this.Editor,{currentBlock:m}=p;let v;h&&m&&m.isEmpty?(v=p.paste(n.tool,n.event,!0),g.setToBlock(v,g.positions.END)):(v=p.paste(n.tool,n.event),g.setToBlock(v,g.positions.END)
2059
+ /**
2060
+ * Insert data passed as application/x-editor-js JSON
2061
+ *
2062
+ * @param {Array} blocks — Blocks' data to insert
2063
+ * @returns {void}
2064
+ */)}insertEditorJSData(n){const{BlockManager:h,Caret:p,Tools:g}=this.Editor;it(n,(n=>g.blockTools.get(n).sanitizeConfig)).forEach((({tool:n,data:g},m)=>{let v=!1;m===0&&(v=h.currentBlock&&h.currentBlock.tool.isDefault&&h.currentBlock.isEmpty);const x=h.insert({tool:n,data:g,replace:v});p.setToBlock(x,p.positions.END)}))}
2065
+ /**
2066
+ * Fetch nodes from Element node
2067
+ *
2068
+ * @param {Node} node - current node
2069
+ * @param {Node[]} nodes - processed nodes
2070
+ * @param {Node} destNode - destination node
2071
+ */processElementNode(n,h,p){const g=Object.keys(this.toolsTags),m=n,{tool:v}=this.toolsTags[m.tagName]||{},x=this.tagsByTool[v==null?void 0:v.name]||[],w=g.includes(m.tagName),E=d.blockElements.includes(m.tagName.toLowerCase()),B=Array.from(m.children).some((({tagName:n})=>g.includes(n)&&!x.includes(n))),T=Array.from(m.children).some((({tagName:n})=>d.blockElements.includes(n.toLowerCase())));return E||w||B?w&&!B||E&&!T&&!B?[...h,p,m]:void 0:(p.appendChild(m),[...h,p])}
2072
+ /**
2073
+ * Recursively divide HTML string to two types of nodes:
2074
+ * 1. Block element
2075
+ * 2. Document Fragments contained text and markup tags like a, b, i etc.
2076
+ *
2077
+ * @param {Node} wrapper - wrapper of paster HTML content
2078
+ * @returns {Node[]}
2079
+ */getNodes(n){const h=Array.from(n.childNodes);let p;const i=(n,h)=>{if(d.isEmpty(h)&&!d.isSingleTag(h))return n;const g=n[n.length-1];let m=new DocumentFragment;switch(g&&d.isFragment(g)&&(m=n.pop()),h.nodeType){case Node.ELEMENT_NODE:if(p=this.processElementNode(h,n,m),p)return p;break;case Node.TEXT_NODE:return m.appendChild(h),[...n,m];default:return[...n,m]}return[...n,...Array.from(h.childNodes).reduce(i,[])]};return h.reduce(i,[])}
2080
+ /**
2081
+ * Compose paste event with passed type and detail
2082
+ *
2083
+ * @param {string} type - event type
2084
+ * @param {PasteEventDetail} detail - event detail
2085
+ */composePasteEvent(n,h){return new CustomEvent(n,{detail:h})}};yi.PATTERN_PROCESSING_MAX_LENGTH=450;let xi=yi;class as extends y{constructor(){super(...arguments),this.toolsDontSupportReadOnly=[],this.readOnlyEnabled=!1}get isEnabled(){return this.readOnlyEnabled}async prepare(){const{Tools:n}=this.Editor,{blockTools:h}=n,p=[];Array.from(h.entries()).forEach((([n,h])=>{h.isReadOnlySupported||p.push(n)})),this.toolsDontSupportReadOnly=p,this.config.readOnly&&p.length>0&&this.throwCriticalError(),this.toggle(this.config.readOnly,!0)
2086
+ /**
2087
+ * Set read-only mode or toggle current state
2088
+ * Call all Modules `toggleReadOnly` method and re-render Editor
2089
+ *
2090
+ * @param state - (optional) read-only state or toggle
2091
+ * @param isInitial - (optional) true when editor is initializing
2092
+ */}async toggle(n=!this.readOnlyEnabled,h=!1){n&&this.toolsDontSupportReadOnly.length>0&&this.throwCriticalError();const p=this.readOnlyEnabled;this.readOnlyEnabled=n;for(const h in this.Editor)this.Editor[h].toggleReadOnly&&this.Editor[h].toggleReadOnly(n);if(p===n)return this.readOnlyEnabled;if(h)return this.readOnlyEnabled;this.Editor.ModificationsObserver.disable();const g=await this.Editor.Saver.save();return await this.Editor.BlockManager.clear(),await this.Editor.Renderer.render(g.blocks),this.Editor.ModificationsObserver.enable(),this.readOnlyEnabled}throwCriticalError(){throw new Pt(`To enable read-only mode all connected tools should support it. Tools ${this.toolsDontSupportReadOnly.join(", ")} don't support read-only mode.`)}}class xe extends y{constructor(){super(...arguments),this.isRectSelectionActivated=!1,this.SCROLL_SPEED=3,this.HEIGHT_OF_SCROLL_ZONE=40,this.BOTTOM_SCROLL_ZONE=1,this.TOP_SCROLL_ZONE=2,this.MAIN_MOUSE_BUTTON=0,this.mousedown=!1,this.isScrolling=!1,this.inScrollZone=null,this.startX=0,this.startY=0,this.mouseX=0,this.mouseY=0,this.stackOfSelected=[],this.listenerIds=[]
2093
+ /**
2094
+ * CSS classes for the Block
2095
+ *
2096
+ * @returns {{wrapper: string, content: string}}
2097
+ */}static get CSS(){return{overlay:"codex-editor-overlay",overlayContainer:"codex-editor-overlay__container",rect:"codex-editor-overlay__rectangle",topScrollZone:"codex-editor-overlay__scroll-zone--top",bottomScrollZone:"codex-editor-overlay__scroll-zone--bottom"}}prepare(){this.enableModuleBindings()}
2098
+ /**
2099
+ * Init rect params
2100
+ *
2101
+ * @param {number} pageX - X coord of mouse
2102
+ * @param {number} pageY - Y coord of mouse
2103
+ */startSelection(n,h){const p=document.elementFromPoint(n-window.pageXOffset,h-window.pageYOffset);p.closest(`.${this.Editor.Toolbar.CSS.toolbar}`)||(this.Editor.BlockSelection.allBlocksSelected=!1,this.clearSelection(),this.stackOfSelected=[]);const g=[`.${D.CSS.content}`,`.${this.Editor.Toolbar.CSS.toolbar}`,`.${this.Editor.InlineToolbar.CSS.inlineToolbar}`],m=p.closest("."+this.Editor.UI.CSS.editorWrapper),v=g.some((n=>!!p.closest(n)));!m||v||(this.mousedown=!0,this.startX=n,this.startY=h)}endSelection(){this.mousedown=!1,this.startX=0,this.startY=0,this.overlayRectangle.style.display="none"}isRectActivated(){return this.isRectSelectionActivated}clearSelection(){this.isRectSelectionActivated=!1}enableModuleBindings(){const{container:n}=this.genHTML();this.listeners.on(n,"mousedown",(n=>{this.processMouseDown(n)}),!1),this.listeners.on(document.body,"mousemove",Ve((n=>{this.processMouseMove(n)}),10),{passive:!0}),this.listeners.on(document.body,"mouseleave",(()=>{this.processMouseLeave()})),this.listeners.on(window,"scroll",Ve((n=>{this.processScroll(n)}),10),{passive:!0}),this.listeners.on(document.body,"mouseup",(()=>{this.processMouseUp()}),!1)
2104
+ /**
2105
+ * Handle mouse down events
2106
+ *
2107
+ * @param {MouseEvent} mouseEvent - mouse event payload
2108
+ */}processMouseDown(n){n.button===this.MAIN_MOUSE_BUTTON&&(n.target.closest(d.allInputsSelector)!==null||this.startSelection(n.pageX,n.pageY))}
2109
+ /**
2110
+ * Handle mouse move events
2111
+ *
2112
+ * @param {MouseEvent} mouseEvent - mouse event payload
2113
+ */processMouseMove(n){this.changingRectangle(n),this.scrollByZones(n.clientY)}processMouseLeave(){this.clearSelection(),this.endSelection()
2114
+ /**
2115
+ * @param {MouseEvent} mouseEvent - mouse event payload
2116
+ */}processScroll(n){this.changingRectangle(n)}processMouseUp(){this.clearSelection(),this.endSelection()
2117
+ /**
2118
+ * Scroll If mouse in scroll zone
2119
+ *
2120
+ * @param {number} clientY - Y coord of mouse
2121
+ */}scrollByZones(n){this.inScrollZone=null,n<=this.HEIGHT_OF_SCROLL_ZONE&&(this.inScrollZone=this.TOP_SCROLL_ZONE),document.documentElement.clientHeight-n<=this.HEIGHT_OF_SCROLL_ZONE&&(this.inScrollZone=this.BOTTOM_SCROLL_ZONE),this.inScrollZone?this.isScrolling||(this.scrollVertical(this.inScrollZone===this.TOP_SCROLL_ZONE?-this.SCROLL_SPEED:this.SCROLL_SPEED),this.isScrolling=!0
2122
+ /**
2123
+ * Generates required HTML elements
2124
+ *
2125
+ * @returns {Object<string, Element>}
2126
+ */):this.isScrolling=!1}genHTML(){const{UI:n}=this.Editor,h=n.nodes.holder.querySelector("."+n.CSS.editorWrapper),p=d.make("div",xe.CSS.overlay,{}),g=d.make("div",xe.CSS.overlayContainer,{}),m=d.make("div",xe.CSS.rect,{});return g.appendChild(m),p.appendChild(g),h.appendChild(p),this.overlayRectangle=m,{container:h,overlay:p}
2127
+ /**
2128
+ * Activates scrolling if blockSelection is active and mouse is in scroll zone
2129
+ *
2130
+ * @param {number} speed - speed of scrolling
2131
+ */}scrollVertical(n){if(!(this.inScrollZone&&this.mousedown))return;const h=window.pageYOffset;window.scrollBy(0,n),this.mouseY+=window.pageYOffset-h,setTimeout((()=>{this.scrollVertical(n)}),0)
2132
+ /**
2133
+ * Handles the change in the rectangle and its effect
2134
+ *
2135
+ * @param {MouseEvent} event - mouse event
2136
+ */}changingRectangle(n){if(!this.mousedown)return;n.pageY!==void 0&&(this.mouseX=n.pageX,this.mouseY=n.pageY);const{rightPos:h,leftPos:p,index:g}=this.genInfoForMouseSelection(),m=this.startX>h&&this.mouseX>h,v=this.startX<p&&this.mouseX<p;this.rectCrossesBlocks=!(m||v),this.isRectSelectionActivated||(this.rectCrossesBlocks=!1,this.isRectSelectionActivated=!0,this.shrinkRectangleToPoint(),this.overlayRectangle.style.display="block"),this.updateRectangleSize(),this.Editor.Toolbar.close(),g!==void 0&&(this.trySelectNextBlock(g),this.inverseSelection(),b.get().removeAllRanges())}shrinkRectangleToPoint(){this.overlayRectangle.style.left=this.startX-window.pageXOffset+"px",this.overlayRectangle.style.top=this.startY-window.pageYOffset+"px",this.overlayRectangle.style.bottom=`calc(100% - ${this.startY-window.pageYOffset}px`,this.overlayRectangle.style.right=`calc(100% - ${this.startX-window.pageXOffset}px`}inverseSelection(){const n=this.Editor.BlockManager.getBlockByIndex(this.stackOfSelected[0]).selected;if(this.rectCrossesBlocks&&!n)for(const n of this.stackOfSelected)this.Editor.BlockSelection.selectBlockByIndex(n);if(!this.rectCrossesBlocks&&n)for(const n of this.stackOfSelected)this.Editor.BlockSelection.unSelectBlockByIndex(n)}updateRectangleSize(){this.mouseY>=this.startY?(this.overlayRectangle.style.top=this.startY-window.pageYOffset+"px",this.overlayRectangle.style.bottom=`calc(100% - ${this.mouseY-window.pageYOffset}px`):(this.overlayRectangle.style.bottom=`calc(100% - ${this.startY-window.pageYOffset}px`,this.overlayRectangle.style.top=this.mouseY-window.pageYOffset+"px"),this.mouseX>=this.startX?(this.overlayRectangle.style.left=this.startX-window.pageXOffset+"px",this.overlayRectangle.style.right=`calc(100% - ${this.mouseX-window.pageXOffset}px`):(this.overlayRectangle.style.right=`calc(100% - ${this.startX-window.pageXOffset}px`,this.overlayRectangle.style.left=this.mouseX-window.pageXOffset+"px"
2137
+ /**
2138
+ * Collects information needed to determine the behavior of the rectangle
2139
+ *
2140
+ * @returns {object} index - index next Block, leftPos - start of left border of Block, rightPos - right border
2141
+ */)}genInfoForMouseSelection(){const n=document.body.offsetWidth/2,h=this.mouseY-window.pageYOffset,p=document.elementFromPoint(n,h),g=this.Editor.BlockManager.getBlockByChildNode(p);let m;g!==void 0&&(m=this.Editor.BlockManager.blocks.findIndex((n=>n.holder===g.holder)));const v=this.Editor.BlockManager.lastBlock.holder.querySelector("."+D.CSS.content),x=Number.parseInt(window.getComputedStyle(v).width,10)/2,w=n-x,E=n+x;return{index:m,leftPos:w,rightPos:E}}
2142
+ /**
2143
+ * Select block with index index
2144
+ *
2145
+ * @param index - index of block in redactor
2146
+ */addBlockInSelection(n){this.rectCrossesBlocks&&this.Editor.BlockSelection.selectBlockByIndex(n),this.stackOfSelected.push(n)
2147
+ /**
2148
+ * Adds a block to the selection and determines which blocks should be selected
2149
+ *
2150
+ * @param {object} index - index of new block in the reactor
2151
+ */}trySelectNextBlock(n){const h=this.stackOfSelected[this.stackOfSelected.length-1]===n,p=this.stackOfSelected.length,g=1,m=-1,v=0;if(h)return;const x=this.stackOfSelected[p-1]-this.stackOfSelected[p-2]>0;let w=v;p>1&&(w=x?g:m);const E=n>this.stackOfSelected[p-1]&&w===g,B=n<this.stackOfSelected[p-1]&&w===m,T=!(E||B||w===v);if(!T&&(n>this.stackOfSelected[p-1]||this.stackOfSelected[p-1]===void 0)){let h=this.stackOfSelected[p-1]+1||n;for(h;h<=n;h++)this.addBlockInSelection(h);return}if(!T&&n<this.stackOfSelected[p-1]){for(let h=this.stackOfSelected[p-1]-1;h>=n;h--)this.addBlockInSelection(h);return}if(!T)return;let I,M=p-1;for(I=n>this.stackOfSelected[p-1]?()=>n>this.stackOfSelected[M]:()=>n<this.stackOfSelected[M];I();)this.rectCrossesBlocks&&this.Editor.BlockSelection.unSelectBlockByIndex(this.stackOfSelected[M]),this.stackOfSelected.pop(),M--}}class cs extends y{
2152
+ /**
2153
+ * Renders passed blocks as one batch
2154
+ *
2155
+ * @param blocksData - blocks to render
2156
+ */
2157
+ async render(n){return new Promise((h=>{const{Tools:p,BlockManager:v}=this.Editor;if(n.length===0)v.insert();else{const h=n.map((({type:n,data:h,tunes:x,id:w})=>{p.available.has(n)===!1&&(m(`Tool «${n}» is not found. Check 'tools' property at the Editor.js config.`,"warn"),h=this.composeStubDataForTool(n,h,w),n=p.stubTool);let E;try{E=v.composeBlock({id:w,tool:n,data:h,tunes:x})}catch(m){g(`Block «${n}» skipped because of plugins error`,"error",{data:h,error:m}),h=this.composeStubDataForTool(n,h,w),n=p.stubTool,E=v.composeBlock({id:w,tool:n,data:h,tunes:x})}return E}));v.insertMany(h)}window.requestIdleCallback((()=>{h()}),{timeout:2e3})}))}
2158
+ /**
2159
+ * Create data for the Stub Tool that will be used instead of unavailable tool
2160
+ *
2161
+ * @param tool - unavailable tool name to stub
2162
+ * @param data - data of unavailable block
2163
+ * @param [id] - id of unavailable block
2164
+ */composeStubDataForTool(n,h,p){const{Tools:g}=this.Editor;let m=n;if(g.unavailable.has(n)){const h=g.unavailable.get(n).toolbox;h!==void 0&&h[0].title!==void 0&&(m=h[0].title)}return{savedData:{id:p,type:n,data:h},title:m}}}class ds extends y{
2165
+ /**
2166
+ * Composes new chain of Promises to fire them alternatelly
2167
+ *
2168
+ * @returns {OutputData}
2169
+ */
2170
+ async save(){const{BlockManager:n,Tools:h}=this.Editor,p=n.blocks,g=[];try{p.forEach((n=>{g.push(this.getSavedData(n))}));const n=await Promise.all(g),m=await it(n,(n=>h.blockTools.get(n).sanitizeConfig));return this.makeOutput(m)}catch(n){m("Saving failed due to the Error %o","error",n)}}
2171
+ /**
2172
+ * Saves and validates
2173
+ *
2174
+ * @param {Block} block - Editor's Tool
2175
+ * @returns {ValidatedData} - Tool's validated data
2176
+ */async getSavedData(n){const h=await n.save(),p=h&&await n.validate(h.data);return{...h,isValid:p}}
2177
+ /**
2178
+ * Creates output object with saved data, time and version of editor
2179
+ *
2180
+ * @param {ValidatedData} allExtractedData - data extracted from Blocks
2181
+ * @returns {OutputData}
2182
+ */makeOutput(n){const h=[];return n.forEach((({id:n,tool:p,data:m,tunes:v,isValid:x})=>{if(!x){g(`Block «${p}» skipped because saved data is invalid`);return}if(p===this.Editor.Tools.stubTool){h.push(m);return}const w={id:n,type:p,data:m,...!V(v)&&{tunes:v}};h.push(w)})),{time:+new Date,blocks:h,version:"2.30.6"}}}(function(){try{if(typeof document<"u"){var n=document.createElement("style");n.appendChild(document.createTextNode(".ce-paragraph{line-height:1.6em;outline:none}.ce-block:only-of-type .ce-paragraph[data-placeholder-active]:empty:before,.ce-block:only-of-type .ce-paragraph[data-placeholder-active][data-empty=true]:before{content:attr(data-placeholder-active)}.ce-paragraph p:first-of-type{margin-top:0}.ce-paragraph p:last-of-type{margin-bottom:0}")),document.head.appendChild(n)}}catch(n){console.error("vite-plugin-css-injected-by-js",n)}})();const wi='<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M8 9V7.2C8 7.08954 8.08954 7 8.2 7L12 7M16 9V7.2C16 7.08954 15.9105 7 15.8 7L12 7M12 7L12 17M12 17H10M12 17H14"/></svg>';function us(n){const h=document.createElement("div");h.innerHTML=n.trim();const p=document.createDocumentFragment();return p.append(...Array.from(h.childNodes)),p
2183
+ /**
2184
+ * Base Paragraph Block for the Editor.js.
2185
+ * Represents a regular text block
2186
+ *
2187
+ * @author CodeX (team@codex.so)
2188
+ * @copyright CodeX 2018
2189
+ * @license The MIT License (MIT)
2190
+ */}class ht{
2191
+ /**
2192
+ * Default placeholder for Paragraph Tool
2193
+ *
2194
+ * @returns {string}
2195
+ * @class
2196
+ */
2197
+ static get DEFAULT_PLACEHOLDER(){return""}
2198
+ /**
2199
+ * Render plugin`s main Element and fill it with saved data
2200
+ *
2201
+ * @param {object} params - constructor params
2202
+ * @param {ParagraphData} params.data - previously saved data
2203
+ * @param {ParagraphConfig} params.config - user config for Tool
2204
+ * @param {object} params.api - editor.js api
2205
+ * @param {boolean} readOnly - read only mode flag
2206
+ */constructor({data:n,config:h,api:p,readOnly:g}){this.api=p,this.readOnly=g,this._CSS={block:this.api.styles.block,wrapper:"ce-paragraph"},this.readOnly||(this.onKeyUp=this.onKeyUp.bind(this)),this._placeholder=h.placeholder?h.placeholder:ht.DEFAULT_PLACEHOLDER,this._data=n??{},this._element=null,this._preserveBlank=h.preserveBlank??!1
2207
+ /**
2208
+ * Check if text content is empty and set empty string to inner html.
2209
+ * We need this because some browsers (e.g. Safari) insert <br> into empty contenteditanle elements
2210
+ *
2211
+ * @param {KeyboardEvent} e - key up event
2212
+ */}onKeyUp(n){if(n.code!=="Backspace"&&n.code!=="Delete"||!this._element)return;const{textContent:h}=this._element;h===""&&(this._element.innerHTML="")}
2213
+ /**
2214
+ * Create Tool's view
2215
+ *
2216
+ * @returns {HTMLDivElement}
2217
+ * @private
2218
+ */drawView(){const n=document.createElement("DIV");return n.classList.add(this._CSS.wrapper,this._CSS.block),n.contentEditable="false",n.dataset.placeholderActive=this.api.i18n.t(this._placeholder),this._data.text&&(n.innerHTML=this._data.text),this.readOnly||(n.contentEditable="true",n.addEventListener("keyup",this.onKeyUp)),n
2219
+ /**
2220
+ * Return Tool's view
2221
+ *
2222
+ * @returns {HTMLDivElement}
2223
+ */}render(){return this._element=this.drawView(),this._element
2224
+ /**
2225
+ * Method that specified how to merge two Text blocks.
2226
+ * Called by Editor.js by backspace at the beginning of the Block
2227
+ *
2228
+ * @param {ParagraphData} data
2229
+ * @public
2230
+ */}merge(n){if(!this._element)return;this._data.text+=n.text;const h=us(n.text);this._element.appendChild(h),this._element.normalize()
2231
+ /**
2232
+ * Validate Paragraph block data:
2233
+ * - check for emptiness
2234
+ *
2235
+ * @param {ParagraphData} savedData — data received after saving
2236
+ * @returns {boolean} false if saved data is not correct, otherwise true
2237
+ * @public
2238
+ */}validate(n){return!(n.text.trim()===""&&!this._preserveBlank)}
2239
+ /**
2240
+ * Extract Tool's data from the view
2241
+ *
2242
+ * @param {HTMLDivElement} toolsContent - Paragraph tools rendered view
2243
+ * @returns {ParagraphData} - saved data
2244
+ * @public
2245
+ */save(n){return{text:n.innerHTML}}
2246
+ /**
2247
+ * On paste callback fired from Editor.
2248
+ *
2249
+ * @param {HTMLPasteEvent} event - event with pasted data
2250
+ */onPaste(n){const h={text:n.detail.data.innerHTML};this._data=h,window.requestAnimationFrame((()=>{this._element&&(this._element.innerHTML=this._data.text||"")}))
2251
+ /**
2252
+ * Enable Conversion Toolbar. Paragraph can be converted to/from other tools
2253
+ * @returns {ConversionConfig}
2254
+ */}static get conversionConfig(){return{export:"text",import:"text"}}
2255
+ /**
2256
+ * Sanitizer rules
2257
+ * @returns {SanitizerConfig} - Edtior.js sanitizer config
2258
+ */static get sanitize(){return{text:{br:!0}}}
2259
+ /**
2260
+ * Returns true to notify the core that read-only mode is supported
2261
+ *
2262
+ * @returns {boolean}
2263
+ */static get isReadOnlySupported(){return!0}
2264
+ /**
2265
+ * Used by Editor paste handling API.
2266
+ * Provides configuration to handle P tags.
2267
+ *
2268
+ * @returns {PasteConfig} - Paragraph Paste Setting
2269
+ */static get pasteConfig(){return{tags:["P"]}}
2270
+ /**
2271
+ * Icon and title for displaying at the Toolbox
2272
+ *
2273
+ * @returns {ToolboxConfig} - Paragraph Toolbox Setting
2274
+ */static get toolbox(){return{icon:wi,title:"Text"}}}class ut{constructor(){this.commandName="bold"}
2275
+ /**
2276
+ * Sanitizer Rule
2277
+ * Leave <b> tags
2278
+ *
2279
+ * @returns {object}
2280
+ */static get sanitize(){return{b:{}}}render(){return{icon:me,name:"bold",onActivate:()=>{document.execCommand(this.commandName)},isActive:()=>document.queryCommandState(this.commandName)}}
2281
+ /**
2282
+ * Set a shortcut
2283
+ *
2284
+ * @returns {boolean}
2285
+ */get shortcut(){return"CMD+B"}}ut.isInline=!0;ut.title="Bold";class pt{constructor(){this.commandName="italic",this.CSS={button:"ce-inline-tool",buttonActive:"ce-inline-tool--active",buttonModifier:"ce-inline-tool--italic"},this.nodes={button:null}
2286
+ /**
2287
+ * Sanitizer Rule
2288
+ * Leave <i> tags
2289
+ *
2290
+ * @returns {object}
2291
+ */}static get sanitize(){return{i:{}}}render(){return this.nodes.button=document.createElement("button"),this.nodes.button.type="button",this.nodes.button.classList.add(this.CSS.button,this.CSS.buttonModifier),this.nodes.button.innerHTML=He,this.nodes.button}surround(){document.execCommand(this.commandName)}checkState(){const n=document.queryCommandState(this.commandName);return this.nodes.button.classList.toggle(this.CSS.buttonActive,n),n}get shortcut(){return"CMD+I"}}pt.isInline=!0;pt.title="Italic";class ft{
2292
+ /**
2293
+ * @param api - Editor.js API
2294
+ */
2295
+ constructor({api:n}){this.commandLink="createLink",this.commandUnlink="unlink",this.ENTER_KEY=13,this.CSS={button:"ce-inline-tool",buttonActive:"ce-inline-tool--active",buttonModifier:"ce-inline-tool--link",buttonUnlink:"ce-inline-tool--unlink",input:"ce-inline-tool-input",inputShowed:"ce-inline-tool-input--showed"},this.nodes={button:null,input:null},this.inputOpened=!1,this.toolbar=n.toolbar,this.inlineToolbar=n.inlineToolbar,this.notifier=n.notifier,this.i18n=n.i18n,this.selection=new b
2296
+ /**
2297
+ * Sanitizer Rule
2298
+ * Leave <a> tags
2299
+ *
2300
+ * @returns {object}
2301
+ */}static get sanitize(){return{a:{href:!0,target:"_blank",rel:"nofollow"}}}render(){return this.nodes.button=document.createElement("button"),this.nodes.button.type="button",this.nodes.button.classList.add(this.CSS.button,this.CSS.buttonModifier),this.nodes.button.innerHTML=Ue,this.nodes.button}renderActions(){return this.nodes.input=document.createElement("input"),this.nodes.input.placeholder=this.i18n.t("Add a link"),this.nodes.input.enterKeyHint="done",this.nodes.input.classList.add(this.CSS.input),this.nodes.input.addEventListener("keydown",(n=>{n.keyCode===this.ENTER_KEY&&this.enterPressed(n)})),this.nodes.input
2302
+ /**
2303
+ * Handle clicks on the Inline Toolbar icon
2304
+ *
2305
+ * @param {Range} range - range to wrap with link
2306
+ */}surround(n){if(n){this.inputOpened?(this.selection.restore(),this.selection.removeFakeBackground()):(this.selection.setFakeBackground(),this.selection.save());const n=this.selection.findParentTag("A");if(n){this.selection.expandToTag(n),this.unlink(),this.closeActions(),this.checkState(),this.toolbar.close();return}}this.toggleActions()}checkState(){const n=this.selection.findParentTag("A");if(n){this.nodes.button.innerHTML=We,this.nodes.button.classList.add(this.CSS.buttonUnlink),this.nodes.button.classList.add(this.CSS.buttonActive),this.openActions();const h=n.getAttribute("href");this.nodes.input.value=h!=="null"?h:"",this.selection.save()}else this.nodes.button.innerHTML=Ue,this.nodes.button.classList.remove(this.CSS.buttonUnlink),this.nodes.button.classList.remove(this.CSS.buttonActive);return!!n}clear(){this.closeActions()}get shortcut(){return"CMD+K"}toggleActions(){this.inputOpened?this.closeActions(!1):this.openActions(!0)}
2307
+ /**
2308
+ * @param {boolean} needFocus - on link creation we need to focus input. On editing - nope.
2309
+ */openActions(n=!1){this.nodes.input.classList.add(this.CSS.inputShowed),n&&this.nodes.input.focus(),this.inputOpened=!0
2310
+ /**
2311
+ * Close input
2312
+ *
2313
+ * @param {boolean} clearSavedSelection — we don't need to clear saved selection
2314
+ * on toggle-clicks on the icon of opened Toolbar
2315
+ */}closeActions(n=!0){if(this.selection.isFakeBackgroundEnabled){const n=new b;n.save(),this.selection.restore(),this.selection.removeFakeBackground(),n.restore()}this.nodes.input.classList.remove(this.CSS.inputShowed),this.nodes.input.value="",n&&this.selection.clearSaved(),this.inputOpened=!1
2316
+ /**
2317
+ * Enter pressed on input
2318
+ *
2319
+ * @param {KeyboardEvent} event - enter keydown event
2320
+ */}enterPressed(n){let h=this.nodes.input.value||"";h.trim()?this.validateURL(h)?(h=this.prepareLink(h),this.selection.restore(),this.selection.removeFakeBackground(),this.insertLink(h),n.preventDefault(),n.stopPropagation(),n.stopImmediatePropagation(),this.selection.collapseToEnd(),this.inlineToolbar.close()
2321
+ /**
2322
+ * Detects if passed string is URL
2323
+ *
2324
+ * @param {string} str - string to validate
2325
+ * @returns {boolean}
2326
+ */):(this.notifier.show({message:"Pasted link is not valid.",style:"error"}),g("Incorrect Link pasted","warn",h)):(this.selection.restore(),this.unlink(),n.preventDefault(),this.closeActions())}validateURL(n){return!/\s/.test(n)}
2327
+ /**
2328
+ * Process link before injection
2329
+ * - sanitize
2330
+ * - add protocol for links like 'google.com'
2331
+ *
2332
+ * @param {string} link - raw user input
2333
+ */prepareLink(n){return n=n.trim(),n=this.addProtocol(n),n
2334
+ /**
2335
+ * Add 'http' protocol to the links like 'vc.ru', 'google.com'
2336
+ *
2337
+ * @param {string} link - string to process
2338
+ */}addProtocol(n){if(/^(\w+):(\/\/)?/.test(n))return n;const h=/^\/[^/\s]/.test(n),p=n.substring(0,1)==="#",g=/^\/\/[^/\s]/.test(n);return!h&&!p&&!g&&(n="http://"+n),n
2339
+ /**
2340
+ * Inserts <a> tag with "href"
2341
+ *
2342
+ * @param {string} link - "href" value
2343
+ */}insertLink(n){const h=this.selection.findParentTag("A");h&&this.selection.expandToTag(h),document.execCommand(this.commandLink,!1,n)}unlink(){document.execCommand(this.commandUnlink)}}ft.isInline=!0;ft.title="Link";class ao{
2344
+ /**
2345
+ * @param api - Editor.js API
2346
+ */
2347
+ constructor({api:n}){this.i18nAPI=n.i18n,this.blocksAPI=n.blocks,this.selectionAPI=n.selection,this.toolsAPI=n.tools,this.caretAPI=n.caret}async render(){const n=b.get(),h=this.blocksAPI.getBlockByElement(n.anchorNode);if(h===void 0)return[];const p=this.toolsAPI.getBlockTools(),g=await zt(h,p);if(g.length===0)return[];const m=g.reduce(((n,p)=>{var g;return(g=p.toolbox)==null||g.forEach((g=>{n.push({icon:g.icon,title:A.t(de.toolNames,g.title),name:p.name,closeOnActivate:!0,onActivate:async()=>{const n=await this.blocksAPI.convert(h.id,p.name,g.data);this.caretAPI.setToBlock(n,"end")}})})),n}),[]),v=await h.getActiveToolboxEntry(),x=v!==void 0?v.icon:Ye,w=!pe();return{icon:x,name:"convert-to",hint:{title:this.i18nAPI.t("Convert to")},children:{searchable:w,items:m,onOpen:()=>{w&&(this.selectionAPI.setFakeBackground(),this.selectionAPI.save())},onClose:()=>{w&&(this.selectionAPI.restore(),this.selectionAPI.removeFakeBackground())}}}}}ao.isInline=!0;class co{
2348
+ /**
2349
+ * @param options - constructor options
2350
+ * @param options.data - stub tool data
2351
+ * @param options.api - Editor.js API
2352
+ */
2353
+ constructor({data:n,api:h}){this.CSS={wrapper:"ce-stub",info:"ce-stub__info",title:"ce-stub__title",subtitle:"ce-stub__subtitle"},this.api=h,this.title=n.title||this.api.i18n.t("Error"),this.subtitle=this.api.i18n.t("The block can not be displayed correctly."),this.savedData=n.savedData,this.wrapper=this.make()
2354
+ /**
2355
+ * Returns stub holder
2356
+ *
2357
+ * @returns {HTMLElement}
2358
+ */}render(){return this.wrapper}
2359
+ /**
2360
+ * Return original Tool data
2361
+ *
2362
+ * @returns {BlockToolData}
2363
+ */save(){return this.savedData}
2364
+ /**
2365
+ * Create Tool html markup
2366
+ *
2367
+ * @returns {HTMLElement}
2368
+ */make(){const n=d.make("div",this.CSS.wrapper),h=Ge,p=d.make("div",this.CSS.info),g=d.make("div",this.CSS.title,{textContent:this.title}),m=d.make("div",this.CSS.subtitle,{textContent:this.subtitle});return n.innerHTML=h,p.appendChild(g),p.appendChild(m),n.appendChild(p),n}}co.isReadOnlySupported=!0;class ps extends dt{constructor(){super(...arguments),this.type=Po.Inline}get title(){return this.constructable[Xo.Title]}create(){return new this.constructable({api:this.api,config:this.settings})}}class fs extends dt{constructor(){super(...arguments),this.type=Po.Tune
2369
+ /**
2370
+ * Constructs new BlockTune instance from constructable
2371
+ *
2372
+ * @param data - Tune data
2373
+ * @param block - Block API object
2374
+ */}create(n,h){return new this.constructable({api:this.api,config:this.settings,block:h,data:n})}}class F extends Map{get blockTools(){const n=Array.from(this.entries()).filter((([,n])=>n.isBlock()));return new F(n)}get inlineTools(){const n=Array.from(this.entries()).filter((([,n])=>n.isInline()));return new F(n)}get blockTunes(){const n=Array.from(this.entries()).filter((([,n])=>n.isTune()));return new F(n)}get internalTools(){const n=Array.from(this.entries()).filter((([,n])=>n.isInternal));return new F(n)}get externalTools(){const n=Array.from(this.entries()).filter((([,n])=>!n.isInternal));return new F(n)}}var Ei=Object.defineProperty,Bi=Object.getOwnPropertyDescriptor,ho=(n,h,p,g)=>{for(var m,v=g>1?void 0:g?Bi(h,p):h,x=n.length-1;x>=0;x--)(m=n[x])&&(v=(g?m(h,p,v):m(v))||v);return g&&v&&Ei(h,p,v),v};class gt extends dt{constructor(){super(...arguments),this.type=Po.Block,this.inlineTools=new F,this.tunes=new F
2375
+ /**
2376
+ * Creates new Tool instance
2377
+ *
2378
+ * @param data - Tool data
2379
+ * @param block - BlockAPI for current Block
2380
+ * @param readOnly - True if Editor is in read-only mode
2381
+ */}create(n,h,p){return new this.constructable({data:n,block:h,readOnly:p,api:this.api,config:this.settings})}get isReadOnlySupported(){return this.constructable[Vo.IsReadOnlySupported]===!0}get isLineBreaksEnabled(){return this.constructable[Vo.IsEnabledLineBreaks]}get toolbox(){const n=this.constructable[Vo.Toolbox],h=this.config[Do.Toolbox];if(!V(n)&&h!==!1)return h?Array.isArray(n)?Array.isArray(h)?h.map(((h,p)=>{const g=n[p];return g?{...g,...h}:h})):[h]:Array.isArray(h)?h:[{...n,...h}]:Array.isArray(n)?n:[n]}get conversionConfig(){return this.constructable[Vo.ConversionConfig]}get enabledInlineTools(){return this.config[Do.EnabledInlineTools]||!1}get enabledBlockTunes(){return this.config[Do.EnabledBlockTunes]}get pasteConfig(){return this.constructable[Vo.PasteConfig]??{}}get sanitizeConfig(){const n=super.sanitizeConfig,h=this.baseSanitizeConfig;if(V(n))return h;const p={};for(const g in n)if(Object.prototype.hasOwnProperty.call(n,g)){const m=n[g];R(m)?p[g]=Object.assign({},h,m):p[g]=m}return p}get baseSanitizeConfig(){const n={};return Array.from(this.inlineTools.values()).forEach((h=>Object.assign(n,h.sanitizeConfig))),Array.from(this.tunes.values()).forEach((h=>Object.assign(n,h.sanitizeConfig))),n}}ho([ue],gt.prototype,"sanitizeConfig",1);ho([ue],gt.prototype,"baseSanitizeConfig",1);class bs{
2382
+ /**
2383
+ * @class
2384
+ * @param config - tools config
2385
+ * @param editorConfig - EditorJS config
2386
+ * @param api - EditorJS API module
2387
+ */
2388
+ constructor(n,h,p){this.api=p,this.config=n,this.editorConfig=h
2389
+ /**
2390
+ * Returns Tool object based on it's type
2391
+ *
2392
+ * @param name - tool name
2393
+ */}get(n){const{class:h,isInternal:p=!1,...g}=this.config[n],m=this.getConstructor(h),v=h[Qo.IsTune];return new m({name:n,constructable:h,config:g,api:this.api.getMethodsForTool(n,v),isDefault:n===this.editorConfig.defaultBlock,defaultPlaceholder:this.editorConfig.placeholder,isInternal:p})}
2394
+ /**
2395
+ * Find appropriate Tool object constructor for Tool constructable
2396
+ *
2397
+ * @param constructable - Tools constructable
2398
+ */getConstructor(n){switch(!0){case n[Xo.IsInline]:return ps;case n[Qo.IsTune]:return fs;default:return gt}}}class uo{
2399
+ /**
2400
+ * MoveDownTune constructor
2401
+ *
2402
+ * @param {API} api — Editor's API
2403
+ */
2404
+ constructor({api:n}){this.CSS={animation:"wobble"},this.api=n}render(){return{icon:be,title:this.api.i18n.t("Move down"),onActivate:()=>this.handleClick(),name:"move-down"}}handleClick(){const n=this.api.blocks.getCurrentBlockIndex(),h=this.api.blocks.getBlockByIndex(n+1);if(!h)throw new Error("Unable to move Block down since it is already the last");const p=h.holder,g=p.getBoundingClientRect();let m=Math.abs(window.innerHeight-p.offsetHeight);g.top<window.innerHeight&&(m=window.scrollY+p.offsetHeight),window.scrollTo(0,m),this.api.blocks.move(n+1),this.api.toolbar.toggleBlockSettings(!0)}}uo.isTune=!0;class po{
2405
+ /**
2406
+ * DeleteTune constructor
2407
+ *
2408
+ * @param {API} api - Editor's API
2409
+ */
2410
+ constructor({api:n}){this.api=n}render(){return{icon:Ie,title:this.api.i18n.t("Delete"),name:"delete",confirmation:{title:this.api.i18n.t("Click to delete"),onActivate:()=>this.handleClick()}}}handleClick(){this.api.blocks.delete()}}po.isTune=!0;class fo{
2411
+ /**
2412
+ * MoveUpTune constructor
2413
+ *
2414
+ * @param {API} api - Editor's API
2415
+ */
2416
+ constructor({api:n}){this.CSS={animation:"wobble"},this.api=n}render(){return{icon:Se,title:this.api.i18n.t("Move up"),onActivate:()=>this.handleClick(),name:"move-up"}}handleClick(){const n=this.api.blocks.getCurrentBlockIndex(),h=this.api.blocks.getBlockByIndex(n),p=this.api.blocks.getBlockByIndex(n-1);if(n===0||!h||!p)throw new Error("Unable to move Block up since it is already the first");const g=h.holder,m=p.holder,v=g.getBoundingClientRect(),x=m.getBoundingClientRect();let w;w=x.top>0?Math.abs(v.top)-Math.abs(x.top):Math.abs(v.top)+x.height,window.scrollBy(0,-1*w),this.api.blocks.move(n-1),this.api.toolbar.toggleBlockSettings(!0)}}fo.isTune=!0;var Ci=Object.defineProperty,Ti=Object.getOwnPropertyDescriptor,ws=(n,h,p,g)=>{for(var m,v=g>1?void 0:g?Ti(h,p):h,x=n.length-1;x>=0;x--)(m=n[x])&&(v=(g?m(h,p,v):m(v))||v);return g&&v&&Ci(h,p,v),v};class go extends y{constructor(){super(...arguments),this.stubTool="stub",this.toolsAvailable=new F,this.toolsUnavailable=new F}get available(){return this.toolsAvailable}get unavailable(){return this.toolsUnavailable}get inlineTools(){return this.available.inlineTools}get blockTools(){return this.available.blockTools}
2417
+ /**
2418
+ * Return available Block Tunes
2419
+ *
2420
+ * @returns {object} - object of Inline Tool's classes
2421
+ */get blockTunes(){return this.available.blockTunes}get defaultTool(){return this.blockTools.get(this.config.defaultBlock)}get internal(){return this.available.internalTools}
2422
+ /**
2423
+ * Creates instances via passed or default configuration
2424
+ *
2425
+ * @returns {Promise<void>}
2426
+ */async prepare(){if(this.validateTools(),this.config.tools=qe({},this.internalTools,this.config.tools),!Object.prototype.hasOwnProperty.call(this.config,"tools")||Object.keys(this.config.tools).length===0)throw Error("Can't start without tools");const n=this.prepareConfig();this.factory=new bs(n,this.config,this.Editor.API);const h=this.getListOfPrepareFunctions(n);if(h.length===0)return Promise.resolve();await Eo(h,(n=>{this.toolPrepareMethodSuccess(n)}),(n=>{this.toolPrepareMethodFallback(n)})),this.prepareBlockTools()}getAllInlineToolsSanitizeConfig(){const n={};return Array.from(this.inlineTools.values()).forEach((h=>{Object.assign(n,h.sanitizeConfig)})),n}destroy(){Object.values(this.available).forEach((async n=>{O(n.reset)&&await n.reset()}))}get internalTools(){return{convertTo:{class:ao,isInternal:!0},link:{class:ft,isInternal:!0},bold:{class:ut,isInternal:!0},italic:{class:pt,isInternal:!0},paragraph:{class:ht,inlineToolbar:!0,isInternal:!0},stub:{class:co,isInternal:!0},moveUp:{class:fo,isInternal:!0},delete:{class:po,isInternal:!0},moveDown:{class:uo,isInternal:!0}}}
2427
+ /**
2428
+ * Tool prepare method success callback
2429
+ *
2430
+ * @param {object} data - append tool to available list
2431
+ */toolPrepareMethodSuccess(n){const h=this.factory.get(n.toolName);if(h.isInline()){const n=["render"].filter((n=>!h.create()[n]));if(n.length){g(`Incorrect Inline Tool: ${h.name}. Some of required methods is not implemented %o`,"warn",n),this.toolsUnavailable.set(h.name,h);return}}this.toolsAvailable.set(h.name,h)}
2432
+ /**
2433
+ * Tool prepare method fail callback
2434
+ *
2435
+ * @param {object} data - append tool to unavailable list
2436
+ */toolPrepareMethodFallback(n){this.toolsUnavailable.set(n.toolName,this.factory.get(n.toolName))}
2437
+ /**
2438
+ * Binds prepare function of plugins with user or default config
2439
+ *
2440
+ * @returns {Array} list of functions that needs to be fired sequentially
2441
+ * @param config - tools config
2442
+ */getListOfPrepareFunctions(n){const h=[];return Object.entries(n).forEach((([n,p])=>{h.push({function:O(p.class.prepare)?p.class.prepare:()=>{},data:{toolName:n,config:p.config}})})),h}prepareBlockTools(){Array.from(this.blockTools.values()).forEach((n=>{this.assignInlineToolsToBlockTool(n),this.assignBlockTunesToBlockTool(n)}))}
2443
+ /**
2444
+ * Assign enabled Inline Tools for Block Tool
2445
+ *
2446
+ * @param tool - Block Tool
2447
+ */assignInlineToolsToBlockTool(n){if(this.config.inlineToolbar!==!1){if(n.enabledInlineTools===!0){n.inlineTools=new F(Array.isArray(this.config.inlineToolbar)?this.config.inlineToolbar.map((n=>[n,this.inlineTools.get(n)])):Array.from(this.inlineTools.entries()));return}Array.isArray(n.enabledInlineTools)&&(n.inlineTools=new F(["convertTo",...n.enabledInlineTools].map((n=>[n,this.inlineTools.get(n)]))))}}
2448
+ /**
2449
+ * Assign enabled Block Tunes for Block Tool
2450
+ *
2451
+ * @param tool — Block Tool
2452
+ */assignBlockTunesToBlockTool(n){if(n.enabledBlockTunes!==!1){if(Array.isArray(n.enabledBlockTunes)){const h=new F(n.enabledBlockTunes.map((n=>[n,this.blockTunes.get(n)])));n.tunes=new F([...h,...this.blockTunes.internalTools]);return}if(Array.isArray(this.config.tunes)){const h=new F(this.config.tunes.map((n=>[n,this.blockTunes.get(n)])));n.tunes=new F([...h,...this.blockTunes.internalTools]);return}n.tunes=this.blockTunes.internalTools}}validateTools(){for(const n in this.config.tools)if(Object.prototype.hasOwnProperty.call(this.config.tools,n)){if(n in this.internalTools)return;const h=this.config.tools[n];if(!O(h)&&!O(h.class))throw Error(`Tool «${n}» must be a constructor function or an object with function in the «class» property`)}}prepareConfig(){const n={};for(const h in this.config.tools)R(this.config.tools[h])?n[h]=this.config.tools[h]:n[h]={class:this.config.tools[h]};return n}}ws([ue],go.prototype,"getAllInlineToolsSanitizeConfig",1);const Si=':root{--selectionColor: #e1f2ff;--inlineSelectionColor: #d4ecff;--bg-light: #eff2f5;--grayText: #707684;--color-dark: #1D202B;--color-active-icon: #388AE5;--color-gray-border: rgba(201, 201, 204, .48);--content-width: 650px;--narrow-mode-right-padding: 50px;--toolbox-buttons-size: 26px;--toolbox-buttons-size--mobile: 36px;--icon-size: 20px;--icon-size--mobile: 28px;--block-padding-vertical: .4em;--color-line-gray: #EFF0F1 }.codex-editor{position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;z-index:1}.codex-editor .hide{display:none}.codex-editor__redactor [contenteditable]:empty:after{content:"\\feff"}@media (min-width: 651px){.codex-editor--narrow .codex-editor__redactor{margin-right:50px}}@media (min-width: 651px){.codex-editor--narrow.codex-editor--rtl .codex-editor__redactor{margin-left:50px;margin-right:0}}@media (min-width: 651px){.codex-editor--narrow .ce-toolbar__actions{right:-5px}}.codex-editor-copyable{position:absolute;height:1px;width:1px;top:-400%;opacity:.001}.codex-editor-overlay{position:fixed;top:0;left:0;right:0;bottom:0;z-index:999;pointer-events:none;overflow:hidden}.codex-editor-overlay__container{position:relative;pointer-events:auto;z-index:0}.codex-editor-overlay__rectangle{position:absolute;pointer-events:none;background-color:#2eaadc33;border:1px solid transparent}.codex-editor svg{max-height:100%}.codex-editor path{stroke:currentColor}.codex-editor ::-moz-selection{background-color:#d4ecff}.codex-editor ::selection{background-color:#d4ecff}.codex-editor--toolbox-opened [contentEditable=true][data-placeholder]:focus:before{opacity:0!important}.ce-scroll-locked{overflow:hidden}.ce-scroll-locked--hard{overflow:hidden;top:calc(-1 * var(--window-scroll-offset));position:fixed;width:100%}.ce-toolbar{position:absolute;left:0;right:0;top:0;-webkit-transition:opacity .1s ease;transition:opacity .1s ease;will-change:opacity,top;display:none}.ce-toolbar--opened{display:block}.ce-toolbar__content{max-width:650px;margin:0 auto;position:relative}.ce-toolbar__plus{color:#1d202b;cursor:pointer;width:26px;height:26px;border-radius:7px;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-ms-flex-negative:0;flex-shrink:0}@media (max-width: 650px){.ce-toolbar__plus{width:36px;height:36px}}@media (hover: hover){.ce-toolbar__plus:hover{background-color:#eff2f5}}.ce-toolbar__plus--active{background-color:#eff2f5;-webkit-animation:bounceIn .75s 1;animation:bounceIn .75s 1;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.ce-toolbar__plus-shortcut{opacity:.6;word-spacing:-2px;margin-top:5px}@media (max-width: 650px){.ce-toolbar__plus{position:absolute;background-color:#fff;border:1px solid #E8E8EB;-webkit-box-shadow:0 3px 15px -3px rgba(13,20,33,.13);box-shadow:0 3px 15px -3px #0d142121;border-radius:6px;z-index:2;position:static}.ce-toolbar__plus--left-oriented:before{left:15px;margin-left:0}.ce-toolbar__plus--right-oriented:before{left:auto;right:15px;margin-left:0}}.ce-toolbar__actions{position:absolute;right:100%;opacity:0;display:-webkit-box;display:-ms-flexbox;display:flex;padding-right:5px}.ce-toolbar__actions--opened{opacity:1}@media (max-width: 650px){.ce-toolbar__actions{right:auto}}.ce-toolbar__settings-btn{color:#1d202b;width:26px;height:26px;border-radius:7px;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;margin-left:3px;cursor:pointer;user-select:none}@media (max-width: 650px){.ce-toolbar__settings-btn{width:36px;height:36px}}@media (hover: hover){.ce-toolbar__settings-btn:hover{background-color:#eff2f5}}.ce-toolbar__settings-btn--active{background-color:#eff2f5;-webkit-animation:bounceIn .75s 1;animation:bounceIn .75s 1;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@media (min-width: 651px){.ce-toolbar__settings-btn{width:24px}}.ce-toolbar__settings-btn--hidden{display:none}@media (max-width: 650px){.ce-toolbar__settings-btn{position:absolute;background-color:#fff;border:1px solid #E8E8EB;-webkit-box-shadow:0 3px 15px -3px rgba(13,20,33,.13);box-shadow:0 3px 15px -3px #0d142121;border-radius:6px;z-index:2;position:static}.ce-toolbar__settings-btn--left-oriented:before{left:15px;margin-left:0}.ce-toolbar__settings-btn--right-oriented:before{left:auto;right:15px;margin-left:0}}.ce-toolbar__plus svg,.ce-toolbar__settings-btn svg{width:24px;height:24px}@media (min-width: 651px){.codex-editor--narrow .ce-toolbar__plus{left:5px}}@media (min-width: 651px){.codex-editor--narrow .ce-toolbox .ce-popover{right:0;left:auto;left:initial}}.ce-inline-toolbar{--y-offset: 8px;--color-background-icon-active: rgba(56, 138, 229, .1);--color-text-icon-active: #388AE5;--color-text-primary: black;position:absolute;visibility:hidden;-webkit-transition:opacity .25s ease;transition:opacity .25s ease;will-change:opacity,left,top;top:0;left:0;z-index:3;opacity:1;visibility:visible}.ce-inline-toolbar [hidden]{display:none!important}.ce-inline-toolbar__toggler-and-button-wrapper{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;padding:0 6px}.ce-inline-toolbar__buttons{display:-webkit-box;display:-ms-flexbox;display:flex}.ce-inline-toolbar__dropdown{display:-webkit-box;display:-ms-flexbox;display:flex;padding:6px;margin:0 6px 0 -6px;-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:pointer;border-right:1px solid rgba(201,201,204,.48);-webkit-box-sizing:border-box;box-sizing:border-box}@media (hover: hover){.ce-inline-toolbar__dropdown:hover{background:#eff2f5}}.ce-inline-toolbar__dropdown--hidden{display:none}.ce-inline-toolbar__dropdown-content,.ce-inline-toolbar__dropdown-arrow{display:-webkit-box;display:-ms-flexbox;display:flex}.ce-inline-toolbar__dropdown-content svg,.ce-inline-toolbar__dropdown-arrow svg{width:20px;height:20px}.ce-inline-toolbar__shortcut{opacity:.6;word-spacing:-3px;margin-top:3px}.ce-inline-tool{color:var(--color-text-primary);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;border-radius:4px;line-height:normal;height:100%;padding:0;width:28px;background-color:transparent;cursor:pointer}@media (max-width: 650px){.ce-inline-tool{width:36px;height:36px}}@media (hover: hover){.ce-inline-tool:hover{background-color:#f8f8f8}}.ce-inline-tool svg{display:block;width:20px;height:20px}@media (max-width: 650px){.ce-inline-tool svg{width:28px;height:28px}}.ce-inline-tool--link .icon--unlink,.ce-inline-tool--unlink .icon--link{display:none}.ce-inline-tool--unlink .icon--unlink{display:inline-block;margin-bottom:-1px}.ce-inline-tool-input{background:#F8F8F8;border:1px solid rgba(226,226,229,.2);border-radius:6px;padding:4px 8px;font-size:14px;line-height:22px;outline:none;margin:0;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box;display:none;font-weight:500;-webkit-appearance:none;font-family:inherit}@media (max-width: 650px){.ce-inline-tool-input{font-size:15px;font-weight:500}}.ce-inline-tool-input::-webkit-input-placeholder{color:#707684}.ce-inline-tool-input::-moz-placeholder{color:#707684}.ce-inline-tool-input:-ms-input-placeholder{color:#707684}.ce-inline-tool-input::-ms-input-placeholder{color:#707684}.ce-inline-tool-input::placeholder{color:#707684}.ce-inline-tool-input--showed{display:block}.ce-inline-tool--active{background:var(--color-background-icon-active);color:var(--color-text-icon-active)}@-webkit-keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.ce-block{-webkit-animation:fade-in .3s ease;animation:fade-in .3s ease;-webkit-animation-fill-mode:none;animation-fill-mode:none;-webkit-animation-fill-mode:initial;animation-fill-mode:initial}.ce-block:first-of-type{margin-top:0}.ce-block--selected .ce-block__content{background:#e1f2ff}.ce-block--selected .ce-block__content [contenteditable]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ce-block--selected .ce-block__content img,.ce-block--selected .ce-block__content .ce-stub{opacity:.55}.ce-block--stretched .ce-block__content{max-width:none}.ce-block__content{position:relative;max-width:650px;margin:0 auto;-webkit-transition:background-color .15s ease;transition:background-color .15s ease}.ce-block--drop-target .ce-block__content:before{content:"";position:absolute;top:100%;left:-20px;margin-top:-1px;height:8px;width:8px;border:solid #388AE5;border-width:1px 1px 0 0;-webkit-transform-origin:right;transform-origin:right;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.ce-block--drop-target .ce-block__content:after{content:"";position:absolute;top:100%;height:1px;width:100%;color:#388ae5;background:repeating-linear-gradient(90deg,#388AE5,#388AE5 1px,#fff 1px,#fff 6px)}.ce-block a{cursor:pointer;-webkit-text-decoration:underline;text-decoration:underline}.ce-block b{font-weight:700}.ce-block i{font-style:italic}@-webkit-keyframes bounceIn{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}20%{-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}60%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@keyframes bounceIn{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}20%{-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}60%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@-webkit-keyframes selectionBounce{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}50%{-webkit-transform:scale3d(1.01,1.01,1.01);transform:scale3d(1.01,1.01,1.01)}70%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@keyframes selectionBounce{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}50%{-webkit-transform:scale3d(1.01,1.01,1.01);transform:scale3d(1.01,1.01,1.01)}70%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@-webkit-keyframes buttonClicked{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.95,.95,.95);transform:scale3d(.95,.95,.95)}60%{-webkit-transform:scale3d(1.02,1.02,1.02);transform:scale3d(1.02,1.02,1.02)}80%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@keyframes buttonClicked{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.95,.95,.95);transform:scale3d(.95,.95,.95)}60%{-webkit-transform:scale3d(1.02,1.02,1.02);transform:scale3d(1.02,1.02,1.02)}80%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}.cdx-block{padding:.4em 0}.cdx-block::-webkit-input-placeholder{line-height:normal!important}.cdx-input{border:1px solid rgba(201,201,204,.48);-webkit-box-shadow:inset 0 1px 2px 0 rgba(35,44,72,.06);box-shadow:inset 0 1px 2px #232c480f;border-radius:3px;padding:10px 12px;outline:none;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.cdx-input[data-placeholder]:before{position:static!important}.cdx-input[data-placeholder]:before{display:inline-block;width:0;white-space:nowrap;pointer-events:none}.cdx-settings-button{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;border-radius:3px;cursor:pointer;border:0;outline:none;background-color:transparent;vertical-align:bottom;color:inherit;margin:0;min-width:26px;min-height:26px}.cdx-settings-button--focused{background:rgba(34,186,255,.08)!important}.cdx-settings-button--focused{-webkit-box-shadow:inset 0 0 0px 1px rgba(7,161,227,.08);box-shadow:inset 0 0 0 1px #07a1e314}.cdx-settings-button--focused-animated{-webkit-animation-name:buttonClicked;animation-name:buttonClicked;-webkit-animation-duration:.25s;animation-duration:.25s}.cdx-settings-button--active{color:#388ae5}.cdx-settings-button svg{width:auto;height:auto}@media (max-width: 650px){.cdx-settings-button svg{width:28px;height:28px}}@media (max-width: 650px){.cdx-settings-button{width:36px;height:36px;border-radius:8px}}@media (hover: hover){.cdx-settings-button:hover{background-color:#eff2f5}}.cdx-loader{position:relative;border:1px solid rgba(201,201,204,.48)}.cdx-loader:before{content:"";position:absolute;left:50%;top:50%;width:18px;height:18px;margin:-11px 0 0 -11px;border:2px solid rgba(201,201,204,.48);border-left-color:#388ae5;border-radius:50%;-webkit-animation:cdxRotation 1.2s infinite linear;animation:cdxRotation 1.2s infinite linear}@-webkit-keyframes cdxRotation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes cdxRotation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.cdx-button{padding:13px;border-radius:3px;border:1px solid rgba(201,201,204,.48);font-size:14.9px;background:#fff;-webkit-box-shadow:0 2px 2px 0 rgba(18,30,57,.04);box-shadow:0 2px 2px #121e390a;color:#707684;text-align:center;cursor:pointer}@media (hover: hover){.cdx-button:hover{background:#FBFCFE;-webkit-box-shadow:0 1px 3px 0 rgba(18,30,57,.08);box-shadow:0 1px 3px #121e3914}}.cdx-button svg{height:20px;margin-right:.2em;margin-top:-2px}.ce-stub{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:12px 18px;margin:10px 0;border-radius:10px;background:#eff2f5;border:1px solid #EFF0F1;color:#707684;font-size:14px}.ce-stub svg{width:20px;height:20px}.ce-stub__info{margin-left:14px}.ce-stub__title{font-weight:500;text-transform:capitalize}.codex-editor.codex-editor--rtl{direction:rtl}.codex-editor.codex-editor--rtl .cdx-list{padding-left:0;padding-right:40px}.codex-editor.codex-editor--rtl .ce-toolbar__plus{right:-26px;left:auto}.codex-editor.codex-editor--rtl .ce-toolbar__actions{right:auto;left:-26px}@media (max-width: 650px){.codex-editor.codex-editor--rtl .ce-toolbar__actions{margin-left:0;margin-right:auto;padding-right:0;padding-left:10px}}.codex-editor.codex-editor--rtl .ce-settings{left:5px;right:auto}.codex-editor.codex-editor--rtl .ce-settings:before{right:auto;left:25px}.codex-editor.codex-editor--rtl .ce-settings__button:not(:nth-child(3n+3)){margin-left:3px;margin-right:0}.codex-editor.codex-editor--rtl .ce-conversion-tool__icon{margin-right:0;margin-left:10px}.codex-editor.codex-editor--rtl .ce-inline-toolbar__dropdown{border-right:0px solid transparent;border-left:1px solid rgba(201,201,204,.48);margin:0 -6px 0 6px}.codex-editor.codex-editor--rtl .ce-inline-toolbar__dropdown .icon--toggler-down{margin-left:0;margin-right:4px}@media (min-width: 651px){.codex-editor--narrow.codex-editor--rtl .ce-toolbar__plus{left:0;right:5px}}@media (min-width: 651px){.codex-editor--narrow.codex-editor--rtl .ce-toolbar__actions{left:-5px}}.cdx-search-field{--icon-margin-right: 10px;background:#F8F8F8;border:1px solid rgba(226,226,229,.2);border-radius:6px;padding:2px;display:grid;grid-template-columns:auto auto 1fr;grid-template-rows:auto}.cdx-search-field__icon{width:26px;height:26px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-right:var(--icon-margin-right)}.cdx-search-field__icon svg{width:20px;height:20px;color:#707684}.cdx-search-field__input{font-size:14px;outline:none;font-weight:500;font-family:inherit;border:0;background:transparent;margin:0;padding:0;line-height:22px;min-width:calc(100% - 26px - var(--icon-margin-right))}.cdx-search-field__input::-webkit-input-placeholder{color:#707684;font-weight:500}.cdx-search-field__input::-moz-placeholder{color:#707684;font-weight:500}.cdx-search-field__input:-ms-input-placeholder{color:#707684;font-weight:500}.cdx-search-field__input::-ms-input-placeholder{color:#707684;font-weight:500}.cdx-search-field__input::placeholder{color:#707684;font-weight:500}.ce-popover{--border-radius: 6px;--width: 200px;--max-height: 270px;--padding: 6px;--offset-from-target: 8px;--color-border: #EFF0F1;--color-shadow: rgba(13, 20, 33, .1);--color-background: white;--color-text-primary: black;--color-text-secondary: #707684;--color-border-icon: rgba(201, 201, 204, .48);--color-border-icon-disabled: #EFF0F1;--color-text-icon-active: #388AE5;--color-background-icon-active: rgba(56, 138, 229, .1);--color-background-item-focus: rgba(34, 186, 255, .08);--color-shadow-item-focus: rgba(7, 161, 227, .08);--color-background-item-hover: #F8F8F8;--color-background-item-confirm: #E24A4A;--color-background-item-confirm-hover: #CE4343;--popover-top: calc(100% + var(--offset-from-target));--popover-left: 0;--nested-popover-overlap: 4px;--icon-size: 20px;--item-padding: 3px;--item-height: calc(var(--icon-size) + 2 * var(--item-padding))}.ce-popover__container{min-width:var(--width);width:var(--width);max-height:var(--max-height);border-radius:var(--border-radius);overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-box-shadow:0px 3px 15px -3px var(--color-shadow);box-shadow:0 3px 15px -3px var(--color-shadow);position:absolute;left:var(--popover-left);top:var(--popover-top);background:var(--color-background);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;z-index:4;opacity:0;max-height:0;pointer-events:none;padding:0;border:none}.ce-popover--opened>.ce-popover__container{opacity:1;padding:var(--padding);max-height:var(--max-height);pointer-events:auto;-webkit-animation:panelShowing .1s ease;animation:panelShowing .1s ease;border:1px solid var(--color-border)}@media (max-width: 650px){.ce-popover--opened>.ce-popover__container{-webkit-animation:panelShowingMobile .25s ease;animation:panelShowingMobile .25s ease}}.ce-popover--open-top .ce-popover__container{--popover-top: calc(-1 * (var(--offset-from-target) + var(--popover-height)))}.ce-popover--open-left .ce-popover__container{--popover-left: calc(-1 * var(--width) + 100%)}.ce-popover__items{overflow-y:auto;-ms-scroll-chaining:none;overscroll-behavior:contain}@media (max-width: 650px){.ce-popover__overlay{position:fixed;top:0;bottom:0;left:0;right:0;background:#1D202B;z-index:3;opacity:.5;-webkit-transition:opacity .12s ease-in;transition:opacity .12s ease-in;will-change:opacity;visibility:visible}}.ce-popover__overlay--hidden{display:none}@media (max-width: 650px){.ce-popover .ce-popover__container{--offset: 5px;position:fixed;max-width:none;min-width:calc(100% - var(--offset) * 2);left:var(--offset);right:var(--offset);bottom:calc(var(--offset) + env(safe-area-inset-bottom));top:auto;border-radius:10px}}.ce-popover__search{margin-bottom:5px}.ce-popover__nothing-found-message{color:#707684;display:none;cursor:default;padding:3px;font-size:14px;line-height:20px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ce-popover__nothing-found-message--displayed{display:block}.ce-popover--nested .ce-popover__container{--popover-left: calc(var(--nesting-level) * (var(--width) - var(--nested-popover-overlap)));top:calc(var(--trigger-item-top) - var(--nested-popover-overlap));position:absolute}.ce-popover--open-top.ce-popover--nested .ce-popover__container{top:calc(var(--trigger-item-top) - var(--popover-height) + var(--item-height) + var(--offset-from-target) + var(--nested-popover-overlap))}.ce-popover--open-left .ce-popover--nested .ce-popover__container{--popover-left: calc(-1 * (var(--nesting-level) + 1) * var(--width) + 100%)}.ce-popover-item-separator{padding:4px 3px}.ce-popover-item-separator--hidden{display:none}.ce-popover-item-separator__line{height:1px;background:var(--color-border);width:100%}.ce-popover-item-html--hidden{display:none}.ce-popover-item{--border-radius: 6px;border-radius:var(--border-radius);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:var(--item-padding);color:var(--color-text-primary);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:none;background:transparent}@media (max-width: 650px){.ce-popover-item{padding:4px}}.ce-popover-item:not(:last-of-type){margin-bottom:1px}.ce-popover-item__icon{width:26px;height:26px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.ce-popover-item__icon svg{width:20px;height:20px}@media (max-width: 650px){.ce-popover-item__icon{width:36px;height:36px;border-radius:8px}.ce-popover-item__icon svg{width:28px;height:28px}}.ce-popover-item__icon--tool{margin-right:4px}.ce-popover-item__title{font-size:14px;line-height:20px;font-weight:500;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-right:auto}@media (max-width: 650px){.ce-popover-item__title{font-size:16px}}.ce-popover-item__secondary-title{color:var(--color-text-secondary);font-size:12px;white-space:nowrap;letter-spacing:-.1em;padding-right:5px;opacity:.6}@media (max-width: 650px){.ce-popover-item__secondary-title{display:none}}.ce-popover-item--active{background:var(--color-background-icon-active);color:var(--color-text-icon-active)}.ce-popover-item--disabled{color:var(--color-text-secondary);cursor:default;pointer-events:none}.ce-popover-item--focused:not(.ce-popover-item--no-focus){background:var(--color-background-item-focus)!important}.ce-popover-item--hidden{display:none}@media (hover: hover){.ce-popover-item:hover{cursor:pointer}.ce-popover-item:hover:not(.ce-popover-item--no-hover){background-color:var(--color-background-item-hover)}}.ce-popover-item--confirmation{background:var(--color-background-item-confirm)}.ce-popover-item--confirmation .ce-popover-item__title,.ce-popover-item--confirmation .ce-popover-item__icon{color:#fff}@media (hover: hover){.ce-popover-item--confirmation:not(.ce-popover-item--no-hover):hover{background:var(--color-background-item-confirm-hover)}}.ce-popover-item--confirmation:not(.ce-popover-item--no-focus).ce-popover-item--focused{background:var(--color-background-item-confirm-hover)!important}@-webkit-keyframes panelShowing{0%{opacity:0;-webkit-transform:translateY(-8px) scale(.9);transform:translateY(-8px) scale(.9)}70%{opacity:1;-webkit-transform:translateY(2px);transform:translateY(2px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes panelShowing{0%{opacity:0;-webkit-transform:translateY(-8px) scale(.9);transform:translateY(-8px) scale(.9)}70%{opacity:1;-webkit-transform:translateY(2px);transform:translateY(2px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes panelShowingMobile{0%{opacity:0;-webkit-transform:translateY(14px) scale(.98);transform:translateY(14px) scale(.98)}70%{opacity:1;-webkit-transform:translateY(-4px);transform:translateY(-4px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes panelShowingMobile{0%{opacity:0;-webkit-transform:translateY(14px) scale(.98);transform:translateY(14px) scale(.98)}70%{opacity:1;-webkit-transform:translateY(-4px);transform:translateY(-4px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}.wobble{-webkit-animation-name:wobble;animation-name:wobble;-webkit-animation-duration:.4s;animation-duration:.4s}@-webkit-keyframes wobble{0%{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}15%{-webkit-transform:translate3d(-9%,0,0);transform:translate3d(-9%,0,0)}30%{-webkit-transform:translate3d(9%,0,0);transform:translate3d(9%,0,0)}45%{-webkit-transform:translate3d(-4%,0,0);transform:translate3d(-4%,0,0)}60%{-webkit-transform:translate3d(4%,0,0);transform:translate3d(4%,0,0)}75%{-webkit-transform:translate3d(-1%,0,0);transform:translate3d(-1%,0,0)}to{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}}@keyframes wobble{0%{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}15%{-webkit-transform:translate3d(-9%,0,0);transform:translate3d(-9%,0,0)}30%{-webkit-transform:translate3d(9%,0,0);transform:translate3d(9%,0,0)}45%{-webkit-transform:translate3d(-4%,0,0);transform:translate3d(-4%,0,0)}60%{-webkit-transform:translate3d(4%,0,0);transform:translate3d(4%,0,0)}75%{-webkit-transform:translate3d(-1%,0,0);transform:translate3d(-1%,0,0)}to{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}}.ce-popover-header{margin-bottom:8px;margin-top:4px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.ce-popover-header__text{font-size:18px;font-weight:600}.ce-popover-header__back-button{border:0;background:transparent;width:36px;height:36px;color:var(--color-text-primary)}.ce-popover-header__back-button svg{display:block;width:28px;height:28px}.ce-popover--inline{--height: 38px;--height-mobile: 46px;--container-padding: 4px;position:relative}.ce-popover--inline .ce-popover__custom-content{margin-bottom:0}.ce-popover--inline .ce-popover__items{display:-webkit-box;display:-ms-flexbox;display:flex}.ce-popover--inline .ce-popover__container{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;padding:var(--container-padding);height:var(--height);top:0;min-width:-webkit-max-content;min-width:-moz-max-content;min-width:max-content;width:-webkit-max-content;width:-moz-max-content;width:max-content;-webkit-animation:none;animation:none}@media (max-width: 650px){.ce-popover--inline .ce-popover__container{height:var(--height-mobile);position:absolute}}.ce-popover--inline .ce-popover-item-separator{padding:0 4px}.ce-popover--inline .ce-popover-item-separator__line{height:100%;width:1px}.ce-popover--inline .ce-popover-item{border-radius:4px;padding:4px}.ce-popover--inline .ce-popover-item__icon--tool{-webkit-box-shadow:none;box-shadow:none;background:transparent;margin-right:0}.ce-popover--inline .ce-popover-item__icon{width:auto;width:initial;height:auto;height:initial}.ce-popover--inline .ce-popover-item__icon svg{width:20px;height:20px}@media (max-width: 650px){.ce-popover--inline .ce-popover-item__icon svg{width:28px;height:28px}}.ce-popover--inline .ce-popover-item:not(:last-of-type){margin-bottom:0;margin-bottom:initial}.ce-popover--inline .ce-popover-item-html{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.ce-popover--inline .ce-popover-item__icon--chevron-right{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.ce-popover--inline .ce-popover--nested-level-1 .ce-popover__container{--offset: 3px;left:0;top:calc(var(--height) + var(--offset))}@media (max-width: 650px){.ce-popover--inline .ce-popover--nested-level-1 .ce-popover__container{top:calc(var(--height-mobile) + var(--offset))}}.ce-popover--inline .ce-popover--nested .ce-popover__container{min-width:var(--width);width:var(--width);height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;padding:6px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.ce-popover--inline .ce-popover--nested .ce-popover__items{display:block;width:100%}.ce-popover--inline .ce-popover--nested .ce-popover-item{border-radius:6px;padding:3px}@media (max-width: 650px){.ce-popover--inline .ce-popover--nested .ce-popover-item{padding:4px}}.ce-popover--inline .ce-popover--nested .ce-popover-item__icon--tool{margin-right:4px}.ce-popover--inline .ce-popover--nested .ce-popover-item__icon{width:26px;height:26px}.ce-popover--inline .ce-popover--nested .ce-popover-item-separator{padding:4px 3px}.ce-popover--inline .ce-popover--nested .ce-popover-item-separator__line{width:100%;height:1px}.codex-editor [data-placeholder]:empty:before,.codex-editor [data-placeholder][data-empty=true]:before{pointer-events:none;color:#707684;cursor:text;content:attr(data-placeholder)}.codex-editor [data-placeholder-active]:empty:before,.codex-editor [data-placeholder-active][data-empty=true]:before{pointer-events:none;color:#707684;cursor:text}.codex-editor [data-placeholder-active]:empty:focus:before,.codex-editor [data-placeholder-active][data-empty=true]:focus:before{content:attr(data-placeholder-active)}\n';class ys extends y{constructor(){super(...arguments),this.isMobile=!1,this.contentRectCache=void 0,this.resizeDebouncer=vt((()=>{this.windowResize()}),200)
2453
+ /**
2454
+ * Editor.js UI CSS class names
2455
+ *
2456
+ * @returns {{editorWrapper: string, editorZone: string}}
2457
+ */}get CSS(){return{editorWrapper:"codex-editor",editorWrapperNarrow:"codex-editor--narrow",editorZone:"codex-editor__redactor",editorZoneHidden:"codex-editor__redactor--hidden",editorEmpty:"codex-editor--empty",editorRtlFix:"codex-editor--rtl"}}
2458
+ /**
2459
+ * Return Width of center column of Editor
2460
+ *
2461
+ * @returns {DOMRect}
2462
+ */get contentRect(){if(this.contentRectCache)return this.contentRectCache;const n=this.nodes.wrapper.querySelector(`.${D.CSS.content}`);return n?(this.contentRectCache=n.getBoundingClientRect(),this.contentRectCache):{width:650,left:0,right:0}}async prepare(){this.setIsMobile(),this.make(),this.loadStyles()
2463
+ /**
2464
+ * Toggle read-only state
2465
+ *
2466
+ * If readOnly is true:
2467
+ * - removes all listeners from main UI module elements
2468
+ *
2469
+ * if readOnly is false:
2470
+ * - enables all listeners to UI module elements
2471
+ *
2472
+ * @param {boolean} readOnlyEnabled - "read only" state
2473
+ */}toggleReadOnly(n){n?this.disableModuleBindings():window.requestIdleCallback((()=>{this.enableModuleBindings()}),{timeout:2e3})}checkEmptiness(){const{BlockManager:n}=this.Editor;this.nodes.wrapper.classList.toggle(this.CSS.editorEmpty,n.isEditorEmpty)}
2474
+ /**
2475
+ * Check if one of Toolbar is opened
2476
+ * Used to prevent global keydowns (for example, Enter) conflicts with Enter-on-toolbar
2477
+ *
2478
+ * @returns {boolean}
2479
+ */get someToolbarOpened(){const{Toolbar:n,BlockSettings:h,InlineToolbar:p}=this.Editor;return!!(h.opened||p.opened||n.toolbox.opened)}get someFlipperButtonFocused(){return!!this.Editor.Toolbar.toolbox.hasFocus()||Object.entries(this.Editor).filter((([n,h])=>h.flipper instanceof le)).some((([n,h])=>h.flipper.hasFocus()))}destroy(){this.nodes.holder.innerHTML=""}closeAllToolbars(){const{Toolbar:n,BlockSettings:h,InlineToolbar:p}=this.Editor;h.close(),p.close(),n.toolbox.close()}setIsMobile(){const n=window.innerWidth<v;n!==this.isMobile&&this.eventsDispatcher.emit(z,{isEnabled:this.isMobile}),this.isMobile=n}make(){this.nodes.holder=d.getHolder(this.config.holder),this.nodes.wrapper=d.make("div",[this.CSS.editorWrapper,...this.isRtl?[this.CSS.editorRtlFix]:[]]),this.nodes.redactor=d.make("div",this.CSS.editorZone),this.nodes.holder.offsetWidth<this.contentRect.width&&this.nodes.wrapper.classList.add(this.CSS.editorWrapperNarrow),this.nodes.redactor.style.paddingBottom=this.config.minHeight+"px",this.nodes.wrapper.appendChild(this.nodes.redactor),this.nodes.holder.appendChild(this.nodes.wrapper)}loadStyles(){const n="editor-js-styles";if(d.get(n))return;const h=d.make("style",null,{id:n,textContent:Si.toString()});this.config.style&&!V(this.config.style)&&this.config.style.nonce&&h.setAttribute("nonce",this.config.style.nonce),d.prepend(document.head,h)}enableModuleBindings(){this.readOnlyMutableListeners.on(this.nodes.redactor,"click",(n=>{this.redactorClicked(n)}),!1),this.readOnlyMutableListeners.on(this.nodes.redactor,"mousedown",(n=>{this.documentTouched(n)}),{capture:!0,passive:!0}),this.readOnlyMutableListeners.on(this.nodes.redactor,"touchstart",(n=>{this.documentTouched(n)}),{capture:!0,passive:!0}),this.readOnlyMutableListeners.on(document,"keydown",(n=>{this.documentKeydown(n)}),!0),this.readOnlyMutableListeners.on(document,"mousedown",(n=>{this.documentClicked(n)}),!0);const n=vt((()=>{this.selectionChanged()}),vi);this.readOnlyMutableListeners.on(document,"selectionchange",n,!0),this.readOnlyMutableListeners.on(window,"resize",(()=>{this.resizeDebouncer()}),{passive:!0}),this.watchBlockHoveredEvents(),this.enableInputsEmptyMark()}watchBlockHoveredEvents(){let n;this.readOnlyMutableListeners.on(this.nodes.redactor,"mousemove",Ve((h=>{const p=h.target.closest(".ce-block");this.Editor.BlockSelection.anyBlockSelected||p&&n!==p&&(n=p,this.eventsDispatcher.emit(No,{block:this.Editor.BlockManager.getBlockByChildNode(p)}))}),20),{passive:!0})}disableModuleBindings(){this.readOnlyMutableListeners.clearAll()}windowResize(){this.contentRectCache=null,this.setIsMobile()
2480
+ /**
2481
+ * All keydowns on document
2482
+ *
2483
+ * @param {KeyboardEvent} event - keyboard event
2484
+ */}documentKeydown(n){switch(n.keyCode){case h.ENTER:this.enterPressed(n);break;case h.BACKSPACE:case h.DELETE:this.backspacePressed(n);break;case h.ESC:this.escapePressed(n);break;default:this.defaultBehaviour(n);break}}
2485
+ /**
2486
+ * Ignore all other document's keydown events
2487
+ *
2488
+ * @param {KeyboardEvent} event - keyboard event
2489
+ */defaultBehaviour(n){const{currentBlock:h}=this.Editor.BlockManager,p=n.target.closest(`.${this.CSS.editorWrapper}`),g=n.altKey||n.ctrlKey||n.metaKey||n.shiftKey;h===void 0||p!==null?p||h&&g||(this.Editor.BlockManager.unsetCurrentBlock(),this.Editor.Toolbar.close()
2490
+ /**
2491
+ * @param {KeyboardEvent} event - keyboard event
2492
+ */):this.Editor.BlockEvents.keydown(n)}backspacePressed(n){const{BlockManager:h,BlockSelection:p,Caret:g}=this.Editor;if(p.anyBlockSelected&&!b.isSelectionExists){const m=h.removeSelectedBlocks(),v=h.insertDefaultBlockAtIndex(m,!0);g.setToBlock(v,g.positions.START),p.clearSelection(n),n.preventDefault(),n.stopPropagation(),n.stopImmediatePropagation()}}
2493
+ /**
2494
+ * Escape pressed
2495
+ * If some of Toolbar components are opened, then close it otherwise close Toolbar
2496
+ *
2497
+ * @param {Event} event - escape keydown event
2498
+ */escapePressed(n){this.Editor.BlockSelection.clearSelection(n),this.Editor.Toolbar.toolbox.opened?(this.Editor.Toolbar.toolbox.close(),this.Editor.Caret.setToBlock(this.Editor.BlockManager.currentBlock,this.Editor.Caret.positions.END)):this.Editor.BlockSettings.opened?this.Editor.BlockSettings.close():this.Editor.InlineToolbar.opened?this.Editor.InlineToolbar.close():this.Editor.Toolbar.close()
2499
+ /**
2500
+ * Enter pressed on document
2501
+ *
2502
+ * @param {KeyboardEvent} event - keyboard event
2503
+ */}enterPressed(n){const{BlockManager:h,BlockSelection:p}=this.Editor;if(this.someToolbarOpened)return;const g=h.currentBlockIndex>=0;if(!p.anyBlockSelected||b.isSelectionExists){if(!this.someToolbarOpened&&g&&n.target.tagName==="BODY"){const h=this.Editor.BlockManager.insert();n.preventDefault(),this.Editor.Caret.setToBlock(h),this.Editor.Toolbar.moveAndOpen(h)}this.Editor.BlockSelection.clearSelection(n)}else p.clearSelection(n),n.preventDefault(),n.stopImmediatePropagation(),n.stopPropagation()}
2504
+ /**
2505
+ * All clicks on document
2506
+ *
2507
+ * @param {MouseEvent} event - Click event
2508
+ */documentClicked(n){var h,p;if(!n.isTrusted)return;const g=n.target;this.nodes.holder.contains(g)||b.isAtEditor||(this.Editor.BlockManager.unsetCurrentBlock(),this.Editor.Toolbar.close());const m=(h=this.Editor.BlockSettings.nodes.wrapper)==null?void 0:h.contains(g),v=(p=this.Editor.Toolbar.nodes.settingsToggler)==null?void 0:p.contains(g),x=m||v;if(this.Editor.BlockSettings.opened&&!x){this.Editor.BlockSettings.close();const n=this.Editor.BlockManager.getBlockByChildNode(g);this.Editor.Toolbar.moveAndOpen(n)}this.Editor.BlockSelection.clearSelection(n)}
2509
+ /**
2510
+ * First touch on editor
2511
+ * Fired before click
2512
+ *
2513
+ * Used to change current block — we need to do it before 'selectionChange' event.
2514
+ * Also:
2515
+ * - Move and show the Toolbar
2516
+ * - Set a Caret
2517
+ *
2518
+ * @param {MouseEvent | TouchEvent} event - touch or mouse event
2519
+ */documentTouched(n){let h=n.target;if(h===this.nodes.redactor){const p=n instanceof MouseEvent?n.clientX:n.touches[0].clientX,g=n instanceof MouseEvent?n.clientY:n.touches[0].clientY;h=document.elementFromPoint(p,g)}try{this.Editor.BlockManager.setCurrentBlockByChildNode(h)}catch{this.Editor.RectangleSelection.isRectActivated()||this.Editor.Caret.setToTheLastBlock()}this.Editor.Toolbar.moveAndOpen()}
2520
+ /**
2521
+ * All clicks on the redactor zone
2522
+ *
2523
+ * @param {MouseEvent} event - click event
2524
+ * @description
2525
+ * - By clicks on the Editor's bottom zone:
2526
+ * - if last Block is empty, set a Caret to this
2527
+ * - otherwise, add a new empty Block and set a Caret to that
2528
+ */redactorClicked(n){if(!b.isCollapsed)return;const h=n.target,p=n.metaKey||n.ctrlKey;if(d.isAnchor(h)&&p){n.stopImmediatePropagation(),n.stopPropagation();const p=h.getAttribute("href"),g=So(p);Mo(g)}else this.processBottomZoneClick(n)}
2529
+ /**
2530
+ * Check if user clicks on the Editor's bottom zone:
2531
+ * - set caret to the last block
2532
+ * - or add new empty block
2533
+ *
2534
+ * @param event - click event
2535
+ */processBottomZoneClick(n){const h=this.Editor.BlockManager.getBlockByIndex(-1),p=d.offset(h.holder).bottom,g=n.pageY,{BlockSelection:m}=this.Editor;if(n.target instanceof Element&&n.target.isEqualNode(this.nodes.redactor)&&!m.anyBlockSelected&&p<g){n.stopImmediatePropagation(),n.stopPropagation();const{BlockManager:h,Caret:p,Toolbar:g}=this.Editor;(!h.lastBlock.tool.isDefault||!h.lastBlock.isEmpty)&&h.insertAtEnd(),p.setToTheLastBlock(),g.moveAndOpen(h.lastBlock)}}selectionChanged(){const{CrossBlockSelection:n,BlockSelection:h}=this.Editor,p=b.anchorElement;if(n.isCrossBlockSelectionStarted&&h.anyBlockSelected&&b.get().removeAllRanges(),!p){b.range||this.Editor.InlineToolbar.close();return}const g=p.closest(`.${D.CSS.content}`);(g===null||g.closest(`.${b.CSS.editorWrapper}`)!==this.nodes.wrapper)&&(this.Editor.InlineToolbar.containsNode(p)||this.Editor.InlineToolbar.close(),!(p.dataset.inlineToolbar==="true"))||(this.Editor.BlockManager.currentBlock||this.Editor.BlockManager.setCurrentBlockByChildNode(p),this.Editor.InlineToolbar.tryToShow(!0))}enableInputsEmptyMark(){function e(n){const h=n.target;Lt(h)}this.readOnlyMutableListeners.on(this.nodes.wrapper,"input",e),this.readOnlyMutableListeners.on(this.nodes.wrapper,"focusin",e),this.readOnlyMutableListeners.on(this.nodes.wrapper,"focusout",e)}}const Ii={BlocksAPI:zo,CaretAPI:jo,EventsAPI:$o,I18nAPI:ot,API:Yo,InlineToolbarAPI:Wo,ListenersAPI:Ko,NotifierAPI:Zo,ReadOnlyAPI:Go,SanitizerAPI:si,SaverAPI:ni,SelectionAPI:ri,ToolsAPI:li,StylesAPI:ai,ToolbarAPI:ci,TooltipAPI:fi,UiAPI:gi,BlockSettings:Ui,Toolbar:qi,InlineToolbar:Zi,BlockEvents:Gi,BlockManager:es,BlockSelection:ts,Caret:Re,CrossBlockSelection:os,DragNDrop:is,ModificationsObserver:rs,Paste:xi,ReadOnly:as,RectangleSelection:xe,Renderer:cs,Saver:ds,Tools:go,UI:ys};class Bs{
2536
+ /**
2537
+ * @param {EditorConfig} config - user configuration
2538
+ */
2539
+ constructor(n){this.moduleInstances={},this.eventsDispatcher=new Te;let h,p;this.isReady=new Promise(((n,g)=>{h=n,p=g})),Promise.resolve().then((async()=>{this.configuration=n,this.validate(),this.init(),await this.start(),await this.render();const{BlockManager:p,Caret:g,UI:m,ModificationsObserver:v}=this.moduleInstances;m.checkEmptiness(),v.enable(),this.configuration.autofocus&&g.setToBlock(p.blocks[0],g.positions.START),h()})).catch((n=>{g(`Editor.js is not ready because of ${n}`,"error"),p(n)}))
2540
+ /**
2541
+ * Setting for configuration
2542
+ *
2543
+ * @param {EditorConfig|string} config - Editor's config to set
2544
+ */}set configuration(h){var p,g;R(h)?this.config={...h}:this.config={holder:h},Ze(!!this.config.holderId,"config.holderId","config.holder"),this.config.holderId&&!this.config.holder&&(this.config.holder=this.config.holderId,this.config.holderId=null),this.config.holder==null&&(this.config.holder="editorjs"),this.config.logLevel||(this.config.logLevel=n.VERBOSE),xo(this.config.logLevel),Ze(!!this.config.initialBlock,"config.initialBlock","config.defaultBlock"),this.config.defaultBlock=this.config.defaultBlock||this.config.initialBlock||"paragraph",this.config.minHeight=this.config.minHeight!==void 0?this.config.minHeight:300;const m={type:this.config.defaultBlock,data:{}};this.config.placeholder=this.config.placeholder||!1,this.config.sanitizer=this.config.sanitizer||{p:!0,b:!0,a:!0},this.config.hideToolbar=!!this.config.hideToolbar&&this.config.hideToolbar,this.config.tools=this.config.tools||{},this.config.i18n=this.config.i18n||{},this.config.data=this.config.data||{blocks:[]},this.config.onReady=this.config.onReady||(()=>{}),this.config.onChange=this.config.onChange||(()=>{}),this.config.inlineToolbar=this.config.inlineToolbar===void 0||this.config.inlineToolbar,(V(this.config.data)||!this.config.data.blocks||this.config.data.blocks.length===0)&&(this.config.data={blocks:[m]}),this.config.readOnly=this.config.readOnly||!1,(p=this.config.i18n)!=null&&p.messages&&A.setDictionary(this.config.i18n.messages),this.config.i18n.direction=((g=this.config.i18n)==null?void 0:g.direction)||"ltr"
2545
+ /**
2546
+ * Returns private property
2547
+ *
2548
+ * @returns {EditorConfig}
2549
+ */}get configuration(){return this.config}validate(){const{holderId:n,holder:h}=this.config;if(n&&h)throw Error("«holderId» and «holder» param can't assign at the same time.");if(Q(h)&&!d.get(h))throw Error(`element with ID «${h}» is missing. Pass correct holder's ID.`);if(h&&R(h)&&!d.isElement(h))throw Error("«holder» value must be an Element node")}init(){this.constructModules(),this.configureModules()
2550
+ /**
2551
+ * Start Editor!
2552
+ *
2553
+ * Get list of modules that needs to be prepared and return a sequence (Promise)
2554
+ *
2555
+ * @returns {Promise<void>}
2556
+ */}async start(){await["Tools","UI","BlockManager","Paste","BlockSelection","RectangleSelection","CrossBlockSelection","ReadOnly"].reduce(((n,h)=>n.then((async()=>{try{await this.moduleInstances[h].prepare()}catch(n){if(n instanceof Pt)throw new Error(n.message);g(`Module ${h} was skipped because of %o`,"warn",n)}}))),Promise.resolve())}render(){return this.moduleInstances.Renderer.render(this.config.data.blocks)}constructModules(){Object.entries(Ii).forEach((([n,h])=>{try{this.moduleInstances[n]=new h({config:this.configuration,eventsDispatcher:this.eventsDispatcher})}catch(h){g("[constructModules]",`Module ${n} skipped because`,"error",h)}}))}configureModules(){for(const n in this.moduleInstances)Object.prototype.hasOwnProperty.call(this.moduleInstances,n)&&(this.moduleInstances[n].state=this.getModulesDiff(n))}
2557
+ /**
2558
+ * Return modules without passed name
2559
+ *
2560
+ * @param {string} name - module for witch modules difference should be calculated
2561
+ */getModulesDiff(n){const h={};for(const p in this.moduleInstances)p!==n&&(h[p]=this.moduleInstances[p]);return h}}
2562
+ /**
2563
+ * Editor.js
2564
+ *
2565
+ * @license Apache-2.0
2566
+ * @see Editor.js <https://editorjs.io>
2567
+ * @author CodeX Team <https://codex.so>
2568
+ */class Ts{static get version(){return"2.30.6"}
2569
+ /**
2570
+ * @param {EditorConfig|string|undefined} [configuration] - user configuration
2571
+ */constructor(n){let t=()=>{};R(n)&&O(n.onReady)&&(t=n.onReady);const h=new Bs(n);this.isReady=h.isReady.then((()=>{this.exportAPI(h),t()}))}
2572
+ /**
2573
+ * Export external API methods
2574
+ *
2575
+ * @param {Core} editor — Editor's instance
2576
+ */exportAPI(n){const h=["configuration"],o=()=>{Object.values(n.moduleInstances).forEach((n=>{O(n.destroy)&&n.destroy(),n.listeners.removeAll()})),pi(),n=null;for(const n in this)Object.prototype.hasOwnProperty.call(this,n)&&delete this[n];Object.setPrototypeOf(this,null)};h.forEach((h=>{this[h]=n[h]})),this.destroy=o,Object.setPrototypeOf(this,n.moduleInstances.API.methods),delete this.exportAPI,Object.entries({blocks:{clear:"clear",render:"render"},caret:{focus:"focus"},events:{on:"on",off:"off",emit:"emit"},saver:{save:"save"}}).forEach((([h,p])=>{Object.entries(p).forEach((([p,g])=>{this[g]=n.moduleInstances.API.methods[h][p]}))}))}}export{Ts as default};
2577
+