artisanal_widgets 0.2.0
artisanal_widgets: ^0.2.0 copied to clipboard
Widget system for composable TUI components, built on top of the artisanal terminal toolkit.
artisanal_widgets #
Flutter-inspired widget framework for terminal UIs, built on top of
artisanal.
This is the primary package for widget-first apps. Use the umbrella
package:artisanal/... widget entrypoints only when you intentionally want the
broader Artisanal toolkit from a single dependency.
Table of Contents #
- Installation
- Import
- Quick start
- Flutter-style component ports
- Program Instrumentation
- Tests
- Command execution note
Installation #
dependencies:
artisanal_widgets: ^0.1.0
Import #
import 'package:artisanal_widgets/app.dart';
import 'package:artisanal_widgets/widgets.dart';
Use the focused stable entrypoints when you need those modules:
package:artisanal_widgets/app.dartfor app shells, runners, reload helpers, and hosted wrapperspackage:artisanal_widgets/charting.dartfor chart widgetspackage:artisanal_widgets/editors.dartforTextField,TextArea,TextEditor,CodeEditor,MarkdownEditor, and the stableTextInputKeyMap/TextAreaKeyMapcustomization surfacepackage:artisanal_widgets/selection.dartforSelectableTextandSelectionAreapackage:artisanal_widgets/testing.dartforWidgetTester
The main package:artisanal_widgets/widgets.dart barrel also re-exports
KeyMap and KeyBinding, so component-level shortcut UIs such as HelpView
and zone-hit messages such as ZoneInBoundsMsg, so shortcut and pointer-aware
widgets do not need an extra package:artisanal/tui.dart import.
Keep package:artisanal_widgets/artisanal_widgets.dart only when you
explicitly want the broader experimental compatibility surface.
Both the local runner helpers and the hosted browser/socket helpers accept an
imageAutoMode override. Hosted browser/socket runners now default
Image(renderMode: auto) to session-driven capability detection, while
WidgetTester keeps the portable half-block fallback for deterministic tests.
Quick start #
import 'package:artisanal_widgets/app.dart';
import 'package:artisanal_widgets/widgets.dart';
class HelloApp extends StatelessWidget {
HelloApp({super.key});
@override
Widget build(BuildContext context) {
final theme = ThemeScope.of(context);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Hello widgets', style: theme.titleLarge),
Text('Press q to quit', style: theme.bodyMedium),
],
);
}
}
void main() async {
await runArtisanalApp(
ArtisanalApp(
title: 'Hello widgets',
home: HelloApp(),
),
);
}
runWidgetApp() and runArtisanalApp() default to
MouseMode.allMotion, so hover-driven widgets such as Tooltip,
MouseRegion, and hover-aware scrollbars work without extra setup. If you
call runtime.runProgram() directly, set mouseMode: runtime.MouseMode.allMotion
for passive hover behavior; mouse: true alone only enables
MouseMode.cellMotion.
Flutter-style component ports #
- Chips:
Chip,ActionChip,ChoiceChip,FilterChip,InputChip - Menus:
DropdownButton,DropdownMenuItem,PopupMenuButton,PopupMenuItem,CheckedPopupMenuItem,PopupMenuDivider - Sliders:
Slider,RangeSlider,RangeValues - Indicators:
LinearProgressIndicator,CircularProgressIndicator - Charts:
SparklineChart,LineChart,BarChart,HeatmapChart,PieChart,RibbonChartwith optional in-chart legends
The OpenCode example is self-contained under
example/opencode (including local data models and theme assets).

Program Instrumentation #
The core TUI runtime (Program) supports general instrumentation and automation
for any app (not OpenCode-specific):
ProgramInterceptorfor message interception/timing hooks.ProgramReplayfor deterministic event playback.
import 'package:artisanal/runtime.dart' as runtime;
import 'package:artisanal_widgets/app.dart';
final replay = runtime.ProgramReplay.script([
runtime.ProgramReplayStep(
after: Duration(milliseconds: 120),
msg: runtime.KeyMsg(
runtime.Key(runtime.KeyType.runes, runes: [0x61]),
),
),
runtime.ProgramReplayStep(
after: Duration(milliseconds: 16),
msg: runtime.QuitMsg(),
),
]);
await runtime.runProgram(
WidgetApp(MyApp()),
options: runtime.ProgramOptions(replay: replay),
);
See the package:artisanal/runtime.dart API docs for full interceptor/replay
details.
Tests #
Component tests are split by widget under
test/components/*_test.dart.
Useful commands:
dart test test/components
dart test
dart analyze
Command execution note #
When combining commands that include runtime-managed commands (EveryCmd,
StreamCmd, or helpers like every(...)), use ParallelCmd so those commands
are started by Program.
Use Cmd.batch(...) for finite commands that only need execute().