// 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`

Items

this._draft = e.target.value} @keydown=${this.#onKeydown} />
${items.length === 0 ? html`

No items yet.

` : html` `} ` } } customElements.define('page-items', PageItems)