@localnerve/editable-object 0.1.7 → 0.1.10
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.
- package/README.md +3 -1
- package/dist/editable-object.css +1 -1
- package/dist/editable-object.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,7 +54,9 @@ This web component issues a 'changed' CustomEvent when an object property is add
|
|
|
54
54
|
* `--eo-item-selected-bg-color` - The background color of the property list item when selected. Defaults to #eee.
|
|
55
55
|
* `--eo-item-selected-color` - The foreground text color of the property list item when selected. Defaults to #222.
|
|
56
56
|
* `--eo-item-selected-border-radius` - The border-radius of the item selection box. Defaults to 4px.
|
|
57
|
-
* `--eo-item-hover-
|
|
57
|
+
* `--eo-item-hover-border-width` - The hover border width. Defaults to 1px.
|
|
58
|
+
* `--eo-item-hover-border-color` - The hover border color. Defaults to #ddd.
|
|
59
|
+
* `--eo-item-hover-border-radius` - The border-radius of the item hover box. Defaults to 4px.
|
|
58
60
|
* `--eo-icon-color` - The color of the toolbar button icons. Defaults to #444.
|
|
59
61
|
* `--eo-add-new-icon-color` - The color of the 'add new property' toolbar button icon. Defdaults to #444.
|
|
60
62
|
* `--eo-input-border-color` - The border color of 'add' and 'edit' input boxes. Defaults to #bbb.
|
package/dist/editable-object.css
CHANGED
|
@@ -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{
|
|
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-item-hover-border-width:1px;--eo-item-hover-border-color:#ddd;--eo-item-hover-border-radius:4px;--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{border:var(--eo-item-hover-border-width) solid var(--eo-item-hover-border-color);border-radius:var(--eo-item-hover-border-radius)}.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}
|
package/dist/editable-object.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! editable-object@0.1.
|
|
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);
|
|
1
|
+
/*! editable-object@0.1.10, 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}#d(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}#a(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})),t.querySelector("input").focus()}#v(e){return new CustomEvent("change",{bubbles:!0,cancelable:!1,composed:!0,detail:e})}#y(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.#e[o]=this.#d(s),this.#r.forEach((e=>{e.host.removeEventListener(e.type,e.listener)})),this.#r.length=0,this.dispatchEvent(this.#v({action:"edit",key:o,previous:this.#d(i),new:this.#d(s)}))}}#f(e){const t=e.previousElementSibling;return!!t&&(e.parentNode.insertBefore(e,t),this.#c(),e.querySelector(".editable-object-up-property").focus(),!0)}#m(e){const t=e.nextElementSibling;return!!t&&(e.parentNode.insertBefore(t,e),this.#c(),e.querySelector(".editable-object-down-property").focus(),!0)}#x(e){e.remove(),this.#c()}#j(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),delete this.#e[o],this.dispatchEvent(this.#v({action:"remove",key:o,previous:this.#d(r),new:null}))}#k(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.#y.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.#k.bind(this),l=this.#E.bind(this),d=this.#j.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",d,!1),this.#o.push({host:e,type:"click",listener:d})}))}#A(e){e.composedPath().includes(this)||this.shadowRoot.querySelector(".editable-object").classList.add("defocused")}#O(){this.shadowRoot.querySelector(".editable-object").classList.remove("defocused")}#P(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}))}))}#_(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=/^\s*(?<property>[^\s:]+)\s*:\s*(?<value>[^$]+)$/,r=t.match(o)?.groups,[i,s]=r?Object.values(r):["",""],n=i.trim(),l=s.trim();if(!n||this.#P(n))return void e.focus();const d={[n]:l};this.mergeObject(d),this.dispatchEvent(this.#v({action:"add",key:n,previous:null,new:this.#d(l)})),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.#a(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(),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-item-hover-border-width:1px;--eo-item-hover-border-color:#ddd;--eo-item-hover-border-radius:4px;--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{border:var(--eo-item-hover-border-width) solid var(--eo-item-hover-border-color);border-radius:var(--eo-item-hover-border-radius)}.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),d=this.#O.bind(this);n&&o.classList.add("touch"),document.addEventListener("click",l,!1),this.#t.push({host:document,type:"click",listener:l}),o.addEventListener("click",d,!0),this.#t.push({host:o,type:"click",listener:d});const a=this.#b.bind(this),c=this.#_.bind(this);r.addEventListener("click",a,!0),this.#t.push({host:r,type:"click",listener:a}),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