dex/src/components/PokemonPicker.js
chris 671e72972a Apply Prettier to the whole tree
Pure formatting — no behaviour change. Verified: build passes, all 14
routes render, service worker active, no console errors.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ve7HLspzeG2xDPtJQ8vmu
2026-09-10 11:24:31 -04:00

105 lines
2.9 KiB
JavaScript

import { el, clear } from '../lib/dom.js';
import { loadSnapshot } from '../data/snapshot.js';
import { settings } from '../store/settings.js';
import { Sprite } from './Sprite.js';
import { TypeChip } from './TypeChip.js';
import { dragToClose } from '../lib/sheet-drag.js';
let openInstance = null;
/**
* A summonable overlay to pick a Pokémon from the full snapshot list.
* `onPick(id)` fires per selection; the sheet stays open so you can add
* several. Dismiss with the backdrop, ✕, or Escape.
*/
export async function openPokemonPicker(onPick, { closeAfterPick = false } = {}) {
if (openInstance) return;
const snap = await loadSnapshot();
const backdrop = el('div', {
class: 'sheet-backdrop',
onclick: (e) => {
if (e.target === backdrop) close();
},
});
const panel = el('div', {
class: 'gsheet',
role: 'dialog',
'aria-modal': 'true',
'aria-label': 'Add a Pokémon',
});
const onKey = (e) => {
if (e.key === 'Escape') close();
};
function close() {
document.removeEventListener('keydown', onKey);
backdrop.classList.remove('is-open');
setTimeout(() => {
backdrop.remove();
openInstance = null;
}, 220);
}
const results = el('div', { class: 'picker__list' });
const input = el('input', {
class: 'search__input',
type: 'search',
placeholder: 'Name, number or type…',
autofocus: true,
oninput: (e) => run(e.target.value),
});
function run(raw) {
const q = raw.trim().toLowerCase();
clear(results);
if (!q) return;
const style = settings.get().spriteStyle;
const matches = snap.species
.filter(
(s) =>
s.name.replace(/-/g, ' ').includes(q) ||
String(s.id) === q ||
(s.types || []).some((t) => t === q),
)
.slice(0, 50);
for (const s of matches) {
results.append(
el(
'button',
{
class: 'picker__row',
type: 'button',
onclick: () => {
onPick(s.id);
if (closeAfterPick) close();
},
},
Sprite(s.id, { style, alt: s.name, size: 44 }),
el('span', { class: 'search__num' }, `#${String(s.id).padStart(4, '0')}`),
el('span', { class: 'search__name' }, s.name.replace(/-/g, ' ')),
el('span', { class: 'search__types' }, ...(s.types || []).map(TypeChip)),
),
);
}
}
const head = el(
'div',
{ class: 'gsheet__head' },
el('h2', {}, 'Add a Pokémon'),
el(
'button',
{ class: 'gsheet__close', type: 'button', 'aria-label': 'Close', onclick: close },
'✕',
),
);
dragToClose(panel, head, close);
panel.append(head, input, results);
backdrop.append(panel);
document.body.append(backdrop);
document.addEventListener('keydown', onKey);
openInstance = backdrop;
requestAnimationFrame(() => backdrop.classList.add('is-open'));
}