js_widget_runtime
A Flutter package that runs JavaScript widgets and renders them as native Flutter UI.
- VM/desktop/mobile: uses
flutter_js(QuickJS / JavaScriptCore). - Web: uses a dedicated
web.Workerspawned from an inline Blob URL.
The JS side communicates with Flutter through a declarative JSON UI tree and a small async bridge (render, fetchJson, exec, storage, secrets, timers, requestAnimationFrame, etc.).
Quick start
import 'package:flutter/material.dart';
import 'package:js_widget_runtime/js_widget_runtime.dart';
class DemoPage extends StatelessWidget {
const DemoPage({super.key});
@override
Widget build(BuildContext context) {
return JsWidgetRuntime(
jsSource: r'''
(function() {
jsr.render({
type: 'center',
child: {
type: 'column',
mainAxisSize: 'min',
children: [
{type: 'text', data: 'Hello from JS!', style: {fontSize: 24}},
{type: 'sizedBox', height: 12},
{
type: 'textButton',
text: 'Tap me',
onTap: 'tap',
},
],
},
});
jsr.onEvent(function(actionId, payload) {
if (actionId === 'tap') {
jsr.setTitle('Tapped!');
}
});
})();
''',
runtimeConfig: JsRuntimeConfig(
onRender: (tree) => print('render: $tree'),
onSetTitle: (title) => print('title: $title'),
onStorageUpdate: (storage) => print('storage: $storage'),
),
);
}
}
See the example/ folder for a runnable menu of sample JS apps.
3D scenes and GLB models
js_widget_runtime does not bundle a 3D engine. Instead it exposes a Js3dHost
interface so the host app can plug in any engine (Flame 3D, three_dart,
flutter_3d_controller, etc.).
JsRuntimeConfig(
js3dHost: const My3dHost(),
// ... other handlers
);
From JS, create a scene and manipulate it:
jsr.scene3d.create('main', {
camera: { position: [0, 2, 5], target: [0, 0, 0] },
lights: [{ type: 'ambient', color: '#ffffff', intensity: 0.5 }]
});
jsr.render({
type: 'scene3d',
id: 'main',
width: 320,
height: 320
});
jsr.scene3d.addModel('main', {
id: 'player',
src: 'assets/player.glb'
});
jsr.scene3d.playAnimation('main', 'player', 'run');
jsr.scene3d.setTransform('main', 'player', {
position: [1, 0, 0],
rotation: [0, 45, 0],
scale: [1.5, 1.5, 1.5]
});
The example/ app includes a 3d-viewer widget powered by
flutter_3d_controller.
Renderer nodes
The JSON tree supports these node types:
| Category | Nodes |
|---|---|
| Layout | column, row, stack, center, padding, sizedBox, expanded, flexible, wrap, align, absoluteFill |
| Display | text, icon, markdown, divider, spacer, image, svg, avatar, chip, badge, path, progress indicators |
| Container | container, card, inkWell, safeArea, scroll, blur |
| List | listView, gridView, listTile. Scrolling is configurable: shrinkWrap (default true) and physics ('never' / 'always' / 'platform'; default 'always' for listView, 'never' for gridView). Use shrinkWrap: false in a bounded parent to let the view scroll |
| Input | button, textButton, outlinedButton, iconButton, textField, textArea (multiline input: value, hint, minLines default 3, maxLines default 8, onChange per keystroke, optional onSubmit done action), switch, checkbox, slider, dropdown |
| Animation | animatedContainer, animatedOpacity, animatedPositioned (implicit change animations); entrance — one-shot mount animation (animation: fade/slideUp/slideDown/slideLeft/slideRight/scale/fadeScale, delay ms for staggered lists, duration, curve); animatedSwitcher — view transition when switchKey changes (animation: fade/slideLeft/slideRight/slideUp/scale/fadeScale) |
| Map | map — OpenStreetMap via flutter_map (no API key). Props: center {lat, lng}, zoom, markers [{id, lat, lng, label?, color?}], polylines [{points, color?, width?}], fitBounds; events: onTap ({lat, lng}), onMarkerTap ({id}) |
| Chart | chart — sparkline or bar chart. Props: data (list of numbers; points accepted as alias), chartType (line default, bar), color, fillColor (hex with alpha, e.g. #22c55e33), strokeWidth, height |
| 3D | scene3d — host-provided 3D engine. Props: id, width, height, camera, lights. GLB/GLTF models, cameras and lights are controlled from JS via jsr.scene3d.* |
| Media | video, audio (host-provided via JsMediaHost) |
| Gestures | gestureDetector |
Features
- Cross-platform JS execution (VM + web).
- Declarative JSON-to-Flutter renderer with layout, input, animation and gesture nodes.
- Effects ported from YoClip: radial gradients, box shadows, blur, 3D transforms, clip, text shadows.
manifest.jsonbased app registry with example widgets.- Injected I/O handlers so the host controls permissions (network, CLI, secure storage).
- Host-specific JS APIs via
JsRuntimeConfig.hostBootstrapJs(e.g.,jsr.yoloit = {...}). - Default in-memory handlers for demo/development use.
License
MIT
Libraries
- js_widget_runtime
- Run JavaScript widgets as Flutter widgets.