122 lines
2.7 KiB
JavaScript
122 lines
2.7 KiB
JavaScript
// components/page-items.js
|
|
import { LitElement, html, css } from 'lit'
|
|
|
|
class PageItems extends LitElement {
|
|
static properties = {
|
|
items: { type: Array },
|
|
_draft: { type: String, state: true }
|
|
}
|
|
|
|
constructor() {
|
|
super();
|
|
this.items = [];
|
|
this._draft = '';
|
|
}
|
|
|
|
static styles = css`
|
|
:host { display: block; padding: 2rem 1.5rem; }
|
|
h1 { font-size: 1.5rem; margin: 0 0 1.5rem; }
|
|
.add-form {
|
|
display: flex;
|
|
gap: 0.5rem;
|
|
margin-bottom: 2rem;
|
|
}
|
|
input {
|
|
flex: 1;
|
|
padding: 0.5rem 0.75rem;
|
|
border: 1px solid #e2e8f0;
|
|
border-radius: 6px;
|
|
font-size: 0.9rem;
|
|
outline: none;
|
|
}
|
|
input:focus { border-color: #94a3b8; }
|
|
button {
|
|
padding: 0.5rem 1rem;
|
|
background: #0f172a;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 6px;
|
|
font-size: 0.9rem;
|
|
cursor: pointer;
|
|
}
|
|
button:hover { background: #1e293b; }
|
|
ul { list-style: none; padding: 0; margin: 0; }
|
|
li {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0.75rem 0;
|
|
border-bottom: 1px solid #f1f5f9;
|
|
font-size: 0.9rem;
|
|
}
|
|
.remove {
|
|
background: none;
|
|
border: none;
|
|
color: #cbd5e1;
|
|
cursor: pointer;
|
|
font-size: 1rem;
|
|
padding: 0;
|
|
}
|
|
.remove:hover { color: #ef4444; }
|
|
.empty { color: #94a3b8; font-size: 0.9rem; }
|
|
`
|
|
|
|
#add() {
|
|
const name = this._draft.trim()
|
|
if (!name) return
|
|
|
|
this.dispatchEvent(new CustomEvent('add-item', {
|
|
detail: { item: { id: crypto.randomUUID(), name } },
|
|
bubbles: true,
|
|
composed: true
|
|
}))
|
|
|
|
this._draft = ''
|
|
}
|
|
|
|
#remove(id) {
|
|
this.dispatchEvent(new CustomEvent('remove-item', {
|
|
detail: { id },
|
|
bubbles: true,
|
|
composed: true
|
|
}))
|
|
}
|
|
|
|
#onKeydown(e) {
|
|
if (e.key === 'Enter') this.#add()
|
|
}
|
|
|
|
render() {
|
|
const items = this.items ?? []
|
|
|
|
return html`
|
|
<h1>Items</h1>
|
|
|
|
<div class="add-form">
|
|
<input
|
|
type="text"
|
|
placeholder="New item…"
|
|
.value=${this._draft}
|
|
@input=${e => this._draft = e.target.value}
|
|
@keydown=${this.#onKeydown}
|
|
/>
|
|
<button @click=${this.#add}>Add</button>
|
|
</div>
|
|
|
|
${items.length === 0
|
|
? html`<p class="empty">No items yet.</p>`
|
|
: html`
|
|
<ul>
|
|
${items.map(item => html`
|
|
<li>
|
|
<span>${item.name}</span>
|
|
<button class="remove" @click=${() => this.#remove(item.id)}>✕</button>
|
|
</li>
|
|
`)}
|
|
</ul>
|
|
`}
|
|
`
|
|
}
|
|
}
|
|
|
|
customElements.define('page-items', PageItems)
|