perfect-gui 4.8.2 → 4.9.0

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 CHANGED
@@ -84,6 +84,10 @@ const gui = new GUI({
84
84
 
85
85
  color: '#bada55',
86
86
  // Default is #2e2e2e
87
+
88
+ onUpdate: () => {
89
+ // Callback function triggered each time this GUI component is updated.
90
+ }
87
91
  });
88
92
  ```
89
93
 
@@ -417,7 +417,7 @@ function A(y) {
417
417
  }
418
418
  class x {
419
419
  constructor(e = {}) {
420
- if (e.container ? (this.container = typeof e.container == "string" ? document.querySelector(e.container) : e.container, this.position_type = "absolute") : (this.container = document.body, this.position_type = "fixed"), this.propReferences = [], this.folders = [], e.isFolder) {
420
+ if (e.container ? (this.container = typeof e.container == "string" ? document.querySelector(e.container) : e.container, this.position_type = "absolute") : (this.container = document.body, this.position_type = "fixed"), typeof e.onUpdate == "function" && (this.onUpdate = e.onUpdate), this.propReferences = [], this.folders = [], e.isFolder) {
421
421
  this._folderConstructor(e.folderOptions);
422
422
  return;
423
423
  }
@@ -474,10 +474,11 @@ class x {
474
474
  }
475
475
  button(e, t) {
476
476
  let o = "";
477
- typeof e != "string" ? typeof e == "object" && (e != null && e.hasOwnProperty("name")) ? o = e.name == "" ? " " : e.name : o = " " : o = e == "" ? " " : e, this.imageContainer = null, typeof t != "function" && (t = () => {
478
- });
477
+ typeof e != "string" ? typeof e == "object" && (e != null && e.hasOwnProperty("name")) ? o = e.name == "" ? " " : e.name : o = " " : o = e == "" ? " " : e, this.imageContainer = null;
479
478
  const a = document.createElement("div");
480
- a.className = "p-gui__button", a.textContent = o, a.addEventListener("click", t), this.wrapper.append(a), typeof e.color == "string" && (a.style.setProperty("--color-accent", e.color), a.style.setProperty("--color-accent-hover", e.hoverColor || e.color));
479
+ a.className = "p-gui__button", a.textContent = o, a.addEventListener("click", () => {
480
+ this.onUpdate && this.onUpdate(), t && t();
481
+ }), this.wrapper.append(a), typeof e.color == "string" && (a.style.setProperty("--color-accent", e.color), a.style.setProperty("--color-accent-hover", e.hoverColor || e.color));
481
482
  }
482
483
  image(e = {}, t) {
483
484
  if (typeof e != "object")
@@ -496,16 +497,16 @@ class x {
496
497
  s.className = "p-gui__image", s.style = "background-image: url(" + o + "); " + n, this.imageContainer.append(s), r && i && s.classList.add("p-gui__image--selected");
497
498
  const l = document.createElement("div");
498
499
  return l.className = "p-gui__image-text", l.textContent = p, s.append(l), s.addEventListener("click", () => {
499
- let f = s.parentElement.querySelectorAll(".p-gui__image--selected");
500
- for (let c = 0; c < f.length; c++)
501
- f[c].classList.remove("p-gui__image--selected");
502
- i && s.classList.add("p-gui__image--selected"), typeof t == "function" && t({ path: o, text: p });
500
+ let h = s.parentElement.querySelectorAll(".p-gui__image--selected");
501
+ for (let c = 0; c < h.length; c++)
502
+ h[c].classList.remove("p-gui__image--selected");
503
+ i && s.classList.add("p-gui__image--selected"), typeof t == "function" && t({ path: o, text: p }), this.onUpdate && this.onUpdate();
503
504
  }), s;
504
505
  }
505
506
  slider(e = {}, t) {
506
507
  if (typeof e != "object")
507
508
  throw Error(`[GUI] slider() first parameter must be an object. Received: ${typeof e}.`);
508
- let o = typeof e.name == "string" && e.name || " ", a = !1, p = null, r = e.obj, i = e.prop, n = typeof e.value == "number" ? e.value : null, s = e.min ?? 0, l = e.max ?? 1, f = e.step || (l - s) / 100;
509
+ let o = typeof e.name == "string" && e.name || " ", a = !1, p = null, r = e.obj, i = e.prop, n = typeof e.value == "number" ? e.value : null, s = e.min ?? 0, l = e.max ?? 1, h = e.step || (l - s) / 100;
509
510
  if (n !== null)
510
511
  (i != null || r != null) && console.warn('[GUI] slider() "obj" and "prop" parameters are ignored when a "value" parameter is used.');
511
512
  else if (i != null && r != null) {
@@ -520,13 +521,13 @@ class x {
520
521
  const c = document.createElement("div");
521
522
  c.className = "p-gui__slider", c.textContent = o, this.wrapper.append(c);
522
523
  const d = document.createElement("input");
523
- d.className = "p-gui__slider-ctrl", d.setAttribute("type", "range"), d.setAttribute("min", s), d.setAttribute("max", l), d.setAttribute("step", f), d.setAttribute("value", a ? r[i] : n), c.append(d);
524
- const h = document.createElement("div");
525
- h.className = "p-gui__slider-value", h.textContent = String(a ? r[i] : n), c.append(h), d.addEventListener("input", () => {
526
- h.textContent = d.value, a ? r[i] = d.value : typeof t == "function" && t(parseFloat(d.value));
524
+ d.className = "p-gui__slider-ctrl", d.setAttribute("type", "range"), d.setAttribute("min", s), d.setAttribute("max", l), d.setAttribute("step", h), d.setAttribute("value", a ? r[i] : n), c.append(d);
525
+ const f = document.createElement("div");
526
+ f.className = "p-gui__slider-value", f.textContent = String(a ? r[i] : n), c.append(f), d.addEventListener("input", () => {
527
+ f.textContent = d.value, a ? r[i] = parseFloat(d.value) : typeof t == "function" && t(parseFloat(d.value)), this.onUpdate && this.onUpdate();
527
528
  }), a && Object.defineProperty(r, i, {
528
529
  set: (g) => {
529
- this.propReferences[p] = g, d.value = g, h.textContent = String(g), typeof t == "function" && t(parseFloat(d.value));
530
+ this.propReferences[p] = g, d.value = g, f.textContent = String(g), typeof t == "function" && t(parseFloat(d.value));
530
531
  },
531
532
  get: () => this.propReferences[p]
532
533
  });
@@ -549,14 +550,14 @@ class x {
549
550
  const s = document.createElement("div");
550
551
  s.textContent = o, s.className = "p-gui__switch", this.wrapper.append(s), s.addEventListener("click", (c) => {
551
552
  const d = c.target.childNodes[1];
552
- let h = !0;
553
- d.classList.contains("p-gui__switch-checkbox--active") && (h = !1), d.classList.toggle("p-gui__switch-checkbox--active"), a ? r[i] = h : typeof t == "function" && t(h);
553
+ let f = !0;
554
+ d.classList.contains("p-gui__switch-checkbox--active") && (f = !1), d.classList.toggle("p-gui__switch-checkbox--active"), a ? r[i] = f : typeof t == "function" && t(f), this.onUpdate && this.onUpdate();
554
555
  });
555
556
  let l = (() => a ? r[i] ? " p-gui__switch-checkbox--active" : "" : n ? " p-gui__switch-checkbox--active" : "")();
556
- const f = document.createElement("div");
557
- f.className = "p-gui__switch-checkbox" + l, s.append(f), a && Object.defineProperty(r, i, {
557
+ const h = document.createElement("div");
558
+ h.className = "p-gui__switch-checkbox" + l, s.append(h), a && Object.defineProperty(r, i, {
558
559
  set: (c) => {
559
- this.propReferences[p] = c, c ? f.classList.add("p-gui__switch-checkbox--active") : f.classList.remove("p-gui__switch-checkbox--active"), typeof t == "function" && t(c);
560
+ this.propReferences[p] = c, c ? h.classList.add("p-gui__switch-checkbox--active") : h.classList.remove("p-gui__switch-checkbox--active"), typeof t == "function" && t(c);
560
561
  },
561
562
  get: () => this.propReferences[p]
562
563
  });
@@ -590,21 +591,21 @@ class x {
590
591
  } else
591
592
  (i != null && r == null || i == null && r == null) && console.warn('[GUI] list() "obj" and "prop" parameters must be used together.');
592
593
  this.imageContainer = null;
593
- let f = document.createElement("div");
594
- f.className = "p-gui__list", f.textContent = o, this.wrapper.append(f);
594
+ let h = document.createElement("div");
595
+ h.className = "p-gui__list", h.textContent = o, this.wrapper.append(h);
595
596
  let c = document.createElement("select");
596
- f.append(c), c.className = "p-gui__list-dropdown", c.addEventListener("change", (d) => {
597
- a ? r[i] = d.target.value : t && t(d.target.value);
598
- }), n && n.forEach((d, h) => {
597
+ h.append(c), c.className = "p-gui__list-dropdown", c.addEventListener("change", (d) => {
598
+ a ? r[i] = d.target.value : t && t(d.target.value), this.onUpdate && this.onUpdate();
599
+ }), n && n.forEach((d, f) => {
599
600
  const g = l ? d.name : d, u = l ? d.value : d;
600
601
  let m = document.createElement("option");
601
- m.setAttribute("value", u), m.textContent = g, c.append(m), (!l && s == h || l && s == u) && m.setAttribute("selected", "");
602
+ m.setAttribute("value", u), m.textContent = g, c.append(m), (!l && s == f || l && s == u) && m.setAttribute("selected", "");
602
603
  }), a && Object.defineProperty(r, i, {
603
604
  set: (d) => {
604
- let h, g, u;
605
- l ? (u = n.find((v) => v.value == d), g = (u == null ? void 0 : u.value) || n[0].value, h = n.indexOf(u)) : (typeof d == "string" && (h = n.indexOf(d), g = d), typeof d == "number" && (h = d, g = n[d])), this.propReferences[p] = l ? g : d;
605
+ let f, g, u;
606
+ l ? (u = n.find((v) => v.value == d), g = (u == null ? void 0 : u.value) || n[0].value, f = n.indexOf(u)) : (typeof d == "string" && (f = n.indexOf(d), g = d), typeof d == "number" && (f = d, g = n[d])), this.propReferences[p] = l ? g : d;
606
607
  const m = c.querySelector("[selected]");
607
- m && m.removeAttribute("selected"), c.querySelectorAll("option")[h].setAttribute("selected", ""), typeof t == "function" && t(l ? u : g, h);
608
+ m && m.removeAttribute("selected"), c.querySelectorAll("option")[f].setAttribute("selected", ""), typeof t == "function" && t(l ? u : g, f);
608
609
  },
609
610
  get: () => this.propReferences[p]
610
611
  });
@@ -613,15 +614,15 @@ class x {
613
614
  if (typeof e != "object")
614
615
  throw Error(`[GUI] vector2() first parameter must be an object. Received: ${typeof e}.`);
615
616
  let o = typeof e.name == "string" && e.name || " ";
616
- const a = e.x.min ?? 0, p = e.x.max ?? 1, r = e.y.min ?? 0, i = e.y.max ?? 1, n = e.x.obj, s = e.x.prop, l = this.propReferences.push(n[s]) - 1, f = e.y.obj, c = e.y.prop, d = this.propReferences.push(f[c]) - 1;
617
+ const a = e.x.min ?? 0, p = e.x.max ?? 1, r = e.y.min ?? 0, i = e.y.max ?? 1, n = e.x.obj, s = e.x.prop, l = this.propReferences.push(n[s]) - 1, h = e.y.obj, c = e.y.prop, d = this.propReferences.push(h[c]) - 1;
617
618
  t = typeof t == "function" ? t : null, this.imageContainer = null;
618
- const h = document.createElement("div");
619
- h.className = "p-gui__vector2", h.textContent = o, this.wrapper.append(h);
619
+ const f = document.createElement("div");
620
+ f.className = "p-gui__vector2", f.textContent = o, this.wrapper.append(f);
620
621
  const g = document.createElement("div");
621
- g.className = "p-gui__vector-value", g.textContent = n[s] + ", " + f[c], h.append(g);
622
+ g.className = "p-gui__vector-value", g.textContent = n[s] + ", " + h[c], f.append(g);
622
623
  const u = document.createElement("div");
623
- u.className = "p-gui__vector2-area", h.append(u), u.addEventListener("click", (b) => {
624
- n[s] = parseFloat(this._mapLinear(b.offsetX, 0, u.clientWidth, a, p).toFixed(2)), f[c] = parseFloat(this._mapLinear(b.offsetY, 0, u.clientHeight, i, r).toFixed(2)), t && t(n[s], n[c]);
624
+ u.className = "p-gui__vector2-area", f.append(u), u.addEventListener("click", (b) => {
625
+ n[s] = parseFloat(this._mapLinear(b.offsetX, 0, u.clientWidth, a, p).toFixed(2)), h[c] = parseFloat(this._mapLinear(b.offsetY, 0, u.clientHeight, i, r).toFixed(2)), t && t(n[s], n[c]), this.onUpdate && this.onUpdate();
625
626
  });
626
627
  let m = !1;
627
628
  u.addEventListener("pointerdown", (b) => {
@@ -629,19 +630,19 @@ class x {
629
630
  }), u.addEventListener("pointerup", () => {
630
631
  m = !1;
631
632
  }), u.addEventListener("pointermove", (b) => {
632
- m && (n[s] = parseFloat(this._mapLinear(b.offsetX, 0, u.clientWidth, a, p).toFixed(2)), f[c] = parseFloat(this._mapLinear(b.offsetY, 0, u.clientHeight, i, r).toFixed(2)), t && t(n[s], n[c]));
633
+ m && (n[s] = parseFloat(this._mapLinear(b.offsetX, 0, u.clientWidth, a, p).toFixed(2)), h[c] = parseFloat(this._mapLinear(b.offsetY, 0, u.clientHeight, i, r).toFixed(2)), t && t(n[s], n[c])), this.onUpdate && this.onUpdate();
633
634
  });
634
635
  const v = document.createElement("div");
635
636
  v.className = "p-gui__vector2-line p-gui__vector2-line-x", u.append(v);
636
637
  const w = document.createElement("div");
637
638
  w.className = "p-gui__vector2-line p-gui__vector2-line-y", u.append(w);
638
639
  const _ = document.createElement("div");
639
- _.className = "p-gui__vector2-dot", u.append(_), _.style.left = this._mapLinear(n[s], a, p, 0, u.clientWidth) + "px", _.style.top = this._mapLinear(f[c], r, i, u.clientHeight, 0) + "px", Object.defineProperty(n, s, {
640
+ _.className = "p-gui__vector2-dot", u.append(_), _.style.left = this._mapLinear(n[s], a, p, 0, u.clientWidth) + "px", _.style.top = this._mapLinear(h[c], r, i, u.clientHeight, 0) + "px", Object.defineProperty(n, s, {
640
641
  set: (b) => {
641
- this.propReferences[l] = b, _.style.left = this._mapLinear(b, a, p, 0, u.clientWidth) + "px", g.textContent = String(b) + ", " + f[c];
642
+ this.propReferences[l] = b, _.style.left = this._mapLinear(b, a, p, 0, u.clientWidth) + "px", g.textContent = String(b) + ", " + h[c];
642
643
  },
643
644
  get: () => this.propReferences[l]
644
- }), Object.defineProperty(f, c, {
645
+ }), Object.defineProperty(h, c, {
645
646
  set: (b) => {
646
647
  this.propReferences[d] = b, _.style.top = this._mapLinear(b, r, i, u.clientHeight, 0) + "px", g.textContent = n[s] + ", " + String(b);
647
648
  },
@@ -667,10 +668,10 @@ class x {
667
668
  s.className = "p-gui__color", s.textContent = o, this.wrapper.append(s);
668
669
  const l = document.createElement("input");
669
670
  l.className = "p-gui__color-picker", l.setAttribute("type", "color"), l.value = n, s.append(l), typeof t == "function" && l.addEventListener("input", () => {
670
- a ? r[i] = l.value : typeof t == "function" && t(l.value);
671
+ a ? r[i] = l.value : typeof t == "function" && t(l.value), this.onUpdate && this.onUpdate();
671
672
  }), a && Object.defineProperty(r, i, {
672
- set: (f) => {
673
- this.propReferences[p] = f, l.value = f, typeof t == "function" && t(f);
673
+ set: (h) => {
674
+ this.propReferences[p] = h, l.value = h, typeof t == "function" && t(h);
674
675
  },
675
676
  get: () => this.propReferences[p]
676
677
  });
@@ -409,10 +409,10 @@
409
409
  .p-gui__folder--closed .p-gui__folder-arrow {
410
410
  transform: rotate(0deg);
411
411
  }
412
- `}class b{constructor(e={}){if(e.container?(this.container=typeof e.container=="string"?document.querySelector(e.container):e.container,this.position_type="absolute"):(this.container=document.body,this.position_type="fixed"),this.propReferences=[],this.folders=[],e.isFolder){this._folderConstructor(e.folderOptions);return}this.name=e!=null&&typeof e.name=="string"?e.name:"",this.backgroundColor=e.color||null,this.container==document.body?this.maxHeight=window.innerHeight:this.maxHeight=Math.min(this.container.clientHeight,window.innerHeight),e.maxHeight&&(this.initMaxHeight=e.maxHeight,this.maxHeight=Math.min(this.initMaxHeight,this.maxHeight)),this.screenCorner=this._parseScreenCorner(e.position),this instanceof b&&(typeof b[b.instanceCounter]!="number"?b[b.instanceCounter]=0:b[b.instanceCounter]++),this.instanceId=b[b.instanceCounter],this.wrapperWidth=e.width||290,this.stylesheet=document.createElement("style"),this.stylesheet.setAttribute("type","text/css"),this.stylesheet.setAttribute("id","lm-gui-stylesheet"),document.head.append(this.stylesheet),this.instanceId==0&&this._addStyles(`${v(this.position_type)}`),this._styleInstance(),this._addWrapper(),this.wrapper.setAttribute("data-corner-x",this.screenCorner.x),this.wrapper.setAttribute("data-corner-y",this.screenCorner.y),e.autoRepositioning!=!1&&window.addEventListener("resize",this._handleResize.bind(this)),this._handleResize(),this.hasBeenDragged=!1,e.draggable==!0&&this._makeDraggable(),this.closed=!1,e.closed&&this.toggleClose()}_styleInstance(){let e=this._getScrollbarWidth(this.container);if(this.screenCorner.x=="left"?this.xOffset=0:this.xOffset=this.container.clientWidth-this.wrapperWidth-e,this.instanceId>0){let t=this.container.querySelectorAll(".p-gui");for(let o=0;o<t.length;o++)this.screenCorner.y==t[o].dataset.cornerY&&(this.screenCorner.x=="left"&&t[o].dataset.cornerX=="left"?this.xOffset+=t[o].offsetWidth:this.screenCorner.x=="right"&&t[o].dataset.cornerX=="right"&&(this.xOffset-=t[o].offsetWidth))}this.yOffset=0,this.position={prevX:this.xOffset,prevY:this.yOffset,x:this.xOffset,y:this.yOffset},this._addStyles(`#p-gui-${this.instanceId} {
412
+ `}class b{constructor(e={}){if(e.container?(this.container=typeof e.container=="string"?document.querySelector(e.container):e.container,this.position_type="absolute"):(this.container=document.body,this.position_type="fixed"),typeof e.onUpdate=="function"&&(this.onUpdate=e.onUpdate),this.propReferences=[],this.folders=[],e.isFolder){this._folderConstructor(e.folderOptions);return}this.name=e!=null&&typeof e.name=="string"?e.name:"",this.backgroundColor=e.color||null,this.container==document.body?this.maxHeight=window.innerHeight:this.maxHeight=Math.min(this.container.clientHeight,window.innerHeight),e.maxHeight&&(this.initMaxHeight=e.maxHeight,this.maxHeight=Math.min(this.initMaxHeight,this.maxHeight)),this.screenCorner=this._parseScreenCorner(e.position),this instanceof b&&(typeof b[b.instanceCounter]!="number"?b[b.instanceCounter]=0:b[b.instanceCounter]++),this.instanceId=b[b.instanceCounter],this.wrapperWidth=e.width||290,this.stylesheet=document.createElement("style"),this.stylesheet.setAttribute("type","text/css"),this.stylesheet.setAttribute("id","lm-gui-stylesheet"),document.head.append(this.stylesheet),this.instanceId==0&&this._addStyles(`${v(this.position_type)}`),this._styleInstance(),this._addWrapper(),this.wrapper.setAttribute("data-corner-x",this.screenCorner.x),this.wrapper.setAttribute("data-corner-y",this.screenCorner.y),e.autoRepositioning!=!1&&window.addEventListener("resize",this._handleResize.bind(this)),this._handleResize(),this.hasBeenDragged=!1,e.draggable==!0&&this._makeDraggable(),this.closed=!1,e.closed&&this.toggleClose()}_styleInstance(){let e=this._getScrollbarWidth(this.container);if(this.screenCorner.x=="left"?this.xOffset=0:this.xOffset=this.container.clientWidth-this.wrapperWidth-e,this.instanceId>0){let t=this.container.querySelectorAll(".p-gui");for(let o=0;o<t.length;o++)this.screenCorner.y==t[o].dataset.cornerY&&(this.screenCorner.x=="left"&&t[o].dataset.cornerX=="left"?this.xOffset+=t[o].offsetWidth:this.screenCorner.x=="right"&&t[o].dataset.cornerX=="right"&&(this.xOffset-=t[o].offsetWidth))}this.yOffset=0,this.position={prevX:this.xOffset,prevY:this.yOffset,x:this.xOffset,y:this.yOffset},this._addStyles(`#p-gui-${this.instanceId} {
413
413
  width: ${this.wrapperWidth}px;
414
414
  max-height: ${this.maxHeight}px;
415
415
  transform: translate3d(${this.xOffset}px,${this.yOffset}px,0);
416
416
  ${this.screenCorner.y=="top"?"":"top: auto; bottom: 0;"}
417
417
  ${this.backgroundColor?"background: "+this.backgroundColor+";":""}
418
- }`)}_folderConstructor(e){this.wrapper=e.wrapper}_parseScreenCorner(e){let t={x:"right",y:"top"};return e==null||(typeof e!="string"&&console.error("[perfect-gui] Position must be a string."),e.includes("left")&&(t.x="left"),e.includes("bottom")&&(t.y="bottom")),t}_getScrollbarWidth(e){return e===document.body?window.innerWidth-document.documentElement.clientWidth:e.offsetWidth-e.clientWidth}_handleResize(){if(this.container==document.body?this.maxHeight=window.innerHeight:this.maxHeight=Math.min(this.container.clientHeight,window.innerHeight),this.initMaxHeight&&(this.maxHeight=Math.min(this.initMaxHeight,this.maxHeight)),this.wrapper.style.maxHeight=this.maxHeight+"px",this.hasBeenDragged)return;let e=this._getScrollbarWidth(this.container);if(this.xOffset=this.screenCorner.x=="left"?0:this.container.clientWidth-this.wrapperWidth-e,this.instanceId>0){let t=this.container.querySelectorAll(`.p-gui:not(#${this.wrapper.id}):not([data-dragged])`);for(let o=0;o<t.length&&!(parseInt(t[o].id.replace("p-gui-",""))>this.instanceId);o++)this.screenCorner.y==t[o].dataset.cornerY&&(this.screenCorner.x=="left"&&t[o].dataset.cornerX=="left"?this.xOffset+=t[o].offsetWidth:this.screenCorner.x=="right"&&t[o].dataset.cornerX=="right"&&(this.xOffset-=t[o].offsetWidth))}this.position={prevX:this.xOffset,prevY:this.yOffset,x:this.xOffset,y:this.yOffset},this.wrapper.style.transform=`translate3d(${this.position.x}px, ${this.position.y}px, 0)`}_addStyles(e){this.stylesheet.innerHTML+=e}_addWrapper(){this.wrapper=document.createElement("div"),this.wrapper.id="p-gui-"+this.instanceId,this.wrapper.className="p-gui",this.container.append(this.wrapper),this.header=document.createElement("div"),this.header.className="p-gui__header",this.header.textContent=this.name,this.header.style=`${this.backgroundColor?"border-color: "+this.backgroundColor+";":""}`,this.wrapper.append(this.header);const e=document.createElement("div");e.className="p-gui__header-close",e.addEventListener("click",this.toggleClose.bind(this)),this.header.append(e)}button(e,t){let o="";typeof e!="string"?typeof e=="object"&&(e!=null&&e.hasOwnProperty("name"))?o=e.name==""?" ":e.name:o=" ":o=e==""?" ":e,this.imageContainer=null,typeof t!="function"&&(t=()=>{});const a=document.createElement("div");a.className="p-gui__button",a.textContent=o,a.addEventListener("click",t),this.wrapper.append(a),typeof e.color=="string"&&(a.style.setProperty("--color-accent",e.color),a.style.setProperty("--color-accent-hover",e.hoverColor||e.color))}image(e={},t){if(typeof e!="object")throw Error(`[GUI] image() first parameter must be an object. Received: ${typeof e}.`);let o;if(typeof e.path=="string")o=e.path;else throw typeof e.path==null?Error("[GUI] image() path must be provided."):Error("[GUI] image() path must be a string.");let a=o.replace(/^.*[\\\/]/,""),p;e.name==null?p=a:p=typeof e.name=="string"&&e.name||" ";const r=e.selected===!0,i=e.selectionBorder!==!1;let n="";e.width&&(typeof e.width=="number"&&(e.width+="px"),n+=`flex: 0 0 calc(${e.width} - 5px); `),e.height&&(typeof e.height=="number"&&(e.height+="px"),n+=`height: ${e.height}; `),this.imageContainer||(this.imageContainer=document.createElement("div"),this.imageContainer.className="p-gui__image-container",this.wrapper.append(this.imageContainer));const s=document.createElement("div");s.className="p-gui__image",s.style="background-image: url("+o+"); "+n,this.imageContainer.append(s),r&&i&&s.classList.add("p-gui__image--selected");const l=document.createElement("div");return l.className="p-gui__image-text",l.textContent=p,s.append(l),s.addEventListener("click",()=>{let f=s.parentElement.querySelectorAll(".p-gui__image--selected");for(let c=0;c<f.length;c++)f[c].classList.remove("p-gui__image--selected");i&&s.classList.add("p-gui__image--selected"),typeof t=="function"&&t({path:o,text:p})}),s}slider(e={},t){if(typeof e!="object")throw Error(`[GUI] slider() first parameter must be an object. Received: ${typeof e}.`);let o=typeof e.name=="string"&&e.name||" ",a=!1,p=null,r=e.obj,i=e.prop,n=typeof e.value=="number"?e.value:null,s=e.min??0,l=e.max??1,f=e.step||(l-s)/100;if(n!==null)(i!=null||r!=null)&&console.warn('[GUI] slider() "obj" and "prop" parameters are ignored when a "value" parameter is used.');else if(i!=null&&r!=null){if(typeof i!="string")throw Error(`[GUI] slider() "prop" parameter must be an string. Received: ${typeof i}.`);if(typeof r!="object")throw Error(`[GUI] slider() "obj" parameter must be an object. Received: ${typeof r}.`);o==" "&&(o=i),p=this.propReferences.push(r[i])-1,a=!0}else(i!=null&&r==null||i==null&&r==null)&&console.warn('[GUI] slider() "obj" and "prop" parameters must be used together.'),n=(l-s)/2;this.imageContainer=null;const c=document.createElement("div");c.className="p-gui__slider",c.textContent=o,this.wrapper.append(c);const d=document.createElement("input");d.className="p-gui__slider-ctrl",d.setAttribute("type","range"),d.setAttribute("min",s),d.setAttribute("max",l),d.setAttribute("step",f),d.setAttribute("value",a?r[i]:n),c.append(d);const h=document.createElement("div");h.className="p-gui__slider-value",h.textContent=String(a?r[i]:n),c.append(h),d.addEventListener("input",()=>{h.textContent=d.value,a?r[i]=d.value:typeof t=="function"&&t(parseFloat(d.value))}),a&&Object.defineProperty(r,i,{set:g=>{this.propReferences[p]=g,d.value=g,h.textContent=String(g),typeof t=="function"&&t(parseFloat(d.value))},get:()=>this.propReferences[p]})}toggle(e={},t){if(typeof e!="object")throw Error(`[GUI] toggle() first parameter must be an object. Received: ${typeof e}.`);let o=typeof e.name=="string"&&e.name||" ",a=!1,p=null,r=e.obj,i=e.prop,n=typeof e.value=="boolean"?e.value:null;if(n!==null)(i!=null||r!=null)&&console.warn('[GUI] toggle() "obj" and "prop" parameters are ignored when a "value" parameter is used.');else if(i!=null&&r!=null){if(typeof i!="string")throw Error(`[GUI] toggle() "prop" parameter must be an string. Received: ${typeof i}.`);if(typeof r!="object")throw Error(`[GUI] toggle() "obj" parameter must be an object. Received: ${typeof r}.`);o==" "&&(o=i),p=this.propReferences.push(r[i])-1,a=!0}else(i!=null&&r==null||i==null&&r==null)&&console.warn('[GUI] toggle() "obj" and "prop" parameters must be used together.');this.imageContainer=null;const s=document.createElement("div");s.textContent=o,s.className="p-gui__switch",this.wrapper.append(s),s.addEventListener("click",c=>{const d=c.target.childNodes[1];let h=!0;d.classList.contains("p-gui__switch-checkbox--active")&&(h=!1),d.classList.toggle("p-gui__switch-checkbox--active"),a?r[i]=h:typeof t=="function"&&t(h)});let l=(()=>a?r[i]?" p-gui__switch-checkbox--active":"":n?" p-gui__switch-checkbox--active":"")();const f=document.createElement("div");f.className="p-gui__switch-checkbox"+l,s.append(f),a&&Object.defineProperty(r,i,{set:c=>{this.propReferences[p]=c,c?f.classList.add("p-gui__switch-checkbox--active"):f.classList.remove("p-gui__switch-checkbox--active"),typeof t=="function"&&t(c)},get:()=>this.propReferences[p]})}list(e={},t){if(typeof e!="object")throw Error(`[GUI] list() first parameter must be an object. Received: ${typeof e}.`);let o=typeof e.name=="string"?e.name:" ",a=!1,p=null,r=e.obj,i=e.prop,n=Array.isArray(e.values)?e.values:null,s,l=typeof n[0]!="string";if(t=typeof t=="function"?t:null,e.value!==void 0||e.value===void 0&&r===void 0&&i===void 0)(i!=null||r!=null)&&console.warn('[GUI] list() "obj" and "prop" parameters are ignored when a "value" parameter is used.'),s=(()=>{if(!n)return null;if(typeof e.value=="string")return n.indexOf(e.value);if(typeof e.value=="number")return e.value})();else if(i!=null&&r!=null){if(typeof i!="string")throw Error(`[GUI] list() "prop" parameter must be an string. Received: ${typeof i}.`);if(typeof r!="object")throw Error(`[GUI] list() "obj" parameter must be an object. Received: ${typeof r}.`);s=(()=>{if(!n)return null;if(typeof r[i]=="string")return l?n.find(d=>d.value===r[i]).value:n.indexOf(r[i]);if(typeof r[i]=="number")return l?n.find(d=>d.value===r[i]).value:r[i]})(),p=this.propReferences.push(r[i])-1,a=!0}else(i!=null&&r==null||i==null&&r==null)&&console.warn('[GUI] list() "obj" and "prop" parameters must be used together.');this.imageContainer=null;let f=document.createElement("div");f.className="p-gui__list",f.textContent=o,this.wrapper.append(f);let c=document.createElement("select");f.append(c),c.className="p-gui__list-dropdown",c.addEventListener("change",d=>{a?r[i]=d.target.value:t&&t(d.target.value)}),n&&n.forEach((d,h)=>{const g=l?d.name:d,u=l?d.value:d;let x=document.createElement("option");x.setAttribute("value",u),x.textContent=g,c.append(x),(!l&&s==h||l&&s==u)&&x.setAttribute("selected","")}),a&&Object.defineProperty(r,i,{set:d=>{let h,g,u;l?(u=n.find(w=>w.value==d),g=(u==null?void 0:u.value)||n[0].value,h=n.indexOf(u)):(typeof d=="string"&&(h=n.indexOf(d),g=d),typeof d=="number"&&(h=d,g=n[d])),this.propReferences[p]=l?g:d;const x=c.querySelector("[selected]");x&&x.removeAttribute("selected"),c.querySelectorAll("option")[h].setAttribute("selected",""),typeof t=="function"&&t(l?u:g,h)},get:()=>this.propReferences[p]})}vector2(e={},t){if(typeof e!="object")throw Error(`[GUI] vector2() first parameter must be an object. Received: ${typeof e}.`);let o=typeof e.name=="string"&&e.name||" ";const a=e.x.min??0,p=e.x.max??1,r=e.y.min??0,i=e.y.max??1,n=e.x.obj,s=e.x.prop,l=this.propReferences.push(n[s])-1,f=e.y.obj,c=e.y.prop,d=this.propReferences.push(f[c])-1;t=typeof t=="function"?t:null,this.imageContainer=null;const h=document.createElement("div");h.className="p-gui__vector2",h.textContent=o,this.wrapper.append(h);const g=document.createElement("div");g.className="p-gui__vector-value",g.textContent=n[s]+", "+f[c],h.append(g);const u=document.createElement("div");u.className="p-gui__vector2-area",h.append(u),u.addEventListener("click",m=>{n[s]=parseFloat(this._mapLinear(m.offsetX,0,u.clientWidth,a,p).toFixed(2)),f[c]=parseFloat(this._mapLinear(m.offsetY,0,u.clientHeight,i,r).toFixed(2)),t&&t(n[s],n[c])});let x=!1;u.addEventListener("pointerdown",m=>{x=!0}),u.addEventListener("pointerup",()=>{x=!1}),u.addEventListener("pointermove",m=>{x&&(n[s]=parseFloat(this._mapLinear(m.offsetX,0,u.clientWidth,a,p).toFixed(2)),f[c]=parseFloat(this._mapLinear(m.offsetY,0,u.clientHeight,i,r).toFixed(2)),t&&t(n[s],n[c]))});const w=document.createElement("div");w.className="p-gui__vector2-line p-gui__vector2-line-x",u.append(w);const y=document.createElement("div");y.className="p-gui__vector2-line p-gui__vector2-line-y",u.append(y);const _=document.createElement("div");_.className="p-gui__vector2-dot",u.append(_),_.style.left=this._mapLinear(n[s],a,p,0,u.clientWidth)+"px",_.style.top=this._mapLinear(f[c],r,i,u.clientHeight,0)+"px",Object.defineProperty(n,s,{set:m=>{this.propReferences[l]=m,_.style.left=this._mapLinear(m,a,p,0,u.clientWidth)+"px",g.textContent=String(m)+", "+f[c]},get:()=>this.propReferences[l]}),Object.defineProperty(f,c,{set:m=>{this.propReferences[d]=m,_.style.top=this._mapLinear(m,r,i,u.clientHeight,0)+"px",g.textContent=n[s]+", "+String(m)},get:()=>this.propReferences[d]})}color(e={},t){if(typeof e!="object")throw Error(`[GUI] color() first parameter must be an object. Received: ${typeof e}.`);let o=typeof e.name=="string"&&e.name||" ",a=!1,p=null,r=e.obj,i=e.prop,n;if(typeof e.value=="string"&&(e.value.length!=7||e.value[0]!="#"?console.error(`[GUI] color() 'value' parameter must be an hexadecimal string in the format "#ffffff". Received: "${e.value}".`):n=e.value),n||(n="#000000"),e.value!==void 0)(i!=null||r!=null)&&console.warn('[GUI] color() "obj" and "prop" parameters are ignored when a "value" parameter is used.');else if(i!=null&&r!=null){if(typeof i!="string")throw Error(`[GUI] color() "prop" parameter must be an string. Received: ${typeof i}.`);if(typeof r!="object")throw Error(`[GUI] color() "obj" parameter must be an object. Received: ${typeof r}.`);o==" "&&(o=i),p=this.propReferences.push(r[i])-1,a=!0}else(i!=null&&r==null||i==null&&r==null)&&console.warn('[GUI] color() "obj" and "prop" parameters must be used together.');this.imageContainer=null;const s=document.createElement("div");s.className="p-gui__color",s.textContent=o,this.wrapper.append(s);const l=document.createElement("input");l.className="p-gui__color-picker",l.setAttribute("type","color"),l.value=n,s.append(l),typeof t=="function"&&l.addEventListener("input",()=>{a?r[i]=l.value:typeof t=="function"&&t(l.value)}),a&&Object.defineProperty(r,i,{set:f=>{this.propReferences[p]=f,l.value=f,typeof t=="function"&&t(f)},get:()=>this.propReferences[p]})}folder(e={}){let t=typeof e.closed=="boolean"?e.closed:!1,o=e.name||"",a=e.color||null,p=e.maxHeight||null;this.imageContainer=null;let r="p-gui__folder";this.folders.length==0&&(r+=" p-gui__folder--first"),t&&(r+=" p-gui__folder--closed");let i=a?`background-color: ${a};`:"";i+=p?`max-height: ${p}px;`:"";const n=document.createElement("div");n.className=r,n.style=i,this.wrapper.append(n);const s=document.createElement("div");s.innerHTML=`<span class="p-gui__folder-arrow"></span>${o}`,s.className="p-gui__folder-header",n.append(s),s.addEventListener("click",()=>{n.classList.toggle("p-gui__folder--closed")});let l=new b({isFolder:!0,folderOptions:{wrapper:n}});return this.folders.push(l),l}_makeDraggable(){var e=this;this.header.addEventListener("pointerdown",t),this.header.addEventListener("pointerup",a);function t(p){p.preventDefault(),e.position.initX=e.position.x,e.position.initY=e.position.y,e.position.prevX=p.clientX,e.position.prevY=p.clientY,document.addEventListener("pointermove",o)}function o(p){p.preventDefault(),e.hasBeenDragged||(e.hasBeenDragged=!0,e.wrapper.setAttribute("data-dragged","true")),e.position.x=e.position.initX+p.clientX-e.position.prevX,e.position.y=e.position.initY+p.clientY-e.position.prevY,e.wrapper.style.transform="translate3d("+e.position.x+"px,"+e.position.y+"px,0)"}function a(p){document.removeEventListener("pointermove",o)}}toggleClose(){this.closed=!this.closed,this.wrapper.classList.toggle("p-gui--collapsed")}kill(){this.wrapper.remove()}_mapLinear(e,t,o,a,p){return a+(e-t)*(p-a)/(o-t)}}return b});
418
+ }`)}_folderConstructor(e){this.wrapper=e.wrapper}_parseScreenCorner(e){let t={x:"right",y:"top"};return e==null||(typeof e!="string"&&console.error("[perfect-gui] Position must be a string."),e.includes("left")&&(t.x="left"),e.includes("bottom")&&(t.y="bottom")),t}_getScrollbarWidth(e){return e===document.body?window.innerWidth-document.documentElement.clientWidth:e.offsetWidth-e.clientWidth}_handleResize(){if(this.container==document.body?this.maxHeight=window.innerHeight:this.maxHeight=Math.min(this.container.clientHeight,window.innerHeight),this.initMaxHeight&&(this.maxHeight=Math.min(this.initMaxHeight,this.maxHeight)),this.wrapper.style.maxHeight=this.maxHeight+"px",this.hasBeenDragged)return;let e=this._getScrollbarWidth(this.container);if(this.xOffset=this.screenCorner.x=="left"?0:this.container.clientWidth-this.wrapperWidth-e,this.instanceId>0){let t=this.container.querySelectorAll(`.p-gui:not(#${this.wrapper.id}):not([data-dragged])`);for(let o=0;o<t.length&&!(parseInt(t[o].id.replace("p-gui-",""))>this.instanceId);o++)this.screenCorner.y==t[o].dataset.cornerY&&(this.screenCorner.x=="left"&&t[o].dataset.cornerX=="left"?this.xOffset+=t[o].offsetWidth:this.screenCorner.x=="right"&&t[o].dataset.cornerX=="right"&&(this.xOffset-=t[o].offsetWidth))}this.position={prevX:this.xOffset,prevY:this.yOffset,x:this.xOffset,y:this.yOffset},this.wrapper.style.transform=`translate3d(${this.position.x}px, ${this.position.y}px, 0)`}_addStyles(e){this.stylesheet.innerHTML+=e}_addWrapper(){this.wrapper=document.createElement("div"),this.wrapper.id="p-gui-"+this.instanceId,this.wrapper.className="p-gui",this.container.append(this.wrapper),this.header=document.createElement("div"),this.header.className="p-gui__header",this.header.textContent=this.name,this.header.style=`${this.backgroundColor?"border-color: "+this.backgroundColor+";":""}`,this.wrapper.append(this.header);const e=document.createElement("div");e.className="p-gui__header-close",e.addEventListener("click",this.toggleClose.bind(this)),this.header.append(e)}button(e,t){let o="";typeof e!="string"?typeof e=="object"&&(e!=null&&e.hasOwnProperty("name"))?o=e.name==""?" ":e.name:o=" ":o=e==""?" ":e,this.imageContainer=null;const a=document.createElement("div");a.className="p-gui__button",a.textContent=o,a.addEventListener("click",()=>{this.onUpdate&&this.onUpdate(),t&&t()}),this.wrapper.append(a),typeof e.color=="string"&&(a.style.setProperty("--color-accent",e.color),a.style.setProperty("--color-accent-hover",e.hoverColor||e.color))}image(e={},t){if(typeof e!="object")throw Error(`[GUI] image() first parameter must be an object. Received: ${typeof e}.`);let o;if(typeof e.path=="string")o=e.path;else throw typeof e.path==null?Error("[GUI] image() path must be provided."):Error("[GUI] image() path must be a string.");let a=o.replace(/^.*[\\\/]/,""),p;e.name==null?p=a:p=typeof e.name=="string"&&e.name||" ";const r=e.selected===!0,i=e.selectionBorder!==!1;let n="";e.width&&(typeof e.width=="number"&&(e.width+="px"),n+=`flex: 0 0 calc(${e.width} - 5px); `),e.height&&(typeof e.height=="number"&&(e.height+="px"),n+=`height: ${e.height}; `),this.imageContainer||(this.imageContainer=document.createElement("div"),this.imageContainer.className="p-gui__image-container",this.wrapper.append(this.imageContainer));const s=document.createElement("div");s.className="p-gui__image",s.style="background-image: url("+o+"); "+n,this.imageContainer.append(s),r&&i&&s.classList.add("p-gui__image--selected");const l=document.createElement("div");return l.className="p-gui__image-text",l.textContent=p,s.append(l),s.addEventListener("click",()=>{let f=s.parentElement.querySelectorAll(".p-gui__image--selected");for(let c=0;c<f.length;c++)f[c].classList.remove("p-gui__image--selected");i&&s.classList.add("p-gui__image--selected"),typeof t=="function"&&t({path:o,text:p}),this.onUpdate&&this.onUpdate()}),s}slider(e={},t){if(typeof e!="object")throw Error(`[GUI] slider() first parameter must be an object. Received: ${typeof e}.`);let o=typeof e.name=="string"&&e.name||" ",a=!1,p=null,r=e.obj,i=e.prop,n=typeof e.value=="number"?e.value:null,s=e.min??0,l=e.max??1,f=e.step||(l-s)/100;if(n!==null)(i!=null||r!=null)&&console.warn('[GUI] slider() "obj" and "prop" parameters are ignored when a "value" parameter is used.');else if(i!=null&&r!=null){if(typeof i!="string")throw Error(`[GUI] slider() "prop" parameter must be an string. Received: ${typeof i}.`);if(typeof r!="object")throw Error(`[GUI] slider() "obj" parameter must be an object. Received: ${typeof r}.`);o==" "&&(o=i),p=this.propReferences.push(r[i])-1,a=!0}else(i!=null&&r==null||i==null&&r==null)&&console.warn('[GUI] slider() "obj" and "prop" parameters must be used together.'),n=(l-s)/2;this.imageContainer=null;const c=document.createElement("div");c.className="p-gui__slider",c.textContent=o,this.wrapper.append(c);const d=document.createElement("input");d.className="p-gui__slider-ctrl",d.setAttribute("type","range"),d.setAttribute("min",s),d.setAttribute("max",l),d.setAttribute("step",f),d.setAttribute("value",a?r[i]:n),c.append(d);const h=document.createElement("div");h.className="p-gui__slider-value",h.textContent=String(a?r[i]:n),c.append(h),d.addEventListener("input",()=>{h.textContent=d.value,a?r[i]=parseFloat(d.value):typeof t=="function"&&t(parseFloat(d.value)),this.onUpdate&&this.onUpdate()}),a&&Object.defineProperty(r,i,{set:g=>{this.propReferences[p]=g,d.value=g,h.textContent=String(g),typeof t=="function"&&t(parseFloat(d.value))},get:()=>this.propReferences[p]})}toggle(e={},t){if(typeof e!="object")throw Error(`[GUI] toggle() first parameter must be an object. Received: ${typeof e}.`);let o=typeof e.name=="string"&&e.name||" ",a=!1,p=null,r=e.obj,i=e.prop,n=typeof e.value=="boolean"?e.value:null;if(n!==null)(i!=null||r!=null)&&console.warn('[GUI] toggle() "obj" and "prop" parameters are ignored when a "value" parameter is used.');else if(i!=null&&r!=null){if(typeof i!="string")throw Error(`[GUI] toggle() "prop" parameter must be an string. Received: ${typeof i}.`);if(typeof r!="object")throw Error(`[GUI] toggle() "obj" parameter must be an object. Received: ${typeof r}.`);o==" "&&(o=i),p=this.propReferences.push(r[i])-1,a=!0}else(i!=null&&r==null||i==null&&r==null)&&console.warn('[GUI] toggle() "obj" and "prop" parameters must be used together.');this.imageContainer=null;const s=document.createElement("div");s.textContent=o,s.className="p-gui__switch",this.wrapper.append(s),s.addEventListener("click",c=>{const d=c.target.childNodes[1];let h=!0;d.classList.contains("p-gui__switch-checkbox--active")&&(h=!1),d.classList.toggle("p-gui__switch-checkbox--active"),a?r[i]=h:typeof t=="function"&&t(h),this.onUpdate&&this.onUpdate()});let l=(()=>a?r[i]?" p-gui__switch-checkbox--active":"":n?" p-gui__switch-checkbox--active":"")();const f=document.createElement("div");f.className="p-gui__switch-checkbox"+l,s.append(f),a&&Object.defineProperty(r,i,{set:c=>{this.propReferences[p]=c,c?f.classList.add("p-gui__switch-checkbox--active"):f.classList.remove("p-gui__switch-checkbox--active"),typeof t=="function"&&t(c)},get:()=>this.propReferences[p]})}list(e={},t){if(typeof e!="object")throw Error(`[GUI] list() first parameter must be an object. Received: ${typeof e}.`);let o=typeof e.name=="string"?e.name:" ",a=!1,p=null,r=e.obj,i=e.prop,n=Array.isArray(e.values)?e.values:null,s,l=typeof n[0]!="string";if(t=typeof t=="function"?t:null,e.value!==void 0||e.value===void 0&&r===void 0&&i===void 0)(i!=null||r!=null)&&console.warn('[GUI] list() "obj" and "prop" parameters are ignored when a "value" parameter is used.'),s=(()=>{if(!n)return null;if(typeof e.value=="string")return n.indexOf(e.value);if(typeof e.value=="number")return e.value})();else if(i!=null&&r!=null){if(typeof i!="string")throw Error(`[GUI] list() "prop" parameter must be an string. Received: ${typeof i}.`);if(typeof r!="object")throw Error(`[GUI] list() "obj" parameter must be an object. Received: ${typeof r}.`);s=(()=>{if(!n)return null;if(typeof r[i]=="string")return l?n.find(d=>d.value===r[i]).value:n.indexOf(r[i]);if(typeof r[i]=="number")return l?n.find(d=>d.value===r[i]).value:r[i]})(),p=this.propReferences.push(r[i])-1,a=!0}else(i!=null&&r==null||i==null&&r==null)&&console.warn('[GUI] list() "obj" and "prop" parameters must be used together.');this.imageContainer=null;let f=document.createElement("div");f.className="p-gui__list",f.textContent=o,this.wrapper.append(f);let c=document.createElement("select");f.append(c),c.className="p-gui__list-dropdown",c.addEventListener("change",d=>{a?r[i]=d.target.value:t&&t(d.target.value),this.onUpdate&&this.onUpdate()}),n&&n.forEach((d,h)=>{const g=l?d.name:d,u=l?d.value:d;let x=document.createElement("option");x.setAttribute("value",u),x.textContent=g,c.append(x),(!l&&s==h||l&&s==u)&&x.setAttribute("selected","")}),a&&Object.defineProperty(r,i,{set:d=>{let h,g,u;l?(u=n.find(w=>w.value==d),g=(u==null?void 0:u.value)||n[0].value,h=n.indexOf(u)):(typeof d=="string"&&(h=n.indexOf(d),g=d),typeof d=="number"&&(h=d,g=n[d])),this.propReferences[p]=l?g:d;const x=c.querySelector("[selected]");x&&x.removeAttribute("selected"),c.querySelectorAll("option")[h].setAttribute("selected",""),typeof t=="function"&&t(l?u:g,h)},get:()=>this.propReferences[p]})}vector2(e={},t){if(typeof e!="object")throw Error(`[GUI] vector2() first parameter must be an object. Received: ${typeof e}.`);let o=typeof e.name=="string"&&e.name||" ";const a=e.x.min??0,p=e.x.max??1,r=e.y.min??0,i=e.y.max??1,n=e.x.obj,s=e.x.prop,l=this.propReferences.push(n[s])-1,f=e.y.obj,c=e.y.prop,d=this.propReferences.push(f[c])-1;t=typeof t=="function"?t:null,this.imageContainer=null;const h=document.createElement("div");h.className="p-gui__vector2",h.textContent=o,this.wrapper.append(h);const g=document.createElement("div");g.className="p-gui__vector-value",g.textContent=n[s]+", "+f[c],h.append(g);const u=document.createElement("div");u.className="p-gui__vector2-area",h.append(u),u.addEventListener("click",m=>{n[s]=parseFloat(this._mapLinear(m.offsetX,0,u.clientWidth,a,p).toFixed(2)),f[c]=parseFloat(this._mapLinear(m.offsetY,0,u.clientHeight,i,r).toFixed(2)),t&&t(n[s],n[c]),this.onUpdate&&this.onUpdate()});let x=!1;u.addEventListener("pointerdown",m=>{x=!0}),u.addEventListener("pointerup",()=>{x=!1}),u.addEventListener("pointermove",m=>{x&&(n[s]=parseFloat(this._mapLinear(m.offsetX,0,u.clientWidth,a,p).toFixed(2)),f[c]=parseFloat(this._mapLinear(m.offsetY,0,u.clientHeight,i,r).toFixed(2)),t&&t(n[s],n[c])),this.onUpdate&&this.onUpdate()});const w=document.createElement("div");w.className="p-gui__vector2-line p-gui__vector2-line-x",u.append(w);const y=document.createElement("div");y.className="p-gui__vector2-line p-gui__vector2-line-y",u.append(y);const _=document.createElement("div");_.className="p-gui__vector2-dot",u.append(_),_.style.left=this._mapLinear(n[s],a,p,0,u.clientWidth)+"px",_.style.top=this._mapLinear(f[c],r,i,u.clientHeight,0)+"px",Object.defineProperty(n,s,{set:m=>{this.propReferences[l]=m,_.style.left=this._mapLinear(m,a,p,0,u.clientWidth)+"px",g.textContent=String(m)+", "+f[c]},get:()=>this.propReferences[l]}),Object.defineProperty(f,c,{set:m=>{this.propReferences[d]=m,_.style.top=this._mapLinear(m,r,i,u.clientHeight,0)+"px",g.textContent=n[s]+", "+String(m)},get:()=>this.propReferences[d]})}color(e={},t){if(typeof e!="object")throw Error(`[GUI] color() first parameter must be an object. Received: ${typeof e}.`);let o=typeof e.name=="string"&&e.name||" ",a=!1,p=null,r=e.obj,i=e.prop,n;if(typeof e.value=="string"&&(e.value.length!=7||e.value[0]!="#"?console.error(`[GUI] color() 'value' parameter must be an hexadecimal string in the format "#ffffff". Received: "${e.value}".`):n=e.value),n||(n="#000000"),e.value!==void 0)(i!=null||r!=null)&&console.warn('[GUI] color() "obj" and "prop" parameters are ignored when a "value" parameter is used.');else if(i!=null&&r!=null){if(typeof i!="string")throw Error(`[GUI] color() "prop" parameter must be an string. Received: ${typeof i}.`);if(typeof r!="object")throw Error(`[GUI] color() "obj" parameter must be an object. Received: ${typeof r}.`);o==" "&&(o=i),p=this.propReferences.push(r[i])-1,a=!0}else(i!=null&&r==null||i==null&&r==null)&&console.warn('[GUI] color() "obj" and "prop" parameters must be used together.');this.imageContainer=null;const s=document.createElement("div");s.className="p-gui__color",s.textContent=o,this.wrapper.append(s);const l=document.createElement("input");l.className="p-gui__color-picker",l.setAttribute("type","color"),l.value=n,s.append(l),typeof t=="function"&&l.addEventListener("input",()=>{a?r[i]=l.value:typeof t=="function"&&t(l.value),this.onUpdate&&this.onUpdate()}),a&&Object.defineProperty(r,i,{set:f=>{this.propReferences[p]=f,l.value=f,typeof t=="function"&&t(f)},get:()=>this.propReferences[p]})}folder(e={}){let t=typeof e.closed=="boolean"?e.closed:!1,o=e.name||"",a=e.color||null,p=e.maxHeight||null;this.imageContainer=null;let r="p-gui__folder";this.folders.length==0&&(r+=" p-gui__folder--first"),t&&(r+=" p-gui__folder--closed");let i=a?`background-color: ${a};`:"";i+=p?`max-height: ${p}px;`:"";const n=document.createElement("div");n.className=r,n.style=i,this.wrapper.append(n);const s=document.createElement("div");s.innerHTML=`<span class="p-gui__folder-arrow"></span>${o}`,s.className="p-gui__folder-header",n.append(s),s.addEventListener("click",()=>{n.classList.toggle("p-gui__folder--closed")});let l=new b({isFolder:!0,folderOptions:{wrapper:n}});return this.folders.push(l),l}_makeDraggable(){var e=this;this.header.addEventListener("pointerdown",t),this.header.addEventListener("pointerup",a);function t(p){p.preventDefault(),e.position.initX=e.position.x,e.position.initY=e.position.y,e.position.prevX=p.clientX,e.position.prevY=p.clientY,document.addEventListener("pointermove",o)}function o(p){p.preventDefault(),e.hasBeenDragged||(e.hasBeenDragged=!0,e.wrapper.setAttribute("data-dragged","true")),e.position.x=e.position.initX+p.clientX-e.position.prevX,e.position.y=e.position.initY+p.clientY-e.position.prevY,e.wrapper.style.transform="translate3d("+e.position.x+"px,"+e.position.y+"px,0)"}function a(p){document.removeEventListener("pointermove",o)}}toggleClose(){this.closed=!this.closed,this.wrapper.classList.toggle("p-gui--collapsed")}kill(){this.wrapper.remove()}_mapLinear(e,t,o,a,p){return a+(e-t)*(p-a)/(o-t)}}return b});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "perfect-gui",
3
- "version": "4.8.2",
3
+ "version": "4.9.0",
4
4
  "description": "GUI for JavaScript",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/src/index.js CHANGED
@@ -11,6 +11,10 @@ export default class GUI {
11
11
  this.position_type = 'fixed';
12
12
  }
13
13
 
14
+ if ( typeof options.onUpdate == 'function' ) {
15
+ this.onUpdate = options.onUpdate;
16
+ }
17
+
14
18
  this.propReferences = [];
15
19
  this.folders = [];
16
20
 
@@ -208,15 +212,18 @@ export default class GUI {
208
212
  }
209
213
 
210
214
  this.imageContainer = null;
211
-
212
- if (typeof callback != 'function') {
213
- callback = () => {};
214
- }
215
215
 
216
216
  const el = document.createElement('div');
217
217
  el.className = 'p-gui__button';
218
218
  el.textContent = name;
219
- el.addEventListener('click', callback);
219
+ el.addEventListener('click', () => {
220
+ if (this.onUpdate) {
221
+ this.onUpdate();
222
+ }
223
+ if (callback) {
224
+ callback();
225
+ }
226
+ });
220
227
  this.wrapper.append(el);
221
228
 
222
229
  if (typeof options.color == 'string') {
@@ -300,6 +307,9 @@ export default class GUI {
300
307
  if (typeof callback == 'function') {
301
308
  callback({ path, text: name });
302
309
  }
310
+ if (this.onUpdate) {
311
+ this.onUpdate();
312
+ }
303
313
  });
304
314
 
305
315
  return image;
@@ -375,13 +385,17 @@ export default class GUI {
375
385
  slider_value.textContent = slider_ctrl.value;
376
386
 
377
387
  if ( isObject ) {
378
- obj[prop] = slider_ctrl.value;
388
+ obj[prop] = parseFloat(slider_ctrl.value);
379
389
  }
380
390
  else {
381
391
  if (typeof callback == "function") {
382
392
  callback(parseFloat(slider_ctrl.value));
383
393
  }
384
394
  }
395
+
396
+ if (this.onUpdate) {
397
+ this.onUpdate();
398
+ }
385
399
  });
