@localnerve/editable-object 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- :host{--eo-min-width:300px;--eo-bg-color:#fafafa;--eo-border-radius:4px;--eo-border-focused-color:#444;--eo-border-defocused-color:#aaa;--eo-item-selected-bg-color:#eee;--eo-item-selected-color:#222;--eo-item-selected-border-radius:4px;--eo-item-hover-color:#ddd;--eo-icon-color:#444;--eo-add-new-icon-color:#444;--eo-input-border-color:#bbb;--eo-input-bg-color:#444;--eo-input-color:#eee;--eo-input-font-family:sans-serif;--eo-input-placeholder-color:#aaa}:host(.disabled){pointer-events:none}.editable-object{background:var(--eo-bg-color);border:1px solid var(--eo-border-focused-color);border-radius:var(--eo-border-radius);padding:1rem;min-width:var(--eo-min-width);display:flex;flex-flow:column nowrap;justify-content:center;align-items:center}.editable-object.defocused{border:1px solid var(--eo-border-defocused-color)}ul{padding:0;margin:0;width:100%}li{line-height:2.5;list-style:none;cursor:default;padding:.5rem}input{padding:6px 8px;border-radius:4px;line-height:1.5;border:1px solid var(--eo-input-border-color);color:var(--eo-input-color);background:var(--eo-input-bg-color);font-family:var(--eo-input-font-family)}input::placeholder{color:var(--eo-input-placeholder-color)}.editable-object:not(.defocused) li.selected{background:var(--eo-item-selected-bg-color);color:var(--eo-item-selected-color);border-radius:var(--eo-item-selected-border-radius)}div>div,li{display:flex;align-items:center;justify-content:space-around}.editable-object:not(.defocused,.touch) li:hover{background:var(--eo-item-hover-color)}.property-wrapper{display:flex;flex-flow:row wrap;flex-grow:1;align-items:baseline;min-width:10em}.property-wrapper label{flex:1 1 100%;min-width:8em;max-width:100%}.property-wrapper input{flex:1;min-width:10em}@media (min-width:41.68em){.property-wrapper label{flex-basis:auto;max-width:45%;min-width:15em;padding-right:.5rem}.property-wrapper input{flex:0 1 50%;min-width:15em}}.toolbar{display:flex;gap:2rem;padding-left:1rem}.editable-object.defocused .toolbar,li:not(.selected) .toolbar{opacity:0;pointer-events:none}.toolbar button{position:relative;fill:var(--eo-icon-color)}.editable-object-add-property.icon{fill:var(--eo-add-new-icon-color)}.toolbar button:hover:before{content:"";position:absolute;width:24px;height:24px;background:rgba(0,0,0,.1);left:-4px;top:-4px;border-radius:50%}.icon{background-color:transparent;border:none;cursor:pointer;font-size:0;fill:var(--eo-icon-color);padding:0}.icon svg{width:16px;height:16px}.new-object-property{margin-top:16px;padding:0 8px 0 2px}.add-new-object-property-input,.edit-object-property-input{min-width:20em}.editable-object.defocused .add-new-object-property-input{border:1px solid transparent;opacity:.5}.edit-object-property-input{margin-left:-8px}
1
+ :host{--eo-min-width:300px;--eo-bg-color:#fafafa;--eo-border-radius:4px;--eo-border-focused-color:#444;--eo-border-defocused-color:#aaa;--eo-item-selected-bg-color:#eee;--eo-item-selected-color:#222;--eo-item-selected-border-radius:4px;--eo-item-hover-color:#ddd;--eo-icon-color:#444;--eo-add-new-icon-color:#444;--eo-input-border-color:#bbb;--eo-input-bg-color:#444;--eo-input-color:#eee;--eo-input-font-family:sans-serif;--eo-input-placeholder-color:#aaa}:host(.disabled){pointer-events:none}.editable-object{background:var(--eo-bg-color);border:1px solid var(--eo-border-focused-color);border-radius:var(--eo-border-radius);padding:1rem;min-width:var(--eo-min-width);display:flex;flex-flow:column nowrap;justify-content:center;align-items:center}.editable-object.defocused{border:1px solid var(--eo-border-defocused-color)}ul{padding:0;margin:0;width:100%}li{line-height:2.5;list-style:none;cursor:default;padding:.5rem}input{padding:6px 8px;border-radius:4px;line-height:1.5;border:1px solid var(--eo-input-border-color);color:var(--eo-input-color);background:var(--eo-input-bg-color);font-family:var(--eo-input-font-family)}input::placeholder{color:var(--eo-input-placeholder-color)}.editable-object:not(.defocused) li.selected{background:var(--eo-item-selected-bg-color);color:var(--eo-item-selected-color);border-radius:var(--eo-item-selected-border-radius)}div>div,li{display:flex;align-items:center;justify-content:space-around}.editable-object:not(.defocused,.touch) li:hover{background:var(--eo-item-hover-color)}.property-wrapper{display:flex;flex-flow:row wrap;flex-grow:1;align-items:baseline;min-width:10em}.property-wrapper label{flex:1 1 100%;min-width:8em;max-width:100%}.property-wrapper input{flex:1;min-width:10em}@media (min-width:41.69em){.property-wrapper label{flex-basis:auto;max-width:45%;min-width:15em;padding-right:.5rem}.property-wrapper input{flex:1 1;min-width:16em}}.toolbar{display:flex;gap:2rem;padding-left:1rem}.editable-object.defocused .toolbar,li:not(.selected) .toolbar{opacity:0;pointer-events:none}.toolbar button{position:relative;fill:var(--eo-icon-color)}.editable-object-add-property.icon{fill:var(--eo-add-new-icon-color)}.toolbar button:hover:before{content:"";position:absolute;width:24px;height:24px;background:rgba(0,0,0,.1);left:-4px;top:-4px;border-radius:50%}.icon{background-color:transparent;border:none;cursor:pointer;font-size:0;fill:var(--eo-icon-color);padding:0}.icon svg{width:16px;height:16px}.new-object-property{margin-top:16px;padding:0 8px 0 2px}.add-new-object-property-input,.edit-object-property-input{min-width:20em}.editable-object.defocused .add-new-object-property-input{border:1px solid transparent;opacity:.5}.edit-object-property-input{margin-left:-8px}
@@ -1,2 +1,2 @@
1
- /*! editable-list@0.1.5, Copyright (c) 2025 Alex Grant <alex@localnerve.com> (https://www.localnerve.com), LocalNerve LLC, BSD-3-Clause */
2
- class e extends HTMLElement{#e=null;#t=[];#o=[];#r=[];static#i=["object","add-property-placeholder"];static#s={object:{},addPropertyPlaceholder:"Add new property in key:value format"};static get observedAttributes(){return this.#i}constructor(){super(),this.attachShadow({mode:"open",delegatesFocus:!0})}#n(t){return this.hasAttribute(t)?this.getAttribute(t):e.#s[t]}#l(e){if("string"==typeof e||"number"==typeof e||"boolean"==typeof e||null===e)return e;if(void 0===e||"function"==typeof e||"symbol"==typeof e)return null;if("bigint"==typeof e)return`${e}n`;"[object RegExp]"===Object.prototype.toString.call(e)&&(e={__pattern:e.source,flags:e.flags});let t=JSON.stringify(e);return"{"===t[0]&&(t=t.replaceAll('"',"'")),t}#a(e){const t=e.trim();let o,r=parseInt(t,10);if(r)return r;if(r=parseFloat(t),r)return r;if(/\d+n$/.test(t))return BigInt(t.slice(0,-1));if("false"===t.toLowerCase())return!1;if("true"===t.toLowerCase())return!0;if("null"===t.toLowerCase())return null;try{let e=t;"{"===e[0]&&(e=e.replaceAll("'",'"'));const r=JSON.parse(e);o=Object.keys(r).includes("__pattern")?new RegExp(r.__pattern,r.flags):r}catch{o=t}return o}#d(e,t){return`\n <div class="property-wrapper">\n <label for="eo-${e}-value">${e}</label>\n <input readonly="true" id="eo-${e}-value" type="text" value="${t}" />\n </div>\n <div class="toolbar">\n <button class="editable-object-up-property icon" title="Move up">\n <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">\n <path d="m5 9 1.41 1.41L11 5.83V22h2V5.83l4.59 4.59L19 9l-7-7-7 7z"></path>\n </svg>\n </button>\n <button class="editable-object-down-property icon" title="Move down">\n <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">\n <path d="m19 15-1.41-1.41L13 18.17V2h-2v16.17l-4.59-4.59L5 15l7 7 7-7z"></path>\n </svg>\n </button>\n <button class="editable-object-remove-property icon" title="Remove">\n <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">\n <path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"></path>\n </svg>\n </button>\n </div>\n `}#c(){const e=this.shadowRoot.querySelectorAll(".editable-object-up-property"),t=this.shadowRoot.querySelectorAll(".editable-object-down-property"),o=e.length;for(let r=0;r<o;r++)e[r].style.visibility=0==r?"hidden":"visible",t[r].style.visibility=r==o-1?"hidden":"visible"}#p(){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)}#h(e){for(;"LI"!==e.tagName;)e=e.parentNode;return e}#u(e){this.#b();const t=this.#h(e.target);t.classList.toggle("selected",!0),[...t.querySelectorAll("button")].forEach((e=>{e.tabIndex=0}))}#y(e){return new CustomEvent("change",{bubbles:!0,cancelable:!1,composed:!0,detail:e})}#v(e){"INPUT"===e.target.nodeName&&("Enter"!==e.key&&" "!==e.key||e.target.click())}#w(e){if(this._editing)return;this._editing=!0;const t=this.#h(e.target).querySelector(".property-wrapper > input");t.readOnly=!1,t._value=t.value;const o=this.#g.bind(this),r=this.#g.bind(this);t.addEventListener("blur",o,!1),this.#r.push({host:t,type:"blur",listener:o}),t.addEventListener("keypress",r,!1),this.#r.push({host:t,type:"keypress",listener:r}),t.focus()}#g(e){if(this._editing&&(e instanceof KeyboardEvent&&"Enter"===e.key||!(e instanceof KeyboardEvent))){e.preventDefault();const t=this.#h(e.target),o=t.querySelector(".property-wrapper > label").innerText,r=t.querySelector(".property-wrapper > input"),i=r._value,s=r.value;this._editing=!1,r.readOnly=!0,this.#r.forEach((e=>{e.host.removeEventListener(e.type,e.listener)})),this.#r.length=0,this.dispatchEvent(this.#y({action:"edit",key:o,previous:this.#a(i),new:this.#a(s)}))}}#f(e){const t=e.previousElementSibling;return!!t&&(e.parentNode.insertBefore(e,t),this.#c(),!0)}#m(e){const t=e.nextElementSibling;return!!t&&(e.parentNode.insertBefore(t,e),this.#c(),!0)}#x(e){e.remove(),this.#c()}#k(e){e.stopPropagation();const t=this.#h(e.target),o=t.querySelector(".property-wrapper > label").innerText.trim(),r=t.querySelector(".property-wrapper > input").value.trim();this.#x(t),this.dispatchEvent(this.#y({action:"remove",key:o,previous:this.#a(r),new:null}))}#j(e){e.stopPropagation();const t=this.#h(e.target);this.#f(t)}#E(e){e.stopPropagation();const t=this.#h(e.target);this.#m(t)}#L(){let e,t=0;return function(o){const r=(new Date).getTime(),i=r-t;i<500&&i>0?(o.preventDefault(),this.#w(o)):e=setTimeout((()=>{clearTimeout(e)}),500),t=r}.bind(this)}#S(e){const t=this.#u.bind(this);e.forEach((e=>{e.addEventListener("click",t,!1),this.#o.push({host:e,type:"click",listener:t})}))}#q(e,t){const o=this.#p(),r=this.#L(),i=this.#w.bind(this),s=this.#v.bind(this);e.forEach((e=>{e.addEventListener("keypress",s,!1),this.#o.push({host:e,type:"keypress",listener:s}),e.addEventListener("dblclick",i,!1),this.#o.push({host:e,type:"dblclick",listener:i}),o&&(e.addEventListener("touchend",r),this.#o.push({host:e,type:"touchend",listener:r}))}));const n=this.#j.bind(this),l=this.#E.bind(this),a=this.#k.bind(this);t.up.forEach((e=>{e.addEventListener("click",n,!1),this.#o.push({host:e,type:"click",listener:n})})),t.down.forEach((e=>{e.addEventListener("click",l,!1),this.#o.push({host:e,type:"click",listener:l})})),t.remove.forEach((e=>{e.addEventListener("click",a,!1),this.#o.push({host:e,type:"click",listener:a})}))}#A(e){e.composedPath().includes(this)||this.shadowRoot.querySelector(".editable-object").classList.add("defocused")}#P(){this.shadowRoot.querySelector(".editable-object").classList.remove("defocused")}#_(e){return e in this.#e}#b(){[...this.shadowRoot.querySelectorAll("li")].forEach((e=>{e.classList.toggle("selected",!1),[...e.querySelectorAll("button")].forEach((e=>{e.tabIndex=-1}))}))}#O(e){if(e instanceof KeyboardEvent&&"Enter"===e.key||!(e instanceof KeyboardEvent)){const e=this.shadowRoot.querySelector(".add-new-object-property-input"),t=e.value.trim();if(""!==t){const[o,r]=t.split(":"),i=o.trim(),s=r.trim();if(this.#_(i))return void e.focus();const n={[i]:s};this.mergeObject(n),this.dispatchEvent(this.#y({action:"add",key:i,previous:null,new:this.#a(s)})),this.shadowRoot.querySelector(".object-properties").lastChild.click(),e.value=""}}}get object(){return this.#e}set object(e){if(!e)return;this.#e&&Object.keys(this.#e).length>0&&[this.#o,this.#r].forEach((e=>{e.forEach((e=>{e.host.removeEventListener(e.type,e.listener)}))}));const t=this.shadowRoot.querySelector(".object-properties");t.innerHTML="";const o=[],r=[],i={up:[],down:[],remove:[]};for(const[s,n]of Object.entries(e)){const e=document.createElement("li");e.innerHTML=this.#d(s,this.#l(n)),t.appendChild(e),o.push(e),r.push(e.querySelector(".property-wrapper")),i.up.push(e.querySelector(".editable-object-up-property")),i.down.push(e.querySelector(".editable-object-down-property")),i.remove.push(e.querySelector(".editable-object-remove-property"))}this.#S(o),this.#q(r,i),this.#c();const s=o[0].querySelector("input");s.click(),s.focus(),this.#e=e}get addPropertyPlaceholder(){return this.#n("add-property-placeholder")}set addPropertyPlaceholder(e){const t="add-property-placeholder";e?this.setAttribute(t,e):this.removeAttribute(t)}mergeObject(e){this.object={...this.#e,...e}}connectedCallback(){const{shadowRoot:e}=this;e.innerHTML='<style>:host{--eo-min-width:300px;--eo-bg-color:#fafafa;--eo-border-radius:4px;--eo-border-focused-color:#444;--eo-border-defocused-color:#aaa;--eo-item-selected-bg-color:#eee;--eo-item-selected-color:#222;--eo-item-selected-border-radius:4px;--eo-item-hover-color:#ddd;--eo-icon-color:#444;--eo-add-new-icon-color:#444;--eo-input-border-color:#bbb;--eo-input-bg-color:#444;--eo-input-color:#eee;--eo-input-font-family:sans-serif;--eo-input-placeholder-color:#aaa}:host(.disabled){pointer-events:none}.editable-object{background:var(--eo-bg-color);border:1px solid var(--eo-border-focused-color);border-radius:var(--eo-border-radius);padding:1rem;min-width:var(--eo-min-width);display:flex;flex-flow:column nowrap;justify-content:center;align-items:center}.editable-object.defocused{border:1px solid var(--eo-border-defocused-color)}ul{padding:0;margin:0;width:100%}li{line-height:2.5;list-style:none;cursor:default;padding:.5rem}input{padding:6px 8px;border-radius:4px;line-height:1.5;border:1px solid var(--eo-input-border-color);color:var(--eo-input-color);background:var(--eo-input-bg-color);font-family:var(--eo-input-font-family)}input::placeholder{color:var(--eo-input-placeholder-color)}.editable-object:not(.defocused) li.selected{background:var(--eo-item-selected-bg-color);color:var(--eo-item-selected-color);border-radius:var(--eo-item-selected-border-radius)}div>div,li{display:flex;align-items:center;justify-content:space-around}.editable-object:not(.defocused,.touch) li:hover{background:var(--eo-item-hover-color)}.property-wrapper{display:flex;flex-flow:row wrap;flex-grow:1;align-items:baseline;min-width:10em}.property-wrapper label{flex:1 1 100%;min-width:8em;max-width:100%}.property-wrapper input{flex:1;min-width:10em}@media (min-width:41.68em){.property-wrapper label{flex-basis:auto;max-width:45%;min-width:15em;padding-right:.5rem}.property-wrapper input{flex:0 1 50%;min-width:15em}}.toolbar{display:flex;gap:2rem;padding-left:1rem}.editable-object.defocused .toolbar,li:not(.selected) .toolbar{opacity:0;pointer-events:none}.toolbar button{position:relative;fill:var(--eo-icon-color)}.editable-object-add-property.icon{fill:var(--eo-add-new-icon-color)}.toolbar button:hover:before{content:"";position:absolute;width:24px;height:24px;background:rgba(0,0,0,.1);left:-4px;top:-4px;border-radius:50%}.icon{background-color:transparent;border:none;cursor:pointer;font-size:0;fill:var(--eo-icon-color);padding:0}.icon svg{width:16px;height:16px}.new-object-property{margin-top:16px;padding:0 8px 0 2px}.add-new-object-property-input,.edit-object-property-input{min-width:20em}.editable-object.defocused .add-new-object-property-input{border:1px solid transparent;opacity:.5}.edit-object-property-input{margin-left:-8px}</style><div class="editable-object defocused"><ul class=object-properties></ul><div class=new-object-property><input class=add-new-object-property-input type=text placeholder="Add new property in key:value format"><div class=toolbar><button class="editable-object-add-property icon" title=Add><svg version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink width=24 height=24 viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"></path></svg></button></div></div></div>';const t=this.getAttribute("object");this.object=JSON.parse(t);const o=e.querySelector(".editable-object"),r=e.querySelector(".new-object-property"),i=e.querySelector(".add-new-object-property-input"),s=e.querySelector(".editable-object-add-property"),n=this.#p(),l=this.#A.bind(this),a=this.#P.bind(this);n&&o.classList.add("touch"),document.addEventListener("click",l,!1),this.#t.push({host:document,type:"click",listener:l}),o.addEventListener("click",a,!0),this.#t.push({host:o,type:"click",listener:a});const d=this.#b.bind(this),c=this.#O.bind(this);r.addEventListener("click",d,!0),this.#t.push({host:r,type:"click",listener:d}),i.addEventListener("keypress",c,!1),this.#t.push({host:i,type:"keypress",listener:c}),s.addEventListener("click",c,!1),this.#t.push({host:s,type:"click",listener:c})}disconnectedCallback(){[this.#t,this.#o,this.#r].forEach((e=>{e.forEach((e=>{e.host.removeEventListener(e.type,e.listener)}))}))}attributeChangedCallback(e,t,o){o!==t&&(this[e]=this.getAttribute(e))}}customElements.define("editable-object",e);
1
+ /*! editable-object@0.1.7, Copyright (c) 2025 Alex Grant <alex@localnerve.com> (https://www.localnerve.com), LocalNerve LLC, BSD-3-Clause */
2
+ class e extends HTMLElement{#e=null;#t=[];#o=[];#r=[];static#i=["object","add-property-placeholder"];static#s={object:{},addPropertyPlaceholder:"Add new property in key:value format"};static get observedAttributes(){return this.#i}constructor(){super(),this.attachShadow({mode:"open",delegatesFocus:!0})}#n(t){return this.hasAttribute(t)?this.getAttribute(t):e.#s[t]}#l(e){if("string"==typeof e||"number"==typeof e||"boolean"==typeof e||null===e)return e;if(void 0===e||"function"==typeof e||"symbol"==typeof e)return null;if("bigint"==typeof e)return`${e}n`;"[object RegExp]"===Object.prototype.toString.call(e)&&(e={__pattern:e.source,flags:e.flags});let t=JSON.stringify(e);return"{"===t[0]&&(t=t.replaceAll('"',"'")),t}#a(e){const t=e.trim();let o,r=parseInt(t,10);if(r)return r;if(r=parseFloat(t),r)return r;if(/\d+n$/.test(t))return BigInt(t.slice(0,-1));if("false"===t.toLowerCase())return!1;if("true"===t.toLowerCase())return!0;if("null"===t.toLowerCase())return null;try{let e=t;"{"===e[0]&&(e=e.replaceAll("'",'"'));const r=JSON.parse(e);o=Object.keys(r).includes("__pattern")?new RegExp(r.__pattern,r.flags):r}catch{o=t}return o}#d(e,t){return`\n <div class="property-wrapper">\n <label for="eo-${e}-value">${e}</label>\n <input readonly="true" id="eo-${e}-value" type="text" value="${t}" />\n </div>\n <div class="toolbar">\n <button class="editable-object-up-property icon" title="Move up">\n <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">\n <path d="m5 9 1.41 1.41L11 5.83V22h2V5.83l4.59 4.59L19 9l-7-7-7 7z"></path>\n </svg>\n </button>\n <button class="editable-object-down-property icon" title="Move down">\n <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">\n <path d="m19 15-1.41-1.41L13 18.17V2h-2v16.17l-4.59-4.59L5 15l7 7 7-7z"></path>\n </svg>\n </button>\n <button class="editable-object-remove-property icon" title="Remove">\n <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">\n <path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"></path>\n </svg>\n </button>\n </div>\n `}#c(){const e=this.shadowRoot.querySelectorAll(".editable-object-up-property"),t=this.shadowRoot.querySelectorAll(".editable-object-down-property"),o=e.length;for(let r=0;r<o;r++)e[r].style.visibility=0==r?"hidden":"visible",t[r].style.visibility=r==o-1?"hidden":"visible"}#p(){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)}#h(e){for(;"LI"!==e.tagName;)e=e.parentNode;return e}#u(e){this.#b();const t=this.#h(e.target);t.classList.toggle("selected",!0),[...t.querySelectorAll("button")].forEach((e=>{e.tabIndex=0}))}#y(e){return new CustomEvent("change",{bubbles:!0,cancelable:!1,composed:!0,detail:e})}#v(e){"INPUT"===e.target.nodeName&&("Enter"!==e.key&&" "!==e.key||e.target.click())}#w(e){if(this._editing)return;this._editing=!0;const t=this.#h(e.target).querySelector(".property-wrapper > input");t.readOnly=!1,t._value=t.value;const o=this.#g.bind(this),r=this.#g.bind(this);t.addEventListener("blur",o,!1),this.#r.push({host:t,type:"blur",listener:o}),t.addEventListener("keypress",r,!1),this.#r.push({host:t,type:"keypress",listener:r}),t.focus()}#g(e){if(this._editing&&(e instanceof KeyboardEvent&&"Enter"===e.key||!(e instanceof KeyboardEvent))){e.preventDefault();const t=this.#h(e.target),o=t.querySelector(".property-wrapper > label").innerText,r=t.querySelector(".property-wrapper > input"),i=r._value,s=r.value;this._editing=!1,r.readOnly=!0,this.#r.forEach((e=>{e.host.removeEventListener(e.type,e.listener)})),this.#r.length=0,this.dispatchEvent(this.#y({action:"edit",key:o,previous:this.#a(i),new:this.#a(s)}))}}#f(e){const t=e.previousElementSibling;return!!t&&(e.parentNode.insertBefore(e,t),this.#c(),!0)}#m(e){const t=e.nextElementSibling;return!!t&&(e.parentNode.insertBefore(t,e),this.#c(),!0)}#x(e){e.remove(),this.#c()}#k(e){e.stopPropagation();const t=this.#h(e.target),o=t.querySelector(".property-wrapper > label").innerText.trim(),r=t.querySelector(".property-wrapper > input").value.trim();this.#x(t),this.dispatchEvent(this.#y({action:"remove",key:o,previous:this.#a(r),new:null}))}#j(e){e.stopPropagation();const t=this.#h(e.target);this.#f(t)}#E(e){e.stopPropagation();const t=this.#h(e.target);this.#m(t)}#L(){let e,t=0;return function(o){const r=(new Date).getTime(),i=r-t;i<500&&i>0?(o.preventDefault(),this.#w(o)):e=setTimeout((()=>{clearTimeout(e)}),500),t=r}.bind(this)}#S(e){const t=this.#u.bind(this);e.forEach((e=>{e.addEventListener("click",t,!1),this.#o.push({host:e,type:"click",listener:t})}))}#q(e,t){const o=this.#p(),r=this.#L(),i=this.#w.bind(this),s=this.#v.bind(this);e.forEach((e=>{e.addEventListener("keypress",s,!1),this.#o.push({host:e,type:"keypress",listener:s}),e.addEventListener("dblclick",i,!1),this.#o.push({host:e,type:"dblclick",listener:i}),o&&(e.addEventListener("touchend",r),this.#o.push({host:e,type:"touchend",listener:r}))}));const n=this.#j.bind(this),l=this.#E.bind(this),a=this.#k.bind(this);t.up.forEach((e=>{e.addEventListener("click",n,!1),this.#o.push({host:e,type:"click",listener:n})})),t.down.forEach((e=>{e.addEventListener("click",l,!1),this.#o.push({host:e,type:"click",listener:l})})),t.remove.forEach((e=>{e.addEventListener("click",a,!1),this.#o.push({host:e,type:"click",listener:a})}))}#A(e){e.composedPath().includes(this)||this.shadowRoot.querySelector(".editable-object").classList.add("defocused")}#P(){this.shadowRoot.querySelector(".editable-object").classList.remove("defocused")}#_(e){return e in this.#e}#b(){[...this.shadowRoot.querySelectorAll("li")].forEach((e=>{e.classList.toggle("selected",!1),[...e.querySelectorAll("button")].forEach((e=>{e.tabIndex=-1}))}))}#O(e){if(e instanceof KeyboardEvent&&"Enter"===e.key||!(e instanceof KeyboardEvent)){const e=this.shadowRoot.querySelector(".add-new-object-property-input"),t=e.value.trim();if(""!==t){const[o,r]=t.split(":"),i=o.trim(),s=r.trim();if(this.#_(i))return void e.focus();const n={[i]:s};this.mergeObject(n),this.dispatchEvent(this.#y({action:"add",key:i,previous:null,new:this.#a(s)})),this.shadowRoot.querySelector(".object-properties").lastChild.click(),e.value=""}}}get object(){return this.#e}set object(e){if(!e)return;this.#e&&Object.keys(this.#e).length>0&&[this.#o,this.#r].forEach((e=>{e.forEach((e=>{e.host.removeEventListener(e.type,e.listener)}))}));const t=this.shadowRoot.querySelector(".object-properties");t.innerHTML="";const o=[],r=[],i={up:[],down:[],remove:[]};for(const[s,n]of Object.entries(e)){const e=document.createElement("li");e.innerHTML=this.#d(s,this.#l(n)),t.appendChild(e),o.push(e),r.push(e.querySelector(".property-wrapper")),i.up.push(e.querySelector(".editable-object-up-property")),i.down.push(e.querySelector(".editable-object-down-property")),i.remove.push(e.querySelector(".editable-object-remove-property"))}this.#S(o),this.#q(r,i),this.#c(),o[0].querySelector("input").click(),this.#e=e}get addPropertyPlaceholder(){return this.#n("add-property-placeholder")}set addPropertyPlaceholder(e){const t="add-property-placeholder";e?this.setAttribute(t,e):this.removeAttribute(t)}mergeObject(e){this.object={...this.#e,...e}}connectedCallback(){const{shadowRoot:e}=this;e.innerHTML='<style>:host{--eo-min-width:300px;--eo-bg-color:#fafafa;--eo-border-radius:4px;--eo-border-focused-color:#444;--eo-border-defocused-color:#aaa;--eo-item-selected-bg-color:#eee;--eo-item-selected-color:#222;--eo-item-selected-border-radius:4px;--eo-item-hover-color:#ddd;--eo-icon-color:#444;--eo-add-new-icon-color:#444;--eo-input-border-color:#bbb;--eo-input-bg-color:#444;--eo-input-color:#eee;--eo-input-font-family:sans-serif;--eo-input-placeholder-color:#aaa}:host(.disabled){pointer-events:none}.editable-object{background:var(--eo-bg-color);border:1px solid var(--eo-border-focused-color);border-radius:var(--eo-border-radius);padding:1rem;min-width:var(--eo-min-width);display:flex;flex-flow:column nowrap;justify-content:center;align-items:center}.editable-object.defocused{border:1px solid var(--eo-border-defocused-color)}ul{padding:0;margin:0;width:100%}li{line-height:2.5;list-style:none;cursor:default;padding:.5rem}input{padding:6px 8px;border-radius:4px;line-height:1.5;border:1px solid var(--eo-input-border-color);color:var(--eo-input-color);background:var(--eo-input-bg-color);font-family:var(--eo-input-font-family)}input::placeholder{color:var(--eo-input-placeholder-color)}.editable-object:not(.defocused) li.selected{background:var(--eo-item-selected-bg-color);color:var(--eo-item-selected-color);border-radius:var(--eo-item-selected-border-radius)}div>div,li{display:flex;align-items:center;justify-content:space-around}.editable-object:not(.defocused,.touch) li:hover{background:var(--eo-item-hover-color)}.property-wrapper{display:flex;flex-flow:row wrap;flex-grow:1;align-items:baseline;min-width:10em}.property-wrapper label{flex:1 1 100%;min-width:8em;max-width:100%}.property-wrapper input{flex:1;min-width:10em}@media (min-width:41.69em){.property-wrapper label{flex-basis:auto;max-width:45%;min-width:15em;padding-right:.5rem}.property-wrapper input{flex:1 1;min-width:16em}}.toolbar{display:flex;gap:2rem;padding-left:1rem}.editable-object.defocused .toolbar,li:not(.selected) .toolbar{opacity:0;pointer-events:none}.toolbar button{position:relative;fill:var(--eo-icon-color)}.editable-object-add-property.icon{fill:var(--eo-add-new-icon-color)}.toolbar button:hover:before{content:"";position:absolute;width:24px;height:24px;background:rgba(0,0,0,.1);left:-4px;top:-4px;border-radius:50%}.icon{background-color:transparent;border:none;cursor:pointer;font-size:0;fill:var(--eo-icon-color);padding:0}.icon svg{width:16px;height:16px}.new-object-property{margin-top:16px;padding:0 8px 0 2px}.add-new-object-property-input,.edit-object-property-input{min-width:20em}.editable-object.defocused .add-new-object-property-input{border:1px solid transparent;opacity:.5}.edit-object-property-input{margin-left:-8px}</style><div class="editable-object defocused"><ul class=object-properties></ul><div class=new-object-property><input class=add-new-object-property-input type=text placeholder="Add new property in key:value format"><div class=toolbar><button class="editable-object-add-property icon" title=Add><svg version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink width=24 height=24 viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"></path></svg></button></div></div></div>';const t=this.getAttribute("object");this.object=JSON.parse(t);const o=e.querySelector(".editable-object"),r=e.querySelector(".new-object-property"),i=e.querySelector(".add-new-object-property-input"),s=e.querySelector(".editable-object-add-property"),n=this.#p(),l=this.#A.bind(this),a=this.#P.bind(this);n&&o.classList.add("touch"),document.addEventListener("click",l,!1),this.#t.push({host:document,type:"click",listener:l}),o.addEventListener("click",a,!0),this.#t.push({host:o,type:"click",listener:a});const d=this.#b.bind(this),c=this.#O.bind(this);r.addEventListener("click",d,!0),this.#t.push({host:r,type:"click",listener:d}),i.addEventListener("keypress",c,!1),this.#t.push({host:i,type:"keypress",listener:c}),s.addEventListener("click",c,!1),this.#t.push({host:s,type:"click",listener:c})}disconnectedCallback(){[this.#t,this.#o,this.#r].forEach((e=>{e.forEach((e=>{e.host.removeEventListener(e.type,e.listener)}))}))}attributeChangedCallback(e,t,o){o!==t&&(this[e]=this.getAttribute(e))}}customElements.define("editable-object",e);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@localnerve/editable-object",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "A vanillajs editable-object web component for visual object display and editing",
5
5
  "main": "dist/index.js",
6
6
  "browser": "dist/editable-object.js",