this repo has no description
at main 178 lines 4.2 kB view raw
1--- 2interface Props { 3 immutable?: true; 4} 5--- 6 7<script> 8 import Powers, { type powerObj } from "../../lib/powers"; 9 10 class HTMLPointsMeterElement extends HTMLElement { 11 dec: HTMLButtonElement; 12 inc: HTMLButtonElement; 13 meter: HTMLMeterElement; 14 count: HTMLElement; 15 max: HTMLElement; 16 17 constructor() { 18 super(); 19 const dec = this.querySelector("button[data-dec]"); 20 const inc = this.querySelector("button[data-inc]"); 21 const meter = this.querySelector("meter"); 22 const count = this.querySelector("span.count"); 23 const max = this.querySelector("span.max"); 24 25 if ( 26 !( 27 dec instanceof HTMLButtonElement && 28 inc instanceof HTMLButtonElement && 29 meter instanceof HTMLMeterElement && 30 count instanceof HTMLElement && 31 max instanceof HTMLElement 32 ) 33 ) { 34 throw "Elements not set correctly"; 35 } 36 37 this.dec = dec; 38 this.inc = inc; 39 this.meter = meter; 40 this.count = count; 41 this.max = max; 42 43 Powers.subscribe(this.handleState.bind(this)); 44 45 this.dec.addEventListener("click", async () => { 46 this.max.innerText = "..."; 47 this.dec.disabled = true; 48 49 await Powers.setKey("points", Powers.get().points - 1).catch((e) => 50 console.warn(e), 51 ); 52 53 this.dec.disabled = 54 !(Powers.get().points - 1 >= 0) || 55 !(Powers.get().points - 1 >= Powers.get().powers.length) || 56 this.getAttribute("disabled") !== null; 57 }); 58 59 this.inc.addEventListener("click", async () => { 60 this.max.innerText = "..."; 61 this.inc.disabled = true; 62 await Powers.setKey("points", Powers.get().points + 1).catch((e) => 63 console.warn(e), 64 ); 65 66 this.inc.disabled = this.getAttribute("disabled") !== null; 67 }); 68 } 69 70 handleState(_val: Readonly<powerObj> | null) { 71 const val = _val ? _val : { powers: [""], points: 1 }; 72 this.meter.value = val.powers.length; 73 this.meter.max = val.points; 74 this.count.innerText = val.powers.length + ""; 75 this.max.innerText = val.points + ""; 76 77 this.dec.disabled = 78 !(val.points - 1 >= 0) || 79 !(val.points - 1 >= val.powers.length) || 80 this.getAttribute("disabled") !== null; 81 } 82 } 83 84 customElements.define("points-meter", HTMLPointsMeterElement); 85</script> 86 87<points-meter disabled={Astro.props.immutable}> 88 <button aria-label="decrement" data-dec disabled={Astro.props.immutable} 89 >-</button 90 > 91 <meter></meter> 92 <span class="total" 93 ><span class="count"></span>/<span class="max"></span></span 94 > 95 <button aria-label="increment" data-inc disabled={Astro.props.immutable} 96 >+</button 97 > 98</points-meter> 99 100<style> 101 points-meter { 102 background-color: color-mix( 103 in oklch, 104 100% var(--background), 105 10% var(--text) 106 ); 107 border: 5px solid var(--text); 108 border-radius: 10px; 109 padding: 1em; 110 z-index: 99; 111 112 display: grid; 113 gap: 1em; 114 grid-template: "dec meter inc" 1fr / 1fr 3fr 1fr; 115 max-width: 100%; 116 width: 400px; 117 118 button { 119 background-color: inherit; 120 border: 3px solid; 121 border-color: inherit; 122 border-radius: inherit; 123 124 &[disabled], 125 &:active { 126 opacity: 0.7; 127 } 128 } 129 130 .total { 131 width: min-content; 132 padding: 0.2em 1em; 133 margin: auto; 134 z-index: 99; 135 136 background: var(--background); 137 border: 1px solid; 138 border-color: inherit; 139 border-radius: 0.5em; 140 } 141 142 meter { 143 appearance: none; 144 width: 100%; 145 height: 3rem; 146 background: var(--background); 147 border-radius: 10px; 148 overflow: clip; 149 150 &::-webkit-meter-bar { 151 background: inherit; 152 height: 3rem; 153 } 154 155 &::-moz-meter-bar { 156 background: var(--green); 157 } 158 159 &::-webkit-meter-optimum-value { 160 background: var(--green); 161 height: 100%; 162 } 163 } 164 165 button[data-dec] { 166 grid-area: dec; 167 } 168 169 button[data-inc] { 170 grid-area: inc; 171 } 172 173 meter, 174 .total { 175 grid-area: meter; 176 } 177 } 178</style>