forked from
grain.social/grain-pwa
WIP PWA for Grain
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}>×</button>
99 ` : ''}
100 </div>
101 `;
102 }
103}
104
105customElements.define('grain-input', GrainInput);