candycore/sugar-bits
最新稳定版本:v0.2.0
Composer 安装命令:
composer require candycore/sugar-bits
包简介
PHP port of charmbracelet/bubbles — 15 pre-built TUI components (text input, dynamic-height textarea, list, table with per-cell styleFunc, tree, viewport, file picker, progress, spinner, etc.) for SugarCraft.
关键字:
README 文档
README
SugarBits
PHP port of charmbracelet/bubbles —
15 pre-built TUI components for SugarCraft, including the interactive
Tree (mirrors upstream Bubbles #233), dynamic-height TextArea
(mirrors #910), and per-cell Table::styleFunc(...) (mirrors #246).
composer require sugarcraft/sugar-bits
TextInput,TextArea, andHelpexpose short-form aliases for the most-used setters:placeholder/charLimit/width/height/prompt/validator/styles/separator/ellipsis. The upstream-mirroringwith*long forms still work side-by-side.
Components
Upstream Bubbles ships 13 components; SugarBits ships those 13 plus
AnimatedProgress (the spring-physics variant lives in its own class
to keep the static Progress lean).
| Component | What it does | Notable msgs |
|---|---|---|
Cursor\Cursor |
Animated text cursor | BlinkMsg |
Help\Help |
Render short / full key-help footer from a KeyMap; Help::updateWithBinding($msg, $toggle) flips show-all in response to a key |
— |
Key\Binding |
One key + label + help row; Binding::new(...), Binding::withDisabled(...) factories |
— |
Spinner\Spinner |
Animated loading glyph — 12 built-in styles | Spinner\TickMsg |
Progress\Progress |
Static progress bar (gradient fill optional, withColors(...) / withColorFunc(...)) |
— |
Progress\AnimatedProgress |
Spring-physics-animated progress bar (HoneyBounce-driven) | SpringTickMsg |
Timer\Timer |
Countdown timer; interval(), timeout(), withInterval(float) |
Timer\TickMsg, TimeoutMsg |
Stopwatch\Stopwatch |
Elapsed-time counter; interval(), withInterval(float) |
Stopwatch\TickMsg |
TextInput\TextInput |
Single-line input with autocomplete + validators + Styles |
— |
TextArea\TextArea |
Multi-line editor with line numbers / set-prompt-func / focused() / cursor() / line() / column(); Ctrl+O opens the buffer in $EDITOR (withEditorExtension('.md') to control the syntax-highlight suffix) |
TextArea\TextAreaEditedMsg |
Viewport\Viewport |
Scrollable text region with mouse-wheel, scrollbar, horizontal scroll, setWidth(int) / setHeight(int) |
— |
Paginator\Paginator |
Dot / arabic page indicator | — |
ItemList\ItemList |
Selectable / scrollable / filterable list with status messages | — |
Tree\Tree |
Interactive tree — cursor, expand/collapse, viewport scroll. Mirrors upstream Bubbles #233. | — |
Table\Table |
Selectable data table with Column struct + nav |
— |
FilePicker\FilePicker |
Directory browser with icons / size / sort modes | — |
Msg routing cheat-sheet
Forward these into your model's update() so the embedded component
can react: BlinkMsg (Cursor / TextInput), Spinner\TickMsg
(Spinner), Timer\TickMsg + Timer\TimeoutMsg, Stopwatch\TickMsg,
SpringTickMsg (AnimatedProgress), StartStopMsg (Timer / Stopwatch),
TextArea\TextAreaEditedMsg (TextArea's Ctrl+O round-trip).
Each component's update() filters by its own id() so multiple
instances of the same component coexist on one event loop.
Quickstart — TextInput with autocomplete
use SugarCraft\Bits\TextInput\TextInput; use SugarCraft\Core\{Cmd, Model, Msg, Program}; use SugarCraft\Core\Msg\KeyMsg; use SugarCraft\Core\KeyType; final class Search implements Model { public function __construct(public readonly TextInput $ti) {} public function init(): ?\Closure { return null; } public function update(Msg $msg): array { if ($msg instanceof KeyMsg && $msg->type === KeyType::Enter) { return [$this, Cmd::quit()]; } if ($msg instanceof KeyMsg && $msg->type === KeyType::Tab) { return [new self($this->ti->acceptSuggestion()), null]; } [$ti, $cmd] = $this->ti->update($msg); return [new self($ti), $cmd]; } public function view(): string { $body = $this->ti->view(); if (($s = $this->ti->currentSuggestion()) !== null) { $body .= "\n → $s"; } return $body; } } [$ti, $cmd] = TextInput::new() ->withSuggestions(['apple', 'apricot', 'banana', 'cherry']) ->showSuggestions() ->withValidator(fn(string $v) => strlen($v) >= 2 ? null : 'too short') ->focus(); (new Program(new Search($ti)))->run();
Quickstart — animated progress bar
use SugarCraft\Bits\Progress\AnimatedProgress; $bar = AnimatedProgress::new() ->withWidth(40) ->withDefaultGradient(); [$bar, $cmd] = $bar->setPercent(0.75); // dispatch $cmd via the Program — ticks re-fire from inside update() // until the bar settles within 5e-4 of the target.
Test
cd sugar-bits && composer install && vendor/bin/phpunit
Demos
Cursor
File picker
Help
Item list
Paginator
Progress
Spinners
Stopwatch
Table
Text area
Text input
Timer
Viewport
candycore/sugar-bits 适用场景与选型建议
candycore/sugar-bits 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 0 次下载、GitHub Stars 达 1, 最近一次更新时间为 2026 年 05 月 07 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「cli」 「components」 「terminal」 「list」 「table」 「widgets」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 candycore/sugar-bits 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 candycore/sugar-bits 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 candycore/sugar-bits 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
A fork of runcmf/runtracy
PHP Terminal emulator controller utilizing ANSI escape sequence coding.
Web Font Loader gives you added control when using linked fonts via @font-face.
Render small SVG icons to monochrome ANSI for terminal UIs (Laravel/Prompts, Symfony Console, plain CLI).
2020 PHP: A showcase and classroom for the cutting edge features of PHP 8
Ariadne Component Library: xml writer and parser Component
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 59
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-05-07