386
400
 
387
401
  if ( isObject ) {
@@ -470,6 +484,10 @@ export default class GUI {
470
484
  callback(value);
471
485
  }
472
486
  }
487
+
488
+ if (this.onUpdate) {
489
+ this.onUpdate();
490
+ }
473
491
  });
474
492
 
475
493
  let activeClass = (() => {
@@ -601,6 +619,10 @@ export default class GUI {
601
619
  else if (callback) {
602
620
  callback(ev.target.value);
603
621
  }
622
+
623
+ if (this.onUpdate) {
624
+ this.onUpdate();
625
+ }
604
626
  });
605
627
 
606
628
  if (values)
@@ -708,6 +730,10 @@ export default class GUI {
708
730
  if (callback) {
709
731
  callback(objectX[propX], objectX[propY]);
710
732
  }
733
+
734
+ if (this.onUpdate) {
735
+ this.onUpdate();
736
+ }
711
737
  });
712
738
 
713
739
  let pointer_is_down = false;
@@ -726,6 +752,10 @@ export default class GUI {
726
752
  callback(objectX[propX], objectX[propY]);
727
753
  }
728
754
  }
755
+
756
+ if (this.onUpdate) {
757
+ this.onUpdate();
758
+ }
729
759
  });
730
760
 
731
761
  const line_x = document.createElement('div');
@@ -840,6 +870,10 @@ export default class GUI {
840
870
  else if (typeof callback == 'function') {
841
871
  callback(colorpicker.value);
842
872
  }
873
+
874
+ if (this.onUpdate) {
875
+ this.onUpdate();
876
+ }
843
877
  });
844
878
  }
845
879