WIP PWA for Grain
at main 105 lines 2.3 kB view raw
1import { LitElement, html, css } from 'lit'; 2 3export class GrainInput extends LitElement { 4 static properties = { 5 type: { type: String }, 6 placeholder: { type: String }, 7 value: { type: String }, 8 clearable: { type: Boolean } 9 }; 10 11 static styles = css` 12 :host { 13 display: block; 14 } 15 .wrapper { 16 position: relative; 17 } 18 input { 19 width: 100%; 20 padding: var(--space-sm); 21 border: 1px solid var(--color-border); 22 border-radius: 6px; 23 background: var(--color-bg-primary); 24 color: var(--color-text-primary); 25 font-size: var(--font-size-sm); 26 font-family: inherit; 27 box-sizing: border-box; 28 } 29 :host([clearable]) input { 30 padding-right: 36px; 31 } 32 input::placeholder { 33 color: var(--color-text-secondary); 34 } 35 input:focus { 36 outline: none; 37 border-color: var(--color-text-secondary); 38 } 39 .clear-btn { 40 position: absolute; 41 right: 10px; 42 top: 50%; 43 transform: translateY(-50%); 44 background: none; 45 border: none; 46 color: var(--color-text-secondary); 47 cursor: pointer; 48 padding: 4px; 49 font-size: 16px; 50 line-height: 1; 51 } 52 `; 53 54 constructor() { 55 super(); 56 this.type = 'text'; 57 this.placeholder = ''; 58 this.value = ''; 59 this.clearable = false; 60 } 61 62 #handleInput(e) { 63 this.value = e.target.value; 64 this.dispatchEvent(new CustomEvent('input', { 65 detail: { value: this.value }, 66 bubbles: true, 67 composed: true 68 })); 69 } 70 71 #handleClear() { 72 this.value = ''; 73 this.dispatchEvent(new CustomEvent('input', { 74 detail: { value: '' }, 75 bubbles: true, 76 composed: true 77 })); 78 this.dispatchEvent(new CustomEvent('clear', { 79 bubbles: true, 80 composed: true 81 })); 82 } 83 84 focus() { 85 this.shadowRoot.querySelector('input')?.focus(); 86 } 87 88 render() { 89 return html` 90 <div class="wrapper"> 91 <input 92 type=${this.type} 93 placeholder=${this.placeholder} 94 .value=${this.value} 95 @input=${this.#handleInput} 96 > 97 ${this.clearable && this.value ? html` 98 <button class="clear-btn" @click=${this.#handleClear}>&times;</button> 99 ` : ''} 100 </div> 101 `; 102 } 103} 104 105customElements.define('grain-input', GrainInput);