From 47f6aeb92c90ed6c27b41fa1a91c260e5b9e7436 Mon Sep 17 00:00:00 2001 From: Aniket-508 Date: Wed, 8 Apr 2026 09:40:36 +0530 Subject: [PATCH 01/23] feat: added opentui as base --- app/(app)/docs/[[...slug]]/page.tsx | 130 +- app/icon.svg | 2 +- components/component-preview-tabs.tsx | 30 + components/component-preview.tsx | 55 +- components/component-source.tsx | 60 +- components/example-preview.tsx | 71 +- ...nal-preview-client.tsx => ink-preview.tsx} | 18 +- components/opentui-preview.tsx | 122 ++ components/terminal-preview.tsx | 32 - components/ui/theme-provider.tsx | 4 +- examples/README.md | 37 + examples/__index__.ts | 1869 ++++++++++++----- examples/{ => ink}/alert-custom.tsx | 2 +- examples/{ => ink}/alert-demo.tsx | 2 +- examples/{ => ink}/alert-error.tsx | 2 +- examples/{ => ink}/alert-no-border.tsx | 2 +- examples/{ => ink}/alert-warning.tsx | 2 +- examples/{ => ink}/app-shell-demo.tsx | 2 +- examples/{ => ink}/aspect-ratio-demo.tsx | 2 +- examples/{ => ink}/badge-basic.tsx | 2 +- examples/{ => ink}/badge-bold.tsx | 2 +- examples/{ => ink}/badge-custom-border.tsx | 2 +- examples/{ => ink}/badge-demo.tsx | 2 +- examples/{ => ink}/banner-demo.tsx | 2 +- examples/{ => ink}/banner-error.tsx | 2 +- examples/{ => ink}/banner-success.tsx | 2 +- examples/{ => ink}/bar-chart-demo.tsx | 2 +- examples/{ => ink}/big-text-demo.tsx | 2 +- examples/{ => ink}/big-text-fonts.tsx | 2 +- examples/{ => ink}/box-demo.tsx | 2 +- examples/{ => ink}/breadcrumb-demo.tsx | 2 +- examples/{ => ink}/bullet-list-demo.tsx | 2 +- examples/{ => ink}/card-demo.tsx | 2 +- examples/{ => ink}/center-demo.tsx | 2 +- examples/{ => ink}/chat-message-demo.tsx | 2 +- examples/{ => ink}/chat-thread-demo.tsx | 2 +- examples/{ => ink}/checkbox-demo.tsx | 2 +- examples/{ => ink}/checkbox-group-demo.tsx | 2 +- examples/{ => ink}/clipboard-demo.tsx | 2 +- examples/{ => ink}/clock-demo.tsx | 2 +- examples/{ => ink}/code-demo.tsx | 2 +- examples/{ => ink}/code-multiline.tsx | 2 +- examples/{ => ink}/color-picker-demo.tsx | 2 +- examples/{ => ink}/columns-demo.tsx | 2 +- examples/{ => ink}/command-palette-demo.tsx | 2 +- examples/{ => ink}/confirm-demo.tsx | 2 +- examples/{ => ink}/data-grid-demo.tsx | 2 +- examples/{ => ink}/date-picker-demo.tsx | 2 +- examples/{ => ink}/definition-demo.tsx | 2 +- examples/{ => ink}/dialog-demo.tsx | 2 +- examples/{ => ink}/diff-view-demo.tsx | 2 +- examples/{ => ink}/digits-demo.tsx | 2 +- examples/{ => ink}/directory-tree-demo.tsx | 0 examples/{ => ink}/divider-custom.tsx | 2 +- examples/{ => ink}/divider-demo.tsx | 2 +- examples/{ => ink}/drawer-demo.tsx | 2 +- examples/{ => ink}/email-input-demo.tsx | 2 +- examples/{ => ink}/embedded-terminal-demo.tsx | 2 +- examples/{ => ink}/error-boundary-demo.tsx | 2 +- examples/{ => ink}/file-change-demo.tsx | 2 +- examples/{ => ink}/file-picker-demo.tsx | 0 examples/{ => ink}/form-demo.tsx | 2 +- examples/{ => ink}/form-field-demo.tsx | 2 +- examples/{ => ink}/gauge-demo.tsx | 2 +- examples/{ => ink}/git-status-demo.tsx | 2 +- examples/{ => ink}/gradient-demo.tsx | 2 +- examples/{ => ink}/gradient-presets.tsx | 2 +- examples/{ => ink}/grid-demo.tsx | 2 +- examples/{ => ink}/heading-demo.tsx | 2 +- examples/{ => ink}/heat-map-demo.tsx | 2 +- examples/{ => ink}/help-demo.tsx | 2 +- examples/{ => ink}/help-screen-demo.tsx | 2 +- examples/{ => ink}/image-demo.tsx | 0 examples/{ => ink}/info-box-demo.tsx | 2 +- examples/{ => ink}/json-demo.tsx | 2 +- examples/{ => ink}/key-value-demo.tsx | 2 +- .../{ => ink}/keyboard-shortcuts-demo.tsx | 2 +- examples/{ => ink}/line-chart-demo.tsx | 2 +- examples/{ => ink}/link-demo.tsx | 2 +- examples/{ => ink}/link-show-href.tsx | 2 +- examples/{ => ink}/list-demo.tsx | 2 +- examples/{ => ink}/log-demo.tsx | 2 +- examples/{ => ink}/login-flow-demo.tsx | 2 +- examples/{ => ink}/markdown-demo.tsx | 2 +- examples/{ => ink}/masked-input-demo.tsx | 2 +- examples/{ => ink}/menu-demo.tsx | 2 +- examples/{ => ink}/modal-demo.tsx | 2 +- examples/{ => ink}/model-selector-demo.tsx | 2 +- examples/{ => ink}/multi-progress-compact.tsx | 2 +- examples/{ => ink}/multi-progress-demo.tsx | 2 +- examples/{ => ink}/multi-select-demo.tsx | 2 +- .../{ => ink}/notification-center-demo.tsx | 2 +- examples/{ => ink}/number-input-demo.tsx | 2 +- examples/{ => ink}/pagination-demo.tsx | 2 +- examples/{ => ink}/panel-demo.tsx | 2 +- examples/{ => ink}/password-input-demo.tsx | 2 +- examples/{ => ink}/path-input-demo.tsx | 0 examples/{ => ink}/pie-chart-demo.tsx | 2 +- examples/{ => ink}/popover-demo.tsx | 2 +- examples/{ => ink}/progress-bar-custom.tsx | 2 +- examples/{ => ink}/progress-bar-demo.tsx | 2 +- examples/{ => ink}/progress-circle-demo.tsx | 2 +- examples/{ => ink}/progress-circle-sizes.tsx | 2 +- examples/{ => ink}/qr-code-demo.tsx | 2 +- examples/{ => ink}/radio-group-demo.tsx | 2 +- examples/{ => ink}/scroll-view-demo.tsx | 2 +- examples/{ => ink}/scroll-view-scrollbar.tsx | 2 +- examples/{ => ink}/search-input-demo.tsx | 2 +- examples/{ => ink}/select-demo.tsx | 2 +- examples/{ => ink}/setup-flow-demo.tsx | 2 +- examples/{ => ink}/sidebar-demo.tsx | 2 +- examples/{ => ink}/skeleton-demo.tsx | 2 +- examples/{ => ink}/skeleton-static.tsx | 2 +- examples/{ => ink}/spacer-demo.tsx | 2 +- examples/{ => ink}/sparkline-demo.tsx | 2 +- examples/{ => ink}/spinner-demo.tsx | 2 +- examples/{ => ink}/spinner-label.tsx | 2 +- examples/{ => ink}/spinner-styles.tsx | 2 +- examples/{ => ink}/splash-screen-demo.tsx | 2 +- examples/{ => ink}/stack-demo.tsx | 2 +- examples/{ => ink}/status-message-demo.tsx | 2 +- .../{ => ink}/status-message-variants.tsx | 2 +- examples/{ => ink}/stopwatch-demo.tsx | 2 +- examples/{ => ink}/streaming-text-demo.tsx | 2 +- examples/{ => ink}/tabbed-content-demo.tsx | 2 +- examples/{ => ink}/table-demo.tsx | 2 +- examples/{ => ink}/table-selectable.tsx | 2 +- examples/{ => ink}/table-sortable.tsx | 2 +- examples/{ => ink}/tabs-demo.tsx | 2 +- examples/{ => ink}/tag-demo.tsx | 2 +- examples/{ => ink}/tag-input-demo.tsx | 2 +- examples/{ => ink}/text-area-demo.tsx | 2 +- examples/{ => ink}/text-input-cursor.tsx | 2 +- examples/{ => ink}/text-input-demo.tsx | 2 +- examples/{ => ink}/text-input-label.tsx | 2 +- examples/{ => ink}/text-input-placeholder.tsx | 2 +- examples/{ => ink}/thinking-block-demo.tsx | 2 +- examples/{ => ink}/time-picker-demo.tsx | 2 +- examples/{ => ink}/timer-demo.tsx | 2 +- examples/{ => ink}/toast-demo.tsx | 2 +- examples/{ => ink}/toast-error.tsx | 2 +- examples/{ => ink}/toggle-demo.tsx | 2 +- examples/{ => ink}/token-usage-demo.tsx | 2 +- examples/{ => ink}/tool-approval-demo.tsx | 2 +- examples/{ => ink}/tool-call-demo.tsx | 2 +- examples/{ => ink}/tooltip-demo.tsx | 2 +- examples/{ => ink}/tree-demo.tsx | 2 +- examples/{ => ink}/tree-select-demo.tsx | 2 +- examples/{ => ink}/usage-monitor-demo.tsx | 2 +- examples/{ => ink}/virtual-list-demo.tsx | 2 +- examples/{ => ink}/welcome-screen-demo.tsx | 2 +- examples/{ => ink}/wizard-demo.tsx | 2 +- examples/opentui/spinner-demo.tsx | 17 + examples/opentui/spinner-react.ts | 15 + hooks/use-animation.ts | 2 +- hooks/use-clipboard.ts | 2 +- hooks/use-focus.ts | 2 +- hooks/use-input.ts | 2 +- hooks/use-interval.ts | 2 +- hooks/use-notifications.ts | 2 +- lib/docs.ts | 57 + lib/events.ts | 48 +- lib/examples.ts | 40 + lib/page-tree.ts | 11 + lib/registry.ts | 38 + lib/terminal-themes.ts | 42 +- mdx-components.tsx | 35 +- next.config.mjs | 9 + package.json | 3 +- registry/bases.ts | 52 + registry/bases/README.md | 17 + registry/bases/__index__.ts | 9 + registry/bases/ink/blocks/.gitkeep | 1 + registry/bases/ink/components/.gitkeep | 1 + registry/bases/ink/examples/.gitkeep | 1 + .../{ => bases/ink}/hooks/use-animation.ts | 0 .../{ => bases/ink}/hooks/use-clipboard.ts | 0 registry/{ => bases/ink}/hooks/use-focus.ts | 0 registry/{ => bases/ink}/hooks/use-input.ts | 0 .../{ => bases/ink}/hooks/use-interval.ts | 0 .../ink}/hooks/use-notifications.ts | 0 registry/bases/ink/internal/.gitkeep | 1 + registry/bases/ink/registry.ts | 6 + registry/{ => bases/ink}/ui/alert.tsx | 0 registry/{ => bases/ink}/ui/app-shell.tsx | 0 registry/{ => bases/ink}/ui/aspect-ratio.tsx | 0 registry/{ => bases/ink}/ui/badge.tsx | 0 registry/{ => bases/ink}/ui/banner.tsx | 0 registry/{ => bases/ink}/ui/bar-chart.tsx | 0 registry/{ => bases/ink}/ui/big-text.tsx | 0 registry/{ => bases/ink}/ui/box.tsx | 0 registry/{ => bases/ink}/ui/breadcrumb.tsx | 0 registry/{ => bases/ink}/ui/bullet-list.tsx | 0 registry/{ => bases/ink}/ui/card.tsx | 0 registry/{ => bases/ink}/ui/center.tsx | 0 registry/{ => bases/ink}/ui/chat-message.tsx | 0 registry/{ => bases/ink}/ui/chat-thread.tsx | 0 .../{ => bases/ink}/ui/checkbox-group.tsx | 0 registry/{ => bases/ink}/ui/checkbox.tsx | 0 registry/{ => bases/ink}/ui/clipboard.tsx | 0 registry/{ => bases/ink}/ui/clock.tsx | 0 registry/{ => bases/ink}/ui/code.tsx | 0 registry/{ => bases/ink}/ui/color-picker.tsx | 0 registry/{ => bases/ink}/ui/columns.tsx | 0 .../{ => bases/ink}/ui/command-palette.tsx | 0 registry/{ => bases/ink}/ui/confirm.tsx | 0 registry/{ => bases/ink}/ui/data-grid.tsx | 0 registry/{ => bases/ink}/ui/date-picker.tsx | 0 registry/{ => bases/ink}/ui/definition.tsx | 0 registry/{ => bases/ink}/ui/dialog.tsx | 0 registry/{ => bases/ink}/ui/diff-view.tsx | 0 registry/{ => bases/ink}/ui/digits.tsx | 0 .../{ => bases/ink}/ui/directory-tree.tsx | 0 registry/{ => bases/ink}/ui/divider.tsx | 0 registry/{ => bases/ink}/ui/drawer.tsx | 0 registry/{ => bases/ink}/ui/email-input.tsx | 0 .../{ => bases/ink}/ui/embedded-terminal.tsx | 0 .../{ => bases/ink}/ui/error-boundary.tsx | 0 registry/{ => bases/ink}/ui/file-change.tsx | 0 registry/{ => bases/ink}/ui/file-picker.tsx | 0 registry/{ => bases/ink}/ui/form-field.tsx | 0 registry/{ => bases/ink}/ui/form.tsx | 2 + registry/{ => bases/ink}/ui/gauge.tsx | 0 registry/{ => bases/ink}/ui/git-status.tsx | 0 registry/{ => bases/ink}/ui/gradient.tsx | 0 registry/{ => bases/ink}/ui/grid.tsx | 0 registry/{ => bases/ink}/ui/heading.tsx | 0 registry/{ => bases/ink}/ui/heat-map.tsx | 0 registry/{ => bases/ink}/ui/help-screen.tsx | 0 registry/{ => bases/ink}/ui/help.tsx | 0 registry/{ => bases/ink}/ui/image.tsx | 0 registry/{ => bases/ink}/ui/info-box.tsx | 0 registry/{ => bases/ink}/ui/json.tsx | 0 registry/{ => bases/ink}/ui/key-value.tsx | 0 .../{ => bases/ink}/ui/keyboard-shortcuts.tsx | 0 registry/{ => bases/ink}/ui/line-chart.tsx | 0 registry/{ => bases/ink}/ui/link.tsx | 0 registry/{ => bases/ink}/ui/list.tsx | 0 registry/{ => bases/ink}/ui/log.tsx | 0 registry/{ => bases/ink}/ui/login-flow.tsx | 0 registry/{ => bases/ink}/ui/markdown.tsx | 0 registry/{ => bases/ink}/ui/masked-input.tsx | 0 registry/{ => bases/ink}/ui/menu.tsx | 0 registry/{ => bases/ink}/ui/modal.tsx | 0 .../{ => bases/ink}/ui/model-selector.tsx | 0 .../{ => bases/ink}/ui/multi-progress.tsx | 0 registry/{ => bases/ink}/ui/multi-select.tsx | 0 .../{ => bases/ink}/ui/notification-badge.tsx | 0 .../ink}/ui/notification-center.tsx | 0 registry/{ => bases/ink}/ui/number-input.tsx | 0 registry/{ => bases/ink}/ui/pagination.tsx | 0 registry/{ => bases/ink}/ui/panel.tsx | 0 .../{ => bases/ink}/ui/password-input.tsx | 0 registry/{ => bases/ink}/ui/path-input.tsx | 0 registry/{ => bases/ink}/ui/pie-chart.tsx | 0 registry/{ => bases/ink}/ui/popover.tsx | 0 registry/{ => bases/ink}/ui/progress-bar.tsx | 0 .../{ => bases/ink}/ui/progress-circle.tsx | 0 registry/{ => bases/ink}/ui/qr-code.tsx | 0 registry/{ => bases/ink}/ui/radio-group.tsx | 0 registry/{ => bases/ink}/ui/scroll-view.tsx | 0 registry/{ => bases/ink}/ui/search-input.tsx | 0 registry/{ => bases/ink}/ui/select.tsx | 0 registry/{ => bases/ink}/ui/setup-flow.tsx | 0 registry/{ => bases/ink}/ui/sidebar.tsx | 0 registry/{ => bases/ink}/ui/skeleton.tsx | 0 registry/{ => bases/ink}/ui/spacer.tsx | 0 registry/{ => bases/ink}/ui/sparkline.tsx | 0 registry/{ => bases/ink}/ui/spinner.tsx | 0 registry/{ => bases/ink}/ui/splash-screen.tsx | 0 registry/{ => bases/ink}/ui/stack.tsx | 0 .../{ => bases/ink}/ui/status-message.tsx | 0 registry/{ => bases/ink}/ui/stopwatch.tsx | 0 .../{ => bases/ink}/ui/streaming-text.tsx | 0 .../{ => bases/ink}/ui/tabbed-content.tsx | 0 registry/{ => bases/ink}/ui/table.tsx | 0 registry/{ => bases/ink}/ui/tabs.tsx | 0 registry/{ => bases/ink}/ui/tag-input.tsx | 0 registry/{ => bases/ink}/ui/tag.tsx | 0 registry/{ => bases/ink}/ui/text-area.tsx | 0 registry/{ => bases/ink}/ui/text-input.tsx | 0 .../{ => bases/ink}/ui/theme-provider.tsx | 0 .../{ => bases/ink}/ui/thinking-block.tsx | 0 registry/{ => bases/ink}/ui/time-picker.tsx | 0 registry/{ => bases/ink}/ui/timer.tsx | 0 registry/{ => bases/ink}/ui/toast.tsx | 0 registry/{ => bases/ink}/ui/toggle.tsx | 0 registry/{ => bases/ink}/ui/token-usage.tsx | 0 registry/{ => bases/ink}/ui/tool-approval.tsx | 0 registry/{ => bases/ink}/ui/tool-call.tsx | 0 registry/{ => bases/ink}/ui/tooltip.tsx | 0 registry/{ => bases/ink}/ui/tree-select.tsx | 0 registry/{ => bases/ink}/ui/tree.tsx | 0 registry/{ => bases/ink}/ui/usage-monitor.tsx | 0 registry/{ => bases/ink}/ui/virtual-list.tsx | 0 .../{ => bases/ink}/ui/welcome-screen.tsx | 0 registry/{ => bases/ink}/ui/wizard.tsx | 0 registry/bases/opentui/blocks/.gitkeep | 1 + registry/bases/opentui/components/.gitkeep | 1 + registry/bases/opentui/examples/.gitkeep | 1 + registry/bases/opentui/hooks/.gitkeep | 1 + registry/bases/opentui/internal/.gitkeep | 1 + registry/bases/opentui/lib/.gitkeep | 1 + registry/bases/opentui/registry.ts | 6 + registry/bases/opentui/ui/spinner.tsx | 124 ++ registry/config.ts | 52 + registry/themes.ts | 135 ++ scripts/build-examples.mts | 103 + scripts/build-registry.mts | 88 + tsconfig.json | 3 + types/opentui-core.d.ts | 41 + types/opentui-react.d.ts | 7 + 312 files changed, 2839 insertions(+), 845 deletions(-) create mode 100644 components/component-preview-tabs.tsx rename components/{terminal-preview-client.tsx => ink-preview.tsx} (68%) create mode 100644 components/opentui-preview.tsx delete mode 100644 components/terminal-preview.tsx create mode 100644 examples/README.md rename examples/{ => ink}/alert-custom.tsx (77%) rename examples/{ => ink}/alert-demo.tsx (87%) rename examples/{ => ink}/alert-error.tsx (75%) rename examples/{ => ink}/alert-no-border.tsx (76%) rename examples/{ => ink}/alert-warning.tsx (75%) rename examples/{ => ink}/app-shell-demo.tsx (90%) rename examples/{ => ink}/aspect-ratio-demo.tsx (73%) rename examples/{ => ink}/badge-basic.tsx (57%) rename examples/{ => ink}/badge-bold.tsx (69%) rename examples/{ => ink}/badge-custom-border.tsx (73%) rename examples/{ => ink}/badge-demo.tsx (84%) rename examples/{ => ink}/banner-demo.tsx (67%) rename examples/{ => ink}/banner-error.tsx (74%) rename examples/{ => ink}/banner-success.tsx (72%) rename examples/{ => ink}/bar-chart-demo.tsx (81%) rename examples/{ => ink}/big-text-demo.tsx (56%) rename examples/{ => ink}/big-text-fonts.tsx (81%) rename examples/{ => ink}/box-demo.tsx (78%) rename examples/{ => ink}/breadcrumb-demo.tsx (81%) rename examples/{ => ink}/bullet-list-demo.tsx (88%) rename examples/{ => ink}/card-demo.tsx (81%) rename examples/{ => ink}/center-demo.tsx (72%) rename examples/{ => ink}/chat-message-demo.tsx (78%) rename examples/{ => ink}/chat-thread-demo.tsx (78%) rename examples/{ => ink}/checkbox-demo.tsx (82%) rename examples/{ => ink}/checkbox-group-demo.tsx (80%) rename examples/{ => ink}/clipboard-demo.tsx (74%) rename examples/{ => ink}/clock-demo.tsx (52%) rename examples/{ => ink}/code-demo.tsx (62%) rename examples/{ => ink}/code-multiline.tsx (76%) rename examples/{ => ink}/color-picker-demo.tsx (58%) rename examples/{ => ink}/columns-demo.tsx (78%) rename examples/{ => ink}/command-palette-demo.tsx (90%) rename examples/{ => ink}/confirm-demo.tsx (70%) rename examples/{ => ink}/data-grid-demo.tsx (88%) rename examples/{ => ink}/date-picker-demo.tsx (64%) rename examples/{ => ink}/definition-demo.tsx (82%) rename examples/{ => ink}/dialog-demo.tsx (86%) rename examples/{ => ink}/diff-view-demo.tsx (82%) rename examples/{ => ink}/digits-demo.tsx (57%) rename examples/{ => ink}/directory-tree-demo.tsx (100%) rename examples/{ => ink}/divider-custom.tsx (88%) rename examples/{ => ink}/divider-demo.tsx (78%) rename examples/{ => ink}/drawer-demo.tsx (80%) rename examples/{ => ink}/email-input-demo.tsx (63%) rename examples/{ => ink}/embedded-terminal-demo.tsx (62%) rename examples/{ => ink}/error-boundary-demo.tsx (75%) rename examples/{ => ink}/file-change-demo.tsx (85%) rename examples/{ => ink}/file-picker-demo.tsx (100%) rename examples/{ => ink}/form-demo.tsx (88%) rename examples/{ => ink}/form-field-demo.tsx (76%) rename examples/{ => ink}/gauge-demo.tsx (66%) rename examples/{ => ink}/git-status-demo.tsx (65%) rename examples/{ => ink}/gradient-demo.tsx (69%) rename examples/{ => ink}/gradient-presets.tsx (83%) rename examples/{ => ink}/grid-demo.tsx (82%) rename examples/{ => ink}/heading-demo.tsx (80%) rename examples/{ => ink}/heat-map-demo.tsx (82%) rename examples/{ => ink}/help-demo.tsx (83%) rename examples/{ => ink}/help-screen-demo.tsx (92%) rename examples/{ => ink}/image-demo.tsx (100%) rename examples/{ => ink}/info-box-demo.tsx (86%) rename examples/{ => ink}/json-demo.tsx (82%) rename examples/{ => ink}/key-value-demo.tsx (78%) rename examples/{ => ink}/keyboard-shortcuts-demo.tsx (84%) rename examples/{ => ink}/line-chart-demo.tsx (81%) rename examples/{ => ink}/link-demo.tsx (71%) rename examples/{ => ink}/link-show-href.tsx (85%) rename examples/{ => ink}/list-demo.tsx (85%) rename examples/{ => ink}/log-demo.tsx (91%) rename examples/{ => ink}/login-flow-demo.tsx (88%) rename examples/{ => ink}/markdown-demo.tsx (69%) rename examples/{ => ink}/masked-input-demo.tsx (72%) rename examples/{ => ink}/menu-demo.tsx (89%) rename examples/{ => ink}/modal-demo.tsx (79%) rename examples/{ => ink}/model-selector-demo.tsx (83%) rename examples/{ => ink}/multi-progress-compact.tsx (79%) rename examples/{ => ink}/multi-progress-demo.tsx (87%) rename examples/{ => ink}/multi-select-demo.tsx (78%) rename examples/{ => ink}/notification-center-demo.tsx (57%) rename examples/{ => ink}/number-input-demo.tsx (63%) rename examples/{ => ink}/pagination-demo.tsx (76%) rename examples/{ => ink}/panel-demo.tsx (79%) rename examples/{ => ink}/password-input-demo.tsx (66%) rename examples/{ => ink}/path-input-demo.tsx (100%) rename examples/{ => ink}/pie-chart-demo.tsx (79%) rename examples/{ => ink}/popover-demo.tsx (80%) rename examples/{ => ink}/progress-bar-custom.tsx (65%) rename examples/{ => ink}/progress-bar-demo.tsx (60%) rename examples/{ => ink}/progress-circle-demo.tsx (61%) rename examples/{ => ink}/progress-circle-sizes.tsx (79%) rename examples/{ => ink}/qr-code-demo.tsx (67%) rename examples/{ => ink}/radio-group-demo.tsx (78%) rename examples/{ => ink}/scroll-view-demo.tsx (88%) rename examples/{ => ink}/scroll-view-scrollbar.tsx (89%) rename examples/{ => ink}/search-input-demo.tsx (75%) rename examples/{ => ink}/select-demo.tsx (82%) rename examples/{ => ink}/setup-flow-demo.tsx (92%) rename examples/{ => ink}/sidebar-demo.tsx (90%) rename examples/{ => ink}/skeleton-demo.tsx (59%) rename examples/{ => ink}/skeleton-static.tsx (63%) rename examples/{ => ink}/spacer-demo.tsx (77%) rename examples/{ => ink}/sparkline-demo.tsx (83%) rename examples/{ => ink}/spinner-demo.tsx (80%) rename examples/{ => ink}/spinner-label.tsx (63%) rename examples/{ => ink}/spinner-styles.tsx (87%) rename examples/{ => ink}/splash-screen-demo.tsx (81%) rename examples/{ => ink}/stack-demo.tsx (79%) rename examples/{ => ink}/status-message-demo.tsx (66%) rename examples/{ => ink}/status-message-variants.tsx (85%) rename examples/{ => ink}/stopwatch-demo.tsx (55%) rename examples/{ => ink}/streaming-text-demo.tsx (63%) rename examples/{ => ink}/tabbed-content-demo.tsx (89%) rename examples/{ => ink}/table-demo.tsx (89%) rename examples/{ => ink}/table-selectable.tsx (92%) rename examples/{ => ink}/table-sortable.tsx (90%) rename examples/{ => ink}/tabs-demo.tsx (91%) rename examples/{ => ink}/tag-demo.tsx (78%) rename examples/{ => ink}/tag-input-demo.tsx (60%) rename examples/{ => ink}/text-area-demo.tsx (72%) rename examples/{ => ink}/text-input-cursor.tsx (84%) rename examples/{ => ink}/text-input-demo.tsx (65%) rename examples/{ => ink}/text-input-label.tsx (80%) rename examples/{ => ink}/text-input-placeholder.tsx (63%) rename examples/{ => ink}/thinking-block-demo.tsx (69%) rename examples/{ => ink}/time-picker-demo.tsx (65%) rename examples/{ => ink}/timer-demo.tsx (67%) rename examples/{ => ink}/toast-demo.tsx (68%) rename examples/{ => ink}/toast-error.tsx (74%) rename examples/{ => ink}/toggle-demo.tsx (62%) rename examples/{ => ink}/token-usage-demo.tsx (60%) rename examples/{ => ink}/tool-approval-demo.tsx (77%) rename examples/{ => ink}/tool-call-demo.tsx (80%) rename examples/{ => ink}/tooltip-demo.tsx (80%) rename examples/{ => ink}/tree-demo.tsx (88%) rename examples/{ => ink}/tree-select-demo.tsx (85%) rename examples/{ => ink}/usage-monitor-demo.tsx (93%) rename examples/{ => ink}/virtual-list-demo.tsx (82%) rename examples/{ => ink}/welcome-screen-demo.tsx (92%) rename examples/{ => ink}/wizard-demo.tsx (90%) create mode 100644 examples/opentui/spinner-demo.tsx create mode 100644 examples/opentui/spinner-react.ts create mode 100644 lib/examples.ts create mode 100644 lib/registry.ts create mode 100644 registry/bases.ts create mode 100644 registry/bases/README.md create mode 100644 registry/bases/__index__.ts create mode 100644 registry/bases/ink/blocks/.gitkeep create mode 100644 registry/bases/ink/components/.gitkeep create mode 100644 registry/bases/ink/examples/.gitkeep rename registry/{ => bases/ink}/hooks/use-animation.ts (100%) rename registry/{ => bases/ink}/hooks/use-clipboard.ts (100%) rename registry/{ => bases/ink}/hooks/use-focus.ts (100%) rename registry/{ => bases/ink}/hooks/use-input.ts (100%) rename registry/{ => bases/ink}/hooks/use-interval.ts (100%) rename registry/{ => bases/ink}/hooks/use-notifications.ts (100%) create mode 100644 registry/bases/ink/internal/.gitkeep create mode 100644 registry/bases/ink/registry.ts rename registry/{ => bases/ink}/ui/alert.tsx (100%) rename registry/{ => bases/ink}/ui/app-shell.tsx (100%) rename registry/{ => bases/ink}/ui/aspect-ratio.tsx (100%) rename registry/{ => bases/ink}/ui/badge.tsx (100%) rename registry/{ => bases/ink}/ui/banner.tsx (100%) rename registry/{ => bases/ink}/ui/bar-chart.tsx (100%) rename registry/{ => bases/ink}/ui/big-text.tsx (100%) rename registry/{ => bases/ink}/ui/box.tsx (100%) rename registry/{ => bases/ink}/ui/breadcrumb.tsx (100%) rename registry/{ => bases/ink}/ui/bullet-list.tsx (100%) rename registry/{ => bases/ink}/ui/card.tsx (100%) rename registry/{ => bases/ink}/ui/center.tsx (100%) rename registry/{ => bases/ink}/ui/chat-message.tsx (100%) rename registry/{ => bases/ink}/ui/chat-thread.tsx (100%) rename registry/{ => bases/ink}/ui/checkbox-group.tsx (100%) rename registry/{ => bases/ink}/ui/checkbox.tsx (100%) rename registry/{ => bases/ink}/ui/clipboard.tsx (100%) rename registry/{ => bases/ink}/ui/clock.tsx (100%) rename registry/{ => bases/ink}/ui/code.tsx (100%) rename registry/{ => bases/ink}/ui/color-picker.tsx (100%) rename registry/{ => bases/ink}/ui/columns.tsx (100%) rename registry/{ => bases/ink}/ui/command-palette.tsx (100%) rename registry/{ => bases/ink}/ui/confirm.tsx (100%) rename registry/{ => bases/ink}/ui/data-grid.tsx (100%) rename registry/{ => bases/ink}/ui/date-picker.tsx (100%) rename registry/{ => bases/ink}/ui/definition.tsx (100%) rename registry/{ => bases/ink}/ui/dialog.tsx (100%) rename registry/{ => bases/ink}/ui/diff-view.tsx (100%) rename registry/{ => bases/ink}/ui/digits.tsx (100%) rename registry/{ => bases/ink}/ui/directory-tree.tsx (100%) rename registry/{ => bases/ink}/ui/divider.tsx (100%) rename registry/{ => bases/ink}/ui/drawer.tsx (100%) rename registry/{ => bases/ink}/ui/email-input.tsx (100%) rename registry/{ => bases/ink}/ui/embedded-terminal.tsx (100%) rename registry/{ => bases/ink}/ui/error-boundary.tsx (100%) rename registry/{ => bases/ink}/ui/file-change.tsx (100%) rename registry/{ => bases/ink}/ui/file-picker.tsx (100%) rename registry/{ => bases/ink}/ui/form-field.tsx (100%) rename registry/{ => bases/ink}/ui/form.tsx (99%) rename registry/{ => bases/ink}/ui/gauge.tsx (100%) rename registry/{ => bases/ink}/ui/git-status.tsx (100%) rename registry/{ => bases/ink}/ui/gradient.tsx (100%) rename registry/{ => bases/ink}/ui/grid.tsx (100%) rename registry/{ => bases/ink}/ui/heading.tsx (100%) rename registry/{ => bases/ink}/ui/heat-map.tsx (100%) rename registry/{ => bases/ink}/ui/help-screen.tsx (100%) rename registry/{ => bases/ink}/ui/help.tsx (100%) rename registry/{ => bases/ink}/ui/image.tsx (100%) rename registry/{ => bases/ink}/ui/info-box.tsx (100%) rename registry/{ => bases/ink}/ui/json.tsx (100%) rename registry/{ => bases/ink}/ui/key-value.tsx (100%) rename registry/{ => bases/ink}/ui/keyboard-shortcuts.tsx (100%) rename registry/{ => bases/ink}/ui/line-chart.tsx (100%) rename registry/{ => bases/ink}/ui/link.tsx (100%) rename registry/{ => bases/ink}/ui/list.tsx (100%) rename registry/{ => bases/ink}/ui/log.tsx (100%) rename registry/{ => bases/ink}/ui/login-flow.tsx (100%) rename registry/{ => bases/ink}/ui/markdown.tsx (100%) rename registry/{ => bases/ink}/ui/masked-input.tsx (100%) rename registry/{ => bases/ink}/ui/menu.tsx (100%) rename registry/{ => bases/ink}/ui/modal.tsx (100%) rename registry/{ => bases/ink}/ui/model-selector.tsx (100%) rename registry/{ => bases/ink}/ui/multi-progress.tsx (100%) rename registry/{ => bases/ink}/ui/multi-select.tsx (100%) rename registry/{ => bases/ink}/ui/notification-badge.tsx (100%) rename registry/{ => bases/ink}/ui/notification-center.tsx (100%) rename registry/{ => bases/ink}/ui/number-input.tsx (100%) rename registry/{ => bases/ink}/ui/pagination.tsx (100%) rename registry/{ => bases/ink}/ui/panel.tsx (100%) rename registry/{ => bases/ink}/ui/password-input.tsx (100%) rename registry/{ => bases/ink}/ui/path-input.tsx (100%) rename registry/{ => bases/ink}/ui/pie-chart.tsx (100%) rename registry/{ => bases/ink}/ui/popover.tsx (100%) rename registry/{ => bases/ink}/ui/progress-bar.tsx (100%) rename registry/{ => bases/ink}/ui/progress-circle.tsx (100%) rename registry/{ => bases/ink}/ui/qr-code.tsx (100%) rename registry/{ => bases/ink}/ui/radio-group.tsx (100%) rename registry/{ => bases/ink}/ui/scroll-view.tsx (100%) rename registry/{ => bases/ink}/ui/search-input.tsx (100%) rename registry/{ => bases/ink}/ui/select.tsx (100%) rename registry/{ => bases/ink}/ui/setup-flow.tsx (100%) rename registry/{ => bases/ink}/ui/sidebar.tsx (100%) rename registry/{ => bases/ink}/ui/skeleton.tsx (100%) rename registry/{ => bases/ink}/ui/spacer.tsx (100%) rename registry/{ => bases/ink}/ui/sparkline.tsx (100%) rename registry/{ => bases/ink}/ui/spinner.tsx (100%) rename registry/{ => bases/ink}/ui/splash-screen.tsx (100%) rename registry/{ => bases/ink}/ui/stack.tsx (100%) rename registry/{ => bases/ink}/ui/status-message.tsx (100%) rename registry/{ => bases/ink}/ui/stopwatch.tsx (100%) rename registry/{ => bases/ink}/ui/streaming-text.tsx (100%) rename registry/{ => bases/ink}/ui/tabbed-content.tsx (100%) rename registry/{ => bases/ink}/ui/table.tsx (100%) rename registry/{ => bases/ink}/ui/tabs.tsx (100%) rename registry/{ => bases/ink}/ui/tag-input.tsx (100%) rename registry/{ => bases/ink}/ui/tag.tsx (100%) rename registry/{ => bases/ink}/ui/text-area.tsx (100%) rename registry/{ => bases/ink}/ui/text-input.tsx (100%) rename registry/{ => bases/ink}/ui/theme-provider.tsx (100%) rename registry/{ => bases/ink}/ui/thinking-block.tsx (100%) rename registry/{ => bases/ink}/ui/time-picker.tsx (100%) rename registry/{ => bases/ink}/ui/timer.tsx (100%) rename registry/{ => bases/ink}/ui/toast.tsx (100%) rename registry/{ => bases/ink}/ui/toggle.tsx (100%) rename registry/{ => bases/ink}/ui/token-usage.tsx (100%) rename registry/{ => bases/ink}/ui/tool-approval.tsx (100%) rename registry/{ => bases/ink}/ui/tool-call.tsx (100%) rename registry/{ => bases/ink}/ui/tooltip.tsx (100%) rename registry/{ => bases/ink}/ui/tree-select.tsx (100%) rename registry/{ => bases/ink}/ui/tree.tsx (100%) rename registry/{ => bases/ink}/ui/usage-monitor.tsx (100%) rename registry/{ => bases/ink}/ui/virtual-list.tsx (100%) rename registry/{ => bases/ink}/ui/welcome-screen.tsx (100%) rename registry/{ => bases/ink}/ui/wizard.tsx (100%) create mode 100644 registry/bases/opentui/blocks/.gitkeep create mode 100644 registry/bases/opentui/components/.gitkeep create mode 100644 registry/bases/opentui/examples/.gitkeep create mode 100644 registry/bases/opentui/hooks/.gitkeep create mode 100644 registry/bases/opentui/internal/.gitkeep create mode 100644 registry/bases/opentui/lib/.gitkeep create mode 100644 registry/bases/opentui/registry.ts create mode 100644 registry/bases/opentui/ui/spinner.tsx create mode 100644 registry/config.ts create mode 100644 registry/themes.ts create mode 100644 scripts/build-examples.mts create mode 100644 scripts/build-registry.mts create mode 100644 types/opentui-core.d.ts create mode 100644 types/opentui-react.d.ts diff --git a/app/(app)/docs/[[...slug]]/page.tsx b/app/(app)/docs/[[...slug]]/page.tsx index 46d600b..5221ea3 100644 --- a/app/(app)/docs/[[...slug]]/page.tsx +++ b/app/(app)/docs/[[...slug]]/page.tsx @@ -3,14 +3,26 @@ import { ArrowLeftIcon, ArrowRightIcon, ArrowUpRightIcon } from "lucide-react"; import Link from "next/link"; import { notFound } from "next/navigation"; +import { ComponentPreviewTabs } from "@/components/component-preview-tabs"; import { DocsCopyPage } from "@/components/docs-copy-page"; import { DocsTableOfContents } from "@/components/docs-toc"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; -import { formatTitleFromSlug } from "@/lib/docs"; +import { + DOCS_FRAMEWORKS, + formatTitleFromSlug, + getDocsFrameworkFromSlug, + getDocsRoute, + getDocsRouteSlug, + isComponentDocsSlug, + stripDocsFrameworkFromSlug, +} from "@/lib/docs"; +import { getAvailableComponentFrameworks } from "@/lib/examples"; +import type { ExampleFramework } from "@/lib/examples"; +import { PUBLIC_REGISTRY_FRAMEWORK } from "@/lib/registry"; import { getPageImage, source } from "@/lib/source"; import { absoluteUrl } from "@/lib/utils"; -import { mdxComponents } from "@/mdx-components"; +import { createMdxComponents } from "@/mdx-components"; import { BreadcrumbJsonLd } from "@/seo/json-ld"; import { createPageMetadata } from "@/seo/metadata"; @@ -18,13 +30,29 @@ export const revalidate = false; export const dynamic = "force-static"; export const dynamicParams = false; -export const generateStaticParams = () => source.generateParams(); +export const generateStaticParams = () => + source.generateParams().flatMap((params) => { + if (!isComponentDocsSlug(params.slug)) { + return [params]; + } + + const componentName = params.slug.at(-1); + const frameworks = componentName + ? getAvailableComponentFrameworks(componentName) + : [PUBLIC_REGISTRY_FRAMEWORK]; + + return frameworks.map((framework) => ({ + slug: getDocsRouteSlug(params.slug, framework), + })); + }); export const generateMetadata = async (props: { params: Promise<{ slug?: string[] }>; }) => { const params = await props.params; - const page = source.getPage(params.slug); + const framework = getDocsFrameworkFromSlug(params.slug); + const contentSlug = stripDocsFrameworkFromSlug(params.slug); + const page = source.getPage(contentSlug); if (!page) { notFound(); @@ -37,7 +65,7 @@ export const generateMetadata = async (props: { description: doc.description, ogImage, ogType: "article", - path: page.url, + path: getDocsRoute(contentSlug, framework), title: doc.title, }); }; @@ -66,20 +94,96 @@ const buildBreadcrumbs = ( return items; }; +const getDocsPageContext = (slug?: string[]) => { + const framework = getDocsFrameworkFromSlug(slug); + const contentSlug = stripDocsFrameworkFromSlug(slug); + const componentName = contentSlug?.at(-1); + const availableFrameworks = + contentSlug?.[0] === "components" && componentName + ? getAvailableComponentFrameworks(componentName) + : DOCS_FRAMEWORKS; + + return { + availableFrameworks, + canonicalSlug: getDocsRouteSlug(contentSlug, framework) ?? [], + contentSlug, + framework, + isComponentPage: isComponentDocsSlug(contentSlug), + pageUrl: getDocsRoute(contentSlug, framework), + }; +}; + +const rewriteDocsNeighbourUrl = (url: string, framework: ExampleFramework) => + (() => { + const slug = url.split("/").filter(Boolean).slice(1); + + if (!isComponentDocsSlug(slug)) { + return getDocsRoute(slug, framework); + } + + const componentName = slug.at(-1); + const targetFramework = + componentName && + getAvailableComponentFrameworks(componentName).includes(framework) + ? framework + : PUBLIC_REGISTRY_FRAMEWORK; + + return getDocsRoute(slug, targetFramework); + })(); + +const getDocsNeighbours = ( + neighbours: Awaited>, + framework: ExampleFramework, + isComponentPage: boolean +) => { + if (!isComponentPage) { + return neighbours; + } + + return { + next: neighbours.next + ? { + ...neighbours.next, + url: rewriteDocsNeighbourUrl(neighbours.next.url, framework), + } + : null, + previous: neighbours.previous + ? { + ...neighbours.previous, + url: rewriteDocsNeighbourUrl(neighbours.previous.url, framework), + } + : null, + }; +}; + const Page = async (props: { params: Promise<{ slug?: string[] }> }) => { const params = await props.params; - const page = source.getPage(params.slug); + const { + availableFrameworks, + canonicalSlug, + contentSlug, + framework, + isComponentPage, + pageUrl, + } = getDocsPageContext(params.slug); + + const page = source.getPage(contentSlug); if (!page) { notFound(); } const doc = page.data; const MdxContent = doc.body; - const neighbours = await findNeighbour(source.pageTree, page.url); + const neighbours = getDocsNeighbours( + await findNeighbour(source.pageTree, page.url), + framework, + isComponentPage + ); const raw = await page.data.getText("raw"); const { links } = doc as { links?: { doc?: string; api?: string } }; - const breadcrumbs = buildBreadcrumbs(page.slugs, doc.title, page.url); + const breadcrumbs = buildBreadcrumbs(canonicalSlug, doc.title, pageUrl); + const mdxComponents = createMdxComponents(framework); return ( <> @@ -99,7 +203,7 @@ const Page = async (props: { params: Promise<{ slug?: string[] }> }) => {
- +
{neighbours.previous && ( @@ -157,6 +261,14 @@ const Page = async (props: { params: Promise<{ slug?: string[] }> }) => { ) : null}
+ {isComponentPage ? ( + + ) : null}
diff --git a/app/icon.svg b/app/icon.svg index f927780..4a57f34 100644 --- a/app/icon.svg +++ b/app/icon.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/components/component-preview-tabs.tsx b/components/component-preview-tabs.tsx new file mode 100644 index 0000000..ccce9fe --- /dev/null +++ b/components/component-preview-tabs.tsx @@ -0,0 +1,30 @@ +import Link from "next/link"; + +import { formatTitleFromSlug, getDocsRoute } from "@/lib/docs"; +import type { ExampleFramework } from "@/lib/examples"; +import { cn } from "@/lib/utils"; + +export const ComponentPreviewTabs = ({ + className, + framework, + frameworks, + slug, +}: { + className?: string; + framework: ExampleFramework; + frameworks: readonly ExampleFramework[]; + slug: string[]; +}) => ( +
+ {frameworks.map((item) => ( + + {formatTitleFromSlug(item)} + + ))} +
+); diff --git a/components/component-preview.tsx b/components/component-preview.tsx index f9fbc46..4238d9f 100644 --- a/components/component-preview.tsx +++ b/components/component-preview.tsx @@ -1,9 +1,30 @@ +"use client"; + +import { createDynamicTerminal } from "ink-web/next"; + import { ComponentSource } from "@/components/component-source"; import { ExamplePreview } from "@/components/example-preview"; -import { TerminalPreview } from "@/components/terminal-preview"; +// import { OpenTuiPreview } from "@/components/opentui-preview"; +import type { ExampleFramework } from "@/lib/examples"; import type { terminalThemeMap } from "@/lib/terminal-themes"; +import { cn } from "@/lib/utils"; + +import type { InkPreviewProps } from "./ink-preview"; +import { MacWindow } from "./mac-window"; +import { TerminalTheme } from "./terminal-theme"; + +const InkPreview = createDynamicTerminal( + async () => { + const m = await import("./ink-preview"); + return m.default; + }, + { + loading: "spinner", + } +); export const ComponentPreview = ({ + framework = "ink", name, title, className, @@ -13,17 +34,29 @@ export const ComponentPreview = ({ name: string; title: string; className?: string; + framework?: ExampleFramework; hideCode?: boolean; theme?: keyof typeof terminalThemeMap; -}) => ( - <> - { + const preview = + framework === "opentui" ? ( + // + + ) : ( + // + + + + ); + + return ( + } > - - - {!hideCode && } - -); + {preview} + {!hideCode && } + + ); +}; diff --git a/components/component-source.tsx b/components/component-source.tsx index fcb93d3..5a4b3a1 100644 --- a/components/component-source.tsx +++ b/components/component-source.tsx @@ -2,7 +2,9 @@ import { promises as fs } from "node:fs"; import path from "node:path"; import { CodeCollapsibleWrapper } from "@/components/code-collapsible-wrapper"; +import type { ExampleFramework } from "@/lib/examples"; import { highlightCode } from "@/lib/highlight-code"; +import { getRegistryUiSourceCandidates } from "@/lib/registry"; import { cn } from "@/lib/utils"; import { CopyButton } from "./copy-button"; @@ -16,12 +18,54 @@ const readOptional = async (filePath: string): Promise => { } }; -const resolveSourceFile = async (name: string): Promise => { +const resolveSourceFile = async ({ + filePath, + framework, + name, +}: { + filePath?: string; + framework?: ExampleFramework; + name?: string; +}): Promise => { const root = process.cwd(); - const examplePath = path.join(root, "examples", `${name}.tsx`); - const registryPath = path.join(root, "registry", "ui", `${name}.tsx`); + + if (filePath) { + const resolvedPath = path.isAbsolute(filePath) + ? filePath + : path.join(root, filePath); + return readOptional(resolvedPath); + } + + if (!name) { + return null; + } + + const examplePath = framework + ? path.join(root, "examples", framework, `${name}.tsx`) + : path.join(root, "examples", "ink", `${name}.tsx`); + const alternateExamplePath = path.join(root, "examples", `${name}.tsx`); + const registryPaths = getRegistryUiSourceCandidates({ framework, name }).map( + (candidate) => path.join(root, candidate) + ); + + const registryCode = await (async () => { + for (const registryPath of registryPaths) { + const code = await readOptional(registryPath); + + if (code) { + return code; + } + } + + return null; + })(); + return ( - (await readOptional(examplePath)) ?? (await readOptional(registryPath)) + (await readOptional(examplePath)) ?? + (framework === undefined + ? await readOptional(alternateExamplePath) + : null) ?? + registryCode ); }; @@ -55,18 +99,22 @@ const ComponentCode = ({ export const ComponentSource = async ({ name, + filePath, + framework, title, collapsible = true, className, language, }: { - name: string; + name?: string; + filePath?: string; + framework?: ExampleFramework; title?: string; collapsible?: boolean; className?: string; language?: string; }) => { - const code = await resolveSourceFile(name); + const code = await resolveSourceFile({ filePath, framework, name }); if (!code) { return null; } diff --git a/components/example-preview.tsx b/components/example-preview.tsx index 6cd5a0b..4e5b04f 100644 --- a/components/example-preview.tsx +++ b/components/example-preview.tsx @@ -4,9 +4,10 @@ import { Box, Text } from "ink"; import { Component as ReactComponent, Suspense } from "react"; import { useTheme } from "@/components/ui/theme-provider"; -import { ExamplesIndex } from "@/examples/__index__"; +import { getExampleEntry } from "@/lib/examples"; +import type { ExampleFramework } from "@/lib/examples"; -const PreviewPlaceholder = ({ +const InkPreviewPlaceholder = ({ componentName, description, }: { @@ -33,13 +34,54 @@ const PreviewPlaceholder = ({ ); }; +const OpenTuiPreviewPlaceholder = ({ + componentName, + description, +}: { + componentName: string; + description: string; +}) => ( +
+
+
{componentName}
+
{description}
+
+
+); + +const PreviewPlaceholder = ({ + componentName, + description, + framework, +}: { + componentName: string; + description: string; + framework: ExampleFramework; +}) => + framework === "opentui" ? ( + + ) : ( + + ); + class PreviewErrorBoundary extends ReactComponent< - { children: React.ReactNode; componentName: string }, + { + children: React.ReactNode; + componentName: string; + framework: ExampleFramework; + }, { hasError: boolean; message?: string } > { public constructor(props: { children: React.ReactNode; componentName: string; + framework: ExampleFramework; }) { super(props); this.state = { hasError: false }; @@ -59,6 +101,7 @@ class PreviewErrorBoundary extends ReactComponent< ? `Live preview fallback: ${this.state.message}` : "Live preview fallback." } + framework={this.props.framework} /> ); } @@ -67,18 +110,34 @@ class PreviewErrorBoundary extends ReactComponent< } } -export const ExamplePreview = ({ name }: { name: string }) => { - const example = ExamplesIndex[name]; +export const ExamplePreview = ({ + framework = "ink", + name, +}: { + framework?: ExampleFramework; + name: string; +}) => { + const example = getExampleEntry(name, framework); + if (!example) { + return ( + + ); + } const ExampleComponent = example.component; return ( - + } > diff --git a/components/terminal-preview-client.tsx b/components/ink-preview.tsx similarity index 68% rename from components/terminal-preview-client.tsx rename to components/ink-preview.tsx index 1ed0b53..93e0607 100644 --- a/components/terminal-preview-client.tsx +++ b/components/ink-preview.tsx @@ -9,28 +9,28 @@ import { ThemeProvider } from "@/components/ui/theme-provider"; import { useConfig } from "@/hooks/use-config"; import { terminalThemeMap } from "@/lib/terminal-themes"; -export interface TerminalPreviewClientProps { +export interface InkPreviewProps { children: React.ReactElement; - defaultThemeKey?: keyof typeof terminalThemeMap; + theme?: keyof typeof terminalThemeMap; onReady?: () => void; rows?: number; } -const TerminalPreviewClient = ({ +const InkPreview = ({ children, - defaultThemeKey, + theme, onReady, rows = 18, -}: TerminalPreviewClientProps) => { +}: InkPreviewProps) => { const [config, setConfig] = useConfig(); const themeKey = config.terminalThemeKey; useEffect(() => { - if (defaultThemeKey === undefined) { + if (theme === undefined) { return; } - setConfig((c) => ({ ...c, terminalThemeKey: defaultThemeKey })); - }, [defaultThemeKey, setConfig]); + setConfig((c) => ({ ...c, terminalThemeKey: theme })); + }, [theme, setConfig]); return ( @@ -41,4 +41,4 @@ const TerminalPreviewClient = ({ ); }; -export default TerminalPreviewClient; +export default InkPreview; diff --git a/components/opentui-preview.tsx b/components/opentui-preview.tsx new file mode 100644 index 0000000..3f6bddb --- /dev/null +++ b/components/opentui-preview.tsx @@ -0,0 +1,122 @@ +"use client"; + +import "@xterm/xterm/css/xterm.css"; +import { Terminal } from "@xterm/xterm"; +import { useEffect, useMemo, useRef } from "react"; + +import { useConfig } from "@/hooks/use-config"; +import { terminalThemeMap } from "@/lib/terminal-themes"; + +export interface OpenTuiFramePreviewProps { + cols?: number; + frames: string[]; + interval?: number; + rows?: number; +} + +const toXtermTheme = ( + theme: (typeof terminalThemeMap)[keyof typeof terminalThemeMap] +) => ({ + background: theme.colors.background, + black: theme.colors.background, + blue: theme.colors.info, + brightBlack: theme.colors.mutedForeground, + brightBlue: theme.colors.infoForeground, + brightCyan: theme.colors.accentForeground, + brightGreen: theme.colors.successForeground, + brightMagenta: theme.colors.secondaryForeground, + brightRed: theme.colors.errorForeground, + brightWhite: theme.colors.primaryForeground, + brightYellow: theme.colors.warningForeground, + cursor: theme.colors.primary, + cursorAccent: theme.colors.background, + cyan: theme.colors.accent, + foreground: theme.colors.foreground, + green: theme.colors.success, + magenta: theme.colors.secondary, + red: theme.colors.error, + selectionBackground: theme.colors.selection, + selectionForeground: theme.colors.selectionForeground, + white: theme.colors.foreground, + yellow: theme.colors.warning, +}); + +export const OpenTuiPreview = ({ + cols = 56, + frames, + interval = 80, + rows = 18, +}: OpenTuiFramePreviewProps) => { + const [config] = useConfig(); + const containerRef = useRef(null); + const terminalRef = useRef(null); + const theme = useMemo( + () => terminalThemeMap[config.terminalThemeKey], + [config.terminalThemeKey] + ); + + useEffect(() => { + if (!containerRef.current) { + return; + } + + const terminal = new Terminal({ + allowTransparency: false, + cols, + cursorBlink: false, + cursorStyle: "block", + disableStdin: true, + fontFamily: "var(--font-geist-mono), monospace", + fontSize: 14, + lineHeight: 1.2, + rows, + theme: toXtermTheme(theme), + }); + + terminal.open(containerRef.current); + terminalRef.current = terminal; + + return () => { + terminal.dispose(); + terminalRef.current = null; + }; + }, [cols, rows, theme]); + + useEffect(() => { + const terminal = terminalRef.current; + if (!terminal || frames.length === 0) { + return; + } + + let frameIndex = 0; + + const renderFrame = (frame: string) => { + terminal.write("\u001B[2J\u001B[H"); + terminal.write(frame); + }; + + renderFrame(frames[0]); + + if (frames.length === 1) { + return; + } + + const timer = window.setInterval(() => { + frameIndex = (frameIndex + 1) % frames.length; + renderFrame(frames[frameIndex]); + }, interval); + + return () => { + window.clearInterval(timer); + }; + }, [frames, interval]); + + return ( +
+
+
+ ); +}; diff --git a/components/terminal-preview.tsx b/components/terminal-preview.tsx deleted file mode 100644 index 719e099..0000000 --- a/components/terminal-preview.tsx +++ /dev/null @@ -1,32 +0,0 @@ -"use client"; - -import { createDynamicTerminal } from "ink-web/next"; - -import { MacWindow } from "@/components/mac-window"; -import type { TerminalPreviewClientProps } from "@/components/terminal-preview-client"; -import { TerminalTheme } from "@/components/terminal-theme"; -import { cn } from "@/lib/utils"; - -const TerminalPreviewClient = createDynamicTerminal( - async () => { - const m = await import("./terminal-preview-client"); - return m.default; - }, - { - loading: "spinner", - } -); - -export const TerminalPreview = ({ - className, - title = "Terminal", - ...props -}: TerminalPreviewClientProps & { className?: string; title?: string }) => ( - } - > - - -); diff --git a/components/ui/theme-provider.tsx b/components/ui/theme-provider.tsx index cd1532b..44382cd 100644 --- a/components/ui/theme-provider.tsx +++ b/components/ui/theme-provider.tsx @@ -11,7 +11,7 @@ export { useTheme, useThemeUpdater, useUnicode, -} from "@/registry/ui/theme-provider"; +} from "@/registry/bases/ink/ui/theme-provider"; export type { AutoThemeProviderProps, @@ -23,4 +23,4 @@ export type { ThemeProviderProps, TypographyTokens, UnicodeContextValue, -} from "@/registry/ui/theme-provider"; +} from "@/registry/bases/ink/ui/theme-provider"; diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..26d0545 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,37 @@ +# Examples + +This directory contains demo components for the documentation preview system. + +## Directory Structure + +```text +examples +├── ink +│ ├── box-demo.tsx +│ └── ... +├── opentui +│ ├── box-demo.tsx +│ └── ... +├── __index__.ts # Auto-generated by scripts/build-examples.mts +├── README.md +└── theme-showcase.tsx +``` + +## Adding a New Example + +1. Add a `.tsx` file directly inside `examples/ink` or `examples/opentui`. +2. Run `pnpm registry:build` to regenerate `examples/__index__.ts`. +3. Reference the example by filename in docs: + +```mdx + +``` + +## Notes + +- `ComponentPreview` resolves the example for the active docs framework route. +- `/docs/components/ink/...` loads `examples/ink/*.tsx`. +- `/docs/components/opentui/...` loads `examples/opentui/*.tsx`. +- Keep example files directly inside the framework folder, not nested deeper. +- Both default exports and named exports are supported. +- Root-level files like `theme-showcase.tsx` are helper modules, not preview entries. diff --git a/examples/__index__.ts b/examples/__index__.ts index 4b88794..01fa4c6 100644 --- a/examples/__index__.ts +++ b/examples/__index__.ts @@ -1,570 +1,1309 @@ -import { lazy } from "react"; +// This file is autogenerated by scripts/build-examples.mts +// Do not edit this file directly. +import * as React from "react"; -export const ExamplesIndex: Record< - string, - { - component: React.LazyExoticComponent; - filePath: string; +export type ExampleFramework = "ink" | "opentui"; +type ExampleComponent = React.ComponentType; +type ExampleModule = { + default?: ExampleComponent; +} & Record; + +export interface ExampleEntry { + component: React.LazyExoticComponent; + filePath: string; + name: string; +} + +const isExampleComponent = (value: unknown): value is ExampleComponent => + typeof value === "function"; + +const MissingExampleExport: ExampleComponent = () => null; + +const resolveExampleComponent = (mod: ExampleModule): ExampleComponent => { + if (isExampleComponent(mod.default)) { + return mod.default; } + + const namedExport = Object.values(mod).find(isExampleComponent); + + return namedExport ?? MissingExampleExport; +}; + +export const ExamplesIndex: Record< + ExampleFramework, + Record > = { - "alert-custom": { - component: lazy(() => import("./alert-custom")), - filePath: "examples/alert-custom.tsx", - }, - "alert-demo": { - component: lazy(() => import("./alert-demo")), - filePath: "examples/alert-demo.tsx", - }, - "alert-error": { - component: lazy(() => import("./alert-error")), - filePath: "examples/alert-error.tsx", - }, - "alert-no-border": { - component: lazy(() => import("./alert-no-border")), - filePath: "examples/alert-no-border.tsx", - }, - "alert-warning": { - component: lazy(() => import("./alert-warning")), - filePath: "examples/alert-warning.tsx", - }, - "app-shell-demo": { - component: lazy(() => import("./app-shell-demo")), - filePath: "examples/app-shell-demo.tsx", - }, - "aspect-ratio-demo": { - component: lazy(() => import("./aspect-ratio-demo")), - filePath: "examples/aspect-ratio-demo.tsx", - }, - "badge-basic": { - component: lazy(() => import("./badge-basic")), - filePath: "examples/badge-basic.tsx", - }, - "badge-bold": { - component: lazy(() => import("./badge-bold")), - filePath: "examples/badge-bold.tsx", - }, - "badge-custom-border": { - component: lazy(() => import("./badge-custom-border")), - filePath: "examples/badge-custom-border.tsx", - }, - "badge-demo": { - component: lazy(() => import("./badge-demo")), - filePath: "examples/badge-demo.tsx", - }, - "banner-demo": { - component: lazy(() => import("./banner-demo")), - filePath: "examples/banner-demo.tsx", - }, - "banner-error": { - component: lazy(() => import("./banner-error")), - filePath: "examples/banner-error.tsx", - }, - "banner-success": { - component: lazy(() => import("./banner-success")), - filePath: "examples/banner-success.tsx", - }, - "bar-chart-demo": { - component: lazy(() => import("./bar-chart-demo")), - filePath: "examples/bar-chart-demo.tsx", - }, - "big-text-demo": { - component: lazy(() => import("./big-text-demo")), - filePath: "examples/big-text-demo.tsx", - }, - "big-text-fonts": { - component: lazy(() => import("./big-text-fonts")), - filePath: "examples/big-text-fonts.tsx", - }, - "box-demo": { - component: lazy(() => import("./box-demo")), - filePath: "examples/box-demo.tsx", - }, - "breadcrumb-demo": { - component: lazy(() => import("./breadcrumb-demo")), - filePath: "examples/breadcrumb-demo.tsx", - }, - "bullet-list-demo": { - component: lazy(() => import("./bullet-list-demo")), - filePath: "examples/bullet-list-demo.tsx", - }, - "card-demo": { - component: lazy(() => import("./card-demo")), - filePath: "examples/card-demo.tsx", - }, - "center-demo": { - component: lazy(() => import("./center-demo")), - filePath: "examples/center-demo.tsx", - }, - "chat-message-demo": { - component: lazy(() => import("./chat-message-demo")), - filePath: "examples/chat-message-demo.tsx", - }, - "chat-thread-demo": { - component: lazy(() => import("./chat-thread-demo")), - filePath: "examples/chat-thread-demo.tsx", - }, - "checkbox-demo": { - component: lazy(() => import("./checkbox-demo")), - filePath: "examples/checkbox-demo.tsx", - }, - "checkbox-group-demo": { - component: lazy(() => import("./checkbox-group-demo")), - filePath: "examples/checkbox-group-demo.tsx", - }, - "clipboard-demo": { - component: lazy(() => import("./clipboard-demo")), - filePath: "examples/clipboard-demo.tsx", - }, - "clock-demo": { - component: lazy(() => import("./clock-demo")), - filePath: "examples/clock-demo.tsx", - }, - "code-demo": { - component: lazy(() => import("./code-demo")), - filePath: "examples/code-demo.tsx", - }, - "code-multiline": { - component: lazy(() => import("./code-multiline")), - filePath: "examples/code-multiline.tsx", - }, - "color-picker-demo": { - component: lazy(() => import("./color-picker-demo")), - filePath: "examples/color-picker-demo.tsx", - }, - "columns-demo": { - component: lazy(() => import("./columns-demo")), - filePath: "examples/columns-demo.tsx", - }, - "command-palette-demo": { - component: lazy(() => import("./command-palette-demo")), - filePath: "examples/command-palette-demo.tsx", - }, - "confirm-demo": { - component: lazy(() => import("./confirm-demo")), - filePath: "examples/confirm-demo.tsx", - }, - "data-grid-demo": { - component: lazy(() => import("./data-grid-demo")), - filePath: "examples/data-grid-demo.tsx", - }, - "date-picker-demo": { - component: lazy(() => import("./date-picker-demo")), - filePath: "examples/date-picker-demo.tsx", - }, - "definition-demo": { - component: lazy(() => import("./definition-demo")), - filePath: "examples/definition-demo.tsx", - }, - "dialog-demo": { - component: lazy(() => import("./dialog-demo")), - filePath: "examples/dialog-demo.tsx", - }, - "diff-view-demo": { - component: lazy(() => import("./diff-view-demo")), - filePath: "examples/diff-view-demo.tsx", - }, - "digits-demo": { - component: lazy(() => import("./digits-demo")), - filePath: "examples/digits-demo.tsx", - }, - "directory-tree-demo": { - component: lazy(() => import("./directory-tree-demo")), - filePath: "examples/directory-tree-demo.tsx", - }, - "divider-custom": { - component: lazy(() => import("./divider-custom")), - filePath: "examples/divider-custom.tsx", - }, - "divider-demo": { - component: lazy(() => import("./divider-demo")), - filePath: "examples/divider-demo.tsx", - }, - "drawer-demo": { - component: lazy(() => import("./drawer-demo")), - filePath: "examples/drawer-demo.tsx", - }, - "email-input-demo": { - component: lazy(() => import("./email-input-demo")), - filePath: "examples/email-input-demo.tsx", - }, - "embedded-terminal-demo": { - component: lazy(() => import("./embedded-terminal-demo")), - filePath: "examples/embedded-terminal-demo.tsx", - }, - "error-boundary-demo": { - component: lazy(() => import("./error-boundary-demo")), - filePath: "examples/error-boundary-demo.tsx", - }, - "file-change-demo": { - component: lazy(() => import("./file-change-demo")), - filePath: "examples/file-change-demo.tsx", - }, - "file-picker-demo": { - component: lazy(() => import("./file-picker-demo")), - filePath: "examples/file-picker-demo.tsx", - }, - "form-demo": { - component: lazy(() => import("./form-demo")), - filePath: "examples/form-demo.tsx", - }, - "form-field-demo": { - component: lazy(() => import("./form-field-demo")), - filePath: "examples/form-field-demo.tsx", - }, - "gauge-demo": { - component: lazy(() => import("./gauge-demo")), - filePath: "examples/gauge-demo.tsx", - }, - "git-status-demo": { - component: lazy(() => import("./git-status-demo")), - filePath: "examples/git-status-demo.tsx", - }, - "gradient-demo": { - component: lazy(() => import("./gradient-demo")), - filePath: "examples/gradient-demo.tsx", - }, - "gradient-presets": { - component: lazy(() => import("./gradient-presets")), - filePath: "examples/gradient-presets.tsx", - }, - "grid-demo": { - component: lazy(() => import("./grid-demo")), - filePath: "examples/grid-demo.tsx", - }, - "heading-demo": { - component: lazy(() => import("./heading-demo")), - filePath: "examples/heading-demo.tsx", - }, - "heat-map-demo": { - component: lazy(() => import("./heat-map-demo")), - filePath: "examples/heat-map-demo.tsx", - }, - "help-demo": { - component: lazy(() => import("./help-demo")), - filePath: "examples/help-demo.tsx", - }, - "help-screen-demo": { - component: lazy(() => import("./help-screen-demo")), - filePath: "examples/help-screen-demo.tsx", - }, - "image-demo": { - component: lazy(() => import("./image-demo")), - filePath: "examples/image-demo.tsx", - }, - "info-box-demo": { - component: lazy(() => import("./info-box-demo")), - filePath: "examples/info-box-demo.tsx", - }, - "json-demo": { - component: lazy(() => import("./json-demo")), - filePath: "examples/json-demo.tsx", - }, - "key-value-demo": { - component: lazy(() => import("./key-value-demo")), - filePath: "examples/key-value-demo.tsx", - }, - "keyboard-shortcuts-demo": { - component: lazy(() => import("./keyboard-shortcuts-demo")), - filePath: "examples/keyboard-shortcuts-demo.tsx", - }, - "line-chart-demo": { - component: lazy(() => import("./line-chart-demo")), - filePath: "examples/line-chart-demo.tsx", - }, - "link-demo": { - component: lazy(() => import("./link-demo")), - filePath: "examples/link-demo.tsx", - }, - "link-show-href": { - component: lazy(() => import("./link-show-href")), - filePath: "examples/link-show-href.tsx", - }, - "list-demo": { - component: lazy(() => import("./list-demo")), - filePath: "examples/list-demo.tsx", - }, - "log-demo": { - component: lazy(() => import("./log-demo")), - filePath: "examples/log-demo.tsx", - }, - "login-flow-demo": { - component: lazy(() => import("./login-flow-demo")), - filePath: "examples/login-flow-demo.tsx", - }, - "markdown-demo": { - component: lazy(() => import("./markdown-demo")), - filePath: "examples/markdown-demo.tsx", - }, - "masked-input-demo": { - component: lazy(() => import("./masked-input-demo")), - filePath: "examples/masked-input-demo.tsx", - }, - "menu-demo": { - component: lazy(() => import("./menu-demo")), - filePath: "examples/menu-demo.tsx", - }, - "modal-demo": { - component: lazy(() => import("./modal-demo")), - filePath: "examples/modal-demo.tsx", - }, - "model-selector-demo": { - component: lazy(() => import("./model-selector-demo")), - filePath: "examples/model-selector-demo.tsx", - }, - "multi-progress-compact": { - component: lazy(() => import("./multi-progress-compact")), - filePath: "examples/multi-progress-compact.tsx", - }, - "multi-progress-demo": { - component: lazy(() => import("./multi-progress-demo")), - filePath: "examples/multi-progress-demo.tsx", - }, - "multi-select-demo": { - component: lazy(() => import("./multi-select-demo")), - filePath: "examples/multi-select-demo.tsx", - }, - "notification-center-demo": { - component: lazy(() => import("./notification-center-demo")), - filePath: "examples/notification-center-demo.tsx", - }, - "number-input-demo": { - component: lazy(() => import("./number-input-demo")), - filePath: "examples/number-input-demo.tsx", - }, - "pagination-demo": { - component: lazy(() => import("./pagination-demo")), - filePath: "examples/pagination-demo.tsx", - }, - "panel-demo": { - component: lazy(() => import("./panel-demo")), - filePath: "examples/panel-demo.tsx", - }, - "password-input-demo": { - component: lazy(() => import("./password-input-demo")), - filePath: "examples/password-input-demo.tsx", - }, - "path-input-demo": { - component: lazy(() => import("./path-input-demo")), - filePath: "examples/path-input-demo.tsx", - }, - "pie-chart-demo": { - component: lazy(() => import("./pie-chart-demo")), - filePath: "examples/pie-chart-demo.tsx", - }, - "popover-demo": { - component: lazy(() => import("./popover-demo")), - filePath: "examples/popover-demo.tsx", - }, - "progress-bar-custom": { - component: lazy(() => import("./progress-bar-custom")), - filePath: "examples/progress-bar-custom.tsx", - }, - "progress-bar-demo": { - component: lazy(() => import("./progress-bar-demo")), - filePath: "examples/progress-bar-demo.tsx", - }, - "progress-circle-demo": { - component: lazy(() => import("./progress-circle-demo")), - filePath: "examples/progress-circle-demo.tsx", - }, - "progress-circle-sizes": { - component: lazy(() => import("./progress-circle-sizes")), - filePath: "examples/progress-circle-sizes.tsx", - }, - "qr-code-demo": { - component: lazy(() => import("./qr-code-demo")), - filePath: "examples/qr-code-demo.tsx", - }, - "radio-group-demo": { - component: lazy(() => import("./radio-group-demo")), - filePath: "examples/radio-group-demo.tsx", - }, - "scroll-view-demo": { - component: lazy(() => import("./scroll-view-demo")), - filePath: "examples/scroll-view-demo.tsx", - }, - "scroll-view-scrollbar": { - component: lazy(() => import("./scroll-view-scrollbar")), - filePath: "examples/scroll-view-scrollbar.tsx", - }, - "search-input-demo": { - component: lazy(() => import("./search-input-demo")), - filePath: "examples/search-input-demo.tsx", - }, - "select-demo": { - component: lazy(() => import("./select-demo")), - filePath: "examples/select-demo.tsx", - }, - "setup-flow-demo": { - component: lazy(() => import("./setup-flow-demo")), - filePath: "examples/setup-flow-demo.tsx", - }, - "sidebar-demo": { - component: lazy(() => import("./sidebar-demo")), - filePath: "examples/sidebar-demo.tsx", - }, - "skeleton-demo": { - component: lazy(() => import("./skeleton-demo")), - filePath: "examples/skeleton-demo.tsx", - }, - "skeleton-static": { - component: lazy(() => import("./skeleton-static")), - filePath: "examples/skeleton-static.tsx", - }, - "spacer-demo": { - component: lazy(() => import("./spacer-demo")), - filePath: "examples/spacer-demo.tsx", - }, - "sparkline-demo": { - component: lazy(() => import("./sparkline-demo")), - filePath: "examples/sparkline-demo.tsx", - }, - "spinner-demo": { - component: lazy(() => import("./spinner-demo")), - filePath: "examples/spinner-demo.tsx", - }, - "spinner-label": { - component: lazy(() => import("./spinner-label")), - filePath: "examples/spinner-label.tsx", - }, - "spinner-styles": { - component: lazy(() => import("./spinner-styles")), - filePath: "examples/spinner-styles.tsx", - }, - "splash-screen-demo": { - component: lazy(() => import("./splash-screen-demo")), - filePath: "examples/splash-screen-demo.tsx", - }, - "stack-demo": { - component: lazy(() => import("./stack-demo")), - filePath: "examples/stack-demo.tsx", - }, - "status-message-demo": { - component: lazy(() => import("./status-message-demo")), - filePath: "examples/status-message-demo.tsx", - }, - "status-message-variants": { - component: lazy(() => import("./status-message-variants")), - filePath: "examples/status-message-variants.tsx", - }, - "stopwatch-demo": { - component: lazy(() => import("./stopwatch-demo")), - filePath: "examples/stopwatch-demo.tsx", - }, - "streaming-text-demo": { - component: lazy(() => import("./streaming-text-demo")), - filePath: "examples/streaming-text-demo.tsx", - }, - "tabbed-content-demo": { - component: lazy(() => import("./tabbed-content-demo")), - filePath: "examples/tabbed-content-demo.tsx", - }, - "table-demo": { - component: lazy(() => import("./table-demo")), - filePath: "examples/table-demo.tsx", - }, - "table-selectable": { - component: lazy(() => import("./table-selectable")), - filePath: "examples/table-selectable.tsx", - }, - "table-sortable": { - component: lazy(() => import("./table-sortable")), - filePath: "examples/table-sortable.tsx", - }, - "tabs-demo": { - component: lazy(() => import("./tabs-demo")), - filePath: "examples/tabs-demo.tsx", - }, - "tag-demo": { - component: lazy(() => import("./tag-demo")), - filePath: "examples/tag-demo.tsx", - }, - "tag-input-demo": { - component: lazy(() => import("./tag-input-demo")), - filePath: "examples/tag-input-demo.tsx", - }, - "text-area-demo": { - component: lazy(() => import("./text-area-demo")), - filePath: "examples/text-area-demo.tsx", - }, - "text-input-cursor": { - component: lazy(() => import("./text-input-cursor")), - filePath: "examples/text-input-cursor.tsx", - }, - "text-input-demo": { - component: lazy(() => import("./text-input-demo")), - filePath: "examples/text-input-demo.tsx", - }, - "text-input-label": { - component: lazy(() => import("./text-input-label")), - filePath: "examples/text-input-label.tsx", - }, - "text-input-placeholder": { - component: lazy(() => import("./text-input-placeholder")), - filePath: "examples/text-input-placeholder.tsx", - }, - "thinking-block-demo": { - component: lazy(() => import("./thinking-block-demo")), - filePath: "examples/thinking-block-demo.tsx", - }, - "time-picker-demo": { - component: lazy(() => import("./time-picker-demo")), - filePath: "examples/time-picker-demo.tsx", - }, - "timer-demo": { - component: lazy(() => import("./timer-demo")), - filePath: "examples/timer-demo.tsx", - }, - "toast-demo": { - component: lazy(() => import("./toast-demo")), - filePath: "examples/toast-demo.tsx", - }, - "toast-error": { - component: lazy(() => import("./toast-error")), - filePath: "examples/toast-error.tsx", - }, - "toggle-demo": { - component: lazy(() => import("./toggle-demo")), - filePath: "examples/toggle-demo.tsx", - }, - "token-usage-demo": { - component: lazy(() => import("./token-usage-demo")), - filePath: "examples/token-usage-demo.tsx", - }, - "tool-approval-demo": { - component: lazy(() => import("./tool-approval-demo")), - filePath: "examples/tool-approval-demo.tsx", - }, - "tool-call-demo": { - component: lazy(() => import("./tool-call-demo")), - filePath: "examples/tool-call-demo.tsx", - }, - "tooltip-demo": { - component: lazy(() => import("./tooltip-demo")), - filePath: "examples/tooltip-demo.tsx", - }, - "tree-demo": { - component: lazy(() => import("./tree-demo")), - filePath: "examples/tree-demo.tsx", - }, - "tree-select-demo": { - component: lazy(() => import("./tree-select-demo")), - filePath: "examples/tree-select-demo.tsx", - }, - "usage-monitor-demo": { - component: lazy(() => import("./usage-monitor-demo")), - filePath: "examples/usage-monitor-demo.tsx", - }, - "virtual-list-demo": { - component: lazy(() => import("./virtual-list-demo")), - filePath: "examples/virtual-list-demo.tsx", - }, - "welcome-screen-demo": { - component: lazy(() => import("./welcome-screen-demo")), - filePath: "examples/welcome-screen-demo.tsx", - }, - "wizard-demo": { - component: lazy(() => import("./wizard-demo")), - filePath: "examples/wizard-demo.tsx", + ink: { + "alert-custom": { + component: React.lazy(async () => { + const mod = await import("./ink/alert-custom"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/alert-custom.tsx", + name: "alert-custom", + }, + "alert-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/alert-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/alert-demo.tsx", + name: "alert-demo", + }, + "alert-error": { + component: React.lazy(async () => { + const mod = await import("./ink/alert-error"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/alert-error.tsx", + name: "alert-error", + }, + "alert-no-border": { + component: React.lazy(async () => { + const mod = await import("./ink/alert-no-border"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/alert-no-border.tsx", + name: "alert-no-border", + }, + "alert-warning": { + component: React.lazy(async () => { + const mod = await import("./ink/alert-warning"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/alert-warning.tsx", + name: "alert-warning", + }, + "app-shell-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/app-shell-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/app-shell-demo.tsx", + name: "app-shell-demo", + }, + "aspect-ratio-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/aspect-ratio-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/aspect-ratio-demo.tsx", + name: "aspect-ratio-demo", + }, + "badge-basic": { + component: React.lazy(async () => { + const mod = await import("./ink/badge-basic"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/badge-basic.tsx", + name: "badge-basic", + }, + "badge-bold": { + component: React.lazy(async () => { + const mod = await import("./ink/badge-bold"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/badge-bold.tsx", + name: "badge-bold", + }, + "badge-custom-border": { + component: React.lazy(async () => { + const mod = await import("./ink/badge-custom-border"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/badge-custom-border.tsx", + name: "badge-custom-border", + }, + "badge-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/badge-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/badge-demo.tsx", + name: "badge-demo", + }, + "banner-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/banner-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/banner-demo.tsx", + name: "banner-demo", + }, + "banner-error": { + component: React.lazy(async () => { + const mod = await import("./ink/banner-error"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/banner-error.tsx", + name: "banner-error", + }, + "banner-success": { + component: React.lazy(async () => { + const mod = await import("./ink/banner-success"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/banner-success.tsx", + name: "banner-success", + }, + "bar-chart-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/bar-chart-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/bar-chart-demo.tsx", + name: "bar-chart-demo", + }, + "big-text-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/big-text-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/big-text-demo.tsx", + name: "big-text-demo", + }, + "big-text-fonts": { + component: React.lazy(async () => { + const mod = await import("./ink/big-text-fonts"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/big-text-fonts.tsx", + name: "big-text-fonts", + }, + "box-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/box-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/box-demo.tsx", + name: "box-demo", + }, + "breadcrumb-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/breadcrumb-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/breadcrumb-demo.tsx", + name: "breadcrumb-demo", + }, + "bullet-list-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/bullet-list-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/bullet-list-demo.tsx", + name: "bullet-list-demo", + }, + "card-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/card-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/card-demo.tsx", + name: "card-demo", + }, + "center-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/center-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/center-demo.tsx", + name: "center-demo", + }, + "chat-message-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/chat-message-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/chat-message-demo.tsx", + name: "chat-message-demo", + }, + "chat-thread-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/chat-thread-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/chat-thread-demo.tsx", + name: "chat-thread-demo", + }, + "checkbox-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/checkbox-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/checkbox-demo.tsx", + name: "checkbox-demo", + }, + "checkbox-group-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/checkbox-group-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/checkbox-group-demo.tsx", + name: "checkbox-group-demo", + }, + "clipboard-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/clipboard-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/clipboard-demo.tsx", + name: "clipboard-demo", + }, + "clock-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/clock-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/clock-demo.tsx", + name: "clock-demo", + }, + "code-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/code-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/code-demo.tsx", + name: "code-demo", + }, + "code-multiline": { + component: React.lazy(async () => { + const mod = await import("./ink/code-multiline"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/code-multiline.tsx", + name: "code-multiline", + }, + "color-picker-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/color-picker-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/color-picker-demo.tsx", + name: "color-picker-demo", + }, + "columns-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/columns-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/columns-demo.tsx", + name: "columns-demo", + }, + "command-palette-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/command-palette-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/command-palette-demo.tsx", + name: "command-palette-demo", + }, + "confirm-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/confirm-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/confirm-demo.tsx", + name: "confirm-demo", + }, + "data-grid-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/data-grid-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/data-grid-demo.tsx", + name: "data-grid-demo", + }, + "date-picker-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/date-picker-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/date-picker-demo.tsx", + name: "date-picker-demo", + }, + "definition-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/definition-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/definition-demo.tsx", + name: "definition-demo", + }, + "dialog-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/dialog-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/dialog-demo.tsx", + name: "dialog-demo", + }, + "diff-view-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/diff-view-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/diff-view-demo.tsx", + name: "diff-view-demo", + }, + "digits-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/digits-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/digits-demo.tsx", + name: "digits-demo", + }, + "directory-tree-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/directory-tree-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/directory-tree-demo.tsx", + name: "directory-tree-demo", + }, + "divider-custom": { + component: React.lazy(async () => { + const mod = await import("./ink/divider-custom"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/divider-custom.tsx", + name: "divider-custom", + }, + "divider-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/divider-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/divider-demo.tsx", + name: "divider-demo", + }, + "drawer-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/drawer-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/drawer-demo.tsx", + name: "drawer-demo", + }, + "email-input-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/email-input-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/email-input-demo.tsx", + name: "email-input-demo", + }, + "embedded-terminal-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/embedded-terminal-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/embedded-terminal-demo.tsx", + name: "embedded-terminal-demo", + }, + "error-boundary-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/error-boundary-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/error-boundary-demo.tsx", + name: "error-boundary-demo", + }, + "file-change-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/file-change-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/file-change-demo.tsx", + name: "file-change-demo", + }, + "file-picker-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/file-picker-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/file-picker-demo.tsx", + name: "file-picker-demo", + }, + "form-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/form-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/form-demo.tsx", + name: "form-demo", + }, + "form-field-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/form-field-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/form-field-demo.tsx", + name: "form-field-demo", + }, + "gauge-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/gauge-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/gauge-demo.tsx", + name: "gauge-demo", + }, + "git-status-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/git-status-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/git-status-demo.tsx", + name: "git-status-demo", + }, + "gradient-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/gradient-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/gradient-demo.tsx", + name: "gradient-demo", + }, + "gradient-presets": { + component: React.lazy(async () => { + const mod = await import("./ink/gradient-presets"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/gradient-presets.tsx", + name: "gradient-presets", + }, + "grid-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/grid-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/grid-demo.tsx", + name: "grid-demo", + }, + "heading-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/heading-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/heading-demo.tsx", + name: "heading-demo", + }, + "heat-map-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/heat-map-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/heat-map-demo.tsx", + name: "heat-map-demo", + }, + "help-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/help-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/help-demo.tsx", + name: "help-demo", + }, + "help-screen-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/help-screen-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/help-screen-demo.tsx", + name: "help-screen-demo", + }, + "image-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/image-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/image-demo.tsx", + name: "image-demo", + }, + "info-box-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/info-box-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/info-box-demo.tsx", + name: "info-box-demo", + }, + "json-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/json-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/json-demo.tsx", + name: "json-demo", + }, + "key-value-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/key-value-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/key-value-demo.tsx", + name: "key-value-demo", + }, + "keyboard-shortcuts-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/keyboard-shortcuts-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/keyboard-shortcuts-demo.tsx", + name: "keyboard-shortcuts-demo", + }, + "line-chart-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/line-chart-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/line-chart-demo.tsx", + name: "line-chart-demo", + }, + "link-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/link-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/link-demo.tsx", + name: "link-demo", + }, + "link-show-href": { + component: React.lazy(async () => { + const mod = await import("./ink/link-show-href"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/link-show-href.tsx", + name: "link-show-href", + }, + "list-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/list-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/list-demo.tsx", + name: "list-demo", + }, + "log-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/log-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/log-demo.tsx", + name: "log-demo", + }, + "login-flow-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/login-flow-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/login-flow-demo.tsx", + name: "login-flow-demo", + }, + "markdown-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/markdown-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/markdown-demo.tsx", + name: "markdown-demo", + }, + "masked-input-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/masked-input-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/masked-input-demo.tsx", + name: "masked-input-demo", + }, + "menu-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/menu-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/menu-demo.tsx", + name: "menu-demo", + }, + "modal-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/modal-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/modal-demo.tsx", + name: "modal-demo", + }, + "model-selector-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/model-selector-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/model-selector-demo.tsx", + name: "model-selector-demo", + }, + "multi-progress-compact": { + component: React.lazy(async () => { + const mod = await import("./ink/multi-progress-compact"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/multi-progress-compact.tsx", + name: "multi-progress-compact", + }, + "multi-progress-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/multi-progress-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/multi-progress-demo.tsx", + name: "multi-progress-demo", + }, + "multi-select-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/multi-select-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/multi-select-demo.tsx", + name: "multi-select-demo", + }, + "notification-center-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/notification-center-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/notification-center-demo.tsx", + name: "notification-center-demo", + }, + "number-input-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/number-input-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/number-input-demo.tsx", + name: "number-input-demo", + }, + "pagination-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/pagination-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/pagination-demo.tsx", + name: "pagination-demo", + }, + "panel-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/panel-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/panel-demo.tsx", + name: "panel-demo", + }, + "password-input-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/password-input-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/password-input-demo.tsx", + name: "password-input-demo", + }, + "path-input-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/path-input-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/path-input-demo.tsx", + name: "path-input-demo", + }, + "pie-chart-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/pie-chart-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/pie-chart-demo.tsx", + name: "pie-chart-demo", + }, + "popover-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/popover-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/popover-demo.tsx", + name: "popover-demo", + }, + "progress-bar-custom": { + component: React.lazy(async () => { + const mod = await import("./ink/progress-bar-custom"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/progress-bar-custom.tsx", + name: "progress-bar-custom", + }, + "progress-bar-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/progress-bar-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/progress-bar-demo.tsx", + name: "progress-bar-demo", + }, + "progress-circle-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/progress-circle-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/progress-circle-demo.tsx", + name: "progress-circle-demo", + }, + "progress-circle-sizes": { + component: React.lazy(async () => { + const mod = await import("./ink/progress-circle-sizes"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/progress-circle-sizes.tsx", + name: "progress-circle-sizes", + }, + "qr-code-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/qr-code-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/qr-code-demo.tsx", + name: "qr-code-demo", + }, + "radio-group-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/radio-group-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/radio-group-demo.tsx", + name: "radio-group-demo", + }, + "scroll-view-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/scroll-view-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/scroll-view-demo.tsx", + name: "scroll-view-demo", + }, + "scroll-view-scrollbar": { + component: React.lazy(async () => { + const mod = await import("./ink/scroll-view-scrollbar"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/scroll-view-scrollbar.tsx", + name: "scroll-view-scrollbar", + }, + "search-input-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/search-input-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/search-input-demo.tsx", + name: "search-input-demo", + }, + "select-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/select-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/select-demo.tsx", + name: "select-demo", + }, + "setup-flow-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/setup-flow-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/setup-flow-demo.tsx", + name: "setup-flow-demo", + }, + "sidebar-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/sidebar-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/sidebar-demo.tsx", + name: "sidebar-demo", + }, + "skeleton-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/skeleton-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/skeleton-demo.tsx", + name: "skeleton-demo", + }, + "skeleton-static": { + component: React.lazy(async () => { + const mod = await import("./ink/skeleton-static"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/skeleton-static.tsx", + name: "skeleton-static", + }, + "spacer-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/spacer-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/spacer-demo.tsx", + name: "spacer-demo", + }, + "sparkline-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/sparkline-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/sparkline-demo.tsx", + name: "sparkline-demo", + }, + "spinner-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/spinner-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/spinner-demo.tsx", + name: "spinner-demo", + }, + "spinner-label": { + component: React.lazy(async () => { + const mod = await import("./ink/spinner-label"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/spinner-label.tsx", + name: "spinner-label", + }, + "spinner-styles": { + component: React.lazy(async () => { + const mod = await import("./ink/spinner-styles"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/spinner-styles.tsx", + name: "spinner-styles", + }, + "splash-screen-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/splash-screen-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/splash-screen-demo.tsx", + name: "splash-screen-demo", + }, + "stack-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/stack-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/stack-demo.tsx", + name: "stack-demo", + }, + "status-message-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/status-message-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/status-message-demo.tsx", + name: "status-message-demo", + }, + "status-message-variants": { + component: React.lazy(async () => { + const mod = await import("./ink/status-message-variants"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/status-message-variants.tsx", + name: "status-message-variants", + }, + "stopwatch-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/stopwatch-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/stopwatch-demo.tsx", + name: "stopwatch-demo", + }, + "streaming-text-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/streaming-text-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/streaming-text-demo.tsx", + name: "streaming-text-demo", + }, + "tabbed-content-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/tabbed-content-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/tabbed-content-demo.tsx", + name: "tabbed-content-demo", + }, + "table-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/table-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/table-demo.tsx", + name: "table-demo", + }, + "table-selectable": { + component: React.lazy(async () => { + const mod = await import("./ink/table-selectable"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/table-selectable.tsx", + name: "table-selectable", + }, + "table-sortable": { + component: React.lazy(async () => { + const mod = await import("./ink/table-sortable"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/table-sortable.tsx", + name: "table-sortable", + }, + "tabs-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/tabs-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/tabs-demo.tsx", + name: "tabs-demo", + }, + "tag-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/tag-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/tag-demo.tsx", + name: "tag-demo", + }, + "tag-input-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/tag-input-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/tag-input-demo.tsx", + name: "tag-input-demo", + }, + "text-area-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/text-area-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/text-area-demo.tsx", + name: "text-area-demo", + }, + "text-input-cursor": { + component: React.lazy(async () => { + const mod = await import("./ink/text-input-cursor"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/text-input-cursor.tsx", + name: "text-input-cursor", + }, + "text-input-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/text-input-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/text-input-demo.tsx", + name: "text-input-demo", + }, + "text-input-label": { + component: React.lazy(async () => { + const mod = await import("./ink/text-input-label"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/text-input-label.tsx", + name: "text-input-label", + }, + "text-input-placeholder": { + component: React.lazy(async () => { + const mod = await import("./ink/text-input-placeholder"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/text-input-placeholder.tsx", + name: "text-input-placeholder", + }, + "thinking-block-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/thinking-block-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/thinking-block-demo.tsx", + name: "thinking-block-demo", + }, + "time-picker-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/time-picker-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/time-picker-demo.tsx", + name: "time-picker-demo", + }, + "timer-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/timer-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/timer-demo.tsx", + name: "timer-demo", + }, + "toast-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/toast-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/toast-demo.tsx", + name: "toast-demo", + }, + "toast-error": { + component: React.lazy(async () => { + const mod = await import("./ink/toast-error"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/toast-error.tsx", + name: "toast-error", + }, + "toggle-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/toggle-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/toggle-demo.tsx", + name: "toggle-demo", + }, + "token-usage-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/token-usage-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/token-usage-demo.tsx", + name: "token-usage-demo", + }, + "tool-approval-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/tool-approval-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/tool-approval-demo.tsx", + name: "tool-approval-demo", + }, + "tool-call-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/tool-call-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/tool-call-demo.tsx", + name: "tool-call-demo", + }, + "tooltip-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/tooltip-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/tooltip-demo.tsx", + name: "tooltip-demo", + }, + "tree-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/tree-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/tree-demo.tsx", + name: "tree-demo", + }, + "tree-select-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/tree-select-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/tree-select-demo.tsx", + name: "tree-select-demo", + }, + "usage-monitor-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/usage-monitor-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/usage-monitor-demo.tsx", + name: "usage-monitor-demo", + }, + "virtual-list-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/virtual-list-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/virtual-list-demo.tsx", + name: "virtual-list-demo", + }, + "welcome-screen-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/welcome-screen-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/welcome-screen-demo.tsx", + name: "welcome-screen-demo", + }, + "wizard-demo": { + component: React.lazy(async () => { + const mod = await import("./ink/wizard-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/ink/wizard-demo.tsx", + name: "wizard-demo", + }, + }, + opentui: { + "spinner-demo": { + component: React.lazy(async () => { + const mod = await import("./opentui/spinner-demo"); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: "examples/opentui/spinner-demo.tsx", + name: "spinner-demo", + }, }, }; diff --git a/examples/alert-custom.tsx b/examples/ink/alert-custom.tsx similarity index 77% rename from examples/alert-custom.tsx rename to examples/ink/alert-custom.tsx index a4c5bd9..2911b74 100644 --- a/examples/alert-custom.tsx +++ b/examples/ink/alert-custom.tsx @@ -1,4 +1,4 @@ -import { Alert } from "@/registry/ui/alert"; +import { Alert } from "@/registry/bases/ink/ui/alert"; export default function AlertCustom() { return ( diff --git a/examples/alert-demo.tsx b/examples/ink/alert-demo.tsx similarity index 87% rename from examples/alert-demo.tsx rename to examples/ink/alert-demo.tsx index 3c5f0bf..ec0b4d3 100644 --- a/examples/alert-demo.tsx +++ b/examples/ink/alert-demo.tsx @@ -1,6 +1,6 @@ import { Box } from "ink"; -import { Alert } from "@/registry/ui/alert"; +import { Alert } from "@/registry/bases/ink/ui/alert"; export default function AlertDemo() { return ( diff --git a/examples/alert-error.tsx b/examples/ink/alert-error.tsx similarity index 75% rename from examples/alert-error.tsx rename to examples/ink/alert-error.tsx index d649299..d605419 100644 --- a/examples/alert-error.tsx +++ b/examples/ink/alert-error.tsx @@ -1,4 +1,4 @@ -import { Alert } from "@/registry/ui/alert"; +import { Alert } from "@/registry/bases/ink/ui/alert"; export default function AlertError() { return ( diff --git a/examples/alert-no-border.tsx b/examples/ink/alert-no-border.tsx similarity index 76% rename from examples/alert-no-border.tsx rename to examples/ink/alert-no-border.tsx index 005245a..029ae7f 100644 --- a/examples/alert-no-border.tsx +++ b/examples/ink/alert-no-border.tsx @@ -1,4 +1,4 @@ -import { Alert } from "@/registry/ui/alert"; +import { Alert } from "@/registry/bases/ink/ui/alert"; export default function AlertNoBorder() { return ( diff --git a/examples/alert-warning.tsx b/examples/ink/alert-warning.tsx similarity index 75% rename from examples/alert-warning.tsx rename to examples/ink/alert-warning.tsx index 031f10c..312e5bf 100644 --- a/examples/alert-warning.tsx +++ b/examples/ink/alert-warning.tsx @@ -1,4 +1,4 @@ -import { Alert } from "@/registry/ui/alert"; +import { Alert } from "@/registry/bases/ink/ui/alert"; export default function AlertWarning() { return ( diff --git a/examples/app-shell-demo.tsx b/examples/ink/app-shell-demo.tsx similarity index 90% rename from examples/app-shell-demo.tsx rename to examples/ink/app-shell-demo.tsx index 566020c..6d9e219 100644 --- a/examples/app-shell-demo.tsx +++ b/examples/ink/app-shell-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { AppShell } from "@/registry/ui/app-shell"; +import { AppShell } from "@/registry/bases/ink/ui/app-shell"; export default function AppShellDemo() { return ( diff --git a/examples/aspect-ratio-demo.tsx b/examples/ink/aspect-ratio-demo.tsx similarity index 73% rename from examples/aspect-ratio-demo.tsx rename to examples/ink/aspect-ratio-demo.tsx index f9c2a35..2b1b820 100644 --- a/examples/aspect-ratio-demo.tsx +++ b/examples/ink/aspect-ratio-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { AspectRatio } from "@/registry/ui/aspect-ratio"; +import { AspectRatio } from "@/registry/bases/ink/ui/aspect-ratio"; export default function AspectRatioDemo() { return ( diff --git a/examples/badge-basic.tsx b/examples/ink/badge-basic.tsx similarity index 57% rename from examples/badge-basic.tsx rename to examples/ink/badge-basic.tsx index 35983da..227aa05 100644 --- a/examples/badge-basic.tsx +++ b/examples/ink/badge-basic.tsx @@ -1,4 +1,4 @@ -import { Badge } from "@/registry/ui/badge"; +import { Badge } from "@/registry/bases/ink/ui/badge"; export default function BadgeBasic() { return Default; diff --git a/examples/badge-bold.tsx b/examples/ink/badge-bold.tsx similarity index 69% rename from examples/badge-bold.tsx rename to examples/ink/badge-bold.tsx index 2f10b69..7e7545a 100644 --- a/examples/badge-bold.tsx +++ b/examples/ink/badge-bold.tsx @@ -1,4 +1,4 @@ -import { Badge } from "@/registry/ui/badge"; +import { Badge } from "@/registry/bases/ink/ui/badge"; export default function BadgeBold() { return ( diff --git a/examples/badge-custom-border.tsx b/examples/ink/badge-custom-border.tsx similarity index 73% rename from examples/badge-custom-border.tsx rename to examples/ink/badge-custom-border.tsx index aac746c..61507e7 100644 --- a/examples/badge-custom-border.tsx +++ b/examples/ink/badge-custom-border.tsx @@ -1,4 +1,4 @@ -import { Badge } from "@/registry/ui/badge"; +import { Badge } from "@/registry/bases/ink/ui/badge"; export default function BadgeCustomBorder() { return ( diff --git a/examples/badge-demo.tsx b/examples/ink/badge-demo.tsx similarity index 84% rename from examples/badge-demo.tsx rename to examples/ink/badge-demo.tsx index fb11021..2ac1332 100644 --- a/examples/badge-demo.tsx +++ b/examples/ink/badge-demo.tsx @@ -1,6 +1,6 @@ import { Box } from "ink"; -import { Badge } from "@/registry/ui/badge"; +import { Badge } from "@/registry/bases/ink/ui/badge"; export default function BadgeDemo() { return ( diff --git a/examples/banner-demo.tsx b/examples/ink/banner-demo.tsx similarity index 67% rename from examples/banner-demo.tsx rename to examples/ink/banner-demo.tsx index f1a4027..3622ccd 100644 --- a/examples/banner-demo.tsx +++ b/examples/ink/banner-demo.tsx @@ -1,4 +1,4 @@ -import { Banner } from "@/registry/ui/banner"; +import { Banner } from "@/registry/bases/ink/ui/banner"; export default function BannerDemo() { return Deployment completed successfully.; diff --git a/examples/banner-error.tsx b/examples/ink/banner-error.tsx similarity index 74% rename from examples/banner-error.tsx rename to examples/ink/banner-error.tsx index bbec7eb..523eb36 100644 --- a/examples/banner-error.tsx +++ b/examples/ink/banner-error.tsx @@ -1,4 +1,4 @@ -import { Banner } from "@/registry/ui/banner"; +import { Banner } from "@/registry/bases/ink/ui/banner"; export default function BannerError() { return ( diff --git a/examples/banner-success.tsx b/examples/ink/banner-success.tsx similarity index 72% rename from examples/banner-success.tsx rename to examples/ink/banner-success.tsx index f672262..3854e9c 100644 --- a/examples/banner-success.tsx +++ b/examples/ink/banner-success.tsx @@ -1,4 +1,4 @@ -import { Banner } from "@/registry/ui/banner"; +import { Banner } from "@/registry/bases/ink/ui/banner"; export default function BannerSuccess() { return ( diff --git a/examples/bar-chart-demo.tsx b/examples/ink/bar-chart-demo.tsx similarity index 81% rename from examples/bar-chart-demo.tsx rename to examples/ink/bar-chart-demo.tsx index 6f7720d..4e2589a 100644 --- a/examples/bar-chart-demo.tsx +++ b/examples/ink/bar-chart-demo.tsx @@ -1,4 +1,4 @@ -import { BarChart } from "@/registry/ui/bar-chart"; +import { BarChart } from "@/registry/bases/ink/ui/bar-chart"; const sampleData = [ { label: "Mon", value: 12 }, diff --git a/examples/big-text-demo.tsx b/examples/ink/big-text-demo.tsx similarity index 56% rename from examples/big-text-demo.tsx rename to examples/ink/big-text-demo.tsx index 4a6f519..7aa627c 100644 --- a/examples/big-text-demo.tsx +++ b/examples/ink/big-text-demo.tsx @@ -1,4 +1,4 @@ -import { BigText } from "@/registry/ui/big-text"; +import { BigText } from "@/registry/bases/ink/ui/big-text"; export default function BigTextDemo() { return termcn; diff --git a/examples/big-text-fonts.tsx b/examples/ink/big-text-fonts.tsx similarity index 81% rename from examples/big-text-fonts.tsx rename to examples/ink/big-text-fonts.tsx index e6db419..373c97c 100644 --- a/examples/big-text-fonts.tsx +++ b/examples/ink/big-text-fonts.tsx @@ -1,6 +1,6 @@ import { Box } from "ink"; -import { BigText } from "@/registry/ui/big-text"; +import { BigText } from "@/registry/bases/ink/ui/big-text"; export default function BigTextFonts() { return ( diff --git a/examples/box-demo.tsx b/examples/ink/box-demo.tsx similarity index 78% rename from examples/box-demo.tsx rename to examples/ink/box-demo.tsx index bed9633..64e3aa5 100644 --- a/examples/box-demo.tsx +++ b/examples/ink/box-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { Box } from "@/registry/ui/box"; +import { Box } from "@/registry/bases/ink/ui/box"; export default function BoxDemo() { return ( diff --git a/examples/breadcrumb-demo.tsx b/examples/ink/breadcrumb-demo.tsx similarity index 81% rename from examples/breadcrumb-demo.tsx rename to examples/ink/breadcrumb-demo.tsx index 7599924..b53b1f2 100644 --- a/examples/breadcrumb-demo.tsx +++ b/examples/ink/breadcrumb-demo.tsx @@ -1,4 +1,4 @@ -import { Breadcrumb } from "@/registry/ui/breadcrumb"; +import { Breadcrumb } from "@/registry/bases/ink/ui/breadcrumb"; export default function BreadcrumbDemo() { return ( diff --git a/examples/bullet-list-demo.tsx b/examples/ink/bullet-list-demo.tsx similarity index 88% rename from examples/bullet-list-demo.tsx rename to examples/ink/bullet-list-demo.tsx index aa72cad..de5c273 100644 --- a/examples/bullet-list-demo.tsx +++ b/examples/ink/bullet-list-demo.tsx @@ -1,4 +1,4 @@ -import { BulletList } from "@/registry/ui/bullet-list"; +import { BulletList } from "@/registry/bases/ink/ui/bullet-list"; export default function BulletListDemo() { return ( diff --git a/examples/card-demo.tsx b/examples/ink/card-demo.tsx similarity index 81% rename from examples/card-demo.tsx rename to examples/ink/card-demo.tsx index d073c98..064a06e 100644 --- a/examples/card-demo.tsx +++ b/examples/ink/card-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { Card } from "@/registry/ui/card"; +import { Card } from "@/registry/bases/ink/ui/card"; export default function CardDemo() { return ( diff --git a/examples/center-demo.tsx b/examples/ink/center-demo.tsx similarity index 72% rename from examples/center-demo.tsx rename to examples/ink/center-demo.tsx index b410a46..440acf8 100644 --- a/examples/center-demo.tsx +++ b/examples/ink/center-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { Center } from "@/registry/ui/center"; +import { Center } from "@/registry/bases/ink/ui/center"; export default function CenterDemo() { return ( diff --git a/examples/chat-message-demo.tsx b/examples/ink/chat-message-demo.tsx similarity index 78% rename from examples/chat-message-demo.tsx rename to examples/ink/chat-message-demo.tsx index 7977537..69106ab 100644 --- a/examples/chat-message-demo.tsx +++ b/examples/ink/chat-message-demo.tsx @@ -1,4 +1,4 @@ -import { ChatMessage } from "@/registry/ui/chat-message"; +import { ChatMessage } from "@/registry/bases/ink/ui/chat-message"; export default function ChatMessageDemo() { return ( diff --git a/examples/chat-thread-demo.tsx b/examples/ink/chat-thread-demo.tsx similarity index 78% rename from examples/chat-thread-demo.tsx rename to examples/ink/chat-thread-demo.tsx index c307144..71be804 100644 --- a/examples/chat-thread-demo.tsx +++ b/examples/ink/chat-thread-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { ChatThread } from "@/registry/ui/chat-thread"; +import { ChatThread } from "@/registry/bases/ink/ui/chat-thread"; export default function ChatThreadDemo() { return ( diff --git a/examples/checkbox-demo.tsx b/examples/ink/checkbox-demo.tsx similarity index 82% rename from examples/checkbox-demo.tsx rename to examples/ink/checkbox-demo.tsx index dd5d852..eee1d5e 100644 --- a/examples/checkbox-demo.tsx +++ b/examples/ink/checkbox-demo.tsx @@ -1,6 +1,6 @@ import { Box } from "ink"; -import { Checkbox } from "@/registry/ui/checkbox"; +import { Checkbox } from "@/registry/bases/ink/ui/checkbox"; export default function CheckboxDemo() { return ( diff --git a/examples/checkbox-group-demo.tsx b/examples/ink/checkbox-group-demo.tsx similarity index 80% rename from examples/checkbox-group-demo.tsx rename to examples/ink/checkbox-group-demo.tsx index d8b42d5..2d0868d 100644 --- a/examples/checkbox-group-demo.tsx +++ b/examples/ink/checkbox-group-demo.tsx @@ -1,4 +1,4 @@ -import { CheckboxGroup } from "@/registry/ui/checkbox-group"; +import { CheckboxGroup } from "@/registry/bases/ink/ui/checkbox-group"; export default function CheckboxGroupDemo() { return ( diff --git a/examples/clipboard-demo.tsx b/examples/ink/clipboard-demo.tsx similarity index 74% rename from examples/clipboard-demo.tsx rename to examples/ink/clipboard-demo.tsx index 978a414..2cc6cc2 100644 --- a/examples/clipboard-demo.tsx +++ b/examples/ink/clipboard-demo.tsx @@ -1,5 +1,5 @@ import { SITE } from "@/constants/site"; -import { Clipboard } from "@/registry/ui/clipboard"; +import { Clipboard } from "@/registry/bases/ink/ui/clipboard"; export default function ClipboardDemo() { return ( diff --git a/examples/clock-demo.tsx b/examples/ink/clock-demo.tsx similarity index 52% rename from examples/clock-demo.tsx rename to examples/ink/clock-demo.tsx index 73673e1..d8543c2 100644 --- a/examples/clock-demo.tsx +++ b/examples/ink/clock-demo.tsx @@ -1,4 +1,4 @@ -import { Clock } from "@/registry/ui/clock"; +import { Clock } from "@/registry/bases/ink/ui/clock"; export default function ClockDemo() { return ; diff --git a/examples/code-demo.tsx b/examples/ink/code-demo.tsx similarity index 62% rename from examples/code-demo.tsx rename to examples/ink/code-demo.tsx index eb6a264..fb477a2 100644 --- a/examples/code-demo.tsx +++ b/examples/ink/code-demo.tsx @@ -1,4 +1,4 @@ -import { Code } from "@/registry/ui/code"; +import { Code } from "@/registry/bases/ink/ui/code"; export default function CodeDemo() { return pnpm build; diff --git a/examples/code-multiline.tsx b/examples/ink/code-multiline.tsx similarity index 76% rename from examples/code-multiline.tsx rename to examples/ink/code-multiline.tsx index e4240f0..5e62ef3 100644 --- a/examples/code-multiline.tsx +++ b/examples/ink/code-multiline.tsx @@ -1,4 +1,4 @@ -import { Code } from "@/registry/ui/code"; +import { Code } from "@/registry/bases/ink/ui/code"; export default function CodeMultiline() { return ( diff --git a/examples/color-picker-demo.tsx b/examples/ink/color-picker-demo.tsx similarity index 58% rename from examples/color-picker-demo.tsx rename to examples/ink/color-picker-demo.tsx index c3c41bd..2945c77 100644 --- a/examples/color-picker-demo.tsx +++ b/examples/ink/color-picker-demo.tsx @@ -1,4 +1,4 @@ -import { ColorPicker } from "@/registry/ui/color-picker"; +import { ColorPicker } from "@/registry/bases/ink/ui/color-picker"; export default function ColorPickerDemo() { return ; diff --git a/examples/columns-demo.tsx b/examples/ink/columns-demo.tsx similarity index 78% rename from examples/columns-demo.tsx rename to examples/ink/columns-demo.tsx index 40c015b..4b5c54c 100644 --- a/examples/columns-demo.tsx +++ b/examples/ink/columns-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { Columns } from "@/registry/ui/columns"; +import { Columns } from "@/registry/bases/ink/ui/columns"; export default function ColumnsDemo() { return ( diff --git a/examples/command-palette-demo.tsx b/examples/ink/command-palette-demo.tsx similarity index 90% rename from examples/command-palette-demo.tsx rename to examples/ink/command-palette-demo.tsx index 3f601b3..b88080f 100644 --- a/examples/command-palette-demo.tsx +++ b/examples/ink/command-palette-demo.tsx @@ -1,4 +1,4 @@ -import { CommandPalette } from "@/registry/ui/command-palette"; +import { CommandPalette } from "@/registry/bases/ink/ui/command-palette"; export default function CommandPaletteDemo() { return ( diff --git a/examples/confirm-demo.tsx b/examples/ink/confirm-demo.tsx similarity index 70% rename from examples/confirm-demo.tsx rename to examples/ink/confirm-demo.tsx index 789e398..619aa77 100644 --- a/examples/confirm-demo.tsx +++ b/examples/ink/confirm-demo.tsx @@ -1,4 +1,4 @@ -import { Confirm } from "@/registry/ui/confirm"; +import { Confirm } from "@/registry/bases/ink/ui/confirm"; export default function ConfirmDemo() { return ( diff --git a/examples/data-grid-demo.tsx b/examples/ink/data-grid-demo.tsx similarity index 88% rename from examples/data-grid-demo.tsx rename to examples/ink/data-grid-demo.tsx index d90379e..8f5c208 100644 --- a/examples/data-grid-demo.tsx +++ b/examples/ink/data-grid-demo.tsx @@ -1,4 +1,4 @@ -import { DataGrid } from "@/registry/ui/data-grid"; +import { DataGrid } from "@/registry/bases/ink/ui/data-grid"; export default function DataGridDemo() { return ( diff --git a/examples/date-picker-demo.tsx b/examples/ink/date-picker-demo.tsx similarity index 64% rename from examples/date-picker-demo.tsx rename to examples/ink/date-picker-demo.tsx index d356753..73026c9 100644 --- a/examples/date-picker-demo.tsx +++ b/examples/ink/date-picker-demo.tsx @@ -1,4 +1,4 @@ -import { DatePicker } from "@/registry/ui/date-picker"; +import { DatePicker } from "@/registry/bases/ink/ui/date-picker"; export default function DatePickerDemo() { return ; diff --git a/examples/definition-demo.tsx b/examples/ink/definition-demo.tsx similarity index 82% rename from examples/definition-demo.tsx rename to examples/ink/definition-demo.tsx index 6ab2019..c4a5a9c 100644 --- a/examples/definition-demo.tsx +++ b/examples/ink/definition-demo.tsx @@ -1,4 +1,4 @@ -import { Definition } from "@/registry/ui/definition"; +import { Definition } from "@/registry/bases/ink/ui/definition"; export default function DefinitionDemo() { return ( diff --git a/examples/dialog-demo.tsx b/examples/ink/dialog-demo.tsx similarity index 86% rename from examples/dialog-demo.tsx rename to examples/ink/dialog-demo.tsx index 19070b7..ece4e22 100644 --- a/examples/dialog-demo.tsx +++ b/examples/ink/dialog-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { Dialog } from "@/registry/ui/dialog"; +import { Dialog } from "@/registry/bases/ink/ui/dialog"; export default function DialogDemo() { return ( diff --git a/examples/diff-view-demo.tsx b/examples/ink/diff-view-demo.tsx similarity index 82% rename from examples/diff-view-demo.tsx rename to examples/ink/diff-view-demo.tsx index 6f9fe21..11f9a43 100644 --- a/examples/diff-view-demo.tsx +++ b/examples/ink/diff-view-demo.tsx @@ -1,4 +1,4 @@ -import { DiffView } from "@/registry/ui/diff-view"; +import { DiffView } from "@/registry/bases/ink/ui/diff-view"; export default function DiffViewDemo() { return ( diff --git a/examples/digits-demo.tsx b/examples/ink/digits-demo.tsx similarity index 57% rename from examples/digits-demo.tsx rename to examples/ink/digits-demo.tsx index d517ed0..1c690e4 100644 --- a/examples/digits-demo.tsx +++ b/examples/ink/digits-demo.tsx @@ -1,4 +1,4 @@ -import { Digits } from "@/registry/ui/digits"; +import { Digits } from "@/registry/bases/ink/ui/digits"; export default function DigitsDemo() { return ; diff --git a/examples/directory-tree-demo.tsx b/examples/ink/directory-tree-demo.tsx similarity index 100% rename from examples/directory-tree-demo.tsx rename to examples/ink/directory-tree-demo.tsx diff --git a/examples/divider-custom.tsx b/examples/ink/divider-custom.tsx similarity index 88% rename from examples/divider-custom.tsx rename to examples/ink/divider-custom.tsx index 0e2920e..ac26c9a 100644 --- a/examples/divider-custom.tsx +++ b/examples/ink/divider-custom.tsx @@ -1,6 +1,6 @@ import { Box, Text } from "ink"; -import { Divider } from "@/registry/ui/divider"; +import { Divider } from "@/registry/bases/ink/ui/divider"; export default function DividerCustom() { return ( diff --git a/examples/divider-demo.tsx b/examples/ink/divider-demo.tsx similarity index 78% rename from examples/divider-demo.tsx rename to examples/ink/divider-demo.tsx index 74cc691..67bf78a 100644 --- a/examples/divider-demo.tsx +++ b/examples/ink/divider-demo.tsx @@ -1,6 +1,6 @@ import { Box, Text } from "ink"; -import { Divider } from "@/registry/ui/divider"; +import { Divider } from "@/registry/bases/ink/ui/divider"; export default function DividerDemo() { return ( diff --git a/examples/drawer-demo.tsx b/examples/ink/drawer-demo.tsx similarity index 80% rename from examples/drawer-demo.tsx rename to examples/ink/drawer-demo.tsx index e59c162..ef92f56 100644 --- a/examples/drawer-demo.tsx +++ b/examples/ink/drawer-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { Drawer } from "@/registry/ui/drawer"; +import { Drawer } from "@/registry/bases/ink/ui/drawer"; export default function DrawerDemo() { return ( diff --git a/examples/email-input-demo.tsx b/examples/ink/email-input-demo.tsx similarity index 63% rename from examples/email-input-demo.tsx rename to examples/ink/email-input-demo.tsx index f5eca84..14ada3c 100644 --- a/examples/email-input-demo.tsx +++ b/examples/ink/email-input-demo.tsx @@ -1,4 +1,4 @@ -import { EmailInput } from "@/registry/ui/email-input"; +import { EmailInput } from "@/registry/bases/ink/ui/email-input"; export default function EmailInputDemo() { return ; diff --git a/examples/embedded-terminal-demo.tsx b/examples/ink/embedded-terminal-demo.tsx similarity index 62% rename from examples/embedded-terminal-demo.tsx rename to examples/ink/embedded-terminal-demo.tsx index f1c04f6..7351dc1 100644 --- a/examples/embedded-terminal-demo.tsx +++ b/examples/ink/embedded-terminal-demo.tsx @@ -1,4 +1,4 @@ -import { EmbeddedTerminal } from "@/registry/ui/embedded-terminal"; +import { EmbeddedTerminal } from "@/registry/bases/ink/ui/embedded-terminal"; export default function EmbeddedTerminalDemo() { return ; diff --git a/examples/error-boundary-demo.tsx b/examples/ink/error-boundary-demo.tsx similarity index 75% rename from examples/error-boundary-demo.tsx rename to examples/ink/error-boundary-demo.tsx index f76dd13..dbe165f 100644 --- a/examples/error-boundary-demo.tsx +++ b/examples/ink/error-boundary-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { ErrorBoundary } from "@/registry/ui/error-boundary"; +import { ErrorBoundary } from "@/registry/bases/ink/ui/error-boundary"; export default function ErrorBoundaryDemo() { return ( diff --git a/examples/file-change-demo.tsx b/examples/ink/file-change-demo.tsx similarity index 85% rename from examples/file-change-demo.tsx rename to examples/ink/file-change-demo.tsx index d7e36d5..c6aa820 100644 --- a/examples/file-change-demo.tsx +++ b/examples/ink/file-change-demo.tsx @@ -1,4 +1,4 @@ -import { FileChange } from "@/registry/ui/file-change"; +import { FileChange } from "@/registry/bases/ink/ui/file-change"; export default function FileChangeDemo() { return ( diff --git a/examples/file-picker-demo.tsx b/examples/ink/file-picker-demo.tsx similarity index 100% rename from examples/file-picker-demo.tsx rename to examples/ink/file-picker-demo.tsx diff --git a/examples/form-demo.tsx b/examples/ink/form-demo.tsx similarity index 88% rename from examples/form-demo.tsx rename to examples/ink/form-demo.tsx index 29f0407..4011ac8 100644 --- a/examples/form-demo.tsx +++ b/examples/ink/form-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { Form } from "@/registry/ui/form"; +import { Form } from "@/registry/bases/ink/ui/form"; export default function FormDemo() { return ( diff --git a/examples/form-field-demo.tsx b/examples/ink/form-field-demo.tsx similarity index 76% rename from examples/form-field-demo.tsx rename to examples/ink/form-field-demo.tsx index 257d8c8..d6a7432 100644 --- a/examples/form-field-demo.tsx +++ b/examples/ink/form-field-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { FormField } from "@/registry/ui/form-field"; +import { FormField } from "@/registry/bases/ink/ui/form-field"; export default function FormFieldDemo() { return ( diff --git a/examples/gauge-demo.tsx b/examples/ink/gauge-demo.tsx similarity index 66% rename from examples/gauge-demo.tsx rename to examples/ink/gauge-demo.tsx index 9933489..70079e5 100644 --- a/examples/gauge-demo.tsx +++ b/examples/ink/gauge-demo.tsx @@ -1,4 +1,4 @@ -import { Gauge } from "@/registry/ui/gauge"; +import { Gauge } from "@/registry/bases/ink/ui/gauge"; export default function GaugeDemo() { return ; diff --git a/examples/git-status-demo.tsx b/examples/ink/git-status-demo.tsx similarity index 65% rename from examples/git-status-demo.tsx rename to examples/ink/git-status-demo.tsx index 3397c1d..f844c28 100644 --- a/examples/git-status-demo.tsx +++ b/examples/ink/git-status-demo.tsx @@ -1,4 +1,4 @@ -import { GitStatus } from "@/registry/ui/git-status"; +import { GitStatus } from "@/registry/bases/ink/ui/git-status"; export default function GitStatusDemo() { return ; diff --git a/examples/gradient-demo.tsx b/examples/ink/gradient-demo.tsx similarity index 69% rename from examples/gradient-demo.tsx rename to examples/ink/gradient-demo.tsx index dbff91d..d1fe894 100644 --- a/examples/gradient-demo.tsx +++ b/examples/ink/gradient-demo.tsx @@ -1,4 +1,4 @@ -import { Gradient } from "@/registry/ui/gradient"; +import { Gradient } from "@/registry/bases/ink/ui/gradient"; export default function GradientDemo() { return ( diff --git a/examples/gradient-presets.tsx b/examples/ink/gradient-presets.tsx similarity index 83% rename from examples/gradient-presets.tsx rename to examples/ink/gradient-presets.tsx index 3be7504..e15b83b 100644 --- a/examples/gradient-presets.tsx +++ b/examples/ink/gradient-presets.tsx @@ -1,6 +1,6 @@ import { Box } from "ink"; -import { Gradient } from "@/registry/ui/gradient"; +import { Gradient } from "@/registry/bases/ink/ui/gradient"; export default function GradientPresets() { return ( diff --git a/examples/grid-demo.tsx b/examples/ink/grid-demo.tsx similarity index 82% rename from examples/grid-demo.tsx rename to examples/ink/grid-demo.tsx index d8c9d4e..f4ce494 100644 --- a/examples/grid-demo.tsx +++ b/examples/ink/grid-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { Grid } from "@/registry/ui/grid"; +import { Grid } from "@/registry/bases/ink/ui/grid"; export default function GridDemo() { return ( diff --git a/examples/heading-demo.tsx b/examples/ink/heading-demo.tsx similarity index 80% rename from examples/heading-demo.tsx rename to examples/ink/heading-demo.tsx index 076b15e..cd9152d 100644 --- a/examples/heading-demo.tsx +++ b/examples/ink/heading-demo.tsx @@ -1,6 +1,6 @@ import { Box } from "ink"; -import { Heading } from "@/registry/ui/heading"; +import { Heading } from "@/registry/bases/ink/ui/heading"; export default function HeadingDemo() { return ( diff --git a/examples/heat-map-demo.tsx b/examples/ink/heat-map-demo.tsx similarity index 82% rename from examples/heat-map-demo.tsx rename to examples/ink/heat-map-demo.tsx index b50533a..c2fc343 100644 --- a/examples/heat-map-demo.tsx +++ b/examples/ink/heat-map-demo.tsx @@ -1,4 +1,4 @@ -import { HeatMap } from "@/registry/ui/heat-map"; +import { HeatMap } from "@/registry/bases/ink/ui/heat-map"; const sampleData = [ [1, 4, 7, 2], diff --git a/examples/help-demo.tsx b/examples/ink/help-demo.tsx similarity index 83% rename from examples/help-demo.tsx rename to examples/ink/help-demo.tsx index c039910..d6f1d86 100644 --- a/examples/help-demo.tsx +++ b/examples/ink/help-demo.tsx @@ -1,4 +1,4 @@ -import { Help } from "@/registry/ui/help"; +import { Help } from "@/registry/bases/ink/ui/help"; export default function HelpDemo() { return ( diff --git a/examples/help-screen-demo.tsx b/examples/ink/help-screen-demo.tsx similarity index 92% rename from examples/help-screen-demo.tsx rename to examples/ink/help-screen-demo.tsx index bee8f85..1aabfc0 100644 --- a/examples/help-screen-demo.tsx +++ b/examples/ink/help-screen-demo.tsx @@ -1,4 +1,4 @@ -import { HelpScreen } from "@/registry/ui/help-screen"; +import { HelpScreen } from "@/registry/bases/ink/ui/help-screen"; export default function HelpScreenDemo() { return ( diff --git a/examples/image-demo.tsx b/examples/ink/image-demo.tsx similarity index 100% rename from examples/image-demo.tsx rename to examples/ink/image-demo.tsx diff --git a/examples/info-box-demo.tsx b/examples/ink/info-box-demo.tsx similarity index 86% rename from examples/info-box-demo.tsx rename to examples/ink/info-box-demo.tsx index cc87b16..9c1bc46 100644 --- a/examples/info-box-demo.tsx +++ b/examples/ink/info-box-demo.tsx @@ -1,4 +1,4 @@ -import { InfoBox } from "@/registry/ui/info-box"; +import { InfoBox } from "@/registry/bases/ink/ui/info-box"; export default function InfoBoxDemo() { return ( diff --git a/examples/json-demo.tsx b/examples/ink/json-demo.tsx similarity index 82% rename from examples/json-demo.tsx rename to examples/ink/json-demo.tsx index 091a7d0..1458d83 100644 --- a/examples/json-demo.tsx +++ b/examples/ink/json-demo.tsx @@ -1,4 +1,4 @@ -import { JSONView } from "@/registry/ui/json"; +import { JSONView } from "@/registry/bases/ink/ui/json"; export default function JSONDemo() { return ( diff --git a/examples/key-value-demo.tsx b/examples/ink/key-value-demo.tsx similarity index 78% rename from examples/key-value-demo.tsx rename to examples/ink/key-value-demo.tsx index 13a825f..316ecc9 100644 --- a/examples/key-value-demo.tsx +++ b/examples/ink/key-value-demo.tsx @@ -1,4 +1,4 @@ -import { KeyValue } from "@/registry/ui/key-value"; +import { KeyValue } from "@/registry/bases/ink/ui/key-value"; export default function KeyValueDemo() { return ( diff --git a/examples/keyboard-shortcuts-demo.tsx b/examples/ink/keyboard-shortcuts-demo.tsx similarity index 84% rename from examples/keyboard-shortcuts-demo.tsx rename to examples/ink/keyboard-shortcuts-demo.tsx index aac588b..44c5e0c 100644 --- a/examples/keyboard-shortcuts-demo.tsx +++ b/examples/ink/keyboard-shortcuts-demo.tsx @@ -1,4 +1,4 @@ -import { KeyboardShortcuts } from "@/registry/ui/keyboard-shortcuts"; +import { KeyboardShortcuts } from "@/registry/bases/ink/ui/keyboard-shortcuts"; export default function KeyboardShortcutsDemo() { return ( diff --git a/examples/line-chart-demo.tsx b/examples/ink/line-chart-demo.tsx similarity index 81% rename from examples/line-chart-demo.tsx rename to examples/ink/line-chart-demo.tsx index 52aaea5..e0f2468 100644 --- a/examples/line-chart-demo.tsx +++ b/examples/ink/line-chart-demo.tsx @@ -1,4 +1,4 @@ -import { LineChart } from "@/registry/ui/line-chart"; +import { LineChart } from "@/registry/bases/ink/ui/line-chart"; const sampleData = [ { label: "Mon", value: 12 }, diff --git a/examples/link-demo.tsx b/examples/ink/link-demo.tsx similarity index 71% rename from examples/link-demo.tsx rename to examples/ink/link-demo.tsx index 6b02968..798019c 100644 --- a/examples/link-demo.tsx +++ b/examples/ink/link-demo.tsx @@ -1,5 +1,5 @@ import { SITE } from "@/constants/site"; -import { Link } from "@/registry/ui/link"; +import { Link } from "@/registry/bases/ink/ui/link"; export default function LinkDemo() { return termcn registry; diff --git a/examples/link-show-href.tsx b/examples/ink/link-show-href.tsx similarity index 85% rename from examples/link-show-href.tsx rename to examples/ink/link-show-href.tsx index 0ecdfcb..8171a48 100644 --- a/examples/link-show-href.tsx +++ b/examples/ink/link-show-href.tsx @@ -1,7 +1,7 @@ import { Box } from "ink"; import { SITE } from "@/constants/site"; -import { Link } from "@/registry/ui/link"; +import { Link } from "@/registry/bases/ink/ui/link"; export default function LinkShowHref() { return ( diff --git a/examples/list-demo.tsx b/examples/ink/list-demo.tsx similarity index 85% rename from examples/list-demo.tsx rename to examples/ink/list-demo.tsx index 2d7ef98..b1d5940 100644 --- a/examples/list-demo.tsx +++ b/examples/ink/list-demo.tsx @@ -1,4 +1,4 @@ -import { List } from "@/registry/ui/list"; +import { List } from "@/registry/bases/ink/ui/list"; export default function ListDemo() { return ( diff --git a/examples/log-demo.tsx b/examples/ink/log-demo.tsx similarity index 91% rename from examples/log-demo.tsx rename to examples/ink/log-demo.tsx index 5de15d5..a6a65b6 100644 --- a/examples/log-demo.tsx +++ b/examples/ink/log-demo.tsx @@ -1,4 +1,4 @@ -import { Log } from "@/registry/ui/log"; +import { Log } from "@/registry/bases/ink/ui/log"; export default function LogDemo() { return ( diff --git a/examples/login-flow-demo.tsx b/examples/ink/login-flow-demo.tsx similarity index 88% rename from examples/login-flow-demo.tsx rename to examples/ink/login-flow-demo.tsx index c1a391d..71dbb25 100644 --- a/examples/login-flow-demo.tsx +++ b/examples/ink/login-flow-demo.tsx @@ -1,4 +1,4 @@ -import { LoginFlow } from "@/registry/ui/login-flow"; +import { LoginFlow } from "@/registry/bases/ink/ui/login-flow"; export default function LoginFlowDemo() { return ( diff --git a/examples/markdown-demo.tsx b/examples/ink/markdown-demo.tsx similarity index 69% rename from examples/markdown-demo.tsx rename to examples/ink/markdown-demo.tsx index d42c535..4935497 100644 --- a/examples/markdown-demo.tsx +++ b/examples/ink/markdown-demo.tsx @@ -1,4 +1,4 @@ -import { Markdown } from "@/registry/ui/markdown"; +import { Markdown } from "@/registry/bases/ink/ui/markdown"; export default function MarkdownDemo() { return ( diff --git a/examples/masked-input-demo.tsx b/examples/ink/masked-input-demo.tsx similarity index 72% rename from examples/masked-input-demo.tsx rename to examples/ink/masked-input-demo.tsx index 36d5717..54aba94 100644 --- a/examples/masked-input-demo.tsx +++ b/examples/ink/masked-input-demo.tsx @@ -1,4 +1,4 @@ -import { MaskedInput } from "@/registry/ui/masked-input"; +import { MaskedInput } from "@/registry/bases/ink/ui/masked-input"; export default function MaskedInputDemo() { return ( diff --git a/examples/menu-demo.tsx b/examples/ink/menu-demo.tsx similarity index 89% rename from examples/menu-demo.tsx rename to examples/ink/menu-demo.tsx index fc50dd7..c189bf5 100644 --- a/examples/menu-demo.tsx +++ b/examples/ink/menu-demo.tsx @@ -1,4 +1,4 @@ -import { Menu } from "@/registry/ui/menu"; +import { Menu } from "@/registry/bases/ink/ui/menu"; export default function MenuDemo() { return ( diff --git a/examples/modal-demo.tsx b/examples/ink/modal-demo.tsx similarity index 79% rename from examples/modal-demo.tsx rename to examples/ink/modal-demo.tsx index ddcd622..8d71d72 100644 --- a/examples/modal-demo.tsx +++ b/examples/ink/modal-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { Modal } from "@/registry/ui/modal"; +import { Modal } from "@/registry/bases/ink/ui/modal"; export default function ModalDemo() { return ( diff --git a/examples/model-selector-demo.tsx b/examples/ink/model-selector-demo.tsx similarity index 83% rename from examples/model-selector-demo.tsx rename to examples/ink/model-selector-demo.tsx index 44b2b13..1d5b0b4 100644 --- a/examples/model-selector-demo.tsx +++ b/examples/ink/model-selector-demo.tsx @@ -1,4 +1,4 @@ -import { ModelSelector } from "@/registry/ui/model-selector"; +import { ModelSelector } from "@/registry/bases/ink/ui/model-selector"; export default function ModelSelectorDemo() { return ( diff --git a/examples/multi-progress-compact.tsx b/examples/ink/multi-progress-compact.tsx similarity index 79% rename from examples/multi-progress-compact.tsx rename to examples/ink/multi-progress-compact.tsx index 0012e09..52a346c 100644 --- a/examples/multi-progress-compact.tsx +++ b/examples/ink/multi-progress-compact.tsx @@ -1,4 +1,4 @@ -import { MultiProgress } from "@/registry/ui/multi-progress"; +import { MultiProgress } from "@/registry/bases/ink/ui/multi-progress"; export default function MultiProgressCompact() { return ( diff --git a/examples/multi-progress-demo.tsx b/examples/ink/multi-progress-demo.tsx similarity index 87% rename from examples/multi-progress-demo.tsx rename to examples/ink/multi-progress-demo.tsx index e3bd7a5..099741d 100644 --- a/examples/multi-progress-demo.tsx +++ b/examples/ink/multi-progress-demo.tsx @@ -1,4 +1,4 @@ -import { MultiProgress } from "@/registry/ui/multi-progress"; +import { MultiProgress } from "@/registry/bases/ink/ui/multi-progress"; export default function MultiProgressDemo() { return ( diff --git a/examples/multi-select-demo.tsx b/examples/ink/multi-select-demo.tsx similarity index 78% rename from examples/multi-select-demo.tsx rename to examples/ink/multi-select-demo.tsx index 2cf21d0..c77bd92 100644 --- a/examples/multi-select-demo.tsx +++ b/examples/ink/multi-select-demo.tsx @@ -1,4 +1,4 @@ -import { MultiSelect } from "@/registry/ui/multi-select"; +import { MultiSelect } from "@/registry/bases/ink/ui/multi-select"; export default function MultiSelectDemo() { return ( diff --git a/examples/notification-center-demo.tsx b/examples/ink/notification-center-demo.tsx similarity index 57% rename from examples/notification-center-demo.tsx rename to examples/ink/notification-center-demo.tsx index 5db70a7..f47c4fc 100644 --- a/examples/notification-center-demo.tsx +++ b/examples/ink/notification-center-demo.tsx @@ -1,4 +1,4 @@ -import { NotificationCenter } from "@/registry/ui/notification-center"; +import { NotificationCenter } from "@/registry/bases/ink/ui/notification-center"; export default function NotificationCenterDemo() { return ; diff --git a/examples/number-input-demo.tsx b/examples/ink/number-input-demo.tsx similarity index 63% rename from examples/number-input-demo.tsx rename to examples/ink/number-input-demo.tsx index 6953f69..342a8cc 100644 --- a/examples/number-input-demo.tsx +++ b/examples/ink/number-input-demo.tsx @@ -1,4 +1,4 @@ -import { NumberInput } from "@/registry/ui/number-input"; +import { NumberInput } from "@/registry/bases/ink/ui/number-input"; export default function NumberInputDemo() { return ; diff --git a/examples/pagination-demo.tsx b/examples/ink/pagination-demo.tsx similarity index 76% rename from examples/pagination-demo.tsx rename to examples/ink/pagination-demo.tsx index 2c8d404..1b1af53 100644 --- a/examples/pagination-demo.tsx +++ b/examples/ink/pagination-demo.tsx @@ -1,6 +1,6 @@ import { useState } from "react"; -import { Pagination } from "@/registry/ui/pagination"; +import { Pagination } from "@/registry/bases/ink/ui/pagination"; export default function PaginationDemo() { const [page, setPage] = useState(1); diff --git a/examples/panel-demo.tsx b/examples/ink/panel-demo.tsx similarity index 79% rename from examples/panel-demo.tsx rename to examples/ink/panel-demo.tsx index f8b4d30..61216fa 100644 --- a/examples/panel-demo.tsx +++ b/examples/ink/panel-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { Panel } from "@/registry/ui/panel"; +import { Panel } from "@/registry/bases/ink/ui/panel"; export default function PanelDemo() { return ( diff --git a/examples/password-input-demo.tsx b/examples/ink/password-input-demo.tsx similarity index 66% rename from examples/password-input-demo.tsx rename to examples/ink/password-input-demo.tsx index eb4c689..5fa7406 100644 --- a/examples/password-input-demo.tsx +++ b/examples/ink/password-input-demo.tsx @@ -1,4 +1,4 @@ -import { PasswordInput } from "@/registry/ui/password-input"; +import { PasswordInput } from "@/registry/bases/ink/ui/password-input"; export default function PasswordInputDemo() { return ( diff --git a/examples/path-input-demo.tsx b/examples/ink/path-input-demo.tsx similarity index 100% rename from examples/path-input-demo.tsx rename to examples/ink/path-input-demo.tsx diff --git a/examples/pie-chart-demo.tsx b/examples/ink/pie-chart-demo.tsx similarity index 79% rename from examples/pie-chart-demo.tsx rename to examples/ink/pie-chart-demo.tsx index ec58462..5323fb5 100644 --- a/examples/pie-chart-demo.tsx +++ b/examples/ink/pie-chart-demo.tsx @@ -1,4 +1,4 @@ -import { PieChart } from "@/registry/ui/pie-chart"; +import { PieChart } from "@/registry/bases/ink/ui/pie-chart"; const sampleData = [ { label: "Mon", value: 12 }, diff --git a/examples/popover-demo.tsx b/examples/ink/popover-demo.tsx similarity index 80% rename from examples/popover-demo.tsx rename to examples/ink/popover-demo.tsx index 1750657..9230846 100644 --- a/examples/popover-demo.tsx +++ b/examples/ink/popover-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { Popover } from "@/registry/ui/popover"; +import { Popover } from "@/registry/bases/ink/ui/popover"; export default function PopoverDemo() { return ( diff --git a/examples/progress-bar-custom.tsx b/examples/ink/progress-bar-custom.tsx similarity index 65% rename from examples/progress-bar-custom.tsx rename to examples/ink/progress-bar-custom.tsx index 20c405b..286b5ca 100644 --- a/examples/progress-bar-custom.tsx +++ b/examples/ink/progress-bar-custom.tsx @@ -1,4 +1,4 @@ -import { ProgressBar } from "@/registry/ui/progress-bar"; +import { ProgressBar } from "@/registry/bases/ink/ui/progress-bar"; export default function ProgressBarCustom() { return ; diff --git a/examples/progress-bar-demo.tsx b/examples/ink/progress-bar-demo.tsx similarity index 60% rename from examples/progress-bar-demo.tsx rename to examples/ink/progress-bar-demo.tsx index df19013..44bd41f 100644 --- a/examples/progress-bar-demo.tsx +++ b/examples/ink/progress-bar-demo.tsx @@ -1,4 +1,4 @@ -import { ProgressBar } from "@/registry/ui/progress-bar"; +import { ProgressBar } from "@/registry/bases/ink/ui/progress-bar"; export default function ProgressBarDemo() { return ; diff --git a/examples/progress-circle-demo.tsx b/examples/ink/progress-circle-demo.tsx similarity index 61% rename from examples/progress-circle-demo.tsx rename to examples/ink/progress-circle-demo.tsx index 3c7e6ca..186e1d1 100644 --- a/examples/progress-circle-demo.tsx +++ b/examples/ink/progress-circle-demo.tsx @@ -1,4 +1,4 @@ -import { ProgressCircle } from "@/registry/ui/progress-circle"; +import { ProgressCircle } from "@/registry/bases/ink/ui/progress-circle"; export default function ProgressCircleDemo() { return ; diff --git a/examples/progress-circle-sizes.tsx b/examples/ink/progress-circle-sizes.tsx similarity index 79% rename from examples/progress-circle-sizes.tsx rename to examples/ink/progress-circle-sizes.tsx index 16aa188..7c08a8e 100644 --- a/examples/progress-circle-sizes.tsx +++ b/examples/ink/progress-circle-sizes.tsx @@ -1,6 +1,6 @@ import { Box } from "ink"; -import { ProgressCircle } from "@/registry/ui/progress-circle"; +import { ProgressCircle } from "@/registry/bases/ink/ui/progress-circle"; export default function ProgressCircleSizes() { return ( diff --git a/examples/qr-code-demo.tsx b/examples/ink/qr-code-demo.tsx similarity index 67% rename from examples/qr-code-demo.tsx rename to examples/ink/qr-code-demo.tsx index ea6f4d6..f01ff1d 100644 --- a/examples/qr-code-demo.tsx +++ b/examples/ink/qr-code-demo.tsx @@ -1,4 +1,4 @@ -import { QRCode } from "@/registry/ui/qr-code"; +import { QRCode } from "@/registry/bases/ink/ui/qr-code"; export default function QRCodeDemo() { return ; diff --git a/examples/radio-group-demo.tsx b/examples/ink/radio-group-demo.tsx similarity index 78% rename from examples/radio-group-demo.tsx rename to examples/ink/radio-group-demo.tsx index daeb22c..1f4cd48 100644 --- a/examples/radio-group-demo.tsx +++ b/examples/ink/radio-group-demo.tsx @@ -1,4 +1,4 @@ -import { RadioGroup } from "@/registry/ui/radio-group"; +import { RadioGroup } from "@/registry/bases/ink/ui/radio-group"; export default function RadioGroupDemo() { return ( diff --git a/examples/scroll-view-demo.tsx b/examples/ink/scroll-view-demo.tsx similarity index 88% rename from examples/scroll-view-demo.tsx rename to examples/ink/scroll-view-demo.tsx index cc99f6f..8666b3a 100644 --- a/examples/scroll-view-demo.tsx +++ b/examples/ink/scroll-view-demo.tsx @@ -1,6 +1,6 @@ import { Box, Text } from "ink"; -import { ScrollView } from "@/registry/ui/scroll-view"; +import { ScrollView } from "@/registry/bases/ink/ui/scroll-view"; export default function ScrollViewDemo() { return ( diff --git a/examples/scroll-view-scrollbar.tsx b/examples/ink/scroll-view-scrollbar.tsx similarity index 89% rename from examples/scroll-view-scrollbar.tsx rename to examples/ink/scroll-view-scrollbar.tsx index c685a1f..b447278 100644 --- a/examples/scroll-view-scrollbar.tsx +++ b/examples/ink/scroll-view-scrollbar.tsx @@ -1,6 +1,6 @@ import { Box, Text } from "ink"; -import { ScrollView } from "@/registry/ui/scroll-view"; +import { ScrollView } from "@/registry/bases/ink/ui/scroll-view"; const lines = Array.from({ length: 12 }, (_, i) => `Line ${i + 1}`); diff --git a/examples/search-input-demo.tsx b/examples/ink/search-input-demo.tsx similarity index 75% rename from examples/search-input-demo.tsx rename to examples/ink/search-input-demo.tsx index e055a0a..0cfd33e 100644 --- a/examples/search-input-demo.tsx +++ b/examples/ink/search-input-demo.tsx @@ -1,4 +1,4 @@ -import { SearchInput } from "@/registry/ui/search-input"; +import { SearchInput } from "@/registry/bases/ink/ui/search-input"; export default function SearchInputDemo() { return ( diff --git a/examples/select-demo.tsx b/examples/ink/select-demo.tsx similarity index 82% rename from examples/select-demo.tsx rename to examples/ink/select-demo.tsx index 5a85953..7bbe8f8 100644 --- a/examples/select-demo.tsx +++ b/examples/ink/select-demo.tsx @@ -1,4 +1,4 @@ -import { Select } from "@/registry/ui/select"; +import { Select } from "@/registry/bases/ink/ui/select"; export default function SelectDemo() { return ( diff --git a/examples/setup-flow-demo.tsx b/examples/ink/setup-flow-demo.tsx similarity index 92% rename from examples/setup-flow-demo.tsx rename to examples/ink/setup-flow-demo.tsx index 5cca245..ac7a3ad 100644 --- a/examples/setup-flow-demo.tsx +++ b/examples/ink/setup-flow-demo.tsx @@ -1,4 +1,4 @@ -import { SetupFlow } from "@/registry/ui/setup-flow"; +import { SetupFlow } from "@/registry/bases/ink/ui/setup-flow"; export default function SetupFlowDemo() { return ( diff --git a/examples/sidebar-demo.tsx b/examples/ink/sidebar-demo.tsx similarity index 90% rename from examples/sidebar-demo.tsx rename to examples/ink/sidebar-demo.tsx index 37c6903..eb86ac6 100644 --- a/examples/sidebar-demo.tsx +++ b/examples/ink/sidebar-demo.tsx @@ -1,4 +1,4 @@ -import { Sidebar } from "@/registry/ui/sidebar"; +import { Sidebar } from "@/registry/bases/ink/ui/sidebar"; export default function SidebarDemo() { return ( diff --git a/examples/skeleton-demo.tsx b/examples/ink/skeleton-demo.tsx similarity index 59% rename from examples/skeleton-demo.tsx rename to examples/ink/skeleton-demo.tsx index 69fda9a..22ac471 100644 --- a/examples/skeleton-demo.tsx +++ b/examples/ink/skeleton-demo.tsx @@ -1,4 +1,4 @@ -import { Skeleton } from "@/registry/ui/skeleton"; +import { Skeleton } from "@/registry/bases/ink/ui/skeleton"; export default function SkeletonDemo() { return ; diff --git a/examples/skeleton-static.tsx b/examples/ink/skeleton-static.tsx similarity index 63% rename from examples/skeleton-static.tsx rename to examples/ink/skeleton-static.tsx index fad8360..db1518b 100644 --- a/examples/skeleton-static.tsx +++ b/examples/ink/skeleton-static.tsx @@ -1,4 +1,4 @@ -import { Skeleton } from "@/registry/ui/skeleton"; +import { Skeleton } from "@/registry/bases/ink/ui/skeleton"; export default function SkeletonStatic() { return ; diff --git a/examples/spacer-demo.tsx b/examples/ink/spacer-demo.tsx similarity index 77% rename from examples/spacer-demo.tsx rename to examples/ink/spacer-demo.tsx index f2fe0ff..c557f95 100644 --- a/examples/spacer-demo.tsx +++ b/examples/ink/spacer-demo.tsx @@ -1,6 +1,6 @@ import { Box, Text } from "ink"; -import { Spacer } from "@/registry/ui/spacer"; +import { Spacer } from "@/registry/bases/ink/ui/spacer"; export default function SpacerDemo() { return ( diff --git a/examples/sparkline-demo.tsx b/examples/ink/sparkline-demo.tsx similarity index 83% rename from examples/sparkline-demo.tsx rename to examples/ink/sparkline-demo.tsx index 47b1b95..5b58209 100644 --- a/examples/sparkline-demo.tsx +++ b/examples/ink/sparkline-demo.tsx @@ -1,4 +1,4 @@ -import { Sparkline } from "@/registry/ui/sparkline"; +import { Sparkline } from "@/registry/bases/ink/ui/sparkline"; const sampleData = [ { label: "Mon", value: 12 }, diff --git a/examples/spinner-demo.tsx b/examples/ink/spinner-demo.tsx similarity index 80% rename from examples/spinner-demo.tsx rename to examples/ink/spinner-demo.tsx index 905000b..93ba2ce 100644 --- a/examples/spinner-demo.tsx +++ b/examples/ink/spinner-demo.tsx @@ -1,6 +1,6 @@ import { Box } from "ink"; -import { Spinner } from "@/registry/ui/spinner"; +import { Spinner } from "@/registry/bases/ink/ui/spinner"; export default function SpinnerDemo() { return ( diff --git a/examples/spinner-label.tsx b/examples/ink/spinner-label.tsx similarity index 63% rename from examples/spinner-label.tsx rename to examples/ink/spinner-label.tsx index db0b806..3ff1771 100644 --- a/examples/spinner-label.tsx +++ b/examples/ink/spinner-label.tsx @@ -1,4 +1,4 @@ -import { Spinner } from "@/registry/ui/spinner"; +import { Spinner } from "@/registry/bases/ink/ui/spinner"; export default function SpinnerLabel() { return ; diff --git a/examples/spinner-styles.tsx b/examples/ink/spinner-styles.tsx similarity index 87% rename from examples/spinner-styles.tsx rename to examples/ink/spinner-styles.tsx index 83d477b..38c151b 100644 --- a/examples/spinner-styles.tsx +++ b/examples/ink/spinner-styles.tsx @@ -1,6 +1,6 @@ import { Box } from "ink"; -import { Spinner } from "@/registry/ui/spinner"; +import { Spinner } from "@/registry/bases/ink/ui/spinner"; export default function SpinnerStyles() { return ( diff --git a/examples/splash-screen-demo.tsx b/examples/ink/splash-screen-demo.tsx similarity index 81% rename from examples/splash-screen-demo.tsx rename to examples/ink/splash-screen-demo.tsx index 86e166e..5d09c7e 100644 --- a/examples/splash-screen-demo.tsx +++ b/examples/ink/splash-screen-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { SplashScreen } from "@/registry/ui/splash-screen"; +import { SplashScreen } from "@/registry/bases/ink/ui/splash-screen"; export default function SplashScreenDemo() { return ( diff --git a/examples/stack-demo.tsx b/examples/ink/stack-demo.tsx similarity index 79% rename from examples/stack-demo.tsx rename to examples/ink/stack-demo.tsx index 33f8f8b..48cacd5 100644 --- a/examples/stack-demo.tsx +++ b/examples/ink/stack-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { Stack } from "@/registry/ui/stack"; +import { Stack } from "@/registry/bases/ink/ui/stack"; export default function StackDemo() { return ( diff --git a/examples/status-message-demo.tsx b/examples/ink/status-message-demo.tsx similarity index 66% rename from examples/status-message-demo.tsx rename to examples/ink/status-message-demo.tsx index b6711bd..694e62e 100644 --- a/examples/status-message-demo.tsx +++ b/examples/ink/status-message-demo.tsx @@ -1,4 +1,4 @@ -import { StatusMessage } from "@/registry/ui/status-message"; +import { StatusMessage } from "@/registry/bases/ink/ui/status-message"; export default function StatusMessageDemo() { return ( diff --git a/examples/status-message-variants.tsx b/examples/ink/status-message-variants.tsx similarity index 85% rename from examples/status-message-variants.tsx rename to examples/ink/status-message-variants.tsx index acaf84a..b19b694 100644 --- a/examples/status-message-variants.tsx +++ b/examples/ink/status-message-variants.tsx @@ -1,6 +1,6 @@ import { Box } from "ink"; -import { StatusMessage } from "@/registry/ui/status-message"; +import { StatusMessage } from "@/registry/bases/ink/ui/status-message"; export default function StatusMessageVariants() { return ( diff --git a/examples/stopwatch-demo.tsx b/examples/ink/stopwatch-demo.tsx similarity index 55% rename from examples/stopwatch-demo.tsx rename to examples/ink/stopwatch-demo.tsx index f927001..4ff15eb 100644 --- a/examples/stopwatch-demo.tsx +++ b/examples/ink/stopwatch-demo.tsx @@ -1,4 +1,4 @@ -import { Stopwatch } from "@/registry/ui/stopwatch"; +import { Stopwatch } from "@/registry/bases/ink/ui/stopwatch"; export default function StopwatchDemo() { return ; diff --git a/examples/streaming-text-demo.tsx b/examples/ink/streaming-text-demo.tsx similarity index 63% rename from examples/streaming-text-demo.tsx rename to examples/ink/streaming-text-demo.tsx index c1aedc3..9406b64 100644 --- a/examples/streaming-text-demo.tsx +++ b/examples/ink/streaming-text-demo.tsx @@ -1,4 +1,4 @@ -import { StreamingText } from "@/registry/ui/streaming-text"; +import { StreamingText } from "@/registry/bases/ink/ui/streaming-text"; export default function StreamingTextDemo() { return ; diff --git a/examples/tabbed-content-demo.tsx b/examples/ink/tabbed-content-demo.tsx similarity index 89% rename from examples/tabbed-content-demo.tsx rename to examples/ink/tabbed-content-demo.tsx index 27f87e0..b4cd986 100644 --- a/examples/tabbed-content-demo.tsx +++ b/examples/ink/tabbed-content-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { TabbedContent } from "@/registry/ui/tabbed-content"; +import { TabbedContent } from "@/registry/bases/ink/ui/tabbed-content"; export default function TabbedContentDemo() { return ( diff --git a/examples/table-demo.tsx b/examples/ink/table-demo.tsx similarity index 89% rename from examples/table-demo.tsx rename to examples/ink/table-demo.tsx index 4f3b93c..d01c2e0 100644 --- a/examples/table-demo.tsx +++ b/examples/ink/table-demo.tsx @@ -1,4 +1,4 @@ -import { Table } from "@/registry/ui/table"; +import { Table } from "@/registry/bases/ink/ui/table"; const data = [ { name: "termcn", status: "ready", version: "0.1.0" }, diff --git a/examples/table-selectable.tsx b/examples/ink/table-selectable.tsx similarity index 92% rename from examples/table-selectable.tsx rename to examples/ink/table-selectable.tsx index f8ac30c..cef8b15 100644 --- a/examples/table-selectable.tsx +++ b/examples/ink/table-selectable.tsx @@ -1,7 +1,7 @@ import { Box, Text } from "ink"; import { useState } from "react"; -import { Table } from "@/registry/ui/table"; +import { Table } from "@/registry/bases/ink/ui/table"; const data = [ { id: "a", name: "Alpha" }, diff --git a/examples/table-sortable.tsx b/examples/ink/table-sortable.tsx similarity index 90% rename from examples/table-sortable.tsx rename to examples/ink/table-sortable.tsx index 5a95610..5fddee4 100644 --- a/examples/table-sortable.tsx +++ b/examples/ink/table-sortable.tsx @@ -1,4 +1,4 @@ -import { Table } from "@/registry/ui/table"; +import { Table } from "@/registry/bases/ink/ui/table"; const data = [ { downloads: 1240, name: "badge", status: "stable" }, diff --git a/examples/tabs-demo.tsx b/examples/ink/tabs-demo.tsx similarity index 91% rename from examples/tabs-demo.tsx rename to examples/ink/tabs-demo.tsx index 9ebb919..615f425 100644 --- a/examples/tabs-demo.tsx +++ b/examples/ink/tabs-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { Tabs } from "@/registry/ui/tabs"; +import { Tabs } from "@/registry/bases/ink/ui/tabs"; export default function TabsDemo() { return ( diff --git a/examples/tag-demo.tsx b/examples/ink/tag-demo.tsx similarity index 78% rename from examples/tag-demo.tsx rename to examples/ink/tag-demo.tsx index 69e83d8..e1bb9a5 100644 --- a/examples/tag-demo.tsx +++ b/examples/ink/tag-demo.tsx @@ -1,6 +1,6 @@ import { Box } from "ink"; -import { Tag } from "@/registry/ui/tag"; +import { Tag } from "@/registry/bases/ink/ui/tag"; export default function TagDemo() { return ( diff --git a/examples/tag-input-demo.tsx b/examples/ink/tag-input-demo.tsx similarity index 60% rename from examples/tag-input-demo.tsx rename to examples/ink/tag-input-demo.tsx index 78f646f..94672a4 100644 --- a/examples/tag-input-demo.tsx +++ b/examples/ink/tag-input-demo.tsx @@ -1,4 +1,4 @@ -import { TagInput } from "@/registry/ui/tag-input"; +import { TagInput } from "@/registry/bases/ink/ui/tag-input"; export default function TagInputDemo() { return ; diff --git a/examples/text-area-demo.tsx b/examples/ink/text-area-demo.tsx similarity index 72% rename from examples/text-area-demo.tsx rename to examples/ink/text-area-demo.tsx index 1530abd..0c59456 100644 --- a/examples/text-area-demo.tsx +++ b/examples/ink/text-area-demo.tsx @@ -1,4 +1,4 @@ -import { TextArea } from "@/registry/ui/text-area"; +import { TextArea } from "@/registry/bases/ink/ui/text-area"; export default function TextAreaDemo() { return ( diff --git a/examples/text-input-cursor.tsx b/examples/ink/text-input-cursor.tsx similarity index 84% rename from examples/text-input-cursor.tsx rename to examples/ink/text-input-cursor.tsx index f0b0764..c144251 100644 --- a/examples/text-input-cursor.tsx +++ b/examples/ink/text-input-cursor.tsx @@ -1,6 +1,6 @@ import { Box, Text } from "ink"; -import { TextInput } from "@/registry/ui/text-input"; +import { TextInput } from "@/registry/bases/ink/ui/text-input"; export default function TextInputCursor() { return ( diff --git a/examples/text-input-demo.tsx b/examples/ink/text-input-demo.tsx similarity index 65% rename from examples/text-input-demo.tsx rename to examples/ink/text-input-demo.tsx index b40351b..1170489 100644 --- a/examples/text-input-demo.tsx +++ b/examples/ink/text-input-demo.tsx @@ -1,4 +1,4 @@ -import { TextInput } from "@/registry/ui/text-input"; +import { TextInput } from "@/registry/bases/ink/ui/text-input"; export default function TextInputDemo() { return ; diff --git a/examples/text-input-label.tsx b/examples/ink/text-input-label.tsx similarity index 80% rename from examples/text-input-label.tsx rename to examples/ink/text-input-label.tsx index fa53b83..a916a35 100644 --- a/examples/text-input-label.tsx +++ b/examples/ink/text-input-label.tsx @@ -1,6 +1,6 @@ import { Box } from "ink"; -import { TextInput } from "@/registry/ui/text-input"; +import { TextInput } from "@/registry/bases/ink/ui/text-input"; export default function TextInputLabel() { return ( diff --git a/examples/text-input-placeholder.tsx b/examples/ink/text-input-placeholder.tsx similarity index 63% rename from examples/text-input-placeholder.tsx rename to examples/ink/text-input-placeholder.tsx index e679507..7cfdb6e 100644 --- a/examples/text-input-placeholder.tsx +++ b/examples/ink/text-input-placeholder.tsx @@ -1,4 +1,4 @@ -import { TextInput } from "@/registry/ui/text-input"; +import { TextInput } from "@/registry/bases/ink/ui/text-input"; export default function TextInputPlaceholder() { return ; diff --git a/examples/thinking-block-demo.tsx b/examples/ink/thinking-block-demo.tsx similarity index 69% rename from examples/thinking-block-demo.tsx rename to examples/ink/thinking-block-demo.tsx index 1ae5984..360b597 100644 --- a/examples/thinking-block-demo.tsx +++ b/examples/ink/thinking-block-demo.tsx @@ -1,4 +1,4 @@ -import { ThinkingBlock } from "@/registry/ui/thinking-block"; +import { ThinkingBlock } from "@/registry/bases/ink/ui/thinking-block"; export default function ThinkingBlockDemo() { return ( diff --git a/examples/time-picker-demo.tsx b/examples/ink/time-picker-demo.tsx similarity index 65% rename from examples/time-picker-demo.tsx rename to examples/ink/time-picker-demo.tsx index f4b8397..39292b9 100644 --- a/examples/time-picker-demo.tsx +++ b/examples/ink/time-picker-demo.tsx @@ -1,4 +1,4 @@ -import { TimePicker } from "@/registry/ui/time-picker"; +import { TimePicker } from "@/registry/bases/ink/ui/time-picker"; export default function TimePickerDemo() { return ; diff --git a/examples/timer-demo.tsx b/examples/ink/timer-demo.tsx similarity index 67% rename from examples/timer-demo.tsx rename to examples/ink/timer-demo.tsx index cb3598e..dd34b5e 100644 --- a/examples/timer-demo.tsx +++ b/examples/ink/timer-demo.tsx @@ -1,4 +1,4 @@ -import { Timer } from "@/registry/ui/timer"; +import { Timer } from "@/registry/bases/ink/ui/timer"; export default function TimerDemo() { return ; diff --git a/examples/toast-demo.tsx b/examples/ink/toast-demo.tsx similarity index 68% rename from examples/toast-demo.tsx rename to examples/ink/toast-demo.tsx index 1f26177..062adc6 100644 --- a/examples/toast-demo.tsx +++ b/examples/ink/toast-demo.tsx @@ -1,4 +1,4 @@ -import { Toast } from "@/registry/ui/toast"; +import { Toast } from "@/registry/bases/ink/ui/toast"; export default function ToastDemo() { return ; diff --git a/examples/toast-error.tsx b/examples/ink/toast-error.tsx similarity index 74% rename from examples/toast-error.tsx rename to examples/ink/toast-error.tsx index 8085e52..1d0691f 100644 --- a/examples/toast-error.tsx +++ b/examples/ink/toast-error.tsx @@ -1,4 +1,4 @@ -import { Toast } from "@/registry/ui/toast"; +import { Toast } from "@/registry/bases/ink/ui/toast"; export default function ToastError() { return ( diff --git a/examples/toggle-demo.tsx b/examples/ink/toggle-demo.tsx similarity index 62% rename from examples/toggle-demo.tsx rename to examples/ink/toggle-demo.tsx index 546ce47..1c7f8e5 100644 --- a/examples/toggle-demo.tsx +++ b/examples/ink/toggle-demo.tsx @@ -1,4 +1,4 @@ -import { Toggle } from "@/registry/ui/toggle"; +import { Toggle } from "@/registry/bases/ink/ui/toggle"; export default function ToggleDemo() { return ; diff --git a/examples/token-usage-demo.tsx b/examples/ink/token-usage-demo.tsx similarity index 60% rename from examples/token-usage-demo.tsx rename to examples/ink/token-usage-demo.tsx index 8ddb698..42929de 100644 --- a/examples/token-usage-demo.tsx +++ b/examples/ink/token-usage-demo.tsx @@ -1,4 +1,4 @@ -import { TokenUsage } from "@/registry/ui/token-usage"; +import { TokenUsage } from "@/registry/bases/ink/ui/token-usage"; export default function TokenUsageDemo() { return ; diff --git a/examples/tool-approval-demo.tsx b/examples/ink/tool-approval-demo.tsx similarity index 77% rename from examples/tool-approval-demo.tsx rename to examples/ink/tool-approval-demo.tsx index e2d8ffc..a71420d 100644 --- a/examples/tool-approval-demo.tsx +++ b/examples/ink/tool-approval-demo.tsx @@ -1,4 +1,4 @@ -import { ToolApproval } from "@/registry/ui/tool-approval"; +import { ToolApproval } from "@/registry/bases/ink/ui/tool-approval"; export default function ToolApprovalDemo() { return ( diff --git a/examples/tool-call-demo.tsx b/examples/ink/tool-call-demo.tsx similarity index 80% rename from examples/tool-call-demo.tsx rename to examples/ink/tool-call-demo.tsx index 7e86519..9741bad 100644 --- a/examples/tool-call-demo.tsx +++ b/examples/ink/tool-call-demo.tsx @@ -1,4 +1,4 @@ -import { ToolCall } from "@/registry/ui/tool-call"; +import { ToolCall } from "@/registry/bases/ink/ui/tool-call"; export default function ToolCallDemo() { return ( diff --git a/examples/tooltip-demo.tsx b/examples/ink/tooltip-demo.tsx similarity index 80% rename from examples/tooltip-demo.tsx rename to examples/ink/tooltip-demo.tsx index 159a8cc..6558fd5 100644 --- a/examples/tooltip-demo.tsx +++ b/examples/ink/tooltip-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { Tooltip } from "@/registry/ui/tooltip"; +import { Tooltip } from "@/registry/bases/ink/ui/tooltip"; export default function TooltipDemo() { return ( diff --git a/examples/tree-demo.tsx b/examples/ink/tree-demo.tsx similarity index 88% rename from examples/tree-demo.tsx rename to examples/ink/tree-demo.tsx index 670a677..c712528 100644 --- a/examples/tree-demo.tsx +++ b/examples/ink/tree-demo.tsx @@ -1,4 +1,4 @@ -import { Tree } from "@/registry/ui/tree"; +import { Tree } from "@/registry/bases/ink/ui/tree"; export default function TreeDemo() { return ( diff --git a/examples/tree-select-demo.tsx b/examples/ink/tree-select-demo.tsx similarity index 85% rename from examples/tree-select-demo.tsx rename to examples/ink/tree-select-demo.tsx index 4b61b4d..e5ae1aa 100644 --- a/examples/tree-select-demo.tsx +++ b/examples/ink/tree-select-demo.tsx @@ -1,4 +1,4 @@ -import { TreeSelect } from "@/registry/ui/tree-select"; +import { TreeSelect } from "@/registry/bases/ink/ui/tree-select"; export default function TreeSelectDemo() { return ( diff --git a/examples/usage-monitor-demo.tsx b/examples/ink/usage-monitor-demo.tsx similarity index 93% rename from examples/usage-monitor-demo.tsx rename to examples/ink/usage-monitor-demo.tsx index db4a7df..af8f101 100644 --- a/examples/usage-monitor-demo.tsx +++ b/examples/ink/usage-monitor-demo.tsx @@ -1,4 +1,4 @@ -import { UsageMonitor } from "@/registry/ui/usage-monitor"; +import { UsageMonitor } from "@/registry/bases/ink/ui/usage-monitor"; export default function UsageMonitorDemo() { return ( diff --git a/examples/virtual-list-demo.tsx b/examples/ink/virtual-list-demo.tsx similarity index 82% rename from examples/virtual-list-demo.tsx rename to examples/ink/virtual-list-demo.tsx index 0106ff0..8d9ce11 100644 --- a/examples/virtual-list-demo.tsx +++ b/examples/ink/virtual-list-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { VirtualList } from "@/registry/ui/virtual-list"; +import { VirtualList } from "@/registry/bases/ink/ui/virtual-list"; const renderVirtualListItem = (item: string) => {item}; diff --git a/examples/welcome-screen-demo.tsx b/examples/ink/welcome-screen-demo.tsx similarity index 92% rename from examples/welcome-screen-demo.tsx rename to examples/ink/welcome-screen-demo.tsx index cfbe7b1..13d6f8c 100644 --- a/examples/welcome-screen-demo.tsx +++ b/examples/ink/welcome-screen-demo.tsx @@ -1,4 +1,4 @@ -import { WelcomeScreen } from "@/registry/ui/welcome-screen"; +import { WelcomeScreen } from "@/registry/bases/ink/ui/welcome-screen"; export default function WelcomeScreenDemo() { return ( diff --git a/examples/wizard-demo.tsx b/examples/ink/wizard-demo.tsx similarity index 90% rename from examples/wizard-demo.tsx rename to examples/ink/wizard-demo.tsx index ced1b52..1756ee9 100644 --- a/examples/wizard-demo.tsx +++ b/examples/ink/wizard-demo.tsx @@ -1,6 +1,6 @@ import { Text } from "ink"; -import { Wizard } from "@/registry/ui/wizard"; +import { Wizard } from "@/registry/bases/ink/ui/wizard"; export default function WizardDemo() { return ( diff --git a/examples/opentui/spinner-demo.tsx b/examples/opentui/spinner-demo.tsx new file mode 100644 index 0000000..0896e68 --- /dev/null +++ b/examples/opentui/spinner-demo.tsx @@ -0,0 +1,17 @@ +import { OpenTuiPreview } from "@/components/opentui-preview"; +import { resolveSpinner } from "@/registry/bases/opentui/ui/spinner"; + +const loadingFrames = resolveSpinner({ + color: "cyan", + name: "dots", +}).frames.map((frame) => `${frame} Loading components...\n`); + +const buildFrames = resolveSpinner({ color: "yellow", name: "arc" }).frames.map( + (frame) => `${frame} Building registry...\n` +); + +const FRAMES = [...loadingFrames, "", ...buildFrames].map((line) => `${line}`); + +export default function OpenTuiSpinnerDemo() { + return ; +} diff --git a/examples/opentui/spinner-react.ts b/examples/opentui/spinner-react.ts new file mode 100644 index 0000000..0a9f615 --- /dev/null +++ b/examples/opentui/spinner-react.ts @@ -0,0 +1,15 @@ +import { createCliRenderer } from "@opentui/core"; +import { createRoot } from "@opentui/react"; +import { createElement } from "react"; + +import { Spinner } from "@/registry/bases/opentui/ui/spinner"; + +const renderer = await createCliRenderer({ exitOnCtrlC: true }); + +createRoot(renderer).render( + createElement(Spinner, { + color: "cyan", + label: "Loading...", + name: "bouncingBall", + }) +); diff --git a/hooks/use-animation.ts b/hooks/use-animation.ts index 10919a9..702e829 100644 --- a/hooks/use-animation.ts +++ b/hooks/use-animation.ts @@ -1 +1 @@ -export { useAnimation } from "@/registry/hooks/use-animation"; +export { useAnimation } from "@/registry/bases/ink/hooks/use-animation"; diff --git a/hooks/use-clipboard.ts b/hooks/use-clipboard.ts index fae6903..a6fa3dd 100644 --- a/hooks/use-clipboard.ts +++ b/hooks/use-clipboard.ts @@ -1 +1 @@ -export { useClipboard } from "@/registry/hooks/use-clipboard"; +export { useClipboard } from "@/registry/bases/ink/hooks/use-clipboard"; diff --git a/hooks/use-focus.ts b/hooks/use-focus.ts index 5c1a2b9..07c6a98 100644 --- a/hooks/use-focus.ts +++ b/hooks/use-focus.ts @@ -1 +1 @@ -export { useFocus } from "@/registry/hooks/use-focus"; +export { useFocus } from "@/registry/bases/ink/hooks/use-focus"; diff --git a/hooks/use-input.ts b/hooks/use-input.ts index acf19b3..21bf60a 100644 --- a/hooks/use-input.ts +++ b/hooks/use-input.ts @@ -2,4 +2,4 @@ export { useInput, type InputHandler, type Key, -} from "@/registry/hooks/use-input"; +} from "@/registry/bases/ink/hooks/use-input"; diff --git a/hooks/use-interval.ts b/hooks/use-interval.ts index b753335..c354f77 100644 --- a/hooks/use-interval.ts +++ b/hooks/use-interval.ts @@ -1 +1 @@ -export { useInterval } from "@/registry/hooks/use-interval"; +export { useInterval } from "@/registry/bases/ink/hooks/use-interval"; diff --git a/hooks/use-notifications.ts b/hooks/use-notifications.ts index de17751..bc9823e 100644 --- a/hooks/use-notifications.ts +++ b/hooks/use-notifications.ts @@ -5,4 +5,4 @@ export { type Notification, type NotificationVariant, type NotificationsContextValue, -} from "@/registry/hooks/use-notifications"; +} from "@/registry/bases/ink/hooks/use-notifications"; diff --git a/lib/docs.ts b/lib/docs.ts index 7e1467a..79b3802 100644 --- a/lib/docs.ts +++ b/lib/docs.ts @@ -1,4 +1,5 @@ import { ROUTES } from "@/constants/routes"; +import type { ExampleFramework } from "@/lib/examples"; import { formatLabelFromSlug } from "./utils"; @@ -19,13 +20,69 @@ export interface DocsConfig { } const TITLE_OVERRIDES: Record = { + ink: "Ink", json: "JSON", + opentui: "OpenTUI", "qr-code": "QR Code", }; +export const DOCS_FRAMEWORKS = ["ink", "opentui"] as const; +export const DEFAULT_DOCS_FRAMEWORK: ExampleFramework = "ink"; + export const formatTitleFromSlug = (slug: string): string => TITLE_OVERRIDES[slug] ?? formatLabelFromSlug(slug); +export const isDocsFramework = ( + value: string | undefined +): value is ExampleFramework => + value !== undefined && (DOCS_FRAMEWORKS as readonly string[]).includes(value); + +export const hasDocsFrameworkInSlug = (slug?: string[]) => + slug?.[0] === "components" && isDocsFramework(slug?.[1]); + +export const getDocsFrameworkFromSlug = (slug?: string[]): ExampleFramework => + slug?.[0] === "components" && isDocsFramework(slug?.[1]) + ? slug[1] + : DEFAULT_DOCS_FRAMEWORK; + +export const stripDocsFrameworkFromSlug = (slug?: string[]) => { + if (slug?.[0] !== "components" || !isDocsFramework(slug?.[1])) { + return slug; + } + + return ["components", ...slug.slice(2)]; +}; + +export const isComponentDocsSlug = (slug?: string[]) => { + const contentSlug = stripDocsFrameworkFromSlug(slug); + + return contentSlug?.[0] === "components" && contentSlug.length >= 3; +}; + +export const getDocsRouteSlug = ( + slug: string[] | undefined, + framework: ExampleFramework = DEFAULT_DOCS_FRAMEWORK +) => { + const contentSlug = stripDocsFrameworkFromSlug(slug); + + if (!contentSlug || !isComponentDocsSlug(contentSlug)) { + return contentSlug; + } + + return ["components", framework, ...contentSlug.slice(1)]; +}; + +export const getDocsRoute = ( + slug: string[] | undefined, + framework: ExampleFramework = DEFAULT_DOCS_FRAMEWORK +) => { + const routeSlug = getDocsRouteSlug(slug, framework); + + return routeSlug?.length + ? `${ROUTES.DOCS}/${routeSlug.join("/")}` + : ROUTES.DOCS; +}; + const navLeaf = ( title: string, href: string diff --git a/lib/events.ts b/lib/events.ts index eca1096..172a4ac 100644 --- a/lib/events.ts +++ b/lib/events.ts @@ -1,25 +1,35 @@ import { track } from "@vercel/analytics"; +import { z } from "zod"; -type EventName = - | "copy_npm_command" - | "copy_usage_import_code" - | "copy_usage_code" - | "copy_primitive_code" - | "copy_theme_code" - | "copy_block_code" - | "copy_chunk_code" - | "enable_lift_mode" - | "copy_chart_code" - | "copy_chart_theme" - | "copy_chart_data" - | "copy_color" - | "set_layout"; +const eventSchema = z.object({ + name: z.enum([ + "copy_npm_command", + "copy_usage_import_code", + "copy_usage_code", + "copy_primitive_code", + "copy_theme_code", + "copy_block_code", + "copy_chunk_code", + "enable_lift_mode", + "copy_chart_code", + "copy_chart_theme", + "copy_chart_data", + "copy_color", + "set_layout", + ]), + properties: z + .record( + z.string(), + z.union([z.string(), z.number(), z.boolean(), z.null()]) + ) + .optional(), +}); -export interface Event { - name: EventName; - properties?: Record; -} +export type Event = z.infer; export const trackEvent = (input: Event): void => { - track(input.name, input.properties); + const event = eventSchema.parse(input); + if (event) { + track(event.name, event.properties); + } }; diff --git a/lib/examples.ts b/lib/examples.ts new file mode 100644 index 0000000..aef13b2 --- /dev/null +++ b/lib/examples.ts @@ -0,0 +1,40 @@ +import { ExamplesIndex } from "@/examples/__index__"; +import type { ExampleEntry, ExampleFramework } from "@/examples/__index__"; +import { PUBLIC_REGISTRY_FRAMEWORK } from "@/lib/registry"; + +export type { ExampleEntry, ExampleFramework }; + +export const getExampleEntry = ( + name: string, + framework: ExampleFramework = "ink" +): ExampleEntry | null => ExamplesIndex[framework][name] ?? null; + +export const hasExampleEntry = ( + name: string, + framework: ExampleFramework = "ink" +): boolean => getExampleEntry(name, framework) !== null; + +export const getExampleFilePath = ( + name: string, + framework: ExampleFramework = "ink" +): string | null => getExampleEntry(name, framework)?.filePath ?? null; + +export const getAvailableExampleFrameworks = ( + name: string +): ExampleFramework[] => + (Object.keys(ExamplesIndex) as ExampleFramework[]).filter((framework) => + hasExampleEntry(name, framework) + ); + +export const getPrimaryExampleNameForComponent = (componentName: string) => + `${componentName}-demo`; + +export const getAvailableComponentFrameworks = ( + componentName: string +): ExampleFramework[] => { + const frameworks = getAvailableExampleFrameworks( + getPrimaryExampleNameForComponent(componentName) + ); + + return frameworks.length > 0 ? frameworks : [PUBLIC_REGISTRY_FRAMEWORK]; +}; diff --git a/lib/page-tree.ts b/lib/page-tree.ts index 7c012ab..bf4272e 100644 --- a/lib/page-tree.ts +++ b/lib/page-tree.ts @@ -1,5 +1,8 @@ import type { Node as PageTreeNode } from "fumadocs-core/page-tree"; +import { DEFAULT_DOCS_FRAMEWORK, isDocsFramework } from "@/lib/docs"; +import type { ExampleFramework } from "@/lib/examples"; + export type PageTreeFolder = Extract; export type PageTreePage = Extract; @@ -16,3 +19,11 @@ export const getPagesFromFolder = (folder: PageTreeFolder): PageTreePage[] => { return pages; }; + +export const getCurrentFramework = (pathname: string): ExampleFramework => { + const frameworkMatch = pathname.match(/\/docs\/components\/(ink|opentui)\//); + + return frameworkMatch && isDocsFramework(frameworkMatch[1]) + ? frameworkMatch[1] + : DEFAULT_DOCS_FRAMEWORK; +}; diff --git a/lib/registry.ts b/lib/registry.ts new file mode 100644 index 0000000..8fc046f --- /dev/null +++ b/lib/registry.ts @@ -0,0 +1,38 @@ +import path from "node:path"; + +import type { ExampleFramework } from "@/examples/__index__"; +import { + BASE_NAMES, + isPublicBaseName, + PUBLIC_BASE_NAME, +} from "@/registry/bases"; + +export const INTERNAL_REGISTRY_FRAMEWORKS = + BASE_NAMES as readonly ExampleFramework[]; + +export const PUBLIC_REGISTRY_FRAMEWORK = PUBLIC_BASE_NAME as Extract< + ExampleFramework, + typeof PUBLIC_BASE_NAME +>; + +export const isPublicRegistryFramework = ( + framework: ExampleFramework | undefined +): framework is typeof PUBLIC_REGISTRY_FRAMEWORK => isPublicBaseName(framework); + +export const getRegistryUiSourceCandidates = ({ + framework, + name, +}: { + framework?: ExampleFramework; + name: string; +}) => { + const candidates: string[] = framework + ? [path.join("registry", "bases", framework, "ui", `${name}.tsx`)] + : []; + + if (!framework || isPublicRegistryFramework(framework)) { + candidates.push(path.join("registry", "ui", `${name}.tsx`)); + } + + return [...new Set(candidates)]; +}; diff --git a/lib/terminal-themes.ts b/lib/terminal-themes.ts index 369782b..6e7ee0b 100644 --- a/lib/terminal-themes.ts +++ b/lib/terminal-themes.ts @@ -1,37 +1,5 @@ -import { formatLabelFromSlug } from "@/lib/utils"; -import { catppuccinTheme } from "@/registry/themes/catppuccin"; -import { defaultTheme } from "@/registry/themes/default"; -import { draculaTheme } from "@/registry/themes/dracula"; -import { - highContrastLightTheme, - highContrastTheme, -} from "@/registry/themes/high-contrast"; -import { monokaiTheme } from "@/registry/themes/monokai"; -import { nordTheme } from "@/registry/themes/nord"; -import { oneDarkTheme } from "@/registry/themes/one-dark"; -import { solarizedTheme } from "@/registry/themes/solarized"; -import { tokyoNightTheme } from "@/registry/themes/tokyo-night"; - -export const terminalThemeMap = { - catppuccin: catppuccinTheme, - default: defaultTheme, - dracula: draculaTheme, - "high-contrast": highContrastTheme, - "high-contrast-light": highContrastLightTheme, - monokai: monokaiTheme, - nord: nordTheme, - "one-dark": oneDarkTheme, - solarized: solarizedTheme, - "tokyo-night": tokyoNightTheme, -} as const; - -const themes = Object.values(terminalThemeMap); - -export const terminalThemeOptions = themes.map((t) => ({ - label: formatLabelFromSlug(t.name), - value: t.name, -})); - -export const themePrimaryBySlug: Record = Object.fromEntries( - themes.map((t) => [t.name, t.colors.primary]) -); +export { + TERMINAL_THEME_MAP as terminalThemeMap, + TERMINAL_THEME_OPTIONS as terminalThemeOptions, + THEME_PRIMARY_BY_NAME as themePrimaryBySlug, +} from "@/registry/themes"; diff --git a/mdx-components.tsx b/mdx-components.tsx index fc2a49c..ab99304 100644 --- a/mdx-components.tsx +++ b/mdx-components.tsx @@ -21,10 +21,18 @@ import { AspectRatio } from "@/components/ui/aspect-ratio"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import { ThemeShowcasePreview } from "@/examples/theme-showcase"; +import type { ExampleFramework } from "@/lib/examples"; import { cn } from "@/lib/utils"; -export const mdxComponents = { +const matchesFramework = ( + currentFramework: ExampleFramework, + targetFramework: ExampleFramework | ExampleFramework[] +) => + Array.isArray(targetFramework) + ? targetFramework.includes(currentFramework) + : currentFramework === targetFramework; + +export const createMdxComponents = (framework: ExampleFramework = "ink") => ({ Accordion, AccordionContent, AccordionItem, @@ -36,8 +44,12 @@ export const mdxComponents = { Button, Callout, CodeTabs, - ComponentPreview, - ComponentSource, + ComponentPreview: (props: React.ComponentProps) => ( + + ), + ComponentSource: (props: React.ComponentProps) => ( + + ), ComponentsList, FeatureCard: ({ icon: Icon, @@ -66,6 +78,13 @@ export const mdxComponents = { ), + FrameworkOnly: ({ + children, + value, + }: { + children?: React.ReactNode; + value: ExampleFramework | ExampleFramework[]; + }) => (matchesFramework(framework, value) ? children : null), Image: ({ src, className, @@ -83,6 +102,8 @@ export const mdxComponents = { {...props} /> ), + InkOnly: ({ children }: { children?: React.ReactNode }) => + framework === "ink" ? children : null, Link: ({ className, ...props }: React.ComponentProps) => ( ), + OpenTUIOnly: ({ children }: { children?: React.ReactNode }) => + framework === "opentui" ? children : null, Step: ({ className, children, ...props }: React.ComponentProps<"h3">) => (

) => (
    ), -}; +}); + +export const mdxComponents = createMdxComponents(); diff --git a/next.config.mjs b/next.config.mjs index 29fa704..293f2de 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -18,6 +18,15 @@ const nextConfig = { outputFileTracingIncludes: { "/*": ["./registry/**/*"], }, + redirects() { + return [ + { + destination: "/docs/components/ink/:category/:component", + permanent: true, + source: "/docs/components/:category/:component", + }, + ]; + }, turbopack: { resolveAlias: { ink: "ink-web" }, }, diff --git a/package.json b/package.json index bd4933a..7715d19 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,10 @@ "scripts": { "dev": "next dev", "build": "pnpm registry:build && next build", + "examples:build": "node ./scripts/build-examples.mts", "start": "next start", "typecheck": "tsc --noEmit", - "registry:build": "shadcn build registry.json --output ./public/r", + "registry:build": "pnpm examples:build && node ./scripts/build-registry.mts", "postinstall": "fumadocs-mdx", "check": "ultracite check", "fix": "ultracite fix", diff --git a/registry/bases.ts b/registry/bases.ts new file mode 100644 index 0000000..c4f5946 --- /dev/null +++ b/registry/bases.ts @@ -0,0 +1,52 @@ +import { inkRegistryBase } from "@/registry/bases/ink/registry"; +import { opentuiRegistryBase } from "@/registry/bases/opentui/registry"; + +export interface RegistryBaseDefinition { + dependencies: readonly string[]; + description: string; + examplesDir: string; + isPublic: boolean; + name: string; + publicRegistryDir: string | null; + sourceDir: string; + title: string; + type: "registry:runtime"; +} + +export const BASES = [ + { + ...inkRegistryBase, + dependencies: ["ink", "ink-web"], + description: "React-powered terminal components rendered with Ink.", + isPublic: true, + title: "Ink", + type: "registry:runtime", + }, + { + ...opentuiRegistryBase, + dependencies: ["@opentui/core", "@opentui/react"], + description: + "OpenTUI React components for internal previews and future CLI installs.", + isPublic: false, + title: "OpenTUI", + type: "registry:runtime", + }, +] as const satisfies readonly RegistryBaseDefinition[]; + +export type Base = (typeof BASES)[number]; +export type BaseName = Base["name"]; + +export const BASE_NAMES = BASES.map((base) => base.name) as [ + BaseName, + ...BaseName[], +]; + +export const PUBLIC_BASE = BASES.find((base) => base.isPublic) ?? BASES[0]; +export const PUBLIC_BASE_NAME = PUBLIC_BASE.name; + +export const getBase = (name: BaseName) => + BASES.find((base) => base.name === name); + +export const isPublicBaseName = ( + name: BaseName | undefined +): name is typeof PUBLIC_BASE_NAME => name === PUBLIC_BASE_NAME; diff --git a/registry/bases/README.md b/registry/bases/README.md new file mode 100644 index 0000000..4508c8e --- /dev/null +++ b/registry/bases/README.md @@ -0,0 +1,17 @@ +# Registry Bases + +This folder mirrors the shadcn `registry/bases` layout for Termcn's internal +source trees. + +- `ink/` contains the installable Ink source that powers the public component + and hook registry output. +- `opentui/` contains internal OpenTUI React components for docs previews and + future Termcn CLI support. +- `../themes/` contains the shared theme source used across both bases. + +The public registry stays flat for shadcn directory compatibility. Internal +development should prefer the base trees in this folder. + +The public build now generates a temporary flat registry workspace from +`registry/bases/ink` during `pnpm registry:build`, so the repo itself only needs +to keep the base trees. diff --git a/registry/bases/__index__.ts b/registry/bases/__index__.ts new file mode 100644 index 0000000..48e8d9a --- /dev/null +++ b/registry/bases/__index__.ts @@ -0,0 +1,9 @@ +export { + BASE_NAMES as registryBaseNames, + BASES, + getBase, + PUBLIC_BASE, + PUBLIC_BASE_NAME, + type Base as RegistryBase, + type BaseName as RegistryBaseName, +} from "@/registry/bases"; diff --git a/registry/bases/ink/blocks/.gitkeep b/registry/bases/ink/blocks/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/registry/bases/ink/blocks/.gitkeep @@ -0,0 +1 @@ + diff --git a/registry/bases/ink/components/.gitkeep b/registry/bases/ink/components/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/registry/bases/ink/components/.gitkeep @@ -0,0 +1 @@ + diff --git a/registry/bases/ink/examples/.gitkeep b/registry/bases/ink/examples/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/registry/bases/ink/examples/.gitkeep @@ -0,0 +1 @@ + diff --git a/registry/hooks/use-animation.ts b/registry/bases/ink/hooks/use-animation.ts similarity index 100% rename from registry/hooks/use-animation.ts rename to registry/bases/ink/hooks/use-animation.ts diff --git a/registry/hooks/use-clipboard.ts b/registry/bases/ink/hooks/use-clipboard.ts similarity index 100% rename from registry/hooks/use-clipboard.ts rename to registry/bases/ink/hooks/use-clipboard.ts diff --git a/registry/hooks/use-focus.ts b/registry/bases/ink/hooks/use-focus.ts similarity index 100% rename from registry/hooks/use-focus.ts rename to registry/bases/ink/hooks/use-focus.ts diff --git a/registry/hooks/use-input.ts b/registry/bases/ink/hooks/use-input.ts similarity index 100% rename from registry/hooks/use-input.ts rename to registry/bases/ink/hooks/use-input.ts diff --git a/registry/hooks/use-interval.ts b/registry/bases/ink/hooks/use-interval.ts similarity index 100% rename from registry/hooks/use-interval.ts rename to registry/bases/ink/hooks/use-interval.ts diff --git a/registry/hooks/use-notifications.ts b/registry/bases/ink/hooks/use-notifications.ts similarity index 100% rename from registry/hooks/use-notifications.ts rename to registry/bases/ink/hooks/use-notifications.ts diff --git a/registry/bases/ink/internal/.gitkeep b/registry/bases/ink/internal/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/registry/bases/ink/internal/.gitkeep @@ -0,0 +1 @@ + diff --git a/registry/bases/ink/registry.ts b/registry/bases/ink/registry.ts new file mode 100644 index 0000000..f3f2a93 --- /dev/null +++ b/registry/bases/ink/registry.ts @@ -0,0 +1,6 @@ +export const inkRegistryBase = { + examplesDir: "examples/ink", + name: "ink", + publicRegistryDir: "registry", + sourceDir: "registry/bases/ink", +} as const; diff --git a/registry/ui/alert.tsx b/registry/bases/ink/ui/alert.tsx similarity index 100% rename from registry/ui/alert.tsx rename to registry/bases/ink/ui/alert.tsx diff --git a/registry/ui/app-shell.tsx b/registry/bases/ink/ui/app-shell.tsx similarity index 100% rename from registry/ui/app-shell.tsx rename to registry/bases/ink/ui/app-shell.tsx diff --git a/registry/ui/aspect-ratio.tsx b/registry/bases/ink/ui/aspect-ratio.tsx similarity index 100% rename from registry/ui/aspect-ratio.tsx rename to registry/bases/ink/ui/aspect-ratio.tsx diff --git a/registry/ui/badge.tsx b/registry/bases/ink/ui/badge.tsx similarity index 100% rename from registry/ui/badge.tsx rename to registry/bases/ink/ui/badge.tsx diff --git a/registry/ui/banner.tsx b/registry/bases/ink/ui/banner.tsx similarity index 100% rename from registry/ui/banner.tsx rename to registry/bases/ink/ui/banner.tsx diff --git a/registry/ui/bar-chart.tsx b/registry/bases/ink/ui/bar-chart.tsx similarity index 100% rename from registry/ui/bar-chart.tsx rename to registry/bases/ink/ui/bar-chart.tsx diff --git a/registry/ui/big-text.tsx b/registry/bases/ink/ui/big-text.tsx similarity index 100% rename from registry/ui/big-text.tsx rename to registry/bases/ink/ui/big-text.tsx diff --git a/registry/ui/box.tsx b/registry/bases/ink/ui/box.tsx similarity index 100% rename from registry/ui/box.tsx rename to registry/bases/ink/ui/box.tsx diff --git a/registry/ui/breadcrumb.tsx b/registry/bases/ink/ui/breadcrumb.tsx similarity index 100% rename from registry/ui/breadcrumb.tsx rename to registry/bases/ink/ui/breadcrumb.tsx diff --git a/registry/ui/bullet-list.tsx b/registry/bases/ink/ui/bullet-list.tsx similarity index 100% rename from registry/ui/bullet-list.tsx rename to registry/bases/ink/ui/bullet-list.tsx diff --git a/registry/ui/card.tsx b/registry/bases/ink/ui/card.tsx similarity index 100% rename from registry/ui/card.tsx rename to registry/bases/ink/ui/card.tsx diff --git a/registry/ui/center.tsx b/registry/bases/ink/ui/center.tsx similarity index 100% rename from registry/ui/center.tsx rename to registry/bases/ink/ui/center.tsx diff --git a/registry/ui/chat-message.tsx b/registry/bases/ink/ui/chat-message.tsx similarity index 100% rename from registry/ui/chat-message.tsx rename to registry/bases/ink/ui/chat-message.tsx diff --git a/registry/ui/chat-thread.tsx b/registry/bases/ink/ui/chat-thread.tsx similarity index 100% rename from registry/ui/chat-thread.tsx rename to registry/bases/ink/ui/chat-thread.tsx diff --git a/registry/ui/checkbox-group.tsx b/registry/bases/ink/ui/checkbox-group.tsx similarity index 100% rename from registry/ui/checkbox-group.tsx rename to registry/bases/ink/ui/checkbox-group.tsx diff --git a/registry/ui/checkbox.tsx b/registry/bases/ink/ui/checkbox.tsx similarity index 100% rename from registry/ui/checkbox.tsx rename to registry/bases/ink/ui/checkbox.tsx diff --git a/registry/ui/clipboard.tsx b/registry/bases/ink/ui/clipboard.tsx similarity index 100% rename from registry/ui/clipboard.tsx rename to registry/bases/ink/ui/clipboard.tsx diff --git a/registry/ui/clock.tsx b/registry/bases/ink/ui/clock.tsx similarity index 100% rename from registry/ui/clock.tsx rename to registry/bases/ink/ui/clock.tsx diff --git a/registry/ui/code.tsx b/registry/bases/ink/ui/code.tsx similarity index 100% rename from registry/ui/code.tsx rename to registry/bases/ink/ui/code.tsx diff --git a/registry/ui/color-picker.tsx b/registry/bases/ink/ui/color-picker.tsx similarity index 100% rename from registry/ui/color-picker.tsx rename to registry/bases/ink/ui/color-picker.tsx diff --git a/registry/ui/columns.tsx b/registry/bases/ink/ui/columns.tsx similarity index 100% rename from registry/ui/columns.tsx rename to registry/bases/ink/ui/columns.tsx diff --git a/registry/ui/command-palette.tsx b/registry/bases/ink/ui/command-palette.tsx similarity index 100% rename from registry/ui/command-palette.tsx rename to registry/bases/ink/ui/command-palette.tsx diff --git a/registry/ui/confirm.tsx b/registry/bases/ink/ui/confirm.tsx similarity index 100% rename from registry/ui/confirm.tsx rename to registry/bases/ink/ui/confirm.tsx diff --git a/registry/ui/data-grid.tsx b/registry/bases/ink/ui/data-grid.tsx similarity index 100% rename from registry/ui/data-grid.tsx rename to registry/bases/ink/ui/data-grid.tsx diff --git a/registry/ui/date-picker.tsx b/registry/bases/ink/ui/date-picker.tsx similarity index 100% rename from registry/ui/date-picker.tsx rename to registry/bases/ink/ui/date-picker.tsx diff --git a/registry/ui/definition.tsx b/registry/bases/ink/ui/definition.tsx similarity index 100% rename from registry/ui/definition.tsx rename to registry/bases/ink/ui/definition.tsx diff --git a/registry/ui/dialog.tsx b/registry/bases/ink/ui/dialog.tsx similarity index 100% rename from registry/ui/dialog.tsx rename to registry/bases/ink/ui/dialog.tsx diff --git a/registry/ui/diff-view.tsx b/registry/bases/ink/ui/diff-view.tsx similarity index 100% rename from registry/ui/diff-view.tsx rename to registry/bases/ink/ui/diff-view.tsx diff --git a/registry/ui/digits.tsx b/registry/bases/ink/ui/digits.tsx similarity index 100% rename from registry/ui/digits.tsx rename to registry/bases/ink/ui/digits.tsx diff --git a/registry/ui/directory-tree.tsx b/registry/bases/ink/ui/directory-tree.tsx similarity index 100% rename from registry/ui/directory-tree.tsx rename to registry/bases/ink/ui/directory-tree.tsx diff --git a/registry/ui/divider.tsx b/registry/bases/ink/ui/divider.tsx similarity index 100% rename from registry/ui/divider.tsx rename to registry/bases/ink/ui/divider.tsx diff --git a/registry/ui/drawer.tsx b/registry/bases/ink/ui/drawer.tsx similarity index 100% rename from registry/ui/drawer.tsx rename to registry/bases/ink/ui/drawer.tsx diff --git a/registry/ui/email-input.tsx b/registry/bases/ink/ui/email-input.tsx similarity index 100% rename from registry/ui/email-input.tsx rename to registry/bases/ink/ui/email-input.tsx diff --git a/registry/ui/embedded-terminal.tsx b/registry/bases/ink/ui/embedded-terminal.tsx similarity index 100% rename from registry/ui/embedded-terminal.tsx rename to registry/bases/ink/ui/embedded-terminal.tsx diff --git a/registry/ui/error-boundary.tsx b/registry/bases/ink/ui/error-boundary.tsx similarity index 100% rename from registry/ui/error-boundary.tsx rename to registry/bases/ink/ui/error-boundary.tsx diff --git a/registry/ui/file-change.tsx b/registry/bases/ink/ui/file-change.tsx similarity index 100% rename from registry/ui/file-change.tsx rename to registry/bases/ink/ui/file-change.tsx diff --git a/registry/ui/file-picker.tsx b/registry/bases/ink/ui/file-picker.tsx similarity index 100% rename from registry/ui/file-picker.tsx rename to registry/bases/ink/ui/file-picker.tsx diff --git a/registry/ui/form-field.tsx b/registry/bases/ink/ui/form-field.tsx similarity index 100% rename from registry/ui/form-field.tsx rename to registry/bases/ink/ui/form-field.tsx diff --git a/registry/ui/form.tsx b/registry/bases/ink/ui/form.tsx similarity index 99% rename from registry/ui/form.tsx rename to registry/bases/ink/ui/form.tsx index 057a1bf..fa20631 100644 --- a/registry/ui/form.tsx +++ b/registry/bases/ink/ui/form.tsx @@ -1,3 +1,5 @@ +"use client"; + import { Box, Text } from "ink"; import { useState, diff --git a/registry/ui/gauge.tsx b/registry/bases/ink/ui/gauge.tsx similarity index 100% rename from registry/ui/gauge.tsx rename to registry/bases/ink/ui/gauge.tsx diff --git a/registry/ui/git-status.tsx b/registry/bases/ink/ui/git-status.tsx similarity index 100% rename from registry/ui/git-status.tsx rename to registry/bases/ink/ui/git-status.tsx diff --git a/registry/ui/gradient.tsx b/registry/bases/ink/ui/gradient.tsx similarity index 100% rename from registry/ui/gradient.tsx rename to registry/bases/ink/ui/gradient.tsx diff --git a/registry/ui/grid.tsx b/registry/bases/ink/ui/grid.tsx similarity index 100% rename from registry/ui/grid.tsx rename to registry/bases/ink/ui/grid.tsx diff --git a/registry/ui/heading.tsx b/registry/bases/ink/ui/heading.tsx similarity index 100% rename from registry/ui/heading.tsx rename to registry/bases/ink/ui/heading.tsx diff --git a/registry/ui/heat-map.tsx b/registry/bases/ink/ui/heat-map.tsx similarity index 100% rename from registry/ui/heat-map.tsx rename to registry/bases/ink/ui/heat-map.tsx diff --git a/registry/ui/help-screen.tsx b/registry/bases/ink/ui/help-screen.tsx similarity index 100% rename from registry/ui/help-screen.tsx rename to registry/bases/ink/ui/help-screen.tsx diff --git a/registry/ui/help.tsx b/registry/bases/ink/ui/help.tsx similarity index 100% rename from registry/ui/help.tsx rename to registry/bases/ink/ui/help.tsx diff --git a/registry/ui/image.tsx b/registry/bases/ink/ui/image.tsx similarity index 100% rename from registry/ui/image.tsx rename to registry/bases/ink/ui/image.tsx diff --git a/registry/ui/info-box.tsx b/registry/bases/ink/ui/info-box.tsx similarity index 100% rename from registry/ui/info-box.tsx rename to registry/bases/ink/ui/info-box.tsx diff --git a/registry/ui/json.tsx b/registry/bases/ink/ui/json.tsx similarity index 100% rename from registry/ui/json.tsx rename to registry/bases/ink/ui/json.tsx diff --git a/registry/ui/key-value.tsx b/registry/bases/ink/ui/key-value.tsx similarity index 100% rename from registry/ui/key-value.tsx rename to registry/bases/ink/ui/key-value.tsx diff --git a/registry/ui/keyboard-shortcuts.tsx b/registry/bases/ink/ui/keyboard-shortcuts.tsx similarity index 100% rename from registry/ui/keyboard-shortcuts.tsx rename to registry/bases/ink/ui/keyboard-shortcuts.tsx diff --git a/registry/ui/line-chart.tsx b/registry/bases/ink/ui/line-chart.tsx similarity index 100% rename from registry/ui/line-chart.tsx rename to registry/bases/ink/ui/line-chart.tsx diff --git a/registry/ui/link.tsx b/registry/bases/ink/ui/link.tsx similarity index 100% rename from registry/ui/link.tsx rename to registry/bases/ink/ui/link.tsx diff --git a/registry/ui/list.tsx b/registry/bases/ink/ui/list.tsx similarity index 100% rename from registry/ui/list.tsx rename to registry/bases/ink/ui/list.tsx diff --git a/registry/ui/log.tsx b/registry/bases/ink/ui/log.tsx similarity index 100% rename from registry/ui/log.tsx rename to registry/bases/ink/ui/log.tsx diff --git a/registry/ui/login-flow.tsx b/registry/bases/ink/ui/login-flow.tsx similarity index 100% rename from registry/ui/login-flow.tsx rename to registry/bases/ink/ui/login-flow.tsx diff --git a/registry/ui/markdown.tsx b/registry/bases/ink/ui/markdown.tsx similarity index 100% rename from registry/ui/markdown.tsx rename to registry/bases/ink/ui/markdown.tsx diff --git a/registry/ui/masked-input.tsx b/registry/bases/ink/ui/masked-input.tsx similarity index 100% rename from registry/ui/masked-input.tsx rename to registry/bases/ink/ui/masked-input.tsx diff --git a/registry/ui/menu.tsx b/registry/bases/ink/ui/menu.tsx similarity index 100% rename from registry/ui/menu.tsx rename to registry/bases/ink/ui/menu.tsx diff --git a/registry/ui/modal.tsx b/registry/bases/ink/ui/modal.tsx similarity index 100% rename from registry/ui/modal.tsx rename to registry/bases/ink/ui/modal.tsx diff --git a/registry/ui/model-selector.tsx b/registry/bases/ink/ui/model-selector.tsx similarity index 100% rename from registry/ui/model-selector.tsx rename to registry/bases/ink/ui/model-selector.tsx diff --git a/registry/ui/multi-progress.tsx b/registry/bases/ink/ui/multi-progress.tsx similarity index 100% rename from registry/ui/multi-progress.tsx rename to registry/bases/ink/ui/multi-progress.tsx diff --git a/registry/ui/multi-select.tsx b/registry/bases/ink/ui/multi-select.tsx similarity index 100% rename from registry/ui/multi-select.tsx rename to registry/bases/ink/ui/multi-select.tsx diff --git a/registry/ui/notification-badge.tsx b/registry/bases/ink/ui/notification-badge.tsx similarity index 100% rename from registry/ui/notification-badge.tsx rename to registry/bases/ink/ui/notification-badge.tsx diff --git a/registry/ui/notification-center.tsx b/registry/bases/ink/ui/notification-center.tsx similarity index 100% rename from registry/ui/notification-center.tsx rename to registry/bases/ink/ui/notification-center.tsx diff --git a/registry/ui/number-input.tsx b/registry/bases/ink/ui/number-input.tsx similarity index 100% rename from registry/ui/number-input.tsx rename to registry/bases/ink/ui/number-input.tsx diff --git a/registry/ui/pagination.tsx b/registry/bases/ink/ui/pagination.tsx similarity index 100% rename from registry/ui/pagination.tsx rename to registry/bases/ink/ui/pagination.tsx diff --git a/registry/ui/panel.tsx b/registry/bases/ink/ui/panel.tsx similarity index 100% rename from registry/ui/panel.tsx rename to registry/bases/ink/ui/panel.tsx diff --git a/registry/ui/password-input.tsx b/registry/bases/ink/ui/password-input.tsx similarity index 100% rename from registry/ui/password-input.tsx rename to registry/bases/ink/ui/password-input.tsx diff --git a/registry/ui/path-input.tsx b/registry/bases/ink/ui/path-input.tsx similarity index 100% rename from registry/ui/path-input.tsx rename to registry/bases/ink/ui/path-input.tsx diff --git a/registry/ui/pie-chart.tsx b/registry/bases/ink/ui/pie-chart.tsx similarity index 100% rename from registry/ui/pie-chart.tsx rename to registry/bases/ink/ui/pie-chart.tsx diff --git a/registry/ui/popover.tsx b/registry/bases/ink/ui/popover.tsx similarity index 100% rename from registry/ui/popover.tsx rename to registry/bases/ink/ui/popover.tsx diff --git a/registry/ui/progress-bar.tsx b/registry/bases/ink/ui/progress-bar.tsx similarity index 100% rename from registry/ui/progress-bar.tsx rename to registry/bases/ink/ui/progress-bar.tsx diff --git a/registry/ui/progress-circle.tsx b/registry/bases/ink/ui/progress-circle.tsx similarity index 100% rename from registry/ui/progress-circle.tsx rename to registry/bases/ink/ui/progress-circle.tsx diff --git a/registry/ui/qr-code.tsx b/registry/bases/ink/ui/qr-code.tsx similarity index 100% rename from registry/ui/qr-code.tsx rename to registry/bases/ink/ui/qr-code.tsx diff --git a/registry/ui/radio-group.tsx b/registry/bases/ink/ui/radio-group.tsx similarity index 100% rename from registry/ui/radio-group.tsx rename to registry/bases/ink/ui/radio-group.tsx diff --git a/registry/ui/scroll-view.tsx b/registry/bases/ink/ui/scroll-view.tsx similarity index 100% rename from registry/ui/scroll-view.tsx rename to registry/bases/ink/ui/scroll-view.tsx diff --git a/registry/ui/search-input.tsx b/registry/bases/ink/ui/search-input.tsx similarity index 100% rename from registry/ui/search-input.tsx rename to registry/bases/ink/ui/search-input.tsx diff --git a/registry/ui/select.tsx b/registry/bases/ink/ui/select.tsx similarity index 100% rename from registry/ui/select.tsx rename to registry/bases/ink/ui/select.tsx diff --git a/registry/ui/setup-flow.tsx b/registry/bases/ink/ui/setup-flow.tsx similarity index 100% rename from registry/ui/setup-flow.tsx rename to registry/bases/ink/ui/setup-flow.tsx diff --git a/registry/ui/sidebar.tsx b/registry/bases/ink/ui/sidebar.tsx similarity index 100% rename from registry/ui/sidebar.tsx rename to registry/bases/ink/ui/sidebar.tsx diff --git a/registry/ui/skeleton.tsx b/registry/bases/ink/ui/skeleton.tsx similarity index 100% rename from registry/ui/skeleton.tsx rename to registry/bases/ink/ui/skeleton.tsx diff --git a/registry/ui/spacer.tsx b/registry/bases/ink/ui/spacer.tsx similarity index 100% rename from registry/ui/spacer.tsx rename to registry/bases/ink/ui/spacer.tsx diff --git a/registry/ui/sparkline.tsx b/registry/bases/ink/ui/sparkline.tsx similarity index 100% rename from registry/ui/sparkline.tsx rename to registry/bases/ink/ui/sparkline.tsx diff --git a/registry/ui/spinner.tsx b/registry/bases/ink/ui/spinner.tsx similarity index 100% rename from registry/ui/spinner.tsx rename to registry/bases/ink/ui/spinner.tsx diff --git a/registry/ui/splash-screen.tsx b/registry/bases/ink/ui/splash-screen.tsx similarity index 100% rename from registry/ui/splash-screen.tsx rename to registry/bases/ink/ui/splash-screen.tsx diff --git a/registry/ui/stack.tsx b/registry/bases/ink/ui/stack.tsx similarity index 100% rename from registry/ui/stack.tsx rename to registry/bases/ink/ui/stack.tsx diff --git a/registry/ui/status-message.tsx b/registry/bases/ink/ui/status-message.tsx similarity index 100% rename from registry/ui/status-message.tsx rename to registry/bases/ink/ui/status-message.tsx diff --git a/registry/ui/stopwatch.tsx b/registry/bases/ink/ui/stopwatch.tsx similarity index 100% rename from registry/ui/stopwatch.tsx rename to registry/bases/ink/ui/stopwatch.tsx diff --git a/registry/ui/streaming-text.tsx b/registry/bases/ink/ui/streaming-text.tsx similarity index 100% rename from registry/ui/streaming-text.tsx rename to registry/bases/ink/ui/streaming-text.tsx diff --git a/registry/ui/tabbed-content.tsx b/registry/bases/ink/ui/tabbed-content.tsx similarity index 100% rename from registry/ui/tabbed-content.tsx rename to registry/bases/ink/ui/tabbed-content.tsx diff --git a/registry/ui/table.tsx b/registry/bases/ink/ui/table.tsx similarity index 100% rename from registry/ui/table.tsx rename to registry/bases/ink/ui/table.tsx diff --git a/registry/ui/tabs.tsx b/registry/bases/ink/ui/tabs.tsx similarity index 100% rename from registry/ui/tabs.tsx rename to registry/bases/ink/ui/tabs.tsx diff --git a/registry/ui/tag-input.tsx b/registry/bases/ink/ui/tag-input.tsx similarity index 100% rename from registry/ui/tag-input.tsx rename to registry/bases/ink/ui/tag-input.tsx diff --git a/registry/ui/tag.tsx b/registry/bases/ink/ui/tag.tsx similarity index 100% rename from registry/ui/tag.tsx rename to registry/bases/ink/ui/tag.tsx diff --git a/registry/ui/text-area.tsx b/registry/bases/ink/ui/text-area.tsx similarity index 100% rename from registry/ui/text-area.tsx rename to registry/bases/ink/ui/text-area.tsx diff --git a/registry/ui/text-input.tsx b/registry/bases/ink/ui/text-input.tsx similarity index 100% rename from registry/ui/text-input.tsx rename to registry/bases/ink/ui/text-input.tsx diff --git a/registry/ui/theme-provider.tsx b/registry/bases/ink/ui/theme-provider.tsx similarity index 100% rename from registry/ui/theme-provider.tsx rename to registry/bases/ink/ui/theme-provider.tsx diff --git a/registry/ui/thinking-block.tsx b/registry/bases/ink/ui/thinking-block.tsx similarity index 100% rename from registry/ui/thinking-block.tsx rename to registry/bases/ink/ui/thinking-block.tsx diff --git a/registry/ui/time-picker.tsx b/registry/bases/ink/ui/time-picker.tsx similarity index 100% rename from registry/ui/time-picker.tsx rename to registry/bases/ink/ui/time-picker.tsx diff --git a/registry/ui/timer.tsx b/registry/bases/ink/ui/timer.tsx similarity index 100% rename from registry/ui/timer.tsx rename to registry/bases/ink/ui/timer.tsx diff --git a/registry/ui/toast.tsx b/registry/bases/ink/ui/toast.tsx similarity index 100% rename from registry/ui/toast.tsx rename to registry/bases/ink/ui/toast.tsx diff --git a/registry/ui/toggle.tsx b/registry/bases/ink/ui/toggle.tsx similarity index 100% rename from registry/ui/toggle.tsx rename to registry/bases/ink/ui/toggle.tsx diff --git a/registry/ui/token-usage.tsx b/registry/bases/ink/ui/token-usage.tsx similarity index 100% rename from registry/ui/token-usage.tsx rename to registry/bases/ink/ui/token-usage.tsx diff --git a/registry/ui/tool-approval.tsx b/registry/bases/ink/ui/tool-approval.tsx similarity index 100% rename from registry/ui/tool-approval.tsx rename to registry/bases/ink/ui/tool-approval.tsx diff --git a/registry/ui/tool-call.tsx b/registry/bases/ink/ui/tool-call.tsx similarity index 100% rename from registry/ui/tool-call.tsx rename to registry/bases/ink/ui/tool-call.tsx diff --git a/registry/ui/tooltip.tsx b/registry/bases/ink/ui/tooltip.tsx similarity index 100% rename from registry/ui/tooltip.tsx rename to registry/bases/ink/ui/tooltip.tsx diff --git a/registry/ui/tree-select.tsx b/registry/bases/ink/ui/tree-select.tsx similarity index 100% rename from registry/ui/tree-select.tsx rename to registry/bases/ink/ui/tree-select.tsx diff --git a/registry/ui/tree.tsx b/registry/bases/ink/ui/tree.tsx similarity index 100% rename from registry/ui/tree.tsx rename to registry/bases/ink/ui/tree.tsx diff --git a/registry/ui/usage-monitor.tsx b/registry/bases/ink/ui/usage-monitor.tsx similarity index 100% rename from registry/ui/usage-monitor.tsx rename to registry/bases/ink/ui/usage-monitor.tsx diff --git a/registry/ui/virtual-list.tsx b/registry/bases/ink/ui/virtual-list.tsx similarity index 100% rename from registry/ui/virtual-list.tsx rename to registry/bases/ink/ui/virtual-list.tsx diff --git a/registry/ui/welcome-screen.tsx b/registry/bases/ink/ui/welcome-screen.tsx similarity index 100% rename from registry/ui/welcome-screen.tsx rename to registry/bases/ink/ui/welcome-screen.tsx diff --git a/registry/ui/wizard.tsx b/registry/bases/ink/ui/wizard.tsx similarity index 100% rename from registry/ui/wizard.tsx rename to registry/bases/ink/ui/wizard.tsx diff --git a/registry/bases/opentui/blocks/.gitkeep b/registry/bases/opentui/blocks/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/registry/bases/opentui/blocks/.gitkeep @@ -0,0 +1 @@ + diff --git a/registry/bases/opentui/components/.gitkeep b/registry/bases/opentui/components/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/registry/bases/opentui/components/.gitkeep @@ -0,0 +1 @@ + diff --git a/registry/bases/opentui/examples/.gitkeep b/registry/bases/opentui/examples/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/registry/bases/opentui/examples/.gitkeep @@ -0,0 +1 @@ + diff --git a/registry/bases/opentui/hooks/.gitkeep b/registry/bases/opentui/hooks/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/registry/bases/opentui/hooks/.gitkeep @@ -0,0 +1 @@ + diff --git a/registry/bases/opentui/internal/.gitkeep b/registry/bases/opentui/internal/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/registry/bases/opentui/internal/.gitkeep @@ -0,0 +1 @@ + diff --git a/registry/bases/opentui/lib/.gitkeep b/registry/bases/opentui/lib/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/registry/bases/opentui/lib/.gitkeep @@ -0,0 +1 @@ + diff --git a/registry/bases/opentui/registry.ts b/registry/bases/opentui/registry.ts new file mode 100644 index 0000000..89350a7 --- /dev/null +++ b/registry/bases/opentui/registry.ts @@ -0,0 +1,6 @@ +export const opentuiRegistryBase = { + examplesDir: "examples/opentui", + name: "opentui", + publicRegistryDir: null, + sourceDir: "registry/bases/opentui", +} as const; diff --git a/registry/bases/opentui/ui/spinner.tsx b/registry/bases/opentui/ui/spinner.tsx new file mode 100644 index 0000000..7f77ee0 --- /dev/null +++ b/registry/bases/opentui/ui/spinner.tsx @@ -0,0 +1,124 @@ +import { createElement, useEffect, useState } from "react"; + +const BUILTIN_SPINNERS = { + arc: { + frames: ["◜", "◠", "◝", "◞", "◡", "◟"], + interval: 80, + }, + bouncingBall: { + frames: [ + "( ● )", + "( ● )", + "( ● )", + "( ● )", + "( ●)", + "( ● )", + "( ● )", + "( ● )", + ], + interval: 90, + }, + dots: { + frames: ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"], + interval: 80, + }, + line: { + frames: ["-", "\\", "|", "/"], + interval: 130, + }, +} as const; + +export type SpinnerName = keyof typeof BUILTIN_SPINNERS; + +export interface SpinnerOptions { + autoplay?: boolean; + backgroundColor?: string; + color?: string; + frames?: string[]; + interval?: number; + name?: SpinnerName; +} + +export interface SpinnerProps extends SpinnerOptions { + label?: string; +} + +export interface ResolvedSpinner { + autoplay: boolean; + backgroundColor?: string; + color: string; + frames: string[]; + interval: number; +} + +export const spinnerNames = Object.keys(BUILTIN_SPINNERS) as SpinnerName[]; + +export const resolveSpinner = ({ + autoplay = true, + backgroundColor, + color = "white", + frames, + interval, + name = "dots", +}: SpinnerOptions = {}): ResolvedSpinner => { + const builtin = BUILTIN_SPINNERS[name]; + + return { + autoplay, + backgroundColor, + color, + frames: frames ?? [...builtin.frames], + interval: interval ?? builtin.interval, + }; +}; + +export const Spinner = ({ + autoplay, + backgroundColor, + color, + frames, + interval, + label, + name, +}: SpinnerProps) => { + const resolved = resolveSpinner({ + autoplay, + backgroundColor, + color, + frames, + interval, + name, + }); + const [frameIndex, setFrameIndex] = useState(0); + + useEffect(() => { + setFrameIndex(0); + }, [resolved.frames]); + + useEffect(() => { + if (!resolved.autoplay || resolved.frames.length <= 1) { + return; + } + + const timer = setInterval(() => { + setFrameIndex((current) => (current + 1) % resolved.frames.length); + }, resolved.interval); + + return () => { + clearInterval(timer); + }; + }, [resolved.autoplay, resolved.frames, resolved.interval]); + + const frame = resolved.frames[frameIndex % resolved.frames.length]; + + return createElement( + "box", + { alignItems: "center", flexDirection: "row" }, + createElement( + "text", + { bg: resolved.backgroundColor, fg: resolved.color }, + frame + ), + label ? createElement("text", { marginLeft: 1 }, label) : null + ); +}; diff --git a/registry/config.ts b/registry/config.ts new file mode 100644 index 0000000..80bf309 --- /dev/null +++ b/registry/config.ts @@ -0,0 +1,52 @@ +import { z } from "zod"; + +import { + BASE_NAMES, + BASES, + getBase, + PUBLIC_BASE, + PUBLIC_BASE_NAME, +} from "@/registry/bases"; +import type { Base, BaseName } from "@/registry/bases"; +import { + getTheme, + getThemesForBase, + THEMES, + THEME_NAMES, +} from "@/registry/themes"; +import type { RegistryTheme, RegistryThemeName } from "@/registry/themes"; + +export { BASES, type Base, type BaseName, PUBLIC_BASE, PUBLIC_BASE_NAME }; +export { THEMES, type RegistryTheme, type RegistryThemeName }; + +export const registryConfigSchema = z.object({ + base: z.enum(BASE_NAMES).default(PUBLIC_BASE_NAME), + theme: z.enum(THEME_NAMES).default("default"), +}); + +export type RegistryConfig = z.infer; + +export const DEFAULT_REGISTRY_CONFIG: RegistryConfig = { + base: PUBLIC_BASE_NAME, + theme: "default", +}; + +export const isThemeAvailableForBase = ( + base: BaseName, + theme: RegistryThemeName +) => getThemesForBase(base).some((entry) => entry.name === theme); + +export const getRegistryConfig = (config?: Partial) => { + const resolved = registryConfigSchema.parse(config ?? {}); + + if (!isThemeAvailableForBase(resolved.base, resolved.theme)) { + return { + ...resolved, + theme: DEFAULT_REGISTRY_CONFIG.theme, + }; + } + + return resolved; +}; + +export { getBase, getTheme, getThemesForBase }; diff --git a/registry/themes.ts b/registry/themes.ts new file mode 100644 index 0000000..566ea2b --- /dev/null +++ b/registry/themes.ts @@ -0,0 +1,135 @@ +import type { Theme as TerminalTheme } from "@/components/ui/theme-provider"; +import type { BaseName } from "@/registry/bases"; +import { catppuccinTheme } from "@/registry/themes/catppuccin"; +import { defaultTheme } from "@/registry/themes/default"; +import { draculaTheme } from "@/registry/themes/dracula"; +import { + highContrastLightTheme, + highContrastTheme, +} from "@/registry/themes/high-contrast"; +import { monokaiTheme } from "@/registry/themes/monokai"; +import { nordTheme } from "@/registry/themes/nord"; +import { oneDarkTheme } from "@/registry/themes/one-dark"; +import { solarizedTheme } from "@/registry/themes/solarized"; +import { tokyoNightTheme } from "@/registry/themes/tokyo-night"; + +const SHARED_BASES = ["ink", "opentui"] as const satisfies readonly BaseName[]; + +export interface RegistryThemeDefinition { + bases: readonly BaseName[]; + description: string; + name: string; + theme: TerminalTheme; + title: string; + type: "registry:theme"; +} + +export const THEMES = [ + { + bases: SHARED_BASES, + description: "The default Termcn dark theme.", + name: "default", + theme: defaultTheme, + title: "Default", + type: "registry:theme", + }, + { + bases: SHARED_BASES, + description: "A soft pastel Catppuccin palette for terminal UIs.", + name: "catppuccin", + theme: catppuccinTheme, + title: "Catppuccin", + type: "registry:theme", + }, + { + bases: SHARED_BASES, + description: "Dracula-inspired purple-forward theme.", + name: "dracula", + theme: draculaTheme, + title: "Dracula", + type: "registry:theme", + }, + { + bases: SHARED_BASES, + description: "WCAG-friendly dark high-contrast theme.", + name: "high-contrast", + theme: highContrastTheme, + title: "High Contrast", + type: "registry:theme", + }, + { + bases: SHARED_BASES, + description: "WCAG-friendly light high-contrast theme.", + name: "high-contrast-light", + theme: highContrastLightTheme, + title: "High Contrast Light", + type: "registry:theme", + }, + { + bases: SHARED_BASES, + description: "Classic Monokai-inspired editor palette.", + name: "monokai", + theme: monokaiTheme, + title: "Monokai", + type: "registry:theme", + }, + { + bases: SHARED_BASES, + description: "Nord-inspired cool blue-gray palette.", + name: "nord", + theme: nordTheme, + title: "Nord", + type: "registry:theme", + }, + { + bases: SHARED_BASES, + description: "One Dark-inspired terminal theme.", + name: "one-dark", + theme: oneDarkTheme, + title: "One Dark", + type: "registry:theme", + }, + { + bases: SHARED_BASES, + description: "Solarized-inspired balanced low-contrast theme.", + name: "solarized", + theme: solarizedTheme, + title: "Solarized", + type: "registry:theme", + }, + { + bases: SHARED_BASES, + description: "Tokyo Night-inspired deep blue palette.", + name: "tokyo-night", + theme: tokyoNightTheme, + title: "Tokyo Night", + type: "registry:theme", + }, +] as const satisfies readonly RegistryThemeDefinition[]; + +export type RegistryTheme = (typeof THEMES)[number]; +export type RegistryThemeName = RegistryTheme["name"]; + +export const THEME_NAMES = THEMES.map((theme) => theme.name) as [ + RegistryThemeName, + ...RegistryThemeName[], +]; + +export const TERMINAL_THEME_MAP = Object.fromEntries( + THEMES.map((theme) => [theme.name, theme.theme]) +) as Record; + +export const TERMINAL_THEME_OPTIONS = THEMES.map((theme) => ({ + label: theme.title, + value: theme.name, +})); + +export const THEME_PRIMARY_BY_NAME: Record = Object.fromEntries( + THEMES.map((theme) => [theme.name, theme.theme.colors.primary]) +); + +export const getTheme = (name: RegistryThemeName) => + THEMES.find((theme) => theme.name === name); + +export const getThemesForBase = (base: BaseName) => + THEMES.filter((theme) => theme.bases.includes(base)); diff --git a/scripts/build-examples.mts b/scripts/build-examples.mts new file mode 100644 index 0000000..6bb041f --- /dev/null +++ b/scripts/build-examples.mts @@ -0,0 +1,103 @@ +import { promises as fs } from "node:fs"; +import path from "node:path"; + +const root = process.cwd(); +const examplesDir = path.join(root, "examples"); +const outputFile = path.join(examplesDir, "__index__.ts"); +const frameworks = ["ink", "opentui"]; + +const toPosixPath = (value: string) => value.split(path.sep).join("/"); + +const listExamples = async (framework: string) => { + const frameworkDir = path.join(examplesDir, framework); + + try { + const entries = await fs.readdir(frameworkDir, { withFileTypes: true }); + + const names = entries + .filter((entry) => entry.isFile() && entry.name.endsWith(".tsx")) + .map((entry) => entry.name.replace(/\.tsx$/, "")); + + return [...names].toSorted((a, b) => a.localeCompare(b)); + } catch (error) { + if ( + error && + typeof error === "object" && + "code" in error && + error.code === "ENOENT" + ) { + return []; + } + + throw error; + } +}; + +const buildExampleEntry = (framework: string, name: string) => { + const importPath = `./${framework}/${name}`; + const filePath = toPosixPath(path.join("examples", framework, `${name}.tsx`)); + + return ` ${JSON.stringify(name)}: { + component: React.lazy(async () => { + const mod = await import(${JSON.stringify(importPath)}); + + return { default: resolveExampleComponent(mod) }; + }), + filePath: ${JSON.stringify(filePath)}, + name: ${JSON.stringify(name)}, + },`; +}; + +const buildFile = async () => { + const records = await Promise.all( + frameworks.map( + async (framework) => [framework, await listExamples(framework)] as const + ) + ); + + const content = `// This file is autogenerated by scripts/build-examples.mts +// Do not edit this file directly. +import * as React from "react"; + +export type ExampleFramework = "ink" | "opentui"; +type ExampleComponent = React.ComponentType; +type ExampleModule = { + default?: ExampleComponent; +} & Record; + +export interface ExampleEntry { + component: React.LazyExoticComponent; + filePath: string; + name: string; +} + +const isExampleComponent = (value: unknown): value is ExampleComponent => + typeof value === "function"; + +const MissingExampleExport: ExampleComponent = () => null; + +const resolveExampleComponent = (mod: ExampleModule): ExampleComponent => { + if (isExampleComponent(mod.default)) { + return mod.default; + } + + const namedExport = Object.values(mod).find(isExampleComponent); + + return namedExport ?? MissingExampleExport; +}; + +export const ExamplesIndex: Record> = { +${records + .map( + ([framework, names]) => ` ${framework}: { +${names.map((name) => buildExampleEntry(framework, name)).join("\n")} + },` + ) + .join("\n")} +}; +`; + + await fs.writeFile(outputFile, `${content.trim()}\n`); +}; + +await buildFile(); diff --git a/scripts/build-registry.mts b/scripts/build-registry.mts new file mode 100644 index 0000000..9dc264e --- /dev/null +++ b/scripts/build-registry.mts @@ -0,0 +1,88 @@ +import { spawnSync } from "node:child_process"; +import { promises as fs } from "node:fs"; +import os from "node:os"; +import path from "node:path"; + +const root = process.cwd(); + +const syncTargets = [ + { + from: path.join(root, "registry", "bases", "ink", "ui"), + to: "ui", + }, + { + from: path.join(root, "registry", "bases", "ink", "hooks"), + to: "hooks", + }, + { + from: path.join(root, "registry", "themes"), + to: "themes", + }, +] as const; + +const ensureDir = async (dir: string) => { + await fs.mkdir(dir, { recursive: true }); +}; + +const copyDirContents = async (from: string, to: string) => { + await ensureDir(to); + + const entries = await fs.readdir(from, { withFileTypes: true }); + + await Promise.all( + entries + .filter((entry) => entry.isFile()) + .map((entry) => + fs.copyFile(path.join(from, entry.name), path.join(to, entry.name)) + ) + ); +}; + +const runShadcnBuild = (cwd: string) => { + const shadcnBin = path.join( + root, + "node_modules", + ".bin", + process.platform === "win32" ? "shadcn.cmd" : "shadcn" + ); + + const result = spawnSync( + shadcnBin, + ["build", "registry.json", "--output", path.join(root, "public", "r")], + { + cwd, + stdio: "inherit", + } + ); + + if (result.error) { + throw result.error; + } + + if (result.status !== 0) { + throw new Error( + `shadcn build failed with exit code ${result.status ?? -1}` + ); + } +}; + +const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "termcn-registry-")); + +try { + const tempRegistryRoot = path.join(tempRoot, "registry"); + + await fs.copyFile( + path.join(root, "registry.json"), + path.join(tempRoot, "registry.json") + ); + + await Promise.all( + syncTargets.map(({ from, to }) => + copyDirContents(from, path.join(tempRegistryRoot, to)) + ) + ); + + runShadcnBuild(tempRoot); +} finally { + await fs.rm(tempRoot, { force: true, recursive: true }); +} diff --git a/tsconfig.json b/tsconfig.json index cfca22f..23030fd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -22,6 +22,8 @@ "baseUrl": ".", "paths": { "@/*": ["./*"], + "@opentui/core": ["./types/opentui-core.d.ts"], + "@opentui/react": ["./types/opentui-react.d.ts"], "react": ["./node_modules/@types/react"] } }, @@ -29,6 +31,7 @@ "next-env.d.ts", "**/*.ts", "**/*.tsx", + "**/*.d.ts", ".next/types/**/*.ts", "scripts/build-registry.mts", "next.config.mjs", diff --git a/types/opentui-core.d.ts b/types/opentui-core.d.ts new file mode 100644 index 0000000..dd65187 --- /dev/null +++ b/types/opentui-core.d.ts @@ -0,0 +1,41 @@ +declare module "@opentui/core" { + export interface CliRendererOptions { + exitOnCtrlC?: boolean; + } + + export interface BoxRenderableOptions { + alignItems?: string; + border?: boolean; + flexDirection?: string; + } + + export interface TextRenderableOptions { + content: string; + fg?: string; + marginLeft?: number; + } + + export interface CliRenderer { + root: { + add(node: unknown): void; + }; + } + + export interface BoxRenderableInstance { + add(child: unknown): void; + } + + export const BoxRenderable: new ( + renderer: unknown, + options?: BoxRenderableOptions + ) => BoxRenderableInstance; + + export const TextRenderable: new ( + renderer: unknown, + options: TextRenderableOptions + ) => unknown; + + export function createCliRenderer( + options?: CliRendererOptions + ): Promise; +} diff --git a/types/opentui-react.d.ts b/types/opentui-react.d.ts new file mode 100644 index 0000000..8b991b9 --- /dev/null +++ b/types/opentui-react.d.ts @@ -0,0 +1,7 @@ +declare module "@opentui/react" { + import type { ReactNode } from "react"; + + export function createRoot(renderer: unknown): { + render(node: ReactNode): void; + }; +} From e6dc24d1a5bf83ca6cf371493c550c0d66191407 Mon Sep 17 00:00:00 2001 From: Aniket-508 Date: Wed, 8 Apr 2026 16:11:04 +0530 Subject: [PATCH 02/23] refactor: simplify MDX component structure by removing unnecessary framework checks and updating imports; introduce TerminalPreview component for enhanced terminal rendering --- app/(app)/docs/[[...slug]]/page.tsx | 3 +- components/component-preview-tabs.tsx | 42 +++++++++----- components/component-preview.tsx | 57 +++++-------------- components/terminal-preview.tsx | 44 ++++++++++++++ examples/__index__.ts | 4 +- examples/{ => ink}/theme-showcase.tsx | 2 - examples/opentui/spinner-demo.tsx | 21 +++---- examples/opentui/spinner-react.ts | 15 ----- lib/page-tree.ts | 11 ---- lib/read-file.ts | 7 +++ mdx-components.tsx | 34 ++--------- registry/bases.ts | 20 +++---- registry/bases/ink/ui/form.tsx | 2 - .../opentui/{ui => components}/spinner.tsx | 0 registry/config.ts | 10 +--- 15 files changed, 114 insertions(+), 158 deletions(-) create mode 100644 components/terminal-preview.tsx rename examples/{ => ink}/theme-showcase.tsx (98%) delete mode 100644 examples/opentui/spinner-react.ts create mode 100644 lib/read-file.ts rename registry/bases/opentui/{ui => components}/spinner.tsx (100%) diff --git a/app/(app)/docs/[[...slug]]/page.tsx b/app/(app)/docs/[[...slug]]/page.tsx index 5221ea3..2f58a73 100644 --- a/app/(app)/docs/[[...slug]]/page.tsx +++ b/app/(app)/docs/[[...slug]]/page.tsx @@ -22,7 +22,7 @@ import type { ExampleFramework } from "@/lib/examples"; import { PUBLIC_REGISTRY_FRAMEWORK } from "@/lib/registry"; import { getPageImage, source } from "@/lib/source"; import { absoluteUrl } from "@/lib/utils"; -import { createMdxComponents } from "@/mdx-components"; +import { mdxComponents } from "@/mdx-components"; import { BreadcrumbJsonLd } from "@/seo/json-ld"; import { createPageMetadata } from "@/seo/metadata"; @@ -183,7 +183,6 @@ const Page = async (props: { params: Promise<{ slug?: string[] }> }) => { const { links } = doc as { links?: { doc?: string; api?: string } }; const breadcrumbs = buildBreadcrumbs(canonicalSlug, doc.title, pageUrl); - const mdxComponents = createMdxComponents(framework); return ( <> diff --git a/components/component-preview-tabs.tsx b/components/component-preview-tabs.tsx index ccce9fe..7db3007 100644 --- a/components/component-preview-tabs.tsx +++ b/components/component-preview-tabs.tsx @@ -3,6 +3,7 @@ import Link from "next/link"; import { formatTitleFromSlug, getDocsRoute } from "@/lib/docs"; import type { ExampleFramework } from "@/lib/examples"; import { cn } from "@/lib/utils"; +import { getBase } from "@/registry/bases"; export const ComponentPreviewTabs = ({ className, @@ -14,17 +15,30 @@ export const ComponentPreviewTabs = ({ framework: ExampleFramework; frameworks: readonly ExampleFramework[]; slug: string[]; -}) => ( -
    - {frameworks.map((item) => ( - - {formatTitleFromSlug(item)} - - ))} -
    -); +}) => { + const activeBase = getBase(framework); + + return ( +
    + {frameworks.map((item) => ( + + {formatTitleFromSlug(item)} + + ))} + {activeBase?.meta?.logo && ( +
    + )} +
    + ); +}; diff --git a/components/component-preview.tsx b/components/component-preview.tsx index 4238d9f..ea5b9f3 100644 --- a/components/component-preview.tsx +++ b/components/component-preview.tsx @@ -1,62 +1,31 @@ -"use client"; - -import { createDynamicTerminal } from "ink-web/next"; - import { ComponentSource } from "@/components/component-source"; -import { ExamplePreview } from "@/components/example-preview"; -// import { OpenTuiPreview } from "@/components/opentui-preview"; -import type { ExampleFramework } from "@/lib/examples"; -import type { terminalThemeMap } from "@/lib/terminal-themes"; +import type { TerminalPreviewProps } from "@/components/terminal-preview"; +import { TerminalPreview } from "@/components/terminal-preview"; +import { TerminalTheme } from "@/components/terminal-theme"; import { cn } from "@/lib/utils"; -import type { InkPreviewProps } from "./ink-preview"; import { MacWindow } from "./mac-window"; -import { TerminalTheme } from "./terminal-theme"; - -const InkPreview = createDynamicTerminal( - async () => { - const m = await import("./ink-preview"); - return m.default; - }, - { - loading: "spinner", - } -); export const ComponentPreview = ({ framework = "ink", name, - title, + title = "Terminal", className, hideCode = false, theme, -}: { - name: string; - title: string; +}: TerminalPreviewProps & { + title?: string; className?: string; - framework?: ExampleFramework; hideCode?: boolean; - theme?: keyof typeof terminalThemeMap; -}) => { - const preview = - framework === "opentui" ? ( - // - - ) : ( - // - - - - ); - - return ( +}) => ( + <> } > - {preview} - {!hideCode && } + - ); -}; + {!hideCode && } + +); diff --git a/components/terminal-preview.tsx b/components/terminal-preview.tsx new file mode 100644 index 0000000..7010301 --- /dev/null +++ b/components/terminal-preview.tsx @@ -0,0 +1,44 @@ +"use client"; + +import { createDynamicTerminal } from "ink-web/next"; + +import { ExamplePreview } from "@/components/example-preview"; +import type { InkPreviewProps } from "@/components/ink-preview"; +import type { ExampleFramework } from "@/lib/examples"; +import type { terminalThemeMap } from "@/lib/terminal-themes"; + +const InkPreview = createDynamicTerminal( + async () => { + const m = await import("./ink-preview"); + return m.default; + }, + { + loading: "spinner", + } +); + +export interface TerminalPreviewProps { + framework: ExampleFramework; + name: string; + theme?: keyof typeof terminalThemeMap; +} + +export const TerminalPreview = ({ + framework, + name, + theme, +}: TerminalPreviewProps) => { + if (framework === "opentui") { + return ( + // + + // + ); + } + + return ( + + + + ); +}; diff --git a/examples/__index__.ts b/examples/__index__.ts index 582b612..8b87879 100644 --- a/examples/__index__.ts +++ b/examples/__index__.ts @@ -1152,11 +1152,11 @@ export const ExamplesIndex: Record< }, "theme-showcase": { component: React.lazy(async () => { - const mod = await import("./theme-showcase"); + const mod = await import("./ink/theme-showcase"); return { default: resolveExampleComponent(mod) }; }), - filePath: "examples/theme-showcase.tsx", + filePath: "examples/ink/theme-showcase.tsx", name: "theme-showcase", }, "thinking-block-demo": { diff --git a/examples/theme-showcase.tsx b/examples/ink/theme-showcase.tsx similarity index 98% rename from examples/theme-showcase.tsx rename to examples/ink/theme-showcase.tsx index a465eea..9ba15d2 100644 --- a/examples/theme-showcase.tsx +++ b/examples/ink/theme-showcase.tsx @@ -1,5 +1,3 @@ -"use client"; - import { Box, Text } from "ink"; import { useTheme } from "@/components/ui/theme-provider"; diff --git a/examples/opentui/spinner-demo.tsx b/examples/opentui/spinner-demo.tsx index 0896e68..8e7c153 100644 --- a/examples/opentui/spinner-demo.tsx +++ b/examples/opentui/spinner-demo.tsx @@ -1,17 +1,10 @@ -import { OpenTuiPreview } from "@/components/opentui-preview"; -import { resolveSpinner } from "@/registry/bases/opentui/ui/spinner"; - -const loadingFrames = resolveSpinner({ - color: "cyan", - name: "dots", -}).frames.map((frame) => `${frame} Loading components...\n`); - -const buildFrames = resolveSpinner({ color: "yellow", name: "arc" }).frames.map( - (frame) => `${frame} Building registry...\n` -); - -const FRAMES = [...loadingFrames, "", ...buildFrames].map((line) => `${line}`); +import { Spinner } from "@/registry/bases/opentui/components/spinner"; export default function OpenTuiSpinnerDemo() { - return ; + return ( + <> + + + + ); } diff --git a/examples/opentui/spinner-react.ts b/examples/opentui/spinner-react.ts deleted file mode 100644 index 0a9f615..0000000 --- a/examples/opentui/spinner-react.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { createCliRenderer } from "@opentui/core"; -import { createRoot } from "@opentui/react"; -import { createElement } from "react"; - -import { Spinner } from "@/registry/bases/opentui/ui/spinner"; - -const renderer = await createCliRenderer({ exitOnCtrlC: true }); - -createRoot(renderer).render( - createElement(Spinner, { - color: "cyan", - label: "Loading...", - name: "bouncingBall", - }) -); diff --git a/lib/page-tree.ts b/lib/page-tree.ts index bf4272e..7c012ab 100644 --- a/lib/page-tree.ts +++ b/lib/page-tree.ts @@ -1,8 +1,5 @@ import type { Node as PageTreeNode } from "fumadocs-core/page-tree"; -import { DEFAULT_DOCS_FRAMEWORK, isDocsFramework } from "@/lib/docs"; -import type { ExampleFramework } from "@/lib/examples"; - export type PageTreeFolder = Extract; export type PageTreePage = Extract; @@ -19,11 +16,3 @@ export const getPagesFromFolder = (folder: PageTreeFolder): PageTreePage[] => { return pages; }; - -export const getCurrentFramework = (pathname: string): ExampleFramework => { - const frameworkMatch = pathname.match(/\/docs\/components\/(ink|opentui)\//); - - return frameworkMatch && isDocsFramework(frameworkMatch[1]) - ? frameworkMatch[1] - : DEFAULT_DOCS_FRAMEWORK; -}; diff --git a/lib/read-file.ts b/lib/read-file.ts new file mode 100644 index 0000000..c2ec8f1 --- /dev/null +++ b/lib/read-file.ts @@ -0,0 +1,7 @@ +import { promises as fs } from "node:fs"; +import path from "node:path"; + +export const readFileFromRoot = (relativePath: string) => { + const absolutePath = path.join(process.cwd(), relativePath); + return fs.readFile(absolutePath, "utf-8"); +}; diff --git a/mdx-components.tsx b/mdx-components.tsx index ab99304..146615f 100644 --- a/mdx-components.tsx +++ b/mdx-components.tsx @@ -21,18 +21,9 @@ import { AspectRatio } from "@/components/ui/aspect-ratio"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import type { ExampleFramework } from "@/lib/examples"; import { cn } from "@/lib/utils"; -const matchesFramework = ( - currentFramework: ExampleFramework, - targetFramework: ExampleFramework | ExampleFramework[] -) => - Array.isArray(targetFramework) - ? targetFramework.includes(currentFramework) - : currentFramework === targetFramework; - -export const createMdxComponents = (framework: ExampleFramework = "ink") => ({ +export const mdxComponents = { Accordion, AccordionContent, AccordionItem, @@ -44,12 +35,8 @@ export const createMdxComponents = (framework: ExampleFramework = "ink") => ({ Button, Callout, CodeTabs, - ComponentPreview: (props: React.ComponentProps) => ( - - ), - ComponentSource: (props: React.ComponentProps) => ( - - ), + ComponentPreview, + ComponentSource, ComponentsList, FeatureCard: ({ icon: Icon, @@ -78,13 +65,6 @@ export const createMdxComponents = (framework: ExampleFramework = "ink") => ({ ), - FrameworkOnly: ({ - children, - value, - }: { - children?: React.ReactNode; - value: ExampleFramework | ExampleFramework[]; - }) => (matchesFramework(framework, value) ? children : null), Image: ({ src, className, @@ -102,8 +82,6 @@ export const createMdxComponents = (framework: ExampleFramework = "ink") => ({ {...props} /> ), - InkOnly: ({ children }: { children?: React.ReactNode }) => - framework === "ink" ? children : null, Link: ({ className, ...props }: React.ComponentProps) => ( ({ {...props} /> ), - OpenTUIOnly: ({ children }: { children?: React.ReactNode }) => - framework === "opentui" ? children : null, Step: ({ className, children, ...props }: React.ComponentProps<"h3">) => (

    ({ ul: ({ className, ...props }: React.ComponentProps<"ul">) => (
      ), -}); - -export const mdxComponents = createMdxComponents(); +}; diff --git a/registry/bases.ts b/registry/bases.ts index c4f5946..06f628f 100644 --- a/registry/bases.ts +++ b/registry/bases.ts @@ -1,24 +1,15 @@ import { inkRegistryBase } from "@/registry/bases/ink/registry"; import { opentuiRegistryBase } from "@/registry/bases/opentui/registry"; -export interface RegistryBaseDefinition { - dependencies: readonly string[]; - description: string; - examplesDir: string; - isPublic: boolean; - name: string; - publicRegistryDir: string | null; - sourceDir: string; - title: string; - type: "registry:runtime"; -} - export const BASES = [ { ...inkRegistryBase, dependencies: ["ink", "ink-web"], description: "React-powered terminal components rendered with Ink.", isPublic: true, + meta: { + logo: "", + }, title: "Ink", type: "registry:runtime", }, @@ -28,10 +19,13 @@ export const BASES = [ description: "OpenTUI React components for internal previews and future CLI installs.", isPublic: false, + meta: { + logo: "", + }, title: "OpenTUI", type: "registry:runtime", }, -] as const satisfies readonly RegistryBaseDefinition[]; +] as const; export type Base = (typeof BASES)[number]; export type BaseName = Base["name"]; diff --git a/registry/bases/ink/ui/form.tsx b/registry/bases/ink/ui/form.tsx index fa20631..057a1bf 100644 --- a/registry/bases/ink/ui/form.tsx +++ b/registry/bases/ink/ui/form.tsx @@ -1,5 +1,3 @@ -"use client"; - import { Box, Text } from "ink"; import { useState, diff --git a/registry/bases/opentui/ui/spinner.tsx b/registry/bases/opentui/components/spinner.tsx similarity index 100% rename from registry/bases/opentui/ui/spinner.tsx rename to registry/bases/opentui/components/spinner.tsx diff --git a/registry/config.ts b/registry/config.ts index 80bf309..1d862ab 100644 --- a/registry/config.ts +++ b/registry/config.ts @@ -3,17 +3,11 @@ import { z } from "zod"; import { BASE_NAMES, BASES, - getBase, PUBLIC_BASE, PUBLIC_BASE_NAME, } from "@/registry/bases"; import type { Base, BaseName } from "@/registry/bases"; -import { - getTheme, - getThemesForBase, - THEMES, - THEME_NAMES, -} from "@/registry/themes"; +import { getThemesForBase, THEMES, THEME_NAMES } from "@/registry/themes"; import type { RegistryTheme, RegistryThemeName } from "@/registry/themes"; export { BASES, type Base, type BaseName, PUBLIC_BASE, PUBLIC_BASE_NAME }; @@ -48,5 +42,3 @@ export const getRegistryConfig = (config?: Partial) => { return resolved; }; - -export { getBase, getTheme, getThemesForBase }; From 56172b29a05fcd1af90e1e6be32ce096117b9b34 Mon Sep 17 00:00:00 2001 From: Aniket-508 Date: Wed, 8 Apr 2026 17:55:23 +0530 Subject: [PATCH 03/23] docs(content): nest component MDX under ink and opentui - Move existing component docs into content/docs/components/ink/* - Add mirrored opentui tree for second registry base - Point components meta.json at ink and opentui via spread pages Made-with: Cursor --- .../components/{ => ink}/ai/chat-message.mdx | 0 .../components/{ => ink}/ai/chat-thread.mdx | 0 .../components/{ => ink}/ai/file-change.mdx | 0 .../docs/components/{ => ink}/ai/index.mdx | 0 .../docs/components/{ => ink}/ai/meta.json | 0 .../{ => ink}/ai/model-selector.mdx | 0 .../{ => ink}/ai/streaming-text.mdx | 0 .../{ => ink}/ai/thinking-block.mdx | 0 .../components/{ => ink}/ai/token-usage.mdx | 0 .../components/{ => ink}/ai/tool-approval.mdx | 0 .../components/{ => ink}/ai/tool-call.mdx | 0 .../components/{ => ink}/charts/bar-chart.mdx | 0 .../components/{ => ink}/charts/gauge.mdx | 0 .../components/{ => ink}/charts/heat-map.mdx | 0 .../components/{ => ink}/charts/index.mdx | 0 .../{ => ink}/charts/line-chart.mdx | 0 .../components/{ => ink}/charts/meta.json | 0 .../components/{ => ink}/charts/pie-chart.mdx | 0 .../components/{ => ink}/charts/sparkline.mdx | 0 .../docs/components/{ => ink}/data/card.mdx | 0 .../components/{ => ink}/data/data-grid.mdx | 0 .../components/{ => ink}/data/definition.mdx | 0 .../components/{ => ink}/data/diff-view.mdx | 0 .../{ => ink}/data/directory-tree.mdx | 0 .../components/{ => ink}/data/git-status.mdx | 0 .../docs/components/{ => ink}/data/index.mdx | 0 .../docs/components/{ => ink}/data/json.mdx | 0 .../components/{ => ink}/data/key-value.mdx | 0 .../docs/components/{ => ink}/data/list.mdx | 0 .../docs/components/{ => ink}/data/meta.json | 0 .../docs/components/{ => ink}/data/table.mdx | 0 .../docs/components/{ => ink}/data/tree.mdx | 0 .../{ => ink}/data/virtual-list.mdx | 0 .../components/{ => ink}/feedback/alert.mdx | 0 .../components/{ => ink}/feedback/banner.mdx | 0 .../components/{ => ink}/feedback/index.mdx | 0 .../components/{ => ink}/feedback/meta.json | 0 .../{ => ink}/feedback/multi-progress.mdx | 0 .../{ => ink}/feedback/progress-bar.mdx | 0 .../{ => ink}/feedback/progress-circle.mdx | 0 .../{ => ink}/feedback/skeleton.mdx | 0 .../components/{ => ink}/feedback/spinner.mdx | 0 .../{ => ink}/feedback/status-message.mdx | 0 .../components/{ => ink}/feedback/toast.mdx | 0 .../components/{ => ink}/forms/confirm.mdx | 0 .../{ => ink}/forms/date-picker.mdx | 0 .../{ => ink}/forms/file-picker.mdx | 0 .../components/{ => ink}/forms/form-field.mdx | 0 .../docs/components/{ => ink}/forms/form.mdx | 0 .../docs/components/{ => ink}/forms/index.mdx | 0 .../docs/components/{ => ink}/forms/meta.json | 0 .../{ => ink}/forms/time-picker.mdx | 0 .../components/{ => ink}/forms/wizard.mdx | 0 .../{ => ink}/input/email-input.mdx | 0 .../docs/components/{ => ink}/input/index.mdx | 0 .../{ => ink}/input/masked-input.mdx | 0 .../docs/components/{ => ink}/input/meta.json | 0 .../{ => ink}/input/number-input.mdx | 0 .../{ => ink}/input/password-input.mdx | 0 .../components/{ => ink}/input/path-input.mdx | 0 .../{ => ink}/input/search-input.mdx | 0 .../components/{ => ink}/input/text-area.mdx | 0 .../components/{ => ink}/input/text-input.mdx | 0 .../{ => ink}/layout/aspect-ratio.mdx | 0 .../docs/components/{ => ink}/layout/box.mdx | 0 .../components/{ => ink}/layout/center.mdx | 0 .../components/{ => ink}/layout/columns.mdx | 0 .../components/{ => ink}/layout/divider.mdx | 0 .../docs/components/{ => ink}/layout/grid.mdx | 0 .../components/{ => ink}/layout/index.mdx | 0 .../components/{ => ink}/layout/meta.json | 0 .../{ => ink}/layout/scroll-view.mdx | 0 .../components/{ => ink}/layout/spacer.mdx | 0 .../components/{ => ink}/layout/stack.mdx | 0 content/docs/components/ink/meta.json | 17 ++++ .../{ => ink}/navigation/breadcrumb.mdx | 0 .../{ => ink}/navigation/command-palette.mdx | 0 .../components/{ => ink}/navigation/index.mdx | 0 .../components/{ => ink}/navigation/menu.mdx | 0 .../components/{ => ink}/navigation/meta.json | 0 .../{ => ink}/navigation/pagination.mdx | 0 .../{ => ink}/navigation/sidebar.mdx | 0 .../{ => ink}/navigation/tabbed-content.mdx | 0 .../components/{ => ink}/navigation/tabs.mdx | 0 .../components/{ => ink}/overlays/dialog.mdx | 0 .../components/{ => ink}/overlays/drawer.mdx | 0 .../components/{ => ink}/overlays/index.mdx | 0 .../components/{ => ink}/overlays/meta.json | 0 .../components/{ => ink}/overlays/modal.mdx | 0 .../overlays/notification-center.mdx | 0 .../components/{ => ink}/overlays/popover.mdx | 0 .../components/{ => ink}/overlays/tooltip.mdx | 0 .../{ => ink}/selection/checkbox-group.mdx | 0 .../{ => ink}/selection/checkbox.mdx | 0 .../{ => ink}/selection/color-picker.mdx | 0 .../components/{ => ink}/selection/index.mdx | 0 .../components/{ => ink}/selection/meta.json | 0 .../{ => ink}/selection/multi-select.mdx | 0 .../{ => ink}/selection/radio-group.mdx | 0 .../components/{ => ink}/selection/select.mdx | 0 .../{ => ink}/selection/tag-input.mdx | 0 .../{ => ink}/selection/tree-select.mdx | 0 .../components/{ => ink}/typography/badge.mdx | 0 .../{ => ink}/typography/big-text.mdx | 0 .../components/{ => ink}/typography/code.mdx | 0 .../{ => ink}/typography/digits.mdx | 0 .../{ => ink}/typography/gradient.mdx | 0 .../{ => ink}/typography/heading.mdx | 0 .../components/{ => ink}/typography/index.mdx | 0 .../components/{ => ink}/typography/link.mdx | 0 .../{ => ink}/typography/markdown.mdx | 0 .../components/{ => ink}/typography/meta.json | 0 .../components/{ => ink}/typography/tag.mdx | 0 .../{ => ink}/utility/clipboard.mdx | 0 .../components/{ => ink}/utility/clock.mdx | 0 .../{ => ink}/utility/embedded-terminal.mdx | 0 .../{ => ink}/utility/error-boundary.mdx | 0 .../components/{ => ink}/utility/help.mdx | 0 .../components/{ => ink}/utility/image.mdx | 0 .../components/{ => ink}/utility/index.mdx | 0 .../{ => ink}/utility/keyboard-shortcuts.mdx | 0 .../docs/components/{ => ink}/utility/log.mdx | 0 .../components/{ => ink}/utility/meta.json | 0 .../components/{ => ink}/utility/panel.mdx | 0 .../components/{ => ink}/utility/qr-code.mdx | 0 .../{ => ink}/utility/stopwatch.mdx | 0 .../components/{ => ink}/utility/timer.mdx | 0 .../components/{ => ink}/utility/toggle.mdx | 0 content/docs/components/meta.json | 17 +--- .../components/opentui/ai/chat-message.mdx | 63 ++++++++++++ .../components/opentui/ai/chat-thread.mdx | 64 ++++++++++++ .../components/opentui/ai/file-change.mdx | 72 ++++++++++++++ content/docs/components/opentui/ai/index.mdx | 6 ++ content/docs/components/opentui/ai/meta.json | 14 +++ .../components/opentui/ai/model-selector.mdx | 76 +++++++++++++++ .../components/opentui/ai/streaming-text.mdx | 65 +++++++++++++ .../components/opentui/ai/thinking-block.mdx | 68 +++++++++++++ .../components/opentui/ai/token-usage.mdx | 71 ++++++++++++++ .../components/opentui/ai/tool-approval.mdx | 71 ++++++++++++++ .../docs/components/opentui/ai/tool-call.mdx | 68 +++++++++++++ .../components/opentui/charts/bar-chart.mdx | 69 +++++++++++++ .../docs/components/opentui/charts/gauge.mdx | 61 ++++++++++++ .../components/opentui/charts/heat-map.mdx | 69 +++++++++++++ .../docs/components/opentui/charts/index.mdx | 6 ++ .../components/opentui/charts/line-chart.mdx | 70 +++++++++++++ .../docs/components/opentui/charts/meta.json | 11 +++ .../components/opentui/charts/pie-chart.mdx | 66 +++++++++++++ .../components/opentui/charts/sparkline.mdx | 59 +++++++++++ content/docs/components/opentui/data/card.mdx | 67 +++++++++++++ .../components/opentui/data/data-grid.mdx | 86 ++++++++++++++++ .../components/opentui/data/definition.mdx | 69 +++++++++++++ .../components/opentui/data/diff-view.mdx | 66 +++++++++++++ .../opentui/data/directory-tree.mdx | 67 +++++++++++++ .../components/opentui/data/git-status.mdx | 60 ++++++++++++ .../docs/components/opentui/data/index.mdx | 6 ++ content/docs/components/opentui/data/json.mdx | 66 +++++++++++++ .../components/opentui/data/key-value.mdx | 74 ++++++++++++++ content/docs/components/opentui/data/list.mdx | 76 +++++++++++++++ .../docs/components/opentui/data/meta.json | 17 ++++ .../docs/components/opentui/data/table.mdx | 97 +++++++++++++++++++ content/docs/components/opentui/data/tree.mdx | 83 ++++++++++++++++ .../components/opentui/data/virtual-list.mdx | 65 +++++++++++++ .../components/opentui/feedback/alert.mdx | 92 ++++++++++++++++++ .../components/opentui/feedback/banner.mdx | 76 +++++++++++++++ .../components/opentui/feedback/index.mdx | 6 ++ .../components/opentui/feedback/meta.json | 14 +++ .../opentui/feedback/multi-progress.mdx | 92 ++++++++++++++++++ .../opentui/feedback/progress-bar.mdx | 70 +++++++++++++ .../opentui/feedback/progress-circle.mdx | 69 +++++++++++++ .../components/opentui/feedback/skeleton.mdx | 64 ++++++++++++ .../components/opentui/feedback/spinner.mdx | 74 ++++++++++++++ .../opentui/feedback/status-message.mdx | 67 +++++++++++++ .../components/opentui/feedback/toast.mdx | 71 ++++++++++++++ .../docs/components/opentui/forms/confirm.mdx | 66 +++++++++++++ .../components/opentui/forms/date-picker.mdx | 68 +++++++++++++ .../components/opentui/forms/file-picker.mdx | 75 ++++++++++++++ .../components/opentui/forms/form-field.mdx | 65 +++++++++++++ .../docs/components/opentui/forms/form.mdx | 68 +++++++++++++ .../docs/components/opentui/forms/index.mdx | 6 ++ .../docs/components/opentui/forms/meta.json | 12 +++ .../components/opentui/forms/time-picker.mdx | 67 +++++++++++++ .../docs/components/opentui/forms/wizard.mdx | 88 +++++++++++++++++ .../components/opentui/input/email-input.mdx | 68 +++++++++++++ .../docs/components/opentui/input/index.mdx | 6 ++ .../components/opentui/input/masked-input.mdx | 68 +++++++++++++ .../docs/components/opentui/input/meta.json | 13 +++ .../components/opentui/input/number-input.mdx | 75 ++++++++++++++ .../opentui/input/password-input.mdx | 75 ++++++++++++++ .../components/opentui/input/path-input.mdx | 74 ++++++++++++++ .../components/opentui/input/search-input.mdx | 74 ++++++++++++++ .../components/opentui/input/text-area.mdx | 70 +++++++++++++ .../components/opentui/input/text-input.mdx | 95 ++++++++++++++++++ .../opentui/layout/aspect-ratio.mdx | 60 ++++++++++++ .../docs/components/opentui/layout/box.mdx | 62 ++++++++++++ .../docs/components/opentui/layout/center.mdx | 59 +++++++++++ .../components/opentui/layout/columns.mdx | 61 ++++++++++++ .../components/opentui/layout/divider.mdx | 75 ++++++++++++++ .../docs/components/opentui/layout/grid.mdx | 65 +++++++++++++ .../docs/components/opentui/layout/index.mdx | 6 ++ .../docs/components/opentui/layout/meta.json | 14 +++ .../components/opentui/layout/scroll-view.mdx | 75 ++++++++++++++ .../docs/components/opentui/layout/spacer.mdx | 61 ++++++++++++ .../docs/components/opentui/layout/stack.mdx | 66 +++++++++++++ content/docs/components/opentui/meta.json | 17 ++++ .../opentui/navigation/breadcrumb.mdx | 72 ++++++++++++++ .../opentui/navigation/command-palette.mdx | 81 ++++++++++++++++ .../components/opentui/navigation/index.mdx | 6 ++ .../components/opentui/navigation/menu.mdx | 77 +++++++++++++++ .../components/opentui/navigation/meta.json | 12 +++ .../opentui/navigation/pagination.mdx | 60 ++++++++++++ .../components/opentui/navigation/sidebar.mdx | 79 +++++++++++++++ .../opentui/navigation/tabbed-content.mdx | 82 ++++++++++++++++ .../components/opentui/navigation/tabs.mdx | 87 +++++++++++++++++ .../components/opentui/overlays/dialog.mdx | 70 +++++++++++++ .../components/opentui/overlays/drawer.mdx | 71 ++++++++++++++ .../components/opentui/overlays/index.mdx | 6 ++ .../components/opentui/overlays/meta.json | 11 +++ .../components/opentui/overlays/modal.mdx | 68 +++++++++++++ .../opentui/overlays/notification-center.mdx | 69 +++++++++++++ .../components/opentui/overlays/popover.mdx | 67 +++++++++++++ .../components/opentui/overlays/tooltip.mdx | 68 +++++++++++++ .../opentui/selection/checkbox-group.mdx | 72 ++++++++++++++ .../components/opentui/selection/checkbox.mdx | 64 ++++++++++++ .../opentui/selection/color-picker.mdx | 62 ++++++++++++ .../components/opentui/selection/index.mdx | 6 ++ .../components/opentui/selection/meta.json | 13 +++ .../opentui/selection/multi-select.mdx | 69 +++++++++++++ .../opentui/selection/radio-group.mdx | 67 +++++++++++++ .../components/opentui/selection/select.mdx | 70 +++++++++++++ .../opentui/selection/tag-input.mdx | 60 ++++++++++++ .../opentui/selection/tree-select.mdx | 75 ++++++++++++++ .../components/opentui/typography/badge.mdx | 82 ++++++++++++++++ .../opentui/typography/big-text.mdx | 66 +++++++++++++ .../components/opentui/typography/code.mdx | 75 ++++++++++++++ .../components/opentui/typography/digits.mdx | 58 +++++++++++ .../opentui/typography/gradient.mdx | 69 +++++++++++++ .../components/opentui/typography/heading.mdx | 62 ++++++++++++ .../components/opentui/typography/index.mdx | 6 ++ .../components/opentui/typography/link.mdx | 68 +++++++++++++ .../opentui/typography/markdown.mdx | 57 +++++++++++ .../components/opentui/typography/meta.json | 14 +++ .../components/opentui/typography/tag.mdx | 59 +++++++++++ .../components/opentui/utility/clipboard.mdx | 59 +++++++++++ .../docs/components/opentui/utility/clock.mdx | 61 ++++++++++++ .../opentui/utility/embedded-terminal.mdx | 74 ++++++++++++++ .../opentui/utility/error-boundary.mdx | 64 ++++++++++++ .../docs/components/opentui/utility/help.mdx | 66 +++++++++++++ .../docs/components/opentui/utility/image.mdx | 65 +++++++++++++ .../docs/components/opentui/utility/index.mdx | 6 ++ .../opentui/utility/keyboard-shortcuts.mdx | 76 +++++++++++++++ .../docs/components/opentui/utility/log.mdx | 77 +++++++++++++++ .../docs/components/opentui/utility/meta.json | 18 ++++ .../docs/components/opentui/utility/panel.mdx | 67 +++++++++++++ .../components/opentui/utility/qr-code.mdx | 59 +++++++++++ .../components/opentui/utility/stopwatch.mdx | 58 +++++++++++ .../docs/components/opentui/utility/timer.mdx | 61 ++++++++++++ .../components/opentui/utility/toggle.mdx | 66 +++++++++++++ 257 files changed, 7453 insertions(+), 15 deletions(-) rename content/docs/components/{ => ink}/ai/chat-message.mdx (100%) rename content/docs/components/{ => ink}/ai/chat-thread.mdx (100%) rename content/docs/components/{ => ink}/ai/file-change.mdx (100%) rename content/docs/components/{ => ink}/ai/index.mdx (100%) rename content/docs/components/{ => ink}/ai/meta.json (100%) rename content/docs/components/{ => ink}/ai/model-selector.mdx (100%) rename content/docs/components/{ => ink}/ai/streaming-text.mdx (100%) rename content/docs/components/{ => ink}/ai/thinking-block.mdx (100%) rename content/docs/components/{ => ink}/ai/token-usage.mdx (100%) rename content/docs/components/{ => ink}/ai/tool-approval.mdx (100%) rename content/docs/components/{ => ink}/ai/tool-call.mdx (100%) rename content/docs/components/{ => ink}/charts/bar-chart.mdx (100%) rename content/docs/components/{ => ink}/charts/gauge.mdx (100%) rename content/docs/components/{ => ink}/charts/heat-map.mdx (100%) rename content/docs/components/{ => ink}/charts/index.mdx (100%) rename content/docs/components/{ => ink}/charts/line-chart.mdx (100%) rename content/docs/components/{ => ink}/charts/meta.json (100%) rename content/docs/components/{ => ink}/charts/pie-chart.mdx (100%) rename content/docs/components/{ => ink}/charts/sparkline.mdx (100%) rename content/docs/components/{ => ink}/data/card.mdx (100%) rename content/docs/components/{ => ink}/data/data-grid.mdx (100%) rename content/docs/components/{ => ink}/data/definition.mdx (100%) rename content/docs/components/{ => ink}/data/diff-view.mdx (100%) rename content/docs/components/{ => ink}/data/directory-tree.mdx (100%) rename content/docs/components/{ => ink}/data/git-status.mdx (100%) rename content/docs/components/{ => ink}/data/index.mdx (100%) rename content/docs/components/{ => ink}/data/json.mdx (100%) rename content/docs/components/{ => ink}/data/key-value.mdx (100%) rename content/docs/components/{ => ink}/data/list.mdx (100%) rename content/docs/components/{ => ink}/data/meta.json (100%) rename content/docs/components/{ => ink}/data/table.mdx (100%) rename content/docs/components/{ => ink}/data/tree.mdx (100%) rename content/docs/components/{ => ink}/data/virtual-list.mdx (100%) rename content/docs/components/{ => ink}/feedback/alert.mdx (100%) rename content/docs/components/{ => ink}/feedback/banner.mdx (100%) rename content/docs/components/{ => ink}/feedback/index.mdx (100%) rename content/docs/components/{ => ink}/feedback/meta.json (100%) rename content/docs/components/{ => ink}/feedback/multi-progress.mdx (100%) rename content/docs/components/{ => ink}/feedback/progress-bar.mdx (100%) rename content/docs/components/{ => ink}/feedback/progress-circle.mdx (100%) rename content/docs/components/{ => ink}/feedback/skeleton.mdx (100%) rename content/docs/components/{ => ink}/feedback/spinner.mdx (100%) rename content/docs/components/{ => ink}/feedback/status-message.mdx (100%) rename content/docs/components/{ => ink}/feedback/toast.mdx (100%) rename content/docs/components/{ => ink}/forms/confirm.mdx (100%) rename content/docs/components/{ => ink}/forms/date-picker.mdx (100%) rename content/docs/components/{ => ink}/forms/file-picker.mdx (100%) rename content/docs/components/{ => ink}/forms/form-field.mdx (100%) rename content/docs/components/{ => ink}/forms/form.mdx (100%) rename content/docs/components/{ => ink}/forms/index.mdx (100%) rename content/docs/components/{ => ink}/forms/meta.json (100%) rename content/docs/components/{ => ink}/forms/time-picker.mdx (100%) rename content/docs/components/{ => ink}/forms/wizard.mdx (100%) rename content/docs/components/{ => ink}/input/email-input.mdx (100%) rename content/docs/components/{ => ink}/input/index.mdx (100%) rename content/docs/components/{ => ink}/input/masked-input.mdx (100%) rename content/docs/components/{ => ink}/input/meta.json (100%) rename content/docs/components/{ => ink}/input/number-input.mdx (100%) rename content/docs/components/{ => ink}/input/password-input.mdx (100%) rename content/docs/components/{ => ink}/input/path-input.mdx (100%) rename content/docs/components/{ => ink}/input/search-input.mdx (100%) rename content/docs/components/{ => ink}/input/text-area.mdx (100%) rename content/docs/components/{ => ink}/input/text-input.mdx (100%) rename content/docs/components/{ => ink}/layout/aspect-ratio.mdx (100%) rename content/docs/components/{ => ink}/layout/box.mdx (100%) rename content/docs/components/{ => ink}/layout/center.mdx (100%) rename content/docs/components/{ => ink}/layout/columns.mdx (100%) rename content/docs/components/{ => ink}/layout/divider.mdx (100%) rename content/docs/components/{ => ink}/layout/grid.mdx (100%) rename content/docs/components/{ => ink}/layout/index.mdx (100%) rename content/docs/components/{ => ink}/layout/meta.json (100%) rename content/docs/components/{ => ink}/layout/scroll-view.mdx (100%) rename content/docs/components/{ => ink}/layout/spacer.mdx (100%) rename content/docs/components/{ => ink}/layout/stack.mdx (100%) create mode 100644 content/docs/components/ink/meta.json rename content/docs/components/{ => ink}/navigation/breadcrumb.mdx (100%) rename content/docs/components/{ => ink}/navigation/command-palette.mdx (100%) rename content/docs/components/{ => ink}/navigation/index.mdx (100%) rename content/docs/components/{ => ink}/navigation/menu.mdx (100%) rename content/docs/components/{ => ink}/navigation/meta.json (100%) rename content/docs/components/{ => ink}/navigation/pagination.mdx (100%) rename content/docs/components/{ => ink}/navigation/sidebar.mdx (100%) rename content/docs/components/{ => ink}/navigation/tabbed-content.mdx (100%) rename content/docs/components/{ => ink}/navigation/tabs.mdx (100%) rename content/docs/components/{ => ink}/overlays/dialog.mdx (100%) rename content/docs/components/{ => ink}/overlays/drawer.mdx (100%) rename content/docs/components/{ => ink}/overlays/index.mdx (100%) rename content/docs/components/{ => ink}/overlays/meta.json (100%) rename content/docs/components/{ => ink}/overlays/modal.mdx (100%) rename content/docs/components/{ => ink}/overlays/notification-center.mdx (100%) rename content/docs/components/{ => ink}/overlays/popover.mdx (100%) rename content/docs/components/{ => ink}/overlays/tooltip.mdx (100%) rename content/docs/components/{ => ink}/selection/checkbox-group.mdx (100%) rename content/docs/components/{ => ink}/selection/checkbox.mdx (100%) rename content/docs/components/{ => ink}/selection/color-picker.mdx (100%) rename content/docs/components/{ => ink}/selection/index.mdx (100%) rename content/docs/components/{ => ink}/selection/meta.json (100%) rename content/docs/components/{ => ink}/selection/multi-select.mdx (100%) rename content/docs/components/{ => ink}/selection/radio-group.mdx (100%) rename content/docs/components/{ => ink}/selection/select.mdx (100%) rename content/docs/components/{ => ink}/selection/tag-input.mdx (100%) rename content/docs/components/{ => ink}/selection/tree-select.mdx (100%) rename content/docs/components/{ => ink}/typography/badge.mdx (100%) rename content/docs/components/{ => ink}/typography/big-text.mdx (100%) rename content/docs/components/{ => ink}/typography/code.mdx (100%) rename content/docs/components/{ => ink}/typography/digits.mdx (100%) rename content/docs/components/{ => ink}/typography/gradient.mdx (100%) rename content/docs/components/{ => ink}/typography/heading.mdx (100%) rename content/docs/components/{ => ink}/typography/index.mdx (100%) rename content/docs/components/{ => ink}/typography/link.mdx (100%) rename content/docs/components/{ => ink}/typography/markdown.mdx (100%) rename content/docs/components/{ => ink}/typography/meta.json (100%) rename content/docs/components/{ => ink}/typography/tag.mdx (100%) rename content/docs/components/{ => ink}/utility/clipboard.mdx (100%) rename content/docs/components/{ => ink}/utility/clock.mdx (100%) rename content/docs/components/{ => ink}/utility/embedded-terminal.mdx (100%) rename content/docs/components/{ => ink}/utility/error-boundary.mdx (100%) rename content/docs/components/{ => ink}/utility/help.mdx (100%) rename content/docs/components/{ => ink}/utility/image.mdx (100%) rename content/docs/components/{ => ink}/utility/index.mdx (100%) rename content/docs/components/{ => ink}/utility/keyboard-shortcuts.mdx (100%) rename content/docs/components/{ => ink}/utility/log.mdx (100%) rename content/docs/components/{ => ink}/utility/meta.json (100%) rename content/docs/components/{ => ink}/utility/panel.mdx (100%) rename content/docs/components/{ => ink}/utility/qr-code.mdx (100%) rename content/docs/components/{ => ink}/utility/stopwatch.mdx (100%) rename content/docs/components/{ => ink}/utility/timer.mdx (100%) rename content/docs/components/{ => ink}/utility/toggle.mdx (100%) create mode 100644 content/docs/components/opentui/ai/chat-message.mdx create mode 100644 content/docs/components/opentui/ai/chat-thread.mdx create mode 100644 content/docs/components/opentui/ai/file-change.mdx create mode 100644 content/docs/components/opentui/ai/index.mdx create mode 100644 content/docs/components/opentui/ai/meta.json create mode 100644 content/docs/components/opentui/ai/model-selector.mdx create mode 100644 content/docs/components/opentui/ai/streaming-text.mdx create mode 100644 content/docs/components/opentui/ai/thinking-block.mdx create mode 100644 content/docs/components/opentui/ai/token-usage.mdx create mode 100644 content/docs/components/opentui/ai/tool-approval.mdx create mode 100644 content/docs/components/opentui/ai/tool-call.mdx create mode 100644 content/docs/components/opentui/charts/bar-chart.mdx create mode 100644 content/docs/components/opentui/charts/gauge.mdx create mode 100644 content/docs/components/opentui/charts/heat-map.mdx create mode 100644 content/docs/components/opentui/charts/index.mdx create mode 100644 content/docs/components/opentui/charts/line-chart.mdx create mode 100644 content/docs/components/opentui/charts/meta.json create mode 100644 content/docs/components/opentui/charts/pie-chart.mdx create mode 100644 content/docs/components/opentui/charts/sparkline.mdx create mode 100644 content/docs/components/opentui/data/card.mdx create mode 100644 content/docs/components/opentui/data/data-grid.mdx create mode 100644 content/docs/components/opentui/data/definition.mdx create mode 100644 content/docs/components/opentui/data/diff-view.mdx create mode 100644 content/docs/components/opentui/data/directory-tree.mdx create mode 100644 content/docs/components/opentui/data/git-status.mdx create mode 100644 content/docs/components/opentui/data/index.mdx create mode 100644 content/docs/components/opentui/data/json.mdx create mode 100644 content/docs/components/opentui/data/key-value.mdx create mode 100644 content/docs/components/opentui/data/list.mdx create mode 100644 content/docs/components/opentui/data/meta.json create mode 100644 content/docs/components/opentui/data/table.mdx create mode 100644 content/docs/components/opentui/data/tree.mdx create mode 100644 content/docs/components/opentui/data/virtual-list.mdx create mode 100644 content/docs/components/opentui/feedback/alert.mdx create mode 100644 content/docs/components/opentui/feedback/banner.mdx create mode 100644 content/docs/components/opentui/feedback/index.mdx create mode 100644 content/docs/components/opentui/feedback/meta.json create mode 100644 content/docs/components/opentui/feedback/multi-progress.mdx create mode 100644 content/docs/components/opentui/feedback/progress-bar.mdx create mode 100644 content/docs/components/opentui/feedback/progress-circle.mdx create mode 100644 content/docs/components/opentui/feedback/skeleton.mdx create mode 100644 content/docs/components/opentui/feedback/spinner.mdx create mode 100644 content/docs/components/opentui/feedback/status-message.mdx create mode 100644 content/docs/components/opentui/feedback/toast.mdx create mode 100644 content/docs/components/opentui/forms/confirm.mdx create mode 100644 content/docs/components/opentui/forms/date-picker.mdx create mode 100644 content/docs/components/opentui/forms/file-picker.mdx create mode 100644 content/docs/components/opentui/forms/form-field.mdx create mode 100644 content/docs/components/opentui/forms/form.mdx create mode 100644 content/docs/components/opentui/forms/index.mdx create mode 100644 content/docs/components/opentui/forms/meta.json create mode 100644 content/docs/components/opentui/forms/time-picker.mdx create mode 100644 content/docs/components/opentui/forms/wizard.mdx create mode 100644 content/docs/components/opentui/input/email-input.mdx create mode 100644 content/docs/components/opentui/input/index.mdx create mode 100644 content/docs/components/opentui/input/masked-input.mdx create mode 100644 content/docs/components/opentui/input/meta.json create mode 100644 content/docs/components/opentui/input/number-input.mdx create mode 100644 content/docs/components/opentui/input/password-input.mdx create mode 100644 content/docs/components/opentui/input/path-input.mdx create mode 100644 content/docs/components/opentui/input/search-input.mdx create mode 100644 content/docs/components/opentui/input/text-area.mdx create mode 100644 content/docs/components/opentui/input/text-input.mdx create mode 100644 content/docs/components/opentui/layout/aspect-ratio.mdx create mode 100644 content/docs/components/opentui/layout/box.mdx create mode 100644 content/docs/components/opentui/layout/center.mdx create mode 100644 content/docs/components/opentui/layout/columns.mdx create mode 100644 content/docs/components/opentui/layout/divider.mdx create mode 100644 content/docs/components/opentui/layout/grid.mdx create mode 100644 content/docs/components/opentui/layout/index.mdx create mode 100644 content/docs/components/opentui/layout/meta.json create mode 100644 content/docs/components/opentui/layout/scroll-view.mdx create mode 100644 content/docs/components/opentui/layout/spacer.mdx create mode 100644 content/docs/components/opentui/layout/stack.mdx create mode 100644 content/docs/components/opentui/meta.json create mode 100644 content/docs/components/opentui/navigation/breadcrumb.mdx create mode 100644 content/docs/components/opentui/navigation/command-palette.mdx create mode 100644 content/docs/components/opentui/navigation/index.mdx create mode 100644 content/docs/components/opentui/navigation/menu.mdx create mode 100644 content/docs/components/opentui/navigation/meta.json create mode 100644 content/docs/components/opentui/navigation/pagination.mdx create mode 100644 content/docs/components/opentui/navigation/sidebar.mdx create mode 100644 content/docs/components/opentui/navigation/tabbed-content.mdx create mode 100644 content/docs/components/opentui/navigation/tabs.mdx create mode 100644 content/docs/components/opentui/overlays/dialog.mdx create mode 100644 content/docs/components/opentui/overlays/drawer.mdx create mode 100644 content/docs/components/opentui/overlays/index.mdx create mode 100644 content/docs/components/opentui/overlays/meta.json create mode 100644 content/docs/components/opentui/overlays/modal.mdx create mode 100644 content/docs/components/opentui/overlays/notification-center.mdx create mode 100644 content/docs/components/opentui/overlays/popover.mdx create mode 100644 content/docs/components/opentui/overlays/tooltip.mdx create mode 100644 content/docs/components/opentui/selection/checkbox-group.mdx create mode 100644 content/docs/components/opentui/selection/checkbox.mdx create mode 100644 content/docs/components/opentui/selection/color-picker.mdx create mode 100644 content/docs/components/opentui/selection/index.mdx create mode 100644 content/docs/components/opentui/selection/meta.json create mode 100644 content/docs/components/opentui/selection/multi-select.mdx create mode 100644 content/docs/components/opentui/selection/radio-group.mdx create mode 100644 content/docs/components/opentui/selection/select.mdx create mode 100644 content/docs/components/opentui/selection/tag-input.mdx create mode 100644 content/docs/components/opentui/selection/tree-select.mdx create mode 100644 content/docs/components/opentui/typography/badge.mdx create mode 100644 content/docs/components/opentui/typography/big-text.mdx create mode 100644 content/docs/components/opentui/typography/code.mdx create mode 100644 content/docs/components/opentui/typography/digits.mdx create mode 100644 content/docs/components/opentui/typography/gradient.mdx create mode 100644 content/docs/components/opentui/typography/heading.mdx create mode 100644 content/docs/components/opentui/typography/index.mdx create mode 100644 content/docs/components/opentui/typography/link.mdx create mode 100644 content/docs/components/opentui/typography/markdown.mdx create mode 100644 content/docs/components/opentui/typography/meta.json create mode 100644 content/docs/components/opentui/typography/tag.mdx create mode 100644 content/docs/components/opentui/utility/clipboard.mdx create mode 100644 content/docs/components/opentui/utility/clock.mdx create mode 100644 content/docs/components/opentui/utility/embedded-terminal.mdx create mode 100644 content/docs/components/opentui/utility/error-boundary.mdx create mode 100644 content/docs/components/opentui/utility/help.mdx create mode 100644 content/docs/components/opentui/utility/image.mdx create mode 100644 content/docs/components/opentui/utility/index.mdx create mode 100644 content/docs/components/opentui/utility/keyboard-shortcuts.mdx create mode 100644 content/docs/components/opentui/utility/log.mdx create mode 100644 content/docs/components/opentui/utility/meta.json create mode 100644 content/docs/components/opentui/utility/panel.mdx create mode 100644 content/docs/components/opentui/utility/qr-code.mdx create mode 100644 content/docs/components/opentui/utility/stopwatch.mdx create mode 100644 content/docs/components/opentui/utility/timer.mdx create mode 100644 content/docs/components/opentui/utility/toggle.mdx diff --git a/content/docs/components/ai/chat-message.mdx b/content/docs/components/ink/ai/chat-message.mdx similarity index 100% rename from content/docs/components/ai/chat-message.mdx rename to content/docs/components/ink/ai/chat-message.mdx diff --git a/content/docs/components/ai/chat-thread.mdx b/content/docs/components/ink/ai/chat-thread.mdx similarity index 100% rename from content/docs/components/ai/chat-thread.mdx rename to content/docs/components/ink/ai/chat-thread.mdx diff --git a/content/docs/components/ai/file-change.mdx b/content/docs/components/ink/ai/file-change.mdx similarity index 100% rename from content/docs/components/ai/file-change.mdx rename to content/docs/components/ink/ai/file-change.mdx diff --git a/content/docs/components/ai/index.mdx b/content/docs/components/ink/ai/index.mdx similarity index 100% rename from content/docs/components/ai/index.mdx rename to content/docs/components/ink/ai/index.mdx diff --git a/content/docs/components/ai/meta.json b/content/docs/components/ink/ai/meta.json similarity index 100% rename from content/docs/components/ai/meta.json rename to content/docs/components/ink/ai/meta.json diff --git a/content/docs/components/ai/model-selector.mdx b/content/docs/components/ink/ai/model-selector.mdx similarity index 100% rename from content/docs/components/ai/model-selector.mdx rename to content/docs/components/ink/ai/model-selector.mdx diff --git a/content/docs/components/ai/streaming-text.mdx b/content/docs/components/ink/ai/streaming-text.mdx similarity index 100% rename from content/docs/components/ai/streaming-text.mdx rename to content/docs/components/ink/ai/streaming-text.mdx diff --git a/content/docs/components/ai/thinking-block.mdx b/content/docs/components/ink/ai/thinking-block.mdx similarity index 100% rename from content/docs/components/ai/thinking-block.mdx rename to content/docs/components/ink/ai/thinking-block.mdx diff --git a/content/docs/components/ai/token-usage.mdx b/content/docs/components/ink/ai/token-usage.mdx similarity index 100% rename from content/docs/components/ai/token-usage.mdx rename to content/docs/components/ink/ai/token-usage.mdx diff --git a/content/docs/components/ai/tool-approval.mdx b/content/docs/components/ink/ai/tool-approval.mdx similarity index 100% rename from content/docs/components/ai/tool-approval.mdx rename to content/docs/components/ink/ai/tool-approval.mdx diff --git a/content/docs/components/ai/tool-call.mdx b/content/docs/components/ink/ai/tool-call.mdx similarity index 100% rename from content/docs/components/ai/tool-call.mdx rename to content/docs/components/ink/ai/tool-call.mdx diff --git a/content/docs/components/charts/bar-chart.mdx b/content/docs/components/ink/charts/bar-chart.mdx similarity index 100% rename from content/docs/components/charts/bar-chart.mdx rename to content/docs/components/ink/charts/bar-chart.mdx diff --git a/content/docs/components/charts/gauge.mdx b/content/docs/components/ink/charts/gauge.mdx similarity index 100% rename from content/docs/components/charts/gauge.mdx rename to content/docs/components/ink/charts/gauge.mdx diff --git a/content/docs/components/charts/heat-map.mdx b/content/docs/components/ink/charts/heat-map.mdx similarity index 100% rename from content/docs/components/charts/heat-map.mdx rename to content/docs/components/ink/charts/heat-map.mdx diff --git a/content/docs/components/charts/index.mdx b/content/docs/components/ink/charts/index.mdx similarity index 100% rename from content/docs/components/charts/index.mdx rename to content/docs/components/ink/charts/index.mdx diff --git a/content/docs/components/charts/line-chart.mdx b/content/docs/components/ink/charts/line-chart.mdx similarity index 100% rename from content/docs/components/charts/line-chart.mdx rename to content/docs/components/ink/charts/line-chart.mdx diff --git a/content/docs/components/charts/meta.json b/content/docs/components/ink/charts/meta.json similarity index 100% rename from content/docs/components/charts/meta.json rename to content/docs/components/ink/charts/meta.json diff --git a/content/docs/components/charts/pie-chart.mdx b/content/docs/components/ink/charts/pie-chart.mdx similarity index 100% rename from content/docs/components/charts/pie-chart.mdx rename to content/docs/components/ink/charts/pie-chart.mdx diff --git a/content/docs/components/charts/sparkline.mdx b/content/docs/components/ink/charts/sparkline.mdx similarity index 100% rename from content/docs/components/charts/sparkline.mdx rename to content/docs/components/ink/charts/sparkline.mdx diff --git a/content/docs/components/data/card.mdx b/content/docs/components/ink/data/card.mdx similarity index 100% rename from content/docs/components/data/card.mdx rename to content/docs/components/ink/data/card.mdx diff --git a/content/docs/components/data/data-grid.mdx b/content/docs/components/ink/data/data-grid.mdx similarity index 100% rename from content/docs/components/data/data-grid.mdx rename to content/docs/components/ink/data/data-grid.mdx diff --git a/content/docs/components/data/definition.mdx b/content/docs/components/ink/data/definition.mdx similarity index 100% rename from content/docs/components/data/definition.mdx rename to content/docs/components/ink/data/definition.mdx diff --git a/content/docs/components/data/diff-view.mdx b/content/docs/components/ink/data/diff-view.mdx similarity index 100% rename from content/docs/components/data/diff-view.mdx rename to content/docs/components/ink/data/diff-view.mdx diff --git a/content/docs/components/data/directory-tree.mdx b/content/docs/components/ink/data/directory-tree.mdx similarity index 100% rename from content/docs/components/data/directory-tree.mdx rename to content/docs/components/ink/data/directory-tree.mdx diff --git a/content/docs/components/data/git-status.mdx b/content/docs/components/ink/data/git-status.mdx similarity index 100% rename from content/docs/components/data/git-status.mdx rename to content/docs/components/ink/data/git-status.mdx diff --git a/content/docs/components/data/index.mdx b/content/docs/components/ink/data/index.mdx similarity index 100% rename from content/docs/components/data/index.mdx rename to content/docs/components/ink/data/index.mdx diff --git a/content/docs/components/data/json.mdx b/content/docs/components/ink/data/json.mdx similarity index 100% rename from content/docs/components/data/json.mdx rename to content/docs/components/ink/data/json.mdx diff --git a/content/docs/components/data/key-value.mdx b/content/docs/components/ink/data/key-value.mdx similarity index 100% rename from content/docs/components/data/key-value.mdx rename to content/docs/components/ink/data/key-value.mdx diff --git a/content/docs/components/data/list.mdx b/content/docs/components/ink/data/list.mdx similarity index 100% rename from content/docs/components/data/list.mdx rename to content/docs/components/ink/data/list.mdx diff --git a/content/docs/components/data/meta.json b/content/docs/components/ink/data/meta.json similarity index 100% rename from content/docs/components/data/meta.json rename to content/docs/components/ink/data/meta.json diff --git a/content/docs/components/data/table.mdx b/content/docs/components/ink/data/table.mdx similarity index 100% rename from content/docs/components/data/table.mdx rename to content/docs/components/ink/data/table.mdx diff --git a/content/docs/components/data/tree.mdx b/content/docs/components/ink/data/tree.mdx similarity index 100% rename from content/docs/components/data/tree.mdx rename to content/docs/components/ink/data/tree.mdx diff --git a/content/docs/components/data/virtual-list.mdx b/content/docs/components/ink/data/virtual-list.mdx similarity index 100% rename from content/docs/components/data/virtual-list.mdx rename to content/docs/components/ink/data/virtual-list.mdx diff --git a/content/docs/components/feedback/alert.mdx b/content/docs/components/ink/feedback/alert.mdx similarity index 100% rename from content/docs/components/feedback/alert.mdx rename to content/docs/components/ink/feedback/alert.mdx diff --git a/content/docs/components/feedback/banner.mdx b/content/docs/components/ink/feedback/banner.mdx similarity index 100% rename from content/docs/components/feedback/banner.mdx rename to content/docs/components/ink/feedback/banner.mdx diff --git a/content/docs/components/feedback/index.mdx b/content/docs/components/ink/feedback/index.mdx similarity index 100% rename from content/docs/components/feedback/index.mdx rename to content/docs/components/ink/feedback/index.mdx diff --git a/content/docs/components/feedback/meta.json b/content/docs/components/ink/feedback/meta.json similarity index 100% rename from content/docs/components/feedback/meta.json rename to content/docs/components/ink/feedback/meta.json diff --git a/content/docs/components/feedback/multi-progress.mdx b/content/docs/components/ink/feedback/multi-progress.mdx similarity index 100% rename from content/docs/components/feedback/multi-progress.mdx rename to content/docs/components/ink/feedback/multi-progress.mdx diff --git a/content/docs/components/feedback/progress-bar.mdx b/content/docs/components/ink/feedback/progress-bar.mdx similarity index 100% rename from content/docs/components/feedback/progress-bar.mdx rename to content/docs/components/ink/feedback/progress-bar.mdx diff --git a/content/docs/components/feedback/progress-circle.mdx b/content/docs/components/ink/feedback/progress-circle.mdx similarity index 100% rename from content/docs/components/feedback/progress-circle.mdx rename to content/docs/components/ink/feedback/progress-circle.mdx diff --git a/content/docs/components/feedback/skeleton.mdx b/content/docs/components/ink/feedback/skeleton.mdx similarity index 100% rename from content/docs/components/feedback/skeleton.mdx rename to content/docs/components/ink/feedback/skeleton.mdx diff --git a/content/docs/components/feedback/spinner.mdx b/content/docs/components/ink/feedback/spinner.mdx similarity index 100% rename from content/docs/components/feedback/spinner.mdx rename to content/docs/components/ink/feedback/spinner.mdx diff --git a/content/docs/components/feedback/status-message.mdx b/content/docs/components/ink/feedback/status-message.mdx similarity index 100% rename from content/docs/components/feedback/status-message.mdx rename to content/docs/components/ink/feedback/status-message.mdx diff --git a/content/docs/components/feedback/toast.mdx b/content/docs/components/ink/feedback/toast.mdx similarity index 100% rename from content/docs/components/feedback/toast.mdx rename to content/docs/components/ink/feedback/toast.mdx diff --git a/content/docs/components/forms/confirm.mdx b/content/docs/components/ink/forms/confirm.mdx similarity index 100% rename from content/docs/components/forms/confirm.mdx rename to content/docs/components/ink/forms/confirm.mdx diff --git a/content/docs/components/forms/date-picker.mdx b/content/docs/components/ink/forms/date-picker.mdx similarity index 100% rename from content/docs/components/forms/date-picker.mdx rename to content/docs/components/ink/forms/date-picker.mdx diff --git a/content/docs/components/forms/file-picker.mdx b/content/docs/components/ink/forms/file-picker.mdx similarity index 100% rename from content/docs/components/forms/file-picker.mdx rename to content/docs/components/ink/forms/file-picker.mdx diff --git a/content/docs/components/forms/form-field.mdx b/content/docs/components/ink/forms/form-field.mdx similarity index 100% rename from content/docs/components/forms/form-field.mdx rename to content/docs/components/ink/forms/form-field.mdx diff --git a/content/docs/components/forms/form.mdx b/content/docs/components/ink/forms/form.mdx similarity index 100% rename from content/docs/components/forms/form.mdx rename to content/docs/components/ink/forms/form.mdx diff --git a/content/docs/components/forms/index.mdx b/content/docs/components/ink/forms/index.mdx similarity index 100% rename from content/docs/components/forms/index.mdx rename to content/docs/components/ink/forms/index.mdx diff --git a/content/docs/components/forms/meta.json b/content/docs/components/ink/forms/meta.json similarity index 100% rename from content/docs/components/forms/meta.json rename to content/docs/components/ink/forms/meta.json diff --git a/content/docs/components/forms/time-picker.mdx b/content/docs/components/ink/forms/time-picker.mdx similarity index 100% rename from content/docs/components/forms/time-picker.mdx rename to content/docs/components/ink/forms/time-picker.mdx diff --git a/content/docs/components/forms/wizard.mdx b/content/docs/components/ink/forms/wizard.mdx similarity index 100% rename from content/docs/components/forms/wizard.mdx rename to content/docs/components/ink/forms/wizard.mdx diff --git a/content/docs/components/input/email-input.mdx b/content/docs/components/ink/input/email-input.mdx similarity index 100% rename from content/docs/components/input/email-input.mdx rename to content/docs/components/ink/input/email-input.mdx diff --git a/content/docs/components/input/index.mdx b/content/docs/components/ink/input/index.mdx similarity index 100% rename from content/docs/components/input/index.mdx rename to content/docs/components/ink/input/index.mdx diff --git a/content/docs/components/input/masked-input.mdx b/content/docs/components/ink/input/masked-input.mdx similarity index 100% rename from content/docs/components/input/masked-input.mdx rename to content/docs/components/ink/input/masked-input.mdx diff --git a/content/docs/components/input/meta.json b/content/docs/components/ink/input/meta.json similarity index 100% rename from content/docs/components/input/meta.json rename to content/docs/components/ink/input/meta.json diff --git a/content/docs/components/input/number-input.mdx b/content/docs/components/ink/input/number-input.mdx similarity index 100% rename from content/docs/components/input/number-input.mdx rename to content/docs/components/ink/input/number-input.mdx diff --git a/content/docs/components/input/password-input.mdx b/content/docs/components/ink/input/password-input.mdx similarity index 100% rename from content/docs/components/input/password-input.mdx rename to content/docs/components/ink/input/password-input.mdx diff --git a/content/docs/components/input/path-input.mdx b/content/docs/components/ink/input/path-input.mdx similarity index 100% rename from content/docs/components/input/path-input.mdx rename to content/docs/components/ink/input/path-input.mdx diff --git a/content/docs/components/input/search-input.mdx b/content/docs/components/ink/input/search-input.mdx similarity index 100% rename from content/docs/components/input/search-input.mdx rename to content/docs/components/ink/input/search-input.mdx diff --git a/content/docs/components/input/text-area.mdx b/content/docs/components/ink/input/text-area.mdx similarity index 100% rename from content/docs/components/input/text-area.mdx rename to content/docs/components/ink/input/text-area.mdx diff --git a/content/docs/components/input/text-input.mdx b/content/docs/components/ink/input/text-input.mdx similarity index 100% rename from content/docs/components/input/text-input.mdx rename to content/docs/components/ink/input/text-input.mdx diff --git a/content/docs/components/layout/aspect-ratio.mdx b/content/docs/components/ink/layout/aspect-ratio.mdx similarity index 100% rename from content/docs/components/layout/aspect-ratio.mdx rename to content/docs/components/ink/layout/aspect-ratio.mdx diff --git a/content/docs/components/layout/box.mdx b/content/docs/components/ink/layout/box.mdx similarity index 100% rename from content/docs/components/layout/box.mdx rename to content/docs/components/ink/layout/box.mdx diff --git a/content/docs/components/layout/center.mdx b/content/docs/components/ink/layout/center.mdx similarity index 100% rename from content/docs/components/layout/center.mdx rename to content/docs/components/ink/layout/center.mdx diff --git a/content/docs/components/layout/columns.mdx b/content/docs/components/ink/layout/columns.mdx similarity index 100% rename from content/docs/components/layout/columns.mdx rename to content/docs/components/ink/layout/columns.mdx diff --git a/content/docs/components/layout/divider.mdx b/content/docs/components/ink/layout/divider.mdx similarity index 100% rename from content/docs/components/layout/divider.mdx rename to content/docs/components/ink/layout/divider.mdx diff --git a/content/docs/components/layout/grid.mdx b/content/docs/components/ink/layout/grid.mdx similarity index 100% rename from content/docs/components/layout/grid.mdx rename to content/docs/components/ink/layout/grid.mdx diff --git a/content/docs/components/layout/index.mdx b/content/docs/components/ink/layout/index.mdx similarity index 100% rename from content/docs/components/layout/index.mdx rename to content/docs/components/ink/layout/index.mdx diff --git a/content/docs/components/layout/meta.json b/content/docs/components/ink/layout/meta.json similarity index 100% rename from content/docs/components/layout/meta.json rename to content/docs/components/ink/layout/meta.json diff --git a/content/docs/components/layout/scroll-view.mdx b/content/docs/components/ink/layout/scroll-view.mdx similarity index 100% rename from content/docs/components/layout/scroll-view.mdx rename to content/docs/components/ink/layout/scroll-view.mdx diff --git a/content/docs/components/layout/spacer.mdx b/content/docs/components/ink/layout/spacer.mdx similarity index 100% rename from content/docs/components/layout/spacer.mdx rename to content/docs/components/ink/layout/spacer.mdx diff --git a/content/docs/components/layout/stack.mdx b/content/docs/components/ink/layout/stack.mdx similarity index 100% rename from content/docs/components/layout/stack.mdx rename to content/docs/components/ink/layout/stack.mdx diff --git a/content/docs/components/ink/meta.json b/content/docs/components/ink/meta.json new file mode 100644 index 0000000..e88c105 --- /dev/null +++ b/content/docs/components/ink/meta.json @@ -0,0 +1,17 @@ +{ + "title": "Ink", + "pages": [ + "layout", + "typography", + "input", + "selection", + "data", + "feedback", + "navigation", + "overlays", + "forms", + "utility", + "charts", + "ai" + ] +} diff --git a/content/docs/components/navigation/breadcrumb.mdx b/content/docs/components/ink/navigation/breadcrumb.mdx similarity index 100% rename from content/docs/components/navigation/breadcrumb.mdx rename to content/docs/components/ink/navigation/breadcrumb.mdx diff --git a/content/docs/components/navigation/command-palette.mdx b/content/docs/components/ink/navigation/command-palette.mdx similarity index 100% rename from content/docs/components/navigation/command-palette.mdx rename to content/docs/components/ink/navigation/command-palette.mdx diff --git a/content/docs/components/navigation/index.mdx b/content/docs/components/ink/navigation/index.mdx similarity index 100% rename from content/docs/components/navigation/index.mdx rename to content/docs/components/ink/navigation/index.mdx diff --git a/content/docs/components/navigation/menu.mdx b/content/docs/components/ink/navigation/menu.mdx similarity index 100% rename from content/docs/components/navigation/menu.mdx rename to content/docs/components/ink/navigation/menu.mdx diff --git a/content/docs/components/navigation/meta.json b/content/docs/components/ink/navigation/meta.json similarity index 100% rename from content/docs/components/navigation/meta.json rename to content/docs/components/ink/navigation/meta.json diff --git a/content/docs/components/navigation/pagination.mdx b/content/docs/components/ink/navigation/pagination.mdx similarity index 100% rename from content/docs/components/navigation/pagination.mdx rename to content/docs/components/ink/navigation/pagination.mdx diff --git a/content/docs/components/navigation/sidebar.mdx b/content/docs/components/ink/navigation/sidebar.mdx similarity index 100% rename from content/docs/components/navigation/sidebar.mdx rename to content/docs/components/ink/navigation/sidebar.mdx diff --git a/content/docs/components/navigation/tabbed-content.mdx b/content/docs/components/ink/navigation/tabbed-content.mdx similarity index 100% rename from content/docs/components/navigation/tabbed-content.mdx rename to content/docs/components/ink/navigation/tabbed-content.mdx diff --git a/content/docs/components/navigation/tabs.mdx b/content/docs/components/ink/navigation/tabs.mdx similarity index 100% rename from content/docs/components/navigation/tabs.mdx rename to content/docs/components/ink/navigation/tabs.mdx diff --git a/content/docs/components/overlays/dialog.mdx b/content/docs/components/ink/overlays/dialog.mdx similarity index 100% rename from content/docs/components/overlays/dialog.mdx rename to content/docs/components/ink/overlays/dialog.mdx diff --git a/content/docs/components/overlays/drawer.mdx b/content/docs/components/ink/overlays/drawer.mdx similarity index 100% rename from content/docs/components/overlays/drawer.mdx rename to content/docs/components/ink/overlays/drawer.mdx diff --git a/content/docs/components/overlays/index.mdx b/content/docs/components/ink/overlays/index.mdx similarity index 100% rename from content/docs/components/overlays/index.mdx rename to content/docs/components/ink/overlays/index.mdx diff --git a/content/docs/components/overlays/meta.json b/content/docs/components/ink/overlays/meta.json similarity index 100% rename from content/docs/components/overlays/meta.json rename to content/docs/components/ink/overlays/meta.json diff --git a/content/docs/components/overlays/modal.mdx b/content/docs/components/ink/overlays/modal.mdx similarity index 100% rename from content/docs/components/overlays/modal.mdx rename to content/docs/components/ink/overlays/modal.mdx diff --git a/content/docs/components/overlays/notification-center.mdx b/content/docs/components/ink/overlays/notification-center.mdx similarity index 100% rename from content/docs/components/overlays/notification-center.mdx rename to content/docs/components/ink/overlays/notification-center.mdx diff --git a/content/docs/components/overlays/popover.mdx b/content/docs/components/ink/overlays/popover.mdx similarity index 100% rename from content/docs/components/overlays/popover.mdx rename to content/docs/components/ink/overlays/popover.mdx diff --git a/content/docs/components/overlays/tooltip.mdx b/content/docs/components/ink/overlays/tooltip.mdx similarity index 100% rename from content/docs/components/overlays/tooltip.mdx rename to content/docs/components/ink/overlays/tooltip.mdx diff --git a/content/docs/components/selection/checkbox-group.mdx b/content/docs/components/ink/selection/checkbox-group.mdx similarity index 100% rename from content/docs/components/selection/checkbox-group.mdx rename to content/docs/components/ink/selection/checkbox-group.mdx diff --git a/content/docs/components/selection/checkbox.mdx b/content/docs/components/ink/selection/checkbox.mdx similarity index 100% rename from content/docs/components/selection/checkbox.mdx rename to content/docs/components/ink/selection/checkbox.mdx diff --git a/content/docs/components/selection/color-picker.mdx b/content/docs/components/ink/selection/color-picker.mdx similarity index 100% rename from content/docs/components/selection/color-picker.mdx rename to content/docs/components/ink/selection/color-picker.mdx diff --git a/content/docs/components/selection/index.mdx b/content/docs/components/ink/selection/index.mdx similarity index 100% rename from content/docs/components/selection/index.mdx rename to content/docs/components/ink/selection/index.mdx diff --git a/content/docs/components/selection/meta.json b/content/docs/components/ink/selection/meta.json similarity index 100% rename from content/docs/components/selection/meta.json rename to content/docs/components/ink/selection/meta.json diff --git a/content/docs/components/selection/multi-select.mdx b/content/docs/components/ink/selection/multi-select.mdx similarity index 100% rename from content/docs/components/selection/multi-select.mdx rename to content/docs/components/ink/selection/multi-select.mdx diff --git a/content/docs/components/selection/radio-group.mdx b/content/docs/components/ink/selection/radio-group.mdx similarity index 100% rename from content/docs/components/selection/radio-group.mdx rename to content/docs/components/ink/selection/radio-group.mdx diff --git a/content/docs/components/selection/select.mdx b/content/docs/components/ink/selection/select.mdx similarity index 100% rename from content/docs/components/selection/select.mdx rename to content/docs/components/ink/selection/select.mdx diff --git a/content/docs/components/selection/tag-input.mdx b/content/docs/components/ink/selection/tag-input.mdx similarity index 100% rename from content/docs/components/selection/tag-input.mdx rename to content/docs/components/ink/selection/tag-input.mdx diff --git a/content/docs/components/selection/tree-select.mdx b/content/docs/components/ink/selection/tree-select.mdx similarity index 100% rename from content/docs/components/selection/tree-select.mdx rename to content/docs/components/ink/selection/tree-select.mdx diff --git a/content/docs/components/typography/badge.mdx b/content/docs/components/ink/typography/badge.mdx similarity index 100% rename from content/docs/components/typography/badge.mdx rename to content/docs/components/ink/typography/badge.mdx diff --git a/content/docs/components/typography/big-text.mdx b/content/docs/components/ink/typography/big-text.mdx similarity index 100% rename from content/docs/components/typography/big-text.mdx rename to content/docs/components/ink/typography/big-text.mdx diff --git a/content/docs/components/typography/code.mdx b/content/docs/components/ink/typography/code.mdx similarity index 100% rename from content/docs/components/typography/code.mdx rename to content/docs/components/ink/typography/code.mdx diff --git a/content/docs/components/typography/digits.mdx b/content/docs/components/ink/typography/digits.mdx similarity index 100% rename from content/docs/components/typography/digits.mdx rename to content/docs/components/ink/typography/digits.mdx diff --git a/content/docs/components/typography/gradient.mdx b/content/docs/components/ink/typography/gradient.mdx similarity index 100% rename from content/docs/components/typography/gradient.mdx rename to content/docs/components/ink/typography/gradient.mdx diff --git a/content/docs/components/typography/heading.mdx b/content/docs/components/ink/typography/heading.mdx similarity index 100% rename from content/docs/components/typography/heading.mdx rename to content/docs/components/ink/typography/heading.mdx diff --git a/content/docs/components/typography/index.mdx b/content/docs/components/ink/typography/index.mdx similarity index 100% rename from content/docs/components/typography/index.mdx rename to content/docs/components/ink/typography/index.mdx diff --git a/content/docs/components/typography/link.mdx b/content/docs/components/ink/typography/link.mdx similarity index 100% rename from content/docs/components/typography/link.mdx rename to content/docs/components/ink/typography/link.mdx diff --git a/content/docs/components/typography/markdown.mdx b/content/docs/components/ink/typography/markdown.mdx similarity index 100% rename from content/docs/components/typography/markdown.mdx rename to content/docs/components/ink/typography/markdown.mdx diff --git a/content/docs/components/typography/meta.json b/content/docs/components/ink/typography/meta.json similarity index 100% rename from content/docs/components/typography/meta.json rename to content/docs/components/ink/typography/meta.json diff --git a/content/docs/components/typography/tag.mdx b/content/docs/components/ink/typography/tag.mdx similarity index 100% rename from content/docs/components/typography/tag.mdx rename to content/docs/components/ink/typography/tag.mdx diff --git a/content/docs/components/utility/clipboard.mdx b/content/docs/components/ink/utility/clipboard.mdx similarity index 100% rename from content/docs/components/utility/clipboard.mdx rename to content/docs/components/ink/utility/clipboard.mdx diff --git a/content/docs/components/utility/clock.mdx b/content/docs/components/ink/utility/clock.mdx similarity index 100% rename from content/docs/components/utility/clock.mdx rename to content/docs/components/ink/utility/clock.mdx diff --git a/content/docs/components/utility/embedded-terminal.mdx b/content/docs/components/ink/utility/embedded-terminal.mdx similarity index 100% rename from content/docs/components/utility/embedded-terminal.mdx rename to content/docs/components/ink/utility/embedded-terminal.mdx diff --git a/content/docs/components/utility/error-boundary.mdx b/content/docs/components/ink/utility/error-boundary.mdx similarity index 100% rename from content/docs/components/utility/error-boundary.mdx rename to content/docs/components/ink/utility/error-boundary.mdx diff --git a/content/docs/components/utility/help.mdx b/content/docs/components/ink/utility/help.mdx similarity index 100% rename from content/docs/components/utility/help.mdx rename to content/docs/components/ink/utility/help.mdx diff --git a/content/docs/components/utility/image.mdx b/content/docs/components/ink/utility/image.mdx similarity index 100% rename from content/docs/components/utility/image.mdx rename to content/docs/components/ink/utility/image.mdx diff --git a/content/docs/components/utility/index.mdx b/content/docs/components/ink/utility/index.mdx similarity index 100% rename from content/docs/components/utility/index.mdx rename to content/docs/components/ink/utility/index.mdx diff --git a/content/docs/components/utility/keyboard-shortcuts.mdx b/content/docs/components/ink/utility/keyboard-shortcuts.mdx similarity index 100% rename from content/docs/components/utility/keyboard-shortcuts.mdx rename to content/docs/components/ink/utility/keyboard-shortcuts.mdx diff --git a/content/docs/components/utility/log.mdx b/content/docs/components/ink/utility/log.mdx similarity index 100% rename from content/docs/components/utility/log.mdx rename to content/docs/components/ink/utility/log.mdx diff --git a/content/docs/components/utility/meta.json b/content/docs/components/ink/utility/meta.json similarity index 100% rename from content/docs/components/utility/meta.json rename to content/docs/components/ink/utility/meta.json diff --git a/content/docs/components/utility/panel.mdx b/content/docs/components/ink/utility/panel.mdx similarity index 100% rename from content/docs/components/utility/panel.mdx rename to content/docs/components/ink/utility/panel.mdx diff --git a/content/docs/components/utility/qr-code.mdx b/content/docs/components/ink/utility/qr-code.mdx similarity index 100% rename from content/docs/components/utility/qr-code.mdx rename to content/docs/components/ink/utility/qr-code.mdx diff --git a/content/docs/components/utility/stopwatch.mdx b/content/docs/components/ink/utility/stopwatch.mdx similarity index 100% rename from content/docs/components/utility/stopwatch.mdx rename to content/docs/components/ink/utility/stopwatch.mdx diff --git a/content/docs/components/utility/timer.mdx b/content/docs/components/ink/utility/timer.mdx similarity index 100% rename from content/docs/components/utility/timer.mdx rename to content/docs/components/ink/utility/timer.mdx diff --git a/content/docs/components/utility/toggle.mdx b/content/docs/components/ink/utility/toggle.mdx similarity index 100% rename from content/docs/components/utility/toggle.mdx rename to content/docs/components/ink/utility/toggle.mdx diff --git a/content/docs/components/meta.json b/content/docs/components/meta.json index dab882a..b366d3b 100644 --- a/content/docs/components/meta.json +++ b/content/docs/components/meta.json @@ -1,17 +1,4 @@ { - "pages": [ - "layout", - "typography", - "input", - "selection", - "data", - "feedback", - "navigation", - "overlays", - "forms", - "utility", - "charts", - "ai" - ], - "title": "Components" + "title": "Components", + "pages": ["..."] } diff --git a/content/docs/components/opentui/ai/chat-message.mdx b/content/docs/components/opentui/ai/chat-message.mdx new file mode 100644 index 0000000..dac590c --- /dev/null +++ b/content/docs/components/opentui/ai/chat-message.mdx @@ -0,0 +1,63 @@ +--- +title: "Chat Message" +description: "Chat message bubble with role label, streaming indicator, and collapsible content" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/chat-message.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { ChatMessage } from "@/components/ui/chat-message"; +``` + +```tsx + + Here is the refactored version of your function. + +``` + +## API Reference + +### ChatMessage + +| Prop | Type | Default | +| ----------- | ---------------------------------------------- | ----------- | +| `sender` | `"user" \| "assistant" \| "system" \| "error"` | `required` | +| `name` | `string` | `undefined` | +| `timestamp` | `Date` | `undefined` | +| `streaming` | `boolean` | `false` | +| `collapsed` | `boolean` | `undefined` | +| `children` | `ReactNode` | `undefined` | diff --git a/content/docs/components/opentui/ai/chat-thread.mdx b/content/docs/components/opentui/ai/chat-thread.mdx new file mode 100644 index 0000000..e0cd85b --- /dev/null +++ b/content/docs/components/opentui/ai/chat-thread.mdx @@ -0,0 +1,64 @@ +--- +title: "Chat Thread" +description: "Scrollable container for stacking ChatMessage components in a conversation thread" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/chat-thread.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { ChatThread } from "@/components/ui/chat-thread"; +import { ChatMessage } from "@/components/ui/chat-message"; +``` + +```tsx + + How do I center a div? + + Use flexbox: display flex, justify-content center, align-items center. + + +``` + +## API Reference + +### ChatThread + +| Prop | Type | Default | +| ------------ | ----------- | ----------- | +| `maxHeight` | `number` | `undefined` | +| `autoScroll` | `boolean` | `true` | +| `children` | `ReactNode` | `undefined` | diff --git a/content/docs/components/opentui/ai/file-change.mdx b/content/docs/components/opentui/ai/file-change.mdx new file mode 100644 index 0000000..56eca93 --- /dev/null +++ b/content/docs/components/opentui/ai/file-change.mdx @@ -0,0 +1,72 @@ +--- +title: "File Change" +description: "Interactive file-change review list with diff expansion, per-file accept/reject actions, and accept-all shortcut" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/file-change.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { FileChange } from "@/components/ui/file-change"; +``` + +```tsx + a + b;", + }, + { path: "src/legacy.ts", type: "delete" }, + ]} + onAccept={(path) => console.log("accepted", path)} + onReject={(path) => console.log("rejected", path)} + onAcceptAll={() => console.log("accepted all")} +/> +``` + +## API Reference + +### FileChange + +| Prop | Type | Default | +| ------------- | ------------------------ | ----------- | +| `changes` | `FileChangeItem[]` | `required` | +| `onAccept` | `(path: string) => void` | `undefined` | +| `onReject` | `(path: string) => void` | `undefined` | +| `onAcceptAll` | `() => void` | `undefined` | diff --git a/content/docs/components/opentui/ai/index.mdx b/content/docs/components/opentui/ai/index.mdx new file mode 100644 index 0000000..b911a75 --- /dev/null +++ b/content/docs/components/opentui/ai/index.mdx @@ -0,0 +1,6 @@ +--- +title: "AI" +description: "Components for building AI-powered chat interfaces and tool interactions." +--- + + diff --git a/content/docs/components/opentui/ai/meta.json b/content/docs/components/opentui/ai/meta.json new file mode 100644 index 0000000..bc25bf3 --- /dev/null +++ b/content/docs/components/opentui/ai/meta.json @@ -0,0 +1,14 @@ +{ + "pages": [ + "chat-message", + "chat-thread", + "file-change", + "model-selector", + "streaming-text", + "thinking-block", + "token-usage", + "tool-approval", + "tool-call" + ], + "title": "AI" +} diff --git a/content/docs/components/opentui/ai/model-selector.mdx b/content/docs/components/opentui/ai/model-selector.mdx new file mode 100644 index 0000000..a4a7108 --- /dev/null +++ b/content/docs/components/opentui/ai/model-selector.mdx @@ -0,0 +1,76 @@ +--- +title: "Model Selector" +description: "Keyboard-navigable list for selecting an AI model, with optional provider grouping and context-window display" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/model-selector.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { ModelSelector } from "@/components/ui/model-selector"; +``` + +```tsx + console.log("selected", id)} +/> +``` + +## API Reference + +### ModelSelector + +| Prop | Type | Default | +| ----------------- | ---------------------- | ---------- | +| `models` | `ModelOption[]` | `required` | +| `selected` | `string` | `required` | +| `onSelect` | `(id: string) => void` | `required` | +| `showContext` | `boolean` | `true` | +| `showProvider` | `boolean` | `true` | +| `groupByProvider` | `boolean` | `false` | diff --git a/content/docs/components/opentui/ai/streaming-text.mdx b/content/docs/components/opentui/ai/streaming-text.mdx new file mode 100644 index 0000000..f269842 --- /dev/null +++ b/content/docs/components/opentui/ai/streaming-text.mdx @@ -0,0 +1,65 @@ +--- +title: "Streaming Text" +description: "Token-by-token streaming text with blinking cursor and optional typing animation" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/streaming-text.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { StreamingText } from "@/components/ui/streaming-text"; +``` + +```tsx + +``` + +## API Reference + +### StreamingText + +| Prop | Type | Default | +| ------------- | ---------------------------- | ----------- | +| `text` | `string` | `undefined` | +| `stream` | `AsyncIterable` | `undefined` | +| `cursor` | `boolean` | `true` | +| `animate` | `boolean` | `false` | +| `speed` | `number` | `30` | +| `onComplete` | `(fullText: string) => void` | `undefined` | +| `cursorColor` | `string` | `undefined` | diff --git a/content/docs/components/opentui/ai/thinking-block.mdx b/content/docs/components/opentui/ai/thinking-block.mdx new file mode 100644 index 0000000..fc80ee9 --- /dev/null +++ b/content/docs/components/opentui/ai/thinking-block.mdx @@ -0,0 +1,68 @@ +--- +title: "Thinking Block" +description: "Collapsible block for displaying extended thinking / reasoning content from an AI model" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/thinking-block.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { ThinkingBlock } from "@/components/ui/thinking-block"; +``` + +```tsx + +``` + +## API Reference + +### ThinkingBlock + +| Prop | Type | Default | +| ------------------ | --------- | ------------- | +| `content` | `string` | `required` | +| `streaming` | `boolean` | `false` | +| `defaultCollapsed` | `boolean` | `true` | +| `label` | `string` | `"Reasoning"` | +| `tokenCount` | `number` | `undefined` | +| `duration` | `number` | `undefined` | diff --git a/content/docs/components/opentui/ai/token-usage.mdx b/content/docs/components/opentui/ai/token-usage.mdx new file mode 100644 index 0000000..e94b87b --- /dev/null +++ b/content/docs/components/opentui/ai/token-usage.mdx @@ -0,0 +1,71 @@ +--- +title: "Token Usage" +description: "Compact token counter showing prompt and completion usage with optional cost estimate; also exports ContextMeter for visualising context window fill" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/token-usage.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { TokenUsage, ContextMeter } from "@/components/ui/token-usage"; +``` + +```tsx + +``` + +## API Reference + +### TokenUsage + +| Prop | Type | Default | +| ------------ | --------- | ----------- | +| `prompt` | `number` | `required` | +| `completion` | `number` | `required` | +| `model` | `string` | `undefined` | +| `showCost` | `boolean` | `false` | + +### ContextMeter + +| Prop | Type | Default | +| ------------- | --------- | ----------- | +| `used` | `number` | `required` | +| `limit` | `number` | `required` | +| `label` | `string` | `undefined` | +| `showPercent` | `boolean` | `true` | +| `warnAt` | `number` | `75` | +| `criticalAt` | `number` | `90` | +| `width` | `number` | `20` | diff --git a/content/docs/components/opentui/ai/tool-approval.mdx b/content/docs/components/opentui/ai/tool-approval.mdx new file mode 100644 index 0000000..3a37f65 --- /dev/null +++ b/content/docs/components/opentui/ai/tool-approval.mdx @@ -0,0 +1,71 @@ +--- +title: "Tool Approval" +description: "Interactive approval prompt for AI tool calls with risk-level badge, args display, and auto-deny timeout" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/tool-approval.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { ToolApproval } from "@/components/ui/tool-approval"; +``` + +```tsx + console.log("approved")} + onDeny={() => console.log("denied")} + timeout={30} +/> +``` + +## API Reference + +### ToolApproval + +| Prop | Type | Default | +| --------------- | ----------------------------- | ----------- | +| `name` | `string` | `required` | +| `description` | `string` | `undefined` | +| `args` | `Record` | `undefined` | +| `risk` | `"low" \| "medium" \| "high"` | `"low"` | +| `onApprove` | `() => void` | `required` | +| `onDeny` | `() => void` | `required` | +| `onAlwaysAllow` | `() => void` | `undefined` | +| `timeout` | `number` | `undefined` | diff --git a/content/docs/components/opentui/ai/tool-call.mdx b/content/docs/components/opentui/ai/tool-call.mdx new file mode 100644 index 0000000..30517d7 --- /dev/null +++ b/content/docs/components/opentui/ai/tool-call.mdx @@ -0,0 +1,68 @@ +--- +title: "Tool Call" +description: "Displays an AI tool invocation with status indicator, args, result, and elapsed time" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/tool-call.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { ToolCall } from "@/components/ui/tool-call"; +``` + +```tsx + +``` + +## API Reference + +### ToolCall + +| Prop | Type | Default | +| ------------------ | ------------------------------------------------ | ----------- | +| `name` | `string` | `required` | +| `args` | `Record` | `undefined` | +| `status` | `"pending" \| "running" \| "success" \| "error"` | `required` | +| `result` | `unknown` | `undefined` | +| `duration` | `number` | `undefined` | +| `collapsible` | `boolean` | `true` | +| `defaultCollapsed` | `boolean` | `true` | diff --git a/content/docs/components/opentui/charts/bar-chart.mdx b/content/docs/components/opentui/charts/bar-chart.mdx new file mode 100644 index 0000000..af07d46 --- /dev/null +++ b/content/docs/components/opentui/charts/bar-chart.mdx @@ -0,0 +1,69 @@ +--- +title: "Bar Chart" +description: "Horizontal and vertical bar chart with labels" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/bar-chart.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { BarChart } from "@/components/ui/bar-chart"; +``` + +```tsx + +``` + +## API Reference + +### BarChart + +| Prop | Type | Default | +| ------------ | ---------------------------- | -------------- | +| `data` | `BarChartItem[]` | `required` | +| `direction` | `"horizontal" \| "vertical"` | `"horizontal"` | +| `width` | `number` | `30` | +| `height` | `number` | `10` | +| `showValues` | `boolean` | `true` | +| `title` | `string` | `undefined` | diff --git a/content/docs/components/opentui/charts/gauge.mdx b/content/docs/components/opentui/charts/gauge.mdx new file mode 100644 index 0000000..23a309b --- /dev/null +++ b/content/docs/components/opentui/charts/gauge.mdx @@ -0,0 +1,61 @@ +--- +title: "Gauge" +description: "Arc/speedometer gauge meter" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/gauge.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { Gauge } from "@/components/ui/gauge"; +``` + +```tsx + +``` + +## API Reference + +### Gauge + +| Prop | Type | Default | +| ------- | ---------------------- | ----------- | +| `value` | `number` | `required` | +| `min` | `number` | `0` | +| `max` | `number` | `100` | +| `label` | `string` | `undefined` | +| `color` | `string` | `undefined` | +| `size` | `"sm" \| "md" \| "lg"` | `"md"` | diff --git a/content/docs/components/opentui/charts/heat-map.mdx b/content/docs/components/opentui/charts/heat-map.mdx new file mode 100644 index 0000000..1a332c7 --- /dev/null +++ b/content/docs/components/opentui/charts/heat-map.mdx @@ -0,0 +1,69 @@ +--- +title: "Heat Map" +description: "Grid heatmap with color intensity scale" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/heat-map.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { HeatMap } from "@/components/ui/heat-map"; +``` + +```tsx + +``` + +## API Reference + +### HeatMap + +| Prop | Type | Default | +| ------------ | ------------ | --------------------- | +| `data` | `number[][]` | `required` | +| `rowLabels` | `string[]` | `undefined` | +| `colLabels` | `string[]` | `undefined` | +| `colorScale` | `string[]` | `DEFAULT_COLOR_SCALE` | +| `cellWidth` | `number` | `5` | +| `showValues` | `boolean` | `false` | diff --git a/content/docs/components/opentui/charts/index.mdx b/content/docs/components/opentui/charts/index.mdx new file mode 100644 index 0000000..0daee64 --- /dev/null +++ b/content/docs/components/opentui/charts/index.mdx @@ -0,0 +1,6 @@ +--- +title: "Charts" +description: "Components for rendering charts and data visualizations in the terminal." +--- + + diff --git a/content/docs/components/opentui/charts/line-chart.mdx b/content/docs/components/opentui/charts/line-chart.mdx new file mode 100644 index 0000000..fb7ce56 --- /dev/null +++ b/content/docs/components/opentui/charts/line-chart.mdx @@ -0,0 +1,70 @@ +--- +title: "Line Chart" +description: "ASCII line chart with axes and multi-series support" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/line-chart.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { LineChart } from "@/components/ui/line-chart"; +``` + +```tsx + +``` + +## API Reference + +### LineChart + +| Prop | Type | Default | +| ---------- | ------------------------------------------------- | ----------- | +| `data` | `(number \| { label?: string; value: number })[]` | `required` | +| `width` | `number` | `40` | +| `height` | `number` | `10` | +| `title` | `string` | `undefined` | +| `color` | `string` | `undefined` | +| `showAxes` | `boolean` | `true` | diff --git a/content/docs/components/opentui/charts/meta.json b/content/docs/components/opentui/charts/meta.json new file mode 100644 index 0000000..5ae91d6 --- /dev/null +++ b/content/docs/components/opentui/charts/meta.json @@ -0,0 +1,11 @@ +{ + "pages": [ + "bar-chart", + "gauge", + "heat-map", + "line-chart", + "pie-chart", + "sparkline" + ], + "title": "Charts" +} diff --git a/content/docs/components/opentui/charts/pie-chart.mdx b/content/docs/components/opentui/charts/pie-chart.mdx new file mode 100644 index 0000000..10caa90 --- /dev/null +++ b/content/docs/components/opentui/charts/pie-chart.mdx @@ -0,0 +1,66 @@ +--- +title: "Pie Chart" +description: "Unicode block pie chart with legend" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/pie-chart.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { PieChart } from "@/components/ui/pie-chart"; +``` + +```tsx + +``` + +## API Reference + +### PieChart + +| Prop | Type | Default | +| ----------------- | ---------------- | ---------- | +| `data` | `PieChartItem[]` | `required` | +| `radius` | `number` | `5` | +| `showLegend` | `boolean` | `true` | +| `showPercentages` | `boolean` | `true` | diff --git a/content/docs/components/opentui/charts/sparkline.mdx b/content/docs/components/opentui/charts/sparkline.mdx new file mode 100644 index 0000000..fb5def9 --- /dev/null +++ b/content/docs/components/opentui/charts/sparkline.mdx @@ -0,0 +1,59 @@ +--- +title: "Sparkline" +description: "Inline Unicode braille sparkline chart" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/sparkline.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { Sparkline } from "@/components/ui/sparkline"; +``` + +```tsx + +``` + +## API Reference + +### Sparkline + +| Prop | Type | Default | +| ------- | ---------- | ----------- | +| `data` | `number[]` | `required` | +| `width` | `number` | `20` | +| `color` | `string` | `undefined` | +| `label` | `string` | `undefined` | diff --git a/content/docs/components/opentui/data/card.mdx b/content/docs/components/opentui/data/card.mdx new file mode 100644 index 0000000..43693fc --- /dev/null +++ b/content/docs/components/opentui/data/card.mdx @@ -0,0 +1,67 @@ +--- +title: "Card" +description: "Card with header, body, and footer slots" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/card.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { Card } from "@/components/ui/card"; +``` + +```tsx + + CPU: 4 cores @ 3.2 GHz + +``` + +## API Reference + +### Card + +| Prop | Type | Default | +| ------------------- | -------------------------------------------------------------------------------------------- | ----------- | +| `title` | `string` | `undefined` | +| `subtitle` | `string` | `undefined` | +| `children` | `ReactNode` | `required` | +| `footer` | `ReactNode` | `undefined` | +| `borderColor` | `string` | `undefined` | +| `width` | `number` | `undefined` | +| `borderStyle` | `"single" \| "double" \| "round" \| "bold" \| "singleDouble" \| "doubleSingle" \| "classic"` | `"round"` | +| `paddingX` | `number` | `1` | +| `paddingY` | `number` | `0` | +| `footerDividerChar` | `string` | `"─"` | diff --git a/content/docs/components/opentui/data/data-grid.mdx b/content/docs/components/opentui/data/data-grid.mdx new file mode 100644 index 0000000..d947545 --- /dev/null +++ b/content/docs/components/opentui/data/data-grid.mdx @@ -0,0 +1,86 @@ +--- +title: "Data Grid" +description: "Advanced data grid with sorting, filtering, pagination, and cell editing" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/data-grid.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { DataGrid } from "@/components/ui/data-grid"; +``` + +```tsx + +``` + +## API Reference + +### DataGrid + +| Prop | Type | Default | +| ------------------- | ---------------------------------------------- | ----------- | +| `data` | `T[]` | `required` | +| `columns` | `DataGridColumn[]` | `required` | +| `pageSize` | `number` | `10` | +| `onRowSelect` | `(row: T) => void` | `undefined` | +| `onCellEdit` | `(row: T, key: string, value: string) => void` | `undefined` | +| `borderColor` | `string` | `undefined` | +| `borderStyle` | `"single" \| "double" \| "round" \| "bold"` | `"single"` | +| `showRowNumbers` | `boolean` | `false` | +| `filterPlaceholder` | `string` | `undefined` | + +### DataGridColumn + +| Prop | Type | Default | +| ------------ | ------------------------------------ | ----------- | +| `key` | `keyof T & string` | `required` | +| `header` | `string` | `required` | +| `width` | `number` | `undefined` | +| `align` | `"left" \| "right" \| "center"` | `"left"` | +| `render` | `(value: unknown, row: T) => string` | `undefined` | +| `filterable` | `boolean` | `undefined` | +| `sortable` | `boolean` | `undefined` | diff --git a/content/docs/components/opentui/data/definition.mdx b/content/docs/components/opentui/data/definition.mdx new file mode 100644 index 0000000..0cff91b --- /dev/null +++ b/content/docs/components/opentui/data/definition.mdx @@ -0,0 +1,69 @@ +--- +title: "Definition" +description: "Term–description definition list" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/definition.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { Definition } from "@/components/ui/definition"; +``` + +```tsx + +``` + +## API Reference + +### Definition + +| Prop | Type | Default | +| ----------- | ------------------ | ----------- | +| `items` | `DefinitionItem[]` | `required` | +| `termColor` | `string` | `undefined` | + +### DefinitionItem + +| Prop | Type | Default | +| ------------- | -------- | ---------- | +| `term` | `string` | `required` | +| `description` | `string` | `required` | diff --git a/content/docs/components/opentui/data/diff-view.mdx b/content/docs/components/opentui/data/diff-view.mdx new file mode 100644 index 0000000..56df0e9 --- /dev/null +++ b/content/docs/components/opentui/data/diff-view.mdx @@ -0,0 +1,66 @@ +--- +title: "Diff View" +description: "Unified, split, and inline diff viewer with LCS-based diff algorithm and line numbers" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/diff-view.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { DiffView } from "@/components/ui/diff-view"; +``` + +```tsx + +``` + +## API Reference + +### DiffView + +| Prop | Type | Default | +| ----------------- | ---------------------------------- | ----------- | +| `oldText` | `string` | `required` | +| `newText` | `string` | `required` | +| `filename` | `string` | `undefined` | +| `language` | `string` | `undefined` | +| `mode` | `"unified" \| "split" \| "inline"` | `"unified"` | +| `context` | `number` | `3` | +| `showLineNumbers` | `boolean` | `false` | diff --git a/content/docs/components/opentui/data/directory-tree.mdx b/content/docs/components/opentui/data/directory-tree.mdx new file mode 100644 index 0000000..8298fc1 --- /dev/null +++ b/content/docs/components/opentui/data/directory-tree.mdx @@ -0,0 +1,67 @@ +--- +title: "Directory Tree" +description: "Filesystem browser with expand/collapse" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/directory-tree.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { DirectoryTree } from "@/components/ui/directory-tree"; +``` + +```tsx + +``` + +## API Reference + +### DirectoryTree + +| Prop | Type | Default | +| ------------ | ------------------------ | --------------- | +| `rootPath` | `string` | `process.cwd()` | +| `onSelect` | `(path: string) => void` | `undefined` | +| `maxDepth` | `number` | `2` | +| `showHidden` | `boolean` | `false` | +| `label` | `string` | `undefined` | diff --git a/content/docs/components/opentui/data/git-status.mdx b/content/docs/components/opentui/data/git-status.mdx new file mode 100644 index 0000000..ca0438b --- /dev/null +++ b/content/docs/components/opentui/data/git-status.mdx @@ -0,0 +1,60 @@ +--- +title: "Git Status" +description: "Git status display (branch, staged, modified, ahead/behind)" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/git-status.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { GitStatus } from "@/components/ui/git-status"; +``` + +```tsx + +``` + +## API Reference + +### GitStatus + +| Prop | Type | Default | +| ---------- | -------- | ---------- | +| `branch` | `string` | `required` | +| `staged` | `number` | `0` | +| `modified` | `number` | `0` | +| `ahead` | `number` | `0` | +| `behind` | `number` | `0` | diff --git a/content/docs/components/opentui/data/index.mdx b/content/docs/components/opentui/data/index.mdx new file mode 100644 index 0000000..5a7a0d1 --- /dev/null +++ b/content/docs/components/opentui/data/index.mdx @@ -0,0 +1,6 @@ +--- +title: "Data" +description: "Components for displaying and visualizing structured data in the terminal." +--- + + diff --git a/content/docs/components/opentui/data/json.mdx b/content/docs/components/opentui/data/json.mdx new file mode 100644 index 0000000..251b239 --- /dev/null +++ b/content/docs/components/opentui/data/json.mdx @@ -0,0 +1,66 @@ +--- +title: "JSON" +description: "Pretty-printed JSON with collapsible nodes" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/json.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { JSONView } from "@/components/ui/json"; +``` + +```tsx + +``` + +## API Reference + +### JSONView + +| Prop | Type | Default | +| ----------- | --------- | ----------- | +| `data` | `unknown` | `required` | +| `indent` | `number` | `2` | +| `collapsed` | `boolean` | `false` | +| `label` | `string` | `undefined` | diff --git a/content/docs/components/opentui/data/key-value.mdx b/content/docs/components/opentui/data/key-value.mdx new file mode 100644 index 0000000..976d93e --- /dev/null +++ b/content/docs/components/opentui/data/key-value.mdx @@ -0,0 +1,74 @@ +--- +title: "Key Value" +description: "Aligned key–value pairs" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/key-value.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { KeyValue } from "@/components/ui/key-value"; +``` + +```tsx + +``` + +## API Reference + +### KeyValue + +| Prop | Type | Default | +| ------------ | ---------------- | ----------- | +| `items` | `KeyValueItem[]` | `required` | +| `keyWidth` | `number` | `undefined` | +| `separator` | `string` | `":"` | +| `keyColor` | `string` | `undefined` | +| `valueColor` | `string` | `undefined` | + +### KeyValueItem + +| Prop | Type | Default | +| ------- | ----------- | ----------- | +| `key` | `string` | `required` | +| `value` | `ReactNode` | `required` | +| `color` | `string` | `undefined` | diff --git a/content/docs/components/opentui/data/list.mdx b/content/docs/components/opentui/data/list.mdx new file mode 100644 index 0000000..e690e95 --- /dev/null +++ b/content/docs/components/opentui/data/list.mdx @@ -0,0 +1,76 @@ +--- +title: "List" +description: "Navigable list with optional filtering" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/list.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { List } from "@/components/ui/list"; +``` + +```tsx + console.log(item.key)} +/> +``` + +## API Reference + +### List + +| Prop | Type | Default | +| ------------ | -------------------------- | ----------- | +| `items` | `ListItem[]` | `required` | +| `onSelect` | `(item: ListItem) => void` | `undefined` | +| `filterable` | `boolean` | `false` | +| `height` | `number` | `10` | +| `cursor` | `string` | `"›"` | + +### ListItem + +| Prop | Type | Default | +| ------------- | -------- | ----------- | +| `key` | `string` | `required` | +| `label` | `string` | `required` | +| `description` | `string` | `undefined` | +| `color` | `string` | `undefined` | diff --git a/content/docs/components/opentui/data/meta.json b/content/docs/components/opentui/data/meta.json new file mode 100644 index 0000000..c2d8110 --- /dev/null +++ b/content/docs/components/opentui/data/meta.json @@ -0,0 +1,17 @@ +{ + "pages": [ + "card", + "data-grid", + "definition", + "diff-view", + "directory-tree", + "git-status", + "json", + "key-value", + "list", + "table", + "tree", + "virtual-list" + ], + "title": "Data" +} diff --git a/content/docs/components/opentui/data/table.mdx b/content/docs/components/opentui/data/table.mdx new file mode 100644 index 0000000..8fd7a82 --- /dev/null +++ b/content/docs/components/opentui/data/table.mdx @@ -0,0 +1,97 @@ +--- +title: "Table" +description: "Sortable, selectable, paginated data table" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/table.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { Table } from "@/components/ui/table"; +``` + +```tsx + +``` + +## Examples + +### Sortable + +Enable keyboard-driven column sorting with `sortable`. Use arrow keys to navigate columns and press `s` to sort. + + + +### Selectable rows + +Use `selectable` with `onSelect` to choose a row with the arrow keys and Enter. + + + +## API Reference + +### Table + +The table draws a fixed-width grid with Unicode box-drawing characters (`╭`, `├`, `│`, …). Width follows column content; it does not stretch to the full terminal width. + +| Prop | Type | Default | +| ------------- | ------------------ | ----------- | +| `data` | `T[]` | `required` | +| `columns` | `Column[]` | `required` | +| `sortable` | `boolean` | `false` | +| `selectable` | `boolean` | `false` | +| `onSelect` | `(row: T) => void` | `undefined` | +| `maxRows` | `number` | `20` | +| `borderColor` | `string` | `undefined` | + +### Column + +| Prop | Type | Default | +| -------- | ------------------------------- | ----------- | +| `key` | `keyof T & string` | `required` | +| `header` | `string` | `required` | +| `width` | `number` | `undefined` | +| `align` | `"left" \| "right" \| "center"` | `"left"` | diff --git a/content/docs/components/opentui/data/tree.mdx b/content/docs/components/opentui/data/tree.mdx new file mode 100644 index 0000000..8e83b30 --- /dev/null +++ b/content/docs/components/opentui/data/tree.mdx @@ -0,0 +1,83 @@ +--- +title: "Tree" +description: "Expandable/collapsible tree view" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/tree.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { Tree } from "@/components/ui/tree"; +``` + +```tsx + +``` + +## API Reference + +### Tree + +| Prop | Type | Default | +| ----------------- | -------------------------- | ----------- | +| `nodes` | `TreeNode[]` | `required` | +| `onSelect` | `(node: TreeNode) => void` | `undefined` | +| `defaultExpanded` | `string[]` | `[]` | +| `expandedIcon` | `string` | `"▼"` | +| `collapsedIcon` | `string` | `"▶"` | +| `leafIcon` | `string` | `"•"` | + +### TreeNode + +| Prop | Type | Default | +| ---------- | ------------ | ----------- | +| `key` | `string` | `required` | +| `label` | `string` | `required` | +| `children` | `TreeNode[]` | `undefined` | +| `icon` | `string` | `undefined` | diff --git a/content/docs/components/opentui/data/virtual-list.mdx b/content/docs/components/opentui/data/virtual-list.mdx new file mode 100644 index 0000000..641b694 --- /dev/null +++ b/content/docs/components/opentui/data/virtual-list.mdx @@ -0,0 +1,65 @@ +--- +title: "Virtual List" +description: "Virtualized list for 10k+ items" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/virtual-list.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { VirtualList } from "@/components/ui/virtual-list"; +``` + +```tsx + `Item ${i + 1}`)} + height={10} + renderItem={(item, index, isActive) => {item}} +/> +``` + +## API Reference + +### VirtualList + +| Prop | Type | Default | +| ------------ | ---------------------------------------------------------- | ----------- | +| `items` | `T[]` | `required` | +| `renderItem` | `(item: T, index: number, isActive: boolean) => ReactNode` | `required` | +| `height` | `number` | `required` | +| `onSelect` | `(item: T, index: number) => void` | `undefined` | +| `cursor` | `string` | `undefined` | +| `overscan` | `number` | `2` | diff --git a/content/docs/components/opentui/feedback/alert.mdx b/content/docs/components/opentui/feedback/alert.mdx new file mode 100644 index 0000000..bd5f542 --- /dev/null +++ b/content/docs/components/opentui/feedback/alert.mdx @@ -0,0 +1,92 @@ +--- +title: "Alert" +description: "Alert box with success/error/warning/info variants" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/alert.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { Alert } from "@/components/ui/alert"; +``` + +```tsx + + Everything is ready to ship. + +``` + +## Examples + +### Error + +Use `variant="error"` to display an error alert. + + + +### Warning + +Use `variant="warning"` to display a warning alert. + + + +### Without Border + +Set `bordered={false}` to remove the border. + + + +### Custom Icon and Color + +Override the icon and color with `icon` and `color` props. + + + +## API Reference + +### Alert + +| Prop | Type | Default | +| ------------- | -------------------------------------------------------------------------------------------- | ----------- | +| `variant` | `"success" \| "error" \| "warning" \| "info"` | `"info"` | +| `title` | `string` | `undefined` | +| `children` | `ReactNode` | `undefined` | +| `icon` | `string` | `undefined` | +| `bordered` | `boolean` | `true` | +| `borderStyle` | `"single" \| "double" \| "round" \| "bold" \| "singleDouble" \| "doubleSingle" \| "classic"` | `undefined` | +| `color` | `string` | `undefined` | +| `paddingX` | `number` | `1` | +| `paddingY` | `number` | `0` | diff --git a/content/docs/components/opentui/feedback/banner.mdx b/content/docs/components/opentui/feedback/banner.mdx new file mode 100644 index 0000000..793611e --- /dev/null +++ b/content/docs/components/opentui/feedback/banner.mdx @@ -0,0 +1,76 @@ +--- +title: "Banner" +description: "Full-width announcement banner" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/banner.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { Banner } from "@/components/ui/banner"; +``` + +```tsx + + A new version is available. Run npx update to upgrade. + +``` + +## Examples + +### Success Banner + + + +### Error with Custom Icon + + + +## API Reference + +### Banner + +| Prop | Type | Default | +| ------------- | ---------------------------------------------------------- | ----------- | +| `children` | `ReactNode` | `required` | +| `variant` | `"info" \| "warning" \| "error" \| "success" \| "neutral"` | `"info"` | +| `icon` | `string` | `undefined` | +| `title` | `string` | `undefined` | +| `dismissible` | `boolean` | `false` | +| `onDismiss` | `() => void` | `undefined` | +| `color` | `string` | `undefined` | +| `accentChar` | `string` | `"┃"` | +| `gap` | `number` | `1` | diff --git a/content/docs/components/opentui/feedback/index.mdx b/content/docs/components/opentui/feedback/index.mdx new file mode 100644 index 0000000..90224f2 --- /dev/null +++ b/content/docs/components/opentui/feedback/index.mdx @@ -0,0 +1,6 @@ +--- +title: "Feedback" +description: "Components for showing progress, status, and notifications in the terminal." +--- + + diff --git a/content/docs/components/opentui/feedback/meta.json b/content/docs/components/opentui/feedback/meta.json new file mode 100644 index 0000000..501dd5e --- /dev/null +++ b/content/docs/components/opentui/feedback/meta.json @@ -0,0 +1,14 @@ +{ + "pages": [ + "alert", + "banner", + "multi-progress", + "progress-bar", + "progress-circle", + "skeleton", + "spinner", + "status-message", + "toast" + ], + "title": "Feedback" +} diff --git a/content/docs/components/opentui/feedback/multi-progress.mdx b/content/docs/components/opentui/feedback/multi-progress.mdx new file mode 100644 index 0000000..4b78ba8 --- /dev/null +++ b/content/docs/components/opentui/feedback/multi-progress.mdx @@ -0,0 +1,92 @@ +--- +title: "Multi Progress" +description: "Parallel progress display for package managers, build pipelines, and deploy tools" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/multi-progress.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { MultiProgress } from "@/components/ui/multi-progress"; +``` + +```tsx + +``` + +## Examples + +### Compact Mode + + + +## API Reference + +### MultiProgress + +| Prop | Type | Default | +| ------------- | --------------------- | ---------- | +| `items` | `MultiProgressItem[]` | `required` | +| `barWidth` | `number` | `20` | +| `labelWidth` | `number` | `20` | +| `compact` | `boolean` | `false` | +| `showPercent` | `boolean` | `true` | + +### MultiProgressItem + +| Prop | Type | Default | +| ------------ | --------------------------------------------- | ----------- | +| `id` | `string` | `required` | +| `label` | `string` | `required` | +| `value` | `number` | `required` | +| `total` | `number` | `required` | +| `status` | `"pending" \| "running" \| "done" \| "error"` | `undefined` | +| `statusText` | `string` | `undefined` | diff --git a/content/docs/components/opentui/feedback/progress-bar.mdx b/content/docs/components/opentui/feedback/progress-bar.mdx new file mode 100644 index 0000000..a75338a --- /dev/null +++ b/content/docs/components/opentui/feedback/progress-bar.mdx @@ -0,0 +1,70 @@ +--- +title: "Progress Bar" +description: "Determinate progress bar with percent and value/total display" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/progress-bar.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { ProgressBar } from "@/components/ui/progress-bar"; +``` + +```tsx + +``` + +## Examples + +### Custom Characters and Color + + + +## API Reference + +### ProgressBar + +| Prop | Type | Default | +| ------------- | --------- | ----------- | +| `value` | `number` | `required` | +| `total` | `number` | `undefined` | +| `width` | `number` | `30` | +| `showPercent` | `boolean` | `true` | +| `showEta` | `boolean` | `false` | +| `fillChar` | `string` | `"█"` | +| `emptyChar` | `string` | `"░"` | +| `color` | `string` | `undefined` | +| `label` | `string` | `undefined` | diff --git a/content/docs/components/opentui/feedback/progress-circle.mdx b/content/docs/components/opentui/feedback/progress-circle.mdx new file mode 100644 index 0000000..9167278 --- /dev/null +++ b/content/docs/components/opentui/feedback/progress-circle.mdx @@ -0,0 +1,69 @@ +--- +title: "Progress Circle" +description: "Circular progress indicator using Unicode braille" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/progress-circle.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { ProgressCircle } from "@/components/ui/progress-circle"; +``` + +```tsx + +``` + +## Examples + +### Sizes + + + +## API Reference + +### ProgressCircle + +| Prop | Type | Default | +| ------------- | ---------------------- | ----------- | +| `value` | `number` | `required` | +| `size` | `"sm" \| "md" \| "lg"` | `"sm"` | +| `color` | `string` | `undefined` | +| `label` | `string` | `undefined` | +| `showPercent` | `boolean` | `false` | diff --git a/content/docs/components/opentui/feedback/skeleton.mdx b/content/docs/components/opentui/feedback/skeleton.mdx new file mode 100644 index 0000000..9b94f17 --- /dev/null +++ b/content/docs/components/opentui/feedback/skeleton.mdx @@ -0,0 +1,64 @@ +--- +title: "Skeleton" +description: "Shimmer loading placeholder" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/skeleton.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { Skeleton } from "@/components/ui/skeleton"; +``` + +```tsx + +``` + +## Examples + +### Static (No Animation) + + + +## API Reference + +### Skeleton + +| Prop | Type | Default | +| ---------- | --------- | ------- | +| `width` | `number` | `20` | +| `height` | `number` | `1` | +| `animated` | `boolean` | `true` | diff --git a/content/docs/components/opentui/feedback/spinner.mdx b/content/docs/components/opentui/feedback/spinner.mdx new file mode 100644 index 0000000..d43b3fd --- /dev/null +++ b/content/docs/components/opentui/feedback/spinner.mdx @@ -0,0 +1,74 @@ +--- +title: "Spinner" +description: "Animated spinner with 12+ styles" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/spinner.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { Spinner } from "@/components/ui/spinner"; +``` + +```tsx + +``` + +## Examples + +### With Label + +A spinner with a descriptive label. + + + +### Spinner Styles + +Multiple built-in animation styles. + + + +## API Reference + +### Spinner + +| Prop | Type | Default | +| -------- | -------------------------------------------------------------------------------------------------------------------------- | ----------- | +| `type` | `"dots" \| "line" \| "star" \| "clock" \| "bounce" \| "bar" \| "arc" \| "arrow" \| "toggle" \| "box" \| "pipe" \| "earth"` | `"dots"` | +| `label` | `string` | `undefined` | +| `color` | `string` | `undefined` | +| `fps` | `number` | `12` | +| `frames` | `string[]` | `undefined` | diff --git a/content/docs/components/opentui/feedback/status-message.mdx b/content/docs/components/opentui/feedback/status-message.mdx new file mode 100644 index 0000000..2a15d89 --- /dev/null +++ b/content/docs/components/opentui/feedback/status-message.mdx @@ -0,0 +1,67 @@ +--- +title: "Status Message" +description: "Inline status message with icon and color" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/status-message.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { StatusMessage } from "@/components/ui/status-message"; +``` + +```tsx +All tests passed. +``` + +## Examples + +### Variants + + + +## API Reference + +### StatusMessage + +| Prop | Type | Default | +| ---------- | ----------------------------------------------------------------------- | ----------- | +| `variant` | `"success" \| "error" \| "warning" \| "info" \| "loading" \| "pending"` | `"info"` | +| `children` | `ReactNode` | `required` | +| `icon` | `string` | `undefined` | diff --git a/content/docs/components/opentui/feedback/toast.mdx b/content/docs/components/opentui/feedback/toast.mdx new file mode 100644 index 0000000..dbf208c --- /dev/null +++ b/content/docs/components/opentui/feedback/toast.mdx @@ -0,0 +1,71 @@ +--- +title: "Toast" +description: "Auto-dismissing toast notification" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/toast.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { Toast } from "@/components/ui/toast"; +``` + +```tsx + console.log("toast closed")} +/> +``` + +## Examples + +### Error with Longer Duration + + + +## API Reference + +### Toast + +| Prop | Type | Default | +| ----------- | --------------------------------------------- | ----------- | +| `message` | `string` | `required` | +| `variant` | `"success" \| "error" \| "warning" \| "info"` | `"info"` | +| `duration` | `number` | `3000` | +| `onDismiss` | `() => void` | `undefined` | +| `icon` | `string` | `undefined` | diff --git a/content/docs/components/opentui/forms/confirm.mdx b/content/docs/components/opentui/forms/confirm.mdx new file mode 100644 index 0000000..69e9f88 --- /dev/null +++ b/content/docs/components/opentui/forms/confirm.mdx @@ -0,0 +1,66 @@ +--- +title: "Confirm" +description: "Yes/No confirmation prompt" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/confirm.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { Confirm } from "@/components/ui/confirm"; +``` + +```tsx + console.log("Confirmed")} + onCancel={() => console.log("Cancelled")} +/> +``` + +## API Reference + +### Confirm + +| Prop | Type | Default | +| -------------- | ----------------------- | ----------- | +| `message` | `string` | `required` | +| `onConfirm` | `() => void` | `undefined` | +| `onCancel` | `() => void` | `undefined` | +| `confirmLabel` | `string` | `"Yes"` | +| `cancelLabel` | `string` | `"No"` | +| `defaultValue` | `boolean` | `false` | +| `variant` | `"default" \| "danger"` | `"default"` | diff --git a/content/docs/components/opentui/forms/date-picker.mdx b/content/docs/components/opentui/forms/date-picker.mdx new file mode 100644 index 0000000..802634f --- /dev/null +++ b/content/docs/components/opentui/forms/date-picker.mdx @@ -0,0 +1,68 @@ +--- +title: "Date Picker" +description: "Calendar date picker with keyboard navigation" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/date-picker.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { DatePicker } from "@/components/ui/date-picker"; +``` + +```tsx + console.log("Selected:", date)} + onSubmit={(date) => console.log("Submitted:", date)} +/> +``` + +## API Reference + +### DatePicker + +| Prop | Type | Default | +| ----------- | ---------------------- | ----------- | +| `value` | `Date` | `undefined` | +| `onChange` | `(date: Date) => void` | `undefined` | +| `onSubmit` | `(date: Date) => void` | `undefined` | +| `label` | `string` | `undefined` | +| `minDate` | `Date` | `undefined` | +| `maxDate` | `Date` | `undefined` | +| `autoFocus` | `boolean` | `false` | +| `id` | `string` | `undefined` | diff --git a/content/docs/components/opentui/forms/file-picker.mdx b/content/docs/components/opentui/forms/file-picker.mdx new file mode 100644 index 0000000..badf738 --- /dev/null +++ b/content/docs/components/opentui/forms/file-picker.mdx @@ -0,0 +1,75 @@ +--- +title: "File Picker" +description: "Interactive file browser and picker" +--- + + + + + File picker requires Node.js filesystem access and may not render in the + browser preview. + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/file-picker.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { FilePicker } from "@/components/ui/file-picker"; +``` + +```tsx + console.log("Selected:", path)} +/> +``` + +## API Reference + +### FilePicker + +| Prop | Type | Default | +| ------------ | ------------------------ | --------------- | +| `value` | `string` | `undefined` | +| `onChange` | `(path: string) => void` | `undefined` | +| `onSubmit` | `(path: string) => void` | `undefined` | +| `label` | `string` | `undefined` | +| `startDir` | `string` | `process.cwd()` | +| `extensions` | `string[]` | `undefined` | +| `dirsOnly` | `boolean` | `false` | +| `autoFocus` | `boolean` | `false` | +| `id` | `string` | `undefined` | +| `width` | `number` | `50` | +| `maxVisible` | `number` | `8` | diff --git a/content/docs/components/opentui/forms/form-field.mdx b/content/docs/components/opentui/forms/form-field.mdx new file mode 100644 index 0000000..a70e1ae --- /dev/null +++ b/content/docs/components/opentui/forms/form-field.mdx @@ -0,0 +1,65 @@ +--- +title: "Form Field" +description: "Form field wrapper with label, hint, and error" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/form-field.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { FormField } from "@/components/ui/form-field"; +``` + +```tsx + + my-input-here + +``` + +## API Reference + +### FormField + +| Prop | Type | Default | +| ------------ | ----------- | ----------- | +| `label` | `string` | `required` | +| `children` | `ReactNode` | `required` | +| `error` | `string` | `undefined` | +| `hint` | `string` | `undefined` | +| `required` | `boolean` | `undefined` | +| `gap` | `number` | `0` | +| `errorIcon` | `string` | `"✗"` | +| `labelColor` | `string` | `undefined` | diff --git a/content/docs/components/opentui/forms/form.mdx b/content/docs/components/opentui/forms/form.mdx new file mode 100644 index 0000000..3d369a6 --- /dev/null +++ b/content/docs/components/opentui/forms/form.mdx @@ -0,0 +1,68 @@ +--- +title: "Form" +description: "Form container with validation, Ctrl+S submit, and dirty tracking" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/form.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { Form } from "@/components/ui/form"; +``` + +```tsx +
      (v ? null : "Name is required") }, + { name: "email", validate: (v) => (v ? null : "Email is required") }, + ]} + onSubmit={(values) => console.log("Submitted:", values)} +> + Name and email form (Ctrl+S to submit) + +``` + +## API Reference + +### Form + +| Prop | Type | Default | +| --------------- | ------------------------------------------- | ---------- | +| `onSubmit` | `(values: Record) => void` | `required` | +| `initialValues` | `Record` | `{}` | +| `fields` | `FormField[]` | `[]` | +| `children` | `ReactNode` | `required` | diff --git a/content/docs/components/opentui/forms/index.mdx b/content/docs/components/opentui/forms/index.mdx new file mode 100644 index 0000000..86d5dd4 --- /dev/null +++ b/content/docs/components/opentui/forms/index.mdx @@ -0,0 +1,6 @@ +--- +title: "Forms" +description: "Components for building multi-step forms and handling user submissions." +--- + + diff --git a/content/docs/components/opentui/forms/meta.json b/content/docs/components/opentui/forms/meta.json new file mode 100644 index 0000000..677e913 --- /dev/null +++ b/content/docs/components/opentui/forms/meta.json @@ -0,0 +1,12 @@ +{ + "pages": [ + "confirm", + "date-picker", + "file-picker", + "form", + "form-field", + "time-picker", + "wizard" + ], + "title": "Forms" +} diff --git a/content/docs/components/opentui/forms/time-picker.mdx b/content/docs/components/opentui/forms/time-picker.mdx new file mode 100644 index 0000000..8b23cba --- /dev/null +++ b/content/docs/components/opentui/forms/time-picker.mdx @@ -0,0 +1,67 @@ +--- +title: "Time Picker" +description: "Time picker with hour/minute/second spinners" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/time-picker.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { TimePicker } from "@/components/ui/time-picker"; +``` + +```tsx + console.log("Changed:", time)} + onSubmit={(time) => console.log("Submitted:", time)} +/> +``` + +## API Reference + +### TimePicker + +| Prop | Type | Default | +| ----------- | ---------------------------------------------------- | ----------- | +| `value` | `{ hours: number; minutes: number }` | `undefined` | +| `onChange` | `(time: { hours: number; minutes: number }) => void` | `undefined` | +| `onSubmit` | `(time: { hours: number; minutes: number }) => void` | `undefined` | +| `label` | `string` | `undefined` | +| `format` | `12 \| 24` | `24` | +| `autoFocus` | `boolean` | `false` | +| `id` | `string` | `undefined` | diff --git a/content/docs/components/opentui/forms/wizard.mdx b/content/docs/components/opentui/forms/wizard.mdx new file mode 100644 index 0000000..488a964 --- /dev/null +++ b/content/docs/components/opentui/forms/wizard.mdx @@ -0,0 +1,88 @@ +--- +title: "Wizard" +description: "Multi-step wizard with per-step validation" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/wizard.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { Wizard } from "@/components/ui/wizard"; +``` + +```tsx +Install dependencies, + }, + { + key: "configure", + title: "Configure", + content: Set up your preferences, + }, + { + key: "finish", + title: "Finish", + content: Review and confirm your settings, + }, + ]} + onComplete={(keys) => console.log("Completed:", keys)} + onCancel={() => console.log("Cancelled")} +/> +``` + +## API Reference + +### Wizard + +| Prop | Type | Default | +| -------------- | ------------------------------------ | ----------- | +| `steps` | `WizardStep[]` | `required` | +| `onComplete` | `(completedSteps: string[]) => void` | `undefined` | +| `onCancel` | `() => void` | `undefined` | +| `showProgress` | `boolean` | `true` | + +### WizardStep + +| Prop | Type | Default | +| ---------- | ------------------------- | ----------- | +| `key` | `string` | `required` | +| `title` | `string` | `required` | +| `content` | `ReactNode` | `required` | +| `validate` | `() => boolean \| string` | `undefined` | diff --git a/content/docs/components/opentui/input/email-input.mdx b/content/docs/components/opentui/input/email-input.mdx new file mode 100644 index 0000000..006e50d --- /dev/null +++ b/content/docs/components/opentui/input/email-input.mdx @@ -0,0 +1,68 @@ +--- +title: "Email Input" +description: "Email input with validation and domain suggestions" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/email-input.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { EmailInput } from "@/components/ui/email-input"; +``` + +```tsx + console.log("Submitted:", value)} +/> +``` + +## API Reference + +### EmailInput + +| Prop | Type | Default | +| ------------- | ------------------------- | ---------------------------------------------------------- | +| `value` | `string` | `undefined` | +| `onChange` | `(value: string) => void` | `undefined` | +| `onSubmit` | `(value: string) => void` | `undefined` | +| `label` | `string` | `undefined` | +| `placeholder` | `string` | `"you@example.com"` | +| `autoFocus` | `boolean` | `false` | +| `id` | `string` | `undefined` | +| `width` | `number` | `40` | +| `suggestions` | `string[]` | `["gmail.com", "yahoo.com", "hotmail.com", "outlook.com"]` | diff --git a/content/docs/components/opentui/input/index.mdx b/content/docs/components/opentui/input/index.mdx new file mode 100644 index 0000000..348d141 --- /dev/null +++ b/content/docs/components/opentui/input/index.mdx @@ -0,0 +1,6 @@ +--- +title: "Input" +description: "Text input components for capturing user input in the terminal." +--- + + diff --git a/content/docs/components/opentui/input/masked-input.mdx b/content/docs/components/opentui/input/masked-input.mdx new file mode 100644 index 0000000..0036381 --- /dev/null +++ b/content/docs/components/opentui/input/masked-input.mdx @@ -0,0 +1,68 @@ +--- +title: "Masked Input" +description: "Masked input for phone, date, credit card formats" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/masked-input.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { MaskedInput } from "@/components/ui/masked-input"; +``` + +```tsx + +``` + +## API Reference + +### MaskedInput + +| Prop | Type | Default | +| ------------- | ------------------------- | ------------ | +| `mask` | `string` | **required** | +| `value` | `string` | `undefined` | +| `onChange` | `(value: string) => void` | `undefined` | +| `onSubmit` | `(value: string) => void` | `undefined` | +| `label` | `string` | `undefined` | +| `placeholder` | `string` | `undefined` | +| `autoFocus` | `boolean` | `false` | +| `id` | `string` | `undefined` | +| `width` | `number` | `40` | diff --git a/content/docs/components/opentui/input/meta.json b/content/docs/components/opentui/input/meta.json new file mode 100644 index 0000000..0a8ac81 --- /dev/null +++ b/content/docs/components/opentui/input/meta.json @@ -0,0 +1,13 @@ +{ + "pages": [ + "email-input", + "masked-input", + "number-input", + "password-input", + "path-input", + "search-input", + "text-area", + "text-input" + ], + "title": "Input" +} diff --git a/content/docs/components/opentui/input/number-input.mdx b/content/docs/components/opentui/input/number-input.mdx new file mode 100644 index 0000000..c3a9447 --- /dev/null +++ b/content/docs/components/opentui/input/number-input.mdx @@ -0,0 +1,75 @@ +--- +title: "Number Input" +description: "Numeric input with increment/decrement and bounds" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/number-input.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { NumberInput } from "@/components/ui/number-input"; +``` + +```tsx + console.log("Value:", value)} +/> +``` + +## API Reference + +### NumberInput + +| Prop | Type | Default | +| ------------- | -------------------------------------------------------------------------------------------- | ------------------------ | +| `value` | `number` | `undefined` | +| `onChange` | `(value: number) => void` | `undefined` | +| `onSubmit` | `(value: number) => void` | `undefined` | +| `min` | `number` | `undefined` | +| `max` | `number` | `undefined` | +| `step` | `number` | `1` | +| `placeholder` | `string` | `""` | +| `label` | `string` | `undefined` | +| `id` | `string` | `undefined` | +| `format` | `(n: number) => string` | `undefined` | +| `borderStyle` | `"single" \| "double" \| "round" \| "bold" \| "singleDouble" \| "doubleSingle" \| "classic"` | `"round"` | +| `paddingX` | `number` | `1` | +| `cursor` | `string` | `"█"` | +| `stepHint` | `string` | `"↑ +{step} ↓ -{step}"` | diff --git a/content/docs/components/opentui/input/password-input.mdx b/content/docs/components/opentui/input/password-input.mdx new file mode 100644 index 0000000..4576dab --- /dev/null +++ b/content/docs/components/opentui/input/password-input.mdx @@ -0,0 +1,75 @@ +--- +title: "Password Input" +description: "Password input with masked characters and reveal toggle" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/password-input.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { PasswordInput } from "@/components/ui/password-input"; +``` + +```tsx + console.log("Password:", value)} +/> +``` + +## API Reference + +### PasswordInput + +| Prop | Type | Default | +| ------------- | -------------------------------------------------------------------------------------------- | ----------- | +| `value` | `string` | `undefined` | +| `onChange` | `(value: string) => void` | `undefined` | +| `onSubmit` | `(value: string) => void` | `undefined` | +| `placeholder` | `string` | `""` | +| `mask` | `string` | `"●"` | +| `showToggle` | `boolean` | `false` | +| `label` | `string` | `undefined` | +| `id` | `string` | `undefined` | +| `borderStyle` | `"single" \| "double" \| "round" \| "bold" \| "singleDouble" \| "doubleSingle" \| "classic"` | `"round"` | +| `paddingX` | `number` | `1` | +| `width` | `number` | `undefined` | +| `cursor` | `string` | `"█"` | diff --git a/content/docs/components/opentui/input/path-input.mdx b/content/docs/components/opentui/input/path-input.mdx new file mode 100644 index 0000000..92163ec --- /dev/null +++ b/content/docs/components/opentui/input/path-input.mdx @@ -0,0 +1,74 @@ +--- +title: "Path Input" +description: "Filesystem path input with tab autocomplete" +--- + + + + + Path input requires Node.js filesystem access and may not render in the + browser preview. + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/path-input.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { PathInput } from "@/components/ui/path-input"; +``` + +```tsx + console.log("Selected:", path)} +/> +``` + +## API Reference + +### PathInput + +| Prop | Type | Default | +| ------------- | ------------------------- | ----------- | +| `value` | `string` | `undefined` | +| `onChange` | `(value: string) => void` | `undefined` | +| `onSubmit` | `(value: string) => void` | `undefined` | +| `label` | `string` | `undefined` | +| `placeholder` | `string` | `"/"` | +| `autoFocus` | `boolean` | `false` | +| `id` | `string` | `undefined` | +| `width` | `number` | `40` | +| `filter` | `string` | `undefined` | +| `dirsOnly` | `boolean` | `false` | diff --git a/content/docs/components/opentui/input/search-input.mdx b/content/docs/components/opentui/input/search-input.mdx new file mode 100644 index 0000000..117fbbe --- /dev/null +++ b/content/docs/components/opentui/input/search-input.mdx @@ -0,0 +1,74 @@ +--- +title: "Search Input" +description: "Fuzzy search input with autocomplete" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/search-input.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { SearchInput } from "@/components/ui/search-input"; +``` + +```tsx + console.log("Selected:", item)} +/> +``` + +## API Reference + +### SearchInput + +| Prop | Type | Default | +| -------------- | -------------------------------------------------------------------------------------------- | ------------- | +| `options` | `T[]` | `undefined` | +| `getValue` | `(item: T) => string` | `undefined` | +| `value` | `string` | `undefined` | +| `onChange` | `(query: string) => void` | `undefined` | +| `onSelect` | `(item: T) => void` | `undefined` | +| `placeholder` | `string` | `"Search..."` | +| `label` | `string` | `undefined` | +| `maxResults` | `number` | `5` | +| `id` | `string` | `undefined` | +| `borderStyle` | `"single" \| "double" \| "round" \| "bold" \| "singleDouble" \| "doubleSingle" \| "classic"` | `"round"` | +| `paddingX` | `number` | `1` | +| `cursor` | `string` | `"█"` | +| `searchIcon` | `string` | `"🔍 "` | +| `resultCursor` | `string` | `"› "` | diff --git a/content/docs/components/opentui/input/text-area.mdx b/content/docs/components/opentui/input/text-area.mdx new file mode 100644 index 0000000..0ae071f --- /dev/null +++ b/content/docs/components/opentui/input/text-area.mdx @@ -0,0 +1,70 @@ +--- +title: "Text Area" +description: "Multi-line text editor with word wrap" +--- + + + +## Installation + + + + + Command + Manual + + + +```bash +npx shadcn@latest add https://termcn.dev/r/text-area.json +``` + + + + + + + +Copy and paste the following code into your project. + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { TextArea } from "@/components/ui/text-area"; +``` + +```tsx +