import type { Application } from 'pixi.js'; import { Button, Checkbox, ColorField, Dialog, HStack, Label, ListView, Menu, NumberField, Panel, ScrollContainer, TextField, Theme, type VStack, toHex, } from './ui'; /** * Developer page (`?playground`) that shows every widget of the toolkit for manual * testing: focus cycling, typing, scrubbing, color picking, scrolling, popups. */ export function mountPlayground(app: Application, root: VStack): void { const status = new Label('Interact with the widgets – events are logged here.', { style: 'muted', padding: Theme.padding, }); const log = (message: string) => status.setText(message); const row = new HStack({ gap: Theme.padding, padding: Theme.padding }); // Column 1: inputs const inputs = new Panel({ title: 'Inputs' }); inputs.content.add(new Label('Text field')); inputs.content.add( new TextField('Crate', { placeholder: 'Name', onInput: (v) => log(`text input: ${v}`), onChange: (v) => log(`text change: ${v}`), }), ); inputs.content.add(new Label('Number field (drag to scrub)')); inputs.content.add( new NumberField(100, { min: 1, step: 1, onInput: (v) => log(`number input: ${v}`), onChange: (v) => log(`number change: ${v}`), }), ); inputs.content.add( new NumberField(1, { min: 0.1, max: 10, step: 0.1, onChange: (v) => log(`zoom change: ${v}`) }), ); inputs.content.add(new Label('Color field')); inputs.content.add( new ColorField(0xe0553f, { onInput: (c) => log(`color input: ${toHex(c)}`), onChange: (c) => log(`color change: ${toHex(c)}`), }), ); const checkRow = new HStack({ gap: Theme.gap, align: 'center' }); const checkbox = new Checkbox(true); checkbox.onChange = (v) => log(`checkbox: ${v}`); checkRow.add(checkbox); checkRow.add(new Label('Checkbox'), 1); inputs.content.add(checkRow); row.add(inputs, 1); // Column 2: buttons + popups const actions = new Panel({ title: 'Buttons & popups' }); actions.content.add(new Button('Default', { onClick: () => log('default clicked') })); actions.content.add(new Button('Primary', { variant: 'primary', onClick: () => log('primary clicked') })); const toggle = new Button('Toggle me'); toggle.onClick = () => { toggle.setToggled(!toggle.toggled); log(`toggled: ${toggle.toggled}`); }; actions.content.add(toggle); actions.content.add(new Button('Ghost', { variant: 'ghost', onClick: () => log('ghost clicked') })); const disabled = new Button('Disabled'); disabled.setEnabled(false); actions.content.add(disabled); const menuButton = new Button('Open menu…'); menuButton.onClick = () => { new Menu([ { label: 'Scene', onSelect: () => log('menu: scene') }, { label: 'Camera', onSelect: () => log('menu: camera') }, { label: 'Sprite', onSelect: () => log('menu: sprite') }, { label: 'Delete', danger: true, onSelect: () => log('menu: delete') }, ]).openBelow(menuButton); }; actions.content.add(menuButton); actions.content.add( new Button('Open dialog…', { onClick: () => new Dialog('Delete asset?', 'Every placed instance is removed as well.', [ { label: 'Cancel' }, { label: 'Delete', danger: true, onClick: () => log('dialog: deleted') }, ]).openCentered(), }), ); row.add(actions, 1); // Column 3: list in a scroll container const listPanel = new Panel({ title: 'List (scroll)', padding: 0 }); const scroll = new ScrollContainer(); const list = new ListView(); list.setItems( Array.from({ length: 40 }, (_, i) => ({ id: `item-${i}`, label: `Item ${i + 1}${i % 7 === 0 ? ' with a rather long name that must truncate' : ''}`, hint: i % 3 === 0 ? 'sprite' : i % 3 === 1 ? 'camera' : 'scene', swatch: i % 3 === 0 ? (0x3fa0e0 + i * 0x040201) & 0xffffff : undefined, depth: i % 5 === 4 ? 1 : 0, })), ); list.onSelect = (id) => log(`list select: ${id}`); list.onActivate = (id) => log(`list activate: ${id}`); list.onContextMenu = (id, x, y) => new Menu([{ label: `Context for ${id}`, onSelect: () => log(`context: ${id}`) }]).open(x, y); scroll.setContent(list); listPanel.content.add(scroll, 1); row.add(listPanel, 1); root.add(new Label('Game Maker – UI playground', { style: 'bodyBold', padding: Theme.padding })); root.add(row, 1); root.add(status); root.resize(app.screen.width, app.screen.height); }