diff --git a/demo/assets/bundle.js b/demo/assets/bundle.js new file mode 100644 index 0000000..fc3c33a --- /dev/null +++ b/demo/assets/bundle.js @@ -0,0 +1 @@ +(()=>{var e={570:()=>{function e(){let e=document.createElement("p");return e.classList.add("johannes-content-element"),e.contentEditable=!0,e.setAttribute("data-placeholder","Write something or type / (slash) to choose a block..."),e}function t(){let t=document.createElement("div"),n=e(),o=document.createElement("button");return o.innerHTML='',t.appendChild(o),t.appendChild(n),t.classList.add("draggable-block"),o.classList.add("drag-handler"),o.classList.add("button-reset"),o.draggable=!0,t}document.addEventListener("DOMContentLoaded",(function(){const e=document.querySelector(".johannes-editor");let n=null,o=document.createElement("div");o.classList.add("drop-line"),o.style.height="2px",o.style.display="none",e.addEventListener("dragstart",(e=>{e.target.classList.contains("drag-handler")&&(n=e.target.closest(".draggable-block"),n.setAttribute("draggable","true"),setTimeout((()=>{n.style.opacity="0.5"}),0))})),e.addEventListener("dragend",(()=>{setTimeout((()=>{n&&(n.style.opacity="",n.removeAttribute("draggable"),n=null),o.remove()}),0)})),e.addEventListener("dragover",(e=>{e.preventDefault();let t=e.target.closest(".draggable-block");if(t&&t!==n){let n=t.getBoundingClientRect(),r=n.y+n.height/2;e.clientY>r?t.nextElementSibling!==o&&t.insertAdjacentElement("afterend",o):t.previousElementSibling!==o&&t.insertAdjacentElement("beforebegin",o)}o.style.display="block"})),e.addEventListener("drop",(e=>{e.preventDefault(),o.parentElement&&(o.parentElement.insertBefore(n,o),o.remove())})),document.addEventListener("keydown",(function(e){if("Enter"===e.key&&e.target.isContentEditable){e.preventDefault();const n=t(),o=e.target.closest(".draggable-block");o&&(o.nextSibling?o.parentNode.insertBefore(n,o.nextSibling):o.parentNode.appendChild(n)),setTimeout((()=>{let e=n.querySelector(".johannes-content-element");e&&e.focus()}),0)}})),document.querySelector(".add-block").addEventListener("click",(function(){let e=t();document.querySelector(".johannes-editor > .content").appendChild(e)}))})),document.addEventListener("DOMContentLoaded",(()=>{document.querySelector(".content").addEventListener("input",(function(e){const n=e.target;if("P"===n.tagName&&n.isContentEditable){const o=n.innerText.split("\n");if(o.length>1){e.preventDefault(),n.innerText=o[0];let r=n;for(let e=1;e{document.querySelector(".content").addEventListener("keydown",(function(e){if("Backspace"===e.key){const t=document.activeElement;if("H1"!==t.tagName&&t.isContentEditable){const n=t.getAttribute("data-placeholder"),o=t.textContent.trim();if(""===o||o===n){e.preventDefault();let n=t.closest(".draggable-block").previousElementSibling;t.remove();let o=n.querySelector(".johannes-content-element");o.focus();let r=document.createRange(),a=window.getSelection();r.selectNodeContents(o),r.collapse(!1),a.removeAllRanges(),a.addRange(r)}}}}))})),document.addEventListener("DOMContentLoaded",(function(){document.body.addEventListener("paste",(function(e){if("true"===e.target.getAttribute("contenteditable")){e.preventDefault();const t=(e.clipboardData||window.clipboardData).getData("text/plain");document.execCommand("insertText",!1,t)}}))})),document.addEventListener("DOMContentLoaded",(e=>{document.querySelector(".content").addEventListener("keydown",(function(e){"Escape"===e.key&&(document.querySelector(".block-options").style.display="none")}))})),document.addEventListener("DOMContentLoaded",(()=>{const t=document.querySelector(".johannes-editor");let n=null;t.addEventListener("keydown",(function(e){"/"===e.key&&setTimeout((()=>{const t=window.getSelection().rangeCount>0?window.getSelection().getRangeAt(0):null;t||alert("Erro fatal!!!");const o=e.target;if(o.closest(".draggable-block")){e.preventDefault(),n=o.closest(".draggable-block");const r=t.getBoundingClientRect(),a=document.querySelector(".block-options");a.style.left=`${r.left}px`,a.style.top=`${r.bottom+window.scrollY}px`,a.style.display="block"}}),0)})),document.querySelectorAll(".block-options .option").forEach((t=>{t.addEventListener("click",(function(){const t=this.getAttribute("data-type");n&&function(t,n){let o,r=t.querySelector(".johannes-content-element"),a=r.innerText;switch(a.endsWith("/")&&(a=a.slice(0,-1)),n){case"p":o=e(),o.innerText=a;break;case"h2":o=function(){let e=document.createElement("h2");return e.classList.add("johannes-content-element"),e.contentEditable=!0,e.setAttribute("data-placeholder","Heading 2"),e}(),o.innerText=a;break;case"code":o=document.createElement("pre");const t=document.createElement("code");t.innerText=a,o.appendChild(t);break;case"image":o=document.createElement("img"),o.src=a,o.alt="Descriptive text";break;case"quote":o=document.createElement("blockquote"),o.innerText=a;break;case"list":o=document.createElement("ul"),a.split("\n").forEach((e=>{const t=document.createElement("li");t.innerText=e,o.appendChild(t)}));break;default:return void console.error("Unsupported type")}t.replaceChild(o,r),o.focus()}(n,t),document.querySelector(".block-options").style.display="none"}))}))}))}},t={};function n(o){var r=t[o];if(void 0!==r)return r.exports;var a=t[o]={exports:{}};return e[o](a,a.exports,n),a.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var o in t)n.o(t,o)&&!n.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{"use strict";n(570)})()})(); \ No newline at end of file diff --git a/demo/assets/style.css b/demo/assets/style.css new file mode 100644 index 0000000..8b41edb --- /dev/null +++ b/demo/assets/style.css @@ -0,0 +1,190 @@ +.drag-handler { + color: #84888d; + visibility: hidden; + cursor: grab; + align-self: start; +} + +.drag-handler:active { + cursor: grabbing; +} + +.draggable-block { + display: flex; + flex-direction: row; + margin-bottom: 1rem; +} + +.draggable-block:hover .drag-handler { + visibility: visible; + vertical-align: top; + justify-content: start; +} + +.drop-line { + height: 1rem; + background-color: #84888d; + width: 100%; +} + + + + +.add-block { + margin: 0; + padding: 0; + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; + border: 1px solid #000; + background-color: white; + transition: all 0.3s ease; + box-sizing: border-box; +} + +.add-block-wrapper { + width: 100%; + height: 3.125rem; + +} + +.add-block-wrapper:hover .add-block { + display: flex; + +} + +h1[data-placeholder]:empty:before { + content: attr(data-placeholder); + color: #84888d !important; + display: block; +} + +h1[data-placeholder]:focus:before {} + + +*[contenteditable="true"]:not(h1):empty:before { + content: attr(data-placeholder); + color: #84888acd; + display: none; +} + +*[contenteditable="true"]:not(h1):empty:hover:before { + display: block; +} + +*[contenteditable="true"]:not(h1)[data-placeholder]:empty:focus:before { + content: attr(data-placeholder); + color: #84888acd !important; + display: block; +} + +h1 { + font-size: 2.5rem; + font-weight: bolder !important; +} + +.block-options { + width: 480px; +} + +.johannes-editor { + width: 100%; + +} + +.content { + width: 100%; + box-sizing: border-box; + + +} + +pre { + width: 100%; +} + +[contenteditable] { + outline: none; +} + +.content-area { + height: 2000px; + background-color: #f0f0f1 !important; + + font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; +} + + +.editor { + + display: flex; + + margin-top: 80px; +} + +.block-options { + padding: 10px; + background: #f9f9f9; + border: 1px solid #ccc; + margin-top: 10px; + position: absolute; + display: none; +} + +.block-options .option { + padding: 5px 10px; + border: 1px solid #ddd; + margin: 5px; + cursor: pointer; + display: inline-block; +} + +.block-options .option:hover { + background-color: #e9e9e9; +} + + +p { + font-size: 20px !important; + color: #242424; +} + + +.draggable-block, +.draggable-block * { + user-select: text; +} + + +.johannes-content-element { + width: 100%; + padding: 0; + margin: 0; +} + + +.editor-wrapper { + width: 80%; + margin-left: auto; + margin-right: auto; +} + + + +.button-reset { + border: none; + margin: 0; + padding: 0; + width: auto; + overflow: visible; + background: transparent; + color: inherit; + font: inherit; + line-height: normal; + -webkit-font-smoothing: inherit; + -moz-osx-font-smoothing: inherit; + -webkit-appearance: none; +} +