summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Gunger <kgunger12@gmail.com>2024-11-12 23:49:21 -0500
committerKyle Gunger <kgunger12@gmail.com>2024-11-12 23:49:21 -0500
commit53c95ab94cab5163424646d4a798a7ea7fb13ec7 (patch)
treebaa4551d161e1f074bc5579f4c9c6b061eddd084
parent4d93bd73f0a56974bd55db8f9e8ff3f318be195d (diff)
Toggle, Checkbox, and Slider widgets
-rw-r--r--index.html12
-rw-r--r--scripts/gui-common/color.js66
-rw-r--r--scripts/gui-common/widgets.js541
-rw-r--r--scripts/main.js36
-rw-r--r--styles/widgets.css109
5 files changed, 674 insertions, 90 deletions
diff --git a/index.html b/index.html
index d34b98d..23578ff 100644
--- a/index.html
+++ b/index.html
@@ -40,17 +40,19 @@
<div class="widget color-temp" style="--percent: 0.3;"></div>
<div class="widget color-light" style="--percent: 0.3;"></div>
<div class="widget thermostat" style="--percent: 0.3; --arch-color: #0084ff;">
- <div class="arch"></div>
- <div class="gague">68</div>
- <div class="temp">72°</div>
+ <arch></arch>
+ <gague>68</gague>
+ <temp>72°</temp>
</div>
- <div class="widget select h">
+ <div class="widget sel-button h">
<div class="widget button">Heat</div>
<div class="widget button">Cool</div>
<div class="widget button" selected>Eco</div>
</div>
</content>
- <script type="module" src="scripts/main.js"></script>
+ <script src="scripts/gui-common/color.js"></script>
+ <script src="scripts/gui-common/widgets.js"></script>
+ <script src="scripts/main.js"></script>
</body>
</html>
diff --git a/scripts/gui-common/color.js b/scripts/gui-common/color.js
new file mode 100644
index 0000000..90eac14
--- /dev/null
+++ b/scripts/gui-common/color.js
@@ -0,0 +1,66 @@
+class Color
+{
+ /** @type {Array<number>} */
+ channels = []
+
+ /**
+ * Construct a color
+ * @param {...number} nums
+ */
+ constructor(...nums)
+ {
+ this.channels = nums;
+ }
+
+ /**
+ * @param {Color} b
+ * @param {number} i
+ * @returns {Color}
+ */
+ interpolate(b, i)
+ {
+ let out = new Color();
+ for (let c = 0; c < this.channels.length && c < b.channels.length; c++)
+ {
+ out.channels.push(b.channels[c] * i + this.channels[c] * (1 - i))
+ }
+ return out;
+ }
+
+ /** Get the CSS string representing rgb
+ * @returns {string}
+ */
+ rgb()
+ {
+ return `rgb(${Math.trunc(this.channels[0] * 255)}, ${Math.trunc(this.channels[1] * 255)}, ${Math.trunc(this.channels[2] * 255)})`;
+ }
+
+ /** Get the CSS string representing rgba
+ * @returns {string}
+ */
+ rgba()
+ {
+ return `rgba(${Math.trunc(this.channels[0] * 255)}, ${Math.trunc(this.channels[1] * 255)}, ${Math.trunc(this.channels[2] * 255)}, ${this.channels[3]})`;
+ }
+
+ static from_rgb(r, g, b)
+ {
+ return new Color(r / 255, g / 255, b / 255);
+ }
+
+ static from_rgba(r, g, b)
+ {
+ return new Color(r / 255, g / 255, b / 255, a);
+ }
+}
+
+/**
+ * Interpolate between two colors
+ * @param {Color} a
+ * @param {Color} b
+ * @param {number} p
+ */
+function interpolate(a, b, p)
+{
+
+} \ No newline at end of file
diff --git a/scripts/gui-common/widgets.js b/scripts/gui-common/widgets.js
index e365f56..88f1db8 100644
--- a/scripts/gui-common/widgets.js
+++ b/scripts/gui-common/widgets.js
@@ -1,37 +1,524 @@
/**
- * @typedef {{
- * el: HTMLElement;
- * value: T;
- * set: (value: T) => void;
- * get: () => T}} Widget<T>
- * @template {any} T
+ * @typedef {"button" | "toggle" | "slider" | "checkbox" | "color-wheel" | "color-temp" | "color-light" | "thermostat" | "sel-button"} WidgetType
*/
-/**
- * @typedef {"button" | "toggle" | "slider" | "checkbox"} WidgetType
- */
+/** @template {*} T */
+class Widget extends EventTarget{
+ /** @type {T} */
+ #value = null;
-/**
- * @template {any} T
- * @param {WidgetType} type
- * @returns {Widget<T>}
- */
-function Widget (type = "button") {
- /** @type {Widget<Number>} */
- let out = {
- el: document.createElement("div"),
- value: 0,
- set: (e) => {value = e},
- get: () => this.value,
- };
+ /** @type {HTMLElement} */
+ element = null;
+
+ /** @type {boolean} */
+ inactive = false;
+
+ /**
+ * Construct a new widget
+ */
+ constructor ()
+ {
+ super();
+ this.element = document.createElement("div");
+ this.element.classList.add("widget");
+
+ this.element.addEventListener("mousedown", this.#emitMouseEvent.bind(this));
+ this.element.addEventListener("mouseup", this.#emitMouseEvent.bind(this));
+ this.element.addEventListener("mousemove", this.#emitMouseEvent.bind(this));
+ this.element.addEventListener("mouseleave", this.#emitMouseEvent.bind(this));
+ this.element.addEventListener("mouseenter", this.#emitMouseEvent.bind(this));
+
+ this.element.addEventListener("touchstart", this.#emitTouchEvent.bind(this));
+ this.element.addEventListener("touchend", this.#emitTouchEvent.bind(this));
+ this.element.addEventListener("touchmove", this.#emitTouchEvent.bind(this));
+ this.element.addEventListener("touchcancel", this.#emitTouchEvent.bind(this));
+
+ this.element.addEventListener("contextmenu", this.#emitContextEvent.bind(this));
+ }
+
+ /** @returns {T} */
+ get()
+ {
+ return this.#value;
+ }
+
+ /** @param {T} v */
+ set(v)
+ {
+ this.#value = v;
+ this.#emitChangeEvent();
+ }
+
+ /** @param {boolean} i */
+ setInactive (i)
+ {
+ this.element.classList.toggle("inactive", i);
+ this.inactive = i;
+ }
+
+ /** @returns {boolean} */
+ getInactive ()
+ {
+ return this.inactive;
+ }
+
+ #emitChangeEvent()
+ {
+ this.dispatchEvent(new CustomEvent("change", {detail: this}));
+ }
+
+ /** @param {MouseEvent} event */
+ #emitMouseEvent(event)
+ {
+ if (this.inactive)
+ this.dispatchEvent(new CustomEvent("inactive", {detail: {widget: this, event: new MouseEvent(event.type, event)}}));
+ else
+ this.dispatchEvent(new MouseEvent(event.type, event));
+ }
+
+ /** @param {TouchEvent} event */
+ #emitTouchEvent(event)
+ {
+ if (this.inactive)
+ this.dispatchEvent(new CustomEvent("inactive", {detail: {widget: this, event: new TouchEvent(event.type, event)}}));
+ else
+ this.dispatchEvent(new TouchEvent(event.type, event));
+ }
+
+ /** @param {Event} event */
+ #emitContextEvent(event)
+ {
+ if (this.inactive)
+ this.dispatchEvent(new CustomEvent("inactive", {detail: {widget: this, event: new Event(event.type, event)}}));
+ else
+ this.dispatchEvent(new Event(event.type, event));
+ event.preventDefault();
+ }
+
+ handleClick() {}
+}
+
+/** @typedef {Widget<boolean>} WidgetButton */
+class WidgetButton extends Widget
+{
+ /** @type {number} */
+ pressing = 0;
+
+ gone = 0;
+
+ #bound = null;
+
+ constructor ()
+ {
+ super();
+ this.element.classList.add("button");
+ this.addEventListener("mousedown", this.#press);
+ this.addEventListener("mouseup", this.#unpress);
+ this.addEventListener("mouseleave", this.#leave);
+ this.addEventListener("mouseenter", this.#enter);
+ this.#bound = this.#unpress.bind(this);
+ }
+
+ /** @param {MouseEvent} event */
+ #press(event)
+ {
+ this.pressing |= (1 << event.button);
+ this.set(true);
+ }
+
+ #unpress (event)
+ {
+ if (((1 << event.button) & this.pressing) == 0)
+ return;
+
+ this.pressing -= (1 << event.button);
+ if (this.pressing == 0)
+ {
+ this.set(false);
+ if (this.gone)
+ {
+ this.gone = 0;
+ window.removeEventListener("mouseup", this.#bound);
+ }
+ }
+ }
+
+ /** @param {MouseEvent} event */
+ #leave(event)
+ {
+ if (this.pressing == 0)
+ return;
+ this.gone = 1;
+ window.addEventListener("mouseup", this.#bound);
+ }
+
+ /** @param {MouseEvent} event */
+ #enter(event)
+ {
+ if (this.primed == 0)
+ return;
+ this.gone = 0;
+ window.removeEventListener("mouseup", this.#bound);
+ }
+}
+
+/** @typedef {Widget<boolean>} WidgetToggle */
+class WidgetToggle extends Widget
+{
+ /** @type {number} */
+ primed = 0;
+
+ /** @type {number} */
+ gone = 0;
+
+ #bound = null;
+
+ constructor ()
+ {
+ super();
+ this.element.classList.add("button");
+ this.element.classList.add("toggle");
+ this.addEventListener("mousedown", this.#prime);
+ this.addEventListener("mouseup", this.#toggle);
+ this.addEventListener("mouseleave", this.#leave);
+ this.addEventListener("mouseenter", this.#enter);
+ this.#bound = this.#toggle.bind(this);
+ }
+
+ /** @param {MouseEvent} event */
+ #prime(event)
+ {
+ this.primed |= (1 << event.button);
+ }
+
+ /** @param {MouseEvent} event */
+ #toggle(event)
+ {
+ if (this.gone)
+ {
+ this.primed = 0;
+ this.gone = 0;
+ window.removeEventListener("mouseup", this.#bound);
+ }
+ if (((1 << event.button) & this.primed) == 0)
+ return;
+ this.set(!this.get());
+ this.element.classList.toggle("active", this.get());
+ this.primed -= (1 << event.button);
+ }
+
+ /** @param {MouseEvent} event */
+ #leave(event)
+ {
+ if (this.primed == 0)
+ return;
+ this.gone = 1;
+ window.addEventListener("mouseup", this.#bound);
+ }
+
+ /** @param {MouseEvent} event */
+ #enter(event)
+ {
+ if (this.primed == 0)
+ return;
+ this.gone = 0;
+ window.removeEventListener("mouseup", this.#bound);
+ }
+}
+
+class WidgetCheckbox extends WidgetToggle {
+
+ constructor()
+ {
+ super();
+ this.element.classList.remove("toggle");
+ this.element.classList.add("checkbox");
+ }
+}
+
+class WidgetSlider extends Widget
+{
+ /** @type {number} */
+ #primed = 0;
+
+ /** @type {number} */
+ #gone = 0;
+
+ #boundUp = null;
+ #boundMove = null;
+
+ /** @type {HTMLElement} */
+ #detail = null;
+ /** @type {(e: HTMLElement, v: number, p: number) => void} */
+ #detailUpdater = null;
+
+ /** @type {number} */
+ #tmpNum = 0;
+
+ /** @type {number} */
+ #max;
+ /** @type {number} */
+ #min;
+ /** @type {number} */
+ #step;
+ /** @type {number} */
+ #precision;
+ /** @type {boolean} */
+ #percent;
+
+
+ /**
+ * Constructor
+ * @param {number} [max] Value the slider represents at maximum
+ * @param {number} [min] Value the slider represents at minimum
+ * @param {number} [step] Step amount
+ * @param {number} [trunc] Decimal places to keep
+ * @param {boolean} [percent] Whether to show a percentage instead of the raw number
+ */
+ constructor (max = 10, min = 1, step = 0.1, trunc = 1, percent = false)
+ {
+ super();
+ this.element.classList.add("slider");
+ let fill = document.createElement("div");
+ fill.classList.add("fill");
+ this.element.appendChild(fill);
+
+ this.#detail = document.createElement("div");
+ this.#detail.classList.add("detail");
+ this.element.appendChild(this.#detail);
+
+ this.addEventListener("mousedown", this.#press);
+ this.addEventListener("mousemove", this.#move);
+ this.addEventListener("mouseup", this.#unpress);
+ this.addEventListener("mouseleave", this.#leave);
+ this.addEventListener("mouseenter", this.#enter);
+ this.addEventListener("change", this.#change);
+
+ this.#boundUp = this.#unpress.bind(this);
+ this.#boundMove = this.#move.bind(this);
+ this.#max = max;
+ this.#min = min;
+ this.#step = step;
+ this.#precision = trunc;
+ this.#percent = percent;
+
+ this.#detailUpdater = this.update_detail.bind(this);
+ }
+
+ /** @param {MouseEvent} event */
+ #press(event)
+ {
+ this.#primed |= (1 << event.button);
+ this.#move(event);
+ }
+
+ /** @param {MouseEvent} event */
+ #move(event)
+ {
+ if (this.#primed == 0)
+ return;
+
+ let rect = this.element.getBoundingClientRect();
+ let top = 0, bot = 0, point = 0;
+ if (this.element.classList.contains("h"))
+ {
+ top = rect.right;
+ bot = rect.left;
+ point = event.clientX;
+ }
+ else
+ {
+ top = rect.bottom;
+ bot = rect.top;
+ point = top - event.clientY + bot;
+ }
+
+ if (point < bot && this.#tmpNum != this.#min)
+ this.#tmpNum = this.#min;
+ else if (point > top && this.#tmpNum != this.#max)
+ this.#tmpNum = this.#max;
+ else if (bot < point && point < top)
+ {
+ let v = ((point - bot) / (top - bot)) * (this.#max - this.#min) + this.#min;
+ let r = v % this.#step;
+ v -= v % this.#step;
+ if (r >= this.#step / 2)
+ v += this.#step;
+ this.#tmpNum = v;
+ }
+ this.#update_ui();
+ }
+
+ #change ()
+ {
+ this.#tmpNum = this.get();
+ this.#update_ui();
+ }
+
+ #update_ui()
+ {
+ if (this.#tmpNum < this.#min || this.#max < this.#tmpNum)
+ this.#tmpNum = Math.min(Math.max(this.#tmpNum, this.#min), this.#max);
+ let percent = (this.#tmpNum - this.#min) / (this.#max - this.#min);
+
+ this.#detailUpdater(this.#detail, this.#tmpNum, percent, this.#percent);
+ this.element.style.setProperty("--percent", percent);
+ }
+
+ /** @param {MouseEvent} event */
+ #unpress(event)
+ {
+ if (((1 << event.button) & this.#primed) == 0)
+ return;
+ this.#primed -= (1 << event.button);
+ if (this.#primed == 0)
+ {
+ this.set(this.#tmpNum);
+ if (this.#gone)
+ {
+ this.#gone = 0;
+ window.removeEventListener("mouseup", this.#boundUp);
+ window.removeEventListener("mousemove", this.#boundMove);
+ }
+ }
+ }
- out.el.classList = ["widget", type];
- if (type == "checkbox" || type == "toggle")
+ /** @param {MouseEvent} event */
+ #leave(event)
{
- out.el.classList.add("button");
+ if (this.#primed == 0)
+ return;
+ this.#gone = 1;
+ window.addEventListener("mouseup", this.#boundUp);
+ window.addEventListener("mousemove", this.#boundMove);
}
- return out;
+ /** @param {MouseEvent} event */
+ #enter(event)
+ {
+ if (this.#primed == 0)
+ return;
+ this.#gone = 0;
+ window.removeEventListener("mouseup", this.#boundUp);
+ window.removeEventListener("mousemove", this.#boundMove);
+ }
+
+ update_detail(el, val, percent)
+ {
+ if (this.#percent)
+ el.innerText = `${Math.trunc(percent * 100)}%`;
+ else
+ el.innerText = `${Math.trunc(Math.pow(10, this.#precision) * val) / Math.pow(10, this.#precision)}`
+ }
+
+ setDetailUpdater(updater)
+ {
+ this.#detailUpdater = updater;
+ }
+
+ /** @param {number} m */
+ setMin(m)
+ {
+ this.#min = m;
+ this.#update_ui();
+ }
+
+ /** @param {number} m */
+ setMax(m)
+ {
+ this.#max = m;
+ this.#update_ui();
+ }
+
+ /** @param {number} s */
+ setStep(s)
+ {
+ this.#step = s;
+ this.#update_ui();
+ }
+}
+
+class WidgetColorTemp extends WidgetSlider
+{
+ /** @type {Color} */
+ ORANGE = Color.from_rgb(250, 160, 100);
+ /** @type {Color} */
+ WHITE = new Color(1, 1, 1);
+ /** @type {Color} */
+ BLUE = Color.from_rgb(190, 200, 255);
+
+ constructor ()
+ {
+ super(6000, 2700, 100);
+ this.element.classList.replace("slider", "color-temp");
+
+ let fills = this.element.getElementsByClassName("fill");
+ for(let f of fills)
+ {
+ f.remove();
+ }
+
+ this.setDetailUpdater(this.update_detail.bind(this));
+ this.set(2700);
+ }
+
+ /**
+ * Update the detail for the color temp slider
+ * @param {HTMLElement} el
+ * @param {number} val
+ * @param {number} percent
+ */
+ update_detail(el, val, percent)
+ {
+ let out = null;
+ if (percent < 0.7)
+ out = this.ORANGE.interpolate(this.WHITE, percent / 0.7);
+ else
+ out = this.WHITE.interpolate(this.BLUE, (percent - 0.7) / 0.3);
+ el.style.setProperty("--detail", out.rgb());
+ }
+}
+
+class WidgetColorLight extends WidgetSlider
+{
+ /** @type {Color} */
+ WHITE = new Color(1, 1, 1);
+ /** @type {Color} */
+ BLACK = new Color(0, 0, 0);
+
+ constructor ()
+ {
+ super(1, 0, 0.01, 0, 1);
+ this.element.classList.replace("slider", "color-light");
+
+ let fills = this.element.getElementsByClassName("fill");
+ for(let f of fills)
+ {
+ f.remove();
+ }
+
+ this.setDetailUpdater(this.update_detail.bind(this));
+ this.set(0);
+ }
+
+ /**
+ * Update the detail for the color temp slider
+ * @param {HTMLElement} el
+ * @param {number} val
+ * @param {number} percent
+ */
+ update_detail(el, val, percent)
+ {
+ let out = this.BLACK.interpolate(this.WHITE, percent);
+ el.style.setProperty("--detail", out.rgb());
+ }
}
-export { Widget }; \ No newline at end of file
+/** @typedef {Widget<number>} WidgetSlider */
+/** @typedef {Widget<string>} WidgetColorWheel */
+/** @typedef {Widget<number>} WidgetColorTemp */
+/** @typedef {Widget<number>} WidgetColorLight */
+/** @typedef {Widget<number> & {getGague: () => number, setGague: (value: number) => void}} WidgetThermostat */
+/** @typedef {Widget<any> & {addSelection: (name: string, value: any) => void, setSelection: (name: string) => boolean, removeSelection: (name: string) => void, getSelection: () => string}} WidgetSelectButton */
+
+// export { Widget }; \ No newline at end of file
diff --git a/scripts/main.js b/scripts/main.js
index ce0dfe4..ac6dbe9 100644
--- a/scripts/main.js
+++ b/scripts/main.js
@@ -1,3 +1,35 @@
-import * as w from './gui-common/widgets.js';
+class Client {
-let a = w.Widget();
+
+
+ /**
+ * @param {HTMLElement} content The base element where page content is placed
+ */
+ constructor (content)
+ {
+ /** @type {WidgetToggle} */
+ this.toggle = new WidgetCheckbox();
+ content.appendChild(this.toggle.element);
+ this.slider = new WidgetSlider();
+ content.appendChild(this.slider.element);
+ this.temp = new WidgetColorTemp();
+ content.appendChild(this.temp.element);
+ this.light = new WidgetColorLight();
+ content.appendChild(this.light.element);
+ // content.appendChild(Widget("button").el);
+ // content.appendChild(Widget("checkbox").el);
+ // content.appendChild(Widget("slider").el);
+ // content.appendChild(Widget("color-wheel").el);
+ // content.appendChild(Widget("color-temp").el);
+ // content.appendChild(Widget("color-light").el);
+ // content.appendChild(Widget("thermostat").el);
+ // content.appendChild(Widget("sel-button").el);
+ this.content = content;
+ }
+}
+
+let contents = document.getElementsByTagName("content");
+if (contents.length > 0)
+ OSmClient = new Client(contents[0]);
+else
+ console.error("Unable to find content tag, OSm stopping client.");
diff --git a/styles/widgets.css b/styles/widgets.css
index 8503364..5a29507 100644
--- a/styles/widgets.css
+++ b/styles/widgets.css
@@ -26,6 +26,8 @@ input {
cursor:pointer;
position: relative;
+
+ user-select: none;
}
.widget:hover {
@@ -127,7 +129,17 @@ input {
width: calc(3 * var(--base-unit));
}
-.slider::before {
+.slider > .fill {
+ overflow: hidden;
+ width: 100%;
+ height: 100%;
+ border-radius: 10px;
+ position: absolute;
+ top: 0;
+ left: 0;
+}
+
+.slider > .fill::before {
border-radius: 10px;
position: absolute;
bottom: 0;
@@ -136,21 +148,19 @@ input {
width: 100%;
background-color: var(--w-sl-fill);
- transition-duration: 0.15s;
-
content: '';
}
-.slider.h::before {
- width: calc(100% * var(--fill-percent));
+.slider.h > .fill::before {
+ width: calc(100% * var(--percent));
height: 100%;
}
-.slider:hover::before {
+.slider:hover > .fill::before {
background-color: var(--w-sl-fill-hover);
}
-.slider:active::before {
+.slider:active > .fill::before {
background-color: var(--w-sl-fill-active);
}
@@ -175,7 +185,7 @@ input {
border-bottom: var(--w-sl-dots);
}
-.slider > .detail {
+.slider > .detail, .color-light > .detail, .color-temp > .detail {
display: block;
position: absolute;
@@ -190,15 +200,18 @@ input {
z-index: 2;
font-weight: bold;
- min-width: var(--base-unit);
+ width: calc(1.2 * var(--base-unit));
height: var(--base-unit);
- transition-duration: 0.15s;
pointer-events: none;
align-content: center;
text-align: center;
- padding-left: 3px;
- padding-right: 3px;
+ padding: 2px;
+}
+
+.slider.h > .detail, .color-light.h > .detail, .color-temp.h > .detail {
+ top: calc(100% + 20px);
+ left: calc(-1.2 * var(--base-unit) / 2 + 100% * var(--percent));
}
.slider:active > .detail {
@@ -206,7 +219,11 @@ input {
color: rgba(255, 255, 255, 1);
}
-.slider.inactive > .detail {
+.color-light:active > .detail, .color-temp:active > .detail {
+ background-color: var(--detail);
+}
+
+.inactive > .detail {
display: none;
}
@@ -359,60 +376,37 @@ input {
overflow: unset;
}
-.color-temp::after {
- content: '';
- width: calc(100% + 8px);
- height: 14px;
- border: 5px solid #444;
- position: absolute;
- bottom: calc(100% * var(--percent) - 7px);
- left: -4px;
-
- box-sizing: border-box;
-
- border-radius: 7px;
- transition-duration: 0.15s;
-}
-
-.color-temp:hover::after {
- border-color: #888;
-}
-
-.color-temp.inactive::after {
- border-color: rgb(68, 68, 68, 0);
-}
-
.color-light {
- height: var(--base-unit);
- width: calc(3 * var(--base-unit));
- background: linear-gradient(to left, white, black);
+ width: var(--base-unit);
+ height: calc(3 * var(--base-unit));
+ background: linear-gradient(white, black);
--side-color: #aaa;
overflow: unset;
}
-.color-light::after {
+.color-temp::after, .color-light::after {
content: '';
- height: calc(100% + 8px);
- width: 14px;
+ width: calc(100% + 8px);
+ height: 14px;
border: 5px solid #444;
position: absolute;
- left: calc(100% * var(--percent) - 7px);
- top: -4px;
+ bottom: calc(100% * var(--percent) - 7px);
+ left: -4px;
box-sizing: border-box;
border-radius: 7px;
- transition-duration: 0.15s;
}
-.color-light:hover::after {
+.color-temp:hover::after, .color-light:hover::after {
border-color: #888;
}
-.color-light.inactive::after {
+.color-temp.inactive::after, .color-light.inactive::after {
border-color: rgb(68, 68, 68, 0);
}
+
/**
Thermostat
*/
@@ -425,7 +419,8 @@ input {
height: calc(3 * var(--base-unit));
}
-.thermostat > .arch {
+.thermostat > arch {
+ display: block;
position: absolute;
height: 100px;
@@ -439,7 +434,7 @@ input {
background-color: #222;
}
-.thermostat > .arch::after {
+.thermostat > arch::after {
content: '';
display: block;
height: 100px;
@@ -450,7 +445,8 @@ input {
transition-duration: 0.5s;
}
-.thermostat > .gague {
+.thermostat > gague {
+ display: block;
position: absolute;
bottom: calc(-13px + ((100% - 100px) / 2) + 90px);
left: calc(-13px + 50%);
@@ -474,7 +470,8 @@ input {
font-weight: bold;
}
-.thermostat > .temp {
+.thermostat > temp {
+ display: block;
position: absolute;
bottom: calc((100% - 100px) / 2);
left: calc(50% - 65px);
@@ -487,7 +484,7 @@ input {
Button Select
*/
-.select {
+.sel-button {
display: inline-flex;
max-height: calc(2 * var(--base-unit));
max-width: calc(8 * var(--base-unit));
@@ -497,7 +494,7 @@ input {
overflow-x: auto;
}
-.select.h {
+.sel-button.h {
flex-direction: column;
height: 100%;
overflow-y: auto;
@@ -506,7 +503,7 @@ input {
overflow-x: hidden;
}
-.select > div {
+.sel-button > div {
margin: 5px 5px;
padding: 7px;
@@ -521,13 +518,13 @@ input {
width: fit-content;
}
-.select.h > div {
+.sel-button.h > div {
height: auto;
width: calc(100% - 12px);
}
-.select > div[selected] {
+.sel-button > div[selected] {
--w-bg: var(--w-sel-button-selected);
--w-bg-hover: var(--w-sel-button-selected-hover);
--w-bg-active: var(--w-sel-button-selected-active);