From 067964435fbe41aa7421855da864eff95e232524 Mon Sep 17 00:00:00 2001 From: Gregg Tavares Date: Tue, 31 Oct 2023 22:49:33 +0900 Subject: [PATCH] add theme --- dist/0.x/muigui.js | 67 ++++++++++++++++-------------- dist/0.x/muigui.min.js | 2 +- dist/0.x/muigui.module.js | 67 ++++++++++++++++-------------- dist/0.x/muigui.module.min.js | 2 +- src/controllers/ValueController.js | 22 ++++++---- src/libs/utils.js | 43 +++++++++---------- 6 files changed, 108 insertions(+), 95 deletions(-) diff --git a/dist/0.x/muigui.js b/dist/0.x/muigui.js index f4d2fe8..7616b09 100644 --- a/dist/0.x/muigui.js +++ b/dist/0.x/muigui.js @@ -867,30 +867,27 @@ const { min, max } = options; const guiMinRange = options.minRange || 0; const valueMinRange = from(guiMinRange)[1]; - console.log('guiMinRange', guiMinRange); - console.log('valueMinRange', valueMinRange); - return [ - gui - .add(properties, minPropName, { - ...options, - min, - max: max - guiMinRange, - }) - .listen() - .onChange(v => { - properties[maxPropName] = Math.min(max, Math.max(v + valueMinRange, properties[maxPropName])); - }), - gui - .add(properties, maxPropName, { - ...options, - min: min + guiMinRange, - max, - }) - .listen() - .onChange(v => { - properties[minPropName] = Math.max(min, Math.min(v - valueMinRange, properties[minPropName])); - }), - ]; + const minGui = gui + .add(properties, minPropName, { + ...options, + min, + max: max - guiMinRange, + }) + // .listen() + .onChange(v => { + maxGui.setValue(Math.min(max, Math.max(v + valueMinRange, properties[maxPropName]))); + }); + const maxGui = gui + .add(properties, maxPropName, { + ...options, + min: min + guiMinRange, + max, + }) + // .listen() + .onChange(v => { + minGui.setValue(Math.max(min, Math.min(v - valueMinRange, properties[minPropName]))); + }); + return [ minGui, maxGui ]; } class View { @@ -1358,31 +1355,39 @@ return view; } #setValueImpl(v, ignoreCache) { + let isDifferent = false; if (typeof v === 'object') { const dst = this.#object[this.#property]; // don't replace objects, just their values. - if (Array.isArray(v)) { + if (Array.isArray(v) || isTypedArray(v)) { for (let i = 0; i < v.length; ++i) { + isDifferent ||= dst[i] !== v[i]; dst[i] = v[i]; } - } else if (isTypedArray(v)) { - dst.set(v); } else { + for (const key of Object.keys(v)) { + isDifferent ||= dst[key] !== v[key]; + } Object.assign(dst, v); } } else { + isDifferent = this.#object[this.#property] !== v; this.#object[this.#property] = v; } this.updateDisplay(ignoreCache); - this.emitChange(this.getValue(), this.#object, this.#property); - return this; + if (isDifferent) { + this.emitChange(this.getValue(), this.#object, this.#property); + } + return isDifferent; } setValue(v) { this.#setValueImpl(v); } setFinalValue(v) { - this.#setValueImpl(v, true); - this.emitFinalChange(this.getValue(), this.#object, this.#property); + const isDifferent = this.#setValueImpl(v, true); + if (isDifferent) { + this.emitFinalChange(this.getValue(), this.#object, this.#property); + } return this; } updateDisplay(ignoreCache) { diff --git a/dist/0.x/muigui.min.js b/dist/0.x/muigui.min.js index e6f7d7b..e2fe7b7 100644 --- a/dist/0.x/muigui.min.js +++ b/dist/0.x/muigui.min.js @@ -1 +1 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).GUI=e()}(this,(function(){"use strict";var t={default:'\n.muigui {\n --bg-color: #ddd;\n --color: #222;\n --contrast-color: #eee;\n --value-color: #145 ;\n --value-bg-color: #eeee;\n --disabled-color: #999;\n --menu-bg-color: #f8f8f8;\n --menu-sep-color: #bbb;\n --hover-bg-color: #999;\n --focus-color: #68C;\n --range-color: #888888;\n --invalid-color: #FF0000;\n --selected-color: rgb(255, 255, 255, 0.9);\n\n --button-bg-color: var(--value-bg-color);\n\n --range-left-color: var(--value-color);\n --range-right-color: var(--value-bg-color); \n --range-right-hover-color: var(--hover-bg-color);\n\n color: var(--color);\n background-color: var(--bg-color);\n}\n\n@media (prefers-color-scheme: dark) {\n .muigui {\n --bg-color: #222222;\n --color: #dddddd;\n --contrast-color: #000;\n --value-color: #43e5f7;\n --value-bg-color: #444444;\n --disabled-color: #666666;\n --menu-bg-color: #080808;\n --menu-sep-color: #444444;\n --hover-bg-color: #666666;\n --focus-color: #88AAFF;\n --range-color: #888888;\n --invalid-color: #FF6666;\n --selected-color: rgba(255, 255, 255, 0.3);\n\n --button-bg-color: var(--value-bg-color);\n\n --range-left-color: var(--value-color);\n --range-right-color: var(--value-bg-color); \n --range-right-hover-color: var(--hover-bg-color);\n\n color: var(--color);\n background-color: var(--bg-color);\n }\n}\n\n.muigui {\n --width: 250px;\n --label-width: 45%;\n --number-width: 40%;\n\n\n --font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;\n --font-size: 11px;\n --font-family-mono: Menlo, Monaco, Consolas, "Droid Sans Mono", monospace;\n --font-size-mono: 11px;\n\n --line-height: 1.7em;\n --border-radius: 0px;\n\n width: var(--width);\n font-family: var(--font-family);\n font-size: var(--font-size);\n box-sizing: border-box;\n line-height: 100%;\n}\n.muigui * {\n box-sizing: inherit;\n}\n\n.muigui-no-scroll {\n touch-action: none;\n}\n.muigui-no-h-scroll {\n touch-action: pan-y;\n}\n.muigui-no-v-scroll {\n touch-action: pan-x;\n}\n\n.muigui-invalid-value {\n background-color: red !important;\n color: white !important;\n}\n\n.muigui-grid {\n display: grid;\n}\n.muigui-rows {\n display: flex;\n flex-direction: column;\n\n min-height: 20px;\n border: 2px solid red;\n}\n.muigui-columns {\n display: flex;\n flex-direction: row;\n\n height: 20px;\n border: 2px solid green;\n}\n.muigui-rows>*,\n.muigui-columns>* {\n flex: 1 1 auto;\n align-items: stretch;\n min-height: 0;\n min-width: 0;\n}\n\n.muigui-row {\n border: 2px solid yellow;\n min-height: 10px\n}\n.muigui-column {\n border: 2px solid lightgreen;\n}\n\n/* -------- */\n\n.muigui-show { /* */ }\n.muigui-hide { \n display: none !important;\n}\n.muigui-disabled {\n pointer-events: none;\n --color: var(--disabled-color) !important;\n --value-color: var(--disabled-color) !important;\n --range-left-color: var(--disabled-color) !important;\n}\n\n.muigui canvas,\n.muigui svg {\n display: block;\n border-radius: var(--border-radius);\n}\n.muigui canvas {\n background-color: var(--value-bg-color);\n}\n\n.muigui-controller {\n min-width: 0;\n min-height: var(--line-height);\n}\n.muigui-root,\n.muigui-menu {\n display: flex;\n flex-direction: column;\n position: relative;\n user-select: none;\n height: fit-content;\n margin: 0;\n padding-bottom: 0.1em;\n border-radius: var(--border-radius);\n}\n.muigui-menu {\n border-bottom: 1px solid var(--menu-sep-color);\n}\n\n.muigui-root>button:nth-child(1),\n.muigui-menu>button:nth-child(1) {\n border-top: 1px solid var(--menu-sep-color);\n border-bottom: 1px solid var(--menu-sep-color);\n position: relative;\n text-align: left;\n color: var(--color);\n background-color: var(--menu-bg-color);\n min-height: var(--line-height);\n padding-top: 0.2em;\n padding-bottom: 0.2em;\n cursor: pointer;\n border-radius: var(--border-radius);\n}\n.muigui-root>div:nth-child(2),\n.muigui-menu>div:nth-child(2) {\n flex: 1 1 auto;\n}\n\n.muigui-controller {\n margin-left: 0.2em;\n margin-right: 0.2em;\n}\n.muigui-root.muigui-controller,\n.muigui-menu.muigui-controller {\n margin-left: 0;\n margin-right: 0;\n}\n.muigui-controller>*:nth-child(1) {\n flex: 1 0 var(--label-width);\n min-width: 0;\n white-space: pre;\n}\n.muigui-controller>label:nth-child(1) {\n place-content: center start;\n display: inline-grid;\n overflow: hidden;\n}\n.muigui-controller>*:nth-child(2) {\n flex: 1 1 75%;\n min-width: 0;\n}\n\n/* -----------------------------------------\n a label controller is [[label][value]]\n*/\n\n.muigui-label-controller {\n display: flex;\n margin: 0.4em 0 0.4em 0;\n word-wrap: initial;\n align-items: stretch;\n}\n\n.muigui-value {\n display: flex;\n align-items: stretch;\n}\n.muigui-value>* {\n flex: 1 1 auto;\n min-width: 0;\n}\n.muigui-value>*:nth-child(1) {\n flex: 1 1 calc(100% - var(--number-width));\n}\n.muigui-value>*:nth-child(2) {\n flex: 1 1 var(--number-width);\n margin-left: 0.2em;\n}\n\n/* fix! */\n.muigui-open>button>label::before,\n.muigui-closed>button>label::before {\n width: 1.25em;\n height: var(--line-height);\n display: inline-grid;\n place-content: center start;\n pointer-events: none;\n}\n.muigui-open>button>label::before {\n content: "ⓧ"; /*"▼";*/\n}\n.muigui-closed>button>label::before {\n content: "⨁"; /*"▶";*/\n}\n.muigui-open>*:nth-child(2) {\n transition: max-height 0.2s ease-out,\n opacity 0.5s ease-out;\n max-height: 100vh;\n overflow: auto;\n opacity: 1;\n}\n\n.muigui-closed>*:nth-child(2) {\n transition: max-height 0.2s ease-out,\n opacity 1s;\n max-height: 0;\n opacity: 0;\n overflow: hidden;\n}\n\n/* ---- popdown ---- */\n\n.muigui-pop-down-top {\n display: flex;\n}\n/* fix? */\n.muigui-value>*:nth-child(1).muigui-pop-down-top {\n flex: 0;\n}\n.muigui-pop-down-bottom {\n\n}\n\n.muigui-pop-down-values {\n min-width: 0;\n display: flex;\n}\n.muigui-pop-down-values>* {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.muigui-value.muigui-pop-down-controller {\n flex-direction: column;\n}\n\n.muigui-pop-down-top input[type=checkbox] {\n -webkit-appearance: none;\n appearance: none;\n width: auto;\n color: var(--value-color);\n background-color: var(--value-bg-color);\n cursor: pointer;\n\n display: grid;\n place-content: center;\n margin: 0;\n font: inherit;\n color: currentColor;\n width: 1.7em;\n height: 1.7em;\n transform: translateY(-0.075em);\n}\n\n.muigui-pop-down-top input[type=checkbox]::before {\n content: "+";\n display: grid;\n place-content: center;\n border-radius: calc(var(--border-radius) + 2px);\n border-left: 1px solid rgba(255,255,255,0.3);\n border-top: 1px solid rgba(255,255,255,0.3);\n border-bottom: 1px solid rgba(0,0,0,0.2);\n border-right: 1px solid rgba(0,0,0,0.2);\n background-color: var(--range-color);\n color: var(--value-bg-color);\n width: calc(var(--line-height) - 4px);\n height: calc(var(--line-height) - 4px);\n}\n\n.muigui-pop-down-top input[type=checkbox]:checked::before {\n content: "X";\n}\n\n\n/* ---- select ---- */\n\n.muigui select,\n.muigui option,\n.muigui input,\n.muigui button {\n color: var(--value-color);\n background-color: var(--value-bg-color);\n font-family: var(--font-family);\n font-size: var(--font-size);\n border: none;\n margin: 0;\n border-radius: var(--border-radius);\n}\n.muigui select {\n appearance: none;\n margin: 0;\n margin-left: 0; /*?*/\n overflow: hidden; /* Safari */\n}\n\n.muigui select:focus,\n.muigui input:focus,\n.muigui button:focus {\n outline: 1px solid var(--focus-color);\n}\n\n.muigui select:hover,\n.muigui option:hover,\n.muigui input:hover,\n.muigui button:hover {\n background-color: var(--hover-bg-color); \n}\n\n/* ------ [ label ] ------ */\n\n.muigui-label {\n border-top: 1px solid var(--menu-sep-color);\n border-bottom: 1px solid var(--menu-sep-color);\n padding-top: 0.4em;\n padding-bottom: 0.3em;\n place-content: center start;\n background-color: var(--menu-bg-color);\n white-space: pre;\n border-radius: var(--border-radius);\n}\n\n/* ------ [ divider] ------ */\n\n.muigui-divider {\n min-height: 6px;\n border-top: 2px solid var(--menu-sep-color);\n margin-top: 6px;\n}\n\n/* ------ [ button ] ------ */\n\n.muigui-button {\n display: grid;\n\n}\n.muigui-button button {\n border: none;\n color: var(--value-color);\n background-color: var(--button-bg-color);\n cursor: pointer;\n place-content: center center;\n}\n\n/* ------ [ color ] ------ */\n\n.muigui-color>div {\n overflow: hidden;\n position: relative;\n margin-left: 0;\n margin-right: 0; /* why? */\n max-width: var(--line-height);\n border-radius: var(--border-radius);\n}\n\n.muigui-color>div:focus-within {\n outline: 1px solid var(--focus-color);\n}\n\n.muigui-color input[type=color] {\n border: none;\n padding: 0;\n background: inherit;\n cursor: pointer;\n position: absolute;\n width: 200%;\n left: -10px;\n top: -10px;\n height: 200%;\n}\n.muigui-disabled canvas,\n.muigui-disabled svg,\n.muigui-disabled img,\n.muigui-disabled .muigui-color input[type=color] {\n opacity: 0.2;\n}\n\n/* ------ [ checkbox ] ------ */\n\n.muigui-checkbox>label:nth-child(2) {\n display: grid;\n place-content: center start;\n margin: 0;\n}\n\n.muigui-checkbox input[type=checkbox] {\n -webkit-appearance: none;\n appearance: none;\n width: auto;\n color: var(--value-color);\n background-color: var(--value-bg-color);\n cursor: pointer;\n\n display: grid;\n place-content: center;\n margin: 0;\n font: inherit;\n color: currentColor;\n width: 1.7em;\n height: 1.7em;\n transform: translateY(-0.075em);\n}\n\n.muigui-checkbox input[type=checkbox]::before {\n content: "";\n color: var(--value-color);\n display: grid;\n place-content: center;\n}\n\n.muigui-checkbox input[type=checkbox]:checked::before {\n content: "✔";\n}\n\n.muigui input[type=number]::-webkit-inner-spin-button, \n.muigui input[type=number]::-webkit-outer-spin-button { \n -webkit-appearance: none;\n appearance: none;\n margin: 0; \n}\n.muigui input[type=number] {\n -moz-appearance: textfield;\n}\n\n/* ------ [ radio grid ] ------ */\n\n.muigui-radio-grid>div {\n display: grid;\n gap: 2px;\n}\n\n.muigui-radio-grid input {\n appearance: none;\n display: none;\n}\n\n.muigui-radio-grid button {\n color: var(--color);\n width: 100%;\n text-align: left;\n}\n\n.muigui-radio-grid input:checked + button {\n color: var(--value-color);\n background-color: var(--selected-color);\n}\n\n/* ------ [ color-chooser ] ------ */\n\n.muigui-color-chooser-cursor {\n stroke-width: 1px;\n stroke: white;\n fill: none;\n}\n.muigui-color-chooser-circle {\n stroke-width: 1px;\n stroke: white;\n fill: none;\n}\n\n\n/* ------ [ vec2 ] ------ */\n\n.muigui-vec2 svg {\n background-color: var(--value-bg-color);\n}\n\n.muigui-vec2-axis {\n stroke: 1px;\n stroke: var(--focus-color);\n}\n\n.muigui-vec2-line {\n stroke-width: 1px;\n stroke: var(--value-color);\n fill: var(--value-color);\n}\n\n/* ------ [ direction ] ------ */\n\n.muigui-direction svg {\n background-color: rgba(0,0,0,0.2);\n}\n\n.muigui-direction:focus-within svg {\n outline: none;\n}\n.muigui-direction-range {\n fill: var(--value-bg-color);\n}\n.muigui-direction svg:focus {\n outline: none;\n}\n.muigui-direction svg:focus .muigui-direction-range {\n stroke-width: 0.5px;\n stroke: var(--focus-color);\n}\n\n.muigui-direction-arrow {\n fill: var(--value-color);\n}\n\n/* ------ [ slider ] ------ */\n\n.muigui-slider>div {\n display: flex;\n align-items: stretch;\n height: var(--line-height);\n}\n.muigui-slider svg {\n flex: 1 1 auto;\n}\n.muigui-slider .muigui-slider-up #muigui-orientation {\n transform: scale(1, -1) translateY(-100%);\n}\n\n.muigui-slider .muigui-slider-up #muigui-number-orientation {\n transform: scale(1,-1);\n}\n\n.muigui-ticks {\n stroke: var(--range-color);\n}\n.muigui-thicks {\n stroke: var(--color);\n stroke-width: 2px;\n}\n.muigui-svg-text {\n fill: var(--color);\n font-size: 7px;\n}\n.muigui-mark {\n fill: var(--value-color);\n}\n\n/* ------ [ range ] ------ */\n\n\n.muigui-range input[type=range] {\n -webkit-appearance: none;\n appearance: none;\n background-color: transparent;\n}\n\n.muigui-range input[type=range]::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n border-radius: calc(var(--border-radius) + 2px);\n border-left: 1px solid rgba(255,255,255,0.3);\n border-top: 1px solid rgba(255,255,255,0.3);\n border-bottom: 1px solid rgba(0,0,0,0.2);\n border-right: 1px solid rgba(0,0,0,0.2);\n background-color: var(--range-color);\n margin-top: calc((var(--line-height) - 2px) / -2);\n width: calc(var(--line-height) - 2px);\n height: calc(var(--line-height) - 2px);\n}\n\n.muigui-range input[type=range]::-webkit-slider-runnable-track {\n -webkit-appearance: none;\n appearance: none;\n border: 1px solid var(--menu-sep-color);\n height: 2px;\n}\n\n\n/* dat.gui style - doesn\'t work on Safari iOS */\n\n/*\n.muigui-range input[type=range] {\n cursor: ew-resize;\n overflow: hidden;\n}\n\n.muigui-range input[type=range] {\n -webkit-appearance: none;\n appearance: none;\n background-color: var(--range-right-color);\n margin: 0;\n}\n.muigui-range input[type=range]:hover {\n background-color: var(--range-right-hover-color);\n}\n\n.muigui-range input[type=range]::-webkit-slider-runnable-track {\n -webkit-appearance: none;\n appearance: none;\n height: max-content;\n color: var(--range-left-color);\n margin-top: -1px;\n}\n\n.muigui-range input[type=range]::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 0px;\n height: max-content;\n box-shadow: -1000px 0 0 1000px var(--range-left-color);\n}\n*/\n\n/* FF */\n/*\n.muigui-range input[type=range]::-moz-slider-progress {\n background-color: var(--range-left-color); \n}\n.muigui-range input[type=range]::-moz-slider-thumb {\n height: max-content;\n width: 0;\n border: none;\n box-shadow: -1000px 0 0 1000px var(--range-left-color);\n box-sizing: border-box;\n}\n*/\n\n/* ---------------------------------------------------------- */\n\n/* needs to be at bottom to take precedence */\n.muigui-auto-place {\n max-height: 100%;\n position: fixed;\n top: 0;\n right: 15px;\n z-index: 100001;\n}\n\n',themes:{default:"",float:"\n :root {\n color-scheme: light dark,\n }\n\n .muigui {\n --width: 400px;\n --bg-color: initial;\n --label-width: 25%;\n }\n\n input,\n .muigui-label-controller>label {\n text-shadow:\n -1px -1px 0 var(--contrast-color),\n 1px -1px 0 var(--contrast-color),\n -1px 1px 0 var(--contrast-color),\n 1px 1px 0 var(--contrast-color);\n }\n\n .muigui-controller > label:nth-child(1) {\n place-content: center end;\n margin-right: 1em;\n }\n\n .muigui-value > :nth-child(2) {\n margin-left: 1em;\n }\n\n .muigui-root>*:nth-child(1) {\n display: none;\n }\n\n .muigui-range input[type=range]::-webkit-slider-thumb {\n border-radius: 1em;\n }\n\n .muigui-range input[type=range]::-webkit-slider-runnable-track {\n -webkit-appearance: initial;\n appearance: none;\n border: 1px solid rgba(0, 0, 0, 0.25);\n height: 2px;\n }\n\n .muigui-colors {\n --value-color: var(--color );\n --value-bg-color: rgba(0, 0, 0, 0.1);\n --disabled-color: #cccccc;\n --menu-bg-color: rgba(0, 0, 0, 0.1);\n --menu-sep-color: #bbbbbb;\n --hover-bg-color: rgba(0, 0, 0, 0);\n --invalid-color: #FF0000;\n --selected-color: rgba(0, 0, 0, 0.3);\n --range-color: rgba(0, 0, 0, 0.125);\n }\n"}};function e(t,e={},n=[]){const i=document.createElement(t);return function(t,e,n){for(const[n,i]of Object.entries(e))if("function"==typeof i&&n.startsWith("on")){const e=n.substring(2).toLowerCase();t.addEventListener(e,i,{passive:!1})}else if("object"==typeof i)for(const[e,o]of Object.entries(i))t[n][e]=o;else void 0===t[n]?t.setAttribute(n,i):t[n]=i;for(const e of n)t.appendChild(e)}(i,e,n),i}function n(t,e){const n=t.indexOf(e);return n&&t.splice(n,1),t}function i(t,e,n){return Math.max(e,Math.min(n,t))}const o="undefined"!=typeof SharedArrayBuffer?function(t){return t&&t.buffer&&(t.buffer instanceof ArrayBuffer||t.buffer instanceof SharedArrayBuffer)}:function(t){return t&&t.buffer&&t.buffer instanceof ArrayBuffer},s=(t,e,n)=>Math.round(e(t)/n)/(1/n),r=(t,e)=>(t%e+e)%e;function a(t,e){for(const n in e)n in t&&(t[n]=e[n]);return t}const l=(t,e,n,i,o)=>(t-e)*(o-i)/(n-e)+i,u=({from:t,to:e})=>({to:n=>l(n,...t,...e),from:n=>[!0,l(n,...e,...t)]}),c=({from:t,to:e,step:n})=>({min:e[0],max:e[1],...n&&{step:n},converters:u({from:t,to:e})}),h={to:t=>t,from:t=>[!0,t]};function d(t,e,n,i,o){const{converters:{from:s}=h}=o,{min:r,max:a}=o,l=o.minRange||0,u=s(l)[1];return console.log("guiMinRange",l),console.log("valueMinRange",u),[t.add(e,n,{...o,min:r,max:a-l}).listen().onChange((t=>{e[i]=Math.min(a,Math.max(t+u,e[i]))})),t.add(e,i,{...o,min:r+l,max:a}).listen().onChange((t=>{e[n]=Math.max(r,Math.min(t-u,e[n]))}))]}class p{#t;#e=[];constructor(t){this.domElement=t,this.#t=t}addElem(t){return this.#t.appendChild(t),t}removeElem(t){return this.#t.removeChild(t),t}pushSubElem(t){this.#t.appendChild(t),this.#t=t}popSubElem(){this.#t=this.#t.parentElement}add(t){return this.#e.push(t),this.addElem(t.domElement),t}remove(t){return this.removeElem(t.domElement),n(this.#e,t),t}pushSubView(t){this.pushSubElem(t.domElement)}popSubView(){this.popSubElem()}setOptions(t){for(const e of this.#e)e.setOptions(t)}updateDisplayIfNeeded(t,e){for(const n of this.#e)n.updateDisplayIfNeeded(t,e);return this}$(t){return this.domElement.querySelector(t)}}class m extends p{#n;#i;#o;constructor(t){super(e("div",{className:"muigui-controller"})),this.#n=[],this.#i=[],t&&this.domElement.classList.add(t)}get parent(){return this.#o}setParent(t){this.#o=t,this.enable(!this.disabled())}show(t=!0){return this.domElement.classList.toggle("muigui-hide",!t),this.domElement.classList.toggle("muigui-show",t),this}hide(){return this.show(!1)}disabled(){return!!this.domElement.closest(".muigui-disabled")}enable(t=!0){return this.domElement.classList.toggle("muigui-disabled",!t),["input","button","select","textarea"].forEach((t=>{this.domElement.querySelectorAll(t).forEach((t=>{const e=!!t.closest(".muigui-disabled");t.disabled=e}))})),this}disable(t=!0){return this.enable(!t)}onChange(t){return this.removeChange(t),this.#n.push(t),this}removeChange(t){return n(this.#n,t),this}onFinishChange(t){return this.removeFinishChange(t),this.#i.push(t),this}removeFinishChange(t){return n(this.#i,t),this}#s(t,e){for(const n of t)n.call(this,e)}emitChange(t,e,n){this.#s(this.#n,t),this.#o&&(void 0===e?this.#o.emitChange(t):this.#o.emitChange({object:e,property:n,value:t,controller:this}))}emitFinalChange(t,e,n){this.#s(this.#i,t),this.#o&&(void 0===e?this.#o.emitChange(t):this.#o.emitFinalChange({object:e,property:n,value:t,controller:this}))}getColors(){const t=t=>t.replace(/-([a-z])/g,((t,e)=>e.toUpperCase())),n=e("div");this.domElement.appendChild(n);const i=Object.fromEntries(["color","bg-color","value-color","value-bg-color","hover-bg-color","menu-bg-color","menu-sep-color","disabled-color"].map((e=>{n.style.color=`var(--${e})`;const i=getComputedStyle(n);return[t(e),i.color]})));return n.remove(),i}}class g extends m{#r;#a;#l;#u={name:""};constructor(t,n,i={}){super("muigui-button",""),this.#r=t,this.#a=n,this.#l=this.addElem(e("button",{type:"button",onClick:()=>{this.#r[this.#a](this)}})),this.setOptions({name:n,...i})}setOptions(t){a(this.#u,t);const{name:e}=this.#u;this.#l.textContent=e}}function f(t,e){if(t.length!==e.length)return!1;for(let n=0;n{t.setValue(i.checked)},onChange:()=>{t.setFinalValue(i.checked)}});super(e("label",{},[i]))}updateDisplay(t){this.domElement.checked=t}}const x=[],w=new Set;let y,k;function E(){y=void 0,k=!0;for(const t of x)w.has(t)||t();k=!1,w.size&&(k?C():(w.forEach((t=>{n(x,t)})),w.clear())),C()}function C(){!y&&x.length&&(y=requestAnimationFrame(E))}let $=0;function M(){return"muigui-"+ ++$}class V extends p{constructor(t=""){super(e("div",{className:"muigui-value"})),t&&this.domElement.classList.add(t)}}class S extends m{#b;#v;constructor(t="",n=""){super("muigui-label-controller"),this.#b=M(),this.#v=e("label",{for:this.#b}),this.domElement.appendChild(this.#v),this.pushSubView(new V(t)),this.name(n)}get id(){return this.#b}name(t){return this.#v.title===this.#v.textContent&&(this.#v.title=t),this.#v.textContent=t,this}tooltip(t){this.#v.title=t}}class I extends S{#r;#a;#x;#w;#e;#y;constructor(t,e,n=""){super(n,e),this.#r=t,this.#a=e,this.#x=this.getValue(),this.#w=!1,this.#e=[]}get initialValue(){return this.#x}get object(){return this.#r}get property(){return this.#a}add(t){return this.#e.push(t),super.add(t),this.updateDisplay(),t}#k(t,e){if("object"==typeof t){const e=this.#r[this.#a];if(Array.isArray(t))for(let n=0;n=0&&x.splice(e,1)}(this.#y)),this}}class D extends I{constructor(t,e){super(t,e,"muigui-checkbox");const n=this.id;this.add(new v(this,n)),this.updateDisplay()}}const F={to:t=>t,from:t=>[!0,t]},L={to:t=>t.toString(),from:t=>{const e=parseFloat(t);return[!Number.isNaN(e),e]}},N={radToDeg:u({to:[0,180],from:[0,Math.PI]})};function A(){let t=0;return function(e,n,i=5){t-=e.deltaY*n/i;const o=Math.floor(Math.abs(t)/n)*Math.sign(t)*n;return t-=o,o}}class U extends b{#E;#C;#$;#M;#u={step:.01,converters:L,min:Number.NEGATIVE_INFINITY,max:Number.POSITIVE_INFINITY};constructor(t,n){const o=t.setValue.bind(t),r=t.setFinalValue.bind(t),a=A();super(e("input",{type:"number",onInput:()=>this.#V(o,!0),onChange:()=>this.#V(r,!1),onWheel:e=>{e.preventDefault();const{min:n,max:o,step:r}=this.#u,l=a(e,r),u=parseFloat(this.domElement.value),c=i(s(u+l,(t=>t),r),n,o);t.setValue(c)}})),this.setOptions(n)}#V(t,e){const n=parseFloat(this.domElement.value),[o,s]=this.#C(n);let r;if(o&&!Number.isNaN(n)){const{min:n,max:o}=this.#u;r=s>=n&&s<=o,this.#M=e,t(i(s,n,o))}this.domElement.classList.toggle("muigui-invalid-value",!o||!r)}updateDisplay(t){this.#M||(this.domElement.value=s(t,this.#E,this.#$)),this.#M=!1}setOptions(t){a(this.#u,t);const{step:e,converters:{to:n,from:i}}=this.#u;return this.#E=n,this.#C=i,this.#$=e,this}}class O extends I{#S;#$;constructor(t,e,n={}){super(t,e,"muigui-checkbox"),this.#S=this.add(new U(this,n)),this.updateDisplay()}}class j extends b{#I;constructor(t,n){const i=[];super(e("select",{onChange:()=>{t.setFinalValue(this.#I[this.domElement.selectedIndex])}},n.map((([t,n])=>(i.push(n),e("option",{textContent:t})))))),this.#I=i}updateDisplay(t){const e=this.#I.indexOf(t);this.domElement.selectedIndex=e}}function T(t,e){return Array.isArray(t)?Array.isArray(t[0])?t:e?t.map(((t,e)=>[t,e])):t.map((t=>[t,t])):[...Object.entries(t)]}class P extends I{constructor(t,e,n){super(t,e,"muigui-select");const i="number"==typeof this.getValue(),{keyValues:o}=n,s=T(o,i);this.add(new j(this,s)),this.updateDisplay()}}class z extends b{#E;#C;#$;#M;#u={step:.01,min:0,max:1,converters:F};constructor(t,n){const o=A();super(e("input",{type:"range",onInput:()=>{this.#M=!0;const{min:e,max:n,step:o}=this.#u,r=parseFloat(this.domElement.value),a=i(s(r,(t=>t),o),e,n),[l,u]=this.#C(a);l&&t.setValue(u)},onChange:()=>{this.#M=!0;const{min:e,max:n,step:o}=this.#u,r=parseFloat(this.domElement.value),a=i(s(r,(t=>t),o),e,n),[l,u]=this.#C(a);l&&t.setFinalValue(u)},onWheel:e=>{e.preventDefault();const[n,r]=this.#C(parseFloat(this.domElement.value));if(!n)return;const{min:a,max:l,step:u}=this.#u,c=o(e,u),h=i(s(r+c,(t=>t),u),a,l);t.setValue(h)}})),this.setOptions(n)}updateDisplay(t){this.#M||(this.domElement.value=s(t,this.#E,this.#$)),this.#M=!1}setOptions(t){a(this.#u,t);const{step:e,min:n,max:i,converters:{to:o,from:s}}=this.#u;return this.#E=o,this.#C=s,this.#$=e,this.domElement.step=e,this.domElement.min=n,this.domElement.max=i,this}}class B extends I{constructor(t,e,n){super(t,e,"muigui-range"),this.add(new z(this,n)),this.add(new U(this,n))}}class G extends b{#E;#C;#M;#u={converters:F};constructor(t,n){const i=t.setValue.bind(t),o=t.setFinalValue.bind(t);super(e("input",{type:"text",onInput:()=>this.#V(i,!0),onChange:()=>this.#V(o,!1)})),this.setOptions(n)}#V(t,e){const[n,i]=this.#C(this.domElement.value);n&&(this.#M=e,t(i)),this.domElement.style.color=n?"":"var(--invalid-color)"}updateDisplay(t){this.#M||(this.domElement.value=this.#E(t),this.domElement.style.color=""),this.#M=!1}setOptions(t){a(this.#u,t);const{converters:{to:e,from:n}}=this.#u;return this.#E=e,this.#C=n,this}}class H extends I{constructor(t,e){super(t,e,"muigui-checkbox"),this.add(new G(this)),this.updateDisplay()}}class R extends p{constructor(t,n){super(e(t,{className:n}))}}class Y extends S{#D;constructor(){super("muigui-canvas"),this.#D=this.add(new R("canvas","muigui-canvas")).domElement}get canvas(){return this.#D}}const W=(t,e,n)=>Math.max(e,Math.min(n,t)),q=t=>+t.toFixed(3),_=t=>parseInt(t.substring(1,3),16)<<16|parseInt(t.substring(3,5),16)<<8|parseInt(t.substring(5,7),16),J=t=>[parseInt(t.substring(1,3),16),parseInt(t.substring(3,5),16),parseInt(t.substring(5,7),16)],K=t=>`#${Array.from(t).map((t=>t.toString(16).padStart(2,"0"))).join("")}`,X=t=>J(t).map((t=>q(t/255))),Z=t=>K(Array.from(t).map((t=>Math.round(W(255*t,0,255))))),Q=t=>({r:parseInt(t.substring(1,3),16)/255,g:parseInt(t.substring(3,5),16)/255,b:parseInt(t.substring(5,7),16)/255}),tt=t=>W(Math.round(255*t),0,255).toString(16).padStart(2,"0"),et=t=>`rgb(${J(t).join(", ")})`,nt=/^\s*rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/,it=t=>{const e=rt(J(t)).map((t=>(t=>+t.toFixed(0))(t)));return`hsl(${e[0]}, ${e[1]}%, ${e[2]}%)`},ot=/^\s*hsl\(\s*(\d+)(?:deg|)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)\s*$/,st=(t,e)=>(t%e+e)%e;const rt=t=>{const[e,n,i]=function([t,e,n]){const i=Math.max(t,e,n),o=Math.min(t,e,n),s=.5*(o+i),r=i-o;let a=0,l=0;if(0!==r)switch(l=0===s||1===s?0:(i-s)/Math.min(s,1-s),i){case t:a=(e-n)/r+(et/255)));return[360*e,100*n,100*i]};function at([t,e,n]){return e=W(e,0,1),n=W(n,0,1),[t,t+2/3,t+1/3].map((t=>{return i=1,o=W(Math.abs(6*(t=>t>=0?t%1:1-t%1)(t)-3)-1,0,1),(i+(o-i)*e)*n;var i,o}))}const lt=t=>Math.round(1e3*t)/1e3;function ut([t,e,n]){const i=n>e?[n,e,-1,2/3]:[e,n,0,-1/3],o=i[0]>t?[i[0],i[1],i[3],t]:[t,i[1],i[2],i[0]],s=o[0]-Math.min(o[3],o[1]);return[Math.abs(o[2]+(o[3]-o[1])/(6*s+Number.EPSILON)),s/(o[0]+Number.EPSILON),o[0]].map(lt)}window.hsv01ToRGBFloat=at,window.rgbFloatToHSV01=ut;const ct=[{re:/^#(?:[0-9a-f]){6}$/i,format:"hex6"},{re:/^(?:[0-9a-f]){6}$/i,format:"hex6-no-hash"},{re:/^#(?:[0-9a-f]){3}$/i,format:"hex3"},{re:/^(?:[0-9a-f]){3}$/i,format:"hex3-no-hash"},{re:nt,format:"css-rgb"},{re:ot,format:"css-hsl"}];function ht(t){switch(typeof t){case"number":return"uint32-rgb";case"string":{const e=function(t){for(const e of ct)if(e.re.test(t))return e}(t.trim());if(e)return e.format;break}case"object":if(t instanceof Uint8Array||t instanceof Uint8ClampedArray){if(3===t.length)return"uint8-rgb"}else if(t instanceof Float32Array){if(3===t.length)return"float-rgb"}else if(Array.isArray(t)){if(3===t.length)return"float-rgb"}else if("r"in t&&"g"in t&&"b"in t)return"object-rgb"}throw new Error(`unknown color format: ${t}`)}function dt(t){return t.trim(t)}function pt(t){return t[1]===t[2]&&t[3]===t[4]&&t[5]===t[6]?`#${t[1]}${t[3]}${t[5]}`:t}const mt=/^(#|)([0-9a-f]{3})$/i;function gt(t){const e=mt.exec(t);if(e){const[,,t]=e;return"#"+`${(n=t)[0]}${n[0]}${n[1]}${n[1]}${n[2]}${n[2]}`}var n;return t}function ft(t){return pt(dt(t))}const bt=t=>{const e=nt.exec(t);if(!e)return[!1];const n=[e[1],e[2],e[3]].map((t=>parseInt(t)));return[!n.find((t=>t>255)),`rgb(${n.join(", ")})`]},vt=t=>{const e=ot.exec(t);if(!e)return[!1];const n=[e[1],e[2],e[3]].map((t=>parseFloat(t)));return[!n.find((t=>Number.isNaN(t))),`hsl(${n[0]}, ${n[1]}%, ${n[2]}%)`]},xt=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*$/,wt=/^\s*(?:0x){0,1}([0-9a-z]{1,6})\s*$/i,yt=/^\s*#[a-f0-9]{6}\s*$|^\s*#[a-f0-9]{3}\s*$/i,kt=/^\s*[a-f0-9]{6}\s*$/i,Et={hex6:{color:{from:t=>[!0,t],to:dt},text:{from:t=>[yt.test(t),t.trim()],to:t=>t}},hex3:{color:{from:t=>[!0,ft(t)],to:gt},text:{from:t=>[yt.test(t),pt(t.trim())],to:t=>t}},"hex6-no-hash":{color:{from:t=>[!0,t.substring(1)],to:t=>`#${dt(t)}`},text:{from:t=>[kt.test(t),t.trim()],to:t=>t}},"hex3-no-hash":{color:{from:t=>[!0,ft(t).substring(1)],to:gt},text:{from:t=>[kt.test(t),pt(t.trim())],to:t=>t}},"uint32-rgb":{color:{from:t=>[!0,_(t)],to:t=>`#${Math.round(t).toString(16).padStart(6,"0")}`},text:{from:t=>(t=>{const e=wt.exec(t);return e?[!0,parseInt(e[1],16)]:[!1]})(t),to:t=>`0x${t.toString(16).padStart(6,"0")}`}},"uint8-rgb":{color:{from:t=>[!0,J(t)],to:K},text:{from:t=>{const e=xt.exec(t);if(!e)return[!1];const n=[e[1],e[2],e[3]].map((t=>parseInt(t)));return[!n.find((t=>t>255)),n]},to:t=>t.join(", ")}},"float-rgb":{color:{from:t=>[!0,X(t)],to:Z},text:{from:t=>{const e=t.split(",").map((t=>t.trim())),n=e.map((t=>parseFloat(t)));if(3!==n.length)return[!1];const i=e.findIndex((t=>isNaN(t)));return[i<0,n.map((t=>q(t)))]},to:t=>Array.from(t).map((t=>q(t))).join(", ")}},"object-rgb":{color:{from:t=>[!0,Q(t)],to:t=>`#${tt(t.r)}${tt(t.g)}${tt(t.b)}`},text:{from:t=>{try{const e=t.replace(/([a-z])/g,'"$1"'),n=JSON.parse(e);if(Number.isNaN(n.r)||Number.isNaN(n.g)||Number.isNaN(n.b))throw new Error("not {r, g, b}");return[!0,n]}catch(t){return[!1]}},to:t=>`{r:${q(t.r)}, g:${q(t.g)}, b:${q(t.b)}}`}},"css-rgb":{color:{from:t=>[!0,et(t)],to:t=>{const e=nt.exec(t);return K([e[1],e[2],e[3]].map((t=>parseInt(t))))}},text:{from:bt,to:t=>bt(t)[1]}},"css-hsl":{color:{from:t=>[!0,it(t)],to:t=>{const e=ot.exec(t),n=function([t,e,n]){t=st(t,360),e=W(e/100,0,1),n=W(n/100,0,1);const i=e*Math.min(n,1-n);function o(e){const o=(e+t/30)%12;return n-i*Math.max(-1,Math.min(o-3,9-o,1))}return[o(0),o(8),o(4)].map((t=>Math.round(255*t)))}([e[1],e[2],e[3]].map((t=>parseFloat(t))));return K(n)}},text:{from:vt,to:t=>vt(t)[1]}}};class Ct extends b{#E;#C;#F;#M;#u={converters:F};constructor(t,n){const i=e("input",{type:"color",onInput:()=>{const[e,n]=this.#C(i.value);e&&(this.#M=!0,t.setValue(n))},onChange:()=>{const[e,n]=this.#C(i.value);e&&(this.#M=!0,t.setFinalValue(n))}});super(e("div",{},[i])),this.setOptions(n),this.#F=i}updateDisplay(t){this.#M||(this.#F.value=this.#E(t)),this.#M=!1}setOptions(t){a(this.#u,t);const{converters:{to:e,from:n}}=this.#u;return this.#E=e,this.#C=n,this}}class $t extends I{#L;#S;constructor(t,e,n={}){super(t,e,"muigui-color");const i=n.format||ht(this.getValue()),{color:o,text:s}=Et[i];this.#L=this.add(new Ct(this,{converters:o})),this.#S=this.add(new G(this,{converters:s})),this.updateDisplay()}setOptions(t){const{format:e}=t;if(e){const{color:t,text:n}=Et[e];this.#L.setOptions({converters:t}),this.#S.setOptions({converters:n})}return super.setOptions(t),this}}class Mt extends m{constructor(){super("muigui-divider")}}class Vt extends m{#N;#A;constructor(t){super(t),this.#N=[],this.#A=this}get children(){return this.#N}get controllers(){return this.#N.filter((t=>!(t instanceof Vt)))}get folders(){return this.#N.filter((t=>t instanceof Vt))}reset(t=!0){for(const e of this.#N)e instanceof Vt&&!t||e.reset(t);return this}remove(t){const e=this.#N.indexOf(t);if(e>=0){const t=this.#N.splice(e,1)[0];t.domElement.remove(),t.setParent(null)}return this}_addControllerImpl(t){return this.domElement.appendChild(t.domElement),this.#N.push(t),t.setParent(this),t}addController(t){return this.#A._addControllerImpl(t)}pushContainer(t){return this.addController(t),this.#A=t,t}popContainer(){return this.#A=this.#A.parent,this}}class St extends Vt{#U;constructor(t="Controls",n="muigui-menu"){super(n),this.#U=e("label"),this.addElem(e("button",{type:"button",onClick:()=>this.toggleOpen()},[this.#U])),this.pushContainer(new Vt),this.name(t),this.open()}open(t=!0){return this.domElement.classList.toggle("muigui-closed",!t),this.domElement.classList.toggle("muigui-open",t),this}close(){return this.open(!1)}name(t){return this.#U.textContent=t,this}title(t){return this.name(t)}toggleOpen(){return this.open(!this.domElement.classList.contains("muigui-open")),this}}class It extends m{constructor(t){super("muigui-label"),this.text(t)}text(t){return this.domElement.textContent=t,this}}class Dt extends St{add(t,e,...n){const i=t instanceof m?t:function(t,e,...n){const[i]=n;if(Array.isArray(i))return new P(t,e,{keyValues:i});const o=typeof t[e];switch(o){case"number":if("number"==typeof n[0]&&"number"==typeof n[1]){const i=n[0],o=n[1],s=n[2];return new B(t,e,{min:i,max:o,...s&&{step:s}})}return 0===n.length?new O(t,e,...n):new B(t,e,...n);case"boolean":return new D(t,e,...n);case"function":return new g(t,e,...n);case"string":return new H(t,e,...n);case"undefined":throw new Error(`no property named ${e}`);default:throw new Error(`unhandled type ${o} for property ${e}`)}}(t,e,...n);return this.addController(i)}addCanvas(t){return this.addController(new Y(t))}addColor(t,e,...n){return this.addController(new $t(t,e,...n))}addDivider(){return this.addController(new Mt)}addFolder(t){return this.addController(new Dt(t))}addLabel(t){return this.addController(new It(t))}}class Ft extends HTMLElement{constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}}customElements.define("muigui-element",Ft);const Lt=new CSSStyleSheet;Lt.replaceSync(t.default);const Nt=new CSSStyleSheet;function At(t){let e,n;function i(){if(e&&!n){const o=e;e=void 0,n=t.replace(o).then((()=>{console.log(o),n=void 0,i()}))}}return function(t){e=t,i()}}const Ut=At(Lt),Ot=At(Nt);class jt extends Dt{static converters=N;static mapRange=l;static makeRangeConverters=u;static makeRangeOptions=c;static makeMinMaxPair=d;#O=new CSSStyleSheet;constructor(t={}){super("Controls","muigui-root"),t instanceof HTMLElement&&(t={parent:t});const{autoPlace:n=!0,width:i,title:o="Controls"}=t;let{parent:s}=t;if(i&&(this.domElement.style.width=/^\d+$/.test(i)?`${i}px`:i),void 0===s&&n&&(s=document.body,this.domElement.classList.add("muigui-auto-place")),s){const t=e("muigui-element");t.shadowRoot.adoptedStyleSheets=[Lt,Nt,this.#O],t.shadow.appendChild(this.domElement),s.appendChild(t)}o&&this.title(o),this.domElement.classList.add("muigui","muigui-colors")}setStyle(t){this.#O.replace(t)}static setBaseStyles(t){Ut(t)}static getBaseStyleSheet(){return Lt}static setUserStyles(t){Ot(t)}static getUserStyleSheet(){return Nt}static setTheme(e){jt.setBaseStyles(`${t.default}\n${t.themes[e]||""}`)}}function Tt(){}function Pt(t,e,n){const i=t.getBoundingClientRect(),o=e.clientX-i.left,s=e.clientY-i.top,r=o/i.width,a=s/i.height,l=o-(n=n||[o,s])[0],u=s-n[1];return{x:o,y:s,nx:r,ny:a,dx:l,dy:u,ndx:l/i.width,ndy:u/i.width}}function zt(t,{onDown:e=Tt,onMove:n=Tt,onUp:i=Tt}){let o;const s=function(e){const i={type:"move",...Pt(t,e,o)};n(i)},r=function(e){t.releasePointerCapture(e.pointerId),t.removeEventListener("pointermove",s),t.removeEventListener("pointerup",r),document.body.style.backgroundColor="",i("up")},a=function(n){t.addEventListener("pointermove",s),t.addEventListener("pointerup",r),t.setPointerCapture(n.pointerId);const i=Pt(t,n);o=[i.x,i.y],e({type:"down",...i})};return t.addEventListener("pointerdown",a),function(){t.removeEventListener("pointerdown",a)}}class Bt extends b{#j;#T;#P;#z;#B;#G;#H;#R;constructor(t){super(e("div",{innerHTML:'\n\n\n \n \n \n \n \n \n \n \n\n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n\n',className:"muigui-no-scroll"})),this.#j=this.domElement.children[0],this.#T=this.domElement.children[1],this.#P=this.$(".muigui-color-chooser-circle"),this.#z=this.$("#muigui-color-chooser-hue"),this.#B=this.$(".muigui-color-chooser-cursor");const n=e=>{const n=i(e.nx,0,1),o=i(e.ny,0,1);this.#G[1]=n,this.#G[2]=1-o,this.#H=!0,t.setValue(Z(at(this.#G)))},o=e=>{const n=i(e.nx,0,1);this.#G[0]=n,this.#R=!0,t.setValue(Z(at(this.#G)))};zt(this.#j,{onDown:n,onMove:n}),zt(this.#T,{onDown:o,onMove:o})}updateDisplay(t){this.#G||(this.#G=ut(X(t)));{const[e,n,i]=ut(X(t));this.#H||(this.#G[0]=n>.001&&i>.001?e:this.#G[0]),this.#R||(this.#G[1]=n,this.#G[2]=i)}{const[t,e,n]=this.#G;this.#H||(this.#B.setAttribute("transform",`translate(${64*t}, 0)`),this.#z.children[0].setAttribute("stop-color",`hsl(${360*t}, 0%, 100%)`),this.#z.children[1].setAttribute("stop-color",`hsl(${360*t}, 100%, 50%)`)),this.#R||(this.#P.setAttribute("cx",""+64*e),this.#P.setAttribute("cy",""+48*(1-n)))}this.#H=!1,this.#R=!1}}class Gt extends I{#Y;#W;#q;#u={open:!1};constructor(t,n,i={}){super(t,n,"muigui-pop-down-controller"),this.#Y=this.add(new R("div","muigui-pop-down-top"));const o=this.#Y.addElem(e("input",{type:"checkbox",onChange:()=>{this.#u.open=o.checked}}));this.#W=this.#Y.add(new R("div","muigui-pop-down-values")),this.#q=this.add(new R("div","muigui-pop-down-bottom")),this.setOptions(i)}updateDisplay(){super.updateDisplay();const{open:t}=this.#u;this.domElement.children[1].classList.toggle("muigui-open",t),this.domElement.children[1].classList.toggle("muigui-closed",!t)}setOptions(t){a(this.#u,t),super.setOptions(t),this.updateDisplay()}addTop(t){return this.#W.add(t)}addBottom(t){return this.#q.add(t)}}function Ht(){}const Rt={ArrowLeft:[-1,0],ArrowRight:[1,0],ArrowUp:[0,-1],ArrowDown:[0,1]};function Yt(t,{onDown:e=Ht,onUp:n=Ht}){const i=function(t){const i=t.shiftKey?10:1,[o,s]=(Rt[t.key]||[0,0]).map((t=>t*i));("keydown"===t.type?e:n)({type:t.type.substring(3),dx:o,dy:s,event:t})};return t.addEventListener("keydown",i),t.addEventListener("keyup",i),function(){t.removeEventListener("keydown",i),t.removeEventListener("keyup",i)}}function Wt(t,e=""){if(!t)throw new Error(e)}function qt(t,e,n,i,o,s){const r=Math.abs(n)*Math.cos(s),a=Math.abs(i)*Math.sin(s);return[t+Math.cos(o)*r-Math.sin(o)*a,e+Math.sin(o)*r+Math.cos(o)*a]}function _t(t,e,n,i,o){Wt(Math.abs(i-o)<=2*Math.PI),Wt(i>=-Math.PI&&i<=2*Math.PI),Wt(i<=o),Wt(o>=-Math.PI&&o<=4*Math.PI);const{x1:s,y1:r,x2:a,y2:l,fa:u,fs:c}=function(t,e,n,i,o,s,r){const[a,l]=qt(t,e,n,i,o,s),[u,c]=qt(t,e,n,i,o,s+r);return{x1:a,y1:l,x2:u,y2:c,fa:Math.abs(r)>Math.PI?1:0,fs:r>0?1:0}}(t,e,n,n,0,i,o-i);return Math.abs(Math.abs(i-o)-2*Math.PI)>Number.EPSILON?`M${t} ${e} L${s} ${r} A ${n} ${n} 0 ${u} ${c} ${a} ${l} L${t} ${e}`:`M${s} ${r} L${s} ${r} A ${n} ${n} 0 ${u} ${c} ${a} ${l}`}const Jt=t=>r(t+Math.PI,2*Math.PI)-Math.PI;class Kt extends b{#_;#J;#K;#X;#u={step:1,min:-180,max:180,dirMin:-Math.PI,dirMax:Math.PI,wrap:void 0,converters:F};constructor(t,n={}){const o=A();super(e("div",{className:"muigui-direction muigui-no-scroll",innerHTML:'\n\n \x3c!----\x3e\n \n \n \n \n \n \n\n',onWheel:e=>{e.preventDefault();const{min:n,max:a,step:l}=this.#u,u=o(e,l);let c=this.#K+u;this.#X&&(c=r(c-n,a-n)+n);const h=i(s(c,(t=>t),l),n,a);t.setValue(h)}}));const a=e=>{const{min:n,max:o,step:r,dirMin:a,dirMax:l}=this.#u,u=2*e.nx-1,c=2*e.ny-1,h=Math.atan2(c,u),d=(a+l)/2,p=i((Jt(h-d)-Jt(a-d))/(l-a),0,1),m=s(n+(o-n)*p,(t=>t),r);t.setValue(m)};zt(this.domElement,{onDown:a,onMove:a}),Yt(this.domElement,{onDown:e=>{const{min:n,max:o,step:r}=this.#u,a=i(s(this.#K+e.dx*r,(t=>t),r),n,o);t.setValue(a)}}),this.#_=this.$("#muigui-arrow"),this.#J=this.$("#muigui-range"),this.setOptions(n)}updateDisplay(t){this.#K=t;const{min:e,max:n}=this.#u,i=(t-e)/(n-e),o=(s=this.#u.dirMin,r=this.#u.dirMax,s+(r-s)*i);var s,r;this.#_.style.transform=`rotate(${o}rad)`}setOptions(t){a(this.#u,t);const{dirMin:e,dirMax:n,wrap:i}=this.#u;this.#X=void 0!==i?i:Math.abs(e-n)>=2*Math.PI-Number.EPSILON;const[o,s]=e(o.push(i),e("label",{},[e("input",{type:"radio",name:s,value:a,onChange:function(){this.checked&&t.setFinalValue(r.#I[this.value])}}),e("button",{type:"button",textContent:n,onClick:function(){this.previousElementSibling.click()}})]))))));const r=this;this.#I=o,this.cols(i)}updateDisplay(t){const e=this.#I.indexOf(t);for(let t=0;t{e({rect:t.getBoundingClientRect(),elem:t})})).observe(t)}function Qt(t,e,n,i){Zt(t,(({rect:o})=>{const{width:s,height:r}=o;t.setAttribute("viewBox",`-${s*e} -${r*n} ${s} ${r}`),i({elem:t,rect:o})}))}function te(t,e,n,i,o,r){const a=[];tt),n)),e=Math.min(e,o);for(let i=t;i<=e;i+=n)a.push(`M${i} 0 l0 ${r}`);return a.join(" ")}class ee extends b{#Z;#Q;#tt;#et;#nt;#it;#ot;#st;#rt;#K;#at;#u={min:-100,max:100,step:1,unit:10,unitSize:10,ticksPerUnit:5,labelFn:t=>t,tickHeight:1,limits:!0,thicksColor:void 0,orientation:void 0};constructor(t,n){const o=A();let r;super(e("div",{innerHTML:'\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \x3c!----\x3e\n \x3c!----\x3e\n \n \n \n \n\n',className:"muigui-no-v-scroll",onWheel:e=>{e.preventDefault();const{min:n,max:r,step:a}=this.#u,l=o(e,a),u=i(s(this.#K+l,(t=>t),a),n,r);t.setValue(u)}})),this.#Z=this.$("svg"),this.#Q=this.$("#muigui-origin"),this.#tt=this.$("#muigui-ticks"),this.#et=this.$("#muigui-thicks"),this.#nt=this.$("#muigui-numbers"),this.#it=this.$("#muigui-left-grad"),this.#ot=this.$("#muigui-right-grad"),this.setOptions(n),zt(this.domElement,{onDown:()=>{r=this.#K},onMove:e=>{const{min:n,max:o,unitSize:a,unit:l,step:u}=this.#u,c=i(s(r-e.dx/a*l,(t=>t),u),n,o);t.setValue(c)}}),Yt(this.domElement,{onDown:e=>{const{min:n,max:o,step:r}=this.#u,a=i(s(this.#K+e.dx*r,(t=>t),r),n,o);t.setValue(a)}}),Qt(this.#Z,.5,0,(({rect:{width:t}})=>{this.#it.setAttribute("x",-t/2),this.#ot.setAttribute("x",t/2-20),this.#at=function(t){const e=t.innerHTML;t.innerHTML="- ";const n=t.querySelector("text").getComputedTextLength();return t.innerHTML=e,n}(this.#nt),this.#st=t,this.#lt()}))}#lt(){if(!this.#st||void 0===this.#K)return;const{labelFn:t,limits:e,min:n,max:i,orientation:o,tickHeight:r,ticksPerUnit:a,unit:l,unitSize:u,thicksColor:c}=this.#u,h=Math.ceil(this.#st/u),d=this.#K/l,p=Math.round(d-h),m=p*u,g=(p+2*h)*u,f=e?n*u/l:m,b=e?i*u/l:g,v=""===t(1)?10:5;a>1&&this.#tt.setAttribute("d",te(m,g,u/a,f,b,v*r)),this.#et.style.stroke=c,this.#et.setAttribute("d",te(m,g,u,f,b,v)),this.#nt.innerHTML=function(t,e,n,i,o,r,a,l){const u=[];tt),n)),e=Math.min(e,a);const c=Math.max(0,-Math.log10(i));for(let s=t;s<=e;s+=n)u.push(`${h=s/n*i,l(h.toFixed(c))}`);var h;return u.join("\n")}(m,g,u,l,this.#at,f,b,t),this.#Q.setAttribute("transform",`translate(${-this.#K*u/l} 0)`),this.#Z.classList.toggle("muigui-slider-up","up"===o)}updateDisplay(t){this.#K=t,this.#lt()}setOptions(t){return a(this.#u,t),this}}class ne extends b{#Z;#_;#P;#K=[];constructor(t){super(e("div",{innerHTML:'\n\n \n \n \n \n \n\n',className:"muigui-no-scroll"}));const n=e=>{const{width:n,height:i}=this.#Z.getBoundingClientRect(),o=2*e.nx-1,s=2*e.ny-1;t.setValue([o*n*.5,s*i*.5])};zt(this.domElement,{onDown:n,onMove:n}),this.#Z=this.$("svg"),this.#_=this.$("#muigui-arrow"),this.#P=this.$("#muigui-circle"),Qt(this.#Z,.5,.5,(()=>this.#ut))}#ut(){const[t,e]=this.#K;this.#_.setAttribute("d",`M0,0L${t},${e}`),this.#P.setAttribute("transform",`translate(${t}, ${e})`)}updateDisplay(t){this.#K[0]=t[0],this.#K[1]=t[1],this.#ut()}}return jt.ColorChooser=class extends Gt{constructor(t,e){super(t,e,"muigui-color-chooser"),this.addTop(new G(this)),this.addBottom(new Bt(this)),this.updateDisplay()}},jt.Direction=class extends Gt{#u;constructor(t,e,n){super(t,e,"muigui-direction"),this.#u=n,this.addTop(new U(this,F)),this.addBottom(new Kt(this,n)),this.updateDisplay()}},jt.RadioGrid=class extends I{constructor(t,e,n){super(t,e,"muigui-radio-grid");const i="number"==typeof this.getValue(),{keyValues:o,cols:s=3}=n,r=T(o,i);this.add(new Xt(this,r,s)),this.updateDisplay()}},jt.Range=B,jt.Select=P,jt.Slider=class extends I{constructor(t,e,n={}){super(t,e,"muigui-slider"),this.add(new ee(this,n)),this.add(new U(this,n)),this.updateDisplay()}},jt.TextNumber=O,jt.Vec2=class extends Gt{constructor(t,e){super(t,e,"muigui-vec2");const n=t=>({setValue:e=>{const n=this.getValue();n[t]=e,this.setValue(n)},setFinalValue:e=>{const n=this.getValue();n[t]=e,this.setFinalValue(n)}});this.addTop(new U(n(0),{converters:{to:t=>t[0],from:L.from}})),this.addTop(new U(n(1),{converters:{to:t=>t[1],from:L.from}})),this.addBottom(new ne(this)),this.updateDisplay()}},jt})); +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).GUI=e()}(this,(function(){"use strict";var t={default:'\n.muigui {\n --bg-color: #ddd;\n --color: #222;\n --contrast-color: #eee;\n --value-color: #145 ;\n --value-bg-color: #eeee;\n --disabled-color: #999;\n --menu-bg-color: #f8f8f8;\n --menu-sep-color: #bbb;\n --hover-bg-color: #999;\n --focus-color: #68C;\n --range-color: #888888;\n --invalid-color: #FF0000;\n --selected-color: rgb(255, 255, 255, 0.9);\n\n --button-bg-color: var(--value-bg-color);\n\n --range-left-color: var(--value-color);\n --range-right-color: var(--value-bg-color); \n --range-right-hover-color: var(--hover-bg-color);\n\n color: var(--color);\n background-color: var(--bg-color);\n}\n\n@media (prefers-color-scheme: dark) {\n .muigui {\n --bg-color: #222222;\n --color: #dddddd;\n --contrast-color: #000;\n --value-color: #43e5f7;\n --value-bg-color: #444444;\n --disabled-color: #666666;\n --menu-bg-color: #080808;\n --menu-sep-color: #444444;\n --hover-bg-color: #666666;\n --focus-color: #88AAFF;\n --range-color: #888888;\n --invalid-color: #FF6666;\n --selected-color: rgba(255, 255, 255, 0.3);\n\n --button-bg-color: var(--value-bg-color);\n\n --range-left-color: var(--value-color);\n --range-right-color: var(--value-bg-color); \n --range-right-hover-color: var(--hover-bg-color);\n\n color: var(--color);\n background-color: var(--bg-color);\n }\n}\n\n.muigui {\n --width: 250px;\n --label-width: 45%;\n --number-width: 40%;\n\n\n --font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;\n --font-size: 11px;\n --font-family-mono: Menlo, Monaco, Consolas, "Droid Sans Mono", monospace;\n --font-size-mono: 11px;\n\n --line-height: 1.7em;\n --border-radius: 0px;\n\n width: var(--width);\n font-family: var(--font-family);\n font-size: var(--font-size);\n box-sizing: border-box;\n line-height: 100%;\n}\n.muigui * {\n box-sizing: inherit;\n}\n\n.muigui-no-scroll {\n touch-action: none;\n}\n.muigui-no-h-scroll {\n touch-action: pan-y;\n}\n.muigui-no-v-scroll {\n touch-action: pan-x;\n}\n\n.muigui-invalid-value {\n background-color: red !important;\n color: white !important;\n}\n\n.muigui-grid {\n display: grid;\n}\n.muigui-rows {\n display: flex;\n flex-direction: column;\n\n min-height: 20px;\n border: 2px solid red;\n}\n.muigui-columns {\n display: flex;\n flex-direction: row;\n\n height: 20px;\n border: 2px solid green;\n}\n.muigui-rows>*,\n.muigui-columns>* {\n flex: 1 1 auto;\n align-items: stretch;\n min-height: 0;\n min-width: 0;\n}\n\n.muigui-row {\n border: 2px solid yellow;\n min-height: 10px\n}\n.muigui-column {\n border: 2px solid lightgreen;\n}\n\n/* -------- */\n\n.muigui-show { /* */ }\n.muigui-hide { \n display: none !important;\n}\n.muigui-disabled {\n pointer-events: none;\n --color: var(--disabled-color) !important;\n --value-color: var(--disabled-color) !important;\n --range-left-color: var(--disabled-color) !important;\n}\n\n.muigui canvas,\n.muigui svg {\n display: block;\n border-radius: var(--border-radius);\n}\n.muigui canvas {\n background-color: var(--value-bg-color);\n}\n\n.muigui-controller {\n min-width: 0;\n min-height: var(--line-height);\n}\n.muigui-root,\n.muigui-menu {\n display: flex;\n flex-direction: column;\n position: relative;\n user-select: none;\n height: fit-content;\n margin: 0;\n padding-bottom: 0.1em;\n border-radius: var(--border-radius);\n}\n.muigui-menu {\n border-bottom: 1px solid var(--menu-sep-color);\n}\n\n.muigui-root>button:nth-child(1),\n.muigui-menu>button:nth-child(1) {\n border-top: 1px solid var(--menu-sep-color);\n border-bottom: 1px solid var(--menu-sep-color);\n position: relative;\n text-align: left;\n color: var(--color);\n background-color: var(--menu-bg-color);\n min-height: var(--line-height);\n padding-top: 0.2em;\n padding-bottom: 0.2em;\n cursor: pointer;\n border-radius: var(--border-radius);\n}\n.muigui-root>div:nth-child(2),\n.muigui-menu>div:nth-child(2) {\n flex: 1 1 auto;\n}\n\n.muigui-controller {\n margin-left: 0.2em;\n margin-right: 0.2em;\n}\n.muigui-root.muigui-controller,\n.muigui-menu.muigui-controller {\n margin-left: 0;\n margin-right: 0;\n}\n.muigui-controller>*:nth-child(1) {\n flex: 1 0 var(--label-width);\n min-width: 0;\n white-space: pre;\n}\n.muigui-controller>label:nth-child(1) {\n place-content: center start;\n display: inline-grid;\n overflow: hidden;\n}\n.muigui-controller>*:nth-child(2) {\n flex: 1 1 75%;\n min-width: 0;\n}\n\n/* -----------------------------------------\n a label controller is [[label][value]]\n*/\n\n.muigui-label-controller {\n display: flex;\n margin: 0.4em 0 0.4em 0;\n word-wrap: initial;\n align-items: stretch;\n}\n\n.muigui-value {\n display: flex;\n align-items: stretch;\n}\n.muigui-value>* {\n flex: 1 1 auto;\n min-width: 0;\n}\n.muigui-value>*:nth-child(1) {\n flex: 1 1 calc(100% - var(--number-width));\n}\n.muigui-value>*:nth-child(2) {\n flex: 1 1 var(--number-width);\n margin-left: 0.2em;\n}\n\n/* fix! */\n.muigui-open>button>label::before,\n.muigui-closed>button>label::before {\n width: 1.25em;\n height: var(--line-height);\n display: inline-grid;\n place-content: center start;\n pointer-events: none;\n}\n.muigui-open>button>label::before {\n content: "ⓧ"; /*"▼";*/\n}\n.muigui-closed>button>label::before {\n content: "⨁"; /*"▶";*/\n}\n.muigui-open>*:nth-child(2) {\n transition: max-height 0.2s ease-out,\n opacity 0.5s ease-out;\n max-height: 100vh;\n overflow: auto;\n opacity: 1;\n}\n\n.muigui-closed>*:nth-child(2) {\n transition: max-height 0.2s ease-out,\n opacity 1s;\n max-height: 0;\n opacity: 0;\n overflow: hidden;\n}\n\n/* ---- popdown ---- */\n\n.muigui-pop-down-top {\n display: flex;\n}\n/* fix? */\n.muigui-value>*:nth-child(1).muigui-pop-down-top {\n flex: 0;\n}\n.muigui-pop-down-bottom {\n\n}\n\n.muigui-pop-down-values {\n min-width: 0;\n display: flex;\n}\n.muigui-pop-down-values>* {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.muigui-value.muigui-pop-down-controller {\n flex-direction: column;\n}\n\n.muigui-pop-down-top input[type=checkbox] {\n -webkit-appearance: none;\n appearance: none;\n width: auto;\n color: var(--value-color);\n background-color: var(--value-bg-color);\n cursor: pointer;\n\n display: grid;\n place-content: center;\n margin: 0;\n font: inherit;\n color: currentColor;\n width: 1.7em;\n height: 1.7em;\n transform: translateY(-0.075em);\n}\n\n.muigui-pop-down-top input[type=checkbox]::before {\n content: "+";\n display: grid;\n place-content: center;\n border-radius: calc(var(--border-radius) + 2px);\n border-left: 1px solid rgba(255,255,255,0.3);\n border-top: 1px solid rgba(255,255,255,0.3);\n border-bottom: 1px solid rgba(0,0,0,0.2);\n border-right: 1px solid rgba(0,0,0,0.2);\n background-color: var(--range-color);\n color: var(--value-bg-color);\n width: calc(var(--line-height) - 4px);\n height: calc(var(--line-height) - 4px);\n}\n\n.muigui-pop-down-top input[type=checkbox]:checked::before {\n content: "X";\n}\n\n\n/* ---- select ---- */\n\n.muigui select,\n.muigui option,\n.muigui input,\n.muigui button {\n color: var(--value-color);\n background-color: var(--value-bg-color);\n font-family: var(--font-family);\n font-size: var(--font-size);\n border: none;\n margin: 0;\n border-radius: var(--border-radius);\n}\n.muigui select {\n appearance: none;\n margin: 0;\n margin-left: 0; /*?*/\n overflow: hidden; /* Safari */\n}\n\n.muigui select:focus,\n.muigui input:focus,\n.muigui button:focus {\n outline: 1px solid var(--focus-color);\n}\n\n.muigui select:hover,\n.muigui option:hover,\n.muigui input:hover,\n.muigui button:hover {\n background-color: var(--hover-bg-color); \n}\n\n/* ------ [ label ] ------ */\n\n.muigui-label {\n border-top: 1px solid var(--menu-sep-color);\n border-bottom: 1px solid var(--menu-sep-color);\n padding-top: 0.4em;\n padding-bottom: 0.3em;\n place-content: center start;\n background-color: var(--menu-bg-color);\n white-space: pre;\n border-radius: var(--border-radius);\n}\n\n/* ------ [ divider] ------ */\n\n.muigui-divider {\n min-height: 6px;\n border-top: 2px solid var(--menu-sep-color);\n margin-top: 6px;\n}\n\n/* ------ [ button ] ------ */\n\n.muigui-button {\n display: grid;\n\n}\n.muigui-button button {\n border: none;\n color: var(--value-color);\n background-color: var(--button-bg-color);\n cursor: pointer;\n place-content: center center;\n}\n\n/* ------ [ color ] ------ */\n\n.muigui-color>div {\n overflow: hidden;\n position: relative;\n margin-left: 0;\n margin-right: 0; /* why? */\n max-width: var(--line-height);\n border-radius: var(--border-radius);\n}\n\n.muigui-color>div:focus-within {\n outline: 1px solid var(--focus-color);\n}\n\n.muigui-color input[type=color] {\n border: none;\n padding: 0;\n background: inherit;\n cursor: pointer;\n position: absolute;\n width: 200%;\n left: -10px;\n top: -10px;\n height: 200%;\n}\n.muigui-disabled canvas,\n.muigui-disabled svg,\n.muigui-disabled img,\n.muigui-disabled .muigui-color input[type=color] {\n opacity: 0.2;\n}\n\n/* ------ [ checkbox ] ------ */\n\n.muigui-checkbox>label:nth-child(2) {\n display: grid;\n place-content: center start;\n margin: 0;\n}\n\n.muigui-checkbox input[type=checkbox] {\n -webkit-appearance: none;\n appearance: none;\n width: auto;\n color: var(--value-color);\n background-color: var(--value-bg-color);\n cursor: pointer;\n\n display: grid;\n place-content: center;\n margin: 0;\n font: inherit;\n color: currentColor;\n width: 1.7em;\n height: 1.7em;\n transform: translateY(-0.075em);\n}\n\n.muigui-checkbox input[type=checkbox]::before {\n content: "";\n color: var(--value-color);\n display: grid;\n place-content: center;\n}\n\n.muigui-checkbox input[type=checkbox]:checked::before {\n content: "✔";\n}\n\n.muigui input[type=number]::-webkit-inner-spin-button, \n.muigui input[type=number]::-webkit-outer-spin-button { \n -webkit-appearance: none;\n appearance: none;\n margin: 0; \n}\n.muigui input[type=number] {\n -moz-appearance: textfield;\n}\n\n/* ------ [ radio grid ] ------ */\n\n.muigui-radio-grid>div {\n display: grid;\n gap: 2px;\n}\n\n.muigui-radio-grid input {\n appearance: none;\n display: none;\n}\n\n.muigui-radio-grid button {\n color: var(--color);\n width: 100%;\n text-align: left;\n}\n\n.muigui-radio-grid input:checked + button {\n color: var(--value-color);\n background-color: var(--selected-color);\n}\n\n/* ------ [ color-chooser ] ------ */\n\n.muigui-color-chooser-cursor {\n stroke-width: 1px;\n stroke: white;\n fill: none;\n}\n.muigui-color-chooser-circle {\n stroke-width: 1px;\n stroke: white;\n fill: none;\n}\n\n\n/* ------ [ vec2 ] ------ */\n\n.muigui-vec2 svg {\n background-color: var(--value-bg-color);\n}\n\n.muigui-vec2-axis {\n stroke: 1px;\n stroke: var(--focus-color);\n}\n\n.muigui-vec2-line {\n stroke-width: 1px;\n stroke: var(--value-color);\n fill: var(--value-color);\n}\n\n/* ------ [ direction ] ------ */\n\n.muigui-direction svg {\n background-color: rgba(0,0,0,0.2);\n}\n\n.muigui-direction:focus-within svg {\n outline: none;\n}\n.muigui-direction-range {\n fill: var(--value-bg-color);\n}\n.muigui-direction svg:focus {\n outline: none;\n}\n.muigui-direction svg:focus .muigui-direction-range {\n stroke-width: 0.5px;\n stroke: var(--focus-color);\n}\n\n.muigui-direction-arrow {\n fill: var(--value-color);\n}\n\n/* ------ [ slider ] ------ */\n\n.muigui-slider>div {\n display: flex;\n align-items: stretch;\n height: var(--line-height);\n}\n.muigui-slider svg {\n flex: 1 1 auto;\n}\n.muigui-slider .muigui-slider-up #muigui-orientation {\n transform: scale(1, -1) translateY(-100%);\n}\n\n.muigui-slider .muigui-slider-up #muigui-number-orientation {\n transform: scale(1,-1);\n}\n\n.muigui-ticks {\n stroke: var(--range-color);\n}\n.muigui-thicks {\n stroke: var(--color);\n stroke-width: 2px;\n}\n.muigui-svg-text {\n fill: var(--color);\n font-size: 7px;\n}\n.muigui-mark {\n fill: var(--value-color);\n}\n\n/* ------ [ range ] ------ */\n\n\n.muigui-range input[type=range] {\n -webkit-appearance: none;\n appearance: none;\n background-color: transparent;\n}\n\n.muigui-range input[type=range]::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n border-radius: calc(var(--border-radius) + 2px);\n border-left: 1px solid rgba(255,255,255,0.3);\n border-top: 1px solid rgba(255,255,255,0.3);\n border-bottom: 1px solid rgba(0,0,0,0.2);\n border-right: 1px solid rgba(0,0,0,0.2);\n background-color: var(--range-color);\n margin-top: calc((var(--line-height) - 2px) / -2);\n width: calc(var(--line-height) - 2px);\n height: calc(var(--line-height) - 2px);\n}\n\n.muigui-range input[type=range]::-webkit-slider-runnable-track {\n -webkit-appearance: none;\n appearance: none;\n border: 1px solid var(--menu-sep-color);\n height: 2px;\n}\n\n\n/* dat.gui style - doesn\'t work on Safari iOS */\n\n/*\n.muigui-range input[type=range] {\n cursor: ew-resize;\n overflow: hidden;\n}\n\n.muigui-range input[type=range] {\n -webkit-appearance: none;\n appearance: none;\n background-color: var(--range-right-color);\n margin: 0;\n}\n.muigui-range input[type=range]:hover {\n background-color: var(--range-right-hover-color);\n}\n\n.muigui-range input[type=range]::-webkit-slider-runnable-track {\n -webkit-appearance: none;\n appearance: none;\n height: max-content;\n color: var(--range-left-color);\n margin-top: -1px;\n}\n\n.muigui-range input[type=range]::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 0px;\n height: max-content;\n box-shadow: -1000px 0 0 1000px var(--range-left-color);\n}\n*/\n\n/* FF */\n/*\n.muigui-range input[type=range]::-moz-slider-progress {\n background-color: var(--range-left-color); \n}\n.muigui-range input[type=range]::-moz-slider-thumb {\n height: max-content;\n width: 0;\n border: none;\n box-shadow: -1000px 0 0 1000px var(--range-left-color);\n box-sizing: border-box;\n}\n*/\n\n/* ---------------------------------------------------------- */\n\n/* needs to be at bottom to take precedence */\n.muigui-auto-place {\n max-height: 100%;\n position: fixed;\n top: 0;\n right: 15px;\n z-index: 100001;\n}\n\n',themes:{default:"",float:"\n :root {\n color-scheme: light dark,\n }\n\n .muigui {\n --width: 400px;\n --bg-color: initial;\n --label-width: 25%;\n }\n\n input,\n .muigui-label-controller>label {\n text-shadow:\n -1px -1px 0 var(--contrast-color),\n 1px -1px 0 var(--contrast-color),\n -1px 1px 0 var(--contrast-color),\n 1px 1px 0 var(--contrast-color);\n }\n\n .muigui-controller > label:nth-child(1) {\n place-content: center end;\n margin-right: 1em;\n }\n\n .muigui-value > :nth-child(2) {\n margin-left: 1em;\n }\n\n .muigui-root>*:nth-child(1) {\n display: none;\n }\n\n .muigui-range input[type=range]::-webkit-slider-thumb {\n border-radius: 1em;\n }\n\n .muigui-range input[type=range]::-webkit-slider-runnable-track {\n -webkit-appearance: initial;\n appearance: none;\n border: 1px solid rgba(0, 0, 0, 0.25);\n height: 2px;\n }\n\n .muigui-colors {\n --value-color: var(--color );\n --value-bg-color: rgba(0, 0, 0, 0.1);\n --disabled-color: #cccccc;\n --menu-bg-color: rgba(0, 0, 0, 0.1);\n --menu-sep-color: #bbbbbb;\n --hover-bg-color: rgba(0, 0, 0, 0);\n --invalid-color: #FF0000;\n --selected-color: rgba(0, 0, 0, 0.3);\n --range-color: rgba(0, 0, 0, 0.125);\n }\n"}};function e(t,e={},n=[]){const i=document.createElement(t);return function(t,e,n){for(const[n,i]of Object.entries(e))if("function"==typeof i&&n.startsWith("on")){const e=n.substring(2).toLowerCase();t.addEventListener(e,i,{passive:!1})}else if("object"==typeof i)for(const[e,o]of Object.entries(i))t[n][e]=o;else void 0===t[n]?t.setAttribute(n,i):t[n]=i;for(const e of n)t.appendChild(e)}(i,e,n),i}function n(t,e){const n=t.indexOf(e);return n&&t.splice(n,1),t}function i(t,e,n){return Math.max(e,Math.min(n,t))}const o="undefined"!=typeof SharedArrayBuffer?function(t){return t&&t.buffer&&(t.buffer instanceof ArrayBuffer||t.buffer instanceof SharedArrayBuffer)}:function(t){return t&&t.buffer&&t.buffer instanceof ArrayBuffer},s=(t,e,n)=>Math.round(e(t)/n)/(1/n),r=(t,e)=>(t%e+e)%e;function a(t,e){for(const n in e)n in t&&(t[n]=e[n]);return t}const l=(t,e,n,i,o)=>(t-e)*(o-i)/(n-e)+i,u=({from:t,to:e})=>({to:n=>l(n,...t,...e),from:n=>[!0,l(n,...e,...t)]}),c=({from:t,to:e,step:n})=>({min:e[0],max:e[1],...n&&{step:n},converters:u({from:t,to:e})}),h={to:t=>t,from:t=>[!0,t]};function d(t,e,n,i,o){const{converters:{from:s}=h}=o,{min:r,max:a}=o,l=o.minRange||0,u=s(l)[1],c=t.add(e,n,{...o,min:r,max:a-l}).onChange((t=>{d.setValue(Math.min(a,Math.max(t+u,e[i])))})),d=t.add(e,i,{...o,min:r+l,max:a}).onChange((t=>{c.setValue(Math.max(r,Math.min(t-u,e[n])))}));return[c,d]}class p{#t;#e=[];constructor(t){this.domElement=t,this.#t=t}addElem(t){return this.#t.appendChild(t),t}removeElem(t){return this.#t.removeChild(t),t}pushSubElem(t){this.#t.appendChild(t),this.#t=t}popSubElem(){this.#t=this.#t.parentElement}add(t){return this.#e.push(t),this.addElem(t.domElement),t}remove(t){return this.removeElem(t.domElement),n(this.#e,t),t}pushSubView(t){this.pushSubElem(t.domElement)}popSubView(){this.popSubElem()}setOptions(t){for(const e of this.#e)e.setOptions(t)}updateDisplayIfNeeded(t,e){for(const n of this.#e)n.updateDisplayIfNeeded(t,e);return this}$(t){return this.domElement.querySelector(t)}}class m extends p{#n;#i;#o;constructor(t){super(e("div",{className:"muigui-controller"})),this.#n=[],this.#i=[],t&&this.domElement.classList.add(t)}get parent(){return this.#o}setParent(t){this.#o=t,this.enable(!this.disabled())}show(t=!0){return this.domElement.classList.toggle("muigui-hide",!t),this.domElement.classList.toggle("muigui-show",t),this}hide(){return this.show(!1)}disabled(){return!!this.domElement.closest(".muigui-disabled")}enable(t=!0){return this.domElement.classList.toggle("muigui-disabled",!t),["input","button","select","textarea"].forEach((t=>{this.domElement.querySelectorAll(t).forEach((t=>{const e=!!t.closest(".muigui-disabled");t.disabled=e}))})),this}disable(t=!0){return this.enable(!t)}onChange(t){return this.removeChange(t),this.#n.push(t),this}removeChange(t){return n(this.#n,t),this}onFinishChange(t){return this.removeFinishChange(t),this.#i.push(t),this}removeFinishChange(t){return n(this.#i,t),this}#s(t,e){for(const n of t)n.call(this,e)}emitChange(t,e,n){this.#s(this.#n,t),this.#o&&(void 0===e?this.#o.emitChange(t):this.#o.emitChange({object:e,property:n,value:t,controller:this}))}emitFinalChange(t,e,n){this.#s(this.#i,t),this.#o&&(void 0===e?this.#o.emitChange(t):this.#o.emitFinalChange({object:e,property:n,value:t,controller:this}))}getColors(){const t=t=>t.replace(/-([a-z])/g,((t,e)=>e.toUpperCase())),n=e("div");this.domElement.appendChild(n);const i=Object.fromEntries(["color","bg-color","value-color","value-bg-color","hover-bg-color","menu-bg-color","menu-sep-color","disabled-color"].map((e=>{n.style.color=`var(--${e})`;const i=getComputedStyle(n);return[t(e),i.color]})));return n.remove(),i}}class g extends m{#r;#a;#l;#u={name:""};constructor(t,n,i={}){super("muigui-button",""),this.#r=t,this.#a=n,this.#l=this.addElem(e("button",{type:"button",onClick:()=>{this.#r[this.#a](this)}})),this.setOptions({name:n,...i})}setOptions(t){a(this.#u,t);const{name:e}=this.#u;this.#l.textContent=e}}function f(t,e){if(t.length!==e.length)return!1;for(let n=0;n{t.setValue(i.checked)},onChange:()=>{t.setFinalValue(i.checked)}});super(e("label",{},[i]))}updateDisplay(t){this.domElement.checked=t}}const x=[],w=new Set;let y,k;function E(){y=void 0,k=!0;for(const t of x)w.has(t)||t();k=!1,w.size&&(k?C():(w.forEach((t=>{n(x,t)})),w.clear())),C()}function C(){!y&&x.length&&(y=requestAnimationFrame(E))}let $=0;function V(){return"muigui-"+ ++$}class M extends p{constructor(t=""){super(e("div",{className:"muigui-value"})),t&&this.domElement.classList.add(t)}}class S extends m{#b;#v;constructor(t="",n=""){super("muigui-label-controller"),this.#b=V(),this.#v=e("label",{for:this.#b}),this.domElement.appendChild(this.#v),this.pushSubView(new M(t)),this.name(n)}get id(){return this.#b}name(t){return this.#v.title===this.#v.textContent&&(this.#v.title=t),this.#v.textContent=t,this}tooltip(t){this.#v.title=t}}class I extends S{#r;#a;#x;#w;#e;#y;constructor(t,e,n=""){super(n,e),this.#r=t,this.#a=e,this.#x=this.getValue(),this.#w=!1,this.#e=[]}get initialValue(){return this.#x}get object(){return this.#r}get property(){return this.#a}add(t){return this.#e.push(t),super.add(t),this.updateDisplay(),t}#k(t,e){let n=!1;if("object"==typeof t){const e=this.#r[this.#a];if(Array.isArray(t)||o(t))for(let i=0;i=0&&x.splice(e,1)}(this.#y)),this}}class D extends I{constructor(t,e){super(t,e,"muigui-checkbox");const n=this.id;this.add(new v(this,n)),this.updateDisplay()}}const F={to:t=>t,from:t=>[!0,t]},L={to:t=>t.toString(),from:t=>{const e=parseFloat(t);return[!Number.isNaN(e),e]}},N={radToDeg:u({to:[0,180],from:[0,Math.PI]})};function A(){let t=0;return function(e,n,i=5){t-=e.deltaY*n/i;const o=Math.floor(Math.abs(t)/n)*Math.sign(t)*n;return t-=o,o}}class U extends b{#E;#C;#$;#V;#u={step:.01,converters:L,min:Number.NEGATIVE_INFINITY,max:Number.POSITIVE_INFINITY};constructor(t,n){const o=t.setValue.bind(t),r=t.setFinalValue.bind(t),a=A();super(e("input",{type:"number",onInput:()=>this.#M(o,!0),onChange:()=>this.#M(r,!1),onWheel:e=>{e.preventDefault();const{min:n,max:o,step:r}=this.#u,l=a(e,r),u=parseFloat(this.domElement.value),c=i(s(u+l,(t=>t),r),n,o);t.setValue(c)}})),this.setOptions(n)}#M(t,e){const n=parseFloat(this.domElement.value),[o,s]=this.#C(n);let r;if(o&&!Number.isNaN(n)){const{min:n,max:o}=this.#u;r=s>=n&&s<=o,this.#V=e,t(i(s,n,o))}this.domElement.classList.toggle("muigui-invalid-value",!o||!r)}updateDisplay(t){this.#V||(this.domElement.value=s(t,this.#E,this.#$)),this.#V=!1}setOptions(t){a(this.#u,t);const{step:e,converters:{to:n,from:i}}=this.#u;return this.#E=n,this.#C=i,this.#$=e,this}}class O extends I{#S;#$;constructor(t,e,n={}){super(t,e,"muigui-checkbox"),this.#S=this.add(new U(this,n)),this.updateDisplay()}}class j extends b{#I;constructor(t,n){const i=[];super(e("select",{onChange:()=>{t.setFinalValue(this.#I[this.domElement.selectedIndex])}},n.map((([t,n])=>(i.push(n),e("option",{textContent:t})))))),this.#I=i}updateDisplay(t){const e=this.#I.indexOf(t);this.domElement.selectedIndex=e}}function T(t,e){return Array.isArray(t)?Array.isArray(t[0])?t:e?t.map(((t,e)=>[t,e])):t.map((t=>[t,t])):[...Object.entries(t)]}class P extends I{constructor(t,e,n){super(t,e,"muigui-select");const i="number"==typeof this.getValue(),{keyValues:o}=n,s=T(o,i);this.add(new j(this,s)),this.updateDisplay()}}class z extends b{#E;#C;#$;#V;#u={step:.01,min:0,max:1,converters:F};constructor(t,n){const o=A();super(e("input",{type:"range",onInput:()=>{this.#V=!0;const{min:e,max:n,step:o}=this.#u,r=parseFloat(this.domElement.value),a=i(s(r,(t=>t),o),e,n),[l,u]=this.#C(a);l&&t.setValue(u)},onChange:()=>{this.#V=!0;const{min:e,max:n,step:o}=this.#u,r=parseFloat(this.domElement.value),a=i(s(r,(t=>t),o),e,n),[l,u]=this.#C(a);l&&t.setFinalValue(u)},onWheel:e=>{e.preventDefault();const[n,r]=this.#C(parseFloat(this.domElement.value));if(!n)return;const{min:a,max:l,step:u}=this.#u,c=o(e,u),h=i(s(r+c,(t=>t),u),a,l);t.setValue(h)}})),this.setOptions(n)}updateDisplay(t){this.#V||(this.domElement.value=s(t,this.#E,this.#$)),this.#V=!1}setOptions(t){a(this.#u,t);const{step:e,min:n,max:i,converters:{to:o,from:s}}=this.#u;return this.#E=o,this.#C=s,this.#$=e,this.domElement.step=e,this.domElement.min=n,this.domElement.max=i,this}}class B extends I{constructor(t,e,n){super(t,e,"muigui-range"),this.add(new z(this,n)),this.add(new U(this,n))}}class G extends b{#E;#C;#V;#u={converters:F};constructor(t,n){const i=t.setValue.bind(t),o=t.setFinalValue.bind(t);super(e("input",{type:"text",onInput:()=>this.#M(i,!0),onChange:()=>this.#M(o,!1)})),this.setOptions(n)}#M(t,e){const[n,i]=this.#C(this.domElement.value);n&&(this.#V=e,t(i)),this.domElement.style.color=n?"":"var(--invalid-color)"}updateDisplay(t){this.#V||(this.domElement.value=this.#E(t),this.domElement.style.color=""),this.#V=!1}setOptions(t){a(this.#u,t);const{converters:{to:e,from:n}}=this.#u;return this.#E=e,this.#C=n,this}}class H extends I{constructor(t,e){super(t,e,"muigui-checkbox"),this.add(new G(this)),this.updateDisplay()}}class R extends p{constructor(t,n){super(e(t,{className:n}))}}class Y extends S{#D;constructor(){super("muigui-canvas"),this.#D=this.add(new R("canvas","muigui-canvas")).domElement}get canvas(){return this.#D}}const W=(t,e,n)=>Math.max(e,Math.min(n,t)),q=t=>+t.toFixed(3),_=t=>parseInt(t.substring(1,3),16)<<16|parseInt(t.substring(3,5),16)<<8|parseInt(t.substring(5,7),16),J=t=>[parseInt(t.substring(1,3),16),parseInt(t.substring(3,5),16),parseInt(t.substring(5,7),16)],K=t=>`#${Array.from(t).map((t=>t.toString(16).padStart(2,"0"))).join("")}`,X=t=>J(t).map((t=>q(t/255))),Z=t=>K(Array.from(t).map((t=>Math.round(W(255*t,0,255))))),Q=t=>({r:parseInt(t.substring(1,3),16)/255,g:parseInt(t.substring(3,5),16)/255,b:parseInt(t.substring(5,7),16)/255}),tt=t=>W(Math.round(255*t),0,255).toString(16).padStart(2,"0"),et=t=>`rgb(${J(t).join(", ")})`,nt=/^\s*rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/,it=t=>{const e=rt(J(t)).map((t=>(t=>+t.toFixed(0))(t)));return`hsl(${e[0]}, ${e[1]}%, ${e[2]}%)`},ot=/^\s*hsl\(\s*(\d+)(?:deg|)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)\s*$/,st=(t,e)=>(t%e+e)%e;const rt=t=>{const[e,n,i]=function([t,e,n]){const i=Math.max(t,e,n),o=Math.min(t,e,n),s=.5*(o+i),r=i-o;let a=0,l=0;if(0!==r)switch(l=0===s||1===s?0:(i-s)/Math.min(s,1-s),i){case t:a=(e-n)/r+(et/255)));return[360*e,100*n,100*i]};function at([t,e,n]){return e=W(e,0,1),n=W(n,0,1),[t,t+2/3,t+1/3].map((t=>{return i=1,o=W(Math.abs(6*(t=>t>=0?t%1:1-t%1)(t)-3)-1,0,1),(i+(o-i)*e)*n;var i,o}))}const lt=t=>Math.round(1e3*t)/1e3;function ut([t,e,n]){const i=n>e?[n,e,-1,2/3]:[e,n,0,-1/3],o=i[0]>t?[i[0],i[1],i[3],t]:[t,i[1],i[2],i[0]],s=o[0]-Math.min(o[3],o[1]);return[Math.abs(o[2]+(o[3]-o[1])/(6*s+Number.EPSILON)),s/(o[0]+Number.EPSILON),o[0]].map(lt)}window.hsv01ToRGBFloat=at,window.rgbFloatToHSV01=ut;const ct=[{re:/^#(?:[0-9a-f]){6}$/i,format:"hex6"},{re:/^(?:[0-9a-f]){6}$/i,format:"hex6-no-hash"},{re:/^#(?:[0-9a-f]){3}$/i,format:"hex3"},{re:/^(?:[0-9a-f]){3}$/i,format:"hex3-no-hash"},{re:nt,format:"css-rgb"},{re:ot,format:"css-hsl"}];function ht(t){switch(typeof t){case"number":return"uint32-rgb";case"string":{const e=function(t){for(const e of ct)if(e.re.test(t))return e}(t.trim());if(e)return e.format;break}case"object":if(t instanceof Uint8Array||t instanceof Uint8ClampedArray){if(3===t.length)return"uint8-rgb"}else if(t instanceof Float32Array){if(3===t.length)return"float-rgb"}else if(Array.isArray(t)){if(3===t.length)return"float-rgb"}else if("r"in t&&"g"in t&&"b"in t)return"object-rgb"}throw new Error(`unknown color format: ${t}`)}function dt(t){return t.trim(t)}function pt(t){return t[1]===t[2]&&t[3]===t[4]&&t[5]===t[6]?`#${t[1]}${t[3]}${t[5]}`:t}const mt=/^(#|)([0-9a-f]{3})$/i;function gt(t){const e=mt.exec(t);if(e){const[,,t]=e;return"#"+`${(n=t)[0]}${n[0]}${n[1]}${n[1]}${n[2]}${n[2]}`}var n;return t}function ft(t){return pt(dt(t))}const bt=t=>{const e=nt.exec(t);if(!e)return[!1];const n=[e[1],e[2],e[3]].map((t=>parseInt(t)));return[!n.find((t=>t>255)),`rgb(${n.join(", ")})`]},vt=t=>{const e=ot.exec(t);if(!e)return[!1];const n=[e[1],e[2],e[3]].map((t=>parseFloat(t)));return[!n.find((t=>Number.isNaN(t))),`hsl(${n[0]}, ${n[1]}%, ${n[2]}%)`]},xt=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*$/,wt=/^\s*(?:0x){0,1}([0-9a-z]{1,6})\s*$/i,yt=/^\s*#[a-f0-9]{6}\s*$|^\s*#[a-f0-9]{3}\s*$/i,kt=/^\s*[a-f0-9]{6}\s*$/i,Et={hex6:{color:{from:t=>[!0,t],to:dt},text:{from:t=>[yt.test(t),t.trim()],to:t=>t}},hex3:{color:{from:t=>[!0,ft(t)],to:gt},text:{from:t=>[yt.test(t),pt(t.trim())],to:t=>t}},"hex6-no-hash":{color:{from:t=>[!0,t.substring(1)],to:t=>`#${dt(t)}`},text:{from:t=>[kt.test(t),t.trim()],to:t=>t}},"hex3-no-hash":{color:{from:t=>[!0,ft(t).substring(1)],to:gt},text:{from:t=>[kt.test(t),pt(t.trim())],to:t=>t}},"uint32-rgb":{color:{from:t=>[!0,_(t)],to:t=>`#${Math.round(t).toString(16).padStart(6,"0")}`},text:{from:t=>(t=>{const e=wt.exec(t);return e?[!0,parseInt(e[1],16)]:[!1]})(t),to:t=>`0x${t.toString(16).padStart(6,"0")}`}},"uint8-rgb":{color:{from:t=>[!0,J(t)],to:K},text:{from:t=>{const e=xt.exec(t);if(!e)return[!1];const n=[e[1],e[2],e[3]].map((t=>parseInt(t)));return[!n.find((t=>t>255)),n]},to:t=>t.join(", ")}},"float-rgb":{color:{from:t=>[!0,X(t)],to:Z},text:{from:t=>{const e=t.split(",").map((t=>t.trim())),n=e.map((t=>parseFloat(t)));if(3!==n.length)return[!1];const i=e.findIndex((t=>isNaN(t)));return[i<0,n.map((t=>q(t)))]},to:t=>Array.from(t).map((t=>q(t))).join(", ")}},"object-rgb":{color:{from:t=>[!0,Q(t)],to:t=>`#${tt(t.r)}${tt(t.g)}${tt(t.b)}`},text:{from:t=>{try{const e=t.replace(/([a-z])/g,'"$1"'),n=JSON.parse(e);if(Number.isNaN(n.r)||Number.isNaN(n.g)||Number.isNaN(n.b))throw new Error("not {r, g, b}");return[!0,n]}catch(t){return[!1]}},to:t=>`{r:${q(t.r)}, g:${q(t.g)}, b:${q(t.b)}}`}},"css-rgb":{color:{from:t=>[!0,et(t)],to:t=>{const e=nt.exec(t);return K([e[1],e[2],e[3]].map((t=>parseInt(t))))}},text:{from:bt,to:t=>bt(t)[1]}},"css-hsl":{color:{from:t=>[!0,it(t)],to:t=>{const e=ot.exec(t),n=function([t,e,n]){t=st(t,360),e=W(e/100,0,1),n=W(n/100,0,1);const i=e*Math.min(n,1-n);function o(e){const o=(e+t/30)%12;return n-i*Math.max(-1,Math.min(o-3,9-o,1))}return[o(0),o(8),o(4)].map((t=>Math.round(255*t)))}([e[1],e[2],e[3]].map((t=>parseFloat(t))));return K(n)}},text:{from:vt,to:t=>vt(t)[1]}}};class Ct extends b{#E;#C;#F;#V;#u={converters:F};constructor(t,n){const i=e("input",{type:"color",onInput:()=>{const[e,n]=this.#C(i.value);e&&(this.#V=!0,t.setValue(n))},onChange:()=>{const[e,n]=this.#C(i.value);e&&(this.#V=!0,t.setFinalValue(n))}});super(e("div",{},[i])),this.setOptions(n),this.#F=i}updateDisplay(t){this.#V||(this.#F.value=this.#E(t)),this.#V=!1}setOptions(t){a(this.#u,t);const{converters:{to:e,from:n}}=this.#u;return this.#E=e,this.#C=n,this}}class $t extends I{#L;#S;constructor(t,e,n={}){super(t,e,"muigui-color");const i=n.format||ht(this.getValue()),{color:o,text:s}=Et[i];this.#L=this.add(new Ct(this,{converters:o})),this.#S=this.add(new G(this,{converters:s})),this.updateDisplay()}setOptions(t){const{format:e}=t;if(e){const{color:t,text:n}=Et[e];this.#L.setOptions({converters:t}),this.#S.setOptions({converters:n})}return super.setOptions(t),this}}class Vt extends m{constructor(){super("muigui-divider")}}class Mt extends m{#N;#A;constructor(t){super(t),this.#N=[],this.#A=this}get children(){return this.#N}get controllers(){return this.#N.filter((t=>!(t instanceof Mt)))}get folders(){return this.#N.filter((t=>t instanceof Mt))}reset(t=!0){for(const e of this.#N)e instanceof Mt&&!t||e.reset(t);return this}remove(t){const e=this.#N.indexOf(t);if(e>=0){const t=this.#N.splice(e,1)[0];t.domElement.remove(),t.setParent(null)}return this}_addControllerImpl(t){return this.domElement.appendChild(t.domElement),this.#N.push(t),t.setParent(this),t}addController(t){return this.#A._addControllerImpl(t)}pushContainer(t){return this.addController(t),this.#A=t,t}popContainer(){return this.#A=this.#A.parent,this}}class St extends Mt{#U;constructor(t="Controls",n="muigui-menu"){super(n),this.#U=e("label"),this.addElem(e("button",{type:"button",onClick:()=>this.toggleOpen()},[this.#U])),this.pushContainer(new Mt),this.name(t),this.open()}open(t=!0){return this.domElement.classList.toggle("muigui-closed",!t),this.domElement.classList.toggle("muigui-open",t),this}close(){return this.open(!1)}name(t){return this.#U.textContent=t,this}title(t){return this.name(t)}toggleOpen(){return this.open(!this.domElement.classList.contains("muigui-open")),this}}class It extends m{constructor(t){super("muigui-label"),this.text(t)}text(t){return this.domElement.textContent=t,this}}class Dt extends St{add(t,e,...n){const i=t instanceof m?t:function(t,e,...n){const[i]=n;if(Array.isArray(i))return new P(t,e,{keyValues:i});const o=typeof t[e];switch(o){case"number":if("number"==typeof n[0]&&"number"==typeof n[1]){const i=n[0],o=n[1],s=n[2];return new B(t,e,{min:i,max:o,...s&&{step:s}})}return 0===n.length?new O(t,e,...n):new B(t,e,...n);case"boolean":return new D(t,e,...n);case"function":return new g(t,e,...n);case"string":return new H(t,e,...n);case"undefined":throw new Error(`no property named ${e}`);default:throw new Error(`unhandled type ${o} for property ${e}`)}}(t,e,...n);return this.addController(i)}addCanvas(t){return this.addController(new Y(t))}addColor(t,e,...n){return this.addController(new $t(t,e,...n))}addDivider(){return this.addController(new Vt)}addFolder(t){return this.addController(new Dt(t))}addLabel(t){return this.addController(new It(t))}}class Ft extends HTMLElement{constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}}customElements.define("muigui-element",Ft);const Lt=new CSSStyleSheet;Lt.replaceSync(t.default);const Nt=new CSSStyleSheet;function At(t){let e,n;function i(){if(e&&!n){const o=e;e=void 0,n=t.replace(o).then((()=>{console.log(o),n=void 0,i()}))}}return function(t){e=t,i()}}const Ut=At(Lt),Ot=At(Nt);class jt extends Dt{static converters=N;static mapRange=l;static makeRangeConverters=u;static makeRangeOptions=c;static makeMinMaxPair=d;#O=new CSSStyleSheet;constructor(t={}){super("Controls","muigui-root"),t instanceof HTMLElement&&(t={parent:t});const{autoPlace:n=!0,width:i,title:o="Controls"}=t;let{parent:s}=t;if(i&&(this.domElement.style.width=/^\d+$/.test(i)?`${i}px`:i),void 0===s&&n&&(s=document.body,this.domElement.classList.add("muigui-auto-place")),s){const t=e("muigui-element");t.shadowRoot.adoptedStyleSheets=[Lt,Nt,this.#O],t.shadow.appendChild(this.domElement),s.appendChild(t)}o&&this.title(o),this.domElement.classList.add("muigui","muigui-colors")}setStyle(t){this.#O.replace(t)}static setBaseStyles(t){Ut(t)}static getBaseStyleSheet(){return Lt}static setUserStyles(t){Ot(t)}static getUserStyleSheet(){return Nt}static setTheme(e){jt.setBaseStyles(`${t.default}\n${t.themes[e]||""}`)}}function Tt(){}function Pt(t,e,n){const i=t.getBoundingClientRect(),o=e.clientX-i.left,s=e.clientY-i.top,r=o/i.width,a=s/i.height,l=o-(n=n||[o,s])[0],u=s-n[1];return{x:o,y:s,nx:r,ny:a,dx:l,dy:u,ndx:l/i.width,ndy:u/i.width}}function zt(t,{onDown:e=Tt,onMove:n=Tt,onUp:i=Tt}){let o;const s=function(e){const i={type:"move",...Pt(t,e,o)};n(i)},r=function(e){t.releasePointerCapture(e.pointerId),t.removeEventListener("pointermove",s),t.removeEventListener("pointerup",r),document.body.style.backgroundColor="",i("up")},a=function(n){t.addEventListener("pointermove",s),t.addEventListener("pointerup",r),t.setPointerCapture(n.pointerId);const i=Pt(t,n);o=[i.x,i.y],e({type:"down",...i})};return t.addEventListener("pointerdown",a),function(){t.removeEventListener("pointerdown",a)}}class Bt extends b{#j;#T;#P;#z;#B;#G;#H;#R;constructor(t){super(e("div",{innerHTML:'\n\n\n \n \n \n \n \n \n \n \n\n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n\n',className:"muigui-no-scroll"})),this.#j=this.domElement.children[0],this.#T=this.domElement.children[1],this.#P=this.$(".muigui-color-chooser-circle"),this.#z=this.$("#muigui-color-chooser-hue"),this.#B=this.$(".muigui-color-chooser-cursor");const n=e=>{const n=i(e.nx,0,1),o=i(e.ny,0,1);this.#G[1]=n,this.#G[2]=1-o,this.#H=!0,t.setValue(Z(at(this.#G)))},o=e=>{const n=i(e.nx,0,1);this.#G[0]=n,this.#R=!0,t.setValue(Z(at(this.#G)))};zt(this.#j,{onDown:n,onMove:n}),zt(this.#T,{onDown:o,onMove:o})}updateDisplay(t){this.#G||(this.#G=ut(X(t)));{const[e,n,i]=ut(X(t));this.#H||(this.#G[0]=n>.001&&i>.001?e:this.#G[0]),this.#R||(this.#G[1]=n,this.#G[2]=i)}{const[t,e,n]=this.#G;this.#H||(this.#B.setAttribute("transform",`translate(${64*t}, 0)`),this.#z.children[0].setAttribute("stop-color",`hsl(${360*t}, 0%, 100%)`),this.#z.children[1].setAttribute("stop-color",`hsl(${360*t}, 100%, 50%)`)),this.#R||(this.#P.setAttribute("cx",""+64*e),this.#P.setAttribute("cy",""+48*(1-n)))}this.#H=!1,this.#R=!1}}class Gt extends I{#Y;#W;#q;#u={open:!1};constructor(t,n,i={}){super(t,n,"muigui-pop-down-controller"),this.#Y=this.add(new R("div","muigui-pop-down-top"));const o=this.#Y.addElem(e("input",{type:"checkbox",onChange:()=>{this.#u.open=o.checked}}));this.#W=this.#Y.add(new R("div","muigui-pop-down-values")),this.#q=this.add(new R("div","muigui-pop-down-bottom")),this.setOptions(i)}updateDisplay(){super.updateDisplay();const{open:t}=this.#u;this.domElement.children[1].classList.toggle("muigui-open",t),this.domElement.children[1].classList.toggle("muigui-closed",!t)}setOptions(t){a(this.#u,t),super.setOptions(t),this.updateDisplay()}addTop(t){return this.#W.add(t)}addBottom(t){return this.#q.add(t)}}function Ht(){}const Rt={ArrowLeft:[-1,0],ArrowRight:[1,0],ArrowUp:[0,-1],ArrowDown:[0,1]};function Yt(t,{onDown:e=Ht,onUp:n=Ht}){const i=function(t){const i=t.shiftKey?10:1,[o,s]=(Rt[t.key]||[0,0]).map((t=>t*i));("keydown"===t.type?e:n)({type:t.type.substring(3),dx:o,dy:s,event:t})};return t.addEventListener("keydown",i),t.addEventListener("keyup",i),function(){t.removeEventListener("keydown",i),t.removeEventListener("keyup",i)}}function Wt(t,e=""){if(!t)throw new Error(e)}function qt(t,e,n,i,o,s){const r=Math.abs(n)*Math.cos(s),a=Math.abs(i)*Math.sin(s);return[t+Math.cos(o)*r-Math.sin(o)*a,e+Math.sin(o)*r+Math.cos(o)*a]}function _t(t,e,n,i,o){Wt(Math.abs(i-o)<=2*Math.PI),Wt(i>=-Math.PI&&i<=2*Math.PI),Wt(i<=o),Wt(o>=-Math.PI&&o<=4*Math.PI);const{x1:s,y1:r,x2:a,y2:l,fa:u,fs:c}=function(t,e,n,i,o,s,r){const[a,l]=qt(t,e,n,i,o,s),[u,c]=qt(t,e,n,i,o,s+r);return{x1:a,y1:l,x2:u,y2:c,fa:Math.abs(r)>Math.PI?1:0,fs:r>0?1:0}}(t,e,n,n,0,i,o-i);return Math.abs(Math.abs(i-o)-2*Math.PI)>Number.EPSILON?`M${t} ${e} L${s} ${r} A ${n} ${n} 0 ${u} ${c} ${a} ${l} L${t} ${e}`:`M${s} ${r} L${s} ${r} A ${n} ${n} 0 ${u} ${c} ${a} ${l}`}const Jt=t=>r(t+Math.PI,2*Math.PI)-Math.PI;class Kt extends b{#_;#J;#K;#X;#u={step:1,min:-180,max:180,dirMin:-Math.PI,dirMax:Math.PI,wrap:void 0,converters:F};constructor(t,n={}){const o=A();super(e("div",{className:"muigui-direction muigui-no-scroll",innerHTML:'\n\n \x3c!----\x3e\n \n \n \n \n \n \n\n',onWheel:e=>{e.preventDefault();const{min:n,max:a,step:l}=this.#u,u=o(e,l);let c=this.#K+u;this.#X&&(c=r(c-n,a-n)+n);const h=i(s(c,(t=>t),l),n,a);t.setValue(h)}}));const a=e=>{const{min:n,max:o,step:r,dirMin:a,dirMax:l}=this.#u,u=2*e.nx-1,c=2*e.ny-1,h=Math.atan2(c,u),d=(a+l)/2,p=i((Jt(h-d)-Jt(a-d))/(l-a),0,1),m=s(n+(o-n)*p,(t=>t),r);t.setValue(m)};zt(this.domElement,{onDown:a,onMove:a}),Yt(this.domElement,{onDown:e=>{const{min:n,max:o,step:r}=this.#u,a=i(s(this.#K+e.dx*r,(t=>t),r),n,o);t.setValue(a)}}),this.#_=this.$("#muigui-arrow"),this.#J=this.$("#muigui-range"),this.setOptions(n)}updateDisplay(t){this.#K=t;const{min:e,max:n}=this.#u,i=(t-e)/(n-e),o=(s=this.#u.dirMin,r=this.#u.dirMax,s+(r-s)*i);var s,r;this.#_.style.transform=`rotate(${o}rad)`}setOptions(t){a(this.#u,t);const{dirMin:e,dirMax:n,wrap:i}=this.#u;this.#X=void 0!==i?i:Math.abs(e-n)>=2*Math.PI-Number.EPSILON;const[o,s]=e(o.push(i),e("label",{},[e("input",{type:"radio",name:s,value:a,onChange:function(){this.checked&&t.setFinalValue(r.#I[this.value])}}),e("button",{type:"button",textContent:n,onClick:function(){this.previousElementSibling.click()}})]))))));const r=this;this.#I=o,this.cols(i)}updateDisplay(t){const e=this.#I.indexOf(t);for(let t=0;t{e({rect:t.getBoundingClientRect(),elem:t})})).observe(t)}function Qt(t,e,n,i){Zt(t,(({rect:o})=>{const{width:s,height:r}=o;t.setAttribute("viewBox",`-${s*e} -${r*n} ${s} ${r}`),i({elem:t,rect:o})}))}function te(t,e,n,i,o,r){const a=[];tt),n)),e=Math.min(e,o);for(let i=t;i<=e;i+=n)a.push(`M${i} 0 l0 ${r}`);return a.join(" ")}class ee extends b{#Z;#Q;#tt;#et;#nt;#it;#ot;#st;#rt;#K;#at;#u={min:-100,max:100,step:1,unit:10,unitSize:10,ticksPerUnit:5,labelFn:t=>t,tickHeight:1,limits:!0,thicksColor:void 0,orientation:void 0};constructor(t,n){const o=A();let r;super(e("div",{innerHTML:'\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \x3c!----\x3e\n \x3c!----\x3e\n \n \n \n \n\n',className:"muigui-no-v-scroll",onWheel:e=>{e.preventDefault();const{min:n,max:r,step:a}=this.#u,l=o(e,a),u=i(s(this.#K+l,(t=>t),a),n,r);t.setValue(u)}})),this.#Z=this.$("svg"),this.#Q=this.$("#muigui-origin"),this.#tt=this.$("#muigui-ticks"),this.#et=this.$("#muigui-thicks"),this.#nt=this.$("#muigui-numbers"),this.#it=this.$("#muigui-left-grad"),this.#ot=this.$("#muigui-right-grad"),this.setOptions(n),zt(this.domElement,{onDown:()=>{r=this.#K},onMove:e=>{const{min:n,max:o,unitSize:a,unit:l,step:u}=this.#u,c=i(s(r-e.dx/a*l,(t=>t),u),n,o);t.setValue(c)}}),Yt(this.domElement,{onDown:e=>{const{min:n,max:o,step:r}=this.#u,a=i(s(this.#K+e.dx*r,(t=>t),r),n,o);t.setValue(a)}}),Qt(this.#Z,.5,0,(({rect:{width:t}})=>{this.#it.setAttribute("x",-t/2),this.#ot.setAttribute("x",t/2-20),this.#at=function(t){const e=t.innerHTML;t.innerHTML="- ";const n=t.querySelector("text").getComputedTextLength();return t.innerHTML=e,n}(this.#nt),this.#st=t,this.#lt()}))}#lt(){if(!this.#st||void 0===this.#K)return;const{labelFn:t,limits:e,min:n,max:i,orientation:o,tickHeight:r,ticksPerUnit:a,unit:l,unitSize:u,thicksColor:c}=this.#u,h=Math.ceil(this.#st/u),d=this.#K/l,p=Math.round(d-h),m=p*u,g=(p+2*h)*u,f=e?n*u/l:m,b=e?i*u/l:g,v=""===t(1)?10:5;a>1&&this.#tt.setAttribute("d",te(m,g,u/a,f,b,v*r)),this.#et.style.stroke=c,this.#et.setAttribute("d",te(m,g,u,f,b,v)),this.#nt.innerHTML=function(t,e,n,i,o,r,a,l){const u=[];tt),n)),e=Math.min(e,a);const c=Math.max(0,-Math.log10(i));for(let s=t;s<=e;s+=n)u.push(`${h=s/n*i,l(h.toFixed(c))}`);var h;return u.join("\n")}(m,g,u,l,this.#at,f,b,t),this.#Q.setAttribute("transform",`translate(${-this.#K*u/l} 0)`),this.#Z.classList.toggle("muigui-slider-up","up"===o)}updateDisplay(t){this.#K=t,this.#lt()}setOptions(t){return a(this.#u,t),this}}class ne extends b{#Z;#_;#P;#K=[];constructor(t){super(e("div",{innerHTML:'\n\n \n \n \n \n \n\n',className:"muigui-no-scroll"}));const n=e=>{const{width:n,height:i}=this.#Z.getBoundingClientRect(),o=2*e.nx-1,s=2*e.ny-1;t.setValue([o*n*.5,s*i*.5])};zt(this.domElement,{onDown:n,onMove:n}),this.#Z=this.$("svg"),this.#_=this.$("#muigui-arrow"),this.#P=this.$("#muigui-circle"),Qt(this.#Z,.5,.5,(()=>this.#ut))}#ut(){const[t,e]=this.#K;this.#_.setAttribute("d",`M0,0L${t},${e}`),this.#P.setAttribute("transform",`translate(${t}, ${e})`)}updateDisplay(t){this.#K[0]=t[0],this.#K[1]=t[1],this.#ut()}}return jt.ColorChooser=class extends Gt{constructor(t,e){super(t,e,"muigui-color-chooser"),this.addTop(new G(this)),this.addBottom(new Bt(this)),this.updateDisplay()}},jt.Direction=class extends Gt{#u;constructor(t,e,n){super(t,e,"muigui-direction"),this.#u=n,this.addTop(new U(this,F)),this.addBottom(new Kt(this,n)),this.updateDisplay()}},jt.RadioGrid=class extends I{constructor(t,e,n){super(t,e,"muigui-radio-grid");const i="number"==typeof this.getValue(),{keyValues:o,cols:s=3}=n,r=T(o,i);this.add(new Xt(this,r,s)),this.updateDisplay()}},jt.Range=B,jt.Select=P,jt.Slider=class extends I{constructor(t,e,n={}){super(t,e,"muigui-slider"),this.add(new ee(this,n)),this.add(new U(this,n)),this.updateDisplay()}},jt.TextNumber=O,jt.Vec2=class extends Gt{constructor(t,e){super(t,e,"muigui-vec2");const n=t=>({setValue:e=>{const n=this.getValue();n[t]=e,this.setValue(n)},setFinalValue:e=>{const n=this.getValue();n[t]=e,this.setFinalValue(n)}});this.addTop(new U(n(0),{converters:{to:t=>t[0],from:L.from}})),this.addTop(new U(n(1),{converters:{to:t=>t[1],from:L.from}})),this.addBottom(new ne(this)),this.updateDisplay()}},jt})); diff --git a/dist/0.x/muigui.module.js b/dist/0.x/muigui.module.js index c77fd35..022e62d 100644 --- a/dist/0.x/muigui.module.js +++ b/dist/0.x/muigui.module.js @@ -861,30 +861,27 @@ function makeMinMaxPair(gui, properties, minPropName, maxPropName, options) { const { min, max } = options; const guiMinRange = options.minRange || 0; const valueMinRange = from(guiMinRange)[1]; - console.log('guiMinRange', guiMinRange); - console.log('valueMinRange', valueMinRange); - return [ - gui - .add(properties, minPropName, { - ...options, - min, - max: max - guiMinRange, - }) - .listen() - .onChange(v => { - properties[maxPropName] = Math.min(max, Math.max(v + valueMinRange, properties[maxPropName])); - }), - gui - .add(properties, maxPropName, { - ...options, - min: min + guiMinRange, - max, - }) - .listen() - .onChange(v => { - properties[minPropName] = Math.max(min, Math.min(v - valueMinRange, properties[minPropName])); - }), - ]; + const minGui = gui + .add(properties, minPropName, { + ...options, + min, + max: max - guiMinRange, + }) +// .listen() + .onChange(v => { + maxGui.setValue(Math.min(max, Math.max(v + valueMinRange, properties[maxPropName]))); + }); + const maxGui = gui + .add(properties, maxPropName, { + ...options, + min: min + guiMinRange, + max, + }) +// .listen() + .onChange(v => { + minGui.setValue(Math.max(min, Math.min(v - valueMinRange, properties[minPropName]))); + }); + return [ minGui, maxGui ]; } class View { @@ -1352,31 +1349,39 @@ class ValueController extends LabelController { return view; } #setValueImpl(v, ignoreCache) { + let isDifferent = false; if (typeof v === 'object') { const dst = this.#object[this.#property]; // don't replace objects, just their values. - if (Array.isArray(v)) { + if (Array.isArray(v) || isTypedArray(v)) { for (let i = 0; i < v.length; ++i) { + isDifferent ||= dst[i] !== v[i]; dst[i] = v[i]; } - } else if (isTypedArray(v)) { - dst.set(v); } else { + for (const key of Object.keys(v)) { + isDifferent ||= dst[key] !== v[key]; + } Object.assign(dst, v); } } else { + isDifferent = this.#object[this.#property] !== v; this.#object[this.#property] = v; } this.updateDisplay(ignoreCache); - this.emitChange(this.getValue(), this.#object, this.#property); - return this; + if (isDifferent) { + this.emitChange(this.getValue(), this.#object, this.#property); + } + return isDifferent; } setValue(v) { this.#setValueImpl(v); } setFinalValue(v) { - this.#setValueImpl(v, true); - this.emitFinalChange(this.getValue(), this.#object, this.#property); + const isDifferent = this.#setValueImpl(v, true); + if (isDifferent) { + this.emitFinalChange(this.getValue(), this.#object, this.#property); + } return this; } updateDisplay(ignoreCache) { diff --git a/dist/0.x/muigui.module.min.js b/dist/0.x/muigui.module.min.js index ea72e29..aac9a08 100644 --- a/dist/0.x/muigui.module.min.js +++ b/dist/0.x/muigui.module.min.js @@ -1 +1 @@ -var t={default:'\n.muigui {\n --bg-color: #ddd;\n --color: #222;\n --contrast-color: #eee;\n --value-color: #145 ;\n --value-bg-color: #eeee;\n --disabled-color: #999;\n --menu-bg-color: #f8f8f8;\n --menu-sep-color: #bbb;\n --hover-bg-color: #999;\n --focus-color: #68C;\n --range-color: #888888;\n --invalid-color: #FF0000;\n --selected-color: rgb(255, 255, 255, 0.9);\n\n --button-bg-color: var(--value-bg-color);\n\n --range-left-color: var(--value-color);\n --range-right-color: var(--value-bg-color); \n --range-right-hover-color: var(--hover-bg-color);\n\n color: var(--color);\n background-color: var(--bg-color);\n}\n\n@media (prefers-color-scheme: dark) {\n .muigui {\n --bg-color: #222222;\n --color: #dddddd;\n --contrast-color: #000;\n --value-color: #43e5f7;\n --value-bg-color: #444444;\n --disabled-color: #666666;\n --menu-bg-color: #080808;\n --menu-sep-color: #444444;\n --hover-bg-color: #666666;\n --focus-color: #88AAFF;\n --range-color: #888888;\n --invalid-color: #FF6666;\n --selected-color: rgba(255, 255, 255, 0.3);\n\n --button-bg-color: var(--value-bg-color);\n\n --range-left-color: var(--value-color);\n --range-right-color: var(--value-bg-color); \n --range-right-hover-color: var(--hover-bg-color);\n\n color: var(--color);\n background-color: var(--bg-color);\n }\n}\n\n.muigui {\n --width: 250px;\n --label-width: 45%;\n --number-width: 40%;\n\n\n --font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;\n --font-size: 11px;\n --font-family-mono: Menlo, Monaco, Consolas, "Droid Sans Mono", monospace;\n --font-size-mono: 11px;\n\n --line-height: 1.7em;\n --border-radius: 0px;\n\n width: var(--width);\n font-family: var(--font-family);\n font-size: var(--font-size);\n box-sizing: border-box;\n line-height: 100%;\n}\n.muigui * {\n box-sizing: inherit;\n}\n\n.muigui-no-scroll {\n touch-action: none;\n}\n.muigui-no-h-scroll {\n touch-action: pan-y;\n}\n.muigui-no-v-scroll {\n touch-action: pan-x;\n}\n\n.muigui-invalid-value {\n background-color: red !important;\n color: white !important;\n}\n\n.muigui-grid {\n display: grid;\n}\n.muigui-rows {\n display: flex;\n flex-direction: column;\n\n min-height: 20px;\n border: 2px solid red;\n}\n.muigui-columns {\n display: flex;\n flex-direction: row;\n\n height: 20px;\n border: 2px solid green;\n}\n.muigui-rows>*,\n.muigui-columns>* {\n flex: 1 1 auto;\n align-items: stretch;\n min-height: 0;\n min-width: 0;\n}\n\n.muigui-row {\n border: 2px solid yellow;\n min-height: 10px\n}\n.muigui-column {\n border: 2px solid lightgreen;\n}\n\n/* -------- */\n\n.muigui-show { /* */ }\n.muigui-hide { \n display: none !important;\n}\n.muigui-disabled {\n pointer-events: none;\n --color: var(--disabled-color) !important;\n --value-color: var(--disabled-color) !important;\n --range-left-color: var(--disabled-color) !important;\n}\n\n.muigui canvas,\n.muigui svg {\n display: block;\n border-radius: var(--border-radius);\n}\n.muigui canvas {\n background-color: var(--value-bg-color);\n}\n\n.muigui-controller {\n min-width: 0;\n min-height: var(--line-height);\n}\n.muigui-root,\n.muigui-menu {\n display: flex;\n flex-direction: column;\n position: relative;\n user-select: none;\n height: fit-content;\n margin: 0;\n padding-bottom: 0.1em;\n border-radius: var(--border-radius);\n}\n.muigui-menu {\n border-bottom: 1px solid var(--menu-sep-color);\n}\n\n.muigui-root>button:nth-child(1),\n.muigui-menu>button:nth-child(1) {\n border-top: 1px solid var(--menu-sep-color);\n border-bottom: 1px solid var(--menu-sep-color);\n position: relative;\n text-align: left;\n color: var(--color);\n background-color: var(--menu-bg-color);\n min-height: var(--line-height);\n padding-top: 0.2em;\n padding-bottom: 0.2em;\n cursor: pointer;\n border-radius: var(--border-radius);\n}\n.muigui-root>div:nth-child(2),\n.muigui-menu>div:nth-child(2) {\n flex: 1 1 auto;\n}\n\n.muigui-controller {\n margin-left: 0.2em;\n margin-right: 0.2em;\n}\n.muigui-root.muigui-controller,\n.muigui-menu.muigui-controller {\n margin-left: 0;\n margin-right: 0;\n}\n.muigui-controller>*:nth-child(1) {\n flex: 1 0 var(--label-width);\n min-width: 0;\n white-space: pre;\n}\n.muigui-controller>label:nth-child(1) {\n place-content: center start;\n display: inline-grid;\n overflow: hidden;\n}\n.muigui-controller>*:nth-child(2) {\n flex: 1 1 75%;\n min-width: 0;\n}\n\n/* -----------------------------------------\n a label controller is [[label][value]]\n*/\n\n.muigui-label-controller {\n display: flex;\n margin: 0.4em 0 0.4em 0;\n word-wrap: initial;\n align-items: stretch;\n}\n\n.muigui-value {\n display: flex;\n align-items: stretch;\n}\n.muigui-value>* {\n flex: 1 1 auto;\n min-width: 0;\n}\n.muigui-value>*:nth-child(1) {\n flex: 1 1 calc(100% - var(--number-width));\n}\n.muigui-value>*:nth-child(2) {\n flex: 1 1 var(--number-width);\n margin-left: 0.2em;\n}\n\n/* fix! */\n.muigui-open>button>label::before,\n.muigui-closed>button>label::before {\n width: 1.25em;\n height: var(--line-height);\n display: inline-grid;\n place-content: center start;\n pointer-events: none;\n}\n.muigui-open>button>label::before {\n content: "ⓧ"; /*"▼";*/\n}\n.muigui-closed>button>label::before {\n content: "⨁"; /*"▶";*/\n}\n.muigui-open>*:nth-child(2) {\n transition: max-height 0.2s ease-out,\n opacity 0.5s ease-out;\n max-height: 100vh;\n overflow: auto;\n opacity: 1;\n}\n\n.muigui-closed>*:nth-child(2) {\n transition: max-height 0.2s ease-out,\n opacity 1s;\n max-height: 0;\n opacity: 0;\n overflow: hidden;\n}\n\n/* ---- popdown ---- */\n\n.muigui-pop-down-top {\n display: flex;\n}\n/* fix? */\n.muigui-value>*:nth-child(1).muigui-pop-down-top {\n flex: 0;\n}\n.muigui-pop-down-bottom {\n\n}\n\n.muigui-pop-down-values {\n min-width: 0;\n display: flex;\n}\n.muigui-pop-down-values>* {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.muigui-value.muigui-pop-down-controller {\n flex-direction: column;\n}\n\n.muigui-pop-down-top input[type=checkbox] {\n -webkit-appearance: none;\n appearance: none;\n width: auto;\n color: var(--value-color);\n background-color: var(--value-bg-color);\n cursor: pointer;\n\n display: grid;\n place-content: center;\n margin: 0;\n font: inherit;\n color: currentColor;\n width: 1.7em;\n height: 1.7em;\n transform: translateY(-0.075em);\n}\n\n.muigui-pop-down-top input[type=checkbox]::before {\n content: "+";\n display: grid;\n place-content: center;\n border-radius: calc(var(--border-radius) + 2px);\n border-left: 1px solid rgba(255,255,255,0.3);\n border-top: 1px solid rgba(255,255,255,0.3);\n border-bottom: 1px solid rgba(0,0,0,0.2);\n border-right: 1px solid rgba(0,0,0,0.2);\n background-color: var(--range-color);\n color: var(--value-bg-color);\n width: calc(var(--line-height) - 4px);\n height: calc(var(--line-height) - 4px);\n}\n\n.muigui-pop-down-top input[type=checkbox]:checked::before {\n content: "X";\n}\n\n\n/* ---- select ---- */\n\n.muigui select,\n.muigui option,\n.muigui input,\n.muigui button {\n color: var(--value-color);\n background-color: var(--value-bg-color);\n font-family: var(--font-family);\n font-size: var(--font-size);\n border: none;\n margin: 0;\n border-radius: var(--border-radius);\n}\n.muigui select {\n appearance: none;\n margin: 0;\n margin-left: 0; /*?*/\n overflow: hidden; /* Safari */\n}\n\n.muigui select:focus,\n.muigui input:focus,\n.muigui button:focus {\n outline: 1px solid var(--focus-color);\n}\n\n.muigui select:hover,\n.muigui option:hover,\n.muigui input:hover,\n.muigui button:hover {\n background-color: var(--hover-bg-color); \n}\n\n/* ------ [ label ] ------ */\n\n.muigui-label {\n border-top: 1px solid var(--menu-sep-color);\n border-bottom: 1px solid var(--menu-sep-color);\n padding-top: 0.4em;\n padding-bottom: 0.3em;\n place-content: center start;\n background-color: var(--menu-bg-color);\n white-space: pre;\n border-radius: var(--border-radius);\n}\n\n/* ------ [ divider] ------ */\n\n.muigui-divider {\n min-height: 6px;\n border-top: 2px solid var(--menu-sep-color);\n margin-top: 6px;\n}\n\n/* ------ [ button ] ------ */\n\n.muigui-button {\n display: grid;\n\n}\n.muigui-button button {\n border: none;\n color: var(--value-color);\n background-color: var(--button-bg-color);\n cursor: pointer;\n place-content: center center;\n}\n\n/* ------ [ color ] ------ */\n\n.muigui-color>div {\n overflow: hidden;\n position: relative;\n margin-left: 0;\n margin-right: 0; /* why? */\n max-width: var(--line-height);\n border-radius: var(--border-radius);\n}\n\n.muigui-color>div:focus-within {\n outline: 1px solid var(--focus-color);\n}\n\n.muigui-color input[type=color] {\n border: none;\n padding: 0;\n background: inherit;\n cursor: pointer;\n position: absolute;\n width: 200%;\n left: -10px;\n top: -10px;\n height: 200%;\n}\n.muigui-disabled canvas,\n.muigui-disabled svg,\n.muigui-disabled img,\n.muigui-disabled .muigui-color input[type=color] {\n opacity: 0.2;\n}\n\n/* ------ [ checkbox ] ------ */\n\n.muigui-checkbox>label:nth-child(2) {\n display: grid;\n place-content: center start;\n margin: 0;\n}\n\n.muigui-checkbox input[type=checkbox] {\n -webkit-appearance: none;\n appearance: none;\n width: auto;\n color: var(--value-color);\n background-color: var(--value-bg-color);\n cursor: pointer;\n\n display: grid;\n place-content: center;\n margin: 0;\n font: inherit;\n color: currentColor;\n width: 1.7em;\n height: 1.7em;\n transform: translateY(-0.075em);\n}\n\n.muigui-checkbox input[type=checkbox]::before {\n content: "";\n color: var(--value-color);\n display: grid;\n place-content: center;\n}\n\n.muigui-checkbox input[type=checkbox]:checked::before {\n content: "✔";\n}\n\n.muigui input[type=number]::-webkit-inner-spin-button, \n.muigui input[type=number]::-webkit-outer-spin-button { \n -webkit-appearance: none;\n appearance: none;\n margin: 0; \n}\n.muigui input[type=number] {\n -moz-appearance: textfield;\n}\n\n/* ------ [ radio grid ] ------ */\n\n.muigui-radio-grid>div {\n display: grid;\n gap: 2px;\n}\n\n.muigui-radio-grid input {\n appearance: none;\n display: none;\n}\n\n.muigui-radio-grid button {\n color: var(--color);\n width: 100%;\n text-align: left;\n}\n\n.muigui-radio-grid input:checked + button {\n color: var(--value-color);\n background-color: var(--selected-color);\n}\n\n/* ------ [ color-chooser ] ------ */\n\n.muigui-color-chooser-cursor {\n stroke-width: 1px;\n stroke: white;\n fill: none;\n}\n.muigui-color-chooser-circle {\n stroke-width: 1px;\n stroke: white;\n fill: none;\n}\n\n\n/* ------ [ vec2 ] ------ */\n\n.muigui-vec2 svg {\n background-color: var(--value-bg-color);\n}\n\n.muigui-vec2-axis {\n stroke: 1px;\n stroke: var(--focus-color);\n}\n\n.muigui-vec2-line {\n stroke-width: 1px;\n stroke: var(--value-color);\n fill: var(--value-color);\n}\n\n/* ------ [ direction ] ------ */\n\n.muigui-direction svg {\n background-color: rgba(0,0,0,0.2);\n}\n\n.muigui-direction:focus-within svg {\n outline: none;\n}\n.muigui-direction-range {\n fill: var(--value-bg-color);\n}\n.muigui-direction svg:focus {\n outline: none;\n}\n.muigui-direction svg:focus .muigui-direction-range {\n stroke-width: 0.5px;\n stroke: var(--focus-color);\n}\n\n.muigui-direction-arrow {\n fill: var(--value-color);\n}\n\n/* ------ [ slider ] ------ */\n\n.muigui-slider>div {\n display: flex;\n align-items: stretch;\n height: var(--line-height);\n}\n.muigui-slider svg {\n flex: 1 1 auto;\n}\n.muigui-slider .muigui-slider-up #muigui-orientation {\n transform: scale(1, -1) translateY(-100%);\n}\n\n.muigui-slider .muigui-slider-up #muigui-number-orientation {\n transform: scale(1,-1);\n}\n\n.muigui-ticks {\n stroke: var(--range-color);\n}\n.muigui-thicks {\n stroke: var(--color);\n stroke-width: 2px;\n}\n.muigui-svg-text {\n fill: var(--color);\n font-size: 7px;\n}\n.muigui-mark {\n fill: var(--value-color);\n}\n\n/* ------ [ range ] ------ */\n\n\n.muigui-range input[type=range] {\n -webkit-appearance: none;\n appearance: none;\n background-color: transparent;\n}\n\n.muigui-range input[type=range]::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n border-radius: calc(var(--border-radius) + 2px);\n border-left: 1px solid rgba(255,255,255,0.3);\n border-top: 1px solid rgba(255,255,255,0.3);\n border-bottom: 1px solid rgba(0,0,0,0.2);\n border-right: 1px solid rgba(0,0,0,0.2);\n background-color: var(--range-color);\n margin-top: calc((var(--line-height) - 2px) / -2);\n width: calc(var(--line-height) - 2px);\n height: calc(var(--line-height) - 2px);\n}\n\n.muigui-range input[type=range]::-webkit-slider-runnable-track {\n -webkit-appearance: none;\n appearance: none;\n border: 1px solid var(--menu-sep-color);\n height: 2px;\n}\n\n\n/* dat.gui style - doesn\'t work on Safari iOS */\n\n/*\n.muigui-range input[type=range] {\n cursor: ew-resize;\n overflow: hidden;\n}\n\n.muigui-range input[type=range] {\n -webkit-appearance: none;\n appearance: none;\n background-color: var(--range-right-color);\n margin: 0;\n}\n.muigui-range input[type=range]:hover {\n background-color: var(--range-right-hover-color);\n}\n\n.muigui-range input[type=range]::-webkit-slider-runnable-track {\n -webkit-appearance: none;\n appearance: none;\n height: max-content;\n color: var(--range-left-color);\n margin-top: -1px;\n}\n\n.muigui-range input[type=range]::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 0px;\n height: max-content;\n box-shadow: -1000px 0 0 1000px var(--range-left-color);\n}\n*/\n\n/* FF */\n/*\n.muigui-range input[type=range]::-moz-slider-progress {\n background-color: var(--range-left-color); \n}\n.muigui-range input[type=range]::-moz-slider-thumb {\n height: max-content;\n width: 0;\n border: none;\n box-shadow: -1000px 0 0 1000px var(--range-left-color);\n box-sizing: border-box;\n}\n*/\n\n/* ---------------------------------------------------------- */\n\n/* needs to be at bottom to take precedence */\n.muigui-auto-place {\n max-height: 100%;\n position: fixed;\n top: 0;\n right: 15px;\n z-index: 100001;\n}\n\n',themes:{default:"",float:"\n :root {\n color-scheme: light dark,\n }\n\n .muigui {\n --width: 400px;\n --bg-color: initial;\n --label-width: 25%;\n }\n\n input,\n .muigui-label-controller>label {\n text-shadow:\n -1px -1px 0 var(--contrast-color),\n 1px -1px 0 var(--contrast-color),\n -1px 1px 0 var(--contrast-color),\n 1px 1px 0 var(--contrast-color);\n }\n\n .muigui-controller > label:nth-child(1) {\n place-content: center end;\n margin-right: 1em;\n }\n\n .muigui-value > :nth-child(2) {\n margin-left: 1em;\n }\n\n .muigui-root>*:nth-child(1) {\n display: none;\n }\n\n .muigui-range input[type=range]::-webkit-slider-thumb {\n border-radius: 1em;\n }\n\n .muigui-range input[type=range]::-webkit-slider-runnable-track {\n -webkit-appearance: initial;\n appearance: none;\n border: 1px solid rgba(0, 0, 0, 0.25);\n height: 2px;\n }\n\n .muigui-colors {\n --value-color: var(--color );\n --value-bg-color: rgba(0, 0, 0, 0.1);\n --disabled-color: #cccccc;\n --menu-bg-color: rgba(0, 0, 0, 0.1);\n --menu-sep-color: #bbbbbb;\n --hover-bg-color: rgba(0, 0, 0, 0);\n --invalid-color: #FF0000;\n --selected-color: rgba(0, 0, 0, 0.3);\n --range-color: rgba(0, 0, 0, 0.125);\n }\n"}};function e(t,e={},n=[]){const i=document.createElement(t);return function(t,e,n){for(const[n,i]of Object.entries(e))if("function"==typeof i&&n.startsWith("on")){const e=n.substring(2).toLowerCase();t.addEventListener(e,i,{passive:!1})}else if("object"==typeof i)for(const[e,o]of Object.entries(i))t[n][e]=o;else void 0===t[n]?t.setAttribute(n,i):t[n]=i;for(const e of n)t.appendChild(e)}(i,e,n),i}function n(t,e){const n=t.indexOf(e);return n&&t.splice(n,1),t}function i(t,e,n){return Math.max(e,Math.min(n,t))}const o="undefined"!=typeof SharedArrayBuffer?function(t){return t&&t.buffer&&(t.buffer instanceof ArrayBuffer||t.buffer instanceof SharedArrayBuffer)}:function(t){return t&&t.buffer&&t.buffer instanceof ArrayBuffer},s=(t,e,n)=>Math.round(e(t)/n)/(1/n),r=(t,e)=>(t%e+e)%e;function a(t,e){for(const n in e)n in t&&(t[n]=e[n]);return t}const l=(t,e,n,i,o)=>(t-e)*(o-i)/(n-e)+i,u=({from:t,to:e})=>({to:n=>l(n,...t,...e),from:n=>[!0,l(n,...e,...t)]}),c=({from:t,to:e,step:n})=>({min:e[0],max:e[1],...n&&{step:n},converters:u({from:t,to:e})}),h={to:t=>t,from:t=>[!0,t]};function d(t,e,n,i,o){const{converters:{from:s}=h}=o,{min:r,max:a}=o,l=o.minRange||0,u=s(l)[1];return console.log("guiMinRange",l),console.log("valueMinRange",u),[t.add(e,n,{...o,min:r,max:a-l}).listen().onChange((t=>{e[i]=Math.min(a,Math.max(t+u,e[i]))})),t.add(e,i,{...o,min:r+l,max:a}).listen().onChange((t=>{e[n]=Math.max(r,Math.min(t-u,e[n]))}))]}class p{#t;#e=[];constructor(t){this.domElement=t,this.#t=t}addElem(t){return this.#t.appendChild(t),t}removeElem(t){return this.#t.removeChild(t),t}pushSubElem(t){this.#t.appendChild(t),this.#t=t}popSubElem(){this.#t=this.#t.parentElement}add(t){return this.#e.push(t),this.addElem(t.domElement),t}remove(t){return this.removeElem(t.domElement),n(this.#e,t),t}pushSubView(t){this.pushSubElem(t.domElement)}popSubView(){this.popSubElem()}setOptions(t){for(const e of this.#e)e.setOptions(t)}updateDisplayIfNeeded(t,e){for(const n of this.#e)n.updateDisplayIfNeeded(t,e);return this}$(t){return this.domElement.querySelector(t)}}class m extends p{#n;#i;#o;constructor(t){super(e("div",{className:"muigui-controller"})),this.#n=[],this.#i=[],t&&this.domElement.classList.add(t)}get parent(){return this.#o}setParent(t){this.#o=t,this.enable(!this.disabled())}show(t=!0){return this.domElement.classList.toggle("muigui-hide",!t),this.domElement.classList.toggle("muigui-show",t),this}hide(){return this.show(!1)}disabled(){return!!this.domElement.closest(".muigui-disabled")}enable(t=!0){return this.domElement.classList.toggle("muigui-disabled",!t),["input","button","select","textarea"].forEach((t=>{this.domElement.querySelectorAll(t).forEach((t=>{const e=!!t.closest(".muigui-disabled");t.disabled=e}))})),this}disable(t=!0){return this.enable(!t)}onChange(t){return this.removeChange(t),this.#n.push(t),this}removeChange(t){return n(this.#n,t),this}onFinishChange(t){return this.removeFinishChange(t),this.#i.push(t),this}removeFinishChange(t){return n(this.#i,t),this}#s(t,e){for(const n of t)n.call(this,e)}emitChange(t,e,n){this.#s(this.#n,t),this.#o&&(void 0===e?this.#o.emitChange(t):this.#o.emitChange({object:e,property:n,value:t,controller:this}))}emitFinalChange(t,e,n){this.#s(this.#i,t),this.#o&&(void 0===e?this.#o.emitChange(t):this.#o.emitFinalChange({object:e,property:n,value:t,controller:this}))}getColors(){const t=t=>t.replace(/-([a-z])/g,((t,e)=>e.toUpperCase())),n=e("div");this.domElement.appendChild(n);const i=Object.fromEntries(["color","bg-color","value-color","value-bg-color","hover-bg-color","menu-bg-color","menu-sep-color","disabled-color"].map((e=>{n.style.color=`var(--${e})`;const i=getComputedStyle(n);return[t(e),i.color]})));return n.remove(),i}}class g extends m{#r;#a;#l;#u={name:""};constructor(t,n,i={}){super("muigui-button",""),this.#r=t,this.#a=n,this.#l=this.addElem(e("button",{type:"button",onClick:()=>{this.#r[this.#a](this)}})),this.setOptions({name:n,...i})}setOptions(t){a(this.#u,t);const{name:e}=this.#u;this.#l.textContent=e}}function f(t,e){if(t.length!==e.length)return!1;for(let n=0;n{t.setValue(i.checked)},onChange:()=>{t.setFinalValue(i.checked)}});super(e("label",{},[i]))}updateDisplay(t){this.domElement.checked=t}}const x=[],w=new Set;let y,k;function E(){y=void 0,k=!0;for(const t of x)w.has(t)||t();k=!1,w.size&&(k?$():(w.forEach((t=>{n(x,t)})),w.clear())),$()}function $(){!y&&x.length&&(y=requestAnimationFrame(E))}let C=0;function M(){return"muigui-"+ ++C}class V extends p{constructor(t=""){super(e("div",{className:"muigui-value"})),t&&this.domElement.classList.add(t)}}class S extends m{#b;#v;constructor(t="",n=""){super("muigui-label-controller"),this.#b=M(),this.#v=e("label",{for:this.#b}),this.domElement.appendChild(this.#v),this.pushSubView(new V(t)),this.name(n)}get id(){return this.#b}name(t){return this.#v.title===this.#v.textContent&&(this.#v.title=t),this.#v.textContent=t,this}tooltip(t){this.#v.title=t}}class I extends S{#r;#a;#x;#w;#e;#y;constructor(t,e,n=""){super(n,e),this.#r=t,this.#a=e,this.#x=this.getValue(),this.#w=!1,this.#e=[]}get initialValue(){return this.#x}get object(){return this.#r}get property(){return this.#a}add(t){return this.#e.push(t),super.add(t),this.updateDisplay(),t}#k(t,e){if("object"==typeof t){const e=this.#r[this.#a];if(Array.isArray(t))for(let n=0;n=0&&x.splice(e,1)}(this.#y)),this}}class D extends I{constructor(t,e){super(t,e,"muigui-checkbox");const n=this.id;this.add(new v(this,n)),this.updateDisplay()}}const F={to:t=>t,from:t=>[!0,t]},L={to:t=>t.toString(),from:t=>{const e=parseFloat(t);return[!Number.isNaN(e),e]}},N={radToDeg:u({to:[0,180],from:[0,Math.PI]})};function A(){let t=0;return function(e,n,i=5){t-=e.deltaY*n/i;const o=Math.floor(Math.abs(t)/n)*Math.sign(t)*n;return t-=o,o}}class U extends b{#E;#$;#C;#M;#u={step:.01,converters:L,min:Number.NEGATIVE_INFINITY,max:Number.POSITIVE_INFINITY};constructor(t,n){const o=t.setValue.bind(t),r=t.setFinalValue.bind(t),a=A();super(e("input",{type:"number",onInput:()=>this.#V(o,!0),onChange:()=>this.#V(r,!1),onWheel:e=>{e.preventDefault();const{min:n,max:o,step:r}=this.#u,l=a(e,r),u=parseFloat(this.domElement.value),c=i(s(u+l,(t=>t),r),n,o);t.setValue(c)}})),this.setOptions(n)}#V(t,e){const n=parseFloat(this.domElement.value),[o,s]=this.#$(n);let r;if(o&&!Number.isNaN(n)){const{min:n,max:o}=this.#u;r=s>=n&&s<=o,this.#M=e,t(i(s,n,o))}this.domElement.classList.toggle("muigui-invalid-value",!o||!r)}updateDisplay(t){this.#M||(this.domElement.value=s(t,this.#E,this.#C)),this.#M=!1}setOptions(t){a(this.#u,t);const{step:e,converters:{to:n,from:i}}=this.#u;return this.#E=n,this.#$=i,this.#C=e,this}}class O extends I{#S;#C;constructor(t,e,n={}){super(t,e,"muigui-checkbox"),this.#S=this.add(new U(this,n)),this.updateDisplay()}}class j extends b{#I;constructor(t,n){const i=[];super(e("select",{onChange:()=>{t.setFinalValue(this.#I[this.domElement.selectedIndex])}},n.map((([t,n])=>(i.push(n),e("option",{textContent:t})))))),this.#I=i}updateDisplay(t){const e=this.#I.indexOf(t);this.domElement.selectedIndex=e}}function T(t,e){return Array.isArray(t)?Array.isArray(t[0])?t:e?t.map(((t,e)=>[t,e])):t.map((t=>[t,t])):[...Object.entries(t)]}class P extends I{constructor(t,e,n){super(t,e,"muigui-select");const i="number"==typeof this.getValue(),{keyValues:o}=n,s=T(o,i);this.add(new j(this,s)),this.updateDisplay()}}class z extends b{#E;#$;#C;#M;#u={step:.01,min:0,max:1,converters:F};constructor(t,n){const o=A();super(e("input",{type:"range",onInput:()=>{this.#M=!0;const{min:e,max:n,step:o}=this.#u,r=parseFloat(this.domElement.value),a=i(s(r,(t=>t),o),e,n),[l,u]=this.#$(a);l&&t.setValue(u)},onChange:()=>{this.#M=!0;const{min:e,max:n,step:o}=this.#u,r=parseFloat(this.domElement.value),a=i(s(r,(t=>t),o),e,n),[l,u]=this.#$(a);l&&t.setFinalValue(u)},onWheel:e=>{e.preventDefault();const[n,r]=this.#$(parseFloat(this.domElement.value));if(!n)return;const{min:a,max:l,step:u}=this.#u,c=o(e,u),h=i(s(r+c,(t=>t),u),a,l);t.setValue(h)}})),this.setOptions(n)}updateDisplay(t){this.#M||(this.domElement.value=s(t,this.#E,this.#C)),this.#M=!1}setOptions(t){a(this.#u,t);const{step:e,min:n,max:i,converters:{to:o,from:s}}=this.#u;return this.#E=o,this.#$=s,this.#C=e,this.domElement.step=e,this.domElement.min=n,this.domElement.max=i,this}}class B extends I{constructor(t,e,n){super(t,e,"muigui-range"),this.add(new z(this,n)),this.add(new U(this,n))}}class G extends b{#E;#$;#M;#u={converters:F};constructor(t,n){const i=t.setValue.bind(t),o=t.setFinalValue.bind(t);super(e("input",{type:"text",onInput:()=>this.#V(i,!0),onChange:()=>this.#V(o,!1)})),this.setOptions(n)}#V(t,e){const[n,i]=this.#$(this.domElement.value);n&&(this.#M=e,t(i)),this.domElement.style.color=n?"":"var(--invalid-color)"}updateDisplay(t){this.#M||(this.domElement.value=this.#E(t),this.domElement.style.color=""),this.#M=!1}setOptions(t){a(this.#u,t);const{converters:{to:e,from:n}}=this.#u;return this.#E=e,this.#$=n,this}}class H extends I{constructor(t,e){super(t,e,"muigui-checkbox"),this.add(new G(this)),this.updateDisplay()}}class R extends p{constructor(t,n){super(e(t,{className:n}))}}class Y extends S{#D;constructor(){super("muigui-canvas"),this.#D=this.add(new R("canvas","muigui-canvas")).domElement}get canvas(){return this.#D}}const W=(t,e,n)=>Math.max(e,Math.min(n,t)),q=t=>+t.toFixed(3),_=t=>parseInt(t.substring(1,3),16)<<16|parseInt(t.substring(3,5),16)<<8|parseInt(t.substring(5,7),16),J=t=>[parseInt(t.substring(1,3),16),parseInt(t.substring(3,5),16),parseInt(t.substring(5,7),16)],K=t=>`#${Array.from(t).map((t=>t.toString(16).padStart(2,"0"))).join("")}`,X=t=>J(t).map((t=>q(t/255))),Z=t=>K(Array.from(t).map((t=>Math.round(W(255*t,0,255))))),Q=t=>({r:parseInt(t.substring(1,3),16)/255,g:parseInt(t.substring(3,5),16)/255,b:parseInt(t.substring(5,7),16)/255}),tt=t=>W(Math.round(255*t),0,255).toString(16).padStart(2,"0"),et=t=>`rgb(${J(t).join(", ")})`,nt=/^\s*rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/,it=t=>{const e=rt(J(t)).map((t=>(t=>+t.toFixed(0))(t)));return`hsl(${e[0]}, ${e[1]}%, ${e[2]}%)`},ot=/^\s*hsl\(\s*(\d+)(?:deg|)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)\s*$/,st=(t,e)=>(t%e+e)%e;const rt=t=>{const[e,n,i]=function([t,e,n]){const i=Math.max(t,e,n),o=Math.min(t,e,n),s=.5*(o+i),r=i-o;let a=0,l=0;if(0!==r)switch(l=0===s||1===s?0:(i-s)/Math.min(s,1-s),i){case t:a=(e-n)/r+(et/255)));return[360*e,100*n,100*i]};function at([t,e,n]){return e=W(e,0,1),n=W(n,0,1),[t,t+2/3,t+1/3].map((t=>{return i=1,o=W(Math.abs(6*(t=>t>=0?t%1:1-t%1)(t)-3)-1,0,1),(i+(o-i)*e)*n;var i,o}))}const lt=t=>Math.round(1e3*t)/1e3;function ut([t,e,n]){const i=n>e?[n,e,-1,2/3]:[e,n,0,-1/3],o=i[0]>t?[i[0],i[1],i[3],t]:[t,i[1],i[2],i[0]],s=o[0]-Math.min(o[3],o[1]);return[Math.abs(o[2]+(o[3]-o[1])/(6*s+Number.EPSILON)),s/(o[0]+Number.EPSILON),o[0]].map(lt)}window.hsv01ToRGBFloat=at,window.rgbFloatToHSV01=ut;const ct=[{re:/^#(?:[0-9a-f]){6}$/i,format:"hex6"},{re:/^(?:[0-9a-f]){6}$/i,format:"hex6-no-hash"},{re:/^#(?:[0-9a-f]){3}$/i,format:"hex3"},{re:/^(?:[0-9a-f]){3}$/i,format:"hex3-no-hash"},{re:nt,format:"css-rgb"},{re:ot,format:"css-hsl"}];function ht(t){switch(typeof t){case"number":return"uint32-rgb";case"string":{const e=function(t){for(const e of ct)if(e.re.test(t))return e}(t.trim());if(e)return e.format;break}case"object":if(t instanceof Uint8Array||t instanceof Uint8ClampedArray){if(3===t.length)return"uint8-rgb"}else if(t instanceof Float32Array){if(3===t.length)return"float-rgb"}else if(Array.isArray(t)){if(3===t.length)return"float-rgb"}else if("r"in t&&"g"in t&&"b"in t)return"object-rgb"}throw new Error(`unknown color format: ${t}`)}function dt(t){return t.trim(t)}function pt(t){return t[1]===t[2]&&t[3]===t[4]&&t[5]===t[6]?`#${t[1]}${t[3]}${t[5]}`:t}const mt=/^(#|)([0-9a-f]{3})$/i;function gt(t){const e=mt.exec(t);if(e){const[,,t]=e;return"#"+`${(n=t)[0]}${n[0]}${n[1]}${n[1]}${n[2]}${n[2]}`}var n;return t}function ft(t){return pt(dt(t))}const bt=t=>{const e=nt.exec(t);if(!e)return[!1];const n=[e[1],e[2],e[3]].map((t=>parseInt(t)));return[!n.find((t=>t>255)),`rgb(${n.join(", ")})`]},vt=t=>{const e=ot.exec(t);if(!e)return[!1];const n=[e[1],e[2],e[3]].map((t=>parseFloat(t)));return[!n.find((t=>Number.isNaN(t))),`hsl(${n[0]}, ${n[1]}%, ${n[2]}%)`]},xt=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*$/,wt=/^\s*(?:0x){0,1}([0-9a-z]{1,6})\s*$/i,yt=/^\s*#[a-f0-9]{6}\s*$|^\s*#[a-f0-9]{3}\s*$/i,kt=/^\s*[a-f0-9]{6}\s*$/i,Et={hex6:{color:{from:t=>[!0,t],to:dt},text:{from:t=>[yt.test(t),t.trim()],to:t=>t}},hex3:{color:{from:t=>[!0,ft(t)],to:gt},text:{from:t=>[yt.test(t),pt(t.trim())],to:t=>t}},"hex6-no-hash":{color:{from:t=>[!0,t.substring(1)],to:t=>`#${dt(t)}`},text:{from:t=>[kt.test(t),t.trim()],to:t=>t}},"hex3-no-hash":{color:{from:t=>[!0,ft(t).substring(1)],to:gt},text:{from:t=>[kt.test(t),pt(t.trim())],to:t=>t}},"uint32-rgb":{color:{from:t=>[!0,_(t)],to:t=>`#${Math.round(t).toString(16).padStart(6,"0")}`},text:{from:t=>(t=>{const e=wt.exec(t);return e?[!0,parseInt(e[1],16)]:[!1]})(t),to:t=>`0x${t.toString(16).padStart(6,"0")}`}},"uint8-rgb":{color:{from:t=>[!0,J(t)],to:K},text:{from:t=>{const e=xt.exec(t);if(!e)return[!1];const n=[e[1],e[2],e[3]].map((t=>parseInt(t)));return[!n.find((t=>t>255)),n]},to:t=>t.join(", ")}},"float-rgb":{color:{from:t=>[!0,X(t)],to:Z},text:{from:t=>{const e=t.split(",").map((t=>t.trim())),n=e.map((t=>parseFloat(t)));if(3!==n.length)return[!1];const i=e.findIndex((t=>isNaN(t)));return[i<0,n.map((t=>q(t)))]},to:t=>Array.from(t).map((t=>q(t))).join(", ")}},"object-rgb":{color:{from:t=>[!0,Q(t)],to:t=>`#${tt(t.r)}${tt(t.g)}${tt(t.b)}`},text:{from:t=>{try{const e=t.replace(/([a-z])/g,'"$1"'),n=JSON.parse(e);if(Number.isNaN(n.r)||Number.isNaN(n.g)||Number.isNaN(n.b))throw new Error("not {r, g, b}");return[!0,n]}catch(t){return[!1]}},to:t=>`{r:${q(t.r)}, g:${q(t.g)}, b:${q(t.b)}}`}},"css-rgb":{color:{from:t=>[!0,et(t)],to:t=>{const e=nt.exec(t);return K([e[1],e[2],e[3]].map((t=>parseInt(t))))}},text:{from:bt,to:t=>bt(t)[1]}},"css-hsl":{color:{from:t=>[!0,it(t)],to:t=>{const e=ot.exec(t),n=function([t,e,n]){t=st(t,360),e=W(e/100,0,1),n=W(n/100,0,1);const i=e*Math.min(n,1-n);function o(e){const o=(e+t/30)%12;return n-i*Math.max(-1,Math.min(o-3,9-o,1))}return[o(0),o(8),o(4)].map((t=>Math.round(255*t)))}([e[1],e[2],e[3]].map((t=>parseFloat(t))));return K(n)}},text:{from:vt,to:t=>vt(t)[1]}}};class $t extends b{#E;#$;#F;#M;#u={converters:F};constructor(t,n){const i=e("input",{type:"color",onInput:()=>{const[e,n]=this.#$(i.value);e&&(this.#M=!0,t.setValue(n))},onChange:()=>{const[e,n]=this.#$(i.value);e&&(this.#M=!0,t.setFinalValue(n))}});super(e("div",{},[i])),this.setOptions(n),this.#F=i}updateDisplay(t){this.#M||(this.#F.value=this.#E(t)),this.#M=!1}setOptions(t){a(this.#u,t);const{converters:{to:e,from:n}}=this.#u;return this.#E=e,this.#$=n,this}}class Ct extends I{#L;#S;constructor(t,e,n={}){super(t,e,"muigui-color");const i=n.format||ht(this.getValue()),{color:o,text:s}=Et[i];this.#L=this.add(new $t(this,{converters:o})),this.#S=this.add(new G(this,{converters:s})),this.updateDisplay()}setOptions(t){const{format:e}=t;if(e){const{color:t,text:n}=Et[e];this.#L.setOptions({converters:t}),this.#S.setOptions({converters:n})}return super.setOptions(t),this}}class Mt extends m{constructor(){super("muigui-divider")}}class Vt extends m{#N;#A;constructor(t){super(t),this.#N=[],this.#A=this}get children(){return this.#N}get controllers(){return this.#N.filter((t=>!(t instanceof Vt)))}get folders(){return this.#N.filter((t=>t instanceof Vt))}reset(t=!0){for(const e of this.#N)e instanceof Vt&&!t||e.reset(t);return this}remove(t){const e=this.#N.indexOf(t);if(e>=0){const t=this.#N.splice(e,1)[0];t.domElement.remove(),t.setParent(null)}return this}_addControllerImpl(t){return this.domElement.appendChild(t.domElement),this.#N.push(t),t.setParent(this),t}addController(t){return this.#A._addControllerImpl(t)}pushContainer(t){return this.addController(t),this.#A=t,t}popContainer(){return this.#A=this.#A.parent,this}}class St extends Vt{#U;constructor(t="Controls",n="muigui-menu"){super(n),this.#U=e("label"),this.addElem(e("button",{type:"button",onClick:()=>this.toggleOpen()},[this.#U])),this.pushContainer(new Vt),this.name(t),this.open()}open(t=!0){return this.domElement.classList.toggle("muigui-closed",!t),this.domElement.classList.toggle("muigui-open",t),this}close(){return this.open(!1)}name(t){return this.#U.textContent=t,this}title(t){return this.name(t)}toggleOpen(){return this.open(!this.domElement.classList.contains("muigui-open")),this}}class It extends m{constructor(t){super("muigui-label"),this.text(t)}text(t){return this.domElement.textContent=t,this}}class Dt extends St{add(t,e,...n){const i=t instanceof m?t:function(t,e,...n){const[i]=n;if(Array.isArray(i))return new P(t,e,{keyValues:i});const o=typeof t[e];switch(o){case"number":if("number"==typeof n[0]&&"number"==typeof n[1]){const i=n[0],o=n[1],s=n[2];return new B(t,e,{min:i,max:o,...s&&{step:s}})}return 0===n.length?new O(t,e,...n):new B(t,e,...n);case"boolean":return new D(t,e,...n);case"function":return new g(t,e,...n);case"string":return new H(t,e,...n);case"undefined":throw new Error(`no property named ${e}`);default:throw new Error(`unhandled type ${o} for property ${e}`)}}(t,e,...n);return this.addController(i)}addCanvas(t){return this.addController(new Y(t))}addColor(t,e,...n){return this.addController(new Ct(t,e,...n))}addDivider(){return this.addController(new Mt)}addFolder(t){return this.addController(new Dt(t))}addLabel(t){return this.addController(new It(t))}}class Ft extends HTMLElement{constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}}customElements.define("muigui-element",Ft);const Lt=new CSSStyleSheet;Lt.replaceSync(t.default);const Nt=new CSSStyleSheet;function At(t){let e,n;function i(){if(e&&!n){const o=e;e=void 0,n=t.replace(o).then((()=>{console.log(o),n=void 0,i()}))}}return function(t){e=t,i()}}const Ut=At(Lt),Ot=At(Nt);class jt extends Dt{static converters=N;static mapRange=l;static makeRangeConverters=u;static makeRangeOptions=c;static makeMinMaxPair=d;#O=new CSSStyleSheet;constructor(t={}){super("Controls","muigui-root"),t instanceof HTMLElement&&(t={parent:t});const{autoPlace:n=!0,width:i,title:o="Controls"}=t;let{parent:s}=t;if(i&&(this.domElement.style.width=/^\d+$/.test(i)?`${i}px`:i),void 0===s&&n&&(s=document.body,this.domElement.classList.add("muigui-auto-place")),s){const t=e("muigui-element");t.shadowRoot.adoptedStyleSheets=[Lt,Nt,this.#O],t.shadow.appendChild(this.domElement),s.appendChild(t)}o&&this.title(o),this.domElement.classList.add("muigui","muigui-colors")}setStyle(t){this.#O.replace(t)}static setBaseStyles(t){Ut(t)}static getBaseStyleSheet(){return Lt}static setUserStyles(t){Ot(t)}static getUserStyleSheet(){return Nt}static setTheme(e){jt.setBaseStyles(`${t.default}\n${t.themes[e]||""}`)}}function Tt(){}function Pt(t,e,n){const i=t.getBoundingClientRect(),o=e.clientX-i.left,s=e.clientY-i.top,r=o/i.width,a=s/i.height,l=o-(n=n||[o,s])[0],u=s-n[1];return{x:o,y:s,nx:r,ny:a,dx:l,dy:u,ndx:l/i.width,ndy:u/i.width}}function zt(t,{onDown:e=Tt,onMove:n=Tt,onUp:i=Tt}){let o;const s=function(e){const i={type:"move",...Pt(t,e,o)};n(i)},r=function(e){t.releasePointerCapture(e.pointerId),t.removeEventListener("pointermove",s),t.removeEventListener("pointerup",r),document.body.style.backgroundColor="",i("up")},a=function(n){t.addEventListener("pointermove",s),t.addEventListener("pointerup",r),t.setPointerCapture(n.pointerId);const i=Pt(t,n);o=[i.x,i.y],e({type:"down",...i})};return t.addEventListener("pointerdown",a),function(){t.removeEventListener("pointerdown",a)}}class Bt extends b{#j;#T;#P;#z;#B;#G;#H;#R;constructor(t){super(e("div",{innerHTML:'\n\n\n \n \n \n \n \n \n \n \n\n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n\n',className:"muigui-no-scroll"})),this.#j=this.domElement.children[0],this.#T=this.domElement.children[1],this.#P=this.$(".muigui-color-chooser-circle"),this.#z=this.$("#muigui-color-chooser-hue"),this.#B=this.$(".muigui-color-chooser-cursor");const n=e=>{const n=i(e.nx,0,1),o=i(e.ny,0,1);this.#G[1]=n,this.#G[2]=1-o,this.#H=!0,t.setValue(Z(at(this.#G)))},o=e=>{const n=i(e.nx,0,1);this.#G[0]=n,this.#R=!0,t.setValue(Z(at(this.#G)))};zt(this.#j,{onDown:n,onMove:n}),zt(this.#T,{onDown:o,onMove:o})}updateDisplay(t){this.#G||(this.#G=ut(X(t)));{const[e,n,i]=ut(X(t));this.#H||(this.#G[0]=n>.001&&i>.001?e:this.#G[0]),this.#R||(this.#G[1]=n,this.#G[2]=i)}{const[t,e,n]=this.#G;this.#H||(this.#B.setAttribute("transform",`translate(${64*t}, 0)`),this.#z.children[0].setAttribute("stop-color",`hsl(${360*t}, 0%, 100%)`),this.#z.children[1].setAttribute("stop-color",`hsl(${360*t}, 100%, 50%)`)),this.#R||(this.#P.setAttribute("cx",""+64*e),this.#P.setAttribute("cy",""+48*(1-n)))}this.#H=!1,this.#R=!1}}class Gt extends I{#Y;#W;#q;#u={open:!1};constructor(t,n,i={}){super(t,n,"muigui-pop-down-controller"),this.#Y=this.add(new R("div","muigui-pop-down-top"));const o=this.#Y.addElem(e("input",{type:"checkbox",onChange:()=>{this.#u.open=o.checked}}));this.#W=this.#Y.add(new R("div","muigui-pop-down-values")),this.#q=this.add(new R("div","muigui-pop-down-bottom")),this.setOptions(i)}updateDisplay(){super.updateDisplay();const{open:t}=this.#u;this.domElement.children[1].classList.toggle("muigui-open",t),this.domElement.children[1].classList.toggle("muigui-closed",!t)}setOptions(t){a(this.#u,t),super.setOptions(t),this.updateDisplay()}addTop(t){return this.#W.add(t)}addBottom(t){return this.#q.add(t)}}class Ht extends Gt{constructor(t,e){super(t,e,"muigui-color-chooser"),this.addTop(new G(this)),this.addBottom(new Bt(this)),this.updateDisplay()}}function Rt(){}const Yt={ArrowLeft:[-1,0],ArrowRight:[1,0],ArrowUp:[0,-1],ArrowDown:[0,1]};function Wt(t,{onDown:e=Rt,onUp:n=Rt}){const i=function(t){const i=t.shiftKey?10:1,[o,s]=(Yt[t.key]||[0,0]).map((t=>t*i));("keydown"===t.type?e:n)({type:t.type.substring(3),dx:o,dy:s,event:t})};return t.addEventListener("keydown",i),t.addEventListener("keyup",i),function(){t.removeEventListener("keydown",i),t.removeEventListener("keyup",i)}}function qt(t,e=""){if(!t)throw new Error(e)}function _t(t,e,n,i,o,s){const r=Math.abs(n)*Math.cos(s),a=Math.abs(i)*Math.sin(s);return[t+Math.cos(o)*r-Math.sin(o)*a,e+Math.sin(o)*r+Math.cos(o)*a]}function Jt(t,e,n,i,o){qt(Math.abs(i-o)<=2*Math.PI),qt(i>=-Math.PI&&i<=2*Math.PI),qt(i<=o),qt(o>=-Math.PI&&o<=4*Math.PI);const{x1:s,y1:r,x2:a,y2:l,fa:u,fs:c}=function(t,e,n,i,o,s,r){const[a,l]=_t(t,e,n,i,o,s),[u,c]=_t(t,e,n,i,o,s+r);return{x1:a,y1:l,x2:u,y2:c,fa:Math.abs(r)>Math.PI?1:0,fs:r>0?1:0}}(t,e,n,n,0,i,o-i);return Math.abs(Math.abs(i-o)-2*Math.PI)>Number.EPSILON?`M${t} ${e} L${s} ${r} A ${n} ${n} 0 ${u} ${c} ${a} ${l} L${t} ${e}`:`M${s} ${r} L${s} ${r} A ${n} ${n} 0 ${u} ${c} ${a} ${l}`}const Kt=t=>r(t+Math.PI,2*Math.PI)-Math.PI;class Xt extends b{#_;#J;#K;#X;#u={step:1,min:-180,max:180,dirMin:-Math.PI,dirMax:Math.PI,wrap:void 0,converters:F};constructor(t,n={}){const o=A();super(e("div",{className:"muigui-direction muigui-no-scroll",innerHTML:'\n\n \x3c!----\x3e\n \n \n \n \n \n \n\n',onWheel:e=>{e.preventDefault();const{min:n,max:a,step:l}=this.#u,u=o(e,l);let c=this.#K+u;this.#X&&(c=r(c-n,a-n)+n);const h=i(s(c,(t=>t),l),n,a);t.setValue(h)}}));const a=e=>{const{min:n,max:o,step:r,dirMin:a,dirMax:l}=this.#u,u=2*e.nx-1,c=2*e.ny-1,h=Math.atan2(c,u),d=(a+l)/2,p=i((Kt(h-d)-Kt(a-d))/(l-a),0,1),m=s(n+(o-n)*p,(t=>t),r);t.setValue(m)};zt(this.domElement,{onDown:a,onMove:a}),Wt(this.domElement,{onDown:e=>{const{min:n,max:o,step:r}=this.#u,a=i(s(this.#K+e.dx*r,(t=>t),r),n,o);t.setValue(a)}}),this.#_=this.$("#muigui-arrow"),this.#J=this.$("#muigui-range"),this.setOptions(n)}updateDisplay(t){this.#K=t;const{min:e,max:n}=this.#u,i=(t-e)/(n-e),o=(s=this.#u.dirMin,r=this.#u.dirMax,s+(r-s)*i);var s,r;this.#_.style.transform=`rotate(${o}rad)`}setOptions(t){a(this.#u,t);const{dirMin:e,dirMax:n,wrap:i}=this.#u;this.#X=void 0!==i?i:Math.abs(e-n)>=2*Math.PI-Number.EPSILON;const[o,s]=e(o.push(i),e("label",{},[e("input",{type:"radio",name:s,value:a,onChange:function(){this.checked&&t.setFinalValue(r.#I[this.value])}}),e("button",{type:"button",textContent:n,onClick:function(){this.previousElementSibling.click()}})]))))));const r=this;this.#I=o,this.cols(i)}updateDisplay(t){const e=this.#I.indexOf(t);for(let t=0;t{e({rect:t.getBoundingClientRect(),elem:t})})).observe(t)}function ne(t,e,n,i){ee(t,(({rect:o})=>{const{width:s,height:r}=o;t.setAttribute("viewBox",`-${s*e} -${r*n} ${s} ${r}`),i({elem:t,rect:o})}))}function ie(t,e,n,i,o,r){const a=[];tt),n)),e=Math.min(e,o);for(let i=t;i<=e;i+=n)a.push(`M${i} 0 l0 ${r}`);return a.join(" ")}class oe extends b{#Z;#Q;#tt;#et;#nt;#it;#ot;#st;#rt;#K;#at;#u={min:-100,max:100,step:1,unit:10,unitSize:10,ticksPerUnit:5,labelFn:t=>t,tickHeight:1,limits:!0,thicksColor:void 0,orientation:void 0};constructor(t,n){const o=A();let r;super(e("div",{innerHTML:'\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \x3c!----\x3e\n \x3c!----\x3e\n \n \n \n \n\n',className:"muigui-no-v-scroll",onWheel:e=>{e.preventDefault();const{min:n,max:r,step:a}=this.#u,l=o(e,a),u=i(s(this.#K+l,(t=>t),a),n,r);t.setValue(u)}})),this.#Z=this.$("svg"),this.#Q=this.$("#muigui-origin"),this.#tt=this.$("#muigui-ticks"),this.#et=this.$("#muigui-thicks"),this.#nt=this.$("#muigui-numbers"),this.#it=this.$("#muigui-left-grad"),this.#ot=this.$("#muigui-right-grad"),this.setOptions(n),zt(this.domElement,{onDown:()=>{r=this.#K},onMove:e=>{const{min:n,max:o,unitSize:a,unit:l,step:u}=this.#u,c=i(s(r-e.dx/a*l,(t=>t),u),n,o);t.setValue(c)}}),Wt(this.domElement,{onDown:e=>{const{min:n,max:o,step:r}=this.#u,a=i(s(this.#K+e.dx*r,(t=>t),r),n,o);t.setValue(a)}}),ne(this.#Z,.5,0,(({rect:{width:t}})=>{this.#it.setAttribute("x",-t/2),this.#ot.setAttribute("x",t/2-20),this.#at=function(t){const e=t.innerHTML;t.innerHTML="- ";const n=t.querySelector("text").getComputedTextLength();return t.innerHTML=e,n}(this.#nt),this.#st=t,this.#lt()}))}#lt(){if(!this.#st||void 0===this.#K)return;const{labelFn:t,limits:e,min:n,max:i,orientation:o,tickHeight:r,ticksPerUnit:a,unit:l,unitSize:u,thicksColor:c}=this.#u,h=Math.ceil(this.#st/u),d=this.#K/l,p=Math.round(d-h),m=p*u,g=(p+2*h)*u,f=e?n*u/l:m,b=e?i*u/l:g,v=""===t(1)?10:5;a>1&&this.#tt.setAttribute("d",ie(m,g,u/a,f,b,v*r)),this.#et.style.stroke=c,this.#et.setAttribute("d",ie(m,g,u,f,b,v)),this.#nt.innerHTML=function(t,e,n,i,o,r,a,l){const u=[];tt),n)),e=Math.min(e,a);const c=Math.max(0,-Math.log10(i));for(let s=t;s<=e;s+=n)u.push(`${h=s/n*i,l(h.toFixed(c))}`);var h;return u.join("\n")}(m,g,u,l,this.#at,f,b,t),this.#Q.setAttribute("transform",`translate(${-this.#K*u/l} 0)`),this.#Z.classList.toggle("muigui-slider-up","up"===o)}updateDisplay(t){this.#K=t,this.#lt()}setOptions(t){return a(this.#u,t),this}}class se extends I{constructor(t,e,n={}){super(t,e,"muigui-slider"),this.add(new oe(this,n)),this.add(new U(this,n)),this.updateDisplay()}}class re extends b{#Z;#_;#P;#K=[];constructor(t){super(e("div",{innerHTML:'\n\n \n \n \n \n \n\n',className:"muigui-no-scroll"}));const n=e=>{const{width:n,height:i}=this.#Z.getBoundingClientRect(),o=2*e.nx-1,s=2*e.ny-1;t.setValue([o*n*.5,s*i*.5])};zt(this.domElement,{onDown:n,onMove:n}),this.#Z=this.$("svg"),this.#_=this.$("#muigui-arrow"),this.#P=this.$("#muigui-circle"),ne(this.#Z,.5,.5,(()=>this.#ut))}#ut(){const[t,e]=this.#K;this.#_.setAttribute("d",`M0,0L${t},${e}`),this.#P.setAttribute("transform",`translate(${t}, ${e})`)}updateDisplay(t){this.#K[0]=t[0],this.#K[1]=t[1],this.#ut()}}class ae extends Gt{constructor(t,e){super(t,e,"muigui-vec2");const n=t=>({setValue:e=>{const n=this.getValue();n[t]=e,this.setValue(n)},setFinalValue:e=>{const n=this.getValue();n[t]=e,this.setFinalValue(n)}});this.addTop(new U(n(0),{converters:{to:t=>t[0],from:L.from}})),this.addTop(new U(n(1),{converters:{to:t=>t[1],from:L.from}})),this.addBottom(new re(this)),this.updateDisplay()}}export{Ht as ColorChooser,Zt as Direction,te as RadioGrid,B as Range,P as Select,se as Slider,O as TextNumber,ae as Vec2,jt as default}; +var t={default:'\n.muigui {\n --bg-color: #ddd;\n --color: #222;\n --contrast-color: #eee;\n --value-color: #145 ;\n --value-bg-color: #eeee;\n --disabled-color: #999;\n --menu-bg-color: #f8f8f8;\n --menu-sep-color: #bbb;\n --hover-bg-color: #999;\n --focus-color: #68C;\n --range-color: #888888;\n --invalid-color: #FF0000;\n --selected-color: rgb(255, 255, 255, 0.9);\n\n --button-bg-color: var(--value-bg-color);\n\n --range-left-color: var(--value-color);\n --range-right-color: var(--value-bg-color); \n --range-right-hover-color: var(--hover-bg-color);\n\n color: var(--color);\n background-color: var(--bg-color);\n}\n\n@media (prefers-color-scheme: dark) {\n .muigui {\n --bg-color: #222222;\n --color: #dddddd;\n --contrast-color: #000;\n --value-color: #43e5f7;\n --value-bg-color: #444444;\n --disabled-color: #666666;\n --menu-bg-color: #080808;\n --menu-sep-color: #444444;\n --hover-bg-color: #666666;\n --focus-color: #88AAFF;\n --range-color: #888888;\n --invalid-color: #FF6666;\n --selected-color: rgba(255, 255, 255, 0.3);\n\n --button-bg-color: var(--value-bg-color);\n\n --range-left-color: var(--value-color);\n --range-right-color: var(--value-bg-color); \n --range-right-hover-color: var(--hover-bg-color);\n\n color: var(--color);\n background-color: var(--bg-color);\n }\n}\n\n.muigui {\n --width: 250px;\n --label-width: 45%;\n --number-width: 40%;\n\n\n --font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;\n --font-size: 11px;\n --font-family-mono: Menlo, Monaco, Consolas, "Droid Sans Mono", monospace;\n --font-size-mono: 11px;\n\n --line-height: 1.7em;\n --border-radius: 0px;\n\n width: var(--width);\n font-family: var(--font-family);\n font-size: var(--font-size);\n box-sizing: border-box;\n line-height: 100%;\n}\n.muigui * {\n box-sizing: inherit;\n}\n\n.muigui-no-scroll {\n touch-action: none;\n}\n.muigui-no-h-scroll {\n touch-action: pan-y;\n}\n.muigui-no-v-scroll {\n touch-action: pan-x;\n}\n\n.muigui-invalid-value {\n background-color: red !important;\n color: white !important;\n}\n\n.muigui-grid {\n display: grid;\n}\n.muigui-rows {\n display: flex;\n flex-direction: column;\n\n min-height: 20px;\n border: 2px solid red;\n}\n.muigui-columns {\n display: flex;\n flex-direction: row;\n\n height: 20px;\n border: 2px solid green;\n}\n.muigui-rows>*,\n.muigui-columns>* {\n flex: 1 1 auto;\n align-items: stretch;\n min-height: 0;\n min-width: 0;\n}\n\n.muigui-row {\n border: 2px solid yellow;\n min-height: 10px\n}\n.muigui-column {\n border: 2px solid lightgreen;\n}\n\n/* -------- */\n\n.muigui-show { /* */ }\n.muigui-hide { \n display: none !important;\n}\n.muigui-disabled {\n pointer-events: none;\n --color: var(--disabled-color) !important;\n --value-color: var(--disabled-color) !important;\n --range-left-color: var(--disabled-color) !important;\n}\n\n.muigui canvas,\n.muigui svg {\n display: block;\n border-radius: var(--border-radius);\n}\n.muigui canvas {\n background-color: var(--value-bg-color);\n}\n\n.muigui-controller {\n min-width: 0;\n min-height: var(--line-height);\n}\n.muigui-root,\n.muigui-menu {\n display: flex;\n flex-direction: column;\n position: relative;\n user-select: none;\n height: fit-content;\n margin: 0;\n padding-bottom: 0.1em;\n border-radius: var(--border-radius);\n}\n.muigui-menu {\n border-bottom: 1px solid var(--menu-sep-color);\n}\n\n.muigui-root>button:nth-child(1),\n.muigui-menu>button:nth-child(1) {\n border-top: 1px solid var(--menu-sep-color);\n border-bottom: 1px solid var(--menu-sep-color);\n position: relative;\n text-align: left;\n color: var(--color);\n background-color: var(--menu-bg-color);\n min-height: var(--line-height);\n padding-top: 0.2em;\n padding-bottom: 0.2em;\n cursor: pointer;\n border-radius: var(--border-radius);\n}\n.muigui-root>div:nth-child(2),\n.muigui-menu>div:nth-child(2) {\n flex: 1 1 auto;\n}\n\n.muigui-controller {\n margin-left: 0.2em;\n margin-right: 0.2em;\n}\n.muigui-root.muigui-controller,\n.muigui-menu.muigui-controller {\n margin-left: 0;\n margin-right: 0;\n}\n.muigui-controller>*:nth-child(1) {\n flex: 1 0 var(--label-width);\n min-width: 0;\n white-space: pre;\n}\n.muigui-controller>label:nth-child(1) {\n place-content: center start;\n display: inline-grid;\n overflow: hidden;\n}\n.muigui-controller>*:nth-child(2) {\n flex: 1 1 75%;\n min-width: 0;\n}\n\n/* -----------------------------------------\n a label controller is [[label][value]]\n*/\n\n.muigui-label-controller {\n display: flex;\n margin: 0.4em 0 0.4em 0;\n word-wrap: initial;\n align-items: stretch;\n}\n\n.muigui-value {\n display: flex;\n align-items: stretch;\n}\n.muigui-value>* {\n flex: 1 1 auto;\n min-width: 0;\n}\n.muigui-value>*:nth-child(1) {\n flex: 1 1 calc(100% - var(--number-width));\n}\n.muigui-value>*:nth-child(2) {\n flex: 1 1 var(--number-width);\n margin-left: 0.2em;\n}\n\n/* fix! */\n.muigui-open>button>label::before,\n.muigui-closed>button>label::before {\n width: 1.25em;\n height: var(--line-height);\n display: inline-grid;\n place-content: center start;\n pointer-events: none;\n}\n.muigui-open>button>label::before {\n content: "ⓧ"; /*"▼";*/\n}\n.muigui-closed>button>label::before {\n content: "⨁"; /*"▶";*/\n}\n.muigui-open>*:nth-child(2) {\n transition: max-height 0.2s ease-out,\n opacity 0.5s ease-out;\n max-height: 100vh;\n overflow: auto;\n opacity: 1;\n}\n\n.muigui-closed>*:nth-child(2) {\n transition: max-height 0.2s ease-out,\n opacity 1s;\n max-height: 0;\n opacity: 0;\n overflow: hidden;\n}\n\n/* ---- popdown ---- */\n\n.muigui-pop-down-top {\n display: flex;\n}\n/* fix? */\n.muigui-value>*:nth-child(1).muigui-pop-down-top {\n flex: 0;\n}\n.muigui-pop-down-bottom {\n\n}\n\n.muigui-pop-down-values {\n min-width: 0;\n display: flex;\n}\n.muigui-pop-down-values>* {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.muigui-value.muigui-pop-down-controller {\n flex-direction: column;\n}\n\n.muigui-pop-down-top input[type=checkbox] {\n -webkit-appearance: none;\n appearance: none;\n width: auto;\n color: var(--value-color);\n background-color: var(--value-bg-color);\n cursor: pointer;\n\n display: grid;\n place-content: center;\n margin: 0;\n font: inherit;\n color: currentColor;\n width: 1.7em;\n height: 1.7em;\n transform: translateY(-0.075em);\n}\n\n.muigui-pop-down-top input[type=checkbox]::before {\n content: "+";\n display: grid;\n place-content: center;\n border-radius: calc(var(--border-radius) + 2px);\n border-left: 1px solid rgba(255,255,255,0.3);\n border-top: 1px solid rgba(255,255,255,0.3);\n border-bottom: 1px solid rgba(0,0,0,0.2);\n border-right: 1px solid rgba(0,0,0,0.2);\n background-color: var(--range-color);\n color: var(--value-bg-color);\n width: calc(var(--line-height) - 4px);\n height: calc(var(--line-height) - 4px);\n}\n\n.muigui-pop-down-top input[type=checkbox]:checked::before {\n content: "X";\n}\n\n\n/* ---- select ---- */\n\n.muigui select,\n.muigui option,\n.muigui input,\n.muigui button {\n color: var(--value-color);\n background-color: var(--value-bg-color);\n font-family: var(--font-family);\n font-size: var(--font-size);\n border: none;\n margin: 0;\n border-radius: var(--border-radius);\n}\n.muigui select {\n appearance: none;\n margin: 0;\n margin-left: 0; /*?*/\n overflow: hidden; /* Safari */\n}\n\n.muigui select:focus,\n.muigui input:focus,\n.muigui button:focus {\n outline: 1px solid var(--focus-color);\n}\n\n.muigui select:hover,\n.muigui option:hover,\n.muigui input:hover,\n.muigui button:hover {\n background-color: var(--hover-bg-color); \n}\n\n/* ------ [ label ] ------ */\n\n.muigui-label {\n border-top: 1px solid var(--menu-sep-color);\n border-bottom: 1px solid var(--menu-sep-color);\n padding-top: 0.4em;\n padding-bottom: 0.3em;\n place-content: center start;\n background-color: var(--menu-bg-color);\n white-space: pre;\n border-radius: var(--border-radius);\n}\n\n/* ------ [ divider] ------ */\n\n.muigui-divider {\n min-height: 6px;\n border-top: 2px solid var(--menu-sep-color);\n margin-top: 6px;\n}\n\n/* ------ [ button ] ------ */\n\n.muigui-button {\n display: grid;\n\n}\n.muigui-button button {\n border: none;\n color: var(--value-color);\n background-color: var(--button-bg-color);\n cursor: pointer;\n place-content: center center;\n}\n\n/* ------ [ color ] ------ */\n\n.muigui-color>div {\n overflow: hidden;\n position: relative;\n margin-left: 0;\n margin-right: 0; /* why? */\n max-width: var(--line-height);\n border-radius: var(--border-radius);\n}\n\n.muigui-color>div:focus-within {\n outline: 1px solid var(--focus-color);\n}\n\n.muigui-color input[type=color] {\n border: none;\n padding: 0;\n background: inherit;\n cursor: pointer;\n position: absolute;\n width: 200%;\n left: -10px;\n top: -10px;\n height: 200%;\n}\n.muigui-disabled canvas,\n.muigui-disabled svg,\n.muigui-disabled img,\n.muigui-disabled .muigui-color input[type=color] {\n opacity: 0.2;\n}\n\n/* ------ [ checkbox ] ------ */\n\n.muigui-checkbox>label:nth-child(2) {\n display: grid;\n place-content: center start;\n margin: 0;\n}\n\n.muigui-checkbox input[type=checkbox] {\n -webkit-appearance: none;\n appearance: none;\n width: auto;\n color: var(--value-color);\n background-color: var(--value-bg-color);\n cursor: pointer;\n\n display: grid;\n place-content: center;\n margin: 0;\n font: inherit;\n color: currentColor;\n width: 1.7em;\n height: 1.7em;\n transform: translateY(-0.075em);\n}\n\n.muigui-checkbox input[type=checkbox]::before {\n content: "";\n color: var(--value-color);\n display: grid;\n place-content: center;\n}\n\n.muigui-checkbox input[type=checkbox]:checked::before {\n content: "✔";\n}\n\n.muigui input[type=number]::-webkit-inner-spin-button, \n.muigui input[type=number]::-webkit-outer-spin-button { \n -webkit-appearance: none;\n appearance: none;\n margin: 0; \n}\n.muigui input[type=number] {\n -moz-appearance: textfield;\n}\n\n/* ------ [ radio grid ] ------ */\n\n.muigui-radio-grid>div {\n display: grid;\n gap: 2px;\n}\n\n.muigui-radio-grid input {\n appearance: none;\n display: none;\n}\n\n.muigui-radio-grid button {\n color: var(--color);\n width: 100%;\n text-align: left;\n}\n\n.muigui-radio-grid input:checked + button {\n color: var(--value-color);\n background-color: var(--selected-color);\n}\n\n/* ------ [ color-chooser ] ------ */\n\n.muigui-color-chooser-cursor {\n stroke-width: 1px;\n stroke: white;\n fill: none;\n}\n.muigui-color-chooser-circle {\n stroke-width: 1px;\n stroke: white;\n fill: none;\n}\n\n\n/* ------ [ vec2 ] ------ */\n\n.muigui-vec2 svg {\n background-color: var(--value-bg-color);\n}\n\n.muigui-vec2-axis {\n stroke: 1px;\n stroke: var(--focus-color);\n}\n\n.muigui-vec2-line {\n stroke-width: 1px;\n stroke: var(--value-color);\n fill: var(--value-color);\n}\n\n/* ------ [ direction ] ------ */\n\n.muigui-direction svg {\n background-color: rgba(0,0,0,0.2);\n}\n\n.muigui-direction:focus-within svg {\n outline: none;\n}\n.muigui-direction-range {\n fill: var(--value-bg-color);\n}\n.muigui-direction svg:focus {\n outline: none;\n}\n.muigui-direction svg:focus .muigui-direction-range {\n stroke-width: 0.5px;\n stroke: var(--focus-color);\n}\n\n.muigui-direction-arrow {\n fill: var(--value-color);\n}\n\n/* ------ [ slider ] ------ */\n\n.muigui-slider>div {\n display: flex;\n align-items: stretch;\n height: var(--line-height);\n}\n.muigui-slider svg {\n flex: 1 1 auto;\n}\n.muigui-slider .muigui-slider-up #muigui-orientation {\n transform: scale(1, -1) translateY(-100%);\n}\n\n.muigui-slider .muigui-slider-up #muigui-number-orientation {\n transform: scale(1,-1);\n}\n\n.muigui-ticks {\n stroke: var(--range-color);\n}\n.muigui-thicks {\n stroke: var(--color);\n stroke-width: 2px;\n}\n.muigui-svg-text {\n fill: var(--color);\n font-size: 7px;\n}\n.muigui-mark {\n fill: var(--value-color);\n}\n\n/* ------ [ range ] ------ */\n\n\n.muigui-range input[type=range] {\n -webkit-appearance: none;\n appearance: none;\n background-color: transparent;\n}\n\n.muigui-range input[type=range]::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n border-radius: calc(var(--border-radius) + 2px);\n border-left: 1px solid rgba(255,255,255,0.3);\n border-top: 1px solid rgba(255,255,255,0.3);\n border-bottom: 1px solid rgba(0,0,0,0.2);\n border-right: 1px solid rgba(0,0,0,0.2);\n background-color: var(--range-color);\n margin-top: calc((var(--line-height) - 2px) / -2);\n width: calc(var(--line-height) - 2px);\n height: calc(var(--line-height) - 2px);\n}\n\n.muigui-range input[type=range]::-webkit-slider-runnable-track {\n -webkit-appearance: none;\n appearance: none;\n border: 1px solid var(--menu-sep-color);\n height: 2px;\n}\n\n\n/* dat.gui style - doesn\'t work on Safari iOS */\n\n/*\n.muigui-range input[type=range] {\n cursor: ew-resize;\n overflow: hidden;\n}\n\n.muigui-range input[type=range] {\n -webkit-appearance: none;\n appearance: none;\n background-color: var(--range-right-color);\n margin: 0;\n}\n.muigui-range input[type=range]:hover {\n background-color: var(--range-right-hover-color);\n}\n\n.muigui-range input[type=range]::-webkit-slider-runnable-track {\n -webkit-appearance: none;\n appearance: none;\n height: max-content;\n color: var(--range-left-color);\n margin-top: -1px;\n}\n\n.muigui-range input[type=range]::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 0px;\n height: max-content;\n box-shadow: -1000px 0 0 1000px var(--range-left-color);\n}\n*/\n\n/* FF */\n/*\n.muigui-range input[type=range]::-moz-slider-progress {\n background-color: var(--range-left-color); \n}\n.muigui-range input[type=range]::-moz-slider-thumb {\n height: max-content;\n width: 0;\n border: none;\n box-shadow: -1000px 0 0 1000px var(--range-left-color);\n box-sizing: border-box;\n}\n*/\n\n/* ---------------------------------------------------------- */\n\n/* needs to be at bottom to take precedence */\n.muigui-auto-place {\n max-height: 100%;\n position: fixed;\n top: 0;\n right: 15px;\n z-index: 100001;\n}\n\n',themes:{default:"",float:"\n :root {\n color-scheme: light dark,\n }\n\n .muigui {\n --width: 400px;\n --bg-color: initial;\n --label-width: 25%;\n }\n\n input,\n .muigui-label-controller>label {\n text-shadow:\n -1px -1px 0 var(--contrast-color),\n 1px -1px 0 var(--contrast-color),\n -1px 1px 0 var(--contrast-color),\n 1px 1px 0 var(--contrast-color);\n }\n\n .muigui-controller > label:nth-child(1) {\n place-content: center end;\n margin-right: 1em;\n }\n\n .muigui-value > :nth-child(2) {\n margin-left: 1em;\n }\n\n .muigui-root>*:nth-child(1) {\n display: none;\n }\n\n .muigui-range input[type=range]::-webkit-slider-thumb {\n border-radius: 1em;\n }\n\n .muigui-range input[type=range]::-webkit-slider-runnable-track {\n -webkit-appearance: initial;\n appearance: none;\n border: 1px solid rgba(0, 0, 0, 0.25);\n height: 2px;\n }\n\n .muigui-colors {\n --value-color: var(--color );\n --value-bg-color: rgba(0, 0, 0, 0.1);\n --disabled-color: #cccccc;\n --menu-bg-color: rgba(0, 0, 0, 0.1);\n --menu-sep-color: #bbbbbb;\n --hover-bg-color: rgba(0, 0, 0, 0);\n --invalid-color: #FF0000;\n --selected-color: rgba(0, 0, 0, 0.3);\n --range-color: rgba(0, 0, 0, 0.125);\n }\n"}};function e(t,e={},n=[]){const i=document.createElement(t);return function(t,e,n){for(const[n,i]of Object.entries(e))if("function"==typeof i&&n.startsWith("on")){const e=n.substring(2).toLowerCase();t.addEventListener(e,i,{passive:!1})}else if("object"==typeof i)for(const[e,o]of Object.entries(i))t[n][e]=o;else void 0===t[n]?t.setAttribute(n,i):t[n]=i;for(const e of n)t.appendChild(e)}(i,e,n),i}function n(t,e){const n=t.indexOf(e);return n&&t.splice(n,1),t}function i(t,e,n){return Math.max(e,Math.min(n,t))}const o="undefined"!=typeof SharedArrayBuffer?function(t){return t&&t.buffer&&(t.buffer instanceof ArrayBuffer||t.buffer instanceof SharedArrayBuffer)}:function(t){return t&&t.buffer&&t.buffer instanceof ArrayBuffer},s=(t,e,n)=>Math.round(e(t)/n)/(1/n),r=(t,e)=>(t%e+e)%e;function a(t,e){for(const n in e)n in t&&(t[n]=e[n]);return t}const l=(t,e,n,i,o)=>(t-e)*(o-i)/(n-e)+i,u=({from:t,to:e})=>({to:n=>l(n,...t,...e),from:n=>[!0,l(n,...e,...t)]}),c=({from:t,to:e,step:n})=>({min:e[0],max:e[1],...n&&{step:n},converters:u({from:t,to:e})}),h={to:t=>t,from:t=>[!0,t]};function d(t,e,n,i,o){const{converters:{from:s}=h}=o,{min:r,max:a}=o,l=o.minRange||0,u=s(l)[1],c=t.add(e,n,{...o,min:r,max:a-l}).onChange((t=>{d.setValue(Math.min(a,Math.max(t+u,e[i])))})),d=t.add(e,i,{...o,min:r+l,max:a}).onChange((t=>{c.setValue(Math.max(r,Math.min(t-u,e[n])))}));return[c,d]}class p{#t;#e=[];constructor(t){this.domElement=t,this.#t=t}addElem(t){return this.#t.appendChild(t),t}removeElem(t){return this.#t.removeChild(t),t}pushSubElem(t){this.#t.appendChild(t),this.#t=t}popSubElem(){this.#t=this.#t.parentElement}add(t){return this.#e.push(t),this.addElem(t.domElement),t}remove(t){return this.removeElem(t.domElement),n(this.#e,t),t}pushSubView(t){this.pushSubElem(t.domElement)}popSubView(){this.popSubElem()}setOptions(t){for(const e of this.#e)e.setOptions(t)}updateDisplayIfNeeded(t,e){for(const n of this.#e)n.updateDisplayIfNeeded(t,e);return this}$(t){return this.domElement.querySelector(t)}}class m extends p{#n;#i;#o;constructor(t){super(e("div",{className:"muigui-controller"})),this.#n=[],this.#i=[],t&&this.domElement.classList.add(t)}get parent(){return this.#o}setParent(t){this.#o=t,this.enable(!this.disabled())}show(t=!0){return this.domElement.classList.toggle("muigui-hide",!t),this.domElement.classList.toggle("muigui-show",t),this}hide(){return this.show(!1)}disabled(){return!!this.domElement.closest(".muigui-disabled")}enable(t=!0){return this.domElement.classList.toggle("muigui-disabled",!t),["input","button","select","textarea"].forEach((t=>{this.domElement.querySelectorAll(t).forEach((t=>{const e=!!t.closest(".muigui-disabled");t.disabled=e}))})),this}disable(t=!0){return this.enable(!t)}onChange(t){return this.removeChange(t),this.#n.push(t),this}removeChange(t){return n(this.#n,t),this}onFinishChange(t){return this.removeFinishChange(t),this.#i.push(t),this}removeFinishChange(t){return n(this.#i,t),this}#s(t,e){for(const n of t)n.call(this,e)}emitChange(t,e,n){this.#s(this.#n,t),this.#o&&(void 0===e?this.#o.emitChange(t):this.#o.emitChange({object:e,property:n,value:t,controller:this}))}emitFinalChange(t,e,n){this.#s(this.#i,t),this.#o&&(void 0===e?this.#o.emitChange(t):this.#o.emitFinalChange({object:e,property:n,value:t,controller:this}))}getColors(){const t=t=>t.replace(/-([a-z])/g,((t,e)=>e.toUpperCase())),n=e("div");this.domElement.appendChild(n);const i=Object.fromEntries(["color","bg-color","value-color","value-bg-color","hover-bg-color","menu-bg-color","menu-sep-color","disabled-color"].map((e=>{n.style.color=`var(--${e})`;const i=getComputedStyle(n);return[t(e),i.color]})));return n.remove(),i}}class g extends m{#r;#a;#l;#u={name:""};constructor(t,n,i={}){super("muigui-button",""),this.#r=t,this.#a=n,this.#l=this.addElem(e("button",{type:"button",onClick:()=>{this.#r[this.#a](this)}})),this.setOptions({name:n,...i})}setOptions(t){a(this.#u,t);const{name:e}=this.#u;this.#l.textContent=e}}function f(t,e){if(t.length!==e.length)return!1;for(let n=0;n{t.setValue(i.checked)},onChange:()=>{t.setFinalValue(i.checked)}});super(e("label",{},[i]))}updateDisplay(t){this.domElement.checked=t}}const x=[],w=new Set;let y,k;function E(){y=void 0,k=!0;for(const t of x)w.has(t)||t();k=!1,w.size&&(k?$():(w.forEach((t=>{n(x,t)})),w.clear())),$()}function $(){!y&&x.length&&(y=requestAnimationFrame(E))}let C=0;function V(){return"muigui-"+ ++C}class M extends p{constructor(t=""){super(e("div",{className:"muigui-value"})),t&&this.domElement.classList.add(t)}}class S extends m{#b;#v;constructor(t="",n=""){super("muigui-label-controller"),this.#b=V(),this.#v=e("label",{for:this.#b}),this.domElement.appendChild(this.#v),this.pushSubView(new M(t)),this.name(n)}get id(){return this.#b}name(t){return this.#v.title===this.#v.textContent&&(this.#v.title=t),this.#v.textContent=t,this}tooltip(t){this.#v.title=t}}class I extends S{#r;#a;#x;#w;#e;#y;constructor(t,e,n=""){super(n,e),this.#r=t,this.#a=e,this.#x=this.getValue(),this.#w=!1,this.#e=[]}get initialValue(){return this.#x}get object(){return this.#r}get property(){return this.#a}add(t){return this.#e.push(t),super.add(t),this.updateDisplay(),t}#k(t,e){let n=!1;if("object"==typeof t){const e=this.#r[this.#a];if(Array.isArray(t)||o(t))for(let i=0;i=0&&x.splice(e,1)}(this.#y)),this}}class D extends I{constructor(t,e){super(t,e,"muigui-checkbox");const n=this.id;this.add(new v(this,n)),this.updateDisplay()}}const F={to:t=>t,from:t=>[!0,t]},L={to:t=>t.toString(),from:t=>{const e=parseFloat(t);return[!Number.isNaN(e),e]}},N={radToDeg:u({to:[0,180],from:[0,Math.PI]})};function A(){let t=0;return function(e,n,i=5){t-=e.deltaY*n/i;const o=Math.floor(Math.abs(t)/n)*Math.sign(t)*n;return t-=o,o}}class U extends b{#E;#$;#C;#V;#u={step:.01,converters:L,min:Number.NEGATIVE_INFINITY,max:Number.POSITIVE_INFINITY};constructor(t,n){const o=t.setValue.bind(t),r=t.setFinalValue.bind(t),a=A();super(e("input",{type:"number",onInput:()=>this.#M(o,!0),onChange:()=>this.#M(r,!1),onWheel:e=>{e.preventDefault();const{min:n,max:o,step:r}=this.#u,l=a(e,r),u=parseFloat(this.domElement.value),c=i(s(u+l,(t=>t),r),n,o);t.setValue(c)}})),this.setOptions(n)}#M(t,e){const n=parseFloat(this.domElement.value),[o,s]=this.#$(n);let r;if(o&&!Number.isNaN(n)){const{min:n,max:o}=this.#u;r=s>=n&&s<=o,this.#V=e,t(i(s,n,o))}this.domElement.classList.toggle("muigui-invalid-value",!o||!r)}updateDisplay(t){this.#V||(this.domElement.value=s(t,this.#E,this.#C)),this.#V=!1}setOptions(t){a(this.#u,t);const{step:e,converters:{to:n,from:i}}=this.#u;return this.#E=n,this.#$=i,this.#C=e,this}}class O extends I{#S;#C;constructor(t,e,n={}){super(t,e,"muigui-checkbox"),this.#S=this.add(new U(this,n)),this.updateDisplay()}}class j extends b{#I;constructor(t,n){const i=[];super(e("select",{onChange:()=>{t.setFinalValue(this.#I[this.domElement.selectedIndex])}},n.map((([t,n])=>(i.push(n),e("option",{textContent:t})))))),this.#I=i}updateDisplay(t){const e=this.#I.indexOf(t);this.domElement.selectedIndex=e}}function T(t,e){return Array.isArray(t)?Array.isArray(t[0])?t:e?t.map(((t,e)=>[t,e])):t.map((t=>[t,t])):[...Object.entries(t)]}class P extends I{constructor(t,e,n){super(t,e,"muigui-select");const i="number"==typeof this.getValue(),{keyValues:o}=n,s=T(o,i);this.add(new j(this,s)),this.updateDisplay()}}class z extends b{#E;#$;#C;#V;#u={step:.01,min:0,max:1,converters:F};constructor(t,n){const o=A();super(e("input",{type:"range",onInput:()=>{this.#V=!0;const{min:e,max:n,step:o}=this.#u,r=parseFloat(this.domElement.value),a=i(s(r,(t=>t),o),e,n),[l,u]=this.#$(a);l&&t.setValue(u)},onChange:()=>{this.#V=!0;const{min:e,max:n,step:o}=this.#u,r=parseFloat(this.domElement.value),a=i(s(r,(t=>t),o),e,n),[l,u]=this.#$(a);l&&t.setFinalValue(u)},onWheel:e=>{e.preventDefault();const[n,r]=this.#$(parseFloat(this.domElement.value));if(!n)return;const{min:a,max:l,step:u}=this.#u,c=o(e,u),h=i(s(r+c,(t=>t),u),a,l);t.setValue(h)}})),this.setOptions(n)}updateDisplay(t){this.#V||(this.domElement.value=s(t,this.#E,this.#C)),this.#V=!1}setOptions(t){a(this.#u,t);const{step:e,min:n,max:i,converters:{to:o,from:s}}=this.#u;return this.#E=o,this.#$=s,this.#C=e,this.domElement.step=e,this.domElement.min=n,this.domElement.max=i,this}}class B extends I{constructor(t,e,n){super(t,e,"muigui-range"),this.add(new z(this,n)),this.add(new U(this,n))}}class G extends b{#E;#$;#V;#u={converters:F};constructor(t,n){const i=t.setValue.bind(t),o=t.setFinalValue.bind(t);super(e("input",{type:"text",onInput:()=>this.#M(i,!0),onChange:()=>this.#M(o,!1)})),this.setOptions(n)}#M(t,e){const[n,i]=this.#$(this.domElement.value);n&&(this.#V=e,t(i)),this.domElement.style.color=n?"":"var(--invalid-color)"}updateDisplay(t){this.#V||(this.domElement.value=this.#E(t),this.domElement.style.color=""),this.#V=!1}setOptions(t){a(this.#u,t);const{converters:{to:e,from:n}}=this.#u;return this.#E=e,this.#$=n,this}}class H extends I{constructor(t,e){super(t,e,"muigui-checkbox"),this.add(new G(this)),this.updateDisplay()}}class R extends p{constructor(t,n){super(e(t,{className:n}))}}class Y extends S{#D;constructor(){super("muigui-canvas"),this.#D=this.add(new R("canvas","muigui-canvas")).domElement}get canvas(){return this.#D}}const W=(t,e,n)=>Math.max(e,Math.min(n,t)),q=t=>+t.toFixed(3),_=t=>parseInt(t.substring(1,3),16)<<16|parseInt(t.substring(3,5),16)<<8|parseInt(t.substring(5,7),16),J=t=>[parseInt(t.substring(1,3),16),parseInt(t.substring(3,5),16),parseInt(t.substring(5,7),16)],K=t=>`#${Array.from(t).map((t=>t.toString(16).padStart(2,"0"))).join("")}`,X=t=>J(t).map((t=>q(t/255))),Z=t=>K(Array.from(t).map((t=>Math.round(W(255*t,0,255))))),Q=t=>({r:parseInt(t.substring(1,3),16)/255,g:parseInt(t.substring(3,5),16)/255,b:parseInt(t.substring(5,7),16)/255}),tt=t=>W(Math.round(255*t),0,255).toString(16).padStart(2,"0"),et=t=>`rgb(${J(t).join(", ")})`,nt=/^\s*rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/,it=t=>{const e=rt(J(t)).map((t=>(t=>+t.toFixed(0))(t)));return`hsl(${e[0]}, ${e[1]}%, ${e[2]}%)`},ot=/^\s*hsl\(\s*(\d+)(?:deg|)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)\s*$/,st=(t,e)=>(t%e+e)%e;const rt=t=>{const[e,n,i]=function([t,e,n]){const i=Math.max(t,e,n),o=Math.min(t,e,n),s=.5*(o+i),r=i-o;let a=0,l=0;if(0!==r)switch(l=0===s||1===s?0:(i-s)/Math.min(s,1-s),i){case t:a=(e-n)/r+(et/255)));return[360*e,100*n,100*i]};function at([t,e,n]){return e=W(e,0,1),n=W(n,0,1),[t,t+2/3,t+1/3].map((t=>{return i=1,o=W(Math.abs(6*(t=>t>=0?t%1:1-t%1)(t)-3)-1,0,1),(i+(o-i)*e)*n;var i,o}))}const lt=t=>Math.round(1e3*t)/1e3;function ut([t,e,n]){const i=n>e?[n,e,-1,2/3]:[e,n,0,-1/3],o=i[0]>t?[i[0],i[1],i[3],t]:[t,i[1],i[2],i[0]],s=o[0]-Math.min(o[3],o[1]);return[Math.abs(o[2]+(o[3]-o[1])/(6*s+Number.EPSILON)),s/(o[0]+Number.EPSILON),o[0]].map(lt)}window.hsv01ToRGBFloat=at,window.rgbFloatToHSV01=ut;const ct=[{re:/^#(?:[0-9a-f]){6}$/i,format:"hex6"},{re:/^(?:[0-9a-f]){6}$/i,format:"hex6-no-hash"},{re:/^#(?:[0-9a-f]){3}$/i,format:"hex3"},{re:/^(?:[0-9a-f]){3}$/i,format:"hex3-no-hash"},{re:nt,format:"css-rgb"},{re:ot,format:"css-hsl"}];function ht(t){switch(typeof t){case"number":return"uint32-rgb";case"string":{const e=function(t){for(const e of ct)if(e.re.test(t))return e}(t.trim());if(e)return e.format;break}case"object":if(t instanceof Uint8Array||t instanceof Uint8ClampedArray){if(3===t.length)return"uint8-rgb"}else if(t instanceof Float32Array){if(3===t.length)return"float-rgb"}else if(Array.isArray(t)){if(3===t.length)return"float-rgb"}else if("r"in t&&"g"in t&&"b"in t)return"object-rgb"}throw new Error(`unknown color format: ${t}`)}function dt(t){return t.trim(t)}function pt(t){return t[1]===t[2]&&t[3]===t[4]&&t[5]===t[6]?`#${t[1]}${t[3]}${t[5]}`:t}const mt=/^(#|)([0-9a-f]{3})$/i;function gt(t){const e=mt.exec(t);if(e){const[,,t]=e;return"#"+`${(n=t)[0]}${n[0]}${n[1]}${n[1]}${n[2]}${n[2]}`}var n;return t}function ft(t){return pt(dt(t))}const bt=t=>{const e=nt.exec(t);if(!e)return[!1];const n=[e[1],e[2],e[3]].map((t=>parseInt(t)));return[!n.find((t=>t>255)),`rgb(${n.join(", ")})`]},vt=t=>{const e=ot.exec(t);if(!e)return[!1];const n=[e[1],e[2],e[3]].map((t=>parseFloat(t)));return[!n.find((t=>Number.isNaN(t))),`hsl(${n[0]}, ${n[1]}%, ${n[2]}%)`]},xt=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*$/,wt=/^\s*(?:0x){0,1}([0-9a-z]{1,6})\s*$/i,yt=/^\s*#[a-f0-9]{6}\s*$|^\s*#[a-f0-9]{3}\s*$/i,kt=/^\s*[a-f0-9]{6}\s*$/i,Et={hex6:{color:{from:t=>[!0,t],to:dt},text:{from:t=>[yt.test(t),t.trim()],to:t=>t}},hex3:{color:{from:t=>[!0,ft(t)],to:gt},text:{from:t=>[yt.test(t),pt(t.trim())],to:t=>t}},"hex6-no-hash":{color:{from:t=>[!0,t.substring(1)],to:t=>`#${dt(t)}`},text:{from:t=>[kt.test(t),t.trim()],to:t=>t}},"hex3-no-hash":{color:{from:t=>[!0,ft(t).substring(1)],to:gt},text:{from:t=>[kt.test(t),pt(t.trim())],to:t=>t}},"uint32-rgb":{color:{from:t=>[!0,_(t)],to:t=>`#${Math.round(t).toString(16).padStart(6,"0")}`},text:{from:t=>(t=>{const e=wt.exec(t);return e?[!0,parseInt(e[1],16)]:[!1]})(t),to:t=>`0x${t.toString(16).padStart(6,"0")}`}},"uint8-rgb":{color:{from:t=>[!0,J(t)],to:K},text:{from:t=>{const e=xt.exec(t);if(!e)return[!1];const n=[e[1],e[2],e[3]].map((t=>parseInt(t)));return[!n.find((t=>t>255)),n]},to:t=>t.join(", ")}},"float-rgb":{color:{from:t=>[!0,X(t)],to:Z},text:{from:t=>{const e=t.split(",").map((t=>t.trim())),n=e.map((t=>parseFloat(t)));if(3!==n.length)return[!1];const i=e.findIndex((t=>isNaN(t)));return[i<0,n.map((t=>q(t)))]},to:t=>Array.from(t).map((t=>q(t))).join(", ")}},"object-rgb":{color:{from:t=>[!0,Q(t)],to:t=>`#${tt(t.r)}${tt(t.g)}${tt(t.b)}`},text:{from:t=>{try{const e=t.replace(/([a-z])/g,'"$1"'),n=JSON.parse(e);if(Number.isNaN(n.r)||Number.isNaN(n.g)||Number.isNaN(n.b))throw new Error("not {r, g, b}");return[!0,n]}catch(t){return[!1]}},to:t=>`{r:${q(t.r)}, g:${q(t.g)}, b:${q(t.b)}}`}},"css-rgb":{color:{from:t=>[!0,et(t)],to:t=>{const e=nt.exec(t);return K([e[1],e[2],e[3]].map((t=>parseInt(t))))}},text:{from:bt,to:t=>bt(t)[1]}},"css-hsl":{color:{from:t=>[!0,it(t)],to:t=>{const e=ot.exec(t),n=function([t,e,n]){t=st(t,360),e=W(e/100,0,1),n=W(n/100,0,1);const i=e*Math.min(n,1-n);function o(e){const o=(e+t/30)%12;return n-i*Math.max(-1,Math.min(o-3,9-o,1))}return[o(0),o(8),o(4)].map((t=>Math.round(255*t)))}([e[1],e[2],e[3]].map((t=>parseFloat(t))));return K(n)}},text:{from:vt,to:t=>vt(t)[1]}}};class $t extends b{#E;#$;#F;#V;#u={converters:F};constructor(t,n){const i=e("input",{type:"color",onInput:()=>{const[e,n]=this.#$(i.value);e&&(this.#V=!0,t.setValue(n))},onChange:()=>{const[e,n]=this.#$(i.value);e&&(this.#V=!0,t.setFinalValue(n))}});super(e("div",{},[i])),this.setOptions(n),this.#F=i}updateDisplay(t){this.#V||(this.#F.value=this.#E(t)),this.#V=!1}setOptions(t){a(this.#u,t);const{converters:{to:e,from:n}}=this.#u;return this.#E=e,this.#$=n,this}}class Ct extends I{#L;#S;constructor(t,e,n={}){super(t,e,"muigui-color");const i=n.format||ht(this.getValue()),{color:o,text:s}=Et[i];this.#L=this.add(new $t(this,{converters:o})),this.#S=this.add(new G(this,{converters:s})),this.updateDisplay()}setOptions(t){const{format:e}=t;if(e){const{color:t,text:n}=Et[e];this.#L.setOptions({converters:t}),this.#S.setOptions({converters:n})}return super.setOptions(t),this}}class Vt extends m{constructor(){super("muigui-divider")}}class Mt extends m{#N;#A;constructor(t){super(t),this.#N=[],this.#A=this}get children(){return this.#N}get controllers(){return this.#N.filter((t=>!(t instanceof Mt)))}get folders(){return this.#N.filter((t=>t instanceof Mt))}reset(t=!0){for(const e of this.#N)e instanceof Mt&&!t||e.reset(t);return this}remove(t){const e=this.#N.indexOf(t);if(e>=0){const t=this.#N.splice(e,1)[0];t.domElement.remove(),t.setParent(null)}return this}_addControllerImpl(t){return this.domElement.appendChild(t.domElement),this.#N.push(t),t.setParent(this),t}addController(t){return this.#A._addControllerImpl(t)}pushContainer(t){return this.addController(t),this.#A=t,t}popContainer(){return this.#A=this.#A.parent,this}}class St extends Mt{#U;constructor(t="Controls",n="muigui-menu"){super(n),this.#U=e("label"),this.addElem(e("button",{type:"button",onClick:()=>this.toggleOpen()},[this.#U])),this.pushContainer(new Mt),this.name(t),this.open()}open(t=!0){return this.domElement.classList.toggle("muigui-closed",!t),this.domElement.classList.toggle("muigui-open",t),this}close(){return this.open(!1)}name(t){return this.#U.textContent=t,this}title(t){return this.name(t)}toggleOpen(){return this.open(!this.domElement.classList.contains("muigui-open")),this}}class It extends m{constructor(t){super("muigui-label"),this.text(t)}text(t){return this.domElement.textContent=t,this}}class Dt extends St{add(t,e,...n){const i=t instanceof m?t:function(t,e,...n){const[i]=n;if(Array.isArray(i))return new P(t,e,{keyValues:i});const o=typeof t[e];switch(o){case"number":if("number"==typeof n[0]&&"number"==typeof n[1]){const i=n[0],o=n[1],s=n[2];return new B(t,e,{min:i,max:o,...s&&{step:s}})}return 0===n.length?new O(t,e,...n):new B(t,e,...n);case"boolean":return new D(t,e,...n);case"function":return new g(t,e,...n);case"string":return new H(t,e,...n);case"undefined":throw new Error(`no property named ${e}`);default:throw new Error(`unhandled type ${o} for property ${e}`)}}(t,e,...n);return this.addController(i)}addCanvas(t){return this.addController(new Y(t))}addColor(t,e,...n){return this.addController(new Ct(t,e,...n))}addDivider(){return this.addController(new Vt)}addFolder(t){return this.addController(new Dt(t))}addLabel(t){return this.addController(new It(t))}}class Ft extends HTMLElement{constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}}customElements.define("muigui-element",Ft);const Lt=new CSSStyleSheet;Lt.replaceSync(t.default);const Nt=new CSSStyleSheet;function At(t){let e,n;function i(){if(e&&!n){const o=e;e=void 0,n=t.replace(o).then((()=>{console.log(o),n=void 0,i()}))}}return function(t){e=t,i()}}const Ut=At(Lt),Ot=At(Nt);class jt extends Dt{static converters=N;static mapRange=l;static makeRangeConverters=u;static makeRangeOptions=c;static makeMinMaxPair=d;#O=new CSSStyleSheet;constructor(t={}){super("Controls","muigui-root"),t instanceof HTMLElement&&(t={parent:t});const{autoPlace:n=!0,width:i,title:o="Controls"}=t;let{parent:s}=t;if(i&&(this.domElement.style.width=/^\d+$/.test(i)?`${i}px`:i),void 0===s&&n&&(s=document.body,this.domElement.classList.add("muigui-auto-place")),s){const t=e("muigui-element");t.shadowRoot.adoptedStyleSheets=[Lt,Nt,this.#O],t.shadow.appendChild(this.domElement),s.appendChild(t)}o&&this.title(o),this.domElement.classList.add("muigui","muigui-colors")}setStyle(t){this.#O.replace(t)}static setBaseStyles(t){Ut(t)}static getBaseStyleSheet(){return Lt}static setUserStyles(t){Ot(t)}static getUserStyleSheet(){return Nt}static setTheme(e){jt.setBaseStyles(`${t.default}\n${t.themes[e]||""}`)}}function Tt(){}function Pt(t,e,n){const i=t.getBoundingClientRect(),o=e.clientX-i.left,s=e.clientY-i.top,r=o/i.width,a=s/i.height,l=o-(n=n||[o,s])[0],u=s-n[1];return{x:o,y:s,nx:r,ny:a,dx:l,dy:u,ndx:l/i.width,ndy:u/i.width}}function zt(t,{onDown:e=Tt,onMove:n=Tt,onUp:i=Tt}){let o;const s=function(e){const i={type:"move",...Pt(t,e,o)};n(i)},r=function(e){t.releasePointerCapture(e.pointerId),t.removeEventListener("pointermove",s),t.removeEventListener("pointerup",r),document.body.style.backgroundColor="",i("up")},a=function(n){t.addEventListener("pointermove",s),t.addEventListener("pointerup",r),t.setPointerCapture(n.pointerId);const i=Pt(t,n);o=[i.x,i.y],e({type:"down",...i})};return t.addEventListener("pointerdown",a),function(){t.removeEventListener("pointerdown",a)}}class Bt extends b{#j;#T;#P;#z;#B;#G;#H;#R;constructor(t){super(e("div",{innerHTML:'\n\n\n \n \n \n \n \n \n \n \n\n \n \n \n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n\n',className:"muigui-no-scroll"})),this.#j=this.domElement.children[0],this.#T=this.domElement.children[1],this.#P=this.$(".muigui-color-chooser-circle"),this.#z=this.$("#muigui-color-chooser-hue"),this.#B=this.$(".muigui-color-chooser-cursor");const n=e=>{const n=i(e.nx,0,1),o=i(e.ny,0,1);this.#G[1]=n,this.#G[2]=1-o,this.#H=!0,t.setValue(Z(at(this.#G)))},o=e=>{const n=i(e.nx,0,1);this.#G[0]=n,this.#R=!0,t.setValue(Z(at(this.#G)))};zt(this.#j,{onDown:n,onMove:n}),zt(this.#T,{onDown:o,onMove:o})}updateDisplay(t){this.#G||(this.#G=ut(X(t)));{const[e,n,i]=ut(X(t));this.#H||(this.#G[0]=n>.001&&i>.001?e:this.#G[0]),this.#R||(this.#G[1]=n,this.#G[2]=i)}{const[t,e,n]=this.#G;this.#H||(this.#B.setAttribute("transform",`translate(${64*t}, 0)`),this.#z.children[0].setAttribute("stop-color",`hsl(${360*t}, 0%, 100%)`),this.#z.children[1].setAttribute("stop-color",`hsl(${360*t}, 100%, 50%)`)),this.#R||(this.#P.setAttribute("cx",""+64*e),this.#P.setAttribute("cy",""+48*(1-n)))}this.#H=!1,this.#R=!1}}class Gt extends I{#Y;#W;#q;#u={open:!1};constructor(t,n,i={}){super(t,n,"muigui-pop-down-controller"),this.#Y=this.add(new R("div","muigui-pop-down-top"));const o=this.#Y.addElem(e("input",{type:"checkbox",onChange:()=>{this.#u.open=o.checked}}));this.#W=this.#Y.add(new R("div","muigui-pop-down-values")),this.#q=this.add(new R("div","muigui-pop-down-bottom")),this.setOptions(i)}updateDisplay(){super.updateDisplay();const{open:t}=this.#u;this.domElement.children[1].classList.toggle("muigui-open",t),this.domElement.children[1].classList.toggle("muigui-closed",!t)}setOptions(t){a(this.#u,t),super.setOptions(t),this.updateDisplay()}addTop(t){return this.#W.add(t)}addBottom(t){return this.#q.add(t)}}class Ht extends Gt{constructor(t,e){super(t,e,"muigui-color-chooser"),this.addTop(new G(this)),this.addBottom(new Bt(this)),this.updateDisplay()}}function Rt(){}const Yt={ArrowLeft:[-1,0],ArrowRight:[1,0],ArrowUp:[0,-1],ArrowDown:[0,1]};function Wt(t,{onDown:e=Rt,onUp:n=Rt}){const i=function(t){const i=t.shiftKey?10:1,[o,s]=(Yt[t.key]||[0,0]).map((t=>t*i));("keydown"===t.type?e:n)({type:t.type.substring(3),dx:o,dy:s,event:t})};return t.addEventListener("keydown",i),t.addEventListener("keyup",i),function(){t.removeEventListener("keydown",i),t.removeEventListener("keyup",i)}}function qt(t,e=""){if(!t)throw new Error(e)}function _t(t,e,n,i,o,s){const r=Math.abs(n)*Math.cos(s),a=Math.abs(i)*Math.sin(s);return[t+Math.cos(o)*r-Math.sin(o)*a,e+Math.sin(o)*r+Math.cos(o)*a]}function Jt(t,e,n,i,o){qt(Math.abs(i-o)<=2*Math.PI),qt(i>=-Math.PI&&i<=2*Math.PI),qt(i<=o),qt(o>=-Math.PI&&o<=4*Math.PI);const{x1:s,y1:r,x2:a,y2:l,fa:u,fs:c}=function(t,e,n,i,o,s,r){const[a,l]=_t(t,e,n,i,o,s),[u,c]=_t(t,e,n,i,o,s+r);return{x1:a,y1:l,x2:u,y2:c,fa:Math.abs(r)>Math.PI?1:0,fs:r>0?1:0}}(t,e,n,n,0,i,o-i);return Math.abs(Math.abs(i-o)-2*Math.PI)>Number.EPSILON?`M${t} ${e} L${s} ${r} A ${n} ${n} 0 ${u} ${c} ${a} ${l} L${t} ${e}`:`M${s} ${r} L${s} ${r} A ${n} ${n} 0 ${u} ${c} ${a} ${l}`}const Kt=t=>r(t+Math.PI,2*Math.PI)-Math.PI;class Xt extends b{#_;#J;#K;#X;#u={step:1,min:-180,max:180,dirMin:-Math.PI,dirMax:Math.PI,wrap:void 0,converters:F};constructor(t,n={}){const o=A();super(e("div",{className:"muigui-direction muigui-no-scroll",innerHTML:'\n\n \x3c!----\x3e\n \n \n \n \n \n \n\n',onWheel:e=>{e.preventDefault();const{min:n,max:a,step:l}=this.#u,u=o(e,l);let c=this.#K+u;this.#X&&(c=r(c-n,a-n)+n);const h=i(s(c,(t=>t),l),n,a);t.setValue(h)}}));const a=e=>{const{min:n,max:o,step:r,dirMin:a,dirMax:l}=this.#u,u=2*e.nx-1,c=2*e.ny-1,h=Math.atan2(c,u),d=(a+l)/2,p=i((Kt(h-d)-Kt(a-d))/(l-a),0,1),m=s(n+(o-n)*p,(t=>t),r);t.setValue(m)};zt(this.domElement,{onDown:a,onMove:a}),Wt(this.domElement,{onDown:e=>{const{min:n,max:o,step:r}=this.#u,a=i(s(this.#K+e.dx*r,(t=>t),r),n,o);t.setValue(a)}}),this.#_=this.$("#muigui-arrow"),this.#J=this.$("#muigui-range"),this.setOptions(n)}updateDisplay(t){this.#K=t;const{min:e,max:n}=this.#u,i=(t-e)/(n-e),o=(s=this.#u.dirMin,r=this.#u.dirMax,s+(r-s)*i);var s,r;this.#_.style.transform=`rotate(${o}rad)`}setOptions(t){a(this.#u,t);const{dirMin:e,dirMax:n,wrap:i}=this.#u;this.#X=void 0!==i?i:Math.abs(e-n)>=2*Math.PI-Number.EPSILON;const[o,s]=e(o.push(i),e("label",{},[e("input",{type:"radio",name:s,value:a,onChange:function(){this.checked&&t.setFinalValue(r.#I[this.value])}}),e("button",{type:"button",textContent:n,onClick:function(){this.previousElementSibling.click()}})]))))));const r=this;this.#I=o,this.cols(i)}updateDisplay(t){const e=this.#I.indexOf(t);for(let t=0;t{e({rect:t.getBoundingClientRect(),elem:t})})).observe(t)}function ne(t,e,n,i){ee(t,(({rect:o})=>{const{width:s,height:r}=o;t.setAttribute("viewBox",`-${s*e} -${r*n} ${s} ${r}`),i({elem:t,rect:o})}))}function ie(t,e,n,i,o,r){const a=[];tt),n)),e=Math.min(e,o);for(let i=t;i<=e;i+=n)a.push(`M${i} 0 l0 ${r}`);return a.join(" ")}class oe extends b{#Z;#Q;#tt;#et;#nt;#it;#ot;#st;#rt;#K;#at;#u={min:-100,max:100,step:1,unit:10,unitSize:10,ticksPerUnit:5,labelFn:t=>t,tickHeight:1,limits:!0,thicksColor:void 0,orientation:void 0};constructor(t,n){const o=A();let r;super(e("div",{innerHTML:'\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \x3c!----\x3e\n \x3c!----\x3e\n \n \n \n \n\n',className:"muigui-no-v-scroll",onWheel:e=>{e.preventDefault();const{min:n,max:r,step:a}=this.#u,l=o(e,a),u=i(s(this.#K+l,(t=>t),a),n,r);t.setValue(u)}})),this.#Z=this.$("svg"),this.#Q=this.$("#muigui-origin"),this.#tt=this.$("#muigui-ticks"),this.#et=this.$("#muigui-thicks"),this.#nt=this.$("#muigui-numbers"),this.#it=this.$("#muigui-left-grad"),this.#ot=this.$("#muigui-right-grad"),this.setOptions(n),zt(this.domElement,{onDown:()=>{r=this.#K},onMove:e=>{const{min:n,max:o,unitSize:a,unit:l,step:u}=this.#u,c=i(s(r-e.dx/a*l,(t=>t),u),n,o);t.setValue(c)}}),Wt(this.domElement,{onDown:e=>{const{min:n,max:o,step:r}=this.#u,a=i(s(this.#K+e.dx*r,(t=>t),r),n,o);t.setValue(a)}}),ne(this.#Z,.5,0,(({rect:{width:t}})=>{this.#it.setAttribute("x",-t/2),this.#ot.setAttribute("x",t/2-20),this.#at=function(t){const e=t.innerHTML;t.innerHTML="- ";const n=t.querySelector("text").getComputedTextLength();return t.innerHTML=e,n}(this.#nt),this.#st=t,this.#lt()}))}#lt(){if(!this.#st||void 0===this.#K)return;const{labelFn:t,limits:e,min:n,max:i,orientation:o,tickHeight:r,ticksPerUnit:a,unit:l,unitSize:u,thicksColor:c}=this.#u,h=Math.ceil(this.#st/u),d=this.#K/l,p=Math.round(d-h),m=p*u,g=(p+2*h)*u,f=e?n*u/l:m,b=e?i*u/l:g,v=""===t(1)?10:5;a>1&&this.#tt.setAttribute("d",ie(m,g,u/a,f,b,v*r)),this.#et.style.stroke=c,this.#et.setAttribute("d",ie(m,g,u,f,b,v)),this.#nt.innerHTML=function(t,e,n,i,o,r,a,l){const u=[];tt),n)),e=Math.min(e,a);const c=Math.max(0,-Math.log10(i));for(let s=t;s<=e;s+=n)u.push(`${h=s/n*i,l(h.toFixed(c))}`);var h;return u.join("\n")}(m,g,u,l,this.#at,f,b,t),this.#Q.setAttribute("transform",`translate(${-this.#K*u/l} 0)`),this.#Z.classList.toggle("muigui-slider-up","up"===o)}updateDisplay(t){this.#K=t,this.#lt()}setOptions(t){return a(this.#u,t),this}}class se extends I{constructor(t,e,n={}){super(t,e,"muigui-slider"),this.add(new oe(this,n)),this.add(new U(this,n)),this.updateDisplay()}}class re extends b{#Z;#_;#P;#K=[];constructor(t){super(e("div",{innerHTML:'\n\n \n \n \n \n \n\n',className:"muigui-no-scroll"}));const n=e=>{const{width:n,height:i}=this.#Z.getBoundingClientRect(),o=2*e.nx-1,s=2*e.ny-1;t.setValue([o*n*.5,s*i*.5])};zt(this.domElement,{onDown:n,onMove:n}),this.#Z=this.$("svg"),this.#_=this.$("#muigui-arrow"),this.#P=this.$("#muigui-circle"),ne(this.#Z,.5,.5,(()=>this.#ut))}#ut(){const[t,e]=this.#K;this.#_.setAttribute("d",`M0,0L${t},${e}`),this.#P.setAttribute("transform",`translate(${t}, ${e})`)}updateDisplay(t){this.#K[0]=t[0],this.#K[1]=t[1],this.#ut()}}class ae extends Gt{constructor(t,e){super(t,e,"muigui-vec2");const n=t=>({setValue:e=>{const n=this.getValue();n[t]=e,this.setValue(n)},setFinalValue:e=>{const n=this.getValue();n[t]=e,this.setFinalValue(n)}});this.addTop(new U(n(0),{converters:{to:t=>t[0],from:L.from}})),this.addTop(new U(n(1),{converters:{to:t=>t[1],from:L.from}})),this.addBottom(new re(this)),this.updateDisplay()}}export{Ht as ColorChooser,Zt as Direction,te as RadioGrid,B as Range,P as Select,se as Slider,O as TextNumber,ae as Vec2,jt as default}; diff --git a/src/controllers/ValueController.js b/src/controllers/ValueController.js index 3d9667c..aada302 100644 --- a/src/controllers/ValueController.js +++ b/src/controllers/ValueController.js @@ -34,31 +34,39 @@ export default class ValueController extends LabelController { return view; } #setValueImpl(v, ignoreCache) { + let isDifferent = false; if (typeof v === 'object') { const dst = this.#object[this.#property]; // don't replace objects, just their values. - if (Array.isArray(v)) { + if (Array.isArray(v) || isTypedArray(v)) { for (let i = 0; i < v.length; ++i) { + isDifferent ||= dst[i] !== v[i]; dst[i] = v[i]; } - } else if (isTypedArray(v)) { - dst.set(v); } else { + for (const key of Object.keys(v)) { + isDifferent ||= dst[key] !== v[key]; + } Object.assign(dst, v); } } else { + isDifferent = this.#object[this.#property] !== v; this.#object[this.#property] = v; } this.updateDisplay(ignoreCache); - this.emitChange(this.getValue(), this.#object, this.#property); - return this; + if (isDifferent) { + this.emitChange(this.getValue(), this.#object, this.#property); + } + return isDifferent; } setValue(v) { this.#setValueImpl(v); } setFinalValue(v) { - this.#setValueImpl(v, true); - this.emitFinalChange(this.getValue(), this.#object, this.#property); + const isDifferent = this.#setValueImpl(v, true); + if (isDifferent) { + this.emitFinalChange(this.getValue(), this.#object, this.#property); + } return this; } updateDisplay(ignoreCache) { diff --git a/src/libs/utils.js b/src/libs/utils.js index c85777a..3f6673c 100644 --- a/src/libs/utils.js +++ b/src/libs/utils.js @@ -82,29 +82,24 @@ export function makeMinMaxPair(gui, properties, minPropName, maxPropName, option const { min, max } = options; const guiMinRange = options.minRange || 0; const valueMinRange = from(guiMinRange)[1]; - console.log('guiMinRange', guiMinRange); - console.log('valueMinRange', valueMinRange); - return [ - gui - .add(properties, minPropName, { - ...options, - min, - max: max - guiMinRange, - }) - .listen() - .onChange(v => { - properties[maxPropName] = Math.min(max, Math.max(v + valueMinRange, properties[maxPropName])); - }), - gui - .add(properties, maxPropName, { - ...options, - min: min + guiMinRange, - max, - }) - .listen() - .onChange(v => { - properties[minPropName] = Math.max(min, Math.min(v - valueMinRange, properties[minPropName])); - }), - ]; + const minGui = gui + .add(properties, minPropName, { + ...options, + min, + max: max - guiMinRange, + }) + .onChange(v => { + maxGui.setValue(Math.min(max, Math.max(v + valueMinRange, properties[maxPropName]))); + }); + const maxGui = gui + .add(properties, maxPropName, { + ...options, + min: min + guiMinRange, + max, + }) + .onChange(v => { + minGui.setValue(Math.max(min, Math.min(v - valueMinRange, properties[minPropName]))); + }); + return [ minGui, maxGui ]; }