From 31061be273b0d4b98b83deafea62cba26eba7a87 Mon Sep 17 00:00:00 2001 From: Charles Lowell Date: Wed, 5 Aug 2026 23:51:49 -0500 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20example:=20add=20interactive=20hell?= =?UTF-8?q?o=20world?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/hello-world/package.json | 16 ++++++ examples/hello-world/src/index.ts | 80 ++++++++++++++++++++++++++++++ examples/hello-world/tsconfig.json | 10 ++++ pnpm-lock.yaml | 16 ++++++ 4 files changed, 122 insertions(+) create mode 100644 examples/hello-world/package.json create mode 100644 examples/hello-world/src/index.ts create mode 100644 examples/hello-world/tsconfig.json diff --git a/examples/hello-world/package.json b/examples/hello-world/package.json new file mode 100644 index 0000000..062ed29 --- /dev/null +++ b/examples/hello-world/package.json @@ -0,0 +1,16 @@ +{ + "name": "@examples/hello-world", + "private": true, + "type": "module", + "scripts": { + "start": "tsx src/index.ts" + }, + "dependencies": { + "@bomb.sh/tty": "^0.7.0", + "@clack/ui": "workspace:*" + }, + "devDependencies": { + "@types/node": "^22.20.0", + "tsx": "^4.19.0" + } +} diff --git a/examples/hello-world/src/index.ts b/examples/hello-world/src/index.ts new file mode 100644 index 0000000..6f2f50d --- /dev/null +++ b/examples/hello-world/src/index.ts @@ -0,0 +1,80 @@ +import { stdin, stdout } from 'node:process'; +import { fixed, grow, percent } from '@bomb.sh/tty'; +import { type BoxProps, createUI, type HostElement, rgba, type TextProps } from '@clack/ui'; + +const blue = rgba(0, 0, 238); +const cyan = rgba(0, 205, 205); +const gray = rgba(127, 127, 127); + +await using ui = await createUI({ input: stdin, output: stdout }); +const { host } = ui; + +const sayInput = host.createElement('input'); +const toInput = host.createElement('input'); + +const say = host.createLiteral('Hello'); +const comma = host.createLiteral(', '); +const to = host.createLiteral('World'); +const bang = host.createLiteral('!'); + +const output = host.createElement('text'); + +host.setProperty(output, 'color', cyan); +host.insertBefore(output, say); +host.insertBefore(output, comma); +host.insertBefore(output, to); +host.insertBefore(output, bang); + +host.addEventListener(sayInput, 'input', (event) => { + host.setText(say, event.value); +}); +host.addEventListener(toInput, 'input', (event) => { + host.setText(to, event.value); +}); + +const app = box( + { + layout: { + direction: 'ttb', + gap: 1, + padding: { top: 1, bottom: 1, left: 2, right: 2 }, + width: fixed(40), + }, + border: { color: blue, top: 1, right: 1, bottom: 1, left: 1 }, + }, + output, + box( + { layout: { direction: 'ttb', width: grow() } }, + box({ layout: { direction: 'ltr', gap: 1, width: grow() } }, label('say:'), label('to:')), + box({ layout: { direction: 'ltr', gap: 1, width: grow() } }, sayInput, toInput), + ), +); + +host.insertBefore(host.element, app); +await ui.main(); + +function box(properties: Omit, ...children: HostElement[]): HostElement { + const element = host.createElement('box'); + setProperties(element, properties); + for (const child of children) { + host.insertBefore(element, child); + } + return element; +} + +function label(content: string): HostElement { + return box({ layout: { width: percent(0.3) } }, text({ color: gray }, content)); +} + +function text(properties: TextProps, content: string): HostElement { + const element = host.createElement('text'); + setProperties(element, properties); + host.insertBefore(element, host.createLiteral(content)); + return element; +} + +function setProperties(element: HostElement, properties: object): void { + for (const [name, value] of Object.entries(properties)) { + host.setProperty(element, name, value); + } +} diff --git a/examples/hello-world/tsconfig.json b/examples/hello-world/tsconfig.json new file mode 100644 index 0000000..b71a5ec --- /dev/null +++ b/examples/hello-world/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@bomb.sh/tools/tsconfig.json", + "compilerOptions": { + "composite": false, + "declaration": false, + "declarationMap": false, + "noEmit": true, + "types": ["node"] + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f253ca2..c7fd563 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,6 +40,22 @@ importers: specifier: ^4.19.0 version: 4.23.15 + examples/hello-world: + dependencies: + '@bomb.sh/tty': + specifier: ^0.7.0 + version: 0.7.0 + '@clack/ui': + specifier: workspace:* + version: link:../../packages/ui + devDependencies: + '@types/node': + specifier: ^22.20.0 + version: 22.20.4 + tsx: + specifier: ^4.19.0 + version: 4.23.15 + packages/ui: dependencies: '@bomb.sh/tty':