English | ไธญๆ
ไธไธชๆ่ถฃ็ React ็ปไปถ โโ ๆบๅจไบบๅ็บธๆก๏ผ
ๅฏ็จไบ AI ๅฏน่ฏใๅฟซๆทๆไปคใๆฐๆฎๅค็ไธญ้ดไปถ็ญๅบๆฏ๏ผ่ชๅธฆ็ฌ็น็ๅจ็ปๆๆๅไบคไบไฝ้ชใ
ๅฑ็คบ้กต๏ผai-island.boat2moon.com
firefox_rtt8vASilo.mp4
ไธไธชๅจTiatapๆบ่ฝๆๆกฃ้กน็ฎไธญ็ๅบ็จ๏ผrumuai.top
firefox_dkJvNHpn7s.mp4
- ๐จ ็ฌ็น่ง่ง้ฃๆ ผ - 3D ๆบๅจไบบๅคด้จ + ๅฏๅฑๅผ็ๅคๅค็บธๆก
- ๐ฑ๏ธ ๅฏๆๆฝ - ๆฏๆๅจ้กต้ขไปปๆไฝ็ฝฎๆๅจ
- ๐ ๆบ่ฝไบคไบ - ่พๅ ฅๆกๆฏๆ Enter ๆไบค๏ผๅณไพง้ๅธฆๅ่ฝฆๅพๆ ๏ผๅ ่ฝฝๆถ่ชๅจ้ๅฎ
- ๐ ็ด่ง็ถๆ - ็ผ็ๆพ็คบๅ ่ฝฝ่ๅฒ/ๅ่ฎกๆถ๏ผๅคฉ็บฟๅ่บซ็ปฟ่ฒไธญๆญขๆ้ฎ
- ๐ด ๆบ่ฝ็ก็ - ๆทฑ่ฒๆจกๅผๆ้ฟๆถ้ดๆ ไบคไบ่ชๅจ้ญ็ผไผๆฏ
- ๐ ๅค้จๆงๅถ - ๆฏๆ้่ฟ
expandedprop ๅค้จๆงๅถๅฑๅผ/ๆถ่ตท - ๐ฏ ๅ่ฝๆ้ฎ - ๅฏ้ ็ฝฎ็ๆไฝๆ้ฎ๏ผๆฏๆๆฌๅๅฑๅผๅญ่ๅ
- ๐ ็ปๆ้ขๆฟ - ๆพ็คบๅค็็ปๆ๏ผๆฏๆๆฟๆข/ๆๅ ฅ็ญๆไฝ
- ๐ฌ ๅบ้จๆ็คบ - ๅฏ่ชๅฎไน็ๆ็คบไฟกๆฏๅบๅ
- ๐ง ้ซๅบฆๅฏ้ ็ฝฎ - ๆๆๅ่ฝ้่ฟ props ๆณจๅ ฅ๏ผๆ ไธๅก้ป่พ่ฆๅ
- ๐ Glass Mode - ๆไพๆฏ็ป็ (Glassmorphism) ้ฃๆ ผ้้กน๏ผ็ฐไปฃๆๅ่ถณ
โ ๏ธ ๅทฒ็ฅ้ฎ้ข: Glass Mode ๅจ Chrome/Edge ไธๅฝๅฑๆถๅฏ่ฝๅบ็ฐ้ช็๏ผ่็ผไธๅฏ่ง๏ผไฝๅฝๅฑไผๆพ็คบ๏ผใ่ฟๆฏ Chromium ๆธฒๆๅผๆ็ ๅทฒ็ฅ Bug๏ผๅจ Firefox ๅ Safari ไธๅฎๅ จๆญฃๅธธใ่ฏฆ่งๆๆฏๅๆใ - ๐ ่ช้ๅบๅธๅฑ - ็ปๆ้ขๆฟ่ชๅจ้ฟ่ฎฉ้ฎๆก๏ผไฝ็ฝฎๅๆฐๅฎๅ จๅฏ้
ๅจ src/components/RobotPrinter/ResultPanel.tsx ๆไปถ้กถ้จ๏ผไฝ ๅฏไปฅๆ นๆฎ้่ฆ่ฐๆดๅธๅฑๅธธ้๏ผ
// --- Glass ๆจกๅผๅๆฐ ---
const GLASS_GAP_TOP = 35;
const GLASS_GAP_BOTTOM = 45;
const GLASS_OFFSET_LEFT = 30;
const GLASS_OFFSET_RIGHT = 30;
// --- Default ๆจกๅผๅๆฐ ---
const DEFAULT_GAP_TOP = 65;
const DEFAULT_GAP_BOTTOM = 65;
// ...- React 19+ (Hooks)
- TypeScript 5.9+ (ไธฅๆ ผๆจกๅผ)
- Vite 7.x (ๅผๅ/ๆๅปบ)
- Vitest (ๅๅ ๆต่ฏ๏ผ114+ ๆต่ฏ็จไพ)
- CSS Variables (ไธป้ขๅ)
- ESLint + Prettier (ไปฃ็ ่ง่)
- Husky + Commitlint (Git Hooks + ๆไบค่ง่)
- GitHub Actions (CI/CD)
- sonner (Toast ้็ฅ๏ผDemo ไฝฟ็จ)
# ๅฐ็ปไปถๆไปถๅคนๅคๅถๅฐไฝ ็้กน็ฎไธญ
cp -r src/components/RobotPrinter your-project/src/components/# ๅ
้ไปๅบ
git clone https://github.com/boat2moon/RobotPrinter.git
cd RobotPrinter
# ๅฎ่ฃ
ไพ่ต
npm install
# ๅฏๅจๅผๅๆๅกๅจ
npm run dev
# ่ฟ่กๆต่ฏ
npm run test
# ๆต่ฏ่ฆ็็
npm run test:coverage
# ็ฑปๅๆฃๆฅ
npm run type-check
# ๆๅปบ็ไบง็ๆฌ
npm run build
# ๆๅปบ็ปไปถๅบ (็จไบ npm ๅๅธ)
npm run build:lib
# ๆๅปบๅนถ็ๆ Bundle ๅๆๆฅๅ
npm run build:lib:analyzeimport { RobotPrinter } from './components/RobotPrinter';
function App() {
const handleSubmit = (value: string) => {
console.log('็จๆท่พๅ
ฅ:', value);
// ่ฐ็จไฝ ็ AI API...
};
return <RobotPrinter placeholder="่พๅ
ฅๆไปค..." onSubmit={handleSubmit} />;
}ๅ ็ฝฎๅค็งๅบๆฏ้ข่ฎพ๏ผๅผ็ฎฑๅณ็จ๏ผ
import { RobotPrinter, chatPreset, darkPreset, compactPreset } from './components/RobotPrinter';
// AI ่ๅคฉๅบๆฏ
<RobotPrinter {...chatPreset} onSubmit={handleSubmit} />
// ๆทฑ่ฒไธป้ข
<RobotPrinter {...darkPreset} onSubmit={handleSubmit} />
// ็ดงๅๆจกๅผ
<RobotPrinter {...compactPreset} onSubmit={handleSubmit} />ๅฏ็จ้ข่ฎพ๏ผcompactPreset | widePreset | chatPreset | darkPreset | demoPreset | minimalPreset | floatingPreset | loadingPreset
ๆจ่ไฝฟ็จ้่ฏฏ่พน็ๅ ่ฃ ็ปไปถ๏ผ้ฒๆญขๆธฒๆ้่ฏฏๅฏผ่ด้กต้ขๅดฉๆบ๏ผ
import { RobotPrinterErrorBoundary, RobotPrinter } from './components/RobotPrinter';
<RobotPrinterErrorBoundary
fallback={(error, reset) => (
<div>
<p>็ปไปถๅบ้: {error.message}</p>
<button onClick={reset}>้่ฏ</button>
</div>
)}
>
<RobotPrinter />
</RobotPrinterErrorBoundary>;
## ๐ API ๆๆกฃ
### ๅบ็ก้
็ฝฎ
| ๅฑๆง | ็ฑปๅ | ้ป่ฎคๅผ | ่ฏดๆ |
| ---------------- | --------- | --------------- | ---------------------- |
| `placeholder` | `string` | `'่พๅ
ฅ่ฎฐๅฝ...'` | ่พๅ
ฅๆกๅ ไฝ็ฌฆๆๆฌ |
| `defaultValue` | `string` | `''` | ่พๅ
ฅๆกๅๅงๅผ |
| `paperWidth` | `number` | `500` | ็บธๆกๅฎฝๅบฆ (px) |
| `showHint` | `boolean` | `true` | ๆฏๅฆๆพ็คบๅบ้จๆไฝๆ็คบ |
| `rotateDuration` | `number` | `400` | ๆบๅจไบบๆ่ฝฌๅจ็ปๆถ้ด(ms) |
| `paperDuration` | `number` | `600` | ็บธๆกๅฑๅผๅจ็ปๆถ้ด(ms) |
### ๅค่ง้
็ฝฎ
| ๅฑๆง | ็ฑปๅ | ้ป่ฎคๅผ | ่ฏดๆ |
| ------------------ | ---------------------- | ----------------------------------- | ---------------------------------- |
| `antennaBallColor` | `string \| string[]` | `['#ff6b6b', '#e74c3c', '#c0392b']` | ๅคฉ็บฟๅฐ็้ข่ฒ๏ผๅ ่ฝฝๆถ่ชๅจๅไธบ็ปฟ่ฒ๏ผ |
| `tiltStrength` | `number` | `1` | ๅพๆๅผบๅบฆ (0-2) |
| `shadowStrength` | `number` | `1` | ้ดๅฝฑๅผบๅบฆ (0-2) |
| `styleMode` | `'default' \| 'glass'` | `'default'` | ่ง่ง้ฃๆ ผ (ๆฐ!) |
| `eyeMode` | `EyeMode` | `{ mode: 'normal' }` | ็ผ็ๆจกๅผ้
็ฝฎ๏ผ่งไธๆน็ฑปๅๅฎไน |
### ็ถๆๆงๅถ
| ๅฑๆง | ็ฑปๅ | ้ป่ฎคๅผ | ่ฏดๆ |
| ------------------ | ----------------------------- | ------- | ---------------------------------------- |
| `loading` | `boolean` | `false` | ๅ ่ฝฝ็ถๆ๏ผ็ฆ็จ่พๅ
ฅๅนถๆพ็คบ่ๅฒๅจ็ป |
| `delay` | `number` | `0` | ้ข็้ๅถๅ่ฎกๆถ (็ง)๏ผ>0 ๆถๆพ็คบ |
| `expanded` | `boolean` | - | ๅค้จๆงๅถๅฑๅผ็ถๆ๏ผๅฏ้๏ผไธไผ ๅๅ
้จๆงๅถ๏ผ |
| `onExpandedChange` | `(expanded: boolean) => void` | - | ๅฑๅผ็ถๆๅๅๅ่ฐ |
| `isDark` | `boolean` | `false` | ๆฏๅฆๆทฑ่ฒๆจกๅผ (ๅฝฑๅ็ผ็็ฉบ้ฒ็ก็ ็ถๆ) |
| `highlightTrigger` | `number` | `0` | ๅผๅๅๆถ่งฆๅๆๅจ้ซไบฎๅจ็ป |
| `position` | `{ x: number; y: number }` | - | ๅค้จๆงๅถไฝ็ฝฎ๏ผๅฏ้๏ผๅๆงๆจกๅผ๏ผ |
| `onPositionChange` | `(pos: Position) => void` | - | ไฝ็ฝฎๅๅๅ่ฐ |
### ้ซ็บง้
็ฝฎ
| ๅฑๆง | ็ฑปๅ | ่ฏดๆ |
| ------------- | ------------------- | ----------------------------------- |
| `actions` | `ActionConfig[]` | ็บธๆกไธๆน็ๆไฝ่ๅ้
็ฝฎ |
| `resultPanel` | `ResultPanelConfig` | ็ปๆๆพ็คบ้ขๆฟ็้
็ฝฎไธ็ถๆ |
| `infoContent` | `ReactNode` | ๅบ้จไฟกๆฏๆ ็่ชๅฎไนๅ
ๅฎน (ไพๅฆ token) |
#### ็ฑปๅๅฎไน
```typescript
// ็ผ็ๆจกๅผ้
็ฝฎ
type EyeMode =
| { mode: 'normal'; blinkInterval?: [number, number] }
| { mode: 'loading' }
| { mode: 'countdown' }
| { mode: 'sleeping' };
// ่ๅๅจไฝ้
็ฝฎ
interface ActionConfig {
label: string;
onClick?: (value: string) => void;
disabled?: boolean;
subActions?: ActionConfig[]; // ้ๅฝๅญ่ๅ
}
// ็ปๆ้ขๆฟ้
็ฝฎ
interface ResultPanelConfig {
visible: boolean;
content: string;
loading: boolean;
onClose: () => void;
actions?: ActionConfig[];
onPlacementChange?: (placement: 'top' | 'bottom') => void;
}
| ๅฑๆง | ็ฑปๅ | ่ฏดๆ |
|---|---|---|
onValueChange |
(value: string) => void |
่พๅ ฅๅ ๅฎนๅๅๆถ่งฆๅ |
onSubmit |
(value: string) => void |
็จๆทๆไบคๅ ๅฎนๆถ่งฆๅ (Enter ้ฎ) |
onAbort |
() => void |
็จๆท็นๅป็ปฟ่ฒๅคฉ็บฟไธญๆญขๆ้ฎๆถ่งฆๅ |
| ๅฑๆง | ็ฑปๅ | ้ป่ฎคๅผ | ่ฏดๆ |
|---|---|---|---|
draggable |
boolean |
false |
ๆฏๅฆๅฏๆๆฝ |
defaultPosition |
{ x: number; y: number } |
ๅณไธ่ง | ๅๅงไฝ็ฝฎ (viewport ๅๆ ) |
const [expanded, setExpanded] = useState(false);
// ๅค้จๆ้ฎๆงๅถๅฑๅผ/ๆถ่ตท
<button onClick={() => setExpanded(true)}>่็ฆๅฑๅผ</button>
<button onClick={() => setExpanded(false)}>ๅคฑ็ฆๆถ่ตท</button>
<RobotPrinter
expanded={expanded}
onExpandedChange={setExpanded}
/>RobotPrinter/
โโโ index.ts # ไธปๅ
ฅๅฃ๏ผๅฏผๅบๆๆๅ
ฌๅ
ฑ API
โโโ RobotPrinter.tsx # ไธป็ปไปถ
โโโ RobotPrinterRoot.tsx # ๅคๅ็ปไปถๆ นๅฎนๅจ
โโโ types.ts # ็ปไธ็ฑปๅๅฎไน
โโโ constants.ts # ๅธธ้้
็ฝฎ
โโโ defaults.ts # Props ้ป่ฎคๅผ็ฎก็
โโโ presets.ts # ้
็ฝฎ้ข่ฎพ (chat, dark, compact...)
โโโ ErrorBoundary.tsx # ้่ฏฏ่พน็็ปไปถ
โโโ Paper.tsx # ็บธๆก่พๅ
ฅๆก็ปไปถ
โโโ ResultPanel.tsx # ็ปๆ้ขๆฟ็ปไปถ
โโโ InfoBar.tsx # ๅบ้จๆ็คบๆ ็ปไปถ
โโโ context/ # Context ๆจกๅ
โ โโโ RobotPrinterContext.tsx # Provider
โ โโโ useRobotPrinter.ts # Context Hooks
โโโ hooks/ # ่ชๅฎไน Hooks
โ โโโ index.ts
โ โโโ useDrag.ts # ๆๆฝ้ป่พ
โ โโโ useAnimationPhase.ts # ๅจ็ป้ถๆฎต็ฎก็
โ โโโ useAnimationMachine.ts # ็ถๆๆบๅจ็ป (useReducer)
โ โโโ useIdleDetection.ts # ็ฉบ้ฒๆฃๆต
โ โโโ useTilt.ts # ๅพๆ/้ดๅฝฑ่ฎก็ฎ
โโโ utils/ # ๅทฅๅ
ทๅฝๆฐ
โ โโโ index.ts
โ โโโ geometry.ts # ๅ ไฝ่ฎก็ฎ
โ โโโ devWarnings.ts # ๅผๅ็ฏๅข่ญฆๅ
โโโ styles/ # ๆจกๅๅ CSS
โ โโโ index.css # ๆ ทๅผๅ
ฅๅฃ
โ โโโ tokens.css # ่ฎพ่ฎกๆ ่ฎฐ/CSS ๅ้
โ โโโ animations.css # ๅจ็ปๅ
ณ้ฎๅธง
โ โโโ base.css # ๅบ็กๅฎนๅจๆ ทๅผ
โ โโโ robot-head.css # ๆบๅจไบบๅคด้จ
โ โโโ paper.css # ็บธๆกๆ ทๅผ
โ โโโ result-panel.css # ็ปๆ้ขๆฟ
โ โโโ action-menu.css # ๆไฝ่ๅ
โ โโโ glass-backdrop.css # ๆฏ็ป็ๆๆ
โโโ menus/ # ่ๅๆจกๅ
โ โโโ index.ts
โ โโโ types.ts
โ โโโ ActionMenu.tsx
โ โโโ ActionButton.tsx
โโโ robot/ # ๆบๅจไบบๅคด้จๆจกๅ
โ โโโ index.ts
โ โโโ RobotHead.tsx
โ โโโ Eyes.tsx
โ โโโ Antenna.tsx
โโโ __tests__/ # ๅๅ
ๆต่ฏ (114+ tests)
โโโ geometry.test.ts
โโโ useIdleDetection.test.ts
โโโ useTilt.test.ts
โโโ useAnimationMachine.test.ts
โโโ devWarnings.test.ts
โโโ defaults.test.ts
โโโ RobotPrinterContext.test.tsx
โโโ RobotPrinterRoot.test.tsx
ๆฌข่ฟๆไบค Issue ๅ PR๏ผ
MIT License
English | ไธญๆ
A fun React component โ Robot Spitting Notes!
Perfect for AI conversations, quick commands, data processing middleware, and more. Features unique animations and interactive experiences.
Demo: www.boat2moon.com/robot-printer
https://github.com/boat2moon/RobotPrinter/releases/download/demo-videos/DEMO1.mp4
https://github.com/boat2moon/RobotPrinter/releases/download/demo-videos/DEMO2.mp4
- ๐จ Unique Visual Style - 3D robot head + expandable vintage paper slip
- ๐ฑ๏ธ Draggable - Drag anywhere on the page
- ๐ Smart Interaction - Enter to submit, visual Enter icon, auto-locks during loading
- ๐ Intuitive States - Eyes show loading pulse/countdown, antenna turns green as abort button
- ๐ด Smart Sleep - Automatically sleeps in dark mode or when idle
- ๐ External Control - Control expand/collapse via
expandedprop - ๐ฏ Action Buttons - Configurable buttons with hover submenus
- ๐ Result Panel - Display AI results with replace/insert actions
- ๐ฌ Info Bar - Customizable hint area at bottom
- ๐ง Highly Configurable - All features via props, no business logic coupling
- ๐ Glass Mode - Provides Glassmorphism style option, modern look
โ ๏ธ Known Issue: Glass Mode may flicker when screen recording in Chrome/Edge (invisible to naked eye, but visible in recordings). This is a known Chromium bug, works perfectly in Firefox and Safari. See technical analysis for details. - ๐ Adaptive Layout - Result panel automatically avoids obstructions, position is fully configurable
You can adjust layout constants at the top of src/components/RobotPrinter/ResultPanel.tsx as needed:
// --- Glass Mode Parameters ---
const GLASS_GAP_TOP = 35;
const GLASS_GAP_BOTTOM = 45;
const GLASS_OFFSET_LEFT = 30;
const GLASS_OFFSET_RIGHT = 30;
// --- Default Mode Parameters ---
const DEFAULT_GAP_TOP = 65;
const DEFAULT_GAP_BOTTOM = 65;
// ...- React 19+ (Hooks)
- TypeScript 5.9+ (Strict mode)
- Vite 7.x (Development/Build)
- Vitest (Unit testing, 114+ test cases)
- CSS Variables (Theming)
- ESLint + Prettier (Code style)
- Husky + Commitlint (Git Hooks + Commit conventions)
- GitHub Actions (CI/CD)
- sonner (Toast notifications, used in Demo)
# Copy component folder to your project
cp -r src/components/RobotPrinter your-project/src/components/# Clone repository
git clone https://github.com/boat2moon/RobotPrinter.git
cd RobotPrinter
# Install dependencies
npm install
# Start dev server
npm run dev
# Run tests
npm run test
# Test coverage
npm run test:coverage
# Type check
npm run type-check
# Build for production
npm run build
# Build component library (for npm publish)
npm run build:lib
# Build with bundle analysis report
npm run build:lib:analyzeimport { RobotPrinter } from './components/RobotPrinter';
function App() {
const handleSubmit = (value: string) => {
console.log('User input:', value);
// Call your AI API...
};
return <RobotPrinter placeholder="Enter command..." onSubmit={handleSubmit} />;
}Built-in presets for common scenarios:
import { RobotPrinter, chatPreset, darkPreset, compactPreset } from './components/RobotPrinter';
// AI Chat scenario
<RobotPrinter {...chatPreset} onSubmit={handleSubmit} />
// Dark theme
<RobotPrinter {...darkPreset} onSubmit={handleSubmit} />
// Compact mode
<RobotPrinter {...compactPreset} onSubmit={handleSubmit} />Available presets: compactPreset | widePreset | chatPreset | darkPreset | demoPreset | minimalPreset | floatingPreset | loadingPreset
Recommended to wrap with error boundary to prevent render errors from crashing the page:
import { RobotPrinterErrorBoundary, RobotPrinter } from './components/RobotPrinter';
<RobotPrinterErrorBoundary
fallback={(error, reset) => (
<div>
<p>Component error: {error.message}</p>
<button onClick={reset}>Retry</button>
</div>
)}
>
<RobotPrinter />
</RobotPrinterErrorBoundary>;
## ๐ API Reference
### Basic Props
| Prop | Type | Default | Description |
| ---------------- | --------- | --------------- | ----------------------------- |
| `placeholder` | `string` | `'่พๅ
ฅ่ฎฐๅฝ...'` | Input placeholder text |
| `defaultValue` | `string` | `''` | Initial input value |
| `paperWidth` | `number` | `500` | Paper width (px) |
| `showHint` | `boolean` | `true` | Show bottom hint |
| `rotateDuration` | `number` | `400` | Robot rotation animation (ms) |
| `paperDuration` | `number` | `600` | Paper expand animation (ms) |
### Appearance
| Prop | Type | Default | Description |
| ------------------ | ---------------------- | ----------------------------------- | --------------------------------------------- |
| `antennaBallColor` | `string \| string[]` | `['#ff6b6b', '#e74c3c', '#c0392b']` | Antenna ball color (turns green when loading) |
| `tiltStrength` | `number` | `1` | Tilt intensity (0-2) |
| `shadowStrength` | `number` | `1` | Shadow intensity (0-2) |
| `styleMode` | `'default' \| 'glass'` | `'default'` | Visual style (New!) |
| `eyeMode` | `EyeMode` | `{ mode: 'normal' }` | Eye mode config, see type defs below |
### State Control
| Prop | Type | Default | Description |
| ------------------ | ----------------------------- | ------- | -------------------------------------------- |
| `loading` | `boolean` | `false` | Loading state, disables input |
| `delay` | `number` | `0` | Rate limit countdown (seconds) |
| `expanded` | `boolean` | - | External control for expand state (optional) |
| `onExpandedChange` | `(expanded: boolean) => void` | - | Callback when expand state changes |
| `isDark` | `boolean` | `false` | Dark mode flag (affects idle sleep state) |
| `highlightTrigger` | `number` | `0` | Changing this value triggers shake animation |
| `position` | `{ x: number; y: number }` | - | External control for position (controlled) |
| `onPositionChange` | `(pos: Position) => void` | - | Callback when position changes |
### Advanced Configuration
| Prop | Type | Description |
| ------------- | ------------------- | ------------------------------------------ |
| `actions` | `ActionConfig[]` | Configuration for the action menu |
| `resultPanel` | `ResultPanelConfig` | Configuration for the result display panel |
| `infoContent` | `ReactNode` | Custom content for bottom info bar |
#### Type Definitions
```typescript
// Eye Mode Configuration
type EyeMode =
| { mode: 'normal'; blinkInterval?: [number, number] }
| { mode: 'loading' }
| { mode: 'countdown' }
| { mode: 'sleeping' };
// Action Menu Configuration
interface ActionConfig {
label: string;
onClick?: (value: string) => void;
disabled?: boolean;
subActions?: ActionConfig[]; // Recursive submenu
}
// Result Panel Configuration
interface ResultPanelConfig {
visible: boolean;
content: string;
loading: boolean;
onClose: () => void;
actions?: ActionConfig[];
onPlacementChange?: (placement: 'top' | 'bottom') => void;
}
| Prop | Type | Description |
|---|---|---|
onValueChange |
(value: string) => void |
Triggered on input change |
onSubmit |
(value: string) => void |
Triggered on Enter key |
onAbort |
() => void |
Triggered on green antenna click |
| Prop | Type | Default | Description |
|---|---|---|---|
draggable |
boolean |
false |
Enable dragging |
defaultPosition |
{ x: number; y: number } |
Bottom-right | Initial position |
const [expanded, setExpanded] = useState(false);
// External buttons to control expand/collapse
<button onClick={() => setExpanded(true)}>Focus & Expand</button>
<button onClick={() => setExpanded(false)}>Blur & Collapse</button>
<RobotPrinter
expanded={expanded}
onExpandedChange={setExpanded}
/>RobotPrinter/
โโโ index.ts # Entry point, exports all public APIs
โโโ RobotPrinter.tsx # Main component
โโโ RobotPrinterRoot.tsx # Compound component root container
โโโ types.ts # Unified type definitions
โโโ constants.ts # Constants configuration
โโโ defaults.ts # Props defaults management
โโโ presets.ts # Configuration presets (chat, dark, compact...)
โโโ ErrorBoundary.tsx # Error boundary component
โโโ Paper.tsx # Paper input component
โโโ ResultPanel.tsx # Result panel component
โโโ InfoBar.tsx # Info bar component
โโโ context/ # Context module
โ โโโ RobotPrinterContext.tsx # Provider
โ โโโ useRobotPrinter.ts # Context Hooks
โโโ hooks/ # Custom Hooks
โ โโโ index.ts
โ โโโ useDrag.ts # Drag logic
โ โโโ useAnimationPhase.ts # Animation phase management
โ โโโ useAnimationMachine.ts # State machine animation (useReducer)
โ โโโ useIdleDetection.ts # Idle detection
โ โโโ useTilt.ts # Tilt/shadow calculation
โโโ utils/ # Utility functions
โ โโโ index.ts
โ โโโ geometry.ts # Geometry calculations
โ โโโ devWarnings.ts # Development warnings
โโโ styles/ # Modular CSS
โ โโโ index.css # Style entry
โ โโโ tokens.css # Design tokens/CSS variables
โ โโโ animations.css # Animation keyframes
โ โโโ base.css # Base container styles
โ โโโ robot-head.css # Robot head
โ โโโ paper.css # Paper styles
โ โโโ result-panel.css # Result panel
โ โโโ action-menu.css # Action menu
โ โโโ glass-backdrop.css # Glassmorphism effect
โโโ menus/ # Menu module
โ โโโ index.ts
โ โโโ types.ts
โ โโโ ActionMenu.tsx
โ โโโ ActionButton.tsx
โโโ robot/ # Robot head module
โ โโโ index.ts
โ โโโ RobotHead.tsx
โ โโโ Eyes.tsx
โ โโโ Antenna.tsx
โโโ __tests__/ # Unit tests (114+ tests)
โโโ geometry.test.ts
โโโ useIdleDetection.test.ts
โโโ useTilt.test.ts
โโโ useAnimationMachine.test.ts
โโโ devWarnings.test.ts
โโโ defaults.test.ts
โโโ RobotPrinterContext.test.tsx
โโโ RobotPrinterRoot.test.tsx
Issues and PRs welcome!
MIT License