diff --git a/dist/0.x/muigui.js b/dist/0.x/muigui.js index 7616b09..3db4800 100644 --- a/dist/0.x/muigui.js +++ b/dist/0.x/muigui.js @@ -1,4 +1,4 @@ -/* muigui@0.0.7, license MIT */ +/* muigui@0.0.10, license MIT */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : @@ -700,6 +700,7 @@ --width: 400px; --bg-color: initial; --label-width: 25%; + --number-width: 20%; } input, @@ -873,7 +874,6 @@ min, max: max - guiMinRange, }) - // .listen() .onChange(v => { maxGui.setValue(Math.min(max, Math.max(v + valueMinRange, properties[maxPropName]))); }); @@ -883,7 +883,6 @@ min: min + guiMinRange, max, }) - // .listen() .onChange(v => { minGui.setValue(Math.max(min, Math.min(v - valueMinRange, properties[minPropName]))); }); @@ -1056,6 +1055,9 @@ } } } + updateDisplay() { + // placeholder. override + } getColors() { const toCamelCase = s => s.replace(/-([a-z])/g, (m, m1) => m1.toUpperCase()); const keys = [ @@ -1208,6 +1210,7 @@ } class CheckboxView extends EditView { + #checkboxElem; constructor(setter, id) { const checkboxElem = createElem('input', { type: 'checkbox', @@ -1220,9 +1223,10 @@ }, }); super(createElem('label', {}, [checkboxElem])); + this.#checkboxElem = checkboxElem; } updateDisplay(v) { - this.domElement.checked = v; + this.#checkboxElem.checked = v; } } @@ -1787,27 +1791,6 @@ } } - class ElementView extends View { - constructor(tag, className) { - super(createElem(tag, {className})); - } - } - - // TODO: remove this? Should just be user side - class Canvas extends LabelController { - #canvasElem; - - constructor() { - super('muigui-canvas'); - this.#canvasElem = this.add( - new ElementView('canvas', 'muigui-canvas'), - ).domElement; - } - get canvas() { - return this.#canvasElem; - } - } - const clamp = (v, min, max) => Math.max(min, Math.min(max, v)); const lerp = (a, b, t) => a + (b - a) * t; const fract = v => v >= 0 ? v % 1 : 1 - (v % 1); @@ -1844,12 +1827,14 @@ const m = cssRGBRegex.exec(v); return uint8RGBToHex([m[1], m[2], m[3]].map(v => parseInt(v))); }; + const cssRGBARegex = /^\s*rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/; const hexToCssHSL = v => { const hsl = rgbUint8ToHsl(hexToUint8RGB(v)).map(v => f0(v)); return `hsl(${hsl[0]}, ${hsl[1]}%, ${hsl[2]}%)`; }; const cssHSLRegex = /^\s*hsl\(\s*(\d+)(?:deg|)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)\s*$/; + const cssHSLARegex = /^\s*hsl\(\s*(\d+)(?:deg|)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)\s*$/; const hex3DigitTo6Digit = v => `${v[0]}${v[0]}${v[1]}${v[1]}${v[2]}${v[2]}`; const cssHSLToHex = v => { @@ -1931,13 +1916,20 @@ window.hsv01ToRGBFloat = hsv01ToRGBFloat; window.rgbFloatToHSV01 = rgbFloatToHSV01; + // Yea, meh! + const hasAlpha = format => format.endsWith('a') || format.startsWith('hex8'); + const cssStringFormats = [ { re: /^#(?:[0-9a-f]){6}$/i, format: 'hex6' }, { re: /^(?:[0-9a-f]){6}$/i, format: 'hex6-no-hash' }, + { re: /^#(?:[0-9a-f]){8}$/i, format: 'hex8' }, + { re: /^(?:[0-9a-f]){8}$/i, format: 'hex8-no-hash' }, { re: /^#(?:[0-9a-f]){3}$/i, format: 'hex3' }, { re: /^(?:[0-9a-f]){3}$/i, format: 'hex3-no-hash' }, { re: cssRGBRegex, format: 'css-rgb' }, { re: cssHSLRegex, format: 'css-hsl' }, + { re: cssRGBARegex, format: 'css-rgba' }, + { re: cssHSLARegex, format: 'css-hsla' }, ]; function guessStringColorFormat(v) { @@ -1952,7 +1944,8 @@ function guessFormat(v) { switch (typeof v) { case 'number': - return 'uint32-rgb'; + console.warn('can not reliably guess format based on a number. You should pass in a format like {format: "uint32-rgb"} or {format: "uint32-rgb"}'); + return v <= 0xFFFFFF ? 'uint32-rgb' : 'uint32-rgba'; case 'string': { const formatInfo = guessStringColorFormat(v.trim()); if (formatInfo) { @@ -1964,18 +1957,28 @@ if (v instanceof Uint8Array || v instanceof Uint8ClampedArray) { if (v.length === 3) { return 'uint8-rgb'; + } else if (v.length === 4) { + return 'uint8-rgba'; } } else if (v instanceof Float32Array) { if (v.length === 3) { return 'float-rgb'; + } else if (v.length === 4) { + return 'float-rgba'; } } else if (Array.isArray(v)) { if (v.length === 3) { return 'float-rgb'; + } else if (v.length === 4) { + return 'float-rgba'; } } else { if ('r' in v && 'g' in v && 'b' in v) { - return 'object-rgb'; + if ('a' in v) { + return 'object-rgba'; + } else { + return 'object-rgb'; + } } } } @@ -2215,6 +2218,27 @@ }, }; + class ElementView extends View { + constructor(tag, className) { + super(createElem(tag, {className})); + } + } + + // TODO: remove this? Should just be user side + class Canvas extends LabelController { + #canvasElem; + + constructor() { + super('muigui-canvas'); + this.#canvasElem = this.add( + new ElementView('canvas', 'muigui-canvas'), + ).domElement; + } + get canvas() { + return this.#canvasElem; + } + } + class ColorView extends EditView { #to; #from; @@ -2319,6 +2343,12 @@ } return this; } + updateDisplay() { + for (const controller of this.#controllers) { + controller.updateDisplay(); + } + return this; + } remove(controller) { const ndx = this.#controllers.indexOf(controller); if (ndx >= 0) { @@ -2398,201 +2428,6 @@ } } - function showCSS(ob) { - if (ob.prototype.css) { - console.log(ob.prototype.css); - showCSS(ob.prototype); - } - } - - class Layout extends View { - static css = 'bar'; - constructor(tag, className) { - super(createElem(tag, {className})); - - showCSS(this); - } - } - - /* - class ValueController ?? { - const row = this.add(new Row()); - const label = row.add(new Label()); - const div = row.add(new Div()); - const row = div.add(new Row()); - } - */ - - /* - class MyCustomThing extends ValueController { - constructor(object, property, options) { - const topRow = this.add(new Row()); - const bottomRow = this.add(new Row()); - topRow.add(new NumberView()); - topRow.add(new NumberView()); - topRow.add(new NumberView()); - topRow.add(new NumberView()); - bottomRow.add(new DirectionView()); - bottomRow.add(new DirectionView()); - bottomRow.add(new DirectionView()); - bottomRow.add(new DirectionView()); - } - } - new Grid([ - [new - ] - */ - - class Column extends Layout { - constructor() { - super('div', 'muigui-row'); - } - } - - class Frame extends Layout { - static css = 'foo'; - constructor() { - super('div', 'muigui-frame'); - } - static get foo() { - return 'boo'; - } - } - - class Grid extends Layout { - constructor() { - super('div', 'muigui-grid'); - } - } - - class Row extends Layout { - constructor() { - super('div', 'muigui-row'); - } - } - - class GUIFolder extends Folder { - add(object, property, ...args) { - const controller = object instanceof Controller - ? object - : createController(object, property, ...args); - return this.addController(controller); - } - addCanvas(name) { - return this.addController(new Canvas(name)); - } - addColor(object, property, ...args) { - return this.addController(new Color(object, property, ...args)); - } - addDivider() { - return this.addController(new Divider()); - } - addFolder(name) { - return this.addController(new GUIFolder(name)); - } - addLabel(text) { - return this.addController(new Label(text)); - } - } - - class MuiguiElement extends HTMLElement { - constructor() { - super(); - this.shadow = this.attachShadow({mode: 'open'}); - } - } - - customElements.define('muigui-element', MuiguiElement); - - const baseStyleSheet = new CSSStyleSheet(); - baseStyleSheet.replaceSync(css.default); - const userStyleSheet = new CSSStyleSheet(); - - function makeStyleSheetUpdater(styleSheet) { - let newCss; - let newCssPromise; - - function updateStyle() { - if (newCss && !newCssPromise) { - const s = newCss; - newCss = undefined; - newCssPromise = styleSheet.replace(s).then(() => { - console.log(s); - newCssPromise = undefined; - updateStyle(); - }); - } - } - - return function updateStyleSheet(css) { - newCss = css; - updateStyle(); - }; - } - - const updateBaseStyle = makeStyleSheetUpdater(baseStyleSheet); - const updateUserStyle = makeStyleSheetUpdater(userStyleSheet); - - class GUI extends GUIFolder { - static converters = converters; - static mapRange = mapRange; - static makeRangeConverters = makeRangeConverters; - static makeRangeOptions = makeRangeOptions; - static makeMinMaxPair = makeMinMaxPair; - #localStyleSheet = new CSSStyleSheet(); - - constructor(options = {}) { - super('Controls', 'muigui-root'); - if (options instanceof HTMLElement) { - options = {parent: options}; - } - const { - autoPlace = true, - width, - title = 'Controls', - } = options; - let { - parent, - } = options; - - if (width) { - this.domElement.style.width = /^\d+$/.test(width) ? `${width}px` : width; - } - if (parent === undefined && autoPlace) { - parent = document.body; - this.domElement.classList.add('muigui-auto-place'); - } - if (parent) { - const muiguiElement = createElem('muigui-element'); - muiguiElement.shadowRoot.adoptedStyleSheets = [baseStyleSheet, userStyleSheet, this.#localStyleSheet]; - muiguiElement.shadow.appendChild(this.domElement); - parent.appendChild(muiguiElement); - } - if (title) { - this.title(title); - } - this.domElement.classList.add('muigui', 'muigui-colors'); - } - setStyle(css) { - this.#localStyleSheet.replace(css); - } - static setBaseStyles(css) { - updateBaseStyle(css); - } - static getBaseStyleSheet() { - return baseStyleSheet; - } - static setUserStyles(css) { - updateUserStyle(css); - } - static getUserStyleSheet() { - return userStyleSheet; - } - static setTheme(name) { - GUI.setBaseStyles(`${css.default}\n${css.themes[name] || ''}`); - } - } - function noop$1() { } @@ -2839,6 +2674,204 @@ } } + function showCSS(ob) { + if (ob.prototype.css) { + showCSS(ob.prototype); + } + } + + class Layout extends View { + static css = 'bar'; + constructor(tag, className) { + super(createElem(tag, {className})); + + showCSS(this); + } + } + + /* + class ValueController ?? { + const row = this.add(new Row()); + const label = row.add(new Label()); + const div = row.add(new Div()); + const row = div.add(new Row()); + } + */ + + /* + class MyCustomThing extends ValueController { + constructor(object, property, options) { + const topRow = this.add(new Row()); + const bottomRow = this.add(new Row()); + topRow.add(new NumberView()); + topRow.add(new NumberView()); + topRow.add(new NumberView()); + topRow.add(new NumberView()); + bottomRow.add(new DirectionView()); + bottomRow.add(new DirectionView()); + bottomRow.add(new DirectionView()); + bottomRow.add(new DirectionView()); + } + } + new Grid([ + [new + ] + */ + + class Column extends Layout { + constructor() { + super('div', 'muigui-row'); + } + } + + class Frame extends Layout { + static css = 'foo'; + constructor() { + super('div', 'muigui-frame'); + } + static get foo() { + return 'boo'; + } + } + + class Grid extends Layout { + constructor() { + super('div', 'muigui-grid'); + } + } + + class Row extends Layout { + constructor() { + super('div', 'muigui-row'); + } + } + + class GUIFolder extends Folder { + add(object, property, ...args) { + const controller = object instanceof Controller + ? object + : createController(object, property, ...args); + return this.addController(controller); + } + addCanvas(name) { + return this.addController(new Canvas(name)); + } + addColor(object, property, options = {}) { + const value = object[property]; + if (hasAlpha(options.format || guessFormat(value))) { + return this.addController(new ColorChooser(object, property, options)); + } else { + return this.addController(new Color(object, property, options)); + } + } + addDivider() { + return this.addController(new Divider()); + } + addFolder(name) { + return this.addController(new GUIFolder(name)); + } + addLabel(text) { + return this.addController(new Label(text)); + } + } + + class MuiguiElement extends HTMLElement { + constructor() { + super(); + this.shadow = this.attachShadow({mode: 'open'}); + } + } + + customElements.define('muigui-element', MuiguiElement); + + const baseStyleSheet = new CSSStyleSheet(); + baseStyleSheet.replaceSync(css.default); + const userStyleSheet = new CSSStyleSheet(); + + function makeStyleSheetUpdater(styleSheet) { + let newCss; + let newCssPromise; + + function updateStyle() { + if (newCss && !newCssPromise) { + const s = newCss; + newCss = undefined; + newCssPromise = styleSheet.replace(s).then(() => { + newCssPromise = undefined; + updateStyle(); + }); + } + } + + return function updateStyleSheet(css) { + newCss = css; + updateStyle(); + }; + } + + const updateBaseStyle = makeStyleSheetUpdater(baseStyleSheet); + const updateUserStyle = makeStyleSheetUpdater(userStyleSheet); + + class GUI extends GUIFolder { + static converters = converters; + static mapRange = mapRange; + static makeRangeConverters = makeRangeConverters; + static makeRangeOptions = makeRangeOptions; + static makeMinMaxPair = makeMinMaxPair; + #localStyleSheet = new CSSStyleSheet(); + + constructor(options = {}) { + super('Controls', 'muigui-root'); + if (options instanceof HTMLElement) { + options = {parent: options}; + } + const { + autoPlace = true, + width, + title = 'Controls', + } = options; + let { + parent, + } = options; + + if (width) { + this.domElement.style.width = /^\d+$/.test(width) ? `${width}px` : width; + } + if (parent === undefined && autoPlace) { + parent = document.body; + this.domElement.classList.add('muigui-auto-place'); + } + if (parent) { + const muiguiElement = createElem('muigui-element'); + muiguiElement.shadowRoot.adoptedStyleSheets = [baseStyleSheet, userStyleSheet, this.#localStyleSheet]; + muiguiElement.shadow.appendChild(this.domElement); + parent.appendChild(muiguiElement); + } + if (title) { + this.title(title); + } + this.domElement.classList.add('muigui', 'muigui-colors'); + } + setStyle(css) { + this.#localStyleSheet.replace(css); + } + static setBaseStyles(css) { + updateBaseStyle(css); + } + static getBaseStyleSheet() { + return baseStyleSheet; + } + static setUserStyles(css) { + updateUserStyle(css); + } + static getUserStyleSheet() { + return userStyleSheet; + } + static setTheme(name) { + GUI.setBaseStyles(`${css.default}\n${css.themes[name] || ''}`); + } + } + function noop() { } diff --git a/dist/0.x/muigui.min.js b/dist/0.x/muigui.min.js index e2fe7b7..9bcf21e 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],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})); +!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 --number-width: 20%;\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}))}updateDisplay(){}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])),this.#b=i}updateDisplay(t){this.#b.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{#v;#x;constructor(t="",n=""){super("muigui-label-controller"),this.#v=V(),this.#x=e("label",{for:this.#v}),this.domElement.appendChild(this.#x),this.pushSubView(new M(t)),this.name(n)}get id(){return this.#v}name(t){return this.#x.title===this.#x.textContent&&(this.#x.title=t),this.#x.textContent=t,this}tooltip(t){this.#x.title=t}}class I extends S{#r;#a;#w;#y;#e;#k;constructor(t,e,n=""){super(n,e),this.#r=t,this.#a=e,this.#w=this.getValue(),this.#y=!1,this.#e=[]}get initialValue(){return this.#w}get object(){return this.#r}get property(){return this.#a}add(t){return this.#e.push(t),super.add(t),this.updateDisplay(),t}#E(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.#k)),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{#$;#C;#V;#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.#S(o,!0),onChange:()=>this.#S(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)}#S(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.#$,this.#V)),this.#M=!1}setOptions(t){a(this.#u,t);const{step:e,converters:{to:n,from:i}}=this.#u;return this.#$=n,this.#C=i,this.#V=e,this}}class O extends I{#I;#V;constructor(t,e,n={}){super(t,e,"muigui-checkbox"),this.#I=this.add(new U(this,n)),this.updateDisplay()}}class j extends b{#D;constructor(t,n){const i=[];super(e("select",{onChange:()=>{t.setFinalValue(this.#D[this.domElement.selectedIndex])}},n.map((([t,n])=>(i.push(n),e("option",{textContent:t})))))),this.#D=i}updateDisplay(t){const e=this.#D.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{#$;#C;#V;#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.#$,this.#V)),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.#$=o,this.#C=s,this.#V=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{#$;#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.#S(i,!0),onChange:()=>this.#S(o,!1)})),this.setOptions(n)}#S(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.#$(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,this.#C=n,this}}class H extends I{constructor(t,e){super(t,e,"muigui-checkbox"),this.add(new G(this)),this.updateDisplay()}}const R=(t,e,n)=>Math.max(e,Math.min(n,t)),Y=t=>+t.toFixed(3),W=t=>parseInt(t.substring(1,3),16)<<16|parseInt(t.substring(3,5),16)<<8|parseInt(t.substring(5,7),16),q=t=>[parseInt(t.substring(1,3),16),parseInt(t.substring(3,5),16),parseInt(t.substring(5,7),16)],_=t=>`#${Array.from(t).map((t=>t.toString(16).padStart(2,"0"))).join("")}`,J=t=>q(t).map((t=>Y(t/255))),K=t=>_(Array.from(t).map((t=>Math.round(R(255*t,0,255))))),X=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}),Z=t=>R(Math.round(255*t),0,255).toString(16).padStart(2,"0"),Q=t=>`rgb(${q(t).join(", ")})`,tt=/^\s*rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/,et=t=>{const e=ot(q(t)).map((t=>(t=>+t.toFixed(0))(t)));return`hsl(${e[0]}, ${e[1]}%, ${e[2]}%)`},nt=/^\s*hsl\(\s*(\d+)(?:deg|)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)\s*$/,it=(t,e)=>(t%e+e)%e;const ot=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 st([t,e,n]){return e=R(e,0,1),n=R(n,0,1),[t,t+2/3,t+1/3].map((t=>{return i=1,o=R(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 rt=t=>Math.round(1e3*t)/1e3;function at([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(rt)}window.hsv01ToRGBFloat=st,window.rgbFloatToHSV01=at;const lt=[{re:/^#(?:[0-9a-f]){6}$/i,format:"hex6"},{re:/^(?:[0-9a-f]){6}$/i,format:"hex6-no-hash"},{re:/^#(?:[0-9a-f]){8}$/i,format:"hex8"},{re:/^(?:[0-9a-f]){8}$/i,format:"hex8-no-hash"},{re:/^#(?:[0-9a-f]){3}$/i,format:"hex3"},{re:/^(?:[0-9a-f]){3}$/i,format:"hex3-no-hash"},{re:tt,format:"css-rgb"},{re:nt,format:"css-hsl"},{re:/^\s*rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/,format:"css-rgba"},{re:/^\s*hsl\(\s*(\d+)(?:deg|)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)\s*$/,format:"css-hsla"}];function ut(t){switch(typeof t){case"number":return console.warn('can not reliably guess format based on a number. You should pass in a format like {format: "uint32-rgb"} or {format: "uint32-rgb"}'),t<=16777215?"uint32-rgb":"uint32-rgba";case"string":{const e=function(t){for(const e of lt)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";if(4===t.length)return"uint8-rgba"}else if(t instanceof Float32Array){if(3===t.length)return"float-rgb";if(4===t.length)return"float-rgba"}else if(Array.isArray(t)){if(3===t.length)return"float-rgb";if(4===t.length)return"float-rgba"}else if("r"in t&&"g"in t&&"b"in t)return"a"in t?"object-rgba":"object-rgb"}throw new Error(`unknown color format: ${t}`)}function ct(t){return t.trim(t)}function ht(t){return t[1]===t[2]&&t[3]===t[4]&&t[5]===t[6]?`#${t[1]}${t[3]}${t[5]}`:t}const dt=/^(#|)([0-9a-f]{3})$/i;function pt(t){const e=dt.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 mt(t){return ht(ct(t))}const gt=t=>{const e=tt.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(", ")})`]},ft=t=>{const e=nt.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]}%)`]},bt=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*$/,vt=/^\s*(?:0x){0,1}([0-9a-z]{1,6})\s*$/i,xt=/^\s*#[a-f0-9]{6}\s*$|^\s*#[a-f0-9]{3}\s*$/i,wt=/^\s*[a-f0-9]{6}\s*$/i,yt={hex6:{color:{from:t=>[!0,t],to:ct},text:{from:t=>[xt.test(t),t.trim()],to:t=>t}},hex3:{color:{from:t=>[!0,mt(t)],to:pt},text:{from:t=>[xt.test(t),ht(t.trim())],to:t=>t}},"hex6-no-hash":{color:{from:t=>[!0,t.substring(1)],to:t=>`#${ct(t)}`},text:{from:t=>[wt.test(t),t.trim()],to:t=>t}},"hex3-no-hash":{color:{from:t=>[!0,mt(t).substring(1)],to:pt},text:{from:t=>[wt.test(t),ht(t.trim())],to:t=>t}},"uint32-rgb":{color:{from:t=>[!0,W(t)],to:t=>`#${Math.round(t).toString(16).padStart(6,"0")}`},text:{from:t=>(t=>{const e=vt.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,q(t)],to:_},text:{from:t=>{const e=bt.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,J(t)],to:K},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=>Y(t)))]},to:t=>Array.from(t).map((t=>Y(t))).join(", ")}},"object-rgb":{color:{from:t=>[!0,X(t)],to:t=>`#${Z(t.r)}${Z(t.g)}${Z(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:${Y(t.r)}, g:${Y(t.g)}, b:${Y(t.b)}}`}},"css-rgb":{color:{from:t=>[!0,Q(t)],to:t=>{const e=tt.exec(t);return _([e[1],e[2],e[3]].map((t=>parseInt(t))))}},text:{from:gt,to:t=>gt(t)[1]}},"css-hsl":{color:{from:t=>[!0,et(t)],to:t=>{const e=nt.exec(t),n=function([t,e,n]){t=it(t,360),e=R(e/100,0,1),n=R(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 _(n)}},text:{from:ft,to:t=>ft(t)[1]}}};class kt extends p{constructor(t,n){super(e(t,{className:n}))}}class Et extends S{#F;constructor(){super("muigui-canvas"),this.#F=this.add(new kt("canvas","muigui-canvas")).domElement}get canvas(){return this.#F}}class $t extends b{#$;#C;#L;#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.#L=i}updateDisplay(t){this.#M||(this.#L.value=this.#$(t)),this.#M=!1}setOptions(t){a(this.#u,t);const{converters:{to:e,from:n}}=this.#u;return this.#$=e,this.#C=n,this}}class Ct extends I{#N;#I;constructor(t,e,n={}){super(t,e,"muigui-color");const i=n.format||ut(this.getValue()),{color:o,text:s}=yt[i];this.#N=this.add(new $t(this,{converters:o})),this.#I=this.add(new G(this,{converters:s})),this.updateDisplay()}setOptions(t){const{format:e}=t;if(e){const{color:t,text:n}=yt[e];this.#N.setOptions({converters:t}),this.#I.setOptions({converters:n})}return super.setOptions(t),this}}class Vt extends m{constructor(){super("muigui-divider")}}class Mt extends m{#A;#U;constructor(t){super(t),this.#A=[],this.#U=this}get children(){return this.#A}get controllers(){return this.#A.filter((t=>!(t instanceof Mt)))}get folders(){return this.#A.filter((t=>t instanceof Mt))}reset(t=!0){for(const e of this.#A)e instanceof Mt&&!t||e.reset(t);return this}updateDisplay(){for(const t of this.#A)t.updateDisplay();return this}remove(t){const e=this.#A.indexOf(t);if(e>=0){const t=this.#A.splice(e,1)[0];t.domElement.remove(),t.setParent(null)}return this}_addControllerImpl(t){return this.domElement.appendChild(t.domElement),this.#A.push(t),t.setParent(this),t}addController(t){return this.#U._addControllerImpl(t)}pushContainer(t){return this.addController(t),this.#U=t,t}popContainer(){return this.#U=this.#U.parent,this}}class St extends Mt{#O;constructor(t="Controls",n="muigui-menu"){super(n),this.#O=e("label"),this.addElem(e("button",{type:"button",onClick:()=>this.toggleOpen()},[this.#O])),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.#O.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}}function Dt(){}function Ft(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 Lt(t,{onDown:e=Dt,onMove:n=Dt,onUp:i=Dt}){let o;const s=function(e){const i={type:"move",...Ft(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=Ft(t,n);o=[i.x,i.y],e({type:"down",...i})};return t.addEventListener("pointerdown",a),function(){t.removeEventListener("pointerdown",a)}}class Nt 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(K(st(this.#G)))},o=e=>{const n=i(e.nx,0,1);this.#G[0]=n,this.#R=!0,t.setValue(K(st(this.#G)))};Lt(this.#j,{onDown:n,onMove:n}),Lt(this.#T,{onDown:o,onMove:o})}updateDisplay(t){this.#G||(this.#G=at(J(t)));{const[e,n,i]=at(J(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 At extends I{#Y;#W;#q;#u={open:!1};constructor(t,n,i={}){super(t,n,"muigui-pop-down-controller"),this.#Y=this.add(new kt("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 kt("div","muigui-pop-down-values")),this.#q=this.add(new kt("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 Ut extends At{constructor(t,e){super(t,e,"muigui-color-chooser"),this.addTop(new G(this)),this.addBottom(new Nt(this)),this.updateDisplay()}}class Ot 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 Et(t))}addColor(t,e,n={}){const i=t[e];return(o=n.format||ut(i)).endsWith("a")||o.startsWith("hex8")?this.addController(new Ut(t,e,n)):this.addController(new Ct(t,e,n));var o}addDivider(){return this.addController(new Vt)}addFolder(t){return this.addController(new Ot(t))}addLabel(t){return this.addController(new It(t))}}class jt extends HTMLElement{constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}}customElements.define("muigui-element",jt);const Tt=new CSSStyleSheet;Tt.replaceSync(t.default);const Pt=new CSSStyleSheet;function zt(t){let e,n;function i(){if(e&&!n){const o=e;e=void 0,n=t.replace(o).then((()=>{n=void 0,i()}))}}return function(t){e=t,i()}}const Bt=zt(Tt),Gt=zt(Pt);class Ht extends Ot{static converters=N;static mapRange=l;static makeRangeConverters=u;static makeRangeOptions=c;static makeMinMaxPair=d;#_=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=[Tt,Pt,this.#_],t.shadow.appendChild(this.domElement),s.appendChild(t)}o&&this.title(o),this.domElement.classList.add("muigui","muigui-colors")}setStyle(t){this.#_.replace(t)}static setBaseStyles(t){Bt(t)}static getBaseStyleSheet(){return Tt}static setUserStyles(t){Gt(t)}static getUserStyleSheet(){return Pt}static setTheme(e){Ht.setBaseStyles(`${t.default}\n${t.themes[e]||""}`)}}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;#Z;#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.#X+u;this.#Z&&(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)};Lt(this.domElement,{onDown:a,onMove:a}),Wt(this.domElement,{onDown:e=>{const{min:n,max:o,step:r}=this.#u,a=i(s(this.#X+e.dx*r,(t=>t),r),n,o);t.setValue(a)}}),this.#J=this.$("#muigui-arrow"),this.#K=this.$("#muigui-range"),this.setOptions(n)}updateDisplay(t){this.#X=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.#J.style.transform=`rotate(${o}rad)`}setOptions(t){a(this.#u,t);const{dirMin:e,dirMax:n,wrap:i}=this.#u;this.#Z=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.#D[this.value])}}),e("button",{type:"button",textContent:n,onClick:function(){this.previousElementSibling.click()}})]))))));const r=this;this.#D=o,this.cols(i)}updateDisplay(t){const e=this.#D.indexOf(t);for(let t=0;t{e({rect:t.getBoundingClientRect(),elem:t})})).observe(t)}function te(t,e,n,i){Qt(t,(({rect:o})=>{const{width:s,height:r}=o;t.setAttribute("viewBox",`-${s*e} -${r*n} ${s} ${r}`),i({elem:t,rect:o})}))}function ee(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 ne extends b{#Q;#tt;#et;#nt;#it;#ot;#st;#rt;#at;#X;#lt;#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.#X+l,(t=>t),a),n,r);t.setValue(u)}})),this.#Q=this.$("svg"),this.#tt=this.$("#muigui-origin"),this.#et=this.$("#muigui-ticks"),this.#nt=this.$("#muigui-thicks"),this.#it=this.$("#muigui-numbers"),this.#ot=this.$("#muigui-left-grad"),this.#st=this.$("#muigui-right-grad"),this.setOptions(n),Lt(this.domElement,{onDown:()=>{r=this.#X},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.#X+e.dx*r,(t=>t),r),n,o);t.setValue(a)}}),te(this.#Q,.5,0,(({rect:{width:t}})=>{this.#ot.setAttribute("x",-t/2),this.#st.setAttribute("x",t/2-20),this.#lt=function(t){const e=t.innerHTML;t.innerHTML="- ";const n=t.querySelector("text").getComputedTextLength();return t.innerHTML=e,n}(this.#it),this.#rt=t,this.#ut()}))}#ut(){if(!this.#rt||void 0===this.#X)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.#rt/u),d=this.#X/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.#et.setAttribute("d",ee(m,g,u/a,f,b,v*r)),this.#nt.style.stroke=c,this.#nt.setAttribute("d",ee(m,g,u,f,b,v)),this.#it.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.#lt,f,b,t),this.#tt.setAttribute("transform",`translate(${-this.#X*u/l} 0)`),this.#Q.classList.toggle("muigui-slider-up","up"===o)}updateDisplay(t){this.#X=t,this.#ut()}setOptions(t){return a(this.#u,t),this}}class ie extends b{#Q;#J;#P;#X=[];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.#Q.getBoundingClientRect(),o=2*e.nx-1,s=2*e.ny-1;t.setValue([o*n*.5,s*i*.5])};Lt(this.domElement,{onDown:n,onMove:n}),this.#Q=this.$("svg"),this.#J=this.$("#muigui-arrow"),this.#P=this.$("#muigui-circle"),te(this.#Q,.5,.5,(()=>this.#ct))}#ct(){const[t,e]=this.#X;this.#J.setAttribute("d",`M0,0L${t},${e}`),this.#P.setAttribute("transform",`translate(${t}, ${e})`)}updateDisplay(t){this.#X[0]=t[0],this.#X[1]=t[1],this.#ct()}}return Ht.ColorChooser=Ut,Ht.Direction=class extends At{#u;constructor(t,e,n){super(t,e,"muigui-direction"),this.#u=n,this.addTop(new U(this,F)),this.addBottom(new Xt(this,n)),this.updateDisplay()}},Ht.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 Zt(this,r,s)),this.updateDisplay()}},Ht.Range=B,Ht.Select=P,Ht.Slider=class extends I{constructor(t,e,n={}){super(t,e,"muigui-slider"),this.add(new ne(this,n)),this.add(new U(this,n)),this.updateDisplay()}},Ht.TextNumber=O,Ht.Vec2=class extends At{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 ie(this)),this.updateDisplay()}},Ht})); diff --git a/dist/0.x/muigui.module.js b/dist/0.x/muigui.module.js index 022e62d..65c3334 100644 --- a/dist/0.x/muigui.module.js +++ b/dist/0.x/muigui.module.js @@ -1,4 +1,4 @@ -/* muigui@0.0.7, license MIT */ +/* muigui@0.0.10, license MIT */ var css = { default: ` .muigui { @@ -694,6 +694,7 @@ themes: { --width: 400px; --bg-color: initial; --label-width: 25%; + --number-width: 20%; } input, @@ -867,7 +868,6 @@ function makeMinMaxPair(gui, properties, minPropName, maxPropName, options) { min, max: max - guiMinRange, }) -// .listen() .onChange(v => { maxGui.setValue(Math.min(max, Math.max(v + valueMinRange, properties[maxPropName]))); }); @@ -877,7 +877,6 @@ function makeMinMaxPair(gui, properties, minPropName, maxPropName, options) { min: min + guiMinRange, max, }) -// .listen() .onChange(v => { minGui.setValue(Math.max(min, Math.min(v - valueMinRange, properties[minPropName]))); }); @@ -1050,6 +1049,9 @@ class Controller extends View { } } } + updateDisplay() { + // placeholder. override + } getColors() { const toCamelCase = s => s.replace(/-([a-z])/g, (m, m1) => m1.toUpperCase()); const keys = [ @@ -1202,6 +1204,7 @@ class EditView extends View { } class CheckboxView extends EditView { + #checkboxElem; constructor(setter, id) { const checkboxElem = createElem('input', { type: 'checkbox', @@ -1214,9 +1217,10 @@ class CheckboxView extends EditView { }, }); super(createElem('label', {}, [checkboxElem])); + this.#checkboxElem = checkboxElem; } updateDisplay(v) { - this.domElement.checked = v; + this.#checkboxElem.checked = v; } } @@ -1781,27 +1785,6 @@ function createController(object, property, ...args) { } } -class ElementView extends View { - constructor(tag, className) { - super(createElem(tag, {className})); - } -} - -// TODO: remove this? Should just be user side -class Canvas extends LabelController { - #canvasElem; - - constructor() { - super('muigui-canvas'); - this.#canvasElem = this.add( - new ElementView('canvas', 'muigui-canvas'), - ).domElement; - } - get canvas() { - return this.#canvasElem; - } -} - const clamp = (v, min, max) => Math.max(min, Math.min(max, v)); const lerp = (a, b, t) => a + (b - a) * t; const fract = v => v >= 0 ? v % 1 : 1 - (v % 1); @@ -1838,12 +1821,14 @@ const cssRGBToHex = v => { const m = cssRGBRegex.exec(v); return uint8RGBToHex([m[1], m[2], m[3]].map(v => parseInt(v))); }; +const cssRGBARegex = /^\s*rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/; const hexToCssHSL = v => { const hsl = rgbUint8ToHsl(hexToUint8RGB(v)).map(v => f0(v)); return `hsl(${hsl[0]}, ${hsl[1]}%, ${hsl[2]}%)`; }; const cssHSLRegex = /^\s*hsl\(\s*(\d+)(?:deg|)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)\s*$/; +const cssHSLARegex = /^\s*hsl\(\s*(\d+)(?:deg|)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)\s*$/; const hex3DigitTo6Digit = v => `${v[0]}${v[0]}${v[1]}${v[1]}${v[2]}${v[2]}`; const cssHSLToHex = v => { @@ -1925,13 +1910,20 @@ function rgbFloatToHSV01([r, g, b]) { window.hsv01ToRGBFloat = hsv01ToRGBFloat; window.rgbFloatToHSV01 = rgbFloatToHSV01; +// Yea, meh! +const hasAlpha = format => format.endsWith('a') || format.startsWith('hex8'); + const cssStringFormats = [ { re: /^#(?:[0-9a-f]){6}$/i, format: 'hex6' }, { re: /^(?:[0-9a-f]){6}$/i, format: 'hex6-no-hash' }, + { re: /^#(?:[0-9a-f]){8}$/i, format: 'hex8' }, + { re: /^(?:[0-9a-f]){8}$/i, format: 'hex8-no-hash' }, { re: /^#(?:[0-9a-f]){3}$/i, format: 'hex3' }, { re: /^(?:[0-9a-f]){3}$/i, format: 'hex3-no-hash' }, { re: cssRGBRegex, format: 'css-rgb' }, { re: cssHSLRegex, format: 'css-hsl' }, + { re: cssRGBARegex, format: 'css-rgba' }, + { re: cssHSLARegex, format: 'css-hsla' }, ]; function guessStringColorFormat(v) { @@ -1946,7 +1938,8 @@ function guessStringColorFormat(v) { function guessFormat(v) { switch (typeof v) { case 'number': - return 'uint32-rgb'; + console.warn('can not reliably guess format based on a number. You should pass in a format like {format: "uint32-rgb"} or {format: "uint32-rgb"}'); + return v <= 0xFFFFFF ? 'uint32-rgb' : 'uint32-rgba'; case 'string': { const formatInfo = guessStringColorFormat(v.trim()); if (formatInfo) { @@ -1958,18 +1951,28 @@ function guessFormat(v) { if (v instanceof Uint8Array || v instanceof Uint8ClampedArray) { if (v.length === 3) { return 'uint8-rgb'; + } else if (v.length === 4) { + return 'uint8-rgba'; } } else if (v instanceof Float32Array) { if (v.length === 3) { return 'float-rgb'; + } else if (v.length === 4) { + return 'float-rgba'; } } else if (Array.isArray(v)) { if (v.length === 3) { return 'float-rgb'; + } else if (v.length === 4) { + return 'float-rgba'; } } else { if ('r' in v && 'g' in v && 'b' in v) { - return 'object-rgb'; + if ('a' in v) { + return 'object-rgba'; + } else { + return 'object-rgb'; + } } } } @@ -2209,6 +2212,27 @@ const colorFormatConverters = { }, }; +class ElementView extends View { + constructor(tag, className) { + super(createElem(tag, {className})); + } +} + +// TODO: remove this? Should just be user side +class Canvas extends LabelController { + #canvasElem; + + constructor() { + super('muigui-canvas'); + this.#canvasElem = this.add( + new ElementView('canvas', 'muigui-canvas'), + ).domElement; + } + get canvas() { + return this.#canvasElem; + } +} + class ColorView extends EditView { #to; #from; @@ -2313,6 +2337,12 @@ class Container extends Controller { } return this; } + updateDisplay() { + for (const controller of this.#controllers) { + controller.updateDisplay(); + } + return this; + } remove(controller) { const ndx = this.#controllers.indexOf(controller); if (ndx >= 0) { @@ -2392,201 +2422,6 @@ class Label extends Controller { } } -function showCSS(ob) { - if (ob.prototype.css) { - console.log(ob.prototype.css); - showCSS(ob.prototype); - } -} - -class Layout extends View { - static css = 'bar'; - constructor(tag, className) { - super(createElem(tag, {className})); - - showCSS(this); - } -} - -/* -class ValueController ?? { - const row = this.add(new Row()); - const label = row.add(new Label()); - const div = row.add(new Div()); - const row = div.add(new Row()); -} -*/ - -/* -class MyCustomThing extends ValueController { - constructor(object, property, options) { - const topRow = this.add(new Row()); - const bottomRow = this.add(new Row()); - topRow.add(new NumberView()); - topRow.add(new NumberView()); - topRow.add(new NumberView()); - topRow.add(new NumberView()); - bottomRow.add(new DirectionView()); - bottomRow.add(new DirectionView()); - bottomRow.add(new DirectionView()); - bottomRow.add(new DirectionView()); - } -} - new Grid([ - [new - ] - */ - -class Column extends Layout { - constructor() { - super('div', 'muigui-row'); - } -} - -class Frame extends Layout { - static css = 'foo'; - constructor() { - super('div', 'muigui-frame'); - } - static get foo() { - return 'boo'; - } -} - -class Grid extends Layout { - constructor() { - super('div', 'muigui-grid'); - } -} - -class Row extends Layout { - constructor() { - super('div', 'muigui-row'); - } -} - -class GUIFolder extends Folder { - add(object, property, ...args) { - const controller = object instanceof Controller - ? object - : createController(object, property, ...args); - return this.addController(controller); - } - addCanvas(name) { - return this.addController(new Canvas(name)); - } - addColor(object, property, ...args) { - return this.addController(new Color(object, property, ...args)); - } - addDivider() { - return this.addController(new Divider()); - } - addFolder(name) { - return this.addController(new GUIFolder(name)); - } - addLabel(text) { - return this.addController(new Label(text)); - } -} - -class MuiguiElement extends HTMLElement { - constructor() { - super(); - this.shadow = this.attachShadow({mode: 'open'}); - } -} - -customElements.define('muigui-element', MuiguiElement); - -const baseStyleSheet = new CSSStyleSheet(); -baseStyleSheet.replaceSync(css.default); -const userStyleSheet = new CSSStyleSheet(); - -function makeStyleSheetUpdater(styleSheet) { - let newCss; - let newCssPromise; - - function updateStyle() { - if (newCss && !newCssPromise) { - const s = newCss; - newCss = undefined; - newCssPromise = styleSheet.replace(s).then(() => { - console.log(s); - newCssPromise = undefined; - updateStyle(); - }); - } - } - - return function updateStyleSheet(css) { - newCss = css; - updateStyle(); - }; -} - -const updateBaseStyle = makeStyleSheetUpdater(baseStyleSheet); -const updateUserStyle = makeStyleSheetUpdater(userStyleSheet); - -class GUI extends GUIFolder { - static converters = converters; - static mapRange = mapRange; - static makeRangeConverters = makeRangeConverters; - static makeRangeOptions = makeRangeOptions; - static makeMinMaxPair = makeMinMaxPair; - #localStyleSheet = new CSSStyleSheet(); - - constructor(options = {}) { - super('Controls', 'muigui-root'); - if (options instanceof HTMLElement) { - options = {parent: options}; - } - const { - autoPlace = true, - width, - title = 'Controls', - } = options; - let { - parent, - } = options; - - if (width) { - this.domElement.style.width = /^\d+$/.test(width) ? `${width}px` : width; - } - if (parent === undefined && autoPlace) { - parent = document.body; - this.domElement.classList.add('muigui-auto-place'); - } - if (parent) { - const muiguiElement = createElem('muigui-element'); - muiguiElement.shadowRoot.adoptedStyleSheets = [baseStyleSheet, userStyleSheet, this.#localStyleSheet]; - muiguiElement.shadow.appendChild(this.domElement); - parent.appendChild(muiguiElement); - } - if (title) { - this.title(title); - } - this.domElement.classList.add('muigui', 'muigui-colors'); - } - setStyle(css) { - this.#localStyleSheet.replace(css); - } - static setBaseStyles(css) { - updateBaseStyle(css); - } - static getBaseStyleSheet() { - return baseStyleSheet; - } - static setUserStyles(css) { - updateUserStyle(css); - } - static getUserStyleSheet() { - return userStyleSheet; - } - static setTheme(name) { - GUI.setBaseStyles(`${css.default}\n${css.themes[name] || ''}`); - } -} - function noop$1() { } @@ -2833,6 +2668,204 @@ class ColorChooser extends PopDownController { } } +function showCSS(ob) { + if (ob.prototype.css) { + showCSS(ob.prototype); + } +} + +class Layout extends View { + static css = 'bar'; + constructor(tag, className) { + super(createElem(tag, {className})); + + showCSS(this); + } +} + +/* +class ValueController ?? { + const row = this.add(new Row()); + const label = row.add(new Label()); + const div = row.add(new Div()); + const row = div.add(new Row()); +} +*/ + +/* +class MyCustomThing extends ValueController { + constructor(object, property, options) { + const topRow = this.add(new Row()); + const bottomRow = this.add(new Row()); + topRow.add(new NumberView()); + topRow.add(new NumberView()); + topRow.add(new NumberView()); + topRow.add(new NumberView()); + bottomRow.add(new DirectionView()); + bottomRow.add(new DirectionView()); + bottomRow.add(new DirectionView()); + bottomRow.add(new DirectionView()); + } +} + new Grid([ + [new + ] + */ + +class Column extends Layout { + constructor() { + super('div', 'muigui-row'); + } +} + +class Frame extends Layout { + static css = 'foo'; + constructor() { + super('div', 'muigui-frame'); + } + static get foo() { + return 'boo'; + } +} + +class Grid extends Layout { + constructor() { + super('div', 'muigui-grid'); + } +} + +class Row extends Layout { + constructor() { + super('div', 'muigui-row'); + } +} + +class GUIFolder extends Folder { + add(object, property, ...args) { + const controller = object instanceof Controller + ? object + : createController(object, property, ...args); + return this.addController(controller); + } + addCanvas(name) { + return this.addController(new Canvas(name)); + } + addColor(object, property, options = {}) { + const value = object[property]; + if (hasAlpha(options.format || guessFormat(value))) { + return this.addController(new ColorChooser(object, property, options)); + } else { + return this.addController(new Color(object, property, options)); + } + } + addDivider() { + return this.addController(new Divider()); + } + addFolder(name) { + return this.addController(new GUIFolder(name)); + } + addLabel(text) { + return this.addController(new Label(text)); + } +} + +class MuiguiElement extends HTMLElement { + constructor() { + super(); + this.shadow = this.attachShadow({mode: 'open'}); + } +} + +customElements.define('muigui-element', MuiguiElement); + +const baseStyleSheet = new CSSStyleSheet(); +baseStyleSheet.replaceSync(css.default); +const userStyleSheet = new CSSStyleSheet(); + +function makeStyleSheetUpdater(styleSheet) { + let newCss; + let newCssPromise; + + function updateStyle() { + if (newCss && !newCssPromise) { + const s = newCss; + newCss = undefined; + newCssPromise = styleSheet.replace(s).then(() => { + newCssPromise = undefined; + updateStyle(); + }); + } + } + + return function updateStyleSheet(css) { + newCss = css; + updateStyle(); + }; +} + +const updateBaseStyle = makeStyleSheetUpdater(baseStyleSheet); +const updateUserStyle = makeStyleSheetUpdater(userStyleSheet); + +class GUI extends GUIFolder { + static converters = converters; + static mapRange = mapRange; + static makeRangeConverters = makeRangeConverters; + static makeRangeOptions = makeRangeOptions; + static makeMinMaxPair = makeMinMaxPair; + #localStyleSheet = new CSSStyleSheet(); + + constructor(options = {}) { + super('Controls', 'muigui-root'); + if (options instanceof HTMLElement) { + options = {parent: options}; + } + const { + autoPlace = true, + width, + title = 'Controls', + } = options; + let { + parent, + } = options; + + if (width) { + this.domElement.style.width = /^\d+$/.test(width) ? `${width}px` : width; + } + if (parent === undefined && autoPlace) { + parent = document.body; + this.domElement.classList.add('muigui-auto-place'); + } + if (parent) { + const muiguiElement = createElem('muigui-element'); + muiguiElement.shadowRoot.adoptedStyleSheets = [baseStyleSheet, userStyleSheet, this.#localStyleSheet]; + muiguiElement.shadow.appendChild(this.domElement); + parent.appendChild(muiguiElement); + } + if (title) { + this.title(title); + } + this.domElement.classList.add('muigui', 'muigui-colors'); + } + setStyle(css) { + this.#localStyleSheet.replace(css); + } + static setBaseStyles(css) { + updateBaseStyle(css); + } + static getBaseStyleSheet() { + return baseStyleSheet; + } + static setUserStyles(css) { + updateUserStyle(css); + } + static getUserStyleSheet() { + return userStyleSheet; + } + static setTheme(name) { + GUI.setBaseStyles(`${css.default}\n${css.themes[name] || ''}`); + } +} + function noop() { } diff --git a/dist/0.x/muigui.module.min.js b/dist/0.x/muigui.module.min.js index aac9a08..d2772c9 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],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}; +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 --number-width: 20%;\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}))}updateDisplay(){}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])),this.#b=i}updateDisplay(t){this.#b.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{#v;#x;constructor(t="",n=""){super("muigui-label-controller"),this.#v=V(),this.#x=e("label",{for:this.#v}),this.domElement.appendChild(this.#x),this.pushSubView(new M(t)),this.name(n)}get id(){return this.#v}name(t){return this.#x.title===this.#x.textContent&&(this.#x.title=t),this.#x.textContent=t,this}tooltip(t){this.#x.title=t}}class I extends S{#r;#a;#w;#y;#e;#k;constructor(t,e,n=""){super(n,e),this.#r=t,this.#a=e,this.#w=this.getValue(),this.#y=!1,this.#e=[]}get initialValue(){return this.#w}get object(){return this.#r}get property(){return this.#a}add(t){return this.#e.push(t),super.add(t),this.updateDisplay(),t}#E(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.#k)),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{#$;#C;#V;#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.#S(o,!0),onChange:()=>this.#S(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)}#S(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.#$,this.#V)),this.#M=!1}setOptions(t){a(this.#u,t);const{step:e,converters:{to:n,from:i}}=this.#u;return this.#$=n,this.#C=i,this.#V=e,this}}class O extends I{#I;#V;constructor(t,e,n={}){super(t,e,"muigui-checkbox"),this.#I=this.add(new U(this,n)),this.updateDisplay()}}class j extends b{#D;constructor(t,n){const i=[];super(e("select",{onChange:()=>{t.setFinalValue(this.#D[this.domElement.selectedIndex])}},n.map((([t,n])=>(i.push(n),e("option",{textContent:t})))))),this.#D=i}updateDisplay(t){const e=this.#D.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{#$;#C;#V;#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.#$,this.#V)),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.#$=o,this.#C=s,this.#V=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{#$;#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.#S(i,!0),onChange:()=>this.#S(o,!1)})),this.setOptions(n)}#S(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.#$(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,this.#C=n,this}}class H extends I{constructor(t,e){super(t,e,"muigui-checkbox"),this.add(new G(this)),this.updateDisplay()}}const R=(t,e,n)=>Math.max(e,Math.min(n,t)),Y=t=>+t.toFixed(3),W=t=>parseInt(t.substring(1,3),16)<<16|parseInt(t.substring(3,5),16)<<8|parseInt(t.substring(5,7),16),q=t=>[parseInt(t.substring(1,3),16),parseInt(t.substring(3,5),16),parseInt(t.substring(5,7),16)],_=t=>`#${Array.from(t).map((t=>t.toString(16).padStart(2,"0"))).join("")}`,J=t=>q(t).map((t=>Y(t/255))),K=t=>_(Array.from(t).map((t=>Math.round(R(255*t,0,255))))),X=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}),Z=t=>R(Math.round(255*t),0,255).toString(16).padStart(2,"0"),Q=t=>`rgb(${q(t).join(", ")})`,tt=/^\s*rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/,et=t=>{const e=ot(q(t)).map((t=>(t=>+t.toFixed(0))(t)));return`hsl(${e[0]}, ${e[1]}%, ${e[2]}%)`},nt=/^\s*hsl\(\s*(\d+)(?:deg|)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)\s*$/,it=(t,e)=>(t%e+e)%e;const ot=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 st([t,e,n]){return e=R(e,0,1),n=R(n,0,1),[t,t+2/3,t+1/3].map((t=>{return i=1,o=R(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 rt=t=>Math.round(1e3*t)/1e3;function at([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(rt)}window.hsv01ToRGBFloat=st,window.rgbFloatToHSV01=at;const lt=[{re:/^#(?:[0-9a-f]){6}$/i,format:"hex6"},{re:/^(?:[0-9a-f]){6}$/i,format:"hex6-no-hash"},{re:/^#(?:[0-9a-f]){8}$/i,format:"hex8"},{re:/^(?:[0-9a-f]){8}$/i,format:"hex8-no-hash"},{re:/^#(?:[0-9a-f]){3}$/i,format:"hex3"},{re:/^(?:[0-9a-f]){3}$/i,format:"hex3-no-hash"},{re:tt,format:"css-rgb"},{re:nt,format:"css-hsl"},{re:/^\s*rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/,format:"css-rgba"},{re:/^\s*hsl\(\s*(\d+)(?:deg|)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)\s*$/,format:"css-hsla"}];function ut(t){switch(typeof t){case"number":return console.warn('can not reliably guess format based on a number. You should pass in a format like {format: "uint32-rgb"} or {format: "uint32-rgb"}'),t<=16777215?"uint32-rgb":"uint32-rgba";case"string":{const e=function(t){for(const e of lt)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";if(4===t.length)return"uint8-rgba"}else if(t instanceof Float32Array){if(3===t.length)return"float-rgb";if(4===t.length)return"float-rgba"}else if(Array.isArray(t)){if(3===t.length)return"float-rgb";if(4===t.length)return"float-rgba"}else if("r"in t&&"g"in t&&"b"in t)return"a"in t?"object-rgba":"object-rgb"}throw new Error(`unknown color format: ${t}`)}function ct(t){return t.trim(t)}function ht(t){return t[1]===t[2]&&t[3]===t[4]&&t[5]===t[6]?`#${t[1]}${t[3]}${t[5]}`:t}const dt=/^(#|)([0-9a-f]{3})$/i;function pt(t){const e=dt.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 mt(t){return ht(ct(t))}const gt=t=>{const e=tt.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(", ")})`]},ft=t=>{const e=nt.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]}%)`]},bt=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*$/,vt=/^\s*(?:0x){0,1}([0-9a-z]{1,6})\s*$/i,xt=/^\s*#[a-f0-9]{6}\s*$|^\s*#[a-f0-9]{3}\s*$/i,wt=/^\s*[a-f0-9]{6}\s*$/i,yt={hex6:{color:{from:t=>[!0,t],to:ct},text:{from:t=>[xt.test(t),t.trim()],to:t=>t}},hex3:{color:{from:t=>[!0,mt(t)],to:pt},text:{from:t=>[xt.test(t),ht(t.trim())],to:t=>t}},"hex6-no-hash":{color:{from:t=>[!0,t.substring(1)],to:t=>`#${ct(t)}`},text:{from:t=>[wt.test(t),t.trim()],to:t=>t}},"hex3-no-hash":{color:{from:t=>[!0,mt(t).substring(1)],to:pt},text:{from:t=>[wt.test(t),ht(t.trim())],to:t=>t}},"uint32-rgb":{color:{from:t=>[!0,W(t)],to:t=>`#${Math.round(t).toString(16).padStart(6,"0")}`},text:{from:t=>(t=>{const e=vt.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,q(t)],to:_},text:{from:t=>{const e=bt.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,J(t)],to:K},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=>Y(t)))]},to:t=>Array.from(t).map((t=>Y(t))).join(", ")}},"object-rgb":{color:{from:t=>[!0,X(t)],to:t=>`#${Z(t.r)}${Z(t.g)}${Z(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:${Y(t.r)}, g:${Y(t.g)}, b:${Y(t.b)}}`}},"css-rgb":{color:{from:t=>[!0,Q(t)],to:t=>{const e=tt.exec(t);return _([e[1],e[2],e[3]].map((t=>parseInt(t))))}},text:{from:gt,to:t=>gt(t)[1]}},"css-hsl":{color:{from:t=>[!0,et(t)],to:t=>{const e=nt.exec(t),n=function([t,e,n]){t=it(t,360),e=R(e/100,0,1),n=R(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 _(n)}},text:{from:ft,to:t=>ft(t)[1]}}};class kt extends p{constructor(t,n){super(e(t,{className:n}))}}class Et extends S{#F;constructor(){super("muigui-canvas"),this.#F=this.add(new kt("canvas","muigui-canvas")).domElement}get canvas(){return this.#F}}class $t extends b{#$;#C;#L;#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.#L=i}updateDisplay(t){this.#M||(this.#L.value=this.#$(t)),this.#M=!1}setOptions(t){a(this.#u,t);const{converters:{to:e,from:n}}=this.#u;return this.#$=e,this.#C=n,this}}class Ct extends I{#N;#I;constructor(t,e,n={}){super(t,e,"muigui-color");const i=n.format||ut(this.getValue()),{color:o,text:s}=yt[i];this.#N=this.add(new $t(this,{converters:o})),this.#I=this.add(new G(this,{converters:s})),this.updateDisplay()}setOptions(t){const{format:e}=t;if(e){const{color:t,text:n}=yt[e];this.#N.setOptions({converters:t}),this.#I.setOptions({converters:n})}return super.setOptions(t),this}}class Vt extends m{constructor(){super("muigui-divider")}}class Mt extends m{#A;#U;constructor(t){super(t),this.#A=[],this.#U=this}get children(){return this.#A}get controllers(){return this.#A.filter((t=>!(t instanceof Mt)))}get folders(){return this.#A.filter((t=>t instanceof Mt))}reset(t=!0){for(const e of this.#A)e instanceof Mt&&!t||e.reset(t);return this}updateDisplay(){for(const t of this.#A)t.updateDisplay();return this}remove(t){const e=this.#A.indexOf(t);if(e>=0){const t=this.#A.splice(e,1)[0];t.domElement.remove(),t.setParent(null)}return this}_addControllerImpl(t){return this.domElement.appendChild(t.domElement),this.#A.push(t),t.setParent(this),t}addController(t){return this.#U._addControllerImpl(t)}pushContainer(t){return this.addController(t),this.#U=t,t}popContainer(){return this.#U=this.#U.parent,this}}class St extends Mt{#O;constructor(t="Controls",n="muigui-menu"){super(n),this.#O=e("label"),this.addElem(e("button",{type:"button",onClick:()=>this.toggleOpen()},[this.#O])),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.#O.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}}function Dt(){}function Ft(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 Lt(t,{onDown:e=Dt,onMove:n=Dt,onUp:i=Dt}){let o;const s=function(e){const i={type:"move",...Ft(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=Ft(t,n);o=[i.x,i.y],e({type:"down",...i})};return t.addEventListener("pointerdown",a),function(){t.removeEventListener("pointerdown",a)}}class Nt 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(K(st(this.#G)))},o=e=>{const n=i(e.nx,0,1);this.#G[0]=n,this.#R=!0,t.setValue(K(st(this.#G)))};Lt(this.#j,{onDown:n,onMove:n}),Lt(this.#T,{onDown:o,onMove:o})}updateDisplay(t){this.#G||(this.#G=at(J(t)));{const[e,n,i]=at(J(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 At extends I{#Y;#W;#q;#u={open:!1};constructor(t,n,i={}){super(t,n,"muigui-pop-down-controller"),this.#Y=this.add(new kt("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 kt("div","muigui-pop-down-values")),this.#q=this.add(new kt("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 Ut extends At{constructor(t,e){super(t,e,"muigui-color-chooser"),this.addTop(new G(this)),this.addBottom(new Nt(this)),this.updateDisplay()}}class Ot 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 Et(t))}addColor(t,e,n={}){const i=t[e];return(o=n.format||ut(i)).endsWith("a")||o.startsWith("hex8")?this.addController(new Ut(t,e,n)):this.addController(new Ct(t,e,n));var o}addDivider(){return this.addController(new Vt)}addFolder(t){return this.addController(new Ot(t))}addLabel(t){return this.addController(new It(t))}}class jt extends HTMLElement{constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}}customElements.define("muigui-element",jt);const Tt=new CSSStyleSheet;Tt.replaceSync(t.default);const Pt=new CSSStyleSheet;function zt(t){let e,n;function i(){if(e&&!n){const o=e;e=void 0,n=t.replace(o).then((()=>{n=void 0,i()}))}}return function(t){e=t,i()}}const Bt=zt(Tt),Gt=zt(Pt);class Ht extends Ot{static converters=N;static mapRange=l;static makeRangeConverters=u;static makeRangeOptions=c;static makeMinMaxPair=d;#_=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=[Tt,Pt,this.#_],t.shadow.appendChild(this.domElement),s.appendChild(t)}o&&this.title(o),this.domElement.classList.add("muigui","muigui-colors")}setStyle(t){this.#_.replace(t)}static setBaseStyles(t){Bt(t)}static getBaseStyleSheet(){return Tt}static setUserStyles(t){Gt(t)}static getUserStyleSheet(){return Pt}static setTheme(e){Ht.setBaseStyles(`${t.default}\n${t.themes[e]||""}`)}}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;#Z;#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.#X+u;this.#Z&&(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)};Lt(this.domElement,{onDown:a,onMove:a}),Wt(this.domElement,{onDown:e=>{const{min:n,max:o,step:r}=this.#u,a=i(s(this.#X+e.dx*r,(t=>t),r),n,o);t.setValue(a)}}),this.#J=this.$("#muigui-arrow"),this.#K=this.$("#muigui-range"),this.setOptions(n)}updateDisplay(t){this.#X=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.#J.style.transform=`rotate(${o}rad)`}setOptions(t){a(this.#u,t);const{dirMin:e,dirMax:n,wrap:i}=this.#u;this.#Z=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.#D[this.value])}}),e("button",{type:"button",textContent:n,onClick:function(){this.previousElementSibling.click()}})]))))));const r=this;this.#D=o,this.cols(i)}updateDisplay(t){const e=this.#D.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{#Q;#tt;#et;#nt;#it;#ot;#st;#rt;#at;#X;#lt;#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.#X+l,(t=>t),a),n,r);t.setValue(u)}})),this.#Q=this.$("svg"),this.#tt=this.$("#muigui-origin"),this.#et=this.$("#muigui-ticks"),this.#nt=this.$("#muigui-thicks"),this.#it=this.$("#muigui-numbers"),this.#ot=this.$("#muigui-left-grad"),this.#st=this.$("#muigui-right-grad"),this.setOptions(n),Lt(this.domElement,{onDown:()=>{r=this.#X},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.#X+e.dx*r,(t=>t),r),n,o);t.setValue(a)}}),ne(this.#Q,.5,0,(({rect:{width:t}})=>{this.#ot.setAttribute("x",-t/2),this.#st.setAttribute("x",t/2-20),this.#lt=function(t){const e=t.innerHTML;t.innerHTML="- ";const n=t.querySelector("text").getComputedTextLength();return t.innerHTML=e,n}(this.#it),this.#rt=t,this.#ut()}))}#ut(){if(!this.#rt||void 0===this.#X)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.#rt/u),d=this.#X/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.#et.setAttribute("d",ie(m,g,u/a,f,b,v*r)),this.#nt.style.stroke=c,this.#nt.setAttribute("d",ie(m,g,u,f,b,v)),this.#it.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.#lt,f,b,t),this.#tt.setAttribute("transform",`translate(${-this.#X*u/l} 0)`),this.#Q.classList.toggle("muigui-slider-up","up"===o)}updateDisplay(t){this.#X=t,this.#ut()}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{#Q;#J;#P;#X=[];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.#Q.getBoundingClientRect(),o=2*e.nx-1,s=2*e.ny-1;t.setValue([o*n*.5,s*i*.5])};Lt(this.domElement,{onDown:n,onMove:n}),this.#Q=this.$("svg"),this.#J=this.$("#muigui-arrow"),this.#P=this.$("#muigui-circle"),ne(this.#Q,.5,.5,(()=>this.#ct))}#ct(){const[t,e]=this.#X;this.#J.setAttribute("d",`M0,0L${t},${e}`),this.#P.setAttribute("transform",`translate(${t}, ${e})`)}updateDisplay(t){this.#X[0]=t[0],this.#X[1]=t[1],this.#ct()}}class ae extends At{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{Ut as ColorChooser,Zt as Direction,te as RadioGrid,B as Range,P as Select,se as Slider,O as TextNumber,ae as Vec2,Ht as default};