this repo has no description

add point counter

vielle.dev bddffbc0 63693774

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